[cmaster-next] [PATCH 2/2] *: always set SO_SNDBUF and SO_RCVBUF using a best effort approach

Renato Westphal renato at opensourcerouting.org
Wed Dec 7 10:21:46 EST 2016


If we fail to set any socket's buffer size, try again with a smaller value
and keep going until it succeeds. This is better than just giving up or,
even worse, abort the creation of a socket (ospf6d and ripd).

Fix broken ospf6d on FreeBSD.

Signed-off-by: Renato Westphal <renato at opensourcerouting.org>
---
 bgpd/bgp_network.c     | 26 ++------------------------
 lib/sockopt.c          | 32 ++++++++++++++++----------------
 lib/sockopt.h          |  4 ++--
 ospf6d/ospf6_network.c | 38 ++------------------------------------
 ospfd/ospf_network.c   | 36 ++----------------------------------
 ripngd/ripngd.c        |  4 +---
 6 files changed, 25 insertions(+), 115 deletions(-)

diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index c528fcd..9a49051 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -151,28 +151,6 @@ bgp_md5_unset (struct peer *peer)
   return bgp_md5_set_password (peer, NULL);
 }
 
-/* Update BGP socket send buffer size */
-static void
-bgp_update_sock_send_buffer_size (int fd)
-{
-  int size = BGP_SOCKET_SNDBUF_SIZE;
-  int optval;
-  socklen_t optlen = sizeof(optval);
-
-  if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0)
-    {
-      zlog_err("getsockopt of SO_SNDBUF failed %s\n", safe_strerror(errno));
-      return;
-    }
-  if (optval < size)
-    {
-      if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
-        {
-          zlog_err("Couldn't increase send buffer: %s\n", safe_strerror(errno));
-        }
-    }
-}
-
 int
 bgp_set_socket_ttl (struct peer *peer, int bgp_sock)
 {
@@ -341,7 +319,7 @@ bgp_accept (struct thread *thread)
     }
 
   /* Set socket send buffer size */
-  bgp_update_sock_send_buffer_size(bgp_sock);
+  setsockopt_so_sendbuf (bgp_sock, BGP_SOCKET_SNDBUF_SIZE);
 
   /* Check remote IP address */
   peer1 = peer_lookup (bgp, &su);
@@ -604,7 +582,7 @@ bgp_connect (struct peer *peer)
   set_nonblocking (peer->fd);
 
   /* Set socket send buffer size */
-  bgp_update_sock_send_buffer_size(peer->fd);
+  setsockopt_so_sendbuf (peer->fd, BGP_SOCKET_SNDBUF_SIZE);
 
   if (bgp_set_socket_ttl (peer, peer->fd) < 0)
     return -1;
diff --git a/lib/sockopt.c b/lib/sockopt.c
index be3ac0e..461e1f7 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -29,30 +29,30 @@
 #include "sockopt.h"
 #include "sockunion.h"
 
-int
+void
 setsockopt_so_recvbuf (int sock, int size)
 {
-  int ret;
-  
-  if ( (ret = setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *)
-                          &size, sizeof (int))) < 0)
-    zlog_err ("fd %d: can't setsockopt SO_RCVBUF to %d: %s",
-	      sock,size,safe_strerror(errno));
+  int orig_req = size;
 
-  return ret;
+  while (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) == -1)
+    size /= 2;
+
+  if (size != orig_req)
+    zlog_warn ("%s: fd %d: SO_RCVBUF set to %d (requested %d)", __func__, sock,
+	       size, orig_req);
 }
 
-int
+void
 setsockopt_so_sendbuf (const int sock, int size)
 {
-  int ret = setsockopt (sock, SOL_SOCKET, SO_SNDBUF,
-    (char *)&size, sizeof (int));
-  
-  if (ret < 0)
-    zlog_err ("fd %d: can't setsockopt SO_SNDBUF to %d: %s",
-      sock, size, safe_strerror (errno));
+  int orig_req = size;
 
-  return ret;
+  while (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) == -1)
+    size /= 2;
+
+  if (size != orig_req)
+    zlog_warn ("%s: fd %d: SO_SNDBUF set to %d (requested %d)", __func__, sock,
+	       size, orig_req);
 }
 
 int
diff --git a/lib/sockopt.h b/lib/sockopt.h
index 02f0189..b3ab57a 100644
--- a/lib/sockopt.h
+++ b/lib/sockopt.h
@@ -24,8 +24,8 @@
 
 #include "sockunion.h"
 
