diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/ngx_connection.c | 110 | ||||
| -rw-r--r-- | src/core/ngx_connection.h | 7 | ||||
| -rw-r--r-- | src/core/ngx_cycle.c | 11 |
3 files changed, 128 insertions, 0 deletions
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 52b97ce89..04a365a76 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -91,6 +91,43 @@ ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) ngx_int_t +ngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls) +{ +#if (NGX_HAVE_REUSEPORT) + + ngx_int_t n; + ngx_core_conf_t *ccf; + ngx_listening_t ols; + + if (!ls->reuseport) { + return NGX_OK; + } + + ols = *ls; + + ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx, + ngx_core_module); + + for (n = 1; n < ccf->worker_processes; n++) { + + /* create a socket for each worker process */ + + ls = ngx_array_push(&cf->cycle->listening); + if (ls == NULL) { + return NGX_ERROR; + } + + *ls = ols; + ls->worker = n; + } + +#endif + + return NGX_OK; +} + + +ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle) { size_t len; @@ -106,6 +143,9 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) int timeout; #endif +#if (NGX_HAVE_REUSEPORT) + int reuseport; +#endif ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { @@ -215,6 +255,25 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) #endif #endif +#if (NGX_HAVE_REUSEPORT) + + reuseport = 0; + olen = sizeof(int); + + if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT, + (void *) &reuseport, &olen) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "getsockopt(SO_REUSEPORT) %V failed, ignored", + &ls[i].addr_text); + + } else { + ls[i].reuseport = reuseport ? 1 : 0; + } + +#endif + #if (NGX_HAVE_TCP_FASTOPEN) olen = sizeof(int); @@ -332,6 +391,31 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) continue; } +#if (NGX_HAVE_REUSEPORT) + + if (ls[i].add_reuseport) { + + /* + * to allow transition from a socket without SO_REUSEPORT + * to multiple sockets with SO_REUSEPORT, we have to set + * SO_REUSEPORT on the old socket before opening new ones + */ + + int reuseport = 1; + + if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed, ignored", + &ls[i].addr_text); + } + + ls[i].add_reuseport = 0; + } +#endif + if (ls[i].fd != (ngx_socket_t) -1) { continue; } @@ -370,6 +454,32 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) return NGX_ERROR; } +#if (NGX_HAVE_REUSEPORT) + + if (ls[i].reuseport) { + int reuseport; + + reuseport = 1; + + if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, + (const void *) &reuseport, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(SO_REUSEPORT) %V failed, ignored", + &ls[i].addr_text); + + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } + } +#endif + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 27bb8a99c..a49aa9579 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -51,6 +51,8 @@ struct ngx_listening_s { ngx_listening_t *previous; ngx_connection_t *connection; + ngx_uint_t worker; + unsigned open:1; unsigned remain:1; unsigned ignore:1; @@ -66,6 +68,10 @@ struct ngx_listening_s { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) unsigned ipv6only:1; #endif +#if (NGX_HAVE_REUSEPORT) + unsigned reuseport:1; + unsigned add_reuseport:1; +#endif unsigned keepalive:2; #if (NGX_HAVE_DEFERRED_ACCEPT) @@ -203,6 +209,7 @@ struct ngx_connection_s { ngx_listening_t *ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen); +ngx_int_t ngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls); ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle); ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle); void ngx_configure_listening_sockets(ngx_cycle_t *cycle); diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 4852e3bbe..b358f3dbe 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -493,6 +493,10 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) continue; } + if (ls[i].remain) { + continue; + } + if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) == NGX_OK) @@ -540,6 +544,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) nls[n].add_deferred = 1; } #endif + +#if (NGX_HAVE_REUSEPORT) + if (nls[n].reuseport && !ls[i].reuseport) { + nls[n].add_reuseport = 1; + } +#endif + break; } } |
