QUIC PORT, CHANNEL: Move ticking code into QUIC_PORT
authorHugo Landau <hlandau@openssl.org>
Thu, 9 Nov 2023 10:27:13 +0000 (10:27 +0000)
committerHugo Landau <hlandau@openssl.org>
Thu, 21 Dec 2023 08:11:59 +0000 (08:11 +0000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22674)

include/internal/quic_channel.h
include/internal/quic_port.h
ssl/quic/quic_channel.c
ssl/quic/quic_channel_local.h
ssl/quic/quic_impl.c
ssl/quic/quic_port.c
ssl/quic/quic_port_local.h
test/quic_multistream_test.c

index b8d3edf23f8b16ce59188fe7a2147f6a88d83680..d0046d07d1c95fda0e5245f6ef154b1fccf51ff0 100644 (file)
@@ -267,6 +267,13 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer,
                                   const QUIC_CONN_ID *peer_scid,
                                   const QUIC_CONN_ID *peer_dcid);
 
+/* For use by QUIC_PORT. You should not need to call this directly. */
+void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *r,
+                               uint32_t flags);
+
+/* For use by QUIC_PORT only. */
+void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch);
+
 /*
  * Queries and Accessors
  * =====================
@@ -294,12 +301,6 @@ BIO *ossl_quic_channel_get_net_wbio(QUIC_CHANNEL *ch);
 int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio);
 int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio);
 
-/*
- * Re-poll the network BIOs already set to determine if their support
- * for polling has changed.
- */
-int ossl_quic_channel_update_poll_descriptors(QUIC_CHANNEL *ch);
-
 /*
  * Returns an existing stream by stream ID. Returns NULL if the stream does not
  * exist.
@@ -396,9 +397,6 @@ int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch);
 /* Force transmission of an ACK-eliciting packet. */
 int ossl_quic_channel_ping(QUIC_CHANNEL *ch);
 
-/* For testing use. While enabled, ticking is not performed. */
-void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit);
-
 /*
  * These queries exist for diagnostic purposes only. They may roll over.
  * Do not rely on them for non-testing purposes.
index 75fcaad87fdedec2439bab6b54e37be2b1ab2ea4..3d9e5b02112d8fc9c4ac19278ec27688398604bb 100644 (file)
@@ -97,6 +97,10 @@ BIO *ossl_quic_port_get_net_wbio(QUIC_PORT *port);
 int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio);
 int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio);
 
+/*
+ * Re-poll the network BIOs already set to determine if their support
+ * for polling has changed.
+ */
 int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port);
 
 /* Gets the reactor which can be used to tick/poll on the port. */
@@ -114,6 +118,20 @@ OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port);
 int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port);
 int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port);
 
+/* For testing use. While enabled, ticking is not performed. */
+void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit);
+
+/*
+ * Events
+ * ======
+ */
+
+/*
+ * Called if a permanent network error occurs. Terminates all channels
+ * immediately.
+ */
+void ossl_quic_port_raise_net_error(QUIC_PORT *port);
+
 # endif
 
 #endif
index 2d7784ff04aa159ec3f3faf75dfcd2eb824d0ac4..24f428a3f882c38883520e0772f76b201a5f0305 100644 (file)
 DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL);
 
 static void ch_save_err_state(QUIC_CHANNEL *ch);
-static void ch_rx_pre(QUIC_CHANNEL *ch);
 static int ch_rx(QUIC_CHANNEL *ch, int channel_only);
 static int ch_tx(QUIC_CHANNEL *ch);
-static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
 static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only);
 static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only);
 static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch);
@@ -92,7 +90,6 @@ static void ch_on_idle_timeout(QUIC_CHANNEL *ch);
 static void ch_update_idle(QUIC_CHANNEL *ch);
 static void ch_update_ping_deadline(QUIC_CHANNEL *ch);
 static void ch_stateless_reset(QUIC_CHANNEL *ch);
