bgpd: increase TCP socket buffer size

BGP does not respond fairly in high scale.  As the number of BGP peers
and prefixes increase, triggers like interface flaps which lead to BGP
peer flaps, cause blockage in bgp_write.

BGP does handle the cases of TCP socket buffer full by queuing a write
event back, there is no functional issue there as such. Still,
increasing the peer socket buffer size should help reduce event queueing
in BGP.

Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Dinesh Dutt <ddutt@cumulusnetworks.com>
[DL: patch split, this is item 3.]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index bcaaba7..d86db3c 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -122,7 +122,29 @@
   
   return ret;
 }
-
+
+/* 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));
+        }
+    }
+}
+
 /* Accept bgp connection. */
 static int
 bgp_accept (struct thread *thread)
@@ -153,6 +175,9 @@
     }
   set_nonblocking (bgp_sock);
 
+  /* Set socket send buffer size */
+  bgp_update_sock_send_buffer_size(bgp_sock);
+
   if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
   
@@ -308,6 +333,9 @@
 
   set_nonblocking (peer->fd);
 
+  /* Set socket send buffer size */
+  bgp_update_sock_send_buffer_size(peer->fd);
+
   /* If we can get socket for the peer, adjest TTL and make connection. */
   if (peer->sort == BGP_PEER_EBGP) {
     sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);