}
#else
UNUSED(handle);
- UNUSED(fd);
result = ISC_R_NOTIMPLEMENTED;
#endif
return (result);
}
+isc_result_t
+isc__nm_socket_reuseport(uv_os_fd_t fd) {
+ /*
+ * This is SO_REUSE**** hell:
+ *
+ * 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 12+, the same thing is achieved with SO_REUSEPORT_LB.
+ *
+ */
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+#if defined(SO_REUSEADDR)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEADDR) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ result = ISC_R_SUCCESS;
+ }
+#endif
+#if defined(SO_REUSEPORT_LB)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT_LB) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ result = ISC_R_SUCCESS;
+ }
+#elif defined(SO_REUSEPORT)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ result = ISC_R_SUCCESS;
+ }
+#endif
+ return (result);
+}
+
+isc_result_t
+isc__nm_socket_incoming_cpu(uv_os_fd_t fd) {
+#ifdef SO_INCOMING_CPU
+ if (setsockopt_on(fd, SOL_SOCKET, SO_INCOMING_CPU) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+#endif
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
#ifdef NETMGR_TRACE
/*
* Dump all active sockets in netmgr. We output to stderr
nsock->extrahandlesize = extrahandlesize;
for (size_t i = 0; i < mgr->nworkers; i++) {
+ isc_result_t result;
uint16_t family = iface->addr.type.sa.sa_family;
- int res = 0;
isc__netievent_udplisten_t *ievent = NULL;
isc_nmsocket_t *csock = &nsock->children[i];
csock->fd = socket(family, SOCK_DGRAM, 0);
RUNTIME_CHECK(csock->fd >= 0);
- /*
- * This is SO_REUSE**** hell:
- *
- * 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.
- *
- */
-#if defined(SO_REUSEADDR)
- res = setsockopt(csock->fd, SOL_SOCKET, SO_REUSEADDR,
- &(int){ 1 }, sizeof(int));
- 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));
- RUNTIME_CHECK(res == 0);
-#endif
+ result = isc__nm_socket_reuseport(csock->fd);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS ||
+ result == ISC_R_NOTIMPLEMENTED);
-#ifdef SO_INCOMING_CPU
/* We don't check for the result, because SO_INCOMING_CPU can be
* available without the setter on Linux kernel version 4.4, and
* setting SO_INCOMING_CPU is just an optimization.
*/
- (void)setsockopt(csock->fd, SOL_SOCKET, SO_INCOMING_CPU,
- &(int){ 1 }, sizeof(int));
-#endif
+ (void)isc__nm_socket_incoming_cpu(csock->fd);
+
ievent = isc__nm_get_ievent(mgr, netievent_udplisten);
ievent->sock = csock;
isc__nm_enqueue_ievent(&mgr->workers[i],