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