performance is affected after merge OCSP changeset

Roman Arutyunyan arut at nginx.com
Tue Oct 26 11:48:03 UTC 2021


On Thu, Oct 21, 2021 at 07:41:05PM +0300, Sergey Kandaurov wrote:
> 
> > On 21 Oct 2021, at 15:15, Roman Arutyunyan <arut at nginx.com> wrote:
> > 
> > On Tue, Oct 19, 2021 at 01:07:56PM +0300, Sergey Kandaurov wrote:
> >> 
> >> [..]
> >> Below is alternative patch, it brings closer to how OCSP validation
> >> is done with SSL_read_early_data(), with its inherent design flaws.
> >> Namely, the case of regular SSL session reuse is still pessimized,
> >> but that shouldn't bring further slowdown with ssl_ocsp disabled,
> >> which is slow by itself.
> >> 
> >> # HG changeset patch
> >> # User Sergey Kandaurov <pluknet at nginx.com>
> >> # Date 1634637049 -10800
> >> #      Tue Oct 19 12:50:49 2021 +0300
> >> # Branch quic
> >> # Node ID 6f26d6656b4ef97a3a245354bd7fa9e5c8671237
> >> # Parent  1798acc01970ae5a03f785b7679fe34c32adcfea
> >> QUIC: speeding up processing 0-RTT.
> >> 
> >> After fe919fd63b0b, processing QUIC streams was postponed until after handshake
> >> completion, which means that 0-RTT is effectively off.  With ssl_ocsp enabled,
> >> it could be further delayed.  This differs to how SSL_read_early_data() works.
> > 
> > differs FROM ?
> > 
> >> This change unlocks processing streams on successful 0-RTT packet decryption.
> >> 
> 
> Both forms seem to be used, but "differs to" looks less popular.
> Rewrote it this way:
> 
> This differs from how OCSP validation works with SSL_read_early_data().
> 
> >> 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
> >> @@ -989,6 +989,21 @@ ngx_quic_process_payload(ngx_connection_
> >>         }
> >>     }
> >> 
> >> +    if (pkt->level == ssl_encryption_early_data && !qc->streams.initialized) {
> >> +        rc = ngx_ssl_ocsp_validate(c);
> >> +
> >> +        if (rc == NGX_ERROR) {
> >> +            return NGX_ERROR;
> >> +        }
> >> +
> >> +        if (rc == NGX_AGAIN) {
> >> +            c->ssl->handler = ngx_quic_init_streams;
> >> +
> >> +        } else {
> >> +            ngx_quic_init_streams(c);
> >> +        }
> >> +    }
> >> +
> >>     if (pkt->level == ssl_encryption_handshake) {
> >>         /*
> >>          * RFC 9001, 4.9.1.  Discarding Initial Keys
> >> diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c
> >> --- a/src/event/quic/ngx_event_quic_ssl.c
> >> +++ b/src/event/quic/ngx_event_quic_ssl.c
> >> @@ -463,6 +463,11 @@ ngx_quic_crypto_input(ngx_connection_t *
> >>         return NGX_ERROR;
> >>     }
> >> 
> >> +    if (qc->streams.initialized) {
> >> +        /* done while processing 0-RTT */
> >> +        return NGX_OK;
> >> +    }
> >> +
> >>     rc = ngx_ssl_ocsp_validate(c);
> >> 
> >>     if (rc == NGX_ERROR) {
> >> 
> > 
> > It would be nice to always call ngx_ssl_ocsp_validate() from the same source
> > file (presumably ngx_event_quic_ssl.c).  But this does not seem to occur
> > naturally so let's leave it as it is.
> > 
> > Looks good.
> > 
> > PS: Also, this can be further refactored to move ngx_ssl_ocsp_validate() inside
> > ngx_quic_init_streams().  In this case we can only call ngx_quic_init_streams()
> > both times.
> 
> This is feasible, if init streams closer to obtaining 0-RTT secret.
> Actually, it is even better, I believe, and it's invoked just once
> regardless of the number of 0-RTT packets.
> Requirement for successful 0-RTT decryption doesn't buy us much.
> 
> N.B. I decided to leave in place "quic init streams" debug.
> This is where streams are now actually initialized,
> and it looks reasonable to see that logged only once.
> 
> # HG changeset patch
> # User Sergey Kandaurov <pluknet at nginx.com>
> # Date 1634832181 -10800
> #      Thu Oct 21 19:03:01 2021 +0300
> # Branch quic
> # Node ID 11119f9fda599c890a93b348310f582e3c49ebb7
> # Parent  1798acc01970ae5a03f785b7679fe34c32adcfea
> QUIC: refactored OCSP validation in preparation for 0-RTT support.
> 
> diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c
> --- a/src/event/quic/ngx_event_quic_ssl.c
> +++ b/src/event/quic/ngx_event_quic_ssl.c
> @@ -361,7 +361,6 @@ static ngx_int_t
>  ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
>  {
>      int                     n, sslerr;
> -    ngx_int_t               rc;
>      ngx_buf_t              *b;
>      ngx_chain_t            *cl;
>      ngx_ssl_conn_t         *ssl_conn;
> @@ -463,19 +462,10 @@ ngx_quic_crypto_input(ngx_connection_t *
>          return NGX_ERROR;
>      }
>  
> -    rc = ngx_ssl_ocsp_validate(c);
> -
> -    if (rc == NGX_ERROR) {
> +    if (ngx_quic_init_streams(c) != NGX_OK) {
>          return NGX_ERROR;
>      }
>  
> -    if (rc == NGX_AGAIN) {
> -        c->ssl->handler = ngx_quic_init_streams;
> -        return NGX_OK;
> -    }
> -
> -    ngx_quic_init_streams(c);
> -
>      return NGX_OK;
>  }
>  
> 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
> @@ -16,6 +16,7 @@
>  static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c,
>      uint64_t id);
>  static ngx_int_t ngx_quic_init_stream(ngx_quic_stream_t *qs);
> +static void ngx_quic_init_streams_handler(ngx_connection_t *c);
>  static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c,
>      uint64_t id);
>  static void ngx_quic_empty_handler(ngx_event_t *ev);
> @@ -369,9 +370,37 @@ ngx_quic_init_stream(ngx_quic_stream_t *
>  }
>  
>  
> -void
> +ngx_int_t
>  ngx_quic_init_streams(ngx_connection_t *c)
>  {
> +    ngx_int_t               rc;
> +    ngx_quic_connection_t  *qc;
> +
> +    qc = ngx_quic_get_connection(c);
> +
> +    if (qc->streams.initialized) {
> +        return NGX_OK;
> +    }
> +
> +    rc = ngx_ssl_ocsp_validate(c);
> +
> +    if (rc == NGX_ERROR) {
> +        return NGX_ERROR;
> +    }
> +
> +    if (rc == NGX_AGAIN) {
> +        c->ssl->handler = ngx_quic_init_streams_handler;
> +        return NGX_OK;
> +    }
> +
> +    ngx_quic_init_streams_handler(c);
> +
> +    return NGX_OK;
> +}
> +

Missing an empty line.

> +static void
> +ngx_quic_init_streams_handler(ngx_connection_t *c)
> +{
>      ngx_queue_t            *q;
>      ngx_quic_stream_t      *qs;
>      ngx_quic_connection_t  *qc;
> diff --git a/src/event/quic/ngx_event_quic_streams.h b/src/event/quic/ngx_event_quic_streams.h
> --- a/src/event/quic/ngx_event_quic_streams.h
> +++ b/src/event/quic/ngx_event_quic_streams.h
> @@ -31,7 +31,7 @@ ngx_int_t ngx_quic_handle_stop_sending_f
>  ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
>      ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f);
>  
> -void ngx_quic_init_streams(ngx_connection_t *c);
> +ngx_int_t ngx_quic_init_streams(ngx_connection_t *c);
>  void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
>      ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
>  ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree,
> # HG changeset patch
> # User Sergey Kandaurov <pluknet at nginx.com>
> # Date 1634832186 -10800
> #      Thu Oct 21 19:03:06 2021 +0300
> # Branch quic
> # Node ID b53e361bee7dfbb027507a717e6648234a06ef13
> # Parent  11119f9fda599c890a93b348310f582e3c49ebb7
> QUIC: speeding up processing 0-RTT.
> 
> After fe919fd63b0b, processing QUIC streams was postponed until after handshake
> completion, which means that 0-RTT is effectively off.  With ssl_ocsp enabled,
> it could be further delayed.  This differs from how OCSP validation works with
> SSL_read_early_data().  With this change, processing QUIC streams is unlocked
> when obtaining 0-RTT secret.
> 
> diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c
> --- a/src/event/quic/ngx_event_quic_ssl.c
> +++ b/src/event/quic/ngx_event_quic_ssl.c
> @@ -71,8 +71,20 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t 
>                     secret_len, rsecret);
>  #endif
>  
> -    return ngx_quic_keys_set_encryption_secret(c->pool, 0, qc->keys, level,
> -                                               cipher, rsecret, secret_len);
> +    if (ngx_quic_keys_set_encryption_secret(c->pool, 0, qc->keys, level,
> +                                            cipher, rsecret, secret_len)
> +        != 1)
> +    {
> +        return 0;
> +    }
> +
> +    if (level == ssl_encryption_early_data) {
> +        if (ngx_quic_init_streams(c) != NGX_OK) {
> +            return 0;
> +        }
> +    }
> +
> +    return 1;
>  }
>  
>  
> @@ -131,6 +143,10 @@ ngx_quic_set_encryption_secrets(ngx_ssl_
>      }
>  
>      if (level == ssl_encryption_early_data) {
> +        if (ngx_quic_init_streams(c) != NGX_OK) {
> +            return 0;
> +        }
> +
>          return 1;
>      }
>  
> 
> -- 
> Sergey Kandaurov
> 

Looks good.

-- 
Roman Arutyunyan


More information about the nginx-devel mailing list