aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorNikolas Gauder <[email protected]>2026-10-21 18:40:34 +0200
committerTomas Mraz <[email protected]>2026-10-23 14:53:45 +0200
commita87db42e4647d36fb82464d9493145ccc9bd21ed (patch)
tree67e93d9b374afed84aee71212c44c8fee7c4d068 /test
parentdoc: RAND(7): a restore from a saved image is not detected; reseed after it (diff)
downloadopenssl-a87db42e4647d36fb82464d9493145ccc9bd21ed.tar.gz
openssl-a87db42e4647d36fb82464d9493145ccc9bd21ed.zip
QUIC: release pseudo-lost packets from the congestion controller
On a Retry, and after version negotiation, the client marks Initial packets it has sent as pseudo-lost, so that their CRYPTO data is sent again. The ACK manager then stops counting them as in flight, but on purpose does not report them to the congestion controller as lost, since the network lost nothing. The congestion controller is not told about them at all, so NewReno kept counting their bytes as in flight for the rest of the connection, and allowed that much less to be sent. Release them with on_data_invalidated(), as when a packet number space is discarded. The congestion window is left alone. This follows the approach proposed in #33099. Fixes: 90699176b074 "QUIC CC: Major revisions to CC abstract interface" Fixes #33079 Assisted-by: Claude:claude-opus-5-5 Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Saša Nedvědický <[email protected]> Merge-date: Fri Oct 23 12:53:54 2026 Merged-from: https://github.com/openssl/openssl/pull/33298
Diffstat (limited to 'test')
-rw-r--r--test/quic_ackm_test.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/test/quic_ackm_test.c b/test/quic_ackm_test.c
index 79fa51b99f5..13c35dcb293 100644
--- a/test/quic_ackm_test.c
+++ b/test/quic_ackm_test.c
@@ -1138,6 +1138,101 @@ err:
}
/*
+ * Pseudo-loss
+ * ******************************************************************
+ */
+
+/*
+ * Pseudo-lost packets (e.g. the Initial packets of a ClientHello sent before a
+ * Retry) are no longer in flight, so the congestion controller must stop
+ * counting them. They were not lost on the network, so the congestion window
+ * must not shrink.
+ */
+static int test_tx_pseudo_loss(void)
+{
+ int testresult = 0, have_statm = 0;
+ OSSL_STATM statm;
+ OSSL_CC_DATA *ccdata = NULL;
+ OSSL_ACKM *ackm = NULL;
+ OSSL_ACKM_TX_PKT *tx[2] = { NULL, NULL };
+ struct pkt_info info[2] = { { 0 } };
+ OSSL_PARAM params[3], *p = params;
+ uint64_t cwnd = 0, bytes_in_flight = 0, init_cwnd;
+ size_t i;
+
+ fake_time = TIME_BASE;
+
+ if (!TEST_int_eq(ossl_statm_init(&statm), 1))
+ goto err;
+
+ have_statm = 1;
+
+ *p++ = OSSL_PARAM_construct_uint64(OSSL_CC_OPTION_CUR_BYTES_IN_FLIGHT,
+ &bytes_in_flight);
+ *p++ = OSSL_PARAM_construct_uint64(OSSL_CC_OPTION_CUR_CWND_SIZE,
+ &cwnd);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ccdata = ossl_cc_newreno_method.new(fake_now, NULL);
+ if (!TEST_ptr(ccdata)
+ || !TEST_true(ossl_cc_newreno_method.bind_diagnostics(ccdata, params)))
+ goto err;
+
+ ackm = ossl_ackm_new(fake_now, NULL, &statm,
+ &ossl_cc_newreno_method, ccdata,
+ /* is_server */ 0);
+ if (!TEST_ptr(ackm))
+ goto err;
+
+ init_cwnd = cwnd;
+
+ for (i = 0; i < OSSL_NELEM(tx); ++i) {
+ if (!TEST_ptr(tx[i] = OPENSSL_zalloc(sizeof(*tx[i]))))
+ goto err;
+
+ tx[i]->pkt_num = i;
+ tx[i]->pkt_space = QUIC_PN_SPACE_INITIAL;
+ tx[i]->is_inflight = 1;
+ tx[i]->is_ack_eliciting = 1;
+ tx[i]->num_bytes = 1200;
+ tx[i]->largest_acked = QUIC_PN_INVALID;
+ tx[i]->on_lost = on_lost;
+ tx[i]->on_acked = on_acked;
+ tx[i]->on_discarded = on_discarded;
+ tx[i]->cb_arg = &info[i];
+ tx[i]->time = fake_time;
+
+ if (!TEST_int_eq(ossl_ackm_on_tx_packet(ackm, tx[i]), 1))
+ goto err;
+ }
+
+ if (!TEST_uint64_t_eq(bytes_in_flight, 2400))
+ goto err;
+
+ if (!TEST_true(ossl_ackm_mark_packet_pseudo_lost(ackm,
+ QUIC_PN_SPACE_INITIAL, 0))
+ || !TEST_uint64_t_eq(bytes_in_flight, 1200)
+ || !TEST_true(ossl_ackm_mark_packet_pseudo_lost(ackm,
+ QUIC_PN_SPACE_INITIAL, 1))
+ || !TEST_uint64_t_eq(bytes_in_flight, 0)
+ || !TEST_int_eq(info[0].lost, 1)
+ || !TEST_int_eq(info[1].lost, 1)
+ || !TEST_uint64_t_eq(cwnd, init_cwnd))
+ goto err;
+
+ testresult = 1;
+err:
+ ossl_ackm_free(ackm);
+ if (ccdata != NULL)
+ ossl_cc_newreno_method.free(ccdata);
+ if (have_statm)
+ ossl_statm_destroy(&statm);
+ for (i = 0; i < OSSL_NELEM(tx); ++i)
+ OPENSSL_free(tx[i]);
+ return testresult;
+}
+
+/*
* Driver
* ******************************************************************
*/
@@ -1170,5 +1265,6 @@ int setup_tests(void)
OSSL_NELEM(tx_ack_cases) * MODE_NUM * QUIC_PN_SPACE_NUM);
ADD_ALL_TESTS(test_tx_ack_time_script, OSSL_NELEM(tx_ack_time_scripts));
ADD_ALL_TESTS(test_rx_ack, OSSL_NELEM(rx_test_scripts) * QUIC_PN_SPACE_NUM);
+ ADD_TEST(test_tx_pseudo_loss);
return 1;
}