From 6e6e1020dd6e974557159740fcbb8ac395a2ef73 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Thu, 6 Apr 2023 13:40:23 -0400 Subject: [PATCH] ospfd: support configuration of socket buffer sizes Add configurable socket send and receive buffer sizes, configured at the instance level. Signed-off-by: Mark Stapp --- doc/user/ospfd.rst | 5 ++++ ospfd/ospf_network.c | 26 +++++++++++++--- ospfd/ospf_network.h | 10 +++++++ ospfd/ospf_vty.c | 71 ++++++++++++++++++++++++++++++++++++++++++++ ospfd/ospfd.c | 29 ++++++++++++++++++ ospfd/ospfd.h | 10 +++++++ 6 files changed, 147 insertions(+), 4 deletions(-) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 67c0d15750..a99785204b 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -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 (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 diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index d3f30ce1ee..bd5cd7682a 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -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); + } +} diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index 33fd8980bf..d9b579c04a 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -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 */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index d3d67ee884..9b918798c0 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -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 \ + ![(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(); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 4737643bc4..15ce1c48a4 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -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)); diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index af60e6cad0..1b66d4d930 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -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); -- 2.39.5