[PATCH 2 of 2] QUIC: input packet batching with recvmmsg()
# HG changeset patch # User Roman Arutyunyan # Date 1707486707 -28800 # Fri Feb 09 21:51:47 2024 +0800 # Node ID 4584ba4b1d65a90f69201cecf1f1e650c1cbd87b # Parent 5d28510b62bffba3187d7fe69baccd2d2da41a12 QUIC: input packet batching with recvmmsg(). diff --git a/auto/os/linux b/auto/os/linux --- a/auto/os/linux +++ b/auto/os/linux @@ -303,4 +303,15 @@ ngx_feature_test="struct mmsghdr msg[UIO . auto/feature +ngx_feature="recvmmsg()" +ngx_feature_name="NGX_HAVE_RECVMMSG" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="struct mmsghdr msg[64]; + recvmmsg(0, msg, 64, 0, NULL);" +. auto/feature + + CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -898,7 +898,11 @@ ngx_event_process_init(ngx_cycle_t *cycl #if (NGX_QUIC) } else if (ls[i].quic) { +#if (NGX_HAVE_RECVMMSG) +rev->handler = ngx_quic_recvmmsg; +#else rev->handler = ngx_quic_recvmsg; +#endif #if (NGX_HAVE_SENDMMSG) wev->handler = ngx_event_sendmmsg; diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h --- a/src/event/quic/ngx_event_quic.h +++ b/src/event/quic/ngx_event_quic.h @@ -112,6 +112,9 @@ struct ngx_quic_stream_s { void ngx_quic_recvmsg(ngx_event_t *ev); +#if (NGX_HAVE_RECVMMSG) +void ngx_quic_recvmmsg(ngx_event_t *ev); +#endif void ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf); ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi); void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, diff --git a/src/event/quic/ngx_event_quic_udp.c b/src/event/quic/ngx_event_quic_udp.c --- a/src/event/quic/ngx_event_quic_udp.c +++ b/src/event/quic/ngx_event_quic_udp.c @@ -11,6 +11,7 @@ #include +static void ngx_quic_handle_msg(ngx_event_t *ev, struct msghdr *msg, size_t n); static void ngx_quic_close_accepted_connection(ngx_connection_t *c); static ngx_connection_t *ngx_quic_lookup_connection(ngx_listening_t *ls, ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen); @@ -20,20 +21,13 @@ void ngx_quic_recvmsg(ngx_event_t *ev) { ssize_t n; -ngx_str_t key; -ngx_buf_t buf; -ngx_log_t *log; ngx_err_t err; -socklen_t socklen, local_socklen; -ngx_event_t*rev, *wev; struct ioveciov[1]; struct msghdr msg; -ngx_sockaddr_t sa, lsa; -struct sockaddr*sockaddr, *local_sockaddr; +ngx_sockaddr_t sa; ngx_listening_t*ls; ngx_event_conf_t *ecf; -ngx_connection_t *c, *lc; -ngx_quic_socket_t *qsock; +ngx_connection_t *lc; static u_char buffer[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; #if (NGX_HAVE_ADDRINFO_CMSG) @@ -106,239 +100,10 @@ ngx_quic_recvmsg(ngx_event_t *ev) } #endif -sockaddr = msg.msg_name; -socklen = msg.msg_namelen; - -if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { -socklen = sizeof(ngx_sockaddr_t); -} - -#if (NGX_HAVE_UNIX_DOMAIN) - -if (sockaddr->sa_family == AF_UNIX) { -struct sockaddr_un *saun = (struct sockaddr_un *) sockaddr; - -if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path) -|| saun->sun_path[0] == '\0') -{ -ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, - "unbound unix socket"); -goto next; -} -} - -#endif - -local_sockaddr = ls->sockaddr; -local_socklen = ls->socklen; - -#if (NGX_HAVE_ADDRINFO_CMSG) - -if (ls->wildcard) { -struct cmsghdr *cmsg; - -ngx_memcpy(&lsa, local_sockaddr, local_socklen); -local_sockaddr = &lsa.sockaddr; - -for (cmsg = CMSG_FIRSTHDR(&msg); - cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) -{ -if (ngx_get_srcaddr_cmsg(cmsg, local_sockaddr) == NGX_OK) { -break; -} -} -} - -#endif - -if (ngx_quic_get_packet_dcid(ev->log, buffer, n, &key) != NGX_OK) { -goto next; -} - -c = ngx_quic_lookup_connection(ls, &key, local_sockaddr, local_socklen); - -if (c) { - -#if (NGX_DEBUG) -if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { -ngx_log_handler_pt handler; - -handler = c->log->handler; -c->log->handler = NULL; - -ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic recvmsg: fd:%d n:%z", c->fd, n); - -c->log->handler = handler; -} -#endif - -ngx_memzero(&buf, sizeof(ngx_buf_t))
[PATCH 1 of 2] QUIC: output packet batching with sendmmsg()
# HG changeset patch # User Roman Arutyunyan # Date 1709833123 -28800 # Fri Mar 08 01:38:43 2024 +0800 # Node ID 5d28510b62bffba3187d7fe69baccd2d2da41a12 # Parent 2ed3f57dca0a664340bca2236c7d614902db4180 QUIC: output packet batching with sendmmsg(). diff --git a/auto/os/linux b/auto/os/linux --- a/auto/os/linux +++ b/auto/os/linux @@ -291,4 +291,16 @@ ngx_feature_test="socklen_t optlen = siz . auto/feature +ngx_feature="sendmmsg()" +ngx_feature_name="NGX_HAVE_SENDMMSG" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="struct mmsghdr msg[UIO_MAXIOV]; + sendmmsg(0, msg, UIO_MAXIOV, 0);" +. auto/feature + + CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -171,6 +171,7 @@ UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \ src/os/unix/ngx_writev_chain.c \ src/os/unix/ngx_udp_send.c \ src/os/unix/ngx_udp_sendmsg_chain.c \ +src/os/unix/ngx_udp_sendmmsg.c \ src/os/unix/ngx_channel.c \ src/os/unix/ngx_shmem.c \ src/os/unix/ngx_process.c \ diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -823,9 +823,11 @@ ngx_event_process_init(ngx_cycle_t *cycl ls[i].connection = c; rev = c->read; +wev = c->write; rev->log = c->log; rev->accept = 1; +wev->log = c->log; #if (NGX_HAVE_DEFERRED_ACCEPT) rev->deferred_accept = ls[i].deferred_accept; @@ -897,6 +899,14 @@ ngx_event_process_init(ngx_cycle_t *cycl #if (NGX_QUIC) } else if (ls[i].quic) { rev->handler = ngx_quic_recvmsg; +#if (NGX_HAVE_SENDMMSG) +wev->handler = ngx_event_sendmmsg; + +c->data = ngx_pcalloc(cycle->pool, sizeof(ngx_sendmmsg_batch_t)); +if (c->data == NULL) { +return NGX_ERROR; +} +#endif #endif } else { rev->handler = ngx_event_recvmsg; diff --git a/src/event/ngx_event_udp.h b/src/event/ngx_event_udp.h --- a/src/event/ngx_event_udp.h +++ b/src/event/ngx_event_udp.h @@ -22,6 +22,8 @@ #endif +#define NGX_SENDMMSG_BUFFER 4194304 /* 4M */ + struct ngx_udp_connection_s { ngx_rbtree_node_t node; @@ -47,6 +49,23 @@ typedef union { #endif } ngx_addrinfo_t; + +#if (NGX_HAVE_SENDMMSG) + +typedef struct { +u_charbuffer[NGX_SENDMMSG_BUFFER]; +struct mmsghdrmsgvec[UIO_MAXIOV]; +size_tsize; +ngx_uint_tvlen; +} ngx_sendmmsg_batch_t; + + +ssize_t ngx_sendmmsg(ngx_connection_t *c, struct msghdr *msg, int flags); +u_char *ngx_sendmmsg_buffer(ngx_connection_t *c, size_t size); +void ngx_event_sendmmsg(ngx_event_t *ev); + +#endif + size_t ngx_set_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr); ngx_int_t ngx_get_srcaddr_cmsg(struct cmsghdr *cmsg, diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -908,10 +908,12 @@ ngx_quic_expire_path_mtu_discovery(ngx_c static ngx_int_t ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path) { +void *bt; size_t mtu; uint64_tpnum; ngx_int_t rc; ngx_uint_t log_error; +ngx_connection_t *lc; ngx_quic_frame_t *frame; ngx_quic_send_ctx_t*ctx; ngx_quic_connection_t *qc; @@ -933,6 +935,10 @@ ngx_quic_send_path_mtu_probe(ngx_connect "mtu:%uz pnum:%uL tries:%ui", path->seqnum, path->mtud, ctx->pnum, path->tries); +lc = c->listening->connection; +bt = lc->data; +lc->data = NULL; + log_error = c->log_error; c->log_error = NGX_ERROR_IGNORE_EMSGSIZE; @@ -943,6 +949,7 @@ ngx_quic_send_path_mtu_probe(ngx_connect path->mtu = mtu; c->log_error = log_error; +lc->data = bt; if (rc == NGX_OK) { path->mtu_pnum[path->tries] = pnum; diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -61,6 +61,7 @@ static void ngx_quic_init_packet(ngx_con static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len, struct sockaddr *sockaddr, socklen_t socklen); +static u_char *ngx_quic_send_buffer(ngx_connection_t *c); static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx); @@ -114,14 +115,13 @@ ngx_quic_create_datagrams(ngx_connection { size_t len, min; ssize_t
[PATCH 0 of 2] QUIC packet batching on Linux
Hi, The patches add sendmmsg() and recvmmsg() to QUIC on Linux instead of sendmsg() and recvmsg(). This allows to do cross-connection batching of QUIC input and output and significantly reduce the number of syscalls. So far I haven't noticed any noticable performance improvements, but the testing is still ongoing. -- Roman Arutyunyan ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
Re: [PATCH] Core: free connections and read/write events at shutdown
> On 28 Feb 2024, at 05:21, Piotr Sikora via nginx-devel > wrote: > > # HG changeset patch > # User Piotr Sikora > # Date 1708977616 0 > # Mon Feb 26 20:00:16 2024 + > # Branch patch002 > # Node ID f8d9fb94eab212f6e640b7a68ed111562e3157d5 > # Parent a8a592b9b62eff7bca03e8b46669f59d2da689ed > Core: free connections and read/write events at shutdown. > > Found with LeakSanitizer. > > Signed-off-by: Piotr Sikora > > diff -r a8a592b9b62e -r f8d9fb94eab2 src/os/unix/ngx_process_cycle.c > --- a/src/os/unix/ngx_process_cycle.c Mon Feb 26 20:00:11 2024 + > +++ b/src/os/unix/ngx_process_cycle.c Mon Feb 26 20:00:16 2024 + > @@ -940,6 +940,7 @@ > ngx_worker_process_exit(ngx_cycle_t *cycle) > { > ngx_uint_t i; > +ngx_event_t *rev, *wev; > ngx_connection_t *c; > > for (i = 0; cycle->modules[i]; i++) { > @@ -989,8 +990,16 @@ > ngx_exit_cycle.files_n = ngx_cycle->files_n; > ngx_cycle = &ngx_exit_cycle; > > +c = cycle->connections; > +rev = cycle->read_events; > +wev = cycle->write_events; > + > ngx_destroy_pool(cycle->pool); > > +ngx_free(c); > +ngx_free(rev); > +ngx_free(wev); > + > ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit"); > > exit(0); Hello. Since this is not a real memory leak (the allocations made in the init_process method of the ngx_event_core_module module are used up to this function and already freed on exit automatically, as this function never returns), I don't think there is something to fix. (Further, the patch misses cycle->files for NGX_USE_FD_EVENT event methods. Also, it's probably better to free the memory in the exit_process method to obey the ownership (this would also fix missing ngx_free() calls on win32), but this would require moving code that uses these connections afterwards to catch socket leaks.) -- Sergey Kandaurov ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
Re: [PATCH] Configure: add support for Homebrew on Apple Silicon
On Wed, 6 Mar 2024 19:36:32 +0400 Sergey Kandaurov wrote: > > On 28 Feb 2024, at 05:24, Piotr Sikora via nginx-devel > > wrote: > > > > # HG changeset patch > > # User Piotr Sikora > > # Date 1708977643 0 > > # Mon Feb 26 20:00:43 2024 + > > # Branch patch017 > > # Node ID dd95daa55cf6131a7e845edd6ad3b429bcef6f98 > > # Parent bb99cbe3a343ae581d2369b990aee66e69679ca2 > > Configure: add support for Homebrew on Apple Silicon. > > > > > Signed-off-by: Piotr Sikora > > Well, this is weird to pick up install prefix depending on the device. > Hopefully, maintainers will rethink. Though given the relevant > issue #9177 on githab is over 3 years, they would rather not. > > An obvious question is why do you need this change. Homebrew seems > to be quite niche to pay attention. Using appropriate paths in > --with-cc-opt / --with-ld-opt should work (not tested). > If it really harms though, I think the change should go in. > > > > > diff -r bb99cbe3a343 -r dd95daa55cf6 auto/lib/geoip/conf > > --- a/auto/lib/geoip/conf Mon Feb 26 20:00:42 2024 + > > +++ b/auto/lib/geoip/conf Mon Feb 26 20:00:43 2024 + > > A quick grep for MacPorts search paths suggests that some libraries > are missing in the change. If this is on purpose, please reflect > this in the description. > > > @@ -64,6 +64,23 @@ > > fi > > > > > > +if [ $ngx_found = no ]; then > > + > > +# Homebrew on Apple Silicon > > Apple Silicon is something from the marketing language, > using Apple ARM instead should be fine. > > Notably, Homebrew uses Hardware::CPU.arm Ruby language boolean > to make the distinction. > > Further, given the smooth decay on Intel-based hardware, > I'd reduce this just to "Homebrew". > It might be worth it to keep at least 'Apple' distinction in there, if this will be added; Homebrew also supports Linux too, and installs to /home/linuxbrew/.linuxbrew as default prefix path... https://docs.brew.sh/Homebrew-on-Linux > [..] > ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel