0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-09 12:48:43 +00:00

IO: Ensure that socket rcvbuf is large enough

The socket structure has the field rbsize (receive buffer size), which
controls the size of the userspace receive buffer. There is also kernel
receive buffer, which in some cases may be smaller (e.g. on FreeBSD it
is by default ~8k). The patch ensures that the kernel receive buffer is
as large as the userspace receive buffer.
This commit is contained in:
Ondrej Zajicek 2024-08-01 14:55:05 +02:00
parent c9836207f5
commit 5214d7e59f

View File

@ -517,6 +517,40 @@ sk_set_high_port(sock *s UNUSED)
return 0; return 0;
} }
static inline int
sk_set_min_rcvbuf_(sock *s, int bufsize)
{
int oldsize = 0, oldsize_s = sizeof(oldsize);
if (getsockopt(s->fd, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldsize_s) < 0)
ERR("SO_RCVBUF");
if (oldsize >= bufsize)
return 0;
bufsize = BIRD_ALIGN(bufsize, 64);
if (setsockopt(s->fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) < 0)
ERR("SO_RCVBUF");
/*
int newsize = 0, newsize_s = sizeof(newsize);
if (getsockopt(s->fd, SOL_SOCKET, SO_RCVBUF, &newsize, &newsize_s) < 0)
ERR("SO_RCVBUF");
log(L_INFO "Setting rcvbuf on %s from %d to %d",
s->iface ? s->iface->name : "*", oldsize, newsize);
*/
return 0;
}
static void
sk_set_min_rcvbuf(sock *s, int bufsize)
{
if (sk_set_min_rcvbuf_(s, bufsize) < 0)
log(L_WARN "Socket error: %s%#m", s->err);
}
static inline byte * static inline byte *
sk_skip_ip_header(byte *pkt, int *len) sk_skip_ip_header(byte *pkt, int *len)
{ {
@ -862,6 +896,9 @@ sk_set_rbsize(sock *s, uint val)
xfree(s->rbuf_alloc); xfree(s->rbuf_alloc);
s->rbuf_alloc = xmalloc(val); s->rbuf_alloc = xmalloc(val);
s->rpos = s->rbuf = s->rbuf_alloc; s->rpos = s->rbuf = s->rbuf_alloc;
if ((s->type == SK_UDP) || (s->type == SK_IP))
sk_set_min_rcvbuf(s, s->rbsize);
} }
void void
@ -1058,6 +1095,9 @@ sk_setup(sock *s)
if (sk_set_priority(s, s->priority) < 0) if (sk_set_priority(s, s->priority) < 0)
return -1; return -1;
if ((s->type == SK_UDP) || (s->type == SK_IP))
sk_set_min_rcvbuf(s, s->rbsize);
return 0; return 0;
} }