Welcome! Log In Create A New Profile

Advanced

Re: [PATCH 04 of 10] QUIC: reusable mode for main connection

Sergey Kandaurov
November 28, 2022 11:12AM
On Thu, Sep 08, 2022 at 01:06:31PM +0400, Roman Arutyunyan wrote:
> # HG changeset patch
> # User Roman Arutyunyan <arut@nginx.com>
> # Date 1662478181 -14400
> # Tue Sep 06 19:29:41 2022 +0400
> # Branch quic
> # Node ID 0a5de8e68cb8b238a1fb82da93ce583c0fa1a6a1
> # Parent b4662fc66f1e8388f54d988777b741964892cec2
> QUIC: reusable mode for main connection.
>
> The connection is automatically switched to this mode by transport layer when
> there are no non-cancelable streams. Currently, cancelable streams are
> HTTP/3 encoder/decoder/control streams.
>
> diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c
> --- a/src/event/quic/ngx_event_quic.c
> +++ b/src/event/quic/ngx_event_quic.c
> @@ -341,6 +341,8 @@ ngx_quic_new_connection(ngx_connection_t
> return NULL;
> }
>
> + ngx_reusable_connection(c, 1);
> +
> ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> "quic connection created");
>
> @@ -420,7 +422,7 @@ ngx_quic_input_handler(ngx_event_t *rev)
> if (c->close) {
> qc->error = NGX_QUIC_ERR_NO_ERROR;
> qc->error_reason = "graceful shutdown";
> - ngx_quic_close_connection(c, NGX_OK);
> + ngx_quic_close_connection(c, NGX_ERROR);
> return;
> }
>
> @@ -603,12 +605,17 @@ ngx_quic_finalize_connection(ngx_connect
> ngx_quic_connection_t *qc;
>
> qc = ngx_quic_get_connection(c);
> +
> + if (qc->closing) {
> + return;
> + }
> +
> qc->error = err;
> qc->error_reason = reason;
> qc->error_app = 1;
> qc->error_ftype = 0;
>
> - ngx_quic_close_connection(c, NGX_OK);
> + ngx_post_event(&qc->close, &ngx_posted_events);
> }
>
>
> @@ -630,20 +637,13 @@ ngx_quic_shutdown_connection(ngx_connect
> static void
> ngx_quic_close_handler(ngx_event_t *ev)
> {
> - ngx_connection_t *c;
> - ngx_quic_connection_t *qc;
> + ngx_connection_t *c;
>
> ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic close handler");
>
> c = ev->data;
> - qc = ngx_quic_get_connection(c);
>
> - if (qc->closing) {
> - ngx_quic_close_connection(c, NGX_OK);
> -
> - } else if (qc->shutdown) {
> - ngx_quic_shutdown_quic(c);
> - }
> + ngx_quic_close_connection(c, NGX_OK);
> }
>
>
> @@ -1428,31 +1428,10 @@ ngx_quic_push_handler(ngx_event_t *ev)
> void
> ngx_quic_shutdown_quic(ngx_connection_t *c)
> {
> - ngx_rbtree_t *tree;
> - ngx_rbtree_node_t *node;
> - ngx_quic_stream_t *qs;
> ngx_quic_connection_t *qc;
>
> - qc = ngx_quic_get_connection(c);
> -
> - if (qc->closing) {
> - return;
> + if (c->reusable) {
> + qc = ngx_quic_get_connection(c);
> + ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason);
> }
> -
> - tree = &qc->streams.tree;
> -
> - if (tree->root != tree->sentinel) {
> - for (node = ngx_rbtree_min(tree->root, tree->sentinel);
> - node;
> - node = ngx_rbtree_next(tree, node))
> - {
> - qs = (ngx_quic_stream_t *) node;
> -
> - if (!qs->cancelable) {
> - return;
> - }
> - }
> - }
> -
> - ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason);
> }
> 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
> @@ -113,6 +113,7 @@ void ngx_quic_shutdown_connection(ngx_co
> const char *reason);
> ngx_int_t ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err);
> ngx_int_t ngx_quic_shutdown_stream(ngx_connection_t *c, int how);
> +void ngx_quic_cancelable_stream(ngx_connection_t *c);
> ngx_int_t ngx_quic_handle_read_event(ngx_event_t *rev, ngx_uint_t flags);
> ngx_int_t ngx_quic_handle_write_event(ngx_event_t *wev, size_t lowat);
> ngx_int_t ngx_quic_get_packet_dcid(ngx_log_t *log, u_char *data, size_t len,
> diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
> --- a/src/event/quic/ngx_event_quic_streams.c
> +++ b/src/event/quic/ngx_event_quic_streams.c
> @@ -33,6 +33,7 @@ static ngx_chain_t *ngx_quic_stream_send
> static ngx_int_t ngx_quic_stream_flush(ngx_quic_stream_t *qs);
> static void ngx_quic_stream_cleanup_handler(void *data);
> static ngx_int_t ngx_quic_close_stream(ngx_quic_stream_t *qs);
> +static ngx_int_t ngx_quic_can_shutdown(ngx_connection_t *c);
> static ngx_int_t ngx_quic_control_flow(ngx_quic_stream_t *qs, uint64_t last);
> static ngx_int_t ngx_quic_update_flow(ngx_quic_stream_t *qs, uint64_t last);
> static ngx_int_t ngx_quic_update_max_stream_data(ngx_quic_stream_t *qs);
> @@ -51,6 +52,10 @@ ngx_quic_open_stream(ngx_connection_t *c
> pc = c->quic ? c->quic->parent : c;
> qc = ngx_quic_get_connection(pc);
>
> + if (qc->shutdown || qc->closing) {

I think the shutdown part needs to be reverted as otherwise
it would prevent creating on-demand a unidirectional stream
used to send Stream Cancelation decoder instruction.
In particular, this is possible if client sends additional
request streams after we sent GOAWAY and the decoder stream
hasn't yet been used (i.e. there were no insertions).

> + return NULL;
> + }
> +
> if (bidi) {
> if (qc->streams.server_streams_bidi
> >= qc->streams.server_max_streams_bidi)
> @@ -161,13 +166,10 @@ ngx_quic_close_streams(ngx_connection_t
> ngx_pool_t *pool;
> ngx_queue_t *q;
> ngx_rbtree_t *tree;
> + ngx_connection_t *sc;
> ngx_rbtree_node_t *node;
> ngx_quic_stream_t *qs;
>
> -#if (NGX_DEBUG)
> - ngx_uint_t ns;
> -#endif
> -
> while (!ngx_queue_empty(&qc->streams.uninitialized)) {
> q = ngx_queue_head(&qc->streams.uninitialized);
> ngx_queue_remove(q);
> @@ -185,34 +187,34 @@ ngx_quic_close_streams(ngx_connection_t
> return NGX_OK;
> }
>
> -#if (NGX_DEBUG)
> - ns = 0;
> -#endif
> -
> node = ngx_rbtree_min(tree->root, tree->sentinel);
>
> while (node) {
> qs = (ngx_quic_stream_t *) node;
> node = ngx_rbtree_next(tree, node);
> + sc = qs->connection;
>
> qs->recv_state = NGX_QUIC_STREAM_RECV_RESET_RECVD;
> qs->send_state = NGX_QUIC_STREAM_SEND_RESET_SENT;
>
> - if (qs->connection == NULL) {
> + if (sc == NULL) {
> ngx_quic_close_stream(qs);
> continue;
> }
>
> - ngx_quic_set_event(qs->connection->read);
> - ngx_quic_set_event(qs->connection->write);
> + ngx_quic_set_event(sc->read);
> + ngx_quic_set_event(sc->write);
>
> -#if (NGX_DEBUG)
> - ns++;
> -#endif
> + sc->close = 1;
> + sc->read->handler(sc->read);
> }
>
> - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
> - "quic connection has %ui active streams", ns);
> + if (tree->root == tree->sentinel) {
> + return NGX_OK;
> + }
> +
> + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> + "quic connection has active streams");
>
> return NGX_AGAIN;
> }
> @@ -587,6 +589,7 @@ ngx_quic_create_stream(ngx_connection_t
> {
> ngx_log_t *log;
> ngx_pool_t *pool;
> + ngx_uint_t reusable;
> ngx_queue_t *q;
> ngx_connection_t *sc;
> ngx_quic_stream_t *qs;
> @@ -639,10 +642,14 @@ ngx_quic_create_stream(ngx_connection_t
> *log = *c->log;
> pool->log = log;
>
> + reusable = c->reusable;
> + ngx_reusable_connection(c, 0);
> +
> sc = ngx_get_connection(c->fd, log);
> if (sc == NULL) {
> ngx_destroy_pool(pool);
> ngx_queue_insert_tail(&qc->streams.free, &qs->queue);
> + ngx_reusable_connection(c, reusable);
> return NULL;
> }
>
> @@ -712,6 +719,7 @@ ngx_quic_create_stream(ngx_connection_t
> ngx_close_connection(sc);
> ngx_destroy_pool(pool);
> ngx_queue_insert_tail(&qc->streams.free, &qs->queue);
> + ngx_reusable_connection(c, reusable);
> return NULL;
> }
>
> @@ -724,6 +732,31 @@ ngx_quic_create_stream(ngx_connection_t
> }
>
>
> +void
> +ngx_quic_cancelable_stream(ngx_connection_t *c)
> +{
> + ngx_connection_t *pc;
> + ngx_quic_stream_t *qs;
> + ngx_quic_connection_t *qc;
> +
> + qs = c->quic;
> + pc = qs->parent;
> + qc = ngx_quic_get_connection(pc);
> +
> + if (!qs->cancelable) {
> + qs->cancelable = 1;
> +
> + if (ngx_quic_can_shutdown(pc) == NGX_OK) {
> + ngx_reusable_connection(pc, 1);
> +
> + if (qc->shutdown) {
> + ngx_quic_shutdown_quic(pc);
> + }
> + }
> + }
> +}
> +
> +
> static void
> ngx_quic_empty_handler(ngx_event_t *ev)
> {
> @@ -1056,14 +1089,47 @@ ngx_quic_close_stream(ngx_quic_stream_t
> ngx_quic_queue_frame(qc, frame);
> }
>
> + if (!pc->reusable && ngx_quic_can_shutdown(pc) == NGX_OK) {
> + ngx_reusable_connection(pc, 1);
> + }
> +
> if (qc->shutdown) {
> - ngx_post_event(&qc->close, &ngx_posted_events);
> + ngx_quic_shutdown_quic(pc);
> }
>
> return NGX_OK;
> }
>
>
> +static ngx_int_t
> +ngx_quic_can_shutdown(ngx_connection_t *c)
> +{
> + ngx_rbtree_t *tree;
> + ngx_rbtree_node_t *node;
> + ngx_quic_stream_t *qs;
> + ngx_quic_connection_t *qc;
> +
> + qc = ngx_quic_get_connection(c);
> +
> + tree = &qc->streams.tree;
> +
> + if (tree->root != tree->sentinel) {
> + for (node = ngx_rbtree_min(tree->root, tree->sentinel);
> + node;
> + node = ngx_rbtree_next(tree, node))
> + {
> + qs = (ngx_quic_stream_t *) node;
> +
> + if (!qs->cancelable) {
> + return NGX_DECLINED;
> + }
> + }
> + }
> +
> + return NGX_OK;
> +}
> +
> +
> ngx_int_t
> ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
> ngx_quic_frame_t *frame)
> diff --git a/src/http/v3/ngx_http_v3_uni.c b/src/http/v3/ngx_http_v3_uni.c
> --- a/src/http/v3/ngx_http_v3_uni.c
> +++ b/src/http/v3/ngx_http_v3_uni.c
> @@ -52,7 +52,7 @@ ngx_http_v3_init_uni_stream(ngx_connecti
> return;
> }
>
> - c->quic->cancelable = 1;
> + ngx_quic_cancelable_stream(c);
>
> us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t));
> if (us == NULL) {
> @@ -182,6 +182,11 @@ ngx_http_v3_uni_read_handler(ngx_event_t
>
> ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler");
>
> + if (c->close) {
> + ngx_http_v3_close_uni_stream(c);
> + return;
> + }
> +
> ngx_memzero(&b, sizeof(ngx_buf_t));
>
> while (rev->ready) {
> @@ -262,6 +267,11 @@ ngx_http_v3_uni_dummy_read_handler(ngx_e
>
> ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy read handler");
>
> + if (c->close) {
> + ngx_http_v3_close_uni_stream(c);
> + return;
> + }
> +
> if (rev->ready) {
> if (c->recv(c, &ch, 1) != 0) {
> ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, NULL);
> @@ -404,7 +414,7 @@ ngx_http_v3_get_uni_stream(ngx_connectio
> goto failed;
> }
>
> - sc->quic->cancelable = 1;
> + ngx_quic_cancelable_stream(sc);
>
> ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
> "http3 create uni stream, type:%ui", type);
_______________________________________________
nginx-devel mailing list -- nginx-devel@nginx.org
To unsubscribe send an email to nginx-devel-leave@nginx.org
Subject Author Views Posted

[PATCH 0 of 2] QUIC connection reuse

Roman Arutyunyan 1406 May 18, 2022 03:00AM

[PATCH 1 of 2] QUIC: reusable and idle modes for main connection

Roman Arutyunyan 204 May 18, 2022 03:02AM

Re: [PATCH 1 of 2] QUIC: reusable and idle modes for main connection

Sergey Kandaurov 260 May 30, 2022 09:56AM

Re: [PATCH 1 of 2] QUIC: reusable and idle modes for main connection

Roman Arutyunyan 195 June 02, 2022 09:42AM

[PATCH 2 of 2] QUIC: init_streams() callback

Roman Arutyunyan 208 May 18, 2022 03:04AM

Re: [PATCH 2 of 2] QUIC: init_streams() callback

Sergey Kandaurov 210 May 30, 2022 05:56PM

Re: [PATCH 2 of 2] QUIC: init_streams() callback

Roman Arutyunyan 188 June 02, 2022 09:46AM

[PATCH 0 of 3] QUIC connection reuse

Roman Arutyunyan 195 June 02, 2022 09:54AM

[PATCH 2 of 3] QUIC: relocated early streams initialization

Roman Arutyunyan 202 June 02, 2022 09:54AM

Re: [PATCH 2 of 3] QUIC: relocated early streams initialization

Sergey Kandaurov 193 June 06, 2022 06:44AM

[PATCH 0 of 8] QUIC connection reuse

Roman Arutyunyan 172 June 23, 2022 12:00PM

[PATCH 2 of 8] QUIC: ngx_quic_terminate_connection() function

Roman Arutyunyan 202 June 23, 2022 12:00PM

[PATCH 1 of 8] QUIC: treat qc->error == -1 as a missing error

Roman Arutyunyan 318 June 23, 2022 12:00PM

Re: [PATCH 1 of 8] QUIC: treat qc->error == -1 as a missing error

Sergey Kandaurov 204 August 02, 2022 09:50AM

Re: [PATCH 1 of 8] QUIC: treat qc->error == -1 as a missing error

Roman Arutyunyan 144 August 23, 2022 08:22AM

[PATCH 4 of 8] QUIC: removed ngx_quic_shutdown_connection()

Roman Arutyunyan 225 June 23, 2022 12:00PM

Re: [PATCH 4 of 8] QUIC: removed ngx_quic_shutdown_connection()

Sergey Kandaurov 180 August 02, 2022 11:46AM

Re: [PATCH 4 of 8] QUIC: removed ngx_quic_shutdown_connection()

Roman Arutyunyan 144 August 23, 2022 08:30AM

[PATCH 5 of 8] HTTP/3: keepalive timer for hq mode

Roman Arutyunyan 175 June 23, 2022 12:00PM

[PATCH 8 of 8] QUIC: application init() callback

Roman Arutyunyan 175 June 23, 2022 12:00PM

[PATCH 3 of 8] QUIC: reusable mode for main connection

Roman Arutyunyan 167 June 23, 2022 12:00PM

[PATCH 7 of 8] HTTP/3: renamed functions

Roman Arutyunyan 163 June 23, 2022 12:00PM

[PATCH 6 of 8] QUIC: idle mode for main connection

Roman Arutyunyan 189 June 23, 2022 12:00PM

[PATCH 0 of 9] QUIC connection reuse

Roman Arutyunyan 154 August 23, 2022 08:52AM

[PATCH 5 of 9] QUIC: do not send MAX_STREAMS in shutdown state

Roman Arutyunyan 172 August 23, 2022 08:52AM

[PATCH 4 of 9] QUIC: defer stream removal until all its data is acked

Roman Arutyunyan 139 August 23, 2022 08:52AM

[PATCH 1 of 9] QUIC: treat qc->error == -1 as a missing error

Roman Arutyunyan 139 August 23, 2022 08:52AM

[PATCH 7 of 9] QUIC: idle mode for main connection

Roman Arutyunyan 144 August 23, 2022 08:52AM

[PATCH 8 of 9] HTTP/3: renamed functions

Roman Arutyunyan 174 August 23, 2022 08:52AM

[PATCH 9 of 9] QUIC: application init() callback

Roman Arutyunyan 162 August 23, 2022 08:54AM

[PATCH 6 of 9] HTTP/3: unified hq code with HTTP/3 code

Roman Arutyunyan 138 August 23, 2022 08:54AM

[PATCH 00 of 10] QUIC connection reuse

Roman Arutyunyan 139 September 08, 2022 05:08AM

[PATCH 06 of 10] QUIC: do not send MAX_STREAMS in shutdown state

Roman Arutyunyan 130 September 08, 2022 05:08AM

[PATCH 03 of 10] QUIC: post close event for connection close

Roman Arutyunyan 144 September 08, 2022 05:10AM

[PATCH 02 of 10] QUIC: made ngx_quic_finalize_connecion() more graceful

Roman Arutyunyan 138 September 08, 2022 05:10AM

[PATCH 07 of 10] HTTP/3: unified hq code with regular HTTP/3 code

Roman Arutyunyan 136 September 08, 2022 05:10AM

Re: [PATCH 07 of 10] HTTP/3: unified hq code with regular HTTP/3 code

Sergey Kandaurov 126 October 20, 2022 07:36AM

Re: [PATCH 07 of 10] HTTP/3: unified hq code with regular HTTP/3 code

Roman Arutyunyan 151 October 20, 2022 09:56AM

[PATCH 04 of 10] QUIC: reusable mode for main connection

Roman Arutyunyan 148 September 08, 2022 05:10AM

Re: [PATCH 04 of 10] QUIC: reusable mode for main connection

Sergey Kandaurov 111 November 28, 2022 11:12AM

[PATCH 08 of 10] QUIC: idle mode for main connection

Roman Arutyunyan 156 September 08, 2022 05:10AM

Re: [PATCH 08 of 10] QUIC: idle mode for main connection

Sergey Kandaurov 159 October 20, 2022 07:52AM

Re: [PATCH 08 of 10] QUIC: idle mode for main connection

Roman Arutyunyan 144 October 20, 2022 10:26AM

Re: [PATCH 08 of 10] QUIC: idle mode for main connection

Roman Arutyunyan 196 November 24, 2022 10:18AM

Re: [PATCH 08 of 10] QUIC: idle mode for main connection

Sergey Kandaurov 120 November 28, 2022 12:42PM

Re: [PATCH 08 of 10] QUIC: idle mode for main connection

Roman Arutyunyan 113 November 29, 2022 09:02AM

Re: [PATCH 08 of 10] QUIC: idle mode for main connection

Roman Arutyunyan 133 November 30, 2022 05:14AM

[PATCH 05 of 10] QUIC: defer stream removal until all its data is acked

Roman Arutyunyan 141 September 08, 2022 05:10AM

[PATCH 10 of 10] QUIC: application init() callback

Roman Arutyunyan 142 September 08, 2022 05:10AM

Re: [PATCH 10 of 10] QUIC: application init() callback

Sergey Kandaurov 129 October 20, 2022 07:54AM

Re: [PATCH 10 of 10] QUIC: application init() callback

Roman Arutyunyan 160 October 20, 2022 10:34AM

Re: [PATCH 10 of 10] QUIC: application init() callback

Roman Arutyunyan 198 October 25, 2022 05:12AM

[PATCH 09 of 10] HTTP/3: renamed functions

Roman Arutyunyan 214 September 08, 2022 05:10AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 312
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready