1 /* 2 * Copyright 2022-2025 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 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 29 static void on_lost(void *arg) 30 { 31 struct pkt_info *info = arg; 32 ++info->lost; 33 } 34 35 static void on_acked(void *arg) 36 { 37 struct pkt_info *info = arg; 38 ++info->acked; 39 } 40 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 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 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_zalloc(sizeof(struct pkt_info) * num_pkts); 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 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 332 static void on_loss_detection_deadline_callback(OSSL_TIME deadline, void *arg) 333 { 334 *(OSSL_TIME *)arg = deadline; 335 } 336 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 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 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 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 918 for (i = 0; i < QUIC_PN_SPACE_NUM; ++i) 919 ack_deadline[i] = ossl_time_infinite(); 920 921 /* Initialise ACK manager. */ 922 if (!TEST_int_eq(helper_init(&h, 0), 1)) 923 goto err; 924 925 /* Arm callback for testing. */ 926 ossl_ackm_set_ack_deadline_callback(h.ackm, on_ack_deadline_callback, 927 ack_deadline); 928 929 /* 930 * Determine how many packets we are TXing, and therefore how many packet 931 * structures we need. 932 */ 933 for (s = script; s->kind != RX_OPK_END; ++s) 934 if (s->kind == RX_OPK_TX) 935 num_tx += s->num_pn; 936 937 /* Allocate packet information structures. */ 938 txs = OPENSSL_zalloc(sizeof(*txs) * num_tx); 939 if (!TEST_ptr(txs)) 940 goto err; 941 942 pkts = OPENSSL_zalloc(sizeof(*pkts) * num_tx); 943 if (!TEST_ptr(pkts)) 944 goto err; 945 946 /* Run script. */ 947 for (s = script; s->kind != RX_OPK_END; ++s, ++opn) { 948 fake_time = ossl_time_add(fake_time, 949 ossl_ticks2time(s->time_advance)); 950 switch (s->kind) { 951 case RX_OPK_PKT: 952 for (i = 0; i < s->num_pn; ++i) { 953 OSSL_ACKM_RX_PKT pkt = {0}; 954 955 pkt.pkt_num = s->pn + i; 956 pkt.time = fake_time; 957 pkt.pkt_space = space; 958 pkt.is_ack_eliciting = 1; 959 960 /* The packet should be processable before we feed it. */ 961 if (!TEST_int_eq(ossl_ackm_is_rx_pn_processable(h.ackm, 962 pkt.pkt_num, 963 pkt.pkt_space), 1)) 964 goto err; 965 966 if (!TEST_int_eq(ossl_ackm_on_rx_packet(h.ackm, &pkt), 1)) 967 goto err; 968 } 969 970 break; 971 972 case RX_OPK_CHECK_UNPROC: 973 case RX_OPK_CHECK_PROC: 974 for (i = 0; i < s->num_pn; ++i) 975 if (!TEST_int_eq(ossl_ackm_is_rx_pn_processable(h.ackm, 976 s->pn + i, space), 977 (s->kind == RX_OPK_CHECK_PROC))) 978 goto err; 979 980 break; 981 982 case RX_OPK_CHECK_STATE: 983 if (!TEST_int_eq(ossl_ackm_is_ack_desired(h.ackm, space), 984 s->expect_desired)) 985 goto err; 986 987 if (!TEST_int_eq(!ossl_time_is_infinite(ossl_ackm_get_ack_deadline(h.ackm, space)) 988 && !ossl_time_is_zero(ossl_ackm_get_ack_deadline(h.ackm, space)), 989 s->expect_deadline)) 990 goto err; 991 992 for (i = 0; i < QUIC_PN_SPACE_NUM; ++i) { 993 if (i != (size_t)space 994 && !TEST_true(ossl_time_is_infinite(ossl_ackm_get_ack_deadline(h.ackm, i)))) 995 goto err; 996 997 if (!TEST_int_eq(ossl_time_compare(ossl_ackm_get_ack_deadline(h.ackm, i), 998 ack_deadline[i]), 0)) 999 goto err; 1000 } 1001 1002 break; 1003 1004 case RX_OPK_CHECK_ACKS: 1005 ack = ossl_ackm_get_ack_frame(h.ackm, space); 1006 1007 /* Should always be able to get an ACK frame. */ 1008 if (!TEST_ptr(ack)) 1009 goto err; 1010 1011 if (!TEST_size_t_eq(ack->num_ack_ranges, s->num_ack_ranges)) 1012 goto err; 1013 1014 for (i = 0; i < ack->num_ack_ranges; ++i) { 1015 if (!TEST_uint64_t_eq(ack->ack_ranges[i].start, 1016 s->ack_ranges[i].start)) 1017 goto err; 1018 if (!TEST_uint64_t_eq(ack->ack_ranges[i].end, 1019 s->ack_ranges[i].end)) 1020 goto err; 1021 } 1022 1023 break; 1024 1025 case RX_OPK_TX: 1026 pkts[txi].pkt = tx = &txs[txi]; 1027 1028 tx->pkt_num = s->pn; 1029 tx->pkt_space = space; 1030 tx->num_bytes = 123; 1031 tx->largest_acked = s->largest_acked; 1032 tx->is_inflight = 1; 1033 tx->is_ack_eliciting = 1; 1034 tx->on_lost = on_lost; 1035 tx->on_acked = on_acked; 1036 tx->on_discarded = on_discarded; 1037 tx->cb_arg = &pkts[txi]; 1038 tx->time = fake_time; 1039 1040 if (!TEST_int_eq(ossl_ackm_on_tx_packet(h.ackm, tx), 1)) 1041 goto err; 1042 1043 ++txi; 1044 break; 1045 1046 case RX_OPK_RX_ACK: 1047 rx_ack.ack_ranges = &rx_ack_range; 1048 rx_ack.num_ack_ranges = 1; 1049 1050 rx_ack_range.start = s->pn; 1051 rx_ack_range.end = s->pn + s->num_pn - 1; 1052 1053 if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &rx_ack, 1054 space, fake_time), 1)) 1055 goto err; 1056 1057 break; 1058 1059 case RX_OPK_SKIP_IF_PN_SPACE: 1060 if (space == (int)s->pn) { 1061 testresult = 1; 1062 goto err; 1063 } 1064 1065 break; 1066 1067 default: 1068 goto err; 1069 } 1070 } 1071 1072 testresult = 1; 1073 err: 1074 if (!testresult) 1075 TEST_error("error in ACKM RX script %d, op %zu", tidx + 1, opn + 1); 1076 1077 helper_destroy(&h); 1078 OPENSSL_free(pkts); 1079 OPENSSL_free(txs); 1080 return testresult; 1081 } 1082 1083 /* 1084 * Driver 1085 * ****************************************************************** 1086 */ 1087 static int test_tx_ack_case(int idx) 1088 { 1089 int tidx, space; 1090 1091 tidx = idx % OSSL_NELEM(tx_ack_cases); 1092 idx /= OSSL_NELEM(tx_ack_cases); 1093 1094 space = idx % QUIC_PN_SPACE_NUM; 1095 idx /= QUIC_PN_SPACE_NUM; 1096 1097 return test_tx_ack_case_actual(tidx, space, idx); 1098 } 1099 1100 static int test_rx_ack(int idx) 1101 { 1102 int tidx; 1103 1104 tidx = idx % OSSL_NELEM(rx_test_scripts); 1105 idx /= OSSL_NELEM(rx_test_scripts); 1106 1107 return test_rx_ack_actual(tidx, idx); 1108 } 1109 1110 int setup_tests(void) 1111 { 1112 ADD_ALL_TESTS(test_tx_ack_case, 1113 OSSL_NELEM(tx_ack_cases) * MODE_NUM * QUIC_PN_SPACE_NUM); 1114 ADD_ALL_TESTS(test_tx_ack_time_script, OSSL_NELEM(tx_ack_time_scripts)); 1115 ADD_ALL_TESTS(test_rx_ack, OSSL_NELEM(rx_test_scripts) * QUIC_PN_SPACE_NUM); 1116 return 1; 1117 } 1118