2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include <openssl/ssl.h>
12 #include "internal/quic_ackm.h"
13 #include "internal/quic_cc.h"
15 static OSSL_TIME fake_time = {0};
17 #define TIME_BASE (ossl_ticks2time(123 * OSSL_TIME_SECOND))
19 static OSSL_TIME fake_now(void *arg)
25 OSSL_ACKM_TX_PKT *pkt;
26 int lost, acked, discarded;
29 static void on_lost(void *arg)
31 struct pkt_info *info = arg;
35 static void on_acked(void *arg)
37 struct pkt_info *info = arg;
41 static void on_discarded(void *arg)
43 struct pkt_info *info = arg;
49 struct pkt_info *pkts;
56 static void helper_destroy(struct helper *h)
60 if (h->ackm != NULL) {
61 ossl_ackm_free(h->ackm);
65 if (h->ccdata != NULL) {
66 ossl_cc_dummy_method.free(h->ccdata);
71 ossl_statm_destroy(&h->statm);
75 if (h->pkts != NULL) {
76 for (i = 0; i < h->num_pkts; ++i) {
77 OPENSSL_free(h->pkts[i].pkt);
78 h->pkts[i].pkt = NULL;
81 OPENSSL_free(h->pkts);
86 static int helper_init(struct helper *h, size_t num_pkts)
90 memset(h, 0, sizeof(*h));
92 fake_time = TIME_BASE;
94 /* Initialise statistics tracker. */
95 if (!TEST_int_eq(ossl_statm_init(&h->statm), 1))
100 /* Initialise congestion controller. */
101 h->ccdata = ossl_cc_dummy_method.new(NULL, NULL, NULL);
102 if (!TEST_ptr(h->ccdata))
105 /* Initialise ACK manager. */
106 h->ackm = ossl_ackm_new(fake_now, NULL, &h->statm,
107 &ossl_cc_dummy_method, h->ccdata);
108 if (!TEST_ptr(h->ackm))
111 /* Allocate our array of packet information. */
112 h->num_pkts = num_pkts;
114 h->pkts = OPENSSL_zalloc(sizeof(struct pkt_info) * num_pkts);
115 if (!TEST_ptr(h->pkts))
129 static const QUIC_PN linear_20[] = {
130 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
133 static const QUIC_PN high_linear_20[] = {
134 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008,
135 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017,
140 * TX ACK (Packet Threshold) Test Cases
141 * ******************************************************************
143 struct tx_ack_test_case {
144 const QUIC_PN *pn_table;
146 const OSSL_QUIC_ACK_RANGE *ack_ranges;
147 size_t num_ack_ranges;
148 const char *expect_ack; /* 1=ack, 2=lost, 4=discarded */
151 #define DEFINE_TX_ACK_CASE(n, pntable) \
152 static const struct tx_ack_test_case tx_ack_case_##n = { \
153 (pntable), OSSL_NELEM(pntable), \
154 tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n), \
158 /* One range, partial coverage of space */
159 static const OSSL_QUIC_ACK_RANGE tx_ack_range_1[] = {
162 static const char tx_ack_expect_1[] = {
163 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
165 DEFINE_TX_ACK_CASE(1, linear_20);
167 /* Two ranges, partial coverage of space, overlapping by 1 */
168 static const OSSL_QUIC_ACK_RANGE tx_ack_range_2[] = {
171 static const char tx_ack_expect_2[] = {
172 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
174 DEFINE_TX_ACK_CASE(2, linear_20);
176 /* Two ranges, partial coverage of space, together contiguous */
177 static const OSSL_QUIC_ACK_RANGE tx_ack_range_3[] = {
180 static const char tx_ack_expect_3[] = {
181 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
183 DEFINE_TX_ACK_CASE(3, linear_20);
186 * Two ranges, partial coverage of space, non-contiguous by 1
187 * Causes inferred loss due to packet threshold being exceeded.
189 static const OSSL_QUIC_ACK_RANGE tx_ack_range_4[] = {
192 static const char tx_ack_expect_4[] = {
193 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
195 DEFINE_TX_ACK_CASE(4, linear_20);
198 * Two ranges, partial coverage of space, non-contiguous by 2
199 * Causes inferred loss due to packet threshold being exceeded.
201 static const OSSL_QUIC_ACK_RANGE tx_ack_range_5[] = {
204 static const char tx_ack_expect_5[] = {
205 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
207 DEFINE_TX_ACK_CASE(5, linear_20);
209 /* One range, covering entire space */
210 static const OSSL_QUIC_ACK_RANGE tx_ack_range_6[] = {
213 static const char tx_ack_expect_6[] = {
214 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
216 DEFINE_TX_ACK_CASE(6, linear_20);
218 /* One range, covering more space than exists */
219 static const OSSL_QUIC_ACK_RANGE tx_ack_range_7[] = {
222 static const char tx_ack_expect_7[] = {
223 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
225 DEFINE_TX_ACK_CASE(7, linear_20);
227 /* One range, covering nothing (too high) */
228 static const OSSL_QUIC_ACK_RANGE tx_ack_range_8[] = {
231 static const char tx_ack_expect_8[] = {
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
234 DEFINE_TX_ACK_CASE(8, linear_20);
236 /* One range, covering nothing (too low) */
237 static const OSSL_QUIC_ACK_RANGE tx_ack_range_9[] = {
240 static const char tx_ack_expect_9[] = {
241 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
243 DEFINE_TX_ACK_CASE(9, high_linear_20);
245 /* One single packet at start of PN set */
246 static const OSSL_QUIC_ACK_RANGE tx_ack_range_10[] = {
249 static const char tx_ack_expect_10[] = {
250 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
252 DEFINE_TX_ACK_CASE(10, linear_20);
255 * One single packet in middle of PN set
256 * Causes inferred loss of one packet due to packet threshold being exceeded,
257 * but several other previous packets survive as they are under the threshold.
259 static const OSSL_QUIC_ACK_RANGE tx_ack_range_11[] = {
262 static const char tx_ack_expect_11[] = {
263 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
265 DEFINE_TX_ACK_CASE(11, linear_20);
268 * One single packet at end of PN set
269 * Causes inferred loss due to packet threshold being exceeded.
271 static const OSSL_QUIC_ACK_RANGE tx_ack_range_12[] = {
274 static const char tx_ack_expect_12[] = {
275 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1
277 DEFINE_TX_ACK_CASE(12, linear_20);
281 * Causes inferred loss due to packet threshold being exceeded.
283 static const OSSL_QUIC_ACK_RANGE tx_ack_range_13[] = {
284 { 1008, 1008 }, { 1004, 1005 }, { 1001, 1002 }
286 static const char tx_ack_expect_13[] = {
287 2, 1, 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
289 DEFINE_TX_ACK_CASE(13, high_linear_20);
291 static const struct tx_ack_test_case *const tx_ack_cases[] = {
308 MODE_ACK, MODE_DISCARD, MODE_PTO, MODE_NUM
311 static int test_probe_counts(const OSSL_ACKM_PROBE_INFO *p,
312 uint32_t anti_deadlock_handshake,
313 uint32_t anti_deadlock_initial,
314 uint32_t pto_initial,
315 uint32_t pto_handshake,
318 if (!TEST_uint_eq(p->anti_deadlock_handshake, anti_deadlock_handshake))
320 if (!TEST_uint_eq(p->anti_deadlock_initial, anti_deadlock_initial))
322 if (!TEST_uint_eq(p->pto[QUIC_PN_SPACE_INITIAL], pto_initial))
324 if (!TEST_uint_eq(p->pto[QUIC_PN_SPACE_HANDSHAKE], pto_handshake))
326 if (!TEST_uint_eq(p->pto[QUIC_PN_SPACE_APP], pto_app))
331 static void on_loss_detection_deadline_callback(OSSL_TIME deadline, void *arg)
333 *(OSSL_TIME *)arg = deadline;
336 static int test_tx_ack_case_actual(int tidx, int space, int mode)
341 OSSL_ACKM_TX_PKT *tx;
342 const struct tx_ack_test_case *c = tx_ack_cases[tidx];
343 OSSL_QUIC_FRAME_ACK ack = {0};
344 OSSL_TIME loss_detection_deadline = ossl_time_zero();
346 /* Cannot discard app space, so skip this */
347 if (mode == MODE_DISCARD && space == QUIC_PN_SPACE_APP) {
348 TEST_skip("skipping test for app space");
352 if (!TEST_int_eq(helper_init(&h, c->pn_table_len), 1))
356 ossl_ackm_set_loss_detection_deadline_callback(h.ackm,
357 on_loss_detection_deadline_callback,
358 &loss_detection_deadline);
360 /* Allocate TX packet structures. */
361 for (i = 0; i < c->pn_table_len; ++i) {
362 h.pkts[i].pkt = tx = OPENSSL_zalloc(sizeof(*tx));
366 tx->pkt_num = c->pn_table[i];
367 tx->pkt_space = space;
369 tx->is_ack_eliciting = 1;
371 tx->largest_acked = QUIC_PN_INVALID;
372 tx->on_lost = on_lost;
373 tx->on_acked = on_acked;
374 tx->on_discarded = on_discarded;
375 tx->cb_arg = &h.pkts[i];
377 tx->time = fake_time;
379 if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1))
383 if (mode == MODE_DISCARD) {
384 /* Try discarding. */
385 if (!TEST_int_eq(ossl_ackm_on_pkt_space_discarded(h.ackm, space), 1))
388 /* Check all discard callbacks were called. */
389 for (i = 0; i < c->pn_table_len; ++i) {
390 if (!TEST_int_eq(h.pkts[i].acked, 0))
392 if (!TEST_int_eq(h.pkts[i].lost, 0))
394 if (!TEST_int_eq(h.pkts[i].discarded, 1))
397 } else if (mode == MODE_ACK) {
398 /* Try acknowledging. */
399 ack.ack_ranges = (OSSL_QUIC_ACK_RANGE *)c->ack_ranges;
400 ack.num_ack_ranges = c->num_ack_ranges;
401 if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space, fake_time), 1))
404 /* Check correct ranges were acknowledged. */
405 for (i = 0; i < c->pn_table_len; ++i) {
406 if (!TEST_int_eq(h.pkts[i].acked,
407 (c->expect_ack[i] & 1) != 0 ? 1 : 0))
409 if (!TEST_int_eq(h.pkts[i].lost,
410 (c->expect_ack[i] & 2) != 0 ? 1 : 0))
412 if (!TEST_int_eq(h.pkts[i].discarded,
413 (c->expect_ack[i] & 4) != 0 ? 1 : 0))
416 } else if (mode == MODE_PTO) {
417 OSSL_TIME deadline = ossl_ackm_get_loss_detection_deadline(h.ackm);
418 OSSL_ACKM_PROBE_INFO probe = {0};
420 if (!TEST_int_eq(ossl_time_compare(deadline, loss_detection_deadline), 0))
423 /* We should have a PTO deadline. */
424 if (!TEST_int_gt(ossl_time_compare(deadline, fake_time), 0))
427 /* Should not have any probe requests yet. */
428 if (!TEST_int_eq(ossl_ackm_get_probe_request(h.ackm, 0, &probe), 1))
431 if (!TEST_int_eq(test_probe_counts(&probe, 0, 0, 0, 0, 0), 1))
435 * If in app space, confirm handshake, as this is necessary to enable
436 * app space PTO probe requests.
438 if (space == QUIC_PN_SPACE_APP)
439 if (!TEST_int_eq(ossl_ackm_on_handshake_confirmed(h.ackm), 1))
442 /* Advance to the PTO deadline. */
443 fake_time = ossl_time_add(deadline, ossl_ticks2time(1));
445 if (!TEST_int_eq(ossl_ackm_on_timeout(h.ackm), 1))
448 /* Should have a probe request. Not cleared by first call. */
449 for (i = 0; i < 3; ++i) {
450 if (!TEST_int_eq(ossl_ackm_get_probe_request(h.ackm, i > 0, &probe), 1))
454 if (!TEST_int_eq(test_probe_counts(&probe, 0, 0, 0, 0, 0), 1))
457 if (!TEST_int_eq(test_probe_counts(&probe, 0, 0,
458 space == QUIC_PN_SPACE_INITIAL,
459 space == QUIC_PN_SPACE_HANDSHAKE,
460 space == QUIC_PN_SPACE_APP), 1))
475 * TX ACK (Time Threshold) Test
476 * ******************************************************************
480 TX_ACK_TIME_OP_PKT, /* TX packets */
481 TX_ACK_TIME_OP_ACK, /* Synthesise incoming ACK of single PN range */
482 TX_ACK_TIME_OP_EXPECT /* Ack/loss assertion */
485 struct tx_ack_time_op {
487 uint64_t time_advance; /* all ops */
488 QUIC_PN pn; /* PKT, ACK */
489 size_t num_pn; /* PKT, ACK */
490 const char *expect; /* 1=ack, 2=lost, 4=discarded */
493 #define TX_OP_PKT(advance, pn, num_pn) \
494 { TX_ACK_TIME_OP_PKT, (advance) * OSSL_TIME_MS, (pn), (num_pn), NULL },
495 #define TX_OP_ACK(advance, pn, num_pn) \
496 { TX_ACK_TIME_OP_ACK, (advance) * OSSL_TIME_MS, (pn), (num_pn), NULL },
497 #define TX_OP_EXPECT(expect) \
498 { TX_ACK_TIME_OP_EXPECT, 0, 0, 0, (expect) },
499 #define TX_OP_END { TX_ACK_TIME_OP_END }
501 static const char tx_ack_time_script_1_expect[] = {
505 static const struct tx_ack_time_op tx_ack_time_script_1[] = {
507 TX_OP_PKT (3600000, 1, 1)
508 TX_OP_ACK ( 1000, 1, 1)
509 TX_OP_EXPECT(tx_ack_time_script_1_expect)
513 static const struct tx_ack_time_op *const tx_ack_time_scripts[] = {
514 tx_ack_time_script_1,
517 static int test_tx_ack_time_script(int tidx)
521 OSSL_ACKM_TX_PKT *tx = NULL;
522 OSSL_QUIC_FRAME_ACK ack = {0};
523 OSSL_QUIC_ACK_RANGE ack_range = {0};
524 size_t i, num_pkts = 0, pkt_idx = 0;
525 const struct tx_ack_time_op *script = tx_ack_time_scripts[tidx], *s;
527 /* Calculate number of packets. */
528 for (s = script; s->kind != TX_ACK_TIME_OP_END; ++s)
529 if (s->kind == TX_ACK_TIME_OP_PKT)
530 num_pkts += s->num_pn;
532 /* Initialise ACK manager and packet structures. */
533 if (!TEST_int_eq(helper_init(&h, num_pkts), 1))
536 for (i = 0; i < num_pkts; ++i) {
537 h.pkts[i].pkt = tx = OPENSSL_zalloc(sizeof(*tx));
543 for (s = script; s->kind != TX_ACK_TIME_OP_END; ++s)
545 case TX_ACK_TIME_OP_PKT:
546 for (i = 0; i < s->num_pn; ++i) {
547 tx = h.pkts[pkt_idx + i].pkt;
549 tx->pkt_num = s->pn + i;
550 tx->pkt_space = QUIC_PN_SPACE_INITIAL;
552 tx->largest_acked = QUIC_PN_INVALID;
554 tx->is_ack_eliciting = 1;
555 tx->on_lost = on_lost;
556 tx->on_acked = on_acked;
557 tx->on_discarded = on_discarded;
558 tx->cb_arg = &h.pkts[pkt_idx + i];
560 fake_time = ossl_time_add(fake_time,
561 ossl_ticks2time(s->time_advance));
562 tx->time = fake_time;
564 if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1))
568 pkt_idx += s->num_pn;
571 case TX_ACK_TIME_OP_ACK:
572 ack.ack_ranges = &ack_range;
573 ack.num_ack_ranges = 1;
575 ack_range.start = s->pn;
576 ack_range.end = s->pn + s->num_pn;
578 fake_time = ossl_time_add(fake_time,
579 ossl_ticks2time(s->time_advance));
581 if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack,
582 QUIC_PN_SPACE_INITIAL,
588 case TX_ACK_TIME_OP_EXPECT:
589 for (i = 0; i < num_pkts; ++i) {
590 if (!TEST_int_eq(h.pkts[i].acked,
591 (s->expect[i] & 1) != 0 ? 1 : 0))
593 if (!TEST_int_eq(h.pkts[i].lost,
594 (s->expect[i] & 2) != 0 ? 1 : 0))
596 if (!TEST_int_eq(h.pkts[i].discarded,
597 (s->expect[i] & 4) != 0 ? 1 : 0))
612 * ******************************************************************
616 RX_OPK_PKT, /* RX packet */
617 RX_OPK_CHECK_UNPROC, /* check PNs unprocessable */
618 RX_OPK_CHECK_PROC, /* check PNs processable */
619 RX_OPK_CHECK_STATE, /* check is_desired/deadline */
620 RX_OPK_CHECK_ACKS, /* check ACK ranges */
621 RX_OPK_TX, /* TX packet */
622 RX_OPK_RX_ACK /* RX ACK frame */
627 uint64_t time_advance;
629 QUIC_PN pn; /* PKT, CHECK_(UN)PROC, TX, RX_ACK */
630 size_t num_pn; /* PKT, CHECK_(UN)PROC, TX, RX_ACK */
632 char expect_desired; /* CHECK_STATE */
633 char expect_deadline; /* CHECK_STATE */
635 const OSSL_QUIC_ACK_RANGE *ack_ranges; /* CHECK_ACKS */
636 size_t num_ack_ranges; /* CHECK_ACKS */
638 QUIC_PN largest_acked; /* TX */
641 #define RX_OP_PKT(advance, pn, num_pn) \
643 RX_OPK_PKT, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
647 #define RX_OP_CHECK_UNPROC(advance, pn, num_pn) \
649 RX_OPK_CHECK_UNPROC, (advance) * OSSL_TIME_MS, (pn), (num_pn),\
653 #define RX_OP_CHECK_PROC(advance, pn, num_pn) \
655 RX_OPK_CHECK_PROC, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
659 #define RX_OP_CHECK_STATE(advance, expect_desired, expect_deadline) \
661 RX_OPK_CHECK_STATE, (advance) * OSSL_TIME_MS, 0, 0, \
662 (expect_desired), (expect_deadline), NULL, 0, 0 \
665 #define RX_OP_CHECK_ACKS(advance, ack_ranges) \
667 RX_OPK_CHECK_ACKS, (advance) * OSSL_TIME_MS, 0, 0, \
668 0, 0, (ack_ranges), OSSL_NELEM(ack_ranges), 0 \
671 #define RX_OP_CHECK_NO_ACKS(advance) \
673 RX_OPK_CHECK_ACKS, (advance) * OSSL_TIME_MS, 0, 0, \
677 #define RX_OP_TX(advance, pn, largest_acked) \
679 RX_OPK_TX, (advance) * OSSL_TIME_MS, (pn), 1, \
680 0, 0, NULL, 0, (largest_acked) \
683 #define RX_OP_RX_ACK(advance, pn, num_pn) \
685 RX_OPK_RX_ACK, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
692 /* RX 1. Simple Test with ACK Desired (Packet Threshold, Exactly) */
693 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_1a[] = {
697 static const struct rx_test_op rx_script_1[] = {
698 RX_OP_CHECK_STATE (0, 0, 0) /* no threshold yet */
699 RX_OP_CHECK_PROC (0, 0, 3)
701 RX_OP_PKT (0, 0, 2) /* two packets, threshold */
702 RX_OP_CHECK_UNPROC (0, 0, 2)
703 RX_OP_CHECK_PROC (0, 2, 1)
704 RX_OP_CHECK_STATE (0, 1, 0) /* threshold met, immediate */
705 RX_OP_CHECK_ACKS (0, rx_ack_ranges_1a)
707 /* At this point we would generate e.g. a packet with an ACK. */
708 RX_OP_TX (0, 0, 1) /* ACKs both */
709 RX_OP_CHECK_ACKS (0, rx_ack_ranges_1a) /* not provably ACKed yet */
710 RX_OP_RX_ACK (0, 0, 1) /* TX'd packet is ACK'd */
712 RX_OP_CHECK_NO_ACKS (0) /* nothing more to ACK */
713 RX_OP_CHECK_UNPROC (0, 0, 2) /* still unprocessable */
714 RX_OP_CHECK_PROC (0, 2, 1) /* still processable */
719 /* RX 2. Simple Test with ACK Not Yet Desired (Packet Threshold) */
720 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_2a[] = {
724 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_2b[] = {
728 static const struct rx_test_op rx_script_2[] = {
729 RX_OP_CHECK_STATE (0, 0, 0) /* no threshold yet */
730 RX_OP_CHECK_PROC (0, 0, 3)
732 /* First packet always generates an ACK so get it out of the way. */
734 RX_OP_CHECK_UNPROC (0, 0, 1)
735 RX_OP_CHECK_PROC (0, 1, 1)
736 RX_OP_CHECK_STATE (0, 1, 0) /* first packet always causes ACK */
737 RX_OP_CHECK_ACKS (0, rx_ack_ranges_2a) /* clears packet counter */
738 RX_OP_CHECK_STATE (0, 0, 0) /* desired state should have been cleared */
740 /* Second packet should not cause ACK-desired state */
741 RX_OP_PKT (0, 1, 1) /* just one packet, threshold is 2 */
742 RX_OP_CHECK_UNPROC (0, 0, 2)
743 RX_OP_CHECK_PROC (0, 2, 1)
744 RX_OP_CHECK_STATE (0, 0, 1) /* threshold not yet met, so deadline */
745 /* Don't check ACKs here, as it would reset our threshold counter. */
747 /* Now receive a second packet, triggering the threshold */
748 RX_OP_PKT (0, 2, 1) /* second packet meets threshold */
749 RX_OP_CHECK_UNPROC (0, 0, 3)
750 RX_OP_CHECK_PROC (0, 3, 1)
751 RX_OP_CHECK_STATE (0, 1, 0) /* desired immediately */
752 RX_OP_CHECK_ACKS (0, rx_ack_ranges_2b)
754 /* At this point we would generate e.g. a packet with an ACK. */
755 RX_OP_TX (0, 0, 2) /* ACKs all */
756 RX_OP_CHECK_ACKS (0, rx_ack_ranges_2b) /* not provably ACKed yet */
757 RX_OP_RX_ACK (0, 0, 1) /* TX'd packet is ACK'd */
759 RX_OP_CHECK_NO_ACKS (0) /* nothing more to ACK */
760 RX_OP_CHECK_UNPROC (0, 0, 3) /* still unprocessable */
761 RX_OP_CHECK_PROC (0, 3, 1) /* still processable */
766 /* RX 3. Simple Test with ACK Desired (Packet Threshold, Multiple Watermarks) */
767 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_3a[] = {
771 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_3b[] = {
775 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_3c[] = {
779 static const struct rx_test_op rx_script_3[] = {
780 RX_OP_CHECK_STATE (0, 0, 0) /* no threshold yet */
781 RX_OP_CHECK_PROC (0, 0, 11)
783 /* First packet always generates an ACK so get it out of the way. */
785 RX_OP_CHECK_UNPROC (0, 0, 1)
786 RX_OP_CHECK_PROC (0, 1, 1)
787 RX_OP_CHECK_STATE (0, 1, 0) /* first packet always causes ACK */
788 RX_OP_CHECK_ACKS (0, rx_ack_ranges_3a) /* clears packet counter */
789 RX_OP_CHECK_STATE (0, 0, 0) /* desired state should have been cleared */
791 /* Generate ten packets, exceeding the threshold. */
792 RX_OP_PKT (0, 1, 10) /* ten packets, threshold is 2 */
793 RX_OP_CHECK_UNPROC (0, 0, 11)
794 RX_OP_CHECK_PROC (0, 11, 1)
795 RX_OP_CHECK_STATE (0, 1, 0) /* threshold met, immediate */
796 RX_OP_CHECK_ACKS (0, rx_ack_ranges_3b)
799 * Test TX'ing a packet which doesn't ACK anything.
801 RX_OP_TX (0, 0, QUIC_PN_INVALID)
802 RX_OP_RX_ACK (0, 0, 1)
805 * At this point we would generate a packet with an ACK immediately.
806 * TX a packet which when ACKed makes [0,5] provably ACKed.
809 RX_OP_CHECK_ACKS (0, rx_ack_ranges_3b) /* not provably ACKed yet */
810 RX_OP_RX_ACK (0, 1, 1)
812 RX_OP_CHECK_ACKS (0, rx_ack_ranges_3c) /* provably ACKed now gone */
813 RX_OP_CHECK_UNPROC (0, 0, 11) /* still unprocessable */
814 RX_OP_CHECK_PROC (0, 11, 1) /* still processable */
817 * Now TX another packet which provably ACKs the rest when ACKed.
820 RX_OP_CHECK_ACKS (0, rx_ack_ranges_3c) /* not provably ACKed yet */
821 RX_OP_RX_ACK (0, 2, 1)
823 RX_OP_CHECK_NO_ACKS (0) /* provably ACKed now gone */
824 RX_OP_CHECK_UNPROC (0, 0, 11) /* still unprocessable */
825 RX_OP_CHECK_PROC (0, 11, 1) /* still processable */
830 static const struct rx_test_op *const rx_test_scripts[] = {
836 static void on_ack_deadline_callback(OSSL_TIME deadline,
837 int pkt_space, void *arg)
839 ((OSSL_TIME *)arg)[pkt_space] = deadline;
842 static int test_rx_ack_actual(int tidx, int space)
846 const struct rx_test_op *script = rx_test_scripts[tidx], *s;
847 size_t i, num_tx = 0, txi = 0;
848 const OSSL_QUIC_FRAME_ACK *ack;
849 OSSL_QUIC_FRAME_ACK rx_ack = {0};
850 OSSL_QUIC_ACK_RANGE rx_ack_range = {0};
851 struct pkt_info *pkts = NULL;
852 OSSL_ACKM_TX_PKT *txs = NULL, *tx;
853 OSSL_TIME ack_deadline[QUIC_PN_SPACE_NUM];
855 for (i = 0; i < QUIC_PN_SPACE_NUM; ++i)
856 ack_deadline[i] = ossl_time_infinite();
858 /* Initialise ACK manager. */
859 if (!TEST_int_eq(helper_init(&h, 0), 1))
862 /* Arm callback for testing. */
863 ossl_ackm_set_ack_deadline_callback(h.ackm, on_ack_deadline_callback,
867 * Determine how many packets we are TXing, and therefore how many packet
868 * structures we need.
870 for (s = script; s->kind != RX_OPK_END; ++s)
871 if (s->kind == RX_OPK_TX)
874 /* Allocate packet information structures. */
875 txs = OPENSSL_zalloc(sizeof(*txs) * num_tx);
879 pkts = OPENSSL_zalloc(sizeof(*pkts) * num_tx);
884 for (s = script; s->kind != RX_OPK_END; ++s) {
885 fake_time = ossl_time_add(fake_time,
886 ossl_ticks2time(s->time_advance));
889 for (i = 0; i < s->num_pn; ++i) {
890 OSSL_ACKM_RX_PKT pkt = {0};
892 pkt.pkt_num = s->pn + i;
893 pkt.time = fake_time;
894 pkt.pkt_space = space;
895 pkt.is_ack_eliciting = 1;
897 /* The packet should be processable before we feed it. */
898 if (!TEST_int_eq(ossl_ackm_is_rx_pn_processable(h.ackm,
903 if (!TEST_int_eq(ossl_ackm_on_rx_packet(h.ackm, &pkt), 1))
909 case RX_OPK_CHECK_UNPROC:
910 case RX_OPK_CHECK_PROC:
911 for (i = 0; i < s->num_pn; ++i)
912 if (!TEST_int_eq(ossl_ackm_is_rx_pn_processable(h.ackm,
914 (s->kind == RX_OPK_CHECK_PROC)))
919 case RX_OPK_CHECK_STATE:
920 if (!TEST_int_eq(ossl_ackm_is_ack_desired(h.ackm, space),
924 if (!TEST_int_eq(!ossl_time_is_infinite(ossl_ackm_get_ack_deadline(h.ackm, space))
925 && !ossl_time_is_zero(ossl_ackm_get_ack_deadline(h.ackm, space)),
929 for (i = 0; i < QUIC_PN_SPACE_NUM; ++i) {
930 if (i != (size_t)space
931 && !TEST_true(ossl_time_is_infinite(ossl_ackm_get_ack_deadline(h.ackm, i))))
934 if (!TEST_int_eq(ossl_time_compare(ossl_ackm_get_ack_deadline(h.ackm, i),
935 ack_deadline[i]), 0))
941 case RX_OPK_CHECK_ACKS:
942 ack = ossl_ackm_get_ack_frame(h.ackm, space);
944 /* Should always be able to get an ACK frame. */
948 if (!TEST_size_t_eq(ack->num_ack_ranges, s->num_ack_ranges))
951 for (i = 0; i < ack->num_ack_ranges; ++i) {
952 if (!TEST_uint64_t_eq(ack->ack_ranges[i].start,
953 s->ack_ranges[i].start))
955 if (!TEST_uint64_t_eq(ack->ack_ranges[i].end,
956 s->ack_ranges[i].end))
963 pkts[txi].pkt = tx = &txs[txi];
966 tx->pkt_space = space;
968 tx->largest_acked = s->largest_acked;
970 tx->is_ack_eliciting = 1;
971 tx->on_lost = on_lost;
972 tx->on_acked = on_acked;
973 tx->on_discarded = on_discarded;
974 tx->cb_arg = &pkts[txi];
975 tx->time = fake_time;
977 if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1))
984 rx_ack.ack_ranges = &rx_ack_range;
985 rx_ack.num_ack_ranges = 1;
987 rx_ack_range.start = s->pn;
988 rx_ack_range.end = s->pn + s->num_pn - 1;
990 if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &rx_ack,
991 space, fake_time), 1))
1011 * ******************************************************************
1013 static int test_tx_ack_case(int idx)
1017 tidx = idx % OSSL_NELEM(tx_ack_cases);
1018 idx /= OSSL_NELEM(tx_ack_cases);
1020 space = idx % QUIC_PN_SPACE_NUM;
1021 idx /= QUIC_PN_SPACE_NUM;
1023 return test_tx_ack_case_actual(tidx, space, idx);
1026 static int test_rx_ack(int idx)
1030 tidx = idx % OSSL_NELEM(rx_test_scripts);
1031 idx /= OSSL_NELEM(rx_test_scripts);
1033 return test_rx_ack_actual(tidx, idx);
1036 int setup_tests(void)
1038 ADD_ALL_TESTS(test_tx_ack_case,
1039 OSSL_NELEM(tx_ack_cases) * MODE_NUM * QUIC_PN_SPACE_NUM);
1040 ADD_ALL_TESTS(test_tx_ack_time_script, OSSL_NELEM(tx_ack_time_scripts));
1041 ADD_ALL_TESTS(test_rx_ack, OSSL_NELEM(rx_test_scripts) * QUIC_PN_SPACE_NUM);