Commit my hack (yes, I still call it hack) - command line switch for zebra
daemon to change netlink receive buffer size.
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 63b736c..97dddec 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2004-08-31 Hasso Tepper <hasso at quagga.net>
+
+ * zebra.8: Document -s/--nl-bufsize command line switch.
+
2004-08-27 Hasso Tepper <hasso at quagga.net>
* Update vtysh man page to reflect changes in shell.
diff --git a/doc/zebra.8 b/doc/zebra.8
index 8f83015..25cbb36 100644
--- a/doc/zebra.8
+++ b/doc/zebra.8
@@ -71,6 +71,18 @@
\fB\-r\fR, \fB\-\-retain\fR
When the program terminates, retain routes added by \fBzebra\fR.
.TP
+\fB\-s\fR, \fB\-\-nl-bufsize \fR\fInetlink-buffer-size\fR
+Set netlink receive buffer size. There are cases where zebra daemon can't
+handle flood of netlink messages from kernel. If you ever see "recvmsg overrun"
+messages in zebra log, you are in trouble.
+
+Solution is to increase receive buffer of netlink socket. Note that kernel
+doesn't allow to increase it over maximum value defined in
+\fI/proc/sys/net/core/rmem_max\fR. If you want to do it, you have to increase
+maximum before starting zebra.
+
+Note that this affects Linux only.
+.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 9dd031c..b679807 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,8 @@
+2004-08-31 Hasso Tepper <hasso at quagga.net>
+
+ * main.c, rt_netlink.c: Added -s command line switch for tuning
+ netlink receive buffer size in Linux to avoid buffer overruns.
+
2004-08-26 Miles Nordin <carton@Ivy.NET>
* ipforward_sysctl.c (mib_ipv6): Use size_t for len, per
diff --git a/zebra/main.c b/zebra/main.c
index 6d40d70..0c1a7dd 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -57,6 +57,11 @@
/* Don't delete kernel route. */
int keep_kernel_mode = 0;
+#ifdef HAVE_NETLINK
+/* Receive buffer size for netlink socket */
+u_int32_t nl_rcvbufsize = 0;
+#endif /* HAVE_NETLINK */
+
/* Command line options. */
struct option longopts[] =
{
@@ -70,6 +75,9 @@
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
+#ifdef HAVE_NETLINK
+ { "nl-bufsize", no_argument, NULL, 's'},
+#endif /* HAVE_NETLINK */
{ "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ 0 }
@@ -111,23 +119,28 @@
fprintf (stderr, "Try `%s --help' for more information.\n", progname);
else
{
- printf ("Usage : %s [OPTION...]\n\n\
-Daemon which manages kernel routing table management and \
-redistribution between different routing protocols.\n\n\
--b, --batch Runs in batch mode\n\
--d, --daemon Runs in daemon mode\n\
--f, --config_file Set configuration file name\n\
--i, --pid_file Set process identifier file name\n\
--k, --keep_kernel Don't delete old routes which installed by zebra.\n\
--l, --log_mode Set verbose log mode flag\n\
--A, --vty_addr Set vty's bind address\n\
--P, --vty_port Set vty's port number\n\
--r, --retain When program terminates, retain added route by zebra.\n\
--u, --user User and group to run as\n\
--v, --version Print program version\n\
--h, --help Display this help and exit\n\
-\n\
-Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+ printf ("Usage : %s [OPTION...]\n\n"\
+ "Daemon which manages kernel routing table management and "\
+ "redistribution between different routing protocols.\n\n"\
+ "-b, --batch Runs in batch mode\n"\
+ "-d, --daemon Runs in daemon mode\n"\
+ "-f, --config_file Set configuration file name\n"\
+ "-i, --pid_file Set process identifier file name\n"\
+ "-k, --keep_kernel Don't delete old routes which installed by "\
+ "zebra.\n"\
+ "-l, --log_mode Set verbose log mode flag\n"\
+ "-A, --vty_addr Set vty's bind address\n"\
+ "-P, --vty_port Set vty's port number\n"\
+ "-r, --retain When program terminates, retain added route "\
+ "by zebra.\n"\
+ "-u, --user User and group to run as\n", progname);
+#ifdef HAVE_NETLINK
+ printf ("-s, --nl-bufsize Set netlink receive buffer size\n");
+#endif /* HAVE_NETLINK */
+ printf ("-v, --version Print program version\n"\
+ "-h, --help Display this help and exit\n"\
+ "\n"\
+ "Report bugs to %s\n", ZEBRA_BUG_ADDRESS);
}
exit (status);
@@ -216,7 +229,11 @@
{
int opt;
+#ifdef HAVE_NETLINK
+ opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:vs:", longopts, 0);
+#else
opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:v", longopts, 0);
+#endif /* HAVE_NETLINK */
if (opt == EOF)
break;
@@ -259,6 +276,11 @@
case 'r':
retain_mode = 1;
break;
+#ifdef HAVE_NETLINK
+ case 's':
+ nl_rcvbufsize = atoi (optarg);
+ break;
+#endif /* HAVE_NETLINK */
case 'u':
zserv_privs.user = zserv_privs.group = optarg;
break;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 2ca0de4..9e6c440 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -84,6 +84,8 @@
extern struct zebra_privs_t zserv_privs;
+extern u_int32_t nl_rcvbufsize;
+
/* Make socket for Linux netlink interface. */
static int
netlink_socket (struct nlsock *nl, unsigned long groups)
@@ -110,6 +112,48 @@
return -1;
}
+ /* Set receive buffer size if it's set from command line */
+ if (nl_rcvbufsize)
+ {
+ u_int32_t oldsize, oldlen;
+ u_int32_t newsize, newlen;
+
+ oldlen = sizeof(oldsize);
+ newlen = sizeof(newsize);
+
+ ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
+ if (ret < 0)
+ {
+ zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
+ strerror (errno));
+ close (sock);
+ return -1;
+ }
+
+ ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
+ sizeof(nl_rcvbufsize));
+ if (ret < 0)
+ {
+ zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
+ strerror (errno));
+ close (sock);
+ return -1;
+ }
+
+ ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
+ if (ret < 0)
+ {
+ zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
+ strerror (errno));
+ close (sock);
+ return -1;
+ }
+
+ zlog (NULL, LOG_INFO,
+ "Setting netlink socket receive buffer size: %u -> %u",
+ oldsize, newsize);
+ }
+
memset (&snl, 0, sizeof snl);
snl.nl_family = AF_NETLINK;
snl.nl_groups = groups;