summaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/ngx_connection.c110
-rw-r--r--src/core/ngx_connection.h7
-rw-r--r--src/core/ngx_cycle.c11
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;
}
}