Merge pull request #117 from chadwill/master

Nginx: support kernel network stack
This commit is contained in:
logwang 2017-12-15 17:36:07 +08:00 committed by GitHub
commit c4e752fc00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 730 additions and 167 deletions

View File

@ -106,8 +106,8 @@ WIN32_SELECT_SRCS=src/event/modules/ngx_win32_select_module.c
POLL_MODULE=ngx_poll_module
POLL_SRCS=src/event/modules/ngx_poll_module.c
KQUEUE_MODULE="ngx_kqueue_module ngx_ff_channel_module"
KQUEUE_SRCS="src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_ff_module.c src/event/modules/ngx_ff_channel.c"
KQUEUE_MODULE="ngx_kqueue_module ngx_ff_host_event_module"
KQUEUE_SRCS="src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_ff_module.c src/event/modules/ngx_ff_host_event_module.c"
DEVPOLL_MODULE=ngx_devpoll_module
DEVPOLL_SRCS=src/event/modules/ngx_devpoll_module.c

View File

@ -41,6 +41,10 @@ http {
listen 80;
server_name localhost;
# bulid server on kernel network stack
#
#kernel_network_stack on;
#charset koi8-r;
access_log /dev/null;

View File

@ -376,6 +376,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
return NGX_OK;
}
#if (NGX_HAVE_FSTACK)
extern int
fstack_territory(int domain, int type, int protocol);
#endif
ngx_int_t
ngx_open_listening_sockets(ngx_cycle_t *cycle)
@ -404,6 +408,36 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
#if (NGX_HAVE_FSTACK)
if (ngx_process <= NGX_PROCESS_MASTER) {
/* process master, kernel network stack*/
if (!ls[i].belong_to_host) {
/* We should continue to process the listening socket,
if it is not supported by fstack.*/
if (fstack_territory(ls[i].sockaddr->sa_family, ls[i].type, 0)) {
continue;
}
}
} else if (NGX_PROCESS_WORKER == ngx_process) {
/* process worker, fstack */
if (ls[i].belong_to_host) {
continue;
}
if (!fstack_territory(ls[i].sockaddr->sa_family, ls[i].type, 0)) {
continue;
}
} else {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"unexpected process type: %d, ignored",
ngx_process);
exit(1);
}
#endif
if (ls[i].ignore) {
continue;
}
@ -971,6 +1005,15 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
#if (NGX_HAVE_FSTACK)
// No need to deal with, just skip
if (fstack_territory(ls[i].sockaddr->sa_family, ls[i].type, 0)) {
continue;
}
#endif //(NGX_HAVE_FSTACK)
c = ls[i].connection;
if (c) {
@ -1032,6 +1075,9 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
ngx_uint_t instance;
ngx_event_t *rev, *wev;
ngx_connection_t *c;
#if (NGX_HAVE_FSTACK)
ngx_atomic_uint_t success;
#endif
/* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
@ -1042,7 +1088,35 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
s, ngx_cycle->files_n);
return NULL;
}
#if (NGX_HAVE_FSTACK)
#ifndef unlikely
#define unlikely(x) __builtin_expect((x),0)
#endif
/* move ngx_cycle->free_connections atomically */
do {
/* Restore n as it may change every loop */
c = ngx_cycle->free_connections;
if (c == NULL) {
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
c = ngx_cycle->free_connections;
}
if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"%ui worker_connections are not enough",
ngx_cycle->connection_n);
return NULL;
}
success = ngx_atomic_cmp_set(&ngx_cycle->free_connections, c,
c->data);
} while (unlikely(success == 0));
ngx_memory_barrier();
#else
c = ngx_cycle->free_connections;
if (c == NULL) {
@ -1059,6 +1133,7 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
}
ngx_cycle->free_connections = c->data;
#endif
ngx_cycle->free_connection_n--;
if (ngx_cycle->files && ngx_cycle->files[s] == NULL) {
@ -1098,8 +1173,25 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
void
ngx_free_connection(ngx_connection_t *c)
{
#if (NGX_HAVE_FSTACK)
ngx_atomic_uint_t success;
/* move ngx_cycle->free_connections atomically */
do {
/* Restore n as it may change every loop */
c->data = ngx_cycle->free_connections;
success = ngx_atomic_cmp_set(&ngx_cycle->free_connections, c->data,
c);
} while (unlikely(success == 0));
ngx_memory_barrier();
#else
ngx_cycle->free_connections = c;
#endif
ngx_cycle->free_connection_n++;
if (ngx_cycle->files && ngx_cycle->files[c->fd] == c) {
@ -1129,7 +1221,11 @@ ngx_close_connection(ngx_connection_t *c)
}
if (!c->shared) {
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.del_conn) {
#else
if (ngx_del_conn) {
#endif
ngx_del_conn(c, NGX_CLOSE_EVENT);
} else {

View File

@ -87,6 +87,9 @@ struct ngx_listening_s {
int fastopen;
#endif
#if (NGX_HAVE_FSTACK)
unsigned belong_to_host:1;
#endif
};

View File

@ -609,11 +609,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
}
#if (!NGX_HAVE_FSTACK)
if (ngx_open_listening_sockets(cycle) != NGX_OK) {
goto failed;
}
#endif
if (!ngx_test_config) {
ngx_configure_listening_sockets(cycle);

View File

@ -4512,7 +4512,11 @@ ngx_tcp_connect(ngx_resolver_connection_t *rec)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.add_conn) {
#else
if (ngx_add_conn) {
#endif
if (ngx_add_conn(c) == NGX_ERROR) {
goto failed;
}
@ -4564,7 +4568,11 @@ ngx_tcp_connect(ngx_resolver_connection_t *rec)
}
}
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.add_conn) {
#else
if (ngx_add_conn) {
#endif
if (rc == -1) {
/* NGX_EINPROGRESS */

View File

@ -33,10 +33,12 @@
#include <pthread.h>
#if (NGX_HAVE_FSTACK)
static void * ngx_ff_channel_create_conf(ngx_cycle_t *cycle);
static char * ngx_ff_channel_init_conf(ngx_cycle_t *cycle,
static void * ngx_ff_host_event_create_conf(ngx_cycle_t *cycle);
static char * ngx_ff_host_event_init_conf(ngx_cycle_t *cycle,
void *conf);
static ngx_int_t ngx_ff_epoll_init(ngx_cycle_t *cycle);
static ngx_int_t ngx_ff_host_event_init_process(ngx_cycle_t *cycle);
static void ngx_ff_host_event_exit_process(ngx_cycle_t *cycle);
static ngx_int_t ngx_ff_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
static ngx_int_t ngx_ff_epoll_add_event(ngx_event_t *ev,
ngx_int_t event, ngx_uint_t flags);
static ngx_int_t ngx_ff_epoll_del_event(ngx_event_t *ev,
@ -46,14 +48,19 @@ static ngx_int_t ngx_ff_epoll_process_events(ngx_cycle_t *cycle,
static ngx_int_t ngx_ff_create_connection(ngx_cycle_t *cycle);
static void ngx_ff_delete_connection();
static void ngx_ff_worker_channel_handler(ngx_event_t *ev);
static void *ngx_ff_channel_thread_main(void *args);
static void *ngx_ff_host_event_thread_main(void *args);
static ngx_int_t ngx_ff_add_channel_event(ngx_cycle_t *cycle,
ngx_fd_t fd, ngx_int_t event, ngx_event_handler_pt handler);
static ngx_int_t ngx_ff_process_channel_events(ngx_cycle_t *cycle);
static void ngx_ff_process_events_and_timers(ngx_cycle_t *cycle);
ngx_int_t ngx_ff_start_worker_channel(ngx_cycle_t *cycle,
ngx_fd_t fd, ngx_int_t event);
void ngx_event_cancel_timers_of_host(void);
void ngx_event_expire_timers_of_host(void);
ngx_msec_t ngx_event_find_timer_of_host(void);
void ngx_event_cancel_timers_of_host(void);
struct channel_thread_args {
ngx_cycle_t *cycle;
ngx_fd_t fd;
@ -69,41 +76,44 @@ static struct epoll_event *event_list;
static ngx_uint_t nevents;
static ngx_connection_t *channel_connection;
#include <semaphore.h>
static sem_t sem;
typedef struct {
ngx_uint_t events;
} ngx_ff_channel_conf_t;
} ngx_ff_host_event_conf_t;
static ngx_command_t ngx_ff_channel_commands[] = {
static ngx_command_t ngx_ff_host_event_commands[] = {
ngx_null_command
};
ngx_core_module_t ngx_ff_channel_module_ctx = {
ngx_string("ff_channel"),
ngx_ff_channel_create_conf, /* create configuration */
ngx_ff_channel_init_conf, /* init configuration */
ngx_core_module_t ngx_ff_host_event_module_ctx = {
ngx_string("ff_host_event"),
ngx_ff_host_event_create_conf, /* create configuration */
ngx_ff_host_event_init_conf, /* init configuration */
};
ngx_module_t ngx_ff_channel_module = {
ngx_module_t ngx_ff_host_event_module = {
NGX_MODULE_V1,
&ngx_ff_channel_module_ctx, /* module context */
ngx_ff_channel_commands, /* module directives */
&ngx_ff_host_event_module_ctx, /* module context */
ngx_ff_host_event_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_ff_epoll_init, /* init process */
ngx_ff_host_event_init_process, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
ngx_ff_host_event_exit_process, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_ff_channel_create_conf(ngx_cycle_t *cycle)
ngx_ff_host_event_create_conf(ngx_cycle_t *cycle)
{
ngx_ff_channel_conf_t *cf;
cf = ngx_palloc(cycle->pool, sizeof(ngx_ff_channel_conf_t));
ngx_ff_host_event_conf_t *cf;
cf = ngx_palloc(cycle->pool, sizeof(ngx_ff_host_event_conf_t));
if (cf == NULL) {
return NULL;
}
@ -112,15 +122,40 @@ ngx_ff_channel_create_conf(ngx_cycle_t *cycle)
}
static char *
ngx_ff_channel_init_conf(ngx_cycle_t *cycle, void *conf)
ngx_ff_host_event_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_ff_channel_conf_t *cf = conf;
ngx_ff_host_event_conf_t *cf = conf;
cf->events = 1;
return NGX_CONF_OK;
}
static ngx_int_t ngx_ff_host_event_init_process(ngx_cycle_t *cycle)
{
if (sem_init(&sem, 0, 0) != 0)
{
return NGX_ERROR;
}
return NGX_OK;
}
static void ngx_ff_host_event_exit_process(ngx_cycle_t *cycle)
{
struct timespec ts;
if (clock_gettime( CLOCK_REALTIME,&ts ) < 0)
return;
//5s
ts.tv_sec += 4;
(void) sem_timedwait(&sem, &ts);
}
static ngx_int_t
ngx_ff_epoll_init(ngx_cycle_t *cycle)
ngx_ff_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
if (ep == -1) {
ep = epoll_create(1);
@ -413,6 +448,7 @@ ngx_ff_epoll_process_events(ngx_cycle_t *cycle,
if ((revents & EPOLLIN) && rev->active) {
rev->ready = 1;
rev->available = 1;
rev->handler(rev);
}
@ -531,6 +567,8 @@ ngx_ff_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd,
rev->channel = 1;
wev->channel = 1;
rev->belong_to_host = wev->belong_to_host = 1;
ev = (event == NGX_READ_EVENT) ? rev : wev;
ev->handler = handler;
@ -623,7 +661,7 @@ ngx_ff_worker_channel_handler(ngx_event_t *ev)
}
static void *
ngx_ff_channel_thread_main(void *args)
ngx_ff_host_event_thread_main(void *args)
{
struct channel_thread_args *cta = args;
ngx_cycle_t *cycle = cta->cycle;
@ -634,21 +672,48 @@ ngx_ff_channel_thread_main(void *args)
}
for (;;) {
ngx_ff_process_channel_events(cycle);
ngx_ff_process_events_and_timers(cycle);
if (thread_quit) {
break;
}
}
ngx_event_cancel_timers_of_host();
ngx_free(cta);
return NULL;
}
static ngx_int_t
ngx_ff_process_channel_events(ngx_cycle_t *cycle)
static void
ngx_ff_process_events_and_timers(ngx_cycle_t *cycle)
{
return ngx_ff_epoll_process_events(cycle, 500, NGX_UPDATE_TIME);
ngx_uint_t flags;
ngx_msec_t timer, delta;
timer = ngx_event_find_timer_of_host();
flags = NGX_UPDATE_TIME;
/* handle signals from master in case of network inactivity */
if (timer == NGX_TIMER_INFINITE || timer > 500) {
timer = 500;
}
delta = ngx_current_msec;
(void) ngx_ff_epoll_process_events(cycle, timer, flags);
delta = ngx_current_msec - delta;
ngx_event_process_posted(cycle, &ngx_posted_accept_events_of_host);
if (delta) {
ngx_event_expire_timers_of_host();
}
ngx_event_process_posted(cycle, &ngx_posted_events_of_host);
}
ngx_int_t
@ -669,7 +734,7 @@ ngx_ff_start_worker_channel(ngx_cycle_t *cycle, ngx_fd_t fd,
cta->handler = ngx_ff_worker_channel_handler;
ret = pthread_create(&channel_thread, NULL,
ngx_ff_channel_thread_main, (void *)cta);
ngx_ff_host_event_thread_main, (void *)cta);
if (ret != 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"pthread_create() failed");
@ -681,4 +746,17 @@ ngx_ff_start_worker_channel(ngx_cycle_t *cycle, ngx_fd_t fd,
return NGX_OK;
}
ngx_event_actions_t ngx_ff_host_event_actions = {
ngx_ff_epoll_add_event, /* add an event */
ngx_ff_epoll_del_event, /* delete an event */
ngx_ff_epoll_add_event, /* enable an event */
ngx_ff_epoll_add_event, /* disable an event */
NULL, /* add an connection */
NULL, /* delete an connection */
NULL, /* trigger a notify */
ngx_ff_epoll_process_events, /* process the events */
ngx_ff_epoll_init, /* init the events */
NULL, /* done the events */
};
#endif

View File

@ -129,6 +129,35 @@ static int inited;
real_##func; \
})
extern intptr_t ngx_max_sockets;
/*-
* Make sockfd assigned by the fstack plus the value of maximum kernel socket.
* so we can tell them apart according to different scopes.
* Solve the condominium ownership at Application Layer and obtain more freedom.
* fstack tried to do this by 'fd_reserve', unfortunately, it doesn't work well.
*/
static inline int convert_fstack_fd(int sockfd) {
return sockfd + ngx_max_sockets;
}
/* Restore socket fd. */
static inline int restore_fstack_fd(int sockfd) {
if(sockfd <= ngx_max_sockets) {
return sockfd;
}
return sockfd - ngx_max_sockets;
}
/* Tell whether a 'sockfd' belongs to fstack. */
static inline int is_fstack_fd(int sockfd) {
if (unlikely(inited == 0)) {
return 0;
}
return sockfd >= ngx_max_sockets;
}
// proc_type, 1: primary, 0: secondary.
int
@ -151,8 +180,17 @@ ff_mod_init(const char *conf, int proc_id, int proc_type) {
}
rc = ff_init(ff_argc, ff_argv);
if (rc == 0)
if (rc == 0) {
/* Ensure that the socket we converted
does not exceed the maximum value of 'int' */
if(ngx_max_sockets + (unsigned)ff_getmaxfd() > INT_MAX)
{
rc = -1;
}
inited = 1;
}
for (i = 0; i < ff_argc; i++) {
free(ff_argv[i]);
@ -163,9 +201,23 @@ ff_mod_init(const char *conf, int proc_id, int proc_type) {
return rc;
}
/*-
* Verify whether the socket is supported by fstack or not.
*/
int
fstack_territory(int domain, int type, int protocol)
{
if ((AF_INET != domain) || (SOCK_STREAM != type && SOCK_DGRAM != type)) {
return 0;
}
return 1;
}
int
socket(int domain, int type, int protocol)
{
int sock;
if (unlikely(inited == 0)) {
return SYSCALL(socket)(domain, type, protocol);
}
@ -174,249 +226,216 @@ socket(int domain, int type, int protocol)
return SYSCALL(socket)(domain, type, protocol);
}
return ff_socket(domain, type, protocol);
sock = ff_socket(domain, type, protocol);
if (sock != -1) {
sock = convert_fstack_fd(sock);
}
return sock;
}
int
bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
if (unlikely(inited == 0)) {
return SYSCALL(bind)(sockfd, addr, addrlen);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_bind(sockfd, (struct linux_sockaddr *)addr, addrlen);
}
if (ff_fdisused(sockfd)) {
return ff_bind(sockfd, (struct linux_sockaddr *)addr, addrlen);
} else {
return SYSCALL(bind)(sockfd, addr, addrlen);
}
}
int
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
if (unlikely(inited == 0)) {
return SYSCALL(connect)(sockfd, addr, addrlen);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_connect(sockfd, (struct linux_sockaddr *)addr, addrlen);
}
if (ff_fdisused(sockfd)) {
return ff_connect(sockfd, (struct linux_sockaddr *)addr, addrlen);
} else {
return SYSCALL(connect)(sockfd, addr, addrlen);
}
}
ssize_t
send(int sockfd, const void *buf, size_t len, int flags)
{
if (unlikely(inited == 0)) {
return SYSCALL(send)(sockfd, buf, len, flags);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_send(sockfd, buf, len, flags);
}
if (ff_fdisused(sockfd)) {
return ff_send(sockfd, buf, len, flags);
} else {
return SYSCALL(send)(sockfd, buf, len, flags);
}
}
ssize_t
sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
if (unlikely(inited == 0)) {
return SYSCALL(sendto)(sockfd, buf, len, flags, dest_addr, addrlen);
}
if (ff_fdisused(sockfd)) {
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_sendto(sockfd, buf, len, flags,
(struct linux_sockaddr *)dest_addr, addrlen);
} else {
return SYSCALL(sendto)(sockfd, buf, len, flags, dest_addr, addrlen);
}
return SYSCALL(sendto)(sockfd, buf, len, flags, dest_addr, addrlen);
}
ssize_t
sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
if (unlikely(inited == 0)) {
return SYSCALL(sendmsg)(sockfd, msg, flags);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_sendmsg(sockfd, msg, flags);
}
if (ff_fdisused(sockfd)) {
return ff_sendmsg(sockfd, msg, flags);
} else {
return SYSCALL(sendmsg)(sockfd, msg, flags);
}
}
ssize_t
recv(int sockfd, void *buf, size_t len, int flags)
{
if (unlikely(inited == 0)) {
return SYSCALL(recv)(sockfd, buf, len, flags);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_recv(sockfd, buf, len, flags);
}
if (ff_fdisused(sockfd)) {
return ff_recv(sockfd, buf, len, flags);
} else {
return SYSCALL(recv)(sockfd, buf, len, flags);
}
}
int
listen(int sockfd, int backlog)
{
if (unlikely(inited == 0)) {
return SYSCALL(listen)(sockfd, backlog);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_listen(sockfd, backlog);
}
if (ff_fdisused(sockfd)) {
return ff_listen(sockfd, backlog);
} else {
return SYSCALL(listen)(sockfd, backlog);
}
}
int
getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen)
{
if (unlikely(inited == 0)) {
return SYSCALL(getsockopt)(sockfd, level, optname, optval, optlen);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_getsockopt(sockfd, level, optname, optval, optlen);
}
if (ff_fdisused(sockfd)) {
return ff_getsockopt(sockfd, level, optname, optval, optlen);
} else {
return SYSCALL(getsockopt)(sockfd, level, optname, optval, optlen);
}
}
int
setsockopt (int sockfd, int level, int optname,
const void *optval, socklen_t optlen)
{
if (unlikely(inited == 0)) {
return SYSCALL(setsockopt)(sockfd, level, optname, optval, optlen);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_setsockopt(sockfd, level, optname, optval, optlen);
}
if (ff_fdisused(sockfd)) {
return ff_setsockopt(sockfd, level, optname, optval, optlen);
} else {
return SYSCALL(setsockopt)(sockfd, level, optname, optval, optlen);
}
}
int
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
if (unlikely(inited == 0)) {
return SYSCALL(accept)(sockfd, addr, addrlen);
int rc;
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
rc = ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
if (rc != -1) {
rc = convert_fstack_fd(rc);
}
if (ff_fdisused(sockfd)) {
return ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
} else {
return SYSCALL(accept)(sockfd, addr, addrlen);
return rc;
}
return SYSCALL(accept)(sockfd, addr, addrlen);
}
int
accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
{
if (unlikely(inited == 0)) {
return SYSCALL(accept4)(sockfd, addr, addrlen, flags);
int rc;
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
rc = ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
if (rc != -1) {
rc = convert_fstack_fd(rc);
}
if (ff_fdisused(sockfd)) {
return ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
} else {
return SYSCALL(accept4)(sockfd, addr, addrlen, flags);
return rc;
}
return SYSCALL(accept4)(sockfd, addr, addrlen, flags);
}
int
close(int sockfd)
{
if (unlikely(inited == 0)) {
return SYSCALL(close)(sockfd);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_close(sockfd);
}
if (ff_fdisused(sockfd)) {
return ff_close(sockfd);
} else {
return SYSCALL(close)(sockfd);
}
}
ssize_t
writev(int sockfd, const struct iovec *iov, int iovcnt)
{
if (unlikely(inited == 0)) {
return SYSCALL(writev)(sockfd, iov, iovcnt);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_writev(sockfd, iov, iovcnt);
}
if (ff_fdisused(sockfd)) {
return ff_writev(sockfd, iov, iovcnt);
} else {
return SYSCALL(writev)(sockfd, iov, iovcnt);
}
}
ssize_t
readv(int sockfd, const struct iovec *iov, int iovcnt)
{
if (unlikely(inited == 0)) {
return SYSCALL(readv)(sockfd, iov, iovcnt);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_readv(sockfd, iov, iovcnt);
}
if (ff_fdisused(sockfd)) {
return ff_readv(sockfd, iov, iovcnt);
} else {
return SYSCALL(readv)(sockfd, iov, iovcnt);
}
}
ssize_t
read(int sockfd, void *buf, size_t count)
{
if (unlikely(inited == 0)) {
return SYSCALL(read)(sockfd, buf, count);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_read(sockfd, buf, count);
}
if (ff_fdisused(sockfd)) {
return ff_read(sockfd, buf, count);
} else {
return SYSCALL(read)(sockfd, buf, count);
}
}
ssize_t
write(int sockfd, const void *buf, size_t count)
{
if (unlikely(inited == 0)) {
return SYSCALL(write)(sockfd, buf, count);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_write(sockfd, buf, count);
}
if (ff_fdisused(sockfd)) {
return ff_write(sockfd, buf, count);
} else {
return SYSCALL(write)(sockfd, buf, count);
}
}
int
ioctl(int sockfd, int request, void *p)
{
if (unlikely(inited == 0)) {
return SYSCALL(ioctl)(sockfd, request, p);
if(is_fstack_fd(sockfd)){
sockfd = restore_fstack_fd(sockfd);
return ff_ioctl(sockfd, request, p);
}
if (ff_fdisused(sockfd)) {
return ff_ioctl(sockfd, request, p);
} else {
return SYSCALL(ioctl)(sockfd, request, p);
}
}
int
@ -429,6 +448,26 @@ int
kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout)
{
struct kevent *kev;
int i = 0;
for(i = 0; i < nchanges; i++) {
kev = (struct kevent *)&changelist[i];
switch (kev->filter) {
case EVFILT_READ:
case EVFILT_WRITE:
case EVFILT_VNODE:
kev->ident = restore_fstack_fd(kev->ident);
break;
case EVFILT_AIO:
case EVFILT_PROC:
case EVFILT_SIGNAL:
case EVFILT_TIMER:
case EVFILT_USER:
default:
break;
}
}
return ff_kevent(kq, changelist, nchanges, eventlist, nevents, timeout);
}
@ -441,4 +480,3 @@ gettimeofday(struct timeval *tv, struct timezone *tz)
return ff_gettimeofday(tv, tz);
}

View File

@ -564,6 +564,11 @@ ngx_timer_signal_handler(int signo)
#endif
#if (NGX_HAVE_FSTACK)
extern ngx_event_actions_t ngx_ff_host_event_actions;
#endif
static ngx_int_t
ngx_event_process_init(ngx_cycle_t *cycle)
@ -602,6 +607,11 @@ ngx_event_process_init(ngx_cycle_t *cycle)
ngx_queue_init(&ngx_posted_accept_events);
ngx_queue_init(&ngx_posted_events);
#if (NGX_HAVE_FSTACK)
ngx_queue_init(&ngx_posted_accept_events_of_host);
ngx_queue_init(&ngx_posted_events_of_host);
#endif
if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
return NGX_ERROR;
}
@ -625,6 +635,13 @@ ngx_event_process_init(ngx_cycle_t *cycle)
break;
}
#if (NGX_HAVE_FSTACK)
if (ngx_ff_host_event_actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
/* fatal */
exit(2);
}
#endif
#if !(NGX_WIN32)
if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
@ -663,8 +680,14 @@ ngx_event_process_init(ngx_cycle_t *cycle)
cycle->files_n = (ngx_uint_t) rlmt.rlim_cur;
#if (NGX_HAVE_FSTACK)
cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n * 2,
cycle->log);
#else
cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n,
cycle->log);
#endif
if (cycle->files == NULL) {
return NGX_ERROR;
}
@ -757,6 +780,12 @@ ngx_event_process_init(ngx_cycle_t *cycle)
rev->log = c->log;
rev->accept = 1;
#if (NGX_HAVE_FSTACK)
/* Note when nginx running on fstack,
make sure that add the right fd to kqueue !! */
c->read->belong_to_host = c->write->belong_to_host = ls[i].belong_to_host;
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT)
rev->deferred_accept = ls[i].deferred_accept;
#endif

View File

@ -142,6 +142,10 @@ struct ngx_event_s {
uint32_t padding[NGX_EVENT_T_PADDING];
#endif
#endif
#if (NGX_HAVE_FSTACK)
unsigned belong_to_host:1;
#endif
};
@ -198,7 +202,9 @@ extern ngx_event_actions_t ngx_event_actions;
#if (NGX_HAVE_EPOLLRDHUP)
extern ngx_uint_t ngx_use_epoll_rdhup;
#endif
#if (NGX_HAVE_FSTACK)
extern ngx_event_actions_t ngx_ff_host_event_actions;
#endif
/*
* The event filter requires to read/write the whole data:
@ -407,6 +413,47 @@ extern ngx_uint_t ngx_use_epoll_rdhup;
#define NGX_CLEAR_EVENT 0 /* dummy declaration */
#endif
#if (NGX_HAVE_FSTACK)
static inline ngx_int_t
ngx_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) {
if (1 == ev->belong_to_host) {
return ngx_ff_host_event_actions.add(ev, event, flags);
} else {
return ngx_event_actions.add(ev, event, flags);
}
}
static inline ngx_int_t
ngx_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) {
if (1 == ev->belong_to_host) {
return ngx_ff_host_event_actions.del(ev, event, flags);
} else {
return ngx_event_actions.del(ev, event, flags);
}
}
static inline ngx_int_t ngx_add_conn(ngx_connection_t *c)
{
return ngx_event_actions.add_conn(c);
}
static inline ngx_int_t ngx_del_conn(
ngx_connection_t *c, ngx_uint_t flags) {
return ngx_event_actions.del_conn(c, flags);
}
static inline ngx_int_t ngx_notify(ngx_event_handler_pt handler) {
return ngx_event_actions.notify(handler);
}
static inline ngx_int_t ngx_process_events(
ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
return ngx_event_actions.process_events(cycle, timer, flags);
}
#else
#define ngx_process_events ngx_event_actions.process_events
#define ngx_done_events ngx_event_actions.done
@ -418,6 +465,8 @@ extern ngx_uint_t ngx_use_epoll_rdhup;
#define ngx_notify ngx_event_actions.notify
#endif
#define ngx_add_timer ngx_event_add_timer
#define ngx_del_timer ngx_event_del_timer

View File

@ -230,6 +230,10 @@ ngx_event_accept(ngx_event_t *ev)
rev = c->read;
wev = c->write;
#if (NGX_HAVE_FSTACK)
rev->belong_to_host = wev->belong_to_host = ev->belong_to_host;
#endif
wev->ready = 1;
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
@ -296,7 +300,11 @@ ngx_event_accept(ngx_event_t *ev)
}
#endif
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
#else
if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
#endif
if (ngx_add_conn(c) == NGX_ERROR) {
ngx_close_accepted_connection(c);
return;
@ -432,6 +440,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
- ngx_cycle->free_connection_n;
c = ngx_get_connection(lc->fd, ev->log);
if (c == NULL) {
return;
}

View File

@ -181,7 +181,11 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.add_conn) {
#else
if (ngx_add_conn) {
#endif
if (ngx_add_conn(c) == NGX_ERROR) {
goto failed;
}
@ -233,7 +237,11 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
}
}
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.add_conn) {
#else
if (ngx_add_conn) {
#endif
if (rc == -1) {
/* NGX_EINPROGRESS */

View File

@ -13,6 +13,11 @@
ngx_queue_t ngx_posted_accept_events;
ngx_queue_t ngx_posted_events;
#if (NGX_HAVE_FSTACK)
ngx_queue_t ngx_posted_accept_events_of_host;
ngx_queue_t ngx_posted_events_of_host;
#endif
void
ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted)

View File

@ -14,6 +14,34 @@
#include <ngx_event.h>
#if (NGX_HAVE_FSTACK)
#define ngx_post_event(ev, q) \
\
if (!(ev)->posted) { \
(ev)->posted = 1; \
if (1 == (ev)->belong_to_host) { \
if (q == &ngx_posted_events) { \
ngx_queue_insert_tail( \
&ngx_posted_events_of_host, &(ev)->queue); \
} else if (q == &ngx_posted_accept_events) { \
ngx_queue_insert_tail( \
&ngx_posted_accept_events_of_host, &(ev)->queue); \
} else { \
ngx_log_error(NGX_LOG_EMERG, (ev)->log, 0, \
"ngx_post_event: unkowned posted queue"); \
exit(1); \
} \
} else { \
ngx_queue_insert_tail(q, &(ev)->queue); \
} \
\
ngx_log_debug1(NGX_LOG_DEBUG_CORE, (ev)->log, 0, "post event %p", ev);\
\
} else { \
ngx_log_debug1(NGX_LOG_DEBUG_CORE, (ev)->log, 0, \
"update posted event %p", ev); \
}
#else
#define ngx_post_event(ev, q) \
\
if (!(ev)->posted) { \
@ -26,6 +54,7 @@
ngx_log_debug1(NGX_LOG_DEBUG_CORE, (ev)->log, 0, \
"update posted event %p", ev); \
}
#endif
#define ngx_delete_posted_event(ev) \
@ -44,5 +73,9 @@ void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted);
extern ngx_queue_t ngx_posted_accept_events;
extern ngx_queue_t ngx_posted_events;
#if (NGX_HAVE_FSTACK)
extern ngx_queue_t ngx_posted_accept_events_of_host;
extern ngx_queue_t ngx_posted_events_of_host;
#endif
#endif /* _NGX_EVENT_POSTED_H_INCLUDED_ */

View File

@ -13,6 +13,11 @@
ngx_rbtree_t ngx_event_timer_rbtree;
static ngx_rbtree_node_t ngx_event_timer_sentinel;
#if (NGX_HAVE_FSTACK)
ngx_rbtree_t ngx_event_timer_rbtree_of_host;
static ngx_rbtree_node_t ngx_event_timer_sentinel_of_host;
#endif
/*
* the event timer rbtree may contain the duplicate keys, however,
* it should not be a problem, because we use the rbtree to find
@ -25,22 +30,54 @@ ngx_event_timer_init(ngx_log_t *log)
ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
ngx_rbtree_insert_timer_value);
#if (NGX_HAVE_FSTACK)
ngx_rbtree_init(&ngx_event_timer_rbtree_of_host, &ngx_event_timer_sentinel_of_host,
ngx_rbtree_insert_timer_value);
#endif
return NGX_OK;
}
#if (NGX_HAVE_FSTACK)
ngx_msec_t
ngx_event_find_timer_internal(
ngx_rbtree_t *rbtree, ngx_rbtree_node_t *sentinel);
ngx_msec_t
ngx_event_find_timer(void)
{
return ngx_event_find_timer_internal(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel);
}
ngx_msec_t
ngx_event_find_timer_of_host(void)
{
return ngx_event_find_timer_internal(&ngx_event_timer_rbtree_of_host, &ngx_event_timer_sentinel_of_host);
}
ngx_msec_t
ngx_event_find_timer_internal(
ngx_rbtree_t *rbtree, ngx_rbtree_node_t *rbtree_sentinel)
{
#else
ngx_msec_t
ngx_event_find_timer(void)
{
ngx_rbtree_t * rbtree = &ngx_event_timer_rbtree;
ngx_rbtree_node_t *rbtree_sentinel = &ngx_event_timer_sentinel;
#endif
ngx_msec_int_t timer;
ngx_rbtree_node_t *node, *root, *sentinel;
if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {
if (rbtree->root == rbtree_sentinel) {
return NGX_TIMER_INFINITE;
}
root = ngx_event_timer_rbtree.root;
sentinel = ngx_event_timer_rbtree.sentinel;
root = rbtree->root;
sentinel = rbtree->sentinel;
node = ngx_rbtree_min(root, sentinel);
@ -50,16 +87,39 @@ ngx_event_find_timer(void)
}
#if (NGX_HAVE_FSTACK)
void
ngx_event_expire_timers_internal(ngx_rbtree_t *rbtree);
void
ngx_event_expire_timers(void)
{
ngx_event_expire_timers_internal(&ngx_event_timer_rbtree);
}
void
ngx_event_expire_timers_of_host(void)
{
ngx_event_expire_timers_internal(&ngx_event_timer_rbtree_of_host);
}
void
ngx_event_expire_timers_internal(ngx_rbtree_t *rbtree)
{
#else
void
ngx_event_expire_timers(void)
{
ngx_rbtree_t * rbtree = &ngx_event_timer_rbtree;
#endif
ngx_event_t *ev;
ngx_rbtree_node_t *node, *root, *sentinel;
sentinel = ngx_event_timer_rbtree.sentinel;
sentinel = rbtree->sentinel;
for ( ;; ) {
root = ngx_event_timer_rbtree.root;
root = rbtree->root;
if (root == sentinel) {
return;
@ -79,7 +139,7 @@ ngx_event_expire_timers(void)
"event timer del: %d: %M",
ngx_event_ident(ev->data), ev->timer.key);
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
ngx_rbtree_delete(rbtree, &ev->timer);
#if (NGX_DEBUG)
ev->timer.left = NULL;
@ -96,16 +156,39 @@ ngx_event_expire_timers(void)
}
#if (NGX_HAVE_FSTACK)
void
ngx_event_cancel_timers_internal(ngx_rbtree_t *rbtree);
void
ngx_event_cancel_timers(void)
{
ngx_event_cancel_timers_internal(&ngx_event_timer_rbtree);
}
void
ngx_event_cancel_timers_of_host(void)
{
ngx_event_cancel_timers_internal(&ngx_event_timer_rbtree_of_host);
}
void
ngx_event_cancel_timers_internal(ngx_rbtree_t *rbtree)
{
#else
void
ngx_event_cancel_timers(void)
{
ngx_rbtree_t * rbtree = &ngx_event_timer_rbtree;
#endif
ngx_event_t *ev;
ngx_rbtree_node_t *node, *root, *sentinel;
sentinel = ngx_event_timer_rbtree.sentinel;
sentinel = rbtree->sentinel;
for ( ;; ) {
root = ngx_event_timer_rbtree.root;
root = rbtree->root;
if (root == sentinel) {
return;
@ -123,7 +206,7 @@ ngx_event_cancel_timers(void)
"event timer cancel: %d: %M",
ngx_event_ident(ev->data), ev->timer.key);
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
ngx_rbtree_delete(rbtree, &ev->timer);
#if (NGX_DEBUG)
ev->timer.left = NULL;

View File

@ -27,6 +27,9 @@ void ngx_event_cancel_timers(void);
extern ngx_rbtree_t ngx_event_timer_rbtree;
#if (NGX_HAVE_FSTACK)
extern ngx_rbtree_t ngx_event_timer_rbtree_of_host;
#endif
static ngx_inline void
ngx_event_del_timer(ngx_event_t *ev)
@ -35,7 +38,19 @@ ngx_event_del_timer(ngx_event_t *ev)
"event timer del: %d: %M",
ngx_event_ident(ev->data), ev->timer.key);
#if (NGX_HAVE_FSTACK)
if(ev->belong_to_host){
ngx_rbtree_delete(&ngx_event_timer_rbtree_of_host, &ev->timer);
} else {
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
}
#else
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
#endif
#if (NGX_DEBUG)
ev->timer.left = NULL;
@ -81,7 +96,19 @@ ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
"event timer add: %d: %M:%M",
ngx_event_ident(ev->data), timer, ev->timer.key);
#if (NGX_HAVE_FSTACK)
if(ev->belong_to_host){
ngx_rbtree_insert(&ngx_event_timer_rbtree_of_host, &ev->timer);
} else {
ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev->timer);
}
#else
ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev->timer);
#endif
ev->timer_set = 1;
}

View File

@ -1775,6 +1775,10 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
ls->reuseport = addr->opt.reuseport;
#endif
#if (NGX_HAVE_FSTACK)
ls->belong_to_host = cscf->kernel_network_stack;
#endif
return ls;
}

View File

@ -293,6 +293,17 @@ static ngx_command_t ngx_http_core_commands[] = {
0,
NULL },
#if (NGX_HAVE_FSTACK)
{ ngx_string("kernel_network_stack"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_core_srv_conf_t, kernel_network_stack),
NULL },
#endif
{ ngx_string("types_hash_max_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
@ -3444,6 +3455,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
cscf->merge_slashes = NGX_CONF_UNSET;
cscf->underscores_in_headers = NGX_CONF_UNSET;
cscf->kernel_network_stack = NGX_CONF_UNSET;
return cscf;
}
@ -3487,6 +3499,12 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->underscores_in_headers,
prev->underscores_in_headers, 0);
#if (NGX_HAVE_FSTACK)
/* By default, we set up a server on fstack */
ngx_conf_merge_value(conf->kernel_network_stack,
prev->kernel_network_stack, 0);
#endif
if (conf->server_names.nelts == 0) {
/* the array has 4 empty preallocated elements, so push cannot fail */
sn = ngx_array_push(&conf->server_names);

View File

@ -199,6 +199,10 @@ typedef struct {
ngx_flag_t merge_slashes;
ngx_flag_t underscores_in_headers;
#if (NGX_HAVE_FSTACK)
ngx_flag_t kernel_network_stack; /* kernel_network_stack */
#endif
unsigned listen:1;
#if (NGX_PCRE)
unsigned captures:1;

View File

@ -345,6 +345,10 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
ls->ipv6only = addr[i].opt.ipv6only;
#endif
#if (NGX_HAVE_FSTACK)
ls->belong_to_host = cscf->kernel_network_stack;
#endif
mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t));
if (mport == NULL) {
return NGX_CONF_ERROR;

View File

@ -112,6 +112,10 @@ typedef struct {
ngx_str_t server_name;
#if (NGX_HAVE_FSTACK)
ngx_flag_t kernel_network_stack; /* kernel_network_stack */
#endif
u_char *file_name;
ngx_uint_t line;

View File

@ -64,6 +64,17 @@ static ngx_command_t ngx_mail_core_commands[] = {
offsetof(ngx_mail_core_srv_conf_t, server_name),
NULL },
#if (NGX_HAVE_FSTACK)
{ ngx_string("kernel_network_stack"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_core_srv_conf_t, kernel_network_stack),
NULL },
#endif
{ ngx_string("error_log"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
ngx_mail_core_error_log,
@ -167,6 +178,9 @@ ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
cscf->file_name = cf->conf_file->file.name.data;
cscf->line = cf->conf_file->line;
#if (NGX_HAVE_FSTACK)
cscf->kernel_network_stack = NGX_CONF_UNSET;
#endif
return cscf;
}
@ -206,6 +220,12 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
#if (NGX_HAVE_FSTACK)
/* By default, we set up a server on fstack */
ngx_conf_merge_value(conf->kernel_network_stack,
prev->kernel_network_stack, 0);
#endif
return NGX_CONF_OK;
}

View File

@ -223,7 +223,11 @@ ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event,
ev->handler = handler;
#if (NGX_HAVE_FSTACK)
if (ngx_event_actions.add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
#else
if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
#endif
if (ngx_add_conn(c) == NGX_ERROR) {
ngx_free_connection(c);
return NGX_ERROR;

View File

@ -737,9 +737,7 @@ ngx_master_process_exit(ngx_cycle_t *cycle)
}
}
#if (!NGX_HAVE_FSTACK)
ngx_close_listening_sockets(cycle);
#endif
/*
* Copy ngx_cycle->log related data to the special static exit cycle,

View File

@ -512,6 +512,10 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
ls->reuseport = addr[i].opt.reuseport;
#endif
#if (NGX_HAVE_FSTACK)
ls->belong_to_host = cscf->kernel_network_stack;
#endif
stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t));
if (stport == NULL) {
return NGX_CONF_ERROR;

View File

@ -185,6 +185,10 @@ typedef struct {
ngx_msec_t proxy_protocol_timeout;
#if (NGX_HAVE_FSTACK)
ngx_flag_t kernel_network_stack; /* kernel_network_stack */
#endif
ngx_uint_t listen; /* unsigned listen:1; */
} ngx_stream_core_srv_conf_t;

View File

@ -56,6 +56,17 @@ static ngx_command_t ngx_stream_core_commands[] = {
0,
NULL },
#if (NGX_HAVE_FSTACK)
{ ngx_string("kernel_network_stack"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_core_srv_conf_t, kernel_network_stack),
NULL },
#endif
{ ngx_string("error_log"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
ngx_stream_core_error_log,
@ -425,6 +436,9 @@ ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
cscf->tcp_nodelay = NGX_CONF_UNSET;
cscf->preread_buffer_size = NGX_CONF_UNSET_SIZE;
cscf->preread_timeout = NGX_CONF_UNSET_MSEC;
#if (NGX_HAVE_FSTACK)
cscf->kernel_network_stack = NGX_CONF_UNSET;
#endif
return cscf;
}
@ -483,6 +497,12 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->preread_timeout,
prev->preread_timeout, 30000);
#if (NGX_HAVE_FSTACK)
/* By default, we set up a server on fstack */
ngx_conf_merge_value(conf->kernel_network_stack,
prev->kernel_network_stack, 0);
#endif
return NGX_CONF_OK;
}

View File

@ -4134,5 +4134,13 @@ ff_fdused_range(int max)
fdalloc(td, 0, &result);
}
int
ff_getmaxfd(void)
{
struct thread *td = curthread;
return getmaxfd(td);
}
#endif

View File

@ -117,6 +117,7 @@ int ff_gettimeofday(struct timeval *tv, struct timezone *tz);
/* Tests if fd is used by F-Stack */
extern int ff_fdisused(int fd);
extern int ff_getmaxfd(void);
/* route api begin */
enum FF_ROUTE_CTL {

View File

@ -43,4 +43,5 @@ ff_route_ctl
ff_rtioctl
ff_gettimeofday
ff_fdisused
ff_getmaxfd
ff_ngctl

View File

@ -32,5 +32,6 @@
void ff_fdused_range(int max);
int ff_fdisused(int fd);
int ff_getmaxfd(void);
#endif /* _FSTACK_SYS_FILEDESC_H_ */