-static void ch_raise_net_error(QUIC_CHANNEL *ch);
 static void ch_on_terminating_timeout(QUIC_CHANNEL *ch);
 static void ch_start_terminating(QUIC_CHANNEL *ch,
                                  const QUIC_TERMINATE_CAUSE *tcause,
@@ -467,8 +464,6 @@ static int ch_init(QUIC_CHANNEL *ch)
         goto err;
 
     ch_update_idle(ch);
-    ossl_quic_reactor_init(&ch->rtor, ch_tick, ch,
-                           ch_determine_next_tick_deadline(ch));
     ossl_list_ch_insert_tail(&ch->port->channel_list, ch);
     ch->on_port_list = 1;
     return 1;
@@ -601,7 +596,7 @@ int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr)
 
 QUIC_REACTOR *ossl_quic_channel_get_reactor(QUIC_CHANNEL *ch)
 {
-    return &ch->rtor;
+    return ossl_quic_port_get0_reactor(ch->port);
 }
 
 QUIC_STREAM_MAP *ossl_quic_channel_get_qsm(QUIC_CHANNEL *ch)
@@ -1839,20 +1834,20 @@ 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, uint32_t flags)
+void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *res,
+                               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
-     * periodically. In order, we:
+     * periodically. Network I/O handling will already have been performed
+     * as necessary by the QUIC port. Thus, in order, we:
      *
-     *   - handle any incoming data from the network;
-     *   - handle any timer events which are due to fire (ACKM, etc.)
-     *   - write any data to the network due to be sent, to the extent
-     *     possible;
+     *   - handle any packets the DEMUX has queued up for us;
+     *   - handle any timer events which are due to fire (ACKM, etc.);
+     *   - generate any packets which need to be sent;
      *   - determine the time at which we should next be ticked.
      */
 
@@ -1880,13 +1875,10 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
         }
     }
 
-    if (!ch->inhibit_tick) {
+    if (!ch->port->inhibit_tick) {
         /* Handle RXKU timeouts. */
         ch_rxku_tick(ch);
 
-        /* Handle any incoming data from network. */
-        ch_rx_pre(ch);
-
         do {
             /* Process queued incoming packets. */
             ch->did_tls_tick        = 0;
@@ -1923,7 +1915,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
          * Idle timeout differs from normal protocol violation because we do
          * not send a CONN_CLOSE frame; go straight to TERMINATED.
          */
-        if (!ch->inhibit_tick)
+        if (!ch->port->inhibit_tick)
             ch_on_idle_timeout(ch);
 
         res->net_read_desired   = 0;
@@ -1932,7 +1924,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
         return;
     }
 
-    if (!ch->inhibit_tick) {
+    if (!ch->port->inhibit_tick) {
         deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm);
         if (!ossl_time_is_zero(deadline)
             && ossl_time_compare(now, deadline) >= 0)
@@ -1954,7 +1946,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
             ch_update_ping_deadline(ch);
         }
 
-        /* Write any data to the network due to be sent. */
+        /* Queue any data to be sent for transmission. */
         ch_tx(ch);
 
         /* Do stream GC. */
@@ -1965,14 +1957,13 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
     res->tick_deadline = ch_determine_next_tick_deadline(ch);
 
     /*
-     * Always process network input unless we are now terminated.
-     * Although we had not terminated at the beginning of this tick, network
-     * errors in ch_rx_pre() or ch_tx() may have caused us to transition to the
-     * Terminated state.
+     * Always process network input unless we are now terminated. Although we
+     * had not terminated at the beginning of this tick, network errors in
+     * ch_tx() may have caused us to transition to the Terminated state.
      */
     res->net_read_desired = !ossl_quic_channel_is_terminated(ch);
 
-    /* We want to write to the network if we have any in our queue. */
+    /* We want to write to the network if we have any data in our TX queue. */
     res->net_write_desired
         = (!ossl_quic_channel_is_terminated(ch)
            && ossl_qtx_get_queue_len_datagrams(ch->qtx) > 0);
@@ -2000,32 +1991,6 @@ static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only)
     return 1;
 }
 
