mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 23:58:44 +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 */
|
/* clang-format off */
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
#include <pthread.h> // for pthread_mutex_unlock, pthread_mutex_lock
|
#include <pthread.h> // for pthread_mutex_unlock, pthread_mutex_lock
|
||||||
|
#include <sys/uio.h> // for writev
|
||||||
|
|
||||||
#include "frr_pthread.h"
|
#include "frr_pthread.h"
|
||||||
#include "linklist.h" // for list_delete, list_delete_all_node, lis...
|
#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;
|
uint8_t type;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
int num;
|
|
||||||
int update_last_write = 0;
|
int update_last_write = 0;
|
||||||
unsigned int count = 0;
|
unsigned int count;
|
||||||
uint32_t uo = 0;
|
uint32_t uo = 0;
|
||||||
uint16_t status = 0;
|
uint16_t status = 0;
|
||||||
uint32_t wpkt_quanta_old;
|
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,
|
wpkt_quanta_old = atomic_load_explicit(&peer->bgp->wpkt_quanta,
|
||||||
memory_order_relaxed);
|
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))) {
|
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);
|
|
||||||
|
|
||||||
if (num < 0) {
|
if (!s)
|
||||||
if (!ERRNO_IO_RETRY(errno)) {
|
goto done;
|
||||||
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
|
||||||
SET_FLAG(status, BGP_IO_FATAL_ERR);
|
|
||||||
} else {
|
|
||||||
SET_FLAG(status, BGP_IO_TRANS_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto done;
|
count = iovsz = 0;
|
||||||
} else if (num != writenum)
|
while (count < wpkt_quanta_old && iovsz < array_size(iov) && s) {
|
||||||
stream_forward_getp(s, num);
|
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. */
|
/* Retrieve BGP packet type. */
|
||||||
stream_set_getp(s, BGP_MARKER_SIZE + 2);
|
stream_set_getp(s, BGP_MARKER_SIZE + 2);
|
||||||
@ -351,9 +411,8 @@ static uint16_t bgp_write(struct peer *peer)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
stream_free(s);
|
||||||
|
ostreams[i] = NULL;
|
||||||
stream_free(stream_fifo_pop(peer->obuf));
|
|
||||||
update_last_write = 1;
|
update_last_write = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user