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