Skip to content

Commit

Permalink
bgpd: vector I/O
Browse files Browse the repository at this point in the history
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
  • Loading branch information
qlyoung committed Oct 14, 2019
1 parent 421a7df commit 093279c
Showing 1 changed file with 80 additions and 21 deletions.
101 changes: 80 additions & 21 deletions bgpd/bgp_io.c
Expand Up @@ -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...
Expand Down Expand Up @@ -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];

s = stream_fifo_head(peer->obuf);

if (!s)
goto done;

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;
}

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;

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);
if (ss > (unsigned int) num)
break;

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);
}
msg_written++;
iovsz--;
writenum -= ss;
num -= ss;
}

goto done;
} else if (num != writenum)
stream_forward_getp(s, num);
total_written += msg_written;

} while (num != writenum);
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);
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 093279c

Please sign in to comment.