-/* Process incoming datagrams, if any. */
-static void ch_rx_pre(QUIC_CHANNEL *ch)
-{
-    int ret;
-
-    if (!ch->is_server && !ch->have_sent_any_pkt)
-        return;
-
-    /*
-     * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams
-     * to the appropriate QRX instance.
-     */
-    ret = ossl_quic_demux_pump(ch->port->demux);
-    if (ret == QUIC_DEMUX_PUMP_RES_STATELESS_RESET)
-        ch_stateless_reset(ch);
-    else if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL)
-        /*
-         * We don't care about transient failure, but permanent failure means we
-         * should tear down the connection as though a protocol violation
-         * occurred. Skip straight to the Terminating state as there is no point
-         * trying to send CONNECTION_CLOSE frames if the network BIO is not
-         * operating correctly.
-         */
-        ch_raise_net_error(ch);
-}
-
 /* Check incoming forged packet limit and terminate connection if needed. */
 static void ch_rx_check_forged_pkt_limit(QUIC_CHANNEL *ch)
 {
@@ -2508,7 +2473,7 @@ static int ch_tx(QUIC_CHANNEL *ch)
     case QTX_FLUSH_NET_RES_PERMANENT_FAIL:
     default:
         /* Permanent underlying network BIO, start terminating. */
-        ch_raise_net_error(ch);
+        ossl_quic_port_raise_net_error(ch->port);
         break;
     }
 
@@ -2571,91 +2536,14 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)
  * =======================================
  */
 
-/* Determines whether we can support a given poll descriptor. */
-static int validate_poll_descriptor(const BIO_POLL_DESCRIPTOR *d)
-{
-    if (d->type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD && d->value.fd < 0) {
-        ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
-        return 0;
-    }
-
-    return 1;
-}
-
-BIO *ossl_quic_channel_get_net_rbio(QUIC_CHANNEL *ch)
-{
-    return ch->net_rbio;
-}
-
-BIO *ossl_quic_channel_get_net_wbio(QUIC_CHANNEL *ch)
-{
-    return ch->net_wbio;
-}
-
-static int ch_update_poll_desc(QUIC_CHANNEL *ch, BIO *net_bio, int for_write)
-{
-    BIO_POLL_DESCRIPTOR d = {0};
-
-    if (net_bio == NULL
-        || (!for_write && !BIO_get_rpoll_descriptor(net_bio, &d))
-        || (for_write && !BIO_get_wpoll_descriptor(net_bio, &d)))
-        /* Non-pollable BIO */
-        d.type = BIO_POLL_DESCRIPTOR_TYPE_NONE;
-
-    if (!validate_poll_descriptor(&d))
-        return 0;
-
-    if (for_write)
-        ossl_quic_reactor_set_poll_w(&ch->rtor, &d);
-    else
-        ossl_quic_reactor_set_poll_r(&ch->rtor, &d);
-
-    return 1;
-}
-
-int ossl_quic_channel_update_poll_descriptors(QUIC_CHANNEL *ch)
-{
-    int ok = 1;
-
-    if (!ch_update_poll_desc(ch, ch->net_rbio, /*for_write=*/0))
-        ok = 0;
-
-    if (!ch_update_poll_desc(ch, ch->net_wbio, /*for_write=*/1))
-        ok = 0;
-
-    return ok;
-}
-
-/*
- * QUIC_CHANNEL does not ref any BIO it is provided with, nor is any ref
- * transferred to it. The caller (i.e., QUIC_CONNECTION) is responsible for
- * ensuring the BIO lasts until the channel is freed or the BIO is switched out
- * for another BIO by a subsequent successful call to this function.
- */
 int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio)
 {
-    if (ch->net_rbio == net_rbio)
-        return 1;
-
-    if (!ch_update_poll_desc(ch, net_rbio, /*for_write=*/0))
-        return 0;
-
-    ossl_quic_demux_set_bio(ch->port->demux, net_rbio);
-    ch->net_rbio = net_rbio;
-    return 1;
+    return ossl_quic_port_set_net_rbio(ch->port, net_rbio);
 }
 
 int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio)
 {
-    if (ch->net_wbio == net_wbio)
-        return 1;
-
-    if (!ch_update_poll_desc(ch, net_wbio, /*for_write=*/1))
-        return 0;
-
-    ossl_qtx_set_bio(ch->qtx, net_wbio);
-    ch->net_wbio = net_wbio;
-    return 1;
+    return ossl_quic_port_set_net_wbio(ch->port, net_wbio);
 }
 
 /*
@@ -2695,7 +2583,7 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch)
     if (!ch_tick_tls(ch, /*channel_only=*/0))
         return 0;
 
-    ossl_quic_reactor_tick(&ch->rtor, 0); /* best effort */
+    ossl_quic_reactor_tick(ossl_quic_port_get0_reactor(ch->port), 0); /* best effort */
     return 1;
 }
 
