changeset 16822:6a814345f16c

lib: Added net_listen_full() with a flag to set SO_REUSEPORT on the socket if available.
author Timo Sirainen <tss@iki.fi>
date Mon, 23 Sep 2013 04:06:08 +0300
parents 1a5d92b8d3d5
children a991a0547daa
files src/lib/net.c src/lib/net.h
diffstat 2 files changed, 24 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/net.c	Sun Sep 22 07:43:31 2013 +0300
+++ b/src/lib/net.c	Mon Sep 23 04:06:08 2013 +0300
@@ -384,6 +384,14 @@
 
 int net_listen(const struct ip_addr *my_ip, unsigned int *port, int backlog)
 {
+	enum net_listen_flags flags = 0;
+
+	return net_listen_full(my_ip, port, &flags, backlog);
+}
+
+int net_listen_full(const struct ip_addr *my_ip, unsigned int *port,
+		    enum net_listen_flags *flags, int backlog)
+{
 	union sockaddr_union so;
 	int ret, fd, opt = 1;
 	socklen_t len;
@@ -413,6 +421,14 @@
 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 	setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));
 
+	if ((*flags & NET_LISTEN_FLAG_REUSEPORT) != 0) {
+#ifdef SO_REUSEPORT
+		if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
+			       &opt, sizeof(opt)) < 0)
+#endif
+			*flags &= ~NET_LISTEN_FLAG_REUSEPORT;
+	}
+
 	/* If using IPv6, bind only to IPv6 if possible. This avoids
 	   ambiguities with IPv4-mapped IPv6 addresses. */
 #ifdef IPV6_V6ONLY
--- a/src/lib/net.h	Sun Sep 22 07:43:31 2013 +0300
+++ b/src/lib/net.h	Mon Sep 23 04:06:08 2013 +0300
@@ -55,6 +55,12 @@
 #define IPADDR_IS_V6(ip) ((ip)->family == AF_INET6)
 #define IPADDR_BITS(ip) (IPADDR_IS_V4(ip) ? 32 : 128)
 
+enum net_listen_flags {
+	/* Try to use SO_REUSEPORT if available. If it's not, this flag is
+	   cleared on return. */
+	NET_LISTEN_FLAG_REUSEPORT	= 0x01
+};
+
 /* Returns TRUE if IPs are the same */
 bool net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2);
 /* Returns 0 if IPs are the same, -1 or 1 otherwise. */
@@ -91,6 +97,8 @@
 
 /* Listen for connections on a socket */
 int net_listen(const struct ip_addr *my_ip, unsigned int *port, int backlog);
+int net_listen_full(const struct ip_addr *my_ip, unsigned int *port,
+		    enum net_listen_flags *flags, int backlog);
 /* Listen for connections on an UNIX socket */
 int net_listen_unix(const char *path, int backlog);
 /* Like net_listen_unix(), but if socket already exists, try to connect to it.