diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 08f9782cf7..ccafc8f0c0 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -154,7 +154,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; @@ -251,12 +250,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, @@ -1624,11 +1622,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 diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 5ff66f7c63..499b9cccf6 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1409,6 +1409,9 @@ static int 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); @@ -1443,6 +1446,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); } diff --git a/zebra/main.c b/zebra/main.c index 079751af0a..6a5bdfed78 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -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; diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index dd788216c7..c0eab9cd6e 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -214,6 +214,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);