1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 25392f7a3SLiteSpeed Tech/* Test both generation and parsing of IETF ACK frames */ 35392f7a3SLiteSpeed Tech 45392f7a3SLiteSpeed Tech#include <assert.h> 55392f7a3SLiteSpeed Tech#include <string.h> 65392f7a3SLiteSpeed Tech 75392f7a3SLiteSpeed Tech#include "lsquic.h" 85392f7a3SLiteSpeed Tech#include "lsquic_types.h" 95392f7a3SLiteSpeed Tech#include "lsquic_int_types.h" 105392f7a3SLiteSpeed Tech#include "lsquic_sizes.h" 115392f7a3SLiteSpeed Tech#include "lsquic_parse.h" 125392f7a3SLiteSpeed Tech#include "lsquic_trans_params.h" 135392f7a3SLiteSpeed Tech 145392f7a3SLiteSpeed Techstruct test 155392f7a3SLiteSpeed Tech{ 165392f7a3SLiteSpeed Tech int lineno; 175392f7a3SLiteSpeed Tech int skip_gen; 185392f7a3SLiteSpeed Tech 195392f7a3SLiteSpeed Tech struct ack_info acki; 205392f7a3SLiteSpeed Tech 215392f7a3SLiteSpeed Tech size_t encoded_sz; 225392f7a3SLiteSpeed Tech unsigned char encoded[0x1000]; 235392f7a3SLiteSpeed Tech}; 245392f7a3SLiteSpeed Tech 255392f7a3SLiteSpeed Techstatic const lsquic_time_t now = 0x12345676890; 265392f7a3SLiteSpeed Tech 275392f7a3SLiteSpeed Techstatic const struct test tests[] = 285392f7a3SLiteSpeed Tech{ 295392f7a3SLiteSpeed Tech { 305392f7a3SLiteSpeed Tech .lineno = __LINE__, 315392f7a3SLiteSpeed Tech .acki = 325392f7a3SLiteSpeed Tech { 335392f7a3SLiteSpeed Tech .n_ranges = 2, 345392f7a3SLiteSpeed Tech .lack_delta = 0xFEDCB0, 355392f7a3SLiteSpeed Tech .ranges = 365392f7a3SLiteSpeed Tech { 375392f7a3SLiteSpeed Tech [0] = { 7, 7, }, 385392f7a3SLiteSpeed Tech [1] = { 0, 0, }, 395392f7a3SLiteSpeed Tech }, 405392f7a3SLiteSpeed Tech }, 415392f7a3SLiteSpeed Tech .encoded = 425392f7a3SLiteSpeed Tech { 435392f7a3SLiteSpeed Tech /* Type */ 0x02, 445392f7a3SLiteSpeed Tech /* Largest acked */ 0x07, 455392f7a3SLiteSpeed Tech /* ACK delay */ 0x80, 0x1F, 0xDB, 0x96, 465392f7a3SLiteSpeed Tech /* Addl block count */ 0x01, 475392f7a3SLiteSpeed Tech /* First ACK block */ 0x00, 485392f7a3SLiteSpeed Tech /* Gap */ 0x05, 495392f7a3SLiteSpeed Tech /* ACK block */ 0x00, 505392f7a3SLiteSpeed Tech }, 515392f7a3SLiteSpeed Tech .encoded_sz = 10, 525392f7a3SLiteSpeed Tech }, 535392f7a3SLiteSpeed Tech 545392f7a3SLiteSpeed Tech { 555392f7a3SLiteSpeed Tech .lineno = __LINE__, 565392f7a3SLiteSpeed Tech .acki = 575392f7a3SLiteSpeed Tech { 585392f7a3SLiteSpeed Tech .n_ranges = 3, 595392f7a3SLiteSpeed Tech .lack_delta = 0xFEDCB0, 605392f7a3SLiteSpeed Tech .ranges = 615392f7a3SLiteSpeed Tech { 625392f7a3SLiteSpeed Tech [0] = { 10, 10, }, 635392f7a3SLiteSpeed Tech [1] = { 7, 7, }, 645392f7a3SLiteSpeed Tech [2] = { 0, 0, }, 655392f7a3SLiteSpeed Tech }, 665392f7a3SLiteSpeed Tech }, 675392f7a3SLiteSpeed Tech .encoded = 685392f7a3SLiteSpeed Tech { 695392f7a3SLiteSpeed Tech /* Type */ 0x02, 705392f7a3SLiteSpeed Tech /* Largest acked */ 10, 715392f7a3SLiteSpeed Tech /* ACK delay */ 0x80, 0x1F, 0xDB, 0x96, 725392f7a3SLiteSpeed Tech /* Addl block count */ 2, 735392f7a3SLiteSpeed Tech /* First ACK block */ 0x00, 745392f7a3SLiteSpeed Tech /* Gap */ 0x01, 755392f7a3SLiteSpeed Tech /* ACK block */ 0x00, 765392f7a3SLiteSpeed Tech /* Gap */ 0x05, 775392f7a3SLiteSpeed Tech /* ACK block */ 0x00, 785392f7a3SLiteSpeed Tech }, 795392f7a3SLiteSpeed Tech .encoded_sz = 12, 805392f7a3SLiteSpeed Tech }, 815392f7a3SLiteSpeed Tech 825392f7a3SLiteSpeed Tech { 835392f7a3SLiteSpeed Tech .lineno = __LINE__, 845392f7a3SLiteSpeed Tech .acki = 855392f7a3SLiteSpeed Tech { 865392f7a3SLiteSpeed Tech .flags = AI_ECN, 875392f7a3SLiteSpeed Tech .n_ranges = 3, 885392f7a3SLiteSpeed Tech .lack_delta = 0xFEDCB0, 895392f7a3SLiteSpeed Tech .ecn_counts = { 0, 0x010203, 1, 0x49, }, 905392f7a3SLiteSpeed Tech .ranges = 915392f7a3SLiteSpeed Tech { 925392f7a3SLiteSpeed Tech [0] = { 10, 10, }, 935392f7a3SLiteSpeed Tech [1] = { 7, 7, }, 945392f7a3SLiteSpeed Tech [2] = { 0, 0, }, 955392f7a3SLiteSpeed Tech }, 965392f7a3SLiteSpeed Tech }, 975392f7a3SLiteSpeed Tech .encoded = 985392f7a3SLiteSpeed Tech { 995392f7a3SLiteSpeed Tech /* Type */ 0x03, 1005392f7a3SLiteSpeed Tech /* Largest acked */ 10, 1015392f7a3SLiteSpeed Tech /* ACK delay */ 0x80, 0x1F, 0xDB, 0x96, 1025392f7a3SLiteSpeed Tech /* Addl block count */ 2, 1035392f7a3SLiteSpeed Tech /* First ACK block */ 0x00, 1045392f7a3SLiteSpeed Tech /* Gap */ 0x01, 1055392f7a3SLiteSpeed Tech /* ACK block */ 0x00, 1065392f7a3SLiteSpeed Tech /* Gap */ 0x05, 1075392f7a3SLiteSpeed Tech /* ACK block */ 0x00, 1085392f7a3SLiteSpeed Tech /* ECT(1) count */ 0x01, 1095392f7a3SLiteSpeed Tech /* ECT(0) count */ 0x80, 0x01, 0x02, 0x03, 1105392f7a3SLiteSpeed Tech /* ECN-CE count */ 0x40, 0x49, 1115392f7a3SLiteSpeed Tech }, 1125392f7a3SLiteSpeed Tech .encoded_sz = 19, 1135392f7a3SLiteSpeed Tech }, 1145392f7a3SLiteSpeed Tech 1155392f7a3SLiteSpeed Tech}; 1165392f7a3SLiteSpeed Tech 1175392f7a3SLiteSpeed Techstruct rechist 1185392f7a3SLiteSpeed Tech{ 1195392f7a3SLiteSpeed Tech const struct ack_info *acki; 1205392f7a3SLiteSpeed Tech unsigned next_range; 1215392f7a3SLiteSpeed Tech}; 1225392f7a3SLiteSpeed Tech 1235392f7a3SLiteSpeed Tech 1245392f7a3SLiteSpeed Techstatic const struct lsquic_packno_range * 1255392f7a3SLiteSpeed Techrechist_next (void *ctx) 1265392f7a3SLiteSpeed Tech{ 1275392f7a3SLiteSpeed Tech struct rechist *rechist = ctx; 1285392f7a3SLiteSpeed Tech if (rechist->next_range < rechist->acki->n_ranges) 1295392f7a3SLiteSpeed Tech return rechist->acki->ranges + rechist->next_range++; 1305392f7a3SLiteSpeed Tech else 1315392f7a3SLiteSpeed Tech return NULL; 1325392f7a3SLiteSpeed Tech} 1335392f7a3SLiteSpeed Tech 1345392f7a3SLiteSpeed Techstatic const struct lsquic_packno_range * 1355392f7a3SLiteSpeed Techrechist_first (void *ctx) 1365392f7a3SLiteSpeed Tech{ 1375392f7a3SLiteSpeed Tech struct rechist *rechist = ctx; 1385392f7a3SLiteSpeed Tech rechist->next_range = 0; 1395392f7a3SLiteSpeed Tech return rechist_next(rechist); 1405392f7a3SLiteSpeed Tech} 1415392f7a3SLiteSpeed Tech 1425392f7a3SLiteSpeed Techstatic lsquic_time_t 1435392f7a3SLiteSpeed Techrechist_largest_recv (void *ctx) 1445392f7a3SLiteSpeed Tech{ 1455392f7a3SLiteSpeed Tech struct rechist *rechist = ctx; 1465392f7a3SLiteSpeed Tech return now - rechist->acki->lack_delta; 1475392f7a3SLiteSpeed Tech} 1485392f7a3SLiteSpeed Tech 1495392f7a3SLiteSpeed Tech 1505392f7a3SLiteSpeed Techstatic void 1515392f7a3SLiteSpeed Techcompare_ackis (const struct ack_info *exp, const struct ack_info *got) 1525392f7a3SLiteSpeed Tech{ 1535392f7a3SLiteSpeed Tech unsigned i; 1545392f7a3SLiteSpeed Tech 1555392f7a3SLiteSpeed Tech assert(exp->flags == got->flags); 1565392f7a3SLiteSpeed Tech assert(exp->n_ranges == got->n_ranges); 1575392f7a3SLiteSpeed Tech assert(exp->lack_delta == got->lack_delta); 1585392f7a3SLiteSpeed Tech 1595392f7a3SLiteSpeed Tech for (i = 0; i < exp->n_ranges; ++i) 1605392f7a3SLiteSpeed Tech { 1615392f7a3SLiteSpeed Tech assert(exp->ranges[i].high == got->ranges[i].high); 1625392f7a3SLiteSpeed Tech assert(exp->ranges[i].low == got->ranges[i].low); 1635392f7a3SLiteSpeed Tech } 1645392f7a3SLiteSpeed Tech 1655392f7a3SLiteSpeed Tech if (exp->flags & AI_ECN) 1665392f7a3SLiteSpeed Tech for (i = 1; i <= 3; ++i) 1675392f7a3SLiteSpeed Tech assert(exp->ecn_counts[i] == got->ecn_counts[i]); 1685392f7a3SLiteSpeed Tech} 1695392f7a3SLiteSpeed Tech 1705392f7a3SLiteSpeed Tech 1715392f7a3SLiteSpeed Techstatic void 1725392f7a3SLiteSpeed Techrun_test (const struct test *test) 1735392f7a3SLiteSpeed Tech{ 1745392f7a3SLiteSpeed Tech int len, has_missing; 1755392f7a3SLiteSpeed Tech lsquic_packno_t largest_received; 1765392f7a3SLiteSpeed Tech const struct parse_funcs *pf; 1775392f7a3SLiteSpeed Tech struct rechist rechist; 1785392f7a3SLiteSpeed Tech struct ack_info acki; 1795392f7a3SLiteSpeed Tech size_t sz; 1805392f7a3SLiteSpeed Tech unsigned char buf[0x1000]; 1815392f7a3SLiteSpeed Tech 182fb73393fSDmitri Tikhonov pf = select_pf_by_ver(LSQVER_ID27); 1835392f7a3SLiteSpeed Tech if (!test->skip_gen) 1845392f7a3SLiteSpeed Tech { 1855392f7a3SLiteSpeed Tech rechist.acki = &test->acki; 1865392f7a3SLiteSpeed Tech len = pf->pf_gen_ack_frame(buf, sizeof(buf), rechist_first, rechist_next, 1875392f7a3SLiteSpeed Tech rechist_largest_recv, &rechist, now, &has_missing, &largest_received, 1885392f7a3SLiteSpeed Tech test->acki.flags & AI_ECN ? rechist.acki->ecn_counts : NULL); 1895392f7a3SLiteSpeed Tech assert(len > 0); 1905392f7a3SLiteSpeed Tech assert(largest_received == largest_acked(&test->acki)); 1915392f7a3SLiteSpeed Tech assert((size_t) len == test->encoded_sz); 1925392f7a3SLiteSpeed Tech assert(0 == memcmp(test->encoded, buf, test->encoded_sz)); 1935392f7a3SLiteSpeed Tech } 1945392f7a3SLiteSpeed Tech 1955392f7a3SLiteSpeed Tech /* Test that shorter buffers cannot get parsed */ 1965392f7a3SLiteSpeed Tech for (sz = 1; sz < test->encoded_sz; ++sz) 1975392f7a3SLiteSpeed Tech { 1985392f7a3SLiteSpeed Tech len = pf->pf_parse_ack_frame(test->encoded, sz, &acki, 1995392f7a3SLiteSpeed Tech TP_DEF_ACK_DELAY_EXP); 2005392f7a3SLiteSpeed Tech assert(len < 0); 2015392f7a3SLiteSpeed Tech } 2025392f7a3SLiteSpeed Tech 2035392f7a3SLiteSpeed Tech len = pf->pf_parse_ack_frame(test->encoded, sizeof(test->encoded), &acki, 2045392f7a3SLiteSpeed Tech TP_DEF_ACK_DELAY_EXP); 2055392f7a3SLiteSpeed Tech assert(len > 0); 2065392f7a3SLiteSpeed Tech assert((size_t) len == test->encoded_sz); 2075392f7a3SLiteSpeed Tech compare_ackis(&test->acki, &acki); 2085392f7a3SLiteSpeed Tech} 2095392f7a3SLiteSpeed Tech 2105392f7a3SLiteSpeed Techint 2115392f7a3SLiteSpeed Techmain (void) 2125392f7a3SLiteSpeed Tech{ 2135392f7a3SLiteSpeed Tech const struct test *test; 2145392f7a3SLiteSpeed Tech 2155392f7a3SLiteSpeed Tech for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test) 2165392f7a3SLiteSpeed Tech run_test(test); 2175392f7a3SLiteSpeed Tech 2185392f7a3SLiteSpeed Tech return 0; 2195392f7a3SLiteSpeed Tech} 220