mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 06:14:35 +00:00
bgpd: vector I/O
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
421a7dfc93
commit
093279cd02
101
bgpd/bgp_io.c
101
bgpd/bgp_io.c
@ -22,6 +22,7 @@
|
||||
/* clang-format off */
|
||||
#include <zebra.h>
|
||||
#include <pthread.h> // for pthread_mutex_unlock, pthread_mutex_lock
|
||||
#include <sys/uio.h> // for writev
|
||||
|
||||
#include "frr_pthread.h"
|
||||
#include "linklist.h" // for list_delete, list_delete_all_node, lis...
|
||||
@ -275,35 +276,94 @@ static uint16_t bgp_write(struct peer *peer)
|
||||
{
|
||||
uint8_t type;
|
||||
struct stream *s;
|
||||
int num;
|
||||
int update_last_write = 0;
|
||||
unsigned int count = 0;
|
||||
unsigned int count;
|
||||
uint32_t uo = 0;
|
||||
uint16_t status = 0;
|
||||
uint32_t wpkt_quanta_old;
|
||||
|
||||
int writenum = 0;
|
||||
int num;
|
||||
unsigned int iovsz;
|
||||
unsigned int strmsz;
|
||||
unsigned int total_written;
|
||||
|
||||
wpkt_quanta_old = atomic_load_explicit(&peer->bgp->wpkt_quanta,
|
||||
memory_order_relaxed);
|
||||
struct stream *ostreams[wpkt_quanta_old];
|
||||
struct stream **streams = ostreams;
|
||||
struct iovec iov[wpkt_quanta_old];
|
||||
|
||||
while (count < wpkt_quanta_old && (s = stream_fifo_head(peer->obuf))) {
|
||||
int writenum;
|
||||
do {
|
||||
writenum = stream_get_endp(s) - stream_get_getp(s);
|
||||
num = write(peer->fd, stream_pnt(s), writenum);
|
||||
s = stream_fifo_head(peer->obuf);
|
||||
|
||||
if (num < 0) {
|
||||
if (!ERRNO_IO_RETRY(errno)) {
|
||||
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
||||
SET_FLAG(status, BGP_IO_FATAL_ERR);
|
||||
} else {
|
||||
SET_FLAG(status, BGP_IO_TRANS_ERR);
|
||||
}
|
||||
if (!s)
|
||||
goto done;
|
||||
|
||||
goto done;
|
||||
} else if (num != writenum)
|
||||
stream_forward_getp(s, num);
|
||||
count = iovsz = 0;
|
||||
while (count < wpkt_quanta_old && iovsz < array_size(iov) && s) {
|
||||
ostreams[iovsz] = s;
|
||||
iov[iovsz].iov_base = stream_pnt(s);
|
||||
iov[iovsz].iov_len = STREAM_READABLE(s);
|
||||
writenum += STREAM_READABLE(s);
|
||||
s = s->next;
|
||||
++iovsz;
|
||||
++count;
|
||||
}
|
||||
|
||||
} while (num != writenum);
|
||||
strmsz = iovsz;
|
||||
total_written = 0;
|
||||
|
||||
do {
|
||||
num = writev(peer->fd, iov, iovsz);
|
||||
|
||||
if (num < 0) {
|
||||
if (!ERRNO_IO_RETRY(errno)) {
|
||||
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
||||
SET_FLAG(status, BGP_IO_FATAL_ERR);
|
||||
} else {
|
||||
SET_FLAG(status, BGP_IO_TRANS_ERR);
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (num != writenum) {
|
||||
unsigned int msg_written = 0;
|
||||
unsigned int ic = iovsz;
|
||||
|
||||
for (unsigned int i = 0; i < ic; i++) {
|
||||
size_t ss = iov[i].iov_len;
|
||||
|
||||
if (ss > (unsigned int) num)
|
||||
break;
|
||||
|
||||
msg_written++;
|
||||
iovsz--;
|
||||
writenum -= ss;
|
||||
num -= ss;
|
||||
}
|
||||
|
||||
total_written += msg_written;
|
||||
|
||||
memmove(&iov, &iov[msg_written],
|
||||
sizeof(iov[0]) * iovsz);
|
||||
streams = &streams[msg_written];
|
||||
stream_forward_getp(streams[0], num);
|
||||
iov[0].iov_base = stream_pnt(streams[0]);
|
||||
iov[0].iov_len = STREAM_READABLE(streams[0]);
|
||||
|
||||
writenum -= num;
|
||||
num = 0;
|
||||
assert(writenum > 0);
|
||||
} else {
|
||||
total_written = strmsz;
|
||||
}
|
||||
|
||||
} while (num != writenum);
|
||||
|
||||
/* Handle statistics */
|
||||
for (unsigned int i = 0; i < total_written; i++) {
|
||||
s = stream_fifo_pop(peer->obuf);
|
||||
|
||||
assert(s == ostreams[i]);
|
||||
|
||||
/* Retrieve BGP packet type. */
|
||||
stream_set_getp(s, BGP_MARKER_SIZE + 2);
|
||||
@ -351,9 +411,8 @@ static uint16_t bgp_write(struct peer *peer)
|
||||
break;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
stream_free(stream_fifo_pop(peer->obuf));
|
||||
stream_free(s);
|
||||
ostreams[i] = NULL;
|
||||
update_last_write = 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user