-extern int setsockopt_so_recvbuf (int sock, int size);
-extern int setsockopt_so_sendbuf (const int sock, int size);
+extern void setsockopt_so_recvbuf (int sock, int size);
+extern void setsockopt_so_sendbuf (const int sock, int size);
 extern int getsockopt_so_sendbuf (const int sock);
 
 #ifdef HAVE_IPV6
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index 0d730c5..0217d66 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -118,8 +118,6 @@ ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option)
   struct ipv6_mreq mreq6;
   int ret;
   int bufsize = (8 * 1024 * 1024);
-  int optval;
-  socklen_t optlen = sizeof(optval);
 
   assert (ifindex);
   mreq6.ipv6mr_interface = ifindex;
@@ -134,40 +132,8 @@ ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option)
       return ret;
     }
 
-  if ((ret = setsockopt (ospf6_sock, SOL_SOCKET, SO_SNDBUF,
-			 &bufsize, sizeof (bufsize))) < 0)
-    {
-      zlog_err ("Couldn't increase raw wbuf size: %s\n", safe_strerror(errno));
-      return ret;
-    }
-
-  if ((ret = getsockopt (ospf6_sock, SOL_SOCKET, SO_SNDBUF,
-			 &optval, &optlen)) < 0)
-    {
-      zlog_err ("getsockopt of SO_SNDBUF failed with error %s\n", safe_strerror(errno));
-      return ret;
-    }
-  else if (optval < bufsize)
-    {
-      zlog_err ("Unable to SO_SNDBUF to %d, set to %d\n", bufsize, optval);
-    }
-
-  if ((ret = setsockopt (ospf6_sock, SOL_SOCKET, SO_RCVBUF,
-			 &bufsize, sizeof (bufsize))) < 0)
-    {
-      zlog_err ("Couldn't increase raw rbuf size: %s\n", safe_strerror(errno));
-    }
-
-  if ((ret = getsockopt (ospf6_sock, SOL_SOCKET, SO_RCVBUF,
-			 &optval, &optlen)) < 0)
-    {
-      zlog_err ("getsockopt of SO_RCVBUF failed with error %s\n", safe_strerror(errno));
-      return ret;
-    }
-  else if (optval < bufsize)
-    {
-      zlog_err ("Unable to SO_RCVBUF to %d, set to %d\n", bufsize, optval);
-    }
+  setsockopt_so_sendbuf (ospf6_sock, bufsize);
+  setsockopt_so_recvbuf (ospf6_sock, bufsize);
 
   return 0;
 }
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
index f02fcd1..d7ec256 100644
--- a/ospfd/ospf_network.c
+++ b/ospfd/ospf_network.c
@@ -161,8 +161,6 @@ ospf_sock_init (void)
   int ospf_sock;
   int ret, hincl = 1;
   int bufsize = (8 * 1024 * 1024);
-  int optval;
-  socklen_t optlen = sizeof(optval);
 
   if ( ospfd_privs.change (ZPRIVS_RAISE) )
     zlog_err ("ospf_sock_init: could not raise privs, %s",
@@ -222,38 +220,8 @@ ospf_sock_init (void)
                safe_strerror (errno) );
     }
 
-  if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF,
-			 &bufsize, sizeof (bufsize))) < 0)
-    {
-      zlog_err ("Couldn't increase raw rbuf size: %s\n", safe_strerror(errno));
-    }
-
-  if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF,
-			 &optval, &optlen)) < 0)
-    {
-      zlog_err("getsockopt of SO_RCVBUF failed with error %s\n", safe_strerror(errno));
-    }
-  if (optval < bufsize)
-    {
-      zlog_err("Unable to SO_RCVBUF to %d, set to %d\n", bufsize, optval);
-    }
-
+  setsockopt_so_sendbuf (ospf_sock, bufsize);
+  setsockopt_so_recvbuf (ospf_sock, bufsize);
 
-  if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF,
-			 &bufsize, sizeof (bufsize))) < 0)
-    {
-      zlog_err ("Couldn't increase raw wbuf size: %s\n", safe_strerror(errno));
-    }
-
-  if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF,
-			 &optval, &optlen)) < 0)
-    {
-      zlog_err ("getsockopt of SO_SNDBUF failed with error %s\n", safe_strerror(errno));
-    }
-  if (optval < bufsize)
-    {
-      zlog_err ("Unable to SO_SNDBUF to %d, set to %d\n", bufsize, optval);
-    }
- 
   return ospf_sock;
 }
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index ca8850e..34ad859 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -111,9 +111,7 @@ ripng_make_socket (void)
       return sock;
     }
 
-  ret = setsockopt_so_recvbuf (sock, 8096);
-  if (ret < 0)
-    return ret;
+  setsockopt_so_recvbuf (sock, 8096);
   ret = setsockopt_ipv6_pktinfo (sock, 1);
   if (ret < 0)
     return ret;
-- 
1.9.1





More information about the dev mailing list