summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2016-12-07 16:21:46 +0100
committerDavid Lamparter <equinox@opensourcerouting.org>2016-12-08 12:50:25 +0100
commit6228a3b8743ea2a6589070de926588e2ceb0f27f (patch)
tree1d4f333086f14d333c2aae31b1c01a27e55e8b0b
parentospfd: set the OSPF socket's send buffer size only once (diff)
downloadfrr-6228a3b8743ea2a6589070de926588e2ceb0f27f.tar.xz
frr-6228a3b8743ea2a6589070de926588e2ceb0f27f.zip
*: always set SO_SNDBUF and SO_RCVBUF using a best effort approach
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@opensourcerouting.org> Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
-rw-r--r--bgpd/bgp_network.c26
-rw-r--r--lib/sockopt.c32
-rw-r--r--lib/sockopt.h4
-rw-r--r--ospf6d/ospf6_network.c38
-rw-r--r--ospfd/ospf_network.c36
-rw-r--r--ripngd/ripngd.c4
6 files changed, 25 insertions, 115 deletions
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index c528fcdcd..9a49051a9 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 be3ac0e4b..461e1f7f5 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 02f018934..b3ab57ab7 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 0d730c596..0217d6603 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 f02fcd14a..d7ec25621 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 82c487748..4d59ef203 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;