@@ -3199,7 +3087,7 @@ static void ch_save_err_state(QUIC_CHANNEL *ch)
     OSSL_ERR_STATE_save(ch->err_state);
 }
 
-static void ch_stateless_reset(QUIC_CHANNEL *ch)
+static void ossl_unused ch_stateless_reset(QUIC_CHANNEL *ch)
 {
     QUIC_TERMINATE_CAUSE tcause = {0};
 
@@ -3207,7 +3095,7 @@ static void ch_stateless_reset(QUIC_CHANNEL *ch)
     ch_start_terminating(ch, &tcause, 1);
 }
 
-static void ch_raise_net_error(QUIC_CHANNEL *ch)
+void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch)
 {
     QUIC_TERMINATE_CAUSE tcause = {0};
 
@@ -3698,11 +3586,6 @@ int ossl_quic_channel_ping(QUIC_CHANNEL *ch)
     return 1;
 }
 
-void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit)
-{
-    ch->inhibit_tick = (inhibit != 0);
-}
-
 uint16_t ossl_quic_channel_get_diag_num_rx_ack(QUIC_CHANNEL *ch)
 {
     return ch->diag_num_rx_ack;
index e2aea16f685a8eb067fb81b73025ef9572efcf24..dafe03fe8a299146824a93abd5cc4ac649481eb8 100644 (file)
@@ -58,15 +58,9 @@ struct quic_channel_st {
      */
     unsigned char                   *local_transport_params;
 
-    /* Asynchronous I/O reactor. */
-    QUIC_REACTOR                    rtor;
-
     /* Our current L4 peer address, if any. */
     BIO_ADDR                        cur_peer_addr;
 
-    /* Network-side read and write BIOs. */
-    BIO                             *net_rbio, *net_wbio;
-
     /*
      * Subcomponents of the connection. All of these components are instantiated
      * and owned by us.
@@ -442,9 +436,6 @@ struct quic_channel_st {
      */
     unsigned int                    protocol_error                      : 1;
 
-    /* Inhibit tick for testing purposes? */
-    unsigned int                    inhibit_tick                        : 1;
-
     /* Are we using addressed mode? */
     unsigned int                    addressed_mode                      : 1;
 
index d1138f89f5c77314bac427ef02a47c24da209e6b..751d5b846a1b72b44666b38ae70ea9325cbc5c5a 100644 (file)
@@ -64,7 +64,7 @@ static int block_until_pred(QUIC_CONNECTION *qc,
      * Any attempt to block auto-disables tick inhibition as otherwise we will
      * hang around forever.
      */
-    ossl_quic_channel_set_inhibit_tick(qc->ch, 0);
+    ossl_quic_port_set_inhibit_tick(qc->port, 0);
 
     rtor = ossl_quic_channel_get_reactor(qc->ch);
     return ossl_quic_reactor_block_until_pred(rtor, pred, pred_arg, flags,
@@ -856,7 +856,7 @@ static int qc_can_support_blocking_cached(QUIC_CONNECTION *qc)
 
 static void qc_update_can_support_blocking(QUIC_CONNECTION *qc)
 {
-    ossl_quic_channel_update_poll_descriptors(qc->ch); /* best effort */
+    ossl_quic_port_update_poll_descriptors(qc->port); /* best effort */
 }
 
 static void qc_update_blocking_mode(QUIC_CONNECTION *qc)
index 5c5cde8ecd8b9dc9f5945a80d405c87704a9593b..ee4b2900e05830a5eed8d32b00e8b1cef2153d3a 100644 (file)
@@ -24,6 +24,7 @@ static void port_cleanup(QUIC_PORT *port);
 static OSSL_TIME get_time(void *arg);
 static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
 static void port_default_packet_handler(QUIC_URXE *e, void *arg);
+static void port_rx_pre(QUIC_PORT *port);
 
 DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL);
 
@@ -217,13 +218,17 @@ int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio)
 
 int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio)
 {
+    QUIC_CHANNEL *ch;
+
     if (port->net_wbio == net_wbio)
         return 1;
 
     if (!port_update_poll_desc(port, net_wbio, /*for_write=*/1))
         return 0;
 
-    //ossl_qtx_set_bio(port->qtx, net_wbio);
+    LIST_FOREACH(ch, ch, &port->channel_list)
+        ossl_qtx_set_bio(ch->qtx, net_wbio);
+
     port->net_wbio = net_wbio;
     return 1;
 }
@@ -301,7 +306,49 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls)
  */
 static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
 {
-    /* TODO */
+    QUIC_PORT *port = arg;
+    QUIC_CHANNEL *ch;
+
+    res->net_read_desired   = 0;
+    res->net_write_desired  = 0;
+    res->tick_deadline      = ossl_time_infinite();
+
+    if (!port->inhibit_tick) {
+        /* Handle any incoming data from network. */
+        port_rx_pre(port);
+
+        /* Iterate through all channels and service them. */
+        LIST_FOREACH(ch, ch, &port->channel_list) {
+            QUIC_TICK_RESULT subr = {0};
+
+            ossl_quic_channel_subtick(ch, &subr, flags);
+            ossl_quic_tick_result_merge_into(res, &subr);
+        }
+    }
+}
+
+/* Process incoming datagrams, if any. */
+static void port_rx_pre(QUIC_PORT *port)
+{
+    int ret;
+
+    // TODO !have_sent_any_pkt
+
+    /*
+     * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams
+     * to the appropriate QRX instances.
+     */
+    ret = ossl_quic_demux_pump(port->demux);
+    // TODO: handle ret, stateless reset
+
+    if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL)
+        /*
+         * We don't care about transient failure, but permanent failure means we
+         * should tear down the port. All connections skip straight to the
+         * Terminated state as there is no point trying to send CONNECTION_CLOSE
+         * frames if the network BIO is not operating correctly.
+         */
+        ossl_quic_port_raise_net_error(port);
 }
 
 /*
@@ -336,9 +383,17 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg)
     QUIC_PKT_HDR hdr;
     QUIC_CHANNEL *new_ch = NULL;
 
+    // TODO review this
     if (port->tserver_ch == NULL)
         goto undesirable;
 
+    // TODO allow_incoming
+    //if (!ossl_assert(ch->is_server))
+    //    goto undesirable;
+
+    //TODO if (ch->state != QUIC_CHANNEL_STATE_IDLE)
+    //    goto undesirable;
+
     /*
      * We have got a packet for an unknown DCID. This might be an attempt to
      * open a new connection.
@@ -395,3 +450,18 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg)
 undesirable:
     ossl_quic_demux_release_urxe(port->demux, e);
 }
+
+void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit)
+{
+    port->inhibit_tick = (inhibit != 0);
+}
+
+void ossl_quic_port_raise_net_error(QUIC_PORT *port)
+{
+    QUIC_CHANNEL *ch;
+
+    // TODO fsm
+
+    LIST_FOREACH(ch, ch, &port->channel_list)
+        ossl_quic_channel_raise_net_error(ch);
+}
index ff109365aaf8b6b8423eeea9af9848148218393a..ad6638eb2f02a5d4d0d7f50f2d71dfdcf8b1d0cc 100644 (file)
@@ -59,6 +59,9 @@ struct quic_port_st {
 
     /* Is this port created to support multiple connections? */
     unsigned int                    is_multi_conn                   : 1;
