]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospfd: support configuration of socket buffer sizes
authorMark Stapp <mjs@labn.net>
Thu, 6 Apr 2023 17:40:23 +0000 (13:40 -0400)
committerMark Stapp <mjs@labn.net>
Thu, 6 Apr 2023 18:16:43 +0000 (14:16 -0400)
Add configurable socket send and receive buffer sizes,
configured at the instance level.

Signed-off-by: Mark Stapp <mjs@labn.net>
doc/user/ospfd.rst
ospfd/ospf_network.c
ospfd/ospf_network.h
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h

index 67c0d15750ec0f7b0eaf994f9032de600ef9be17..a99785204b4582f20f02906af8f2bf3d0c6f0d72 100644 (file)
@@ -310,6 +310,11 @@ To start OSPF process you have to specify the OSPF router.
    of packets to process before returning. The defult value of this parameter
    is 20.
 
+.. clicmd:: socket buffer <send | recv | all> (1-4000000000)
+
+   This command controls the ospf instance's socket buffer sizes. The
+   'no' form resets one or both values to the default.
+   
 .. _ospf-area:
 
 Areas
index d3f30ce1ee81c93ec10ad522afbb39dc44a3b4ff..bd5cd7682a6034be245ec99825b2691d78d8f764 100644 (file)
@@ -111,7 +111,7 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
                         "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s",
                         top->fd, &p->u.prefix4, ifindex,
                         safe_strerror(errno));
-       else
+       else if (IS_DEBUG_OSPF_EVENT)
                zlog_debug(
                        "interface %pI4 [%u] leave AllDRouters Multicast group.",
                        &p->u.prefix4, ifindex);
@@ -159,7 +159,6 @@ int ospf_sock_init(struct ospf *ospf)
 {
        int ospf_sock;
        int ret, hincl = 1;
-       int bufsize = (8 * 1024 * 1024);
 
        /* silently ignore. already done */
        if (ospf->fd > 0)
@@ -213,9 +212,28 @@ int ospf_sock_init(struct ospf *ospf)
                                 ospf_sock);
        }
 
-       setsockopt_so_sendbuf(ospf_sock, bufsize);
-       setsockopt_so_recvbuf(ospf_sock, bufsize);
+       /* Update socket buffer sizes */
+       ospf_sock_bufsize_update(ospf, ospf_sock, OSPF_SOCK_BOTH);
 
        ospf->fd = ospf_sock;
        return ret;
 }
+
+/*
+ * Update a socket bufsize(s), based on its ospf instance
+ */
+void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
+                             enum ospf_sock_type_e type)
+{
+       int bufsize;
+
+       if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_RECV) {
+               bufsize = ospf->recv_sock_bufsize;
+               setsockopt_so_recvbuf(sock, bufsize);
+       }
+
+       if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_SEND) {
+               bufsize = ospf->send_sock_bufsize;
+               setsockopt_so_sendbuf(sock, bufsize);
+       }
+}
index 33fd8980bff20366716be1a3fd495f5358977574..d9b579c04a448260e76667cf1d72c31ea6d13264 100644 (file)
@@ -16,4 +16,14 @@ extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t);
 extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t);
 extern int ospf_sock_init(struct ospf *ospf);
 
+enum ospf_sock_type_e {
+       OSPF_SOCK_NONE = 0,
+       OSPF_SOCK_RECV,
+       OSPF_SOCK_SEND,
+       OSPF_SOCK_BOTH
+};
+
+void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
+                             enum ospf_sock_type_e type);
+
 #endif /* _ZEBRA_OSPF_NETWORK_H */
index d3d67ee88446cd99fe8fb64ed2fe76fd9f63dbf8..9b918798c04c11ff30e5c5bdbdbe75067f77fec4 100644 (file)
@@ -3403,6 +3403,23 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
        /* show LDP-Sync status */
        ospf_ldp_sync_show_info(vty, ospf, json_vrf, json ? 1 : 0);
 
+       /* Socket buffer sizes */
+       if (json) {
+               if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+                       json_object_int_add(json_vrf, "recvSockBufsize",
+                                           ospf->recv_sock_bufsize);
+               if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+                       json_object_int_add(json_vrf, "sendSockBufsize",
+                                           ospf->send_sock_bufsize);
+       } else {
+               if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+                       vty_out(vty, " Receive socket bufsize: %u\n",
+                               ospf->recv_sock_bufsize);
+               if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+                       vty_out(vty, " Send socket bufsize: %u\n",
+                               ospf->send_sock_bufsize);
+       }
+
        /* Show each area status. */
        for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
                show_ip_ospf_area(vty, area, json_areas, json ? 1 : 0);
@@ -12550,6 +12567,22 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
        /* LDP-Sync print */
        ospf_ldp_sync_write_config(vty, ospf);
 
