networkd: fix kernel rtnl receive buffer overrun error

We got the following error when running systemd on a device  with many ports:

"rtnl: kernel receive buffer overrun
Event source 'rtnl-receive-message' returned error, disabling: No buffer space
available"

I think the kernel socket receive buffer queue should be increased. The default
value is taken from:
"/proc/sys/net/core/rmem_default", but we can overwrite it using SO_RCVBUF
socket option.

This is already done in networkd for other sockets.
For example, the bus socket (sd-bus/bus-socket.c) has a receive queue of 8MB.
In our case, the default is 208KB.

Increasing the buffer receive queue for manager socket to 512KB should be enough
to get rid of the above error.

[tomegun: bump the limit even higher to 8M]
This commit is contained in:
Alin Rauta 2014-11-27 18:50:48 +01:00 committed by Tom Gundersen
parent 0e3434aeb1
commit be660c371b
3 changed files with 12 additions and 0 deletions

View file

@ -140,6 +140,10 @@ int sd_rtnl_open(sd_rtnl **ret, unsigned n_groups, ...) {
return 0;
}
int sd_rtnl_inc_rcvbuf(const sd_rtnl *const rtnl, const int size) {
return fd_inc_rcvbuf(rtnl->fd, size);
}
sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) {
assert_return(rtnl, NULL);
assert_return(!rtnl_pid_changed(rtnl), NULL);

View file

@ -36,6 +36,9 @@
#include "sd-rtnl.h"
/* use 8 MB for receive socket kernel queue. */
#define RCVBUF_SIZE (8*1024*1024)
const char* const network_dirs[] = {
"/etc/systemd/network",
"/run/systemd/network",
@ -98,6 +101,10 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
r = sd_rtnl_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
if (r < 0)
return r;
r = sd_bus_default_system(&m->bus);
if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
return r;

View file

@ -41,6 +41,7 @@ typedef int (*sd_rtnl_message_handler_t)(sd_rtnl *rtnl, sd_rtnl_message *m, void
/* bus */
int sd_rtnl_open(sd_rtnl **nl, unsigned n_groups, ...);
int sd_rtnl_inc_rcvbuf(const sd_rtnl *const rtnl, const int size);
sd_rtnl *sd_rtnl_ref(sd_rtnl *nl);
sd_rtnl *sd_rtnl_unref(sd_rtnl *nl);