From d5615fd6f84e643f194be8c3e91343b35585eb9c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 3 Dec 2024 18:38:59 -0500 Subject: [PATCH 1/2] lib: Allow setsockopt functions to return size set When finding a send/receive buffer size that is usable let's report how big we were able to set it. Signed-off-by: Donald Sharp --- lib/sockopt.c | 8 ++++++-- lib/sockopt.h | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/sockopt.c b/lib/sockopt.c index 74bc034ccd75..003ddb72dc2d 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -19,7 +19,7 @@ #define HAVE_BSD_STRUCT_IP_MREQ_HACK #endif -void setsockopt_so_recvbuf(int sock, int size) +int setsockopt_so_recvbuf(int sock, int size) { int orig_req = size; @@ -34,9 +34,11 @@ void setsockopt_so_recvbuf(int sock, int size) flog_err(EC_LIB_SOCKET, "%s: fd %d: SO_RCVBUF set to %d (requested %d)", __func__, sock, size, orig_req); + + return size; } -void setsockopt_so_sendbuf(const int sock, int size) +int setsockopt_so_sendbuf(const int sock, int size) { int orig_req = size; @@ -51,6 +53,8 @@ void setsockopt_so_sendbuf(const int sock, int size) flog_err(EC_LIB_SOCKET, "%s: fd %d: SO_SNDBUF set to %d (requested %d)", __func__, sock, size, orig_req); + + return size; } int getsockopt_so_sendbuf(const int sock) diff --git a/lib/sockopt.h b/lib/sockopt.h index e6fb78d5e4ef..cbf988cbe718 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -12,8 +12,8 @@ extern "C" { #endif -extern void setsockopt_so_recvbuf(int sock, int size); -extern void setsockopt_so_sendbuf(const int sock, int size); +extern int setsockopt_so_recvbuf(int sock, int size); +extern int setsockopt_so_sendbuf(const int sock, int size); extern int getsockopt_so_sendbuf(const int sock); extern int getsockopt_so_recvbuf(const int sock); From 959dbe27cde21ab212f6566b30865b2da418b4d2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 3 Dec 2024 18:49:59 -0500 Subject: [PATCH 2/2] lib,vtysh: Use backoff setsockopt option for freebsd Commit: 9112fb367b1ae0168b4e7a81f41c2ca621979199 Introduced the idea of setting the socket buffer send/receive sizes. BSD's in general have the fun issue of not allowing nearly as large as a size as linux. Since the above commit was developed on linux and not run on bsd it was never tested. Modify the codebase to use the backoff setsockopt that we have in the code base and use the returned values to allow us to notice what was set and respond appropriately. Signed-off-by: Donald Sharp --- lib/vty.c | 16 ++++++++++++---- lib/vty.h | 3 +++ vtysh/vtysh.c | 6 +++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/vty.c b/lib/vty.c index 256a3bb3f538..1d04e75bf445 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -43,6 +43,7 @@ #include "northbound_cli.h" #include "printfrr.h" #include "json.h" +#include "sockopt.h" #include #include @@ -352,7 +353,7 @@ int vty_out(struct vty *vty, const char *format, ...) * put the data of collective vty->obuf Linked List items on the * socket and free the vty->obuf data. */ - if (vty->vty_buf_size_accumulated >= VTY_MAX_INTERMEDIATE_FLUSH) { + if (vty->vty_buf_size_accumulated >= vty->buf_size_intermediate) { vty->vty_buf_size_accumulated = 0; vtysh_flush(vty); } @@ -2157,15 +2158,15 @@ static void vtysh_accept(struct event *thread) * Increasing the SEND socket buffer size so that the socket can hold * before sending it to VTY shell. */ - ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbufsize, - sizeof(sndbufsize)); - if (ret < 0) { + ret = setsockopt_so_sendbuf(sock, sndbufsize); + if (ret <= 0) { flog_err(EC_LIB_SOCKET, "Cannot set socket %d send buffer size, %s", sock, safe_strerror(errno)); close(sock); return; } + set_cloexec(sock); #ifdef VTYSH_DEBUG @@ -2173,6 +2174,13 @@ static void vtysh_accept(struct event *thread) #endif /* VTYSH_DEBUG */ vty = vty_new(); + + vty->buf_size_set = ret; + if (vty->buf_size_set < VTY_MAX_INTERMEDIATE_FLUSH) + vty->buf_size_intermediate = vty->buf_size_set / 2; + else + vty->buf_size_intermediate = VTY_MAX_INTERMEDIATE_FLUSH; + vty->fd = sock; vty->wfd = sock; vty->type = VTY_SHELL_SERV; diff --git a/lib/vty.h b/lib/vty.h index e511e8e79ae4..be54159aa95d 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -237,6 +237,9 @@ struct vty { bool mgmt_locked_candidate_ds; bool mgmt_locked_running_ds; uint64_t vty_buf_size_accumulated; + + int buf_size_set; + uint64_t buf_size_intermediate; }; static inline void vty_push_context(struct vty *vty, int node, uint64_t id) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 5a54c60c6b11..c460dea70cda 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -39,6 +39,7 @@ #include "frrstr.h" #include "json.h" #include "ferr.h" +#include "sockopt.h" DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy"); @@ -4690,9 +4691,8 @@ static int vtysh_connect(struct vtysh_client *vclient) * Increasing the RECEIVE socket buffer size so that the socket can hold * after receving from other process. */ - ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbufsize, - sizeof(rcvbufsize)); - if (ret < 0) { + ret = setsockopt_so_recvbuf(sock, rcvbufsize); + if (ret <= 0) { #ifdef DEBUG fprintf(stderr, "Cannot set socket %d rcv buffer size, %s\n", sock, safe_strerror(errno));