+       /* Socket buffer sizes */
+       if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) {
+               if (ospf->send_sock_bufsize == ospf->recv_sock_bufsize)
+                       vty_out(vty, " socket buffer all %u\n",
+                               ospf->recv_sock_bufsize);
+               else
+                       vty_out(vty, " socket buffer recv %u\n",
+                               ospf->recv_sock_bufsize);
+       }
+
+       if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE &&
+           ospf->send_sock_bufsize != ospf->recv_sock_bufsize)
+               vty_out(vty, " socket buffer send %u\n",
+                       ospf->send_sock_bufsize);
+
+
        vty_out(vty, "exit\n");
 
        write++;
@@ -13006,6 +13039,42 @@ DEFPY(no_flood_reduction_area, no_flood_reduction_area_cmd,
        return CMD_SUCCESS;
 }
 
+DEFPY(ospf_socket_bufsizes,
+      ospf_socket_bufsizes_cmd,
+      "[no] socket buffer <send$send_val | recv$recv_val | all$all_val> \
+         ![(1-4000000000)$bufsize]",
+      NO_STR
+      "Socket parameters\n"
+      "Buffer size configuration\n"
+      "Send buffer size\n"
+      "Receive buffer size\n"
+      "Both send and receive buffer sizes\n"
+      "Buffer size, in bytes\n")
+{
+       VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+       uint32_t recvsz, sendsz;
+
+       if (no)
+               bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+
+       if (all_val) {
+               recvsz = bufsize;
+               sendsz = bufsize;
+       } else if (send_val) {
+               sendsz = bufsize;
+               recvsz = ospf->recv_sock_bufsize;
+       } else if (recv_val) {
+               recvsz = bufsize;
+               sendsz = ospf->send_sock_bufsize;
+       } else
+               return CMD_SUCCESS;
+
+       /* React to a change by modifying existing sockets */
+       ospf_update_bufsize(ospf, recvsz, sendsz);
+
+       return CMD_SUCCESS;
+}
+
 void ospf_vty_clear_init(void)
 {
        install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd);
@@ -13169,6 +13238,8 @@ void ospf_vty_init(void)
        install_element(OSPF_NODE, &flood_reduction_area_cmd);
        install_element(OSPF_NODE, &no_flood_reduction_area_cmd);
 
+       install_element(OSPF_NODE, &ospf_socket_bufsizes_cmd);
+
        /* Init interface related vty commands. */
        ospf_vty_if_init();
 
index 4737643bc424f8f3d1bd5f9deb9b213cb530cf4e..15ce1c48a436d6fa773bc7db5acfc80e825644a4 100644 (file)
@@ -420,6 +420,9 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
 
        new->fd = -1;
 
+       new->recv_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+       new->send_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+
        return new;
 }
 
@@ -2180,6 +2183,32 @@ int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr)
        return 1;
 }
 
+/*
+ * Update socket bufsize(s), usually after config change
+ */
+void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize,
+                        uint32_t sendsize)
+{
+       enum ospf_sock_type_e type = OSPF_SOCK_NONE;
+
+       /* Figure out whether there's been a change */
+       if (recvsize != ospf->recv_sock_bufsize) {
+               type = OSPF_SOCK_RECV;
+               ospf->recv_sock_bufsize = recvsize;
+
+               if (sendsize != ospf->send_sock_bufsize) {
+                       type = OSPF_SOCK_BOTH;
+                       ospf->send_sock_bufsize = sendsize;
+               }
+       } else if (sendsize != ospf->send_sock_bufsize) {
+               type = OSPF_SOCK_SEND;
+               ospf->send_sock_bufsize = sendsize;
+       }
+
+       if (type != OSPF_SOCK_NONE)
+               ospf_sock_bufsize_update(ospf, ospf->fd, type);
+}
+
 void ospf_master_init(struct event_loop *master)
 {
        memset(&ospf_master, 0, sizeof(ospf_master));
index af60e6cad042ec842ddd9433f02e130865703652..1b66d4d9304c97e2fc2b7d744962f4c41a97bfbe 100644 (file)
@@ -67,6 +67,9 @@
 #define OSPF_LS_REFRESH_SHIFT       (60 * 15)
 #define OSPF_LS_REFRESH_JITTER      60
 
+/* Default socket buffer size */
+#define OSPF_DEFAULT_SOCK_BUFSIZE   (8 * 1024 * 1024)
+
 struct ospf_external {
        unsigned short instance;
        struct route_table *external_info;
@@ -424,6 +427,10 @@ struct ospf {
        /* Flood Reduction configuration state */
        bool fr_configured;
 
+       /* Socket buffer sizes */
+       uint32_t recv_sock_bufsize;
+       uint32_t send_sock_bufsize;
+
        QOBJ_FIELDS;
 };
 DECLARE_QOBJ_TYPE(ospf);
@@ -793,6 +800,9 @@ int ospf_area_nssa_no_summary_set(struct ospf *ospf, struct in_addr area_id);
 const char *ospf_get_name(const struct ospf *ospf);
 extern struct ospf_interface *add_ospf_interface(struct connected *co,
                                                 struct ospf_area *area);
+/* Update socket bufsize(s), after config change */
+void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize,
+                        uint32_t sendsize);
 
 extern int p_spaces_compare_func(const struct p_space *a,
                                 const struct p_space *b);