summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlin Rauta <alin.rauta@intel.com>2014-11-27 18:50:48 +0100
committerTom Gundersen <teg@jklm.no>2014-11-27 18:59:47 +0100
commitbe660c371b231c253a97464ddd8f32ec8721da21 (patch)
tree5d66f4f5a4abb1a0e011b1cca596280dc065063c
parent0e3434aeb1eed951fdbeddacc6126e10d82a1c8b (diff)
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]
-rw-r--r--src/libsystemd/sd-rtnl/sd-rtnl.c4
-rw-r--r--src/network/networkd-manager.c7
-rw-r--r--src/systemd/sd-rtnl.h1
3 files changed, 12 insertions, 0 deletions
diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 1af38f3667..abb011ea24 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -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);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 2c8a330d75..6046dc7d62 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -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;
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 0980de8e3f..95bdb1d3d6 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -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);