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