From c56cd29bbbf19db1f71db4e2df16f569fd92308b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 15 Apr 2020 07:33:44 +0200 Subject: [PATCH] Use SO_REUSEPORT only on Linux, use SO_REUSEPORT_LB on FreeBSD The SO_REUSEPORT socket option on Linux means something else on BSD based systems. On FreeBSD there's 1:1 option SO_REUSEPORT_LB, so we can use that. (cherry picked from commit 09ba47b0676f14af47b71364e1fe52c298b4079a) --- lib/isc/netmgr/udp.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 6f8c83a75f..8f6826ffa9 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -66,7 +66,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb, for (size_t i = 0; i < mgr->nworkers; i++) { uint16_t family = iface->addr.type.sa.sa_family; - int res; + int res = 0; isc__netievent_udplisten_t *ievent = NULL; isc_nmsocket_t *csock = &nsock->children[i]; @@ -84,22 +84,40 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb, /* * This is SO_REUSE**** hell: - * On Linux SO_REUSEPORT allows multiple sockets to bind to - * the same host:port pair. - * On Windows the same thing is achieved with SO_REUSEADDR + * + * Generally, the SO_REUSEADDR socket option allows reuse of + * local addresses. On Windows, it also allows a socket to + * forcibly bind to a port in use by another socket. + * + * On Linux, SO_REUSEPORT socket option allows sockets to be + * bound to an identical socket address. For UDP sockets, the + * use of this option can provide better distribution of + * incoming datagrams to multiple processes (or threads) as + * compared to the traditional technique of having multiple + * processes compete to receive datagrams on the same socket. + * + * On FreeBSD, the same thing is achieved with SO_REUSEPORT_LB. + * */ -#ifdef WIN32 +#if defined(SO_REUSEADDR) res = setsockopt(csock->fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)); -#else /* ifdef WIN32 */ + RUNTIME_CHECK(res == 0); +#endif +#if defined(SO_REUSEPORT_LB) + res = setsockopt(csock->fd, SOL_SOCKET, SO_REUSEPORT_LB, + &(int){ 1 }, sizeof(int)); + RUNTIME_CHECK(res == 0); +#elif defined(SO_REUSEPORT) res = setsockopt(csock->fd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof(int)); -#endif /* ifdef WIN32 */ RUNTIME_CHECK(res == 0); +#endif #ifdef SO_INCOMING_CPU - setsockopt(csock->fd, SOL_SOCKET, SO_INCOMING_CPU, &(int){ 1 }, - sizeof(int)); + res = setsockopt(csock->fd, SOL_SOCKET, SO_INCOMING_CPU, + &(int){ 1 }, sizeof(int)); + RUNTIME_CHECK(res == 0); #endif ievent = isc__nm_get_ievent(mgr, netievent_udplisten); ievent->sock = csock;