Add channel-only tick mode and use it for thread assisted mode
authorHugo Landau <hlandau@openssl.org>
Tue, 21 Feb 2023 10:18:59 +0000 (10:18 +0000)
committerHugo Landau <hlandau@openssl.org>
Thu, 30 Mar 2023 10:14:08 +0000 (11:14 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20348)

include/internal/quic_reactor.h
ssl/quic/quic_channel.c
ssl/quic/quic_impl.c
ssl/quic/quic_reactor.c
ssl/quic/quic_thread_assist.c
ssl/quic/quic_tserver.c

index e978dac8ff66fb67658d98253986ba4015138b9b..6a8ebbe29dbf823f88a2c76bb78121a0f1f344a6 100644 (file)
@@ -85,7 +85,7 @@ typedef struct quic_reactor_st {
     BIO_POLL_DESCRIPTOR poll_r, poll_w;
     OSSL_TIME tick_deadline; /* ossl_time_infinite() if none currently applicable */
 
-    void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg);
+    void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
     void *tick_cb_arg;
 
     /*
@@ -97,7 +97,8 @@ typedef struct quic_reactor_st {
 } QUIC_REACTOR;
 
 void ossl_quic_reactor_init(QUIC_REACTOR *rtor,
-                            void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg),
+                            void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg,
+                                            uint32_t flags),
                             void *tick_cb_arg,
                             OSSL_TIME initial_tick_deadline);
 
@@ -121,8 +122,13 @@ OSSL_TIME ossl_quic_reactor_get_tick_deadline(QUIC_REACTOR *rtor);
  * Do whatever work can be done, and as much work as can be done. This involves
  * e.g. seeing if we can read anything from the network (if we want to), seeing
  * if we can write anything to the network (if we want to), etc.
+ *
+ * If the CHANNEL_ONLY flag is set, this indicates that we should only
+ * touch state which is synchronised by the channel mutex.
  */
-int ossl_quic_reactor_tick(QUIC_REACTOR *rtor);
+#define QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY  (1U << 0)
+
+int ossl_quic_reactor_tick(QUIC_REACTOR *rtor, uint32_t flags);
 
 /*
  * Blocking I/O Adaptation Layer
index 07c680511c849c1ec328c5a8c8b87b93096c28ac..16b158d8a9312730b9fc352492e94172c434314a 100644 (file)
@@ -31,7 +31,7 @@
 static void ch_rx_pre(QUIC_CHANNEL *ch);
 static int ch_rx(QUIC_CHANNEL *ch);
 static int ch_tx(QUIC_CHANNEL *ch);
-static void ch_tick(QUIC_TICK_RESULT *res, void *arg);
+static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
 static void ch_rx_handle_packet(QUIC_CHANNEL *ch);
 static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch);
 static int ch_retry(QUIC_CHANNEL *ch,
@@ -1207,10 +1207,11 @@ err:
  * at least everything network I/O related. Best effort - not allowed to fail
  * "loudly".
  */
-static void ch_tick(QUIC_TICK_RESULT *res, void *arg)
+static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
 {
     OSSL_TIME now, deadline;
     QUIC_CHANNEL *ch = arg;
+    int channel_only = ((flags & QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY) != 0);
 
     /*
      * When we tick the QUIC connection, we do everything we need to do
@@ -1259,7 +1260,8 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg)
          * new outgoing data.
          */
         ch->have_new_rx_secret = 0;
-        ossl_quic_tls_tick(ch->qtls);
+        if (!channel_only)
+            ossl_quic_tls_tick(ch->qtls);
 
         /*
          * If the handshake layer gave us a new secret, we need to do RX again
@@ -1753,7 +1755,7 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch)
     if (!ossl_quic_tls_tick(ch->qtls))
         return 0;
 
-    ossl_quic_reactor_tick(&ch->rtor); /* best effort */
+    ossl_quic_reactor_tick(&ch->rtor, 0); /* best effort */
     return 1;
 }
 
index 73071d4a73014b993d0e192e9ba644f57a083b48..4286c526b769ec283cb70ed9472ef112a742dbf7 100644 (file)
@@ -450,7 +450,7 @@ int ossl_quic_tick(QUIC_CONNECTION *qc)
         return 1;
     }
 
