]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Allow *BSD to specify a receive buffer size
authorDonald Sharp <sharpd@nvidia.com>
Sat, 26 Feb 2022 20:40:15 +0000 (15:40 -0500)
committerDonald Sharp <sharpd@nvidia.com>
Sun, 27 Feb 2022 12:47:58 +0000 (07:47 -0500)
End operator is reporting that they are receiving buffer overruns
when attempting to read from the kernel receive socket.  It is
possible to adjust this size to more modern levels especially
for when the system is under load.  Modify the code base
so that *BSD operators can use the zebra `-s XXX` option
to specify a read buffer.

Additionally setup the default receive buffer size on *BSD
to be 128k instead of the 8k so that FRR does not run into
this issue again.

Fixes: #10666
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
zebra/kernel_netlink.c
zebra/kernel_socket.c
zebra/main.c
zebra/zebra_router.h

index 031ac0733c0b3abdd6ddc4e9da66bf835b141682..d84b0c13251f7c4e249663812cf9f2adb6d5e4c3 100644 (file)
@@ -155,7 +155,6 @@ static const struct message rttype_str[] = {{RTN_UNSPEC, "none"},
                                            {0}};
 
 extern struct thread_master *master;
-extern uint32_t nl_rcvbufsize;
 
 extern struct zebra_privs_t zserv_privs;
 
@@ -261,12 +260,11 @@ static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize)
        /* Try force option (linux >= 2.6.14) and fall back to normal set */
        frr_with_privs(&zserv_privs) {
                ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE,
-                                &nl_rcvbufsize,
-                                sizeof(nl_rcvbufsize));
+                                &rcvbufsize, sizeof(rcvbufsize));
        }
        if (ret < 0)
-               ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF,
-                                &nl_rcvbufsize, sizeof(nl_rcvbufsize));
+               ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
+                                sizeof(rcvbufsize));
        if (ret < 0) {
                flog_err_sys(EC_LIB_SOCKET,
                             "Can't set %s receive buffer size: %s", nl->name,
@@ -1732,11 +1730,11 @@ void kernel_init(struct zebra_ns *zns)
                         errno);
 
        /* Set receive buffer size if it's set from command line */
-       if (nl_rcvbufsize) {
-               netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
-               netlink_recvbuf(&zns->netlink_cmd, nl_rcvbufsize);
-               netlink_recvbuf(&zns->netlink_dplane_out, nl_rcvbufsize);
-               netlink_recvbuf(&zns->netlink_dplane_in, nl_rcvbufsize);
+       if (rcvbufsize) {
+               netlink_recvbuf(&zns->netlink, rcvbufsize);
+               netlink_recvbuf(&zns->netlink_cmd, rcvbufsize);
+               netlink_recvbuf(&zns->netlink_dplane_out, rcvbufsize);
+               netlink_recvbuf(&zns->netlink_dplane_in, rcvbufsize);
        }
 
        /* Set filter for inbound sockets, to exclude events we've generated
index 53b7a21d32d648cbf5b4efffe6f6e91365e0af66..d812094848cd730c21ef09aa03da89f97197439a 100644 (file)
@@ -1408,6 +1408,9 @@ static void kernel_read(struct thread *thread)
 /* Make routing socket. */
 static void routing_socket(struct zebra_ns *zns)
 {
+       uint32_t default_rcvbuf;
+       socklen_t optlen;
+
        frr_with_privs(&zserv_privs) {
                routing_sock = ns_socket(AF_ROUTE, SOCK_RAW, 0, zns->ns_id);
 
@@ -1442,6 +1445,23 @@ static void routing_socket(struct zebra_ns *zns)
        /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
          zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
 
+       /*
+        * Attempt to set a more useful receive buffer size
+        */
+       optlen = sizeof(default_rcvbuf);
+       if (getsockopt(routing_sock, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf,
+                      &optlen) == -1)
+               flog_err_sys(EC_LIB_SOCKET,
+                            "routing_sock sockopt SOL_SOCKET SO_RCVBUF");
+       else {
+               for (; rcvbufsize > default_rcvbuf &&
+                      setsockopt(routing_sock, SOL_SOCKET, SO_RCVBUF,
+                                 &rcvbufsize, sizeof(rcvbufsize)) == -1 &&
+                      errno == ENOBUFS;
+                    rcvbufsize /= 2)
+                       ;
+       }
+
        /* kernel_read needs rewrite. */
        thread_add_read(zrouter.master, kernel_read, NULL, routing_sock, NULL);
 }
index 9deafb532ed8182b13b2636078ad8cef4fee9d82..7ef30d1d491614ab36d94b59f3e3695dfefc0e47 100644 (file)
@@ -78,10 +78,12 @@ int graceful_restart;
 
 bool v6_rr_semantics = false;
 
+/* Receive buffer size for kernel control sockets */
 #ifdef HAVE_NETLINK
-/* Receive buffer size for netlink socket */
-uint32_t nl_rcvbufsize = 4194304;
-#endif /* HAVE_NETLINK */
+uint32_t rcvbufsize = 4194304;
+#else
+uint32_t rcvbufsize = 128 * 1024;
+#endif
 
 #define OPTION_V6_RR_SEMANTICS 2000
 #define OPTION_ASIC_OFFLOAD    2001
@@ -294,9 +296,9 @@ int main(int argc, char **argv)
        frr_preinit(&zebra_di, argc, argv);
 
        frr_opt_add(
-               "baz:e:rK:"
+               "baz:e:rK:s:"
 #ifdef HAVE_NETLINK
-               "s:n"
+               "n"
 #endif
                ,
                longopts,
@@ -308,9 +310,11 @@ int main(int argc, char **argv)
                "  -K, --graceful_restart   Graceful restart at the kernel level, timer in seconds for expiration\n"
                "  -A, --asic-offload       FRR is interacting with an asic underneath the linux kernel\n"
 #ifdef HAVE_NETLINK
-               "  -n, --vrfwnetns          Use NetNS as VRF backend\n"
                "  -s, --nl-bufsize         Set netlink receive buffer size\n"
+               "  -n, --vrfwnetns          Use NetNS as VRF backend\n"
                "      --v6-rr-semantics    Use v6 RR semantics\n"
+#else
+               "  -s,                      Set kernel socket receive buffer size\n"
 #endif /* HAVE_NETLINK */
        );
 
@@ -359,10 +363,10 @@ int main(int argc, char **argv)
                case 'K':
                        graceful_restart = atoi(optarg);
                        break;
-#ifdef HAVE_NETLINK
                case 's':
-                       nl_rcvbufsize = atoi(optarg);
+                       rcvbufsize = atoi(optarg);
                        break;
+#ifdef HAVE_NETLINK
                case 'n':
                        vrf_configure_backend(VRF_BACKEND_NETNS);
                        break;
index dafe925c26d4757a41f893aee5b93970c5482252..63a61d5293c56eb1719936eacf12a1258866426f 100644 (file)
@@ -216,6 +216,7 @@ struct zebra_router {
 #define GRACEFUL_RESTART_TIME 60
 
 extern struct zebra_router zrouter;
+extern uint32_t rcvbufsize;
 
 extern void zebra_router_init(bool asic_offload, bool notify_on_ack);
 extern void zebra_router_cleanup(void);