[PATCH 2 of 2] QUIC: input packet batching with recvmmsg()

2024-03-07 Thread Roman Arutyunyan
# 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()

2024-03-07 Thread Roman Arutyunyan
# 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

2024-03-07 Thread Roman Arutyunyan
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

2024-03-07 Thread Sergey Kandaurov

> 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

2024-03-07 Thread J Carter
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