-    ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+    ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
     quic_unlock(qc);
     return 1;
 }
@@ -587,7 +587,7 @@ int ossl_quic_conn_shutdown(QUIC_CONNECTION *qc, uint64_t flags,
     if (blocking_mode(qc) && (flags & SSL_SHUTDOWN_FLAG_RAPID) == 0)
         block_until_pred(qc, quic_shutdown_wait, qc, 0);
     else
-        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
 
     ret = ossl_quic_channel_is_terminated(qc->ch);
     quic_unlock(qc);
@@ -783,7 +783,7 @@ static int quic_do_handshake(QUIC_CONNECTION *qc)
         return 1;
     } else {
         /* Try to advance the reactor. */
-        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
 
         if (ossl_quic_channel_is_handshake_complete(qc->ch))
             /* The handshake is now done. */
@@ -895,7 +895,7 @@ static void quic_post_write(QUIC_CONNECTION *qc, int did_append, int do_tick)
      * plus we should eventually consider Nagle's algorithm.
      */
     if (do_tick)
-        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
 }
 
 struct quic_write_again_args {
@@ -1282,7 +1282,7 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
          * Even though we succeeded, tick the reactor here to ensure we are
          * handling other aspects of the QUIC connection.
          */
-        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+        ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
         ret = 1;
     } else if (blocking_mode(qc)) {
         /*
index 864ba3281c18efa6fe06c86d4a840c35c9f33c12..cae8dffe0eb52a1557abf692b928913081a77587 100644 (file)
@@ -14,7 +14,8 @@
  * ==========================
  */
 void ossl_quic_reactor_init(QUIC_REACTOR *rtor,
-                            void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg),
+                            void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg,
+                                            uint32_t flags),
                             void *tick_cb_arg,
                             OSSL_TIME initial_tick_deadline)
 {
@@ -63,7 +64,7 @@ OSSL_TIME ossl_quic_reactor_get_tick_deadline(QUIC_REACTOR *rtor)
     return rtor->tick_deadline;
 }
 
-int ossl_quic_reactor_tick(QUIC_REACTOR *rtor)
+int ossl_quic_reactor_tick(QUIC_REACTOR *rtor, uint32_t flags)
 {
     QUIC_TICK_RESULT res = {0};
 
@@ -74,7 +75,7 @@ int ossl_quic_reactor_tick(QUIC_REACTOR *rtor)
      * best effort. If something fatal happens with a connection we can report
      * it on the next actual application I/O call.
      */
-    rtor->tick_cb(&res, rtor->tick_cb_arg);
+    rtor->tick_cb(&res, rtor->tick_cb_arg, flags);
 
     rtor->net_read_desired  = res.net_read_desired;
     rtor->net_write_desired = res.net_write_desired;
@@ -315,7 +316,7 @@ int ossl_quic_reactor_block_until_pred(QUIC_REACTOR *rtor,
             flags &= ~SKIP_FIRST_TICK;
         else
             /* best effort */
-            ossl_quic_reactor_tick(rtor);
+            ossl_quic_reactor_tick(rtor, 0);
 
         if ((res = pred(pred_arg)) != 0)
             return res;
index 6b2c21998262b442ea7f522887dd698fc32dc677..4f760ea99cfd2ece8dae29ab8f599f931614d222 100644 (file)
@@ -49,7 +49,7 @@ static unsigned int assist_thread_main(void *arg)
         if (qta->teardown)
             break;
 
-        ossl_quic_reactor_tick(rtor);
+        ossl_quic_reactor_tick(rtor, QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY);
     }
 
     CRYPTO_THREAD_unlock(m);
index 158abf705bcb717aa56b417bc63aa8ba50d20d3a..4278f13f09616936cfc7bee439f6f80bb08aa924 100644 (file)
@@ -153,7 +153,7 @@ int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER *srv,
 
 int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
 {
-    ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch));
+    ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);
 
     if (ossl_quic_channel_is_active(srv->ch))
         srv->connected = 1;