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 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 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 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 331 static void on_loss_detection_deadline_callback(OSSL_TIME deadline, void *arg) 332 { 333 *(OSSL_TIME *)arg = deadline; 334 } 335 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 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 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 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 */ 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 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 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