summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-02-21 10:18:59 +0000
committerHugo Landau <hlandau@openssl.org>2023-03-30 11:14:09 +0100
commit3b1ab5a3a0a10798ea9a1547b6cb50182edaeb5b (patch)
tree56bbcf1b2cf13dba60d0bc0d9c7503bc5be696d7 /ssl
parent4648eac53385c5e04bd4ec9dcefe04a74d4221c3 (diff)
Enhance quic_tserver test to fully test thread assisted mode
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20348)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_channel.c59
-rw-r--r--ssl/quic/quic_channel_local.h13
-rw-r--r--ssl/quic/quic_impl.c8
3 files changed, 79 insertions, 1 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index 8ffb5b99e4..2360809295 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -67,6 +67,7 @@ static int ch_discard_el(QUIC_CHANNEL *ch,
uint32_t enc_level);
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_raise_net_error(QUIC_CHANNEL *ch);
static void ch_on_terminating_timeout(QUIC_CHANNEL *ch);
static void ch_start_terminating(QUIC_CHANNEL *ch,
@@ -1305,6 +1306,13 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
if (!ossl_time_is_zero(deadline) && ossl_time_compare(now, deadline) >= 0)
ossl_ackm_on_timeout(ch->ackm);
+ /* If a ping is due, inform TXP. */
+ if (ossl_time_compare(now, ch->ping_deadline) >= 0) {
+ int pn_space = ossl_quic_enc_level_to_pn_space(ch->tx_enc_level);
+
+ ossl_quic_tx_packetiser_schedule_ack_eliciting(ch->txp, pn_space);
+ }
+
/* Write any data to the network due to be sent. */
ch_tx(ch);
@@ -1380,6 +1388,7 @@ static int ch_rx(QUIC_CHANNEL *ch)
ossl_qrx_pkt_release(ch->qrx_pkt);
ch->qrx_pkt = NULL;
+ ch->have_sent_ack_eliciting_since_rx = 0;
handled_any = 1;
}
@@ -1569,6 +1578,8 @@ undesirable:
/* Try to generate packets and if possible, flush them to the network. */
static int ch_tx(QUIC_CHANNEL *ch)
{
+ int sent_ack_eliciting = 0;
+
if (ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING) {
/*
* While closing, only send CONN_CLOSE if we've received more traffic
@@ -1590,10 +1601,24 @@ static int ch_tx(QUIC_CHANNEL *ch)
* flush any queued packets which we already generated.
*/
switch (ossl_quic_tx_packetiser_generate(ch->txp,
- TX_PACKETISER_ARCHETYPE_NORMAL)) {
+ TX_PACKETISER_ARCHETYPE_NORMAL,
+ &sent_ack_eliciting)) {
case TX_PACKETISER_RES_SENT_PKT:
ch->have_sent_any_pkt = 1; /* Packet was sent */
+
+ /*
+ * RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when
+ * sending an ack-eliciting packet if no other ack-eliciting packets
+ * have been sentsince last receiving and processing a packet.'
+ */
+ if (sent_ack_eliciting && !ch->have_sent_ack_eliciting_since_rx) {
+ ch_update_idle(ch);
+ ch->have_sent_ack_eliciting_since_rx = 1;
+ }
+
+ ch_update_ping_deadline(ch);
break;
+
case TX_PACKETISER_RES_NO_PKT:
break; /* No packet was sent */
default:
@@ -1650,6 +1675,14 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)
deadline = ossl_time_min(deadline,
ch->idle_deadline);
+ /*
+ * When do we need to send an ACK-eliciting packet to reset the idle
+ * deadline timer for the peer?
+ */
+ if (!ossl_time_is_infinite(ch->ping_deadline))
+ deadline = ossl_time_min(deadline,
+ ch->ping_deadline);
+
return deadline;
}
@@ -2051,6 +2084,30 @@ static void ch_update_idle(QUIC_CHANNEL *ch)
ossl_ms2time(ch->max_idle_timeout));
}
+/*
+ * Updates our ping deadline, which determines when we next generate a ping if
+ * we don't have any other ACK-eliciting frames to send.
+ */
+static void ch_update_ping_deadline(QUIC_CHANNEL *ch)
+{
+ if (ch->max_idle_timeout > 0) {
+ /*
+ * Maximum amount of time without traffic before we send a PING to
+ * keep the connection open. Usually we use max_idle_timeout/2, but
+ * ensure the period never exceeds 25 seconds to ensure NAT devices
+ * don't have their state time out (RFC 9000 s. 10.1.2).
+ */
+ OSSL_TIME max_span
+ = ossl_time_divide(ossl_ms2time(ch->max_idle_timeout), 2);
+
+ max_span = ossl_time_min(max_span, ossl_ms2time(25000));
+
+ ch->ping_deadline = ossl_time_add(get_time(ch), max_span);
+ } else {
+ ch->ping_deadline = ossl_time_infinite();
+ }
+}
+
/* Called when the idle timeout expires. */
static void ch_on_idle_timeout(QUIC_CHANNEL *ch)
{
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
index 57db9792a9..bd8f95b7a5 100644
--- a/ssl/quic/quic_channel_local.h
+++ b/ssl/quic/quic_channel_local.h
@@ -176,6 +176,12 @@ struct quic_channel_st {
OSSL_TIME idle_deadline;
/*
+ * Deadline at which we should send an ACK-eliciting packet to ensure
+ * idle timeout does not occur.
+ */
+ OSSL_TIME ping_deadline;
+
+ /*
* State tracking. QUIC connection-level state is best represented based on
* whether various things have happened yet or not, rather than as an
* explicit FSM. We do have a coarse state variable which tracks the basic
@@ -270,6 +276,13 @@ struct quic_channel_st {
* Used to determine if we need to check our RX queues again.
*/
unsigned int have_new_rx_secret : 1;
+
+ /*
+ * Have we sent an ack-eliciting packet since the last successful packet
+ * reception? Used to determine when to bump idle timer (see RFC 9000 s.
+ * 10.1).
+ */
+ unsigned int have_sent_ack_eliciting_since_rx : 1;
};
# endif
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index 766a88633a..483b694c7d 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -256,6 +256,14 @@ void ossl_quic_conn_set_override_now_cb(SSL *s,
qc->override_now_cb_arg = now_cb_arg;
}
+void ossl_quic_conn_force_assist_thread_wake(SSL *s)
+{
+ QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(s);
+
+ if (qc->is_thread_assisted && qc->started)
+ ossl_quic_thread_assist_notify_deadline_changed(&qc->thread_assist);
+}
+
/*
* QUIC Front-End I/O API: Network BIO Configuration
* =================================================