+
+    /* Inhibit tick for testing purposes? */
+    unsigned int                    inhibit_tick                    : 1;
 };
 
 # endif
index d0560bb04186ece2b50bf6143bb3ef9213dbf3ab..604c2f986b813751929f2d242af1e810d0f12856 100644 (file)
@@ -14,6 +14,7 @@
 #include "internal/quic_ssl.h"
 #include "internal/quic_error.h"
 #include "internal/quic_stream_map.h"
+#include "internal/quic_port.h"
 #include "testutil.h"
 #include "helpers/quictestlib.h"
 #if defined(OPENSSL_THREADS)
@@ -1594,7 +1595,7 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
                 QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn);
                 SSL_SHUTDOWN_EX_ARGS args = {0};
 
-                ossl_quic_channel_set_inhibit_tick(ch, 0);
+                ossl_quic_port_set_inhibit_tick(ossl_quic_channel_get0_port(ch), 0);
 
                 if (!TEST_ptr(c_tgt))
                     goto out;
@@ -1918,7 +1919,8 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
             {
                 QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn);
 
-                ossl_quic_channel_set_inhibit_tick(ch, op->arg1);
+                ossl_quic_port_set_inhibit_tick(ossl_quic_channel_get0_port(ch),
+                                                op->arg1);
             }
             break;