iproute uses too small of a receive buffer
It uses 1MB as receive buf limit by default (without
increasing /proc/sys/net/core/rmem_max it will be limited by less
however) and allows to specify the size manually using "-rcvbuf X"
(-r is already used, so you need to specify at least -rc).
Additionally rtnl_listen() continues on ENOBUFS after printing the
error message.
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 0e02468..61da15b 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -17,6 +17,8 @@
__u32 dump;
};
+extern int rcvbuf;
+
extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol);
extern void rtnl_close(struct rtnl_handle *rth);
diff --git a/ip/ip.c b/ip/ip.c
index 2bd54b2..b4c076a 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -50,7 +50,8 @@
" tunnel | maddr | mroute | monitor | xfrm }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -f[amily] { inet | inet6 | ipx | dnet | link } |\n"
-" -o[neline] | -t[imestamp] | -b[atch] [filename] }\n");
+" -o[neline] | -t[imestamp] | -b[atch] [filename] |\n"
+" -rc[vbuf] [size]}\n");
exit(-1);
}
@@ -213,6 +214,19 @@
if (argc <= 1)
usage();
batch_file = argv[1];
+ } else if (matches(opt, "-rcvbuf") == 0) {
+ unsigned int size;
+
+ argc--;
+ argv++;
+ if (argc <= 1)
+ usage();
+ if (get_unsigned(&size, argv[1], 0)) {
+ fprintf(stderr, "Invalid rcvbuf size '%s'\n",
+ argv[1]);
+ exit(-1);
+ }
+ rcvbuf = size;
} else if (matches(opt, "-help") == 0) {
usage();
} else {
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 100dd40..a6c0306 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -25,6 +25,8 @@
#include "libnetlink.h"
+int rcvbuf = 1024 * 1024;
+
void rtnl_close(struct rtnl_handle *rth)
{
if (rth->fd >= 0) {
@@ -38,7 +40,6 @@
{
socklen_t addr_len;
int sndbuf = 32768;
- int rcvbuf = 32768;
memset(rth, 0, sizeof(*rth));
@@ -409,6 +410,8 @@
continue;
fprintf(stderr, "netlink receive error %s (%d)\n",
strerror(errno), errno);
+ if (errno == ENOBUFS)
+ continue;
return -1;
}
if (status == 0) {