[nginx] Stream: set SO_REUSEADDR for UDP upstream sockets.

Roman Arutyunyan arut at nginx.com
Mon Jun 20 09:50:11 UTC 2016


details:   http://hg.nginx.org/nginx/rev/e778fe9a4463
branches:  
changeset: 6596:e778fe9a4463
user:      Roman Arutyunyan <arut at nginx.com>
date:      Mon Jun 20 12:48:47 2016 +0300
description:
Stream: set SO_REUSEADDR for UDP upstream sockets.

The option is only set if the socket is bound to a specific port to allow
several such sockets coexist at the same time.  This is required, for example,
when nginx acts as a transparent proxy and receives two datagrams from the same
client in a short time.

The feature is only implemented for Linux.

diffstat:

 src/event/ngx_event_connect.c |  26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)

diffs (52 lines):

diff -r 0c98c4092440 -r e778fe9a4463 src/event/ngx_event_connect.c
--- a/src/event/ngx_event_connect.c	Mon Jun 20 11:50:44 2016 +0300
+++ b/src/event/ngx_event_connect.c	Mon Jun 20 12:48:47 2016 +0300
@@ -21,6 +21,9 @@ ngx_int_t
 ngx_event_connect_peer(ngx_peer_connection_t *pc)
 {
     int                rc, type;
+#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX)
+    in_port_t          port;
+#endif
     ngx_int_t          event;
     ngx_err_t          err;
     ngx_uint_t         level;
@@ -87,9 +90,13 @@ ngx_event_connect_peer(ngx_peer_connecti
         }
 #endif
 
+#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX)
+        port = ngx_inet_get_port(pc->sockaddr);
+#endif
+
 #if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT)
 
-        if (pc->sockaddr->sa_family != AF_UNIX) {
+        if (pc->sockaddr->sa_family != AF_UNIX && port == 0) {
             static int  bind_address_no_port = 1;
 
             if (bind_address_no_port) {
@@ -113,6 +120,23 @@ ngx_event_connect_peer(ngx_peer_connecti
 
 #endif
 
+#if (NGX_LINUX)
+
+        if (pc->type == SOCK_DGRAM && port != 0) {
+            int  reuse_addr = 1;
+
+            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                           (const void *) &reuse_addr, sizeof(int))
+                 == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+                              "setsockopt(SO_REUSEADDR) failed");
+                goto failed;
+            }
+        }
+
+#endif
+
         if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
             ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
                           "bind(%V) failed", &pc->local->name);



More information about the nginx-devel mailing list