diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index c2d8cae580..99d0344c9f 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -462,10 +462,13 @@ done : { */ static uint16_t bgp_read(struct peer *peer, int *code_p) { + size_t readsize; // how many bytes we want to read ssize_t nbytes; // how many bytes we actually read uint16_t status = 0; - nbytes = ringbuf_read(peer->ibuf_work, peer->fd); + readsize = + MIN(ringbuf_space(peer->ibuf_work), sizeof(peer->ibuf_scratch)); + nbytes = read(peer->fd, peer->ibuf_scratch, readsize); /* EAGAIN or EWOULDBLOCK; come back later */ if (nbytes < 0 && ERRNO_IO_RETRY(errno)) { @@ -493,6 +496,9 @@ static uint16_t bgp_read(struct peer *peer, int *code_p) *code_p = TCP_connection_closed; SET_FLAG(status, BGP_IO_FATAL_ERR); + } else { + assert(ringbuf_put(peer->ibuf_work, peer->ibuf_scratch, nbytes) + == (size_t)nbytes); } return status; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 51134dc8c5..88588952ba 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -44,6 +44,7 @@ #include "bgp_addpath_types.h" #include "bgp_nexthop.h" #include "bgp_damp.h" +#include "bgp_io.h" #include "lib/bfd.h" @@ -1047,6 +1048,9 @@ struct peer { struct stream_fifo *ibuf; // packets waiting to be processed struct stream_fifo *obuf; // packets waiting to be written + /* used as a block to deposit raw wire data to */ + uint8_t ibuf_scratch[BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE + * BGP_READ_PACKET_MAX]; struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only struct stream *obuf_work; // WiP buffer used to construct packets diff --git a/lib/ringbuf.c b/lib/ringbuf.c index 49221e7cb3..6efa8077c2 100644 --- a/lib/ringbuf.c +++ b/lib/ringbuf.c @@ -131,38 +131,3 @@ void ringbuf_wipe(struct ringbuf *buf) memset(buf->data, 0x00, buf->size); ringbuf_reset(buf); } - -ssize_t ringbuf_read(struct ringbuf *buf, int sock) -{ - size_t to_read = ringbuf_space(buf); - size_t bytes_to_end = buf->size - buf->end; - ssize_t bytes_read; - struct iovec iov[2] = {}; - - /* Calculate amount of read blocks. */ - if (to_read > bytes_to_end) { - iov[0].iov_base = buf->data + buf->end; - iov[0].iov_len = bytes_to_end; - iov[1].iov_base = buf->data; - iov[1].iov_len = to_read - bytes_to_end; - } else { - iov[0].iov_base = buf->data + buf->end; - iov[0].iov_len = to_read; - } - - /* Do the system call. */ - bytes_read = readv(sock, iov, 2); - if (bytes_read <= 0) - return bytes_read; - - /* Calculate the new end. */ - if ((size_t)bytes_read > bytes_to_end) - buf->end = bytes_read - bytes_to_end; - else - buf->end += bytes_read; - - /* Set emptiness state. */ - buf->empty = (buf->start == buf->end) && (buf->empty && !bytes_read); - - return bytes_read; -} diff --git a/lib/ringbuf.h b/lib/ringbuf.h index 209687512b..b8f4d9798d 100644 --- a/lib/ringbuf.h +++ b/lib/ringbuf.h @@ -126,17 +126,6 @@ void ringbuf_reset(struct ringbuf *buf); */ void ringbuf_wipe(struct ringbuf *buf); -/** - * Perform a socket/file `read()` in to the ring buffer. - * - * \param buf the ring buffer pointer. - * \param sock the file descriptor. - * \returns the number of bytes read, `0` on connection close or `-1` with - * `errno` pointing the error (see `readv()` man page for more - * information.) - */ -ssize_t ringbuf_read(struct ringbuf *buf, int sock); - #ifdef __cplusplus } #endif