diff options
-rw-r--r-- | doc/ChangeLog | 4 | ||||
-rw-r--r-- | doc/zebra.8 | 12 | ||||
-rw-r--r-- | zebra/ChangeLog | 5 | ||||
-rw-r--r-- | zebra/main.c | 56 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 44 |
5 files changed, 104 insertions, 17 deletions
diff --git a/doc/ChangeLog b/doc/ChangeLog index 63b736cc..97dddece 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 8f830152..25cbb363 100644 --- a/doc/zebra.8 +++ b/doc/zebra.8 @@ -71,6 +71,18 @@ name at the moment. Default is \fIquagga\fR. \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 9dd031cb..b6798077 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 6d40d708..0c1a7ddb 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -57,6 +57,11 @@ int retain_mode = 0; /* 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 @@ struct option longopts[] = { "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 @@ usage (char *progname, int status) 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 @@ main (int argc, char **argv) { 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 @@ main (int argc, char **argv) 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 2ca0de43..9e6c440b 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -84,6 +84,8 @@ extern struct zebra_t zebrad; 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 @@ netlink_socket (struct nlsock *nl, unsigned long groups) 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; |