xref: /freebsd/crypto/openssl/test/quic_ackm_test.c (revision 78e936b2d0b5e6554425009199be31e76bc67c10)
1 /*
2  * Copyright 2022-2026 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9 
10 #include "testutil.h"
11 #include <openssl/ssl.h>
12 #include "internal/quic_ackm.h"
13 #include "internal/quic_cc.h"
14 #include "internal/quic_vlint.h"
15 
16 static OSSL_TIME fake_time = { 0 };
17 
18 #define TIME_BASE (ossl_ticks2time(123 * OSSL_TIME_SECOND))
19 
fake_now(void * arg)20 static OSSL_TIME fake_now(void *arg)
21 {
22     return fake_time;
23 }
24 
25 struct pkt_info {
26     OSSL_ACKM_TX_PKT *pkt;
27     int lost, acked, discarded;
28 };
29 
on_lost(void * arg)30 static void on_lost(void *arg)
31 {
32     struct pkt_info *info = arg;
33     ++info->lost;
34 }
35 
on_acked(void * arg)36 static void on_acked(void *arg)
37 {
38     struct pkt_info *info = arg;
39     ++info->acked;
40 }
41 
on_discarded(void * arg)42 static void on_discarded(void *arg)
43 {
44     struct pkt_info *info = arg;
45     ++info->discarded;
46 }
47 
48 struct helper {
49     OSSL_ACKM *ackm;
50     struct pkt_info *pkts;
51     size_t num_pkts;
52     OSSL_CC_DATA *ccdata;
53     OSSL_STATM statm;
54     int have_statm;
55 };
56 
helper_destroy(struct helper * h)57 static void helper_destroy(struct helper *h)
58 {
59     size_t i;
60 
61     if (h->ackm != NULL) {
62         ossl_ackm_free(h->ackm);
63         h->ackm = NULL;
64     }
65 
66     if (h->ccdata != NULL) {
67         ossl_cc_dummy_method.free(h->ccdata);
68         h->ccdata = NULL;
69     }
70 
71     if (h->have_statm) {
72         ossl_statm_destroy(&h->statm);
73         h->have_statm = 0;
74     }
75 
76     if (h->pkts != NULL) {
77         for (i = 0; i < h->num_pkts; ++i) {
78             OPENSSL_free(h->pkts[i].pkt);
79             h->pkts[i].pkt = NULL;
80         }
81 
82         OPENSSL_free(h->pkts);
83         h->pkts = NULL;
84     }
85 }
86 
helper_init(struct helper * h,size_t num_pkts)87 static int helper_init(struct helper *h, size_t num_pkts)
88 {
89     int rc = 0;
90 
91     memset(h, 0, sizeof(*h));
92 
93     fake_time = TIME_BASE;
94 
95     /* Initialise statistics tracker. */
96     if (!TEST_int_eq(ossl_statm_init(&h->statm), 1))
97         goto err;
98 
99     h->have_statm = 1;
100 
101     /* Initialise congestion controller. */
102     h->ccdata = ossl_cc_dummy_method.new(fake_now, NULL);
103     if (!TEST_ptr(h->ccdata))
104         goto err;
105 
106     /* Initialise ACK manager. */
107     h->ackm = ossl_ackm_new(fake_now, NULL, &h->statm,
108         &ossl_cc_dummy_method, h->ccdata,
109         /* is_server */ 0);
110     if (!TEST_ptr(h->ackm))
111         goto err;
112 
113     /* Allocate our array of packet information. */
114     h->num_pkts = num_pkts;
115     if (num_pkts > 0) {
116         h->pkts = OPENSSL_zalloc(sizeof(struct pkt_info) * num_pkts);
117         if (!TEST_ptr(h->pkts))
118             goto err;
119     } else {
120         h->pkts = NULL;
121     }
122 
123     rc = 1;
124 err:
125     if (rc == 0)
126         helper_destroy(h);
127 
128     return rc;
129 }
130 
131 static const QUIC_PN linear_20[] = {
132     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
133 };
134 
135 static const QUIC_PN high_linear_20[] = {
136     1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008,
137     1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017,
138     1018, 1019
139 };
140 
141 /*
142  * TX ACK (Packet Threshold) Test Cases
143  * ******************************************************************
144  */
145 struct tx_ack_test_case {
146     const QUIC_PN *pn_table;
147     size_t pn_table_len;
148     const OSSL_QUIC_ACK_RANGE *ack_ranges;
149     size_t num_ack_ranges;
150     const char *expect_ack; /* 1=ack, 2=lost, 4=discarded */
151     int expect_reject; /* if nonzero the ACK must be rejected (returns 0) */
152 };
153 
154 #define DEFINE_TX_ACK_CASE(n, pntable)                       \
155     static const struct tx_ack_test_case tx_ack_case_##n = { \
156         (pntable), OSSL_NELEM(pntable),                      \
157         tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n),      \
158         tx_ack_expect_##n, 0                                 \
159     }
160 
161 /*
162  * As DEFINE_TX_ACK_CASE, but the ACK acknowledges a packet number that was
163  * never sent and so must be rejected by ossl_ackm_on_rx_ack_frame()
164  * (RFC 9000 s. 13.1).
165  */
166 #define DEFINE_TX_ACK_CASE_REJECT(n, pntable)                \
167     static const struct tx_ack_test_case tx_ack_case_##n = { \
168         (pntable), OSSL_NELEM(pntable),                      \
169         tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n),      \
170         tx_ack_expect_##n, 1                                 \
171     }
172 
173 /* One range, partial coverage of space */
174 static const OSSL_QUIC_ACK_RANGE tx_ack_range_1[] = {
175     { 0, 10 },
176 };
177 static const char tx_ack_expect_1[] = {
178     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
179 };
180 DEFINE_TX_ACK_CASE(1, linear_20);
181 
182 /* Two ranges, partial coverage of space, overlapping by 1 */
183 static const OSSL_QUIC_ACK_RANGE tx_ack_range_2[] = {
184     { 5, 10 }, { 0, 5 }
185 };
186 static const char tx_ack_expect_2[] = {
187     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
188 };
189 DEFINE_TX_ACK_CASE(2, linear_20);
190 
191 /* Two ranges, partial coverage of space, together contiguous */
192 static const OSSL_QUIC_ACK_RANGE tx_ack_range_3[] = {
193     { 6, 10 }, { 0, 5 }
194 };
195 static const char tx_ack_expect_3[] = {
196     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
197 };
198 DEFINE_TX_ACK_CASE(3, linear_20);
199 
200 /*
201  * Two ranges, partial coverage of space, non-contiguous by 1
202  * Causes inferred loss due to packet threshold being exceeded.
203  */
204 static const OSSL_QUIC_ACK_RANGE tx_ack_range_4[] = {
205     { 7, 10 }, { 0, 5 }
206 };
207 static const char tx_ack_expect_4[] = {
208     1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
209 };
210 DEFINE_TX_ACK_CASE(4, linear_20);
211 
212 /*
213  * Two ranges, partial coverage of space, non-contiguous by 2
214  * Causes inferred loss due to packet threshold being exceeded.
215  */
216 static const OSSL_QUIC_ACK_RANGE tx_ack_range_5[] = {
217     { 7, 10 }, { 0, 4 }
218 };
219 static const char tx_ack_expect_5[] = {
220     1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
221 };
222 DEFINE_TX_ACK_CASE(5, linear_20);
223 
224 /* One range covering the whole space (0..19, highest sent PN is 19): all acked */
225 static const OSSL_QUIC_ACK_RANGE tx_ack_range_6[] = {
226     { 0, 19 },
227 };
228 static const char tx_ack_expect_6[] = {
229     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
230 };
231 DEFINE_TX_ACK_CASE(6, linear_20);
232 
233 /* One range above the highest sent PN (30 > 19): ACK rejected */
234 static const OSSL_QUIC_ACK_RANGE tx_ack_range_7[] = {
235     { 0, 30 },
236 };
237 static const char tx_ack_expect_7[] = {
238     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
239 };
240 DEFINE_TX_ACK_CASE_REJECT(7, linear_20);
241 
242 /* One range entirely above the sent PNs (21..30): ACK rejected */
243 static const OSSL_QUIC_ACK_RANGE tx_ack_range_8[] = {
244     { 21, 30 },
245 };
246 static const char tx_ack_expect_8[] = {
247     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
248 };
249 DEFINE_TX_ACK_CASE_REJECT(8, linear_20);
250 
251 /* One range, covering nothing (too low) */
252 static const OSSL_QUIC_ACK_RANGE tx_ack_range_9[] = {
253     { 0, 999 },
254 };
255 static const char tx_ack_expect_9[] = {
256     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
257 };
258 DEFINE_TX_ACK_CASE(9, high_linear_20);
259 
260 /* One single packet at start of PN set */
261 static const OSSL_QUIC_ACK_RANGE tx_ack_range_10[] = {
262     { 0, 0 },
263 };
264 static const char tx_ack_expect_10[] = {
265     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
266 };
267 DEFINE_TX_ACK_CASE(10, linear_20);
268 
269 /*
270  * One single packet in middle of PN set
271  * Causes inferred loss of one packet due to packet threshold being exceeded,
272  * but several other previous packets survive as they are under the threshold.
273  */
274 static const OSSL_QUIC_ACK_RANGE tx_ack_range_11[] = {
275     { 3, 3 },
276 };
277 static const char tx_ack_expect_11[] = {
278     2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
279 };
280 DEFINE_TX_ACK_CASE(11, linear_20);
281 
282 /*
283  * One single packet at end of PN set
284  * Causes inferred loss due to packet threshold being exceeded.
285  */
286 static const OSSL_QUIC_ACK_RANGE tx_ack_range_12[] = {
287     { 19, 19 },
288 };
289 static const char tx_ack_expect_12[] = {
290     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1
291 };
292 DEFINE_TX_ACK_CASE(12, linear_20);
293 
294 /*
295  * Mixed straddling
296  * Causes inferred loss due to packet threshold being exceeded.
297  */
298 static const OSSL_QUIC_ACK_RANGE tx_ack_range_13[] = {
299     { 1008, 1008 }, { 1004, 1005 }, { 1001, 1002 }
300 };
301 static const char tx_ack_expect_13[] = {
302     2, 1, 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
303 };
304 DEFINE_TX_ACK_CASE(13, high_linear_20);
305 
306 /*
307  * Largest range claims the maximum PN (2**62 - 1, never sent) plus a second
308  * range over real packets so loss detection would otherwise run. ACK rejected;
309  * otherwise largest_acked_pkt pins at the maximum and every in-flight packet is
310  * declared lost.
311  */
312 static const OSSL_QUIC_ACK_RANGE tx_ack_range_14[] = {
313     { OSSL_QUIC_VLINT_MAX, OSSL_QUIC_VLINT_MAX }, { 15, 19 }
314 };
315 static const char tx_ack_expect_14[] = {
316     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
317 };
318 DEFINE_TX_ACK_CASE_REJECT(14, linear_20);
319 
320 static const struct tx_ack_test_case *const tx_ack_cases[] = {
321     &tx_ack_case_1,
322     &tx_ack_case_2,
323     &tx_ack_case_3,
324     &tx_ack_case_4,
325     &tx_ack_case_5,
326     &tx_ack_case_6,
327     &tx_ack_case_7,
328     &tx_ack_case_8,
329     &tx_ack_case_9,
330     &tx_ack_case_10,
331     &tx_ack_case_11,
332     &tx_ack_case_12,
333     &tx_ack_case_13,
334     &tx_ack_case_14,
335 };
336 
337 enum {
338     MODE_ACK,
339     MODE_DISCARD,
340     MODE_PTO,
341     MODE_NUM
342 };
343 
test_probe_counts(const OSSL_ACKM_PROBE_INFO * p,uint32_t anti_deadlock_handshake,uint32_t anti_deadlock_initial,uint32_t pto_initial,uint32_t pto_handshake,uint32_t pto_app)344 static int test_probe_counts(const OSSL_ACKM_PROBE_INFO *p,
345     uint32_t anti_deadlock_handshake,
346     uint32_t anti_deadlock_initial,
347     uint32_t pto_initial,
348     uint32_t pto_handshake,
349     uint32_t pto_app)
350 {
351     if (!TEST_uint_eq(p->anti_deadlock_handshake, anti_deadlock_handshake))
352         return 0;
353     if (!TEST_uint_eq(p->anti_deadlock_initial, anti_deadlock_initial))
354         return 0;
355     if (!TEST_uint_eq(p->pto[QUIC_PN_SPACE_INITIAL], pto_initial))
356         return 0;
357     if (!TEST_uint_eq(p->pto[QUIC_PN_SPACE_HANDSHAKE], pto_handshake))
358         return 0;
359     if (!TEST_uint_eq(p->pto[QUIC_PN_SPACE_APP], pto_app))
360         return 0;
361     return 1;
362 }
363 
on_loss_detection_deadline_callback(OSSL_TIME deadline,void * arg)364 static void on_loss_detection_deadline_callback(OSSL_TIME deadline, void *arg)
365 {
366     *(OSSL_TIME *)arg = deadline;
367 }
368 
test_tx_ack_case_actual(int tidx,int space,int mode)369 static int test_tx_ack_case_actual(int tidx, int space, int mode)
370 {
371     int testresult = 0;
372     struct helper h;
373     size_t i;
374     OSSL_ACKM_TX_PKT *tx;
375     const struct tx_ack_test_case *c = tx_ack_cases[tidx];
376     OSSL_QUIC_FRAME_ACK ack = { 0 };
377     OSSL_TIME loss_detection_deadline = ossl_time_zero();
378 
379     /* Cannot discard app space, so skip this */
380     if (mode == MODE_DISCARD && space == QUIC_PN_SPACE_APP) {
381         TEST_skip("skipping test for app space");
382         return 1;
383     }
384 
385     if (!TEST_int_eq(helper_init(&h, c->pn_table_len), 1))
386         goto err;
387 
388     /* Arm callback. */
389     ossl_ackm_set_loss_detection_deadline_callback(h.ackm,
390         on_loss_detection_deadline_callback,
391         &loss_detection_deadline);
392 
393     /* Allocate TX packet structures. */
394     for (i = 0; i < c->pn_table_len; ++i) {
395         h.pkts[i].pkt = tx = OPENSSL_zalloc(sizeof(*tx));
396         if (!TEST_ptr(tx))
397             goto err;
398 
399         tx->pkt_num = c->pn_table[i];
400         tx->pkt_space = space;
401         tx->is_inflight = 1;
402         tx->is_ack_eliciting = 1;
403         tx->num_bytes = 123;
404         tx->largest_acked = QUIC_PN_INVALID;
405         tx->on_lost = on_lost;
406         tx->on_acked = on_acked;
407         tx->on_discarded = on_discarded;
408         tx->cb_arg = &h.pkts[i];
409 
410         tx->time = fake_time;
411 
412         if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1))
413             goto err;
414     }
415 
416     if (mode == MODE_DISCARD) {
417         /* Try discarding. */
418         if (!TEST_int_eq(ossl_ackm_on_pkt_space_discarded(h.ackm, space), 1))
419             goto err;
420 
421         /* Check all discard callbacks were called. */
422         for (i = 0; i < c->pn_table_len; ++i) {
423             if (!TEST_int_eq(h.pkts[i].acked, 0))
424                 goto err;
425             if (!TEST_int_eq(h.pkts[i].lost, 0))
426                 goto err;
427             if (!TEST_int_eq(h.pkts[i].discarded, 1))
428                 goto err;
429         }
430     } else if (mode == MODE_ACK) {
431         /* Try acknowledging. */
432         ack.ack_ranges = (OSSL_QUIC_ACK_RANGE *)c->ack_ranges;
433         ack.num_ack_ranges = c->num_ack_ranges;
434 
435         if (c->expect_reject) {
436             /* ACK of an unsent PN: rejected without touching loss detection. */
437             if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space,
438                                  fake_time),
439                     0))
440                 goto err;
441 
442             for (i = 0; i < c->pn_table_len; ++i) {
443                 if (!TEST_int_eq(h.pkts[i].acked, 0)
444                     || !TEST_int_eq(h.pkts[i].lost, 0)
445                     || !TEST_int_eq(h.pkts[i].discarded, 0))
446                     goto err;
447             }
448 
449             testresult = 1;
450             goto err;
451         }
452 
453         if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space, fake_time), 1))
454             goto err;
455 
456         /* Check correct ranges were acknowledged. */
457         for (i = 0; i < c->pn_table_len; ++i) {
458             if (!TEST_int_eq(h.pkts[i].acked,
459                     (c->expect_ack[i] & 1) != 0 ? 1 : 0))
460                 goto err;
461             if (!TEST_int_eq(h.pkts[i].lost,
462                     (c->expect_ack[i] & 2) != 0 ? 1 : 0))
463                 goto err;
464             if (!TEST_int_eq(h.pkts[i].discarded,
465                     (c->expect_ack[i] & 4) != 0 ? 1 : 0))
466                 goto err;
467         }
468     } else if (mode == MODE_PTO) {
469         OSSL_TIME deadline = ossl_ackm_get_loss_detection_deadline(h.ackm);
470         OSSL_ACKM_PROBE_INFO probe;
471 
472         if (!TEST_int_eq(ossl_time_compare(deadline, loss_detection_deadline), 0))
473             goto err;
474 
475         /* We should have a PTO deadline. */
476         if (!TEST_int_gt(ossl_time_compare(deadline, fake_time), 0))
477             goto err;
478 
479         /* Should not have any probe requests yet. */
480         probe = *ossl_ackm_get0_probe_request(h.ackm);
481         if (!TEST_int_eq(test_probe_counts(&probe, 0, 0, 0, 0, 0), 1))
482             goto err;
483 
484         /*
485          * If in app space, confirm handshake, as this is necessary to enable
486          * app space PTO probe requests.
487          */
488         if (space == QUIC_PN_SPACE_APP)
489             if (!TEST_int_eq(ossl_ackm_on_handshake_confirmed(h.ackm), 1))
490                 goto err;
491 
492         /* Advance to the PTO deadline. */
493         fake_time = ossl_time_add(deadline, ossl_ticks2time(1));
494 
495         if (!TEST_int_eq(ossl_ackm_on_timeout(h.ackm), 1))
496             goto err;
497 
498         /* Should have a probe request. Not cleared by first call. */
499         for (i = 0; i < 3; ++i) {
500             probe = *ossl_ackm_get0_probe_request(h.ackm);
501             if (i > 0)
502                 memset(ossl_ackm_get0_probe_request(h.ackm), 0, sizeof(probe));
503 
504             if (i == 2) {
505                 if (!TEST_int_eq(test_probe_counts(&probe, 0, 0, 0, 0, 0), 1))
506                     goto err;
507             } else {
508                 if (!TEST_int_eq(test_probe_counts(&probe, 0, 0,
509                                      space == QUIC_PN_SPACE_INITIAL,
510                                      space == QUIC_PN_SPACE_HANDSHAKE,
511                                      space == QUIC_PN_SPACE_APP),
512                         1))
513                     goto err;
514             }
515         }
516 
517     } else
518         goto err;
519 
520     testresult = 1;
521 err:
522     helper_destroy(&h);
523     return testresult;
524 }
525 
526 /*
527  * TX ACK (Time Threshold) Test
528  * ******************************************************************
529  */
530 enum {
531     TX_ACK_TIME_OP_END,
532     TX_ACK_TIME_OP_PKT, /* TX packets */
533     TX_ACK_TIME_OP_ACK, /* Synthesise incoming ACK of single PN range */
534     TX_ACK_TIME_OP_EXPECT /* Ack/loss assertion */
535 };
536 
537 struct tx_ack_time_op {
538     int kind;
539     uint64_t time_advance; /* all ops */
540     QUIC_PN pn; /* PKT, ACK */
541     size_t num_pn; /* PKT, ACK */
542     const char *expect; /* 1=ack, 2=lost, 4=discarded */
543 };
544 
545 #define TX_OP_PKT(advance, pn, num_pn) \
546     { TX_ACK_TIME_OP_PKT, (advance) * OSSL_TIME_MS, (pn), (num_pn), NULL },
547 #define TX_OP_ACK(advance, pn, num_pn) \
548     { TX_ACK_TIME_OP_ACK, (advance) * OSSL_TIME_MS, (pn), (num_pn), NULL },
549 #define TX_OP_EXPECT(expect) \
550     { TX_ACK_TIME_OP_EXPECT, 0, 0, 0, (expect) },
551 #define TX_OP_END { TX_ACK_TIME_OP_END }
552 
553 static const char tx_ack_time_script_1_expect[] = {
554     2, 1
555 };
556 
557 static const struct tx_ack_time_op tx_ack_time_script_1[] = {
558     TX_OP_PKT(0, 0, 1)
559         TX_OP_PKT(3600000, 1, 1)
560             TX_OP_ACK(1000, 1, 1)
561                 TX_OP_EXPECT(tx_ack_time_script_1_expect)
562                     TX_OP_END
563 };
564 
565 static const struct tx_ack_time_op *const tx_ack_time_scripts[] = {
566     tx_ack_time_script_1,
567 };
568 
test_tx_ack_time_script(int tidx)569 static int test_tx_ack_time_script(int tidx)
570 {
571     int testresult = 0;
572     struct helper h;
573     OSSL_ACKM_TX_PKT *tx = NULL;
574     OSSL_QUIC_FRAME_ACK ack = { 0 };
575     OSSL_QUIC_ACK_RANGE ack_range = { 0 };
576     size_t i, num_pkts = 0, pkt_idx = 0;
577     const struct tx_ack_time_op *script = tx_ack_time_scripts[tidx], *s;
578 
579     /* Calculate number of packets. */
580     for (s = script; s->kind != TX_ACK_TIME_OP_END; ++s)
581         if (s->kind == TX_ACK_TIME_OP_PKT)
582             num_pkts += s->num_pn;
583 
584     /* Initialise ACK manager and packet structures. */
585     if (!TEST_int_eq(helper_init(&h, num_pkts), 1))
586         goto err;
587 
588     for (i = 0; i < num_pkts; ++i) {
589         h.pkts[i].pkt = tx = OPENSSL_zalloc(sizeof(*tx));
590         if (!TEST_ptr(tx))
591             goto err;
592     }
593 
594     /* Run script. */
595     for (s = script; s->kind != TX_ACK_TIME_OP_END; ++s)
596         switch (s->kind) {
597         case TX_ACK_TIME_OP_PKT:
598             for (i = 0; i < s->num_pn; ++i) {
599                 tx = h.pkts[pkt_idx + i].pkt;
600 
601                 tx->pkt_num = s->pn + i;
602                 tx->pkt_space = QUIC_PN_SPACE_INITIAL;
603                 tx->num_bytes = 123;
604                 tx->largest_acked = QUIC_PN_INVALID;
605                 tx->is_inflight = 1;
606                 tx->is_ack_eliciting = 1;
607                 tx->on_lost = on_lost;
608                 tx->on_acked = on_acked;
609                 tx->on_discarded = on_discarded;
610                 tx->cb_arg = &h.pkts[pkt_idx + i];
611 
612                 fake_time = ossl_time_add(fake_time,
613                     ossl_ticks2time(s->time_advance));
614                 tx->time = fake_time;
615 
616                 if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1))
617                     goto err;
618             }
619 
620             pkt_idx += s->num_pn;
621             break;
622 
623         case TX_ACK_TIME_OP_ACK:
624             ack.ack_ranges = &ack_range;
625             ack.num_ack_ranges = 1;
626 
627             ack_range.start = s->pn;
628             ack_range.end = s->pn + s->num_pn - 1;
629 
630             fake_time = ossl_time_add(fake_time,
631                 ossl_ticks2time(s->time_advance));
632 
633             if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack,
634                                  QUIC_PN_SPACE_INITIAL,
635                                  fake_time),
636                     1))
637                 goto err;
638 
639             break;
640 
641         case TX_ACK_TIME_OP_EXPECT:
642             for (i = 0; i < num_pkts; ++i) {
643                 if (!TEST_int_eq(h.pkts[i].acked,
644                         (s->expect[i] & 1) != 0 ? 1 : 0))
645                     goto err;
646                 if (!TEST_int_eq(h.pkts[i].lost,
647                         (s->expect[i] & 2) != 0 ? 1 : 0))
648                     goto err;
649                 if (!TEST_int_eq(h.pkts[i].discarded,
650                         (s->expect[i] & 4) != 0 ? 1 : 0))
651                     goto err;
652             }
653 
654             break;
655         }
656 
657     testresult = 1;
658 err:
659     helper_destroy(&h);
660     return testresult;
661 }
662 
663 /*
664  * RX ACK Test
665  * ******************************************************************
666  */
667 enum {
668     RX_OPK_END,
669     RX_OPK_PKT, /* RX packet */
670     RX_OPK_CHECK_UNPROC, /* check PNs unprocessable */
671     RX_OPK_CHECK_PROC, /* check PNs processable */
672     RX_OPK_CHECK_STATE, /* check is_desired/deadline */
673     RX_OPK_CHECK_ACKS, /* check ACK ranges */
674     RX_OPK_TX, /* TX packet */
675     RX_OPK_RX_ACK, /* RX ACK frame */
676     RX_OPK_SKIP_IF_PN_SPACE /* skip for a given PN space */
677 };
678 
679 struct rx_test_op {
680     int kind;
681     uint64_t time_advance;
682 
683     QUIC_PN pn; /* PKT, CHECK_(UN)PROC, TX, RX_ACK */
684     size_t num_pn; /* PKT, CHECK_(UN)PROC, TX, RX_ACK */
685 
686     char expect_desired; /* CHECK_STATE */
687     char expect_deadline; /* CHECK_STATE */
688 
689     const OSSL_QUIC_ACK_RANGE *ack_ranges; /* CHECK_ACKS */
690     size_t num_ack_ranges; /* CHECK_ACKS */
691 
692     QUIC_PN largest_acked; /* TX */
693 };
694 
695 #define RX_OP_PKT(advance, pn, num_pn)                        \
696     {                                                         \
697         RX_OPK_PKT, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
698         0, 0, NULL, 0, 0                                      \
699     },
700 
701 #define RX_OP_CHECK_UNPROC(advance, pn, num_pn)                        \
702     {                                                                  \
703         RX_OPK_CHECK_UNPROC, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
704         0, 0, NULL, 0, 0                                               \
705     },
706 
707 #define RX_OP_CHECK_PROC(advance, pn, num_pn)                        \
708     {                                                                \
709         RX_OPK_CHECK_PROC, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
710         0, 0, NULL, 0, 0                                             \
711     },
712 
713 #define RX_OP_CHECK_STATE(advance, expect_desired, expect_deadline) \
714     {                                                               \
715         RX_OPK_CHECK_STATE, (advance) * OSSL_TIME_MS, 0, 0,         \
716         (expect_desired), (expect_deadline), NULL, 0, 0             \
717     },
718 
719 #define RX_OP_CHECK_ACKS(advance, ack_ranges)              \
720     {                                                      \
721         RX_OPK_CHECK_ACKS, (advance) * OSSL_TIME_MS, 0, 0, \
722         0, 0, (ack_ranges), OSSL_NELEM(ack_ranges), 0      \
723     },
724 
725 #define RX_OP_CHECK_NO_ACKS(advance)                       \
726     {                                                      \
727         RX_OPK_CHECK_ACKS, (advance) * OSSL_TIME_MS, 0, 0, \
728         0, 0, NULL, 0, 0                                   \
729     },
730 
731 #define RX_OP_TX(advance, pn, largest_acked)          \
732     {                                                 \
733         RX_OPK_TX, (advance) * OSSL_TIME_MS, (pn), 1, \
734         0, 0, NULL, 0, (largest_acked)                \
735     },
736 
737 #define RX_OP_RX_ACK(advance, pn, num_pn)                        \
738     {                                                            \
739         RX_OPK_RX_ACK, (advance) * OSSL_TIME_MS, (pn), (num_pn), \
740         0, 0, NULL, 0, 0                                         \
741     },
742 
743 #define RX_OP_SKIP_IF_PN_SPACE(pn_space)           \
744     {                                              \
745         RX_OPK_SKIP_IF_PN_SPACE, 0, (pn_space), 0, \
746         0, 0, NULL, 0, 0                           \
747     },
748 
749 #define RX_OP_END \
750     { RX_OPK_END }
751 
752 /* RX 1. Simple Test with ACK Desired (Packet Threshold, Exactly) */
753 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_1a[] = {
754     { 0, 1 }
755 };
756 
757 static const struct rx_test_op rx_script_1[] = {
758     RX_OP_CHECK_STATE(0, 0, 0) /* no threshold yet */
759     RX_OP_CHECK_PROC(0, 0, 3)
760 
761         RX_OP_PKT(0, 0, 2) /* two packets, threshold */
762     RX_OP_CHECK_UNPROC(0, 0, 2)
763         RX_OP_CHECK_PROC(0, 2, 1)
764             RX_OP_CHECK_STATE(0, 1, 0) /* threshold met, immediate */
765     RX_OP_CHECK_ACKS(0, rx_ack_ranges_1a)
766 
767     /* At this point we would generate e.g. a packet with an ACK. */
768     RX_OP_TX(0, 0, 1) /* ACKs both */
769     RX_OP_CHECK_ACKS(0, rx_ack_ranges_1a) /* not provably ACKed yet */
770     RX_OP_RX_ACK(0, 0, 1) /* TX'd packet is ACK'd */
771 
772     RX_OP_CHECK_NO_ACKS(0) /* nothing more to ACK */
773     RX_OP_CHECK_UNPROC(0, 0, 2) /* still unprocessable */
774     RX_OP_CHECK_PROC(0, 2, 1) /* still processable */
775 
776     RX_OP_END
777 };
778 
779 /* RX 2. Simple Test with ACK Not Yet Desired (Packet Threshold) (1-RTT) */
780 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_2a[] = {
781     { 0, 0 }
782 };
783 
784 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_2b[] = {
785     { 0, 2 }
786 };
787 
788 static const struct rx_test_op rx_script_2[] = {
789     /*
790      * We skip this for INITIAL/HANDSHAKE and use a separate version
791      * (rx_script_4) for those spaces as those spaces should not delay ACK
792      * generation, so a different RX_OP_CHECK_STATE test is needed.
793      */
794     RX_OP_SKIP_IF_PN_SPACE(QUIC_PN_SPACE_INITIAL)
795         RX_OP_SKIP_IF_PN_SPACE(QUIC_PN_SPACE_HANDSHAKE)
796 
797             RX_OP_CHECK_STATE(0, 0, 0) /* no threshold yet */
798     RX_OP_CHECK_PROC(0, 0, 3)
799 
800     /* First packet always generates an ACK so get it out of the way. */
801     RX_OP_PKT(0, 0, 1)
802         RX_OP_CHECK_UNPROC(0, 0, 1)
803             RX_OP_CHECK_PROC(0, 1, 1)
804                 RX_OP_CHECK_STATE(0, 1, 0) /* first packet always causes ACK */
805     RX_OP_CHECK_ACKS(0, rx_ack_ranges_2a) /* clears packet counter */
806     RX_OP_CHECK_STATE(0, 0, 0) /* desired state should have been cleared */
807 
808     /* Second packet should not cause ACK-desired state */
809     RX_OP_PKT(0, 1, 1) /* just one packet, threshold is 2 */
810     RX_OP_CHECK_UNPROC(0, 0, 2)
811         RX_OP_CHECK_PROC(0, 2, 1)
812             RX_OP_CHECK_STATE(0, 0, 1) /* threshold not yet met, so deadline */
813     /* Don't check ACKs here, as it would reset our threshold counter. */
814 
815     /* Now receive a second packet, triggering the threshold */
816     RX_OP_PKT(0, 2, 1) /* second packet meets threshold */
817     RX_OP_CHECK_UNPROC(0, 0, 3)
818         RX_OP_CHECK_PROC(0, 3, 1)
819             RX_OP_CHECK_STATE(0, 1, 0) /* desired immediately */
820     RX_OP_CHECK_ACKS(0, rx_ack_ranges_2b)
821 
822     /* At this point we would generate e.g. a packet with an ACK. */
823     RX_OP_TX(0, 0, 2) /* ACKs all */
824     RX_OP_CHECK_ACKS(0, rx_ack_ranges_2b) /* not provably ACKed yet */
825     RX_OP_RX_ACK(0, 0, 1) /* TX'd packet is ACK'd */
826 
827     RX_OP_CHECK_NO_ACKS(0) /* nothing more to ACK */
828     RX_OP_CHECK_UNPROC(0, 0, 3) /* still unprocessable */
829     RX_OP_CHECK_PROC(0, 3, 1) /* still processable */
830 
831     RX_OP_END
832 };
833 
834 /* RX 3. Simple Test with ACK Desired (Packet Threshold, Multiple Watermarks) */
835 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_3a[] = {
836     { 0, 0 }
837 };
838 
839 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_3b[] = {
840     { 0, 10 }
841 };
842 
843 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_3c[] = {
844     { 6, 10 }
845 };
846 
847 static const struct rx_test_op rx_script_3[] = {
848     RX_OP_CHECK_STATE(0, 0, 0) /* no threshold yet */
849     RX_OP_CHECK_PROC(0, 0, 11)
850 
851     /* First packet always generates an ACK so get it out of the way. */
852     RX_OP_PKT(0, 0, 1)
853         RX_OP_CHECK_UNPROC(0, 0, 1)
854             RX_OP_CHECK_PROC(0, 1, 1)
855                 RX_OP_CHECK_STATE(0, 1, 0) /* first packet always causes ACK */
856     RX_OP_CHECK_ACKS(0, rx_ack_ranges_3a) /* clears packet counter */
857     RX_OP_CHECK_STATE(0, 0, 0) /* desired state should have been cleared */
858 
859     /* Generate ten packets, exceeding the threshold. */
860     RX_OP_PKT(0, 1, 10) /* ten packets, threshold is 2 */
861     RX_OP_CHECK_UNPROC(0, 0, 11)
862         RX_OP_CHECK_PROC(0, 11, 1)
863             RX_OP_CHECK_STATE(0, 1, 0) /* threshold met, immediate */
864     RX_OP_CHECK_ACKS(0, rx_ack_ranges_3b)
865 
866     /*
867      * Test TX'ing a packet which doesn't ACK anything.
868      */
869     RX_OP_TX(0, 0, QUIC_PN_INVALID)
870         RX_OP_RX_ACK(0, 0, 1)
871 
872     /*
873      * At this point we would generate a packet with an ACK immediately.
874      * TX a packet which when ACKed makes [0,5] provably ACKed.
875      */
876     RX_OP_TX(0, 1, 5)
877         RX_OP_CHECK_ACKS(0, rx_ack_ranges_3b) /* not provably ACKed yet */
878     RX_OP_RX_ACK(0, 1, 1)
879 
880         RX_OP_CHECK_ACKS(0, rx_ack_ranges_3c) /* provably ACKed now gone */
881     RX_OP_CHECK_UNPROC(0, 0, 11) /* still unprocessable */
882     RX_OP_CHECK_PROC(0, 11, 1) /* still processable */
883 
884     /*
885      * Now TX another packet which provably ACKs the rest when ACKed.
886      */
887     RX_OP_TX(0, 2, 10)
888         RX_OP_CHECK_ACKS(0, rx_ack_ranges_3c) /* not provably ACKed yet */
889     RX_OP_RX_ACK(0, 2, 1)
890 
891         RX_OP_CHECK_NO_ACKS(0) /* provably ACKed now gone */
892     RX_OP_CHECK_UNPROC(0, 0, 11) /* still unprocessable */
893     RX_OP_CHECK_PROC(0, 11, 1) /* still processable */
894 
895     RX_OP_END
896 };
897 
898 /*
899  * RX 4. Simple Test with ACK Not Yet Desired (Packet Threshold)
900  * (Initial/Handshake)
901  */
902 static const OSSL_QUIC_ACK_RANGE rx_ack_ranges_4a[] = {
903     { 0, 1 }
904 };
905 
906 static const struct rx_test_op rx_script_4[] = {
907     /* The application PN space is tested in rx_script_2. */
908     RX_OP_SKIP_IF_PN_SPACE(QUIC_PN_SPACE_APP)
909 
910         RX_OP_CHECK_STATE(0, 0, 0) /* no threshold yet */
911     RX_OP_CHECK_PROC(0, 0, 3)
912 
913     /* First packet always generates an ACK so get it out of the way. */
914     RX_OP_PKT(0, 0, 1)
915         RX_OP_CHECK_UNPROC(0, 0, 1)
916             RX_OP_CHECK_PROC(0, 1, 1)
917                 RX_OP_CHECK_STATE(0, 1, 0) /* first packet always causes ACK */
918     RX_OP_CHECK_ACKS(0, rx_ack_ranges_2a) /* clears packet counter */
919     RX_OP_CHECK_STATE(0, 0, 0) /* desired state should have been cleared */
920 
921     /*
922      * Second packet should cause ACK-desired state because we are
923      * INITIAL/HANDSHAKE (RFC 9000 s. 13.2.1)
924      */
925     RX_OP_PKT(0, 1, 1) /* just one packet, threshold is 2 */
926     RX_OP_CHECK_UNPROC(0, 0, 2)
927         RX_OP_CHECK_PROC(0, 2, 1)
928             RX_OP_CHECK_STATE(0, 1, 1)
929                 RX_OP_CHECK_ACKS(0, rx_ack_ranges_4a)
930                     RX_OP_CHECK_STATE(0, 0, 0) /* desired state should have been cleared */
931 
932     /* At this point we would generate e.g. a packet with an ACK. */
933     RX_OP_TX(0, 0, 1) /* ACKs all */
934     RX_OP_CHECK_ACKS(0, rx_ack_ranges_4a) /* not provably ACKed yet */
935     RX_OP_RX_ACK(0, 0, 1) /* TX'd packet is ACK'd */
936 
937     RX_OP_CHECK_NO_ACKS(0) /* nothing more to ACK */
938     RX_OP_CHECK_UNPROC(0, 0, 2) /* still unprocessable */
939     RX_OP_CHECK_PROC(0, 2, 1) /* still processable */
940 
941     RX_OP_END
942 };
943 
944 static const struct rx_test_op *const rx_test_scripts[] = {
945     rx_script_1,
946     rx_script_2,
947     rx_script_3,
948     rx_script_4
949 };
950 
on_ack_deadline_callback(OSSL_TIME deadline,int pkt_space,void * arg)951 static void on_ack_deadline_callback(OSSL_TIME deadline,
952     int pkt_space, void *arg)
953 {
954     ((OSSL_TIME *)arg)[pkt_space] = deadline;
955 }
956 
test_rx_ack_actual(int tidx,int space)957 static int test_rx_ack_actual(int tidx, int space)
958 {
959     int testresult = 0;
960     struct helper h;
961     const struct rx_test_op *script = rx_test_scripts[tidx], *s;
962     size_t i, num_tx = 0, txi = 0;
963     const OSSL_QUIC_FRAME_ACK *ack;
964     OSSL_QUIC_FRAME_ACK rx_ack = { 0 };
965     OSSL_QUIC_ACK_RANGE rx_ack_range = { 0 };
966     struct pkt_info *pkts = NULL;
967     OSSL_ACKM_TX_PKT *txs = NULL, *tx;
968     OSSL_TIME ack_deadline[QUIC_PN_SPACE_NUM];
969     size_t opn = 0;
970 
971     for (i = 0; i < QUIC_PN_SPACE_NUM; ++i)
972         ack_deadline[i] = ossl_time_infinite();
973 
974     /* Initialise ACK manager. */
975     if (!TEST_int_eq(helper_init(&h, 0), 1))
976         goto err;
977 
978     /* Arm callback for testing. */
979     ossl_ackm_set_ack_deadline_callback(h.ackm, on_ack_deadline_callback,
980         ack_deadline);
981 
982     /*
983      * Determine how many packets we are TXing, and therefore how many packet
984      * structures we need.
985      */
986     for (s = script; s->kind != RX_OPK_END; ++s)
987         if (s->kind == RX_OPK_TX)
988             num_tx += s->num_pn;
989 
990     /* Allocate packet information structures. */
991     txs = OPENSSL_zalloc(sizeof(*txs) * num_tx);
992     if (!TEST_ptr(txs))
993         goto err;
994 
995     pkts = OPENSSL_zalloc(sizeof(*pkts) * num_tx);
996     if (!TEST_ptr(pkts))
997         goto err;
998 
999     /* Run script. */
1000     for (s = script; s->kind != RX_OPK_END; ++s, ++opn) {
1001         fake_time = ossl_time_add(fake_time,
1002             ossl_ticks2time(s->time_advance));
1003         switch (s->kind) {
1004         case RX_OPK_PKT:
1005             for (i = 0; i < s->num_pn; ++i) {
1006                 OSSL_ACKM_RX_PKT pkt = { 0 };
1007 
1008                 pkt.pkt_num = s->pn + i;
1009                 pkt.time = fake_time;
1010                 pkt.pkt_space = space;
1011                 pkt.is_ack_eliciting = 1;
1012 
1013                 /* The packet should be processable before we feed it. */
1014                 if (!TEST_int_eq(ossl_ackm_is_rx_pn_processable(h.ackm,
1015                                      pkt.pkt_num,
1016                                      pkt.pkt_space),
1017                         1))
1018                     goto err;
1019 
1020                 if (!TEST_int_eq(ossl_ackm_on_rx_packet(h.ackm, &pkt), 1))
1021                     goto err;
1022             }
1023 
1024             break;
1025 
1026         case RX_OPK_CHECK_UNPROC:
1027         case RX_OPK_CHECK_PROC:
1028             for (i = 0; i < s->num_pn; ++i)
1029                 if (!TEST_int_eq(ossl_ackm_is_rx_pn_processable(h.ackm,
1030                                      s->pn + i, space),
1031                         (s->kind == RX_OPK_CHECK_PROC)))
1032                     goto err;
1033 
1034             break;
1035 
1036         case RX_OPK_CHECK_STATE:
1037             if (!TEST_int_eq(ossl_ackm_is_ack_desired(h.ackm, space),
1038                     s->expect_desired))
1039                 goto err;
1040 
1041             if (!TEST_int_eq(!ossl_time_is_infinite(ossl_ackm_get_ack_deadline(h.ackm, space))
1042                         && !ossl_time_is_zero(ossl_ackm_get_ack_deadline(h.ackm, space)),
1043                     s->expect_deadline))
1044                 goto err;
1045 
1046             for (i = 0; i < QUIC_PN_SPACE_NUM; ++i) {
1047                 if (i != (size_t)space
1048                     && !TEST_true(ossl_time_is_infinite(ossl_ackm_get_ack_deadline(h.ackm, i))))
1049                     goto err;
1050 
1051                 if (!TEST_int_eq(ossl_time_compare(ossl_ackm_get_ack_deadline(h.ackm, i),
1052                                      ack_deadline[i]),
1053                         0))
1054                     goto err;
1055             }
1056 
1057             break;
1058 
1059         case RX_OPK_CHECK_ACKS:
1060             ack = ossl_ackm_get_ack_frame(h.ackm, space);
1061 
1062             /* Should always be able to get an ACK frame. */
1063             if (!TEST_ptr(ack))
1064                 goto err;
1065 
1066             if (!TEST_size_t_eq(ack->num_ack_ranges, s->num_ack_ranges))
1067                 goto err;
1068 
1069             for (i = 0; i < ack->num_ack_ranges; ++i) {
1070                 if (!TEST_uint64_t_eq(ack->ack_ranges[i].start,
1071                         s->ack_ranges[i].start))
1072                     goto err;
1073                 if (!TEST_uint64_t_eq(ack->ack_ranges[i].end,
1074                         s->ack_ranges[i].end))
1075                     goto err;
1076             }
1077 
1078             break;
1079 
1080         case RX_OPK_TX:
1081             pkts[txi].pkt = tx = &txs[txi];
1082 
1083             tx->pkt_num = s->pn;
1084             tx->pkt_space = space;
1085             tx->num_bytes = 123;
1086             tx->largest_acked = s->largest_acked;
1087             tx->is_inflight = 1;
1088             tx->is_ack_eliciting = 1;
1089             tx->on_lost = on_lost;
1090             tx->on_acked = on_acked;
1091             tx->on_discarded = on_discarded;
1092             tx->cb_arg = &pkts[txi];
1093             tx->time = fake_time;
1094 
1095             if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1))
1096                 goto err;
1097 
1098             ++txi;
1099             break;
1100 
1101         case RX_OPK_RX_ACK:
1102             rx_ack.ack_ranges = &rx_ack_range;
1103             rx_ack.num_ack_ranges = 1;
1104 
1105             rx_ack_range.start = s->pn;
1106             rx_ack_range.end = s->pn + s->num_pn - 1;
1107 
1108             if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &rx_ack,
1109                                  space, fake_time),
1110                     1))
1111                 goto err;
1112 
1113             break;
1114 
1115         case RX_OPK_SKIP_IF_PN_SPACE:
1116             if (space == (int)s->pn) {
1117                 testresult = 1;
1118                 goto err;
1119             }
1120 
1121             break;
1122 
1123         default:
1124             goto err;
1125         }
1126     }
1127 
1128     testresult = 1;
1129 err:
1130     if (!testresult)
1131         TEST_error("error in ACKM RX script %d, op %zu", tidx + 1, opn + 1);
1132 
1133     helper_destroy(&h);
1134     OPENSSL_free(pkts);
1135     OPENSSL_free(txs);
1136     return testresult;
1137 }
1138 
1139 /*
1140  * Driver
1141  * ******************************************************************
1142  */
test_tx_ack_case(int idx)1143 static int test_tx_ack_case(int idx)
1144 {
1145     int tidx, space;
1146 
1147     tidx = idx % OSSL_NELEM(tx_ack_cases);
1148     idx /= OSSL_NELEM(tx_ack_cases);
1149 
1150     space = idx % QUIC_PN_SPACE_NUM;
1151     idx /= QUIC_PN_SPACE_NUM;
1152 
1153     return test_tx_ack_case_actual(tidx, space, idx);
1154 }
1155 
test_rx_ack(int idx)1156 static int test_rx_ack(int idx)
1157 {
1158     int tidx;
1159 
1160     tidx = idx % OSSL_NELEM(rx_test_scripts);
1161     idx /= OSSL_NELEM(rx_test_scripts);
1162 
1163     return test_rx_ack_actual(tidx, idx);
1164 }
1165 
setup_tests(void)1166 int setup_tests(void)
1167 {
1168     ADD_ALL_TESTS(test_tx_ack_case,
1169         OSSL_NELEM(tx_ack_cases) * MODE_NUM * QUIC_PN_SPACE_NUM);
1170     ADD_ALL_TESTS(test_tx_ack_time_script, OSSL_NELEM(tx_ack_time_scripts));
1171     ADD_ALL_TESTS(test_rx_ack, OSSL_NELEM(rx_test_scripts) * QUIC_PN_SPACE_NUM);
1172     return 1;
1173 }
1174