1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/queue.h>
7#ifndef WIN32
8#include <sys/time.h>
9#endif
10
11#include "lsquic.h"
12#include "lsquic_types.h"
13#include "lsquic_packet_common.h"
14#include "lsquic_parse.h"
15
16
17//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
18#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
19
20
21struct packno_bits_test {
22    int             pbt_lineno;
23    /* Inputs: */
24    lsquic_packno_t pbt_packno,
25                    pbt_least_unacked;
26    uint64_t        pbt_n_in_flight;
27    /* Output: */
28    enum packno_bits pbt_packno_bits;
29};
30
31
32static const struct packno_bits_test pb_tests[] = {
33
34    {   .pbt_lineno         = __LINE__,
35        .pbt_packno         = 1,
36        .pbt_least_unacked  = 0,
37        .pbt_n_in_flight    = 0,
38        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
39    },
40
41    {   .pbt_lineno         = __LINE__,
42        .pbt_packno         = 101,
43        .pbt_least_unacked  = 100,
44        .pbt_n_in_flight    = 0,
45        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
46    },
47
48    {   .pbt_lineno         = __LINE__,
49        .pbt_packno         = 10001,
50        .pbt_least_unacked  = 10000,
51        .pbt_n_in_flight    = 1 << 6,
52        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
53    },
54
55    {   .pbt_lineno         = __LINE__,
56        .pbt_packno         = 10001,
57        .pbt_least_unacked  = 10000,
58        .pbt_n_in_flight    = (1 << 6) + 1,
59        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
60    },
61
62    {   .pbt_lineno         = __LINE__,
63        .pbt_packno         = (1 << 16) + 1,
64        .pbt_least_unacked  = 1 << 16,
65        .pbt_n_in_flight    = 1 << 14,
66        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
67    },
68
69    {   .pbt_lineno         = __LINE__,
70        .pbt_packno         = (1 << 16) + 1,
71        .pbt_least_unacked  = 1 << 16,
72        .pbt_n_in_flight    = (1 << 14) + 1,
73        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
74    },
75
76    {   .pbt_lineno         = __LINE__,
77        .pbt_packno         = (1ULL << 33) + 1,
78        .pbt_least_unacked  = 1ULL << 33,
79        .pbt_n_in_flight    = 1ULL << 30,
80        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
81    },
82
83    {   .pbt_lineno         = __LINE__,
84        .pbt_packno         = (1ULL << 33) + 1,
85        .pbt_least_unacked  = 1ULL << 33,
86        .pbt_n_in_flight    = (1ULL << 30) + 1,
87        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
88    },
89
90    {   .pbt_lineno         = __LINE__,
91        .pbt_packno         = 100,
92        .pbt_least_unacked  = 1,
93        .pbt_n_in_flight    = 3,
94        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
95    },
96
97    {   .pbt_lineno         = __LINE__,
98        .pbt_packno         = 100,
99        .pbt_least_unacked  = 1,
100        .pbt_n_in_flight    = 99,
101        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
102    },
103
104    {   .pbt_lineno         = __LINE__,
105        .pbt_packno         = 1 + (1 << 6),
106        .pbt_least_unacked  = 1,
107        .pbt_n_in_flight    = 0,
108        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
109    },
110
111    {   .pbt_lineno         = __LINE__,
112        .pbt_packno         = 1 + (1 << 6) + 1,
113        .pbt_least_unacked  = 1,
114        .pbt_n_in_flight    = 0,
115        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
116    },
117
118    {   .pbt_lineno         = __LINE__,
119        .pbt_packno         = (1 << 20) + (1 << 14),
120        .pbt_least_unacked  = 1 << 20,
121        .pbt_n_in_flight    = 0,
122        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
123    },
124
125    {   .pbt_lineno         = __LINE__,
126        .pbt_packno         = (1 << 20) + (1 << 14) + 1,
127        .pbt_least_unacked  = 1 << 20,
128        .pbt_n_in_flight    = 0,
129        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
130    },
131
132    {   .pbt_lineno         = __LINE__,
133        .pbt_packno         = (1 << 20) + (1ULL << 30),
134        .pbt_least_unacked  = 1 << 20,
135        .pbt_n_in_flight    = 0,
136        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
137    },
138
139    {   .pbt_lineno         = __LINE__,
140        .pbt_packno         = (1 << 20) + (1ULL << 30) + 1,
141        .pbt_least_unacked  = 1 << 20,
142        .pbt_n_in_flight    = 0,
143        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
144    },
145
146    /* Tests from Chrome: */
147    {   .pbt_lineno         = __LINE__,
148        .pbt_packno         = 65,
149        .pbt_least_unacked  = 2,
150        .pbt_n_in_flight    = 7,
151        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
152    },
153
154    {   .pbt_lineno         = __LINE__,
155        .pbt_packno         = 64 * 256 - 1,
156        .pbt_least_unacked  = 2,
157        .pbt_n_in_flight    = 7,
158        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
159    },
160
161    {   .pbt_lineno         = __LINE__,
162        .pbt_packno         = 64 * 256 * 256 - 1,
163        .pbt_least_unacked  = 2,
164        .pbt_n_in_flight    = 7,
165        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
166    },
167
168    {   .pbt_lineno         = __LINE__,
169        .pbt_packno         = 64ULL * 256 * 256 * 256 * 256 - 1,
170        .pbt_least_unacked  = 2,
171        .pbt_n_in_flight    = 7,
172        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
173    },
174
175    {   .pbt_lineno         = __LINE__,
176        .pbt_packno         = 2,
177        .pbt_least_unacked  = 1,
178        .pbt_n_in_flight    = 7,
179        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
180    },
181
182    {   .pbt_lineno         = __LINE__,
183        .pbt_packno         = 2,
184        .pbt_least_unacked  = 1,
185        .pbt_n_in_flight    = 1896,
186        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
187    },
188
189    {   .pbt_lineno         = __LINE__,
190        .pbt_packno         = 2,
191        .pbt_least_unacked  = 1,
192        .pbt_n_in_flight    = 48545,
193        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
194    },
195
196    {   .pbt_lineno         = __LINE__,
197        .pbt_packno         = 2,
198        .pbt_least_unacked  = 1,
199        .pbt_n_in_flight    = 3181457256ULL,
200        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
201    },
202
203};
204
205
206static void
207run_pbt (int i)
208{
209    const struct packno_bits_test *const pbt = &pb_tests[i];
210    enum packno_bits packno_bits = pf->pf_calc_packno_bits(pbt->pbt_packno,
211                                pbt->pbt_least_unacked, pbt->pbt_n_in_flight);
212    assert(packno_bits == pbt->pbt_packno_bits);
213    unsigned packet_len = pf->pf_packno_bits2len(packno_bits);
214    /* Now see if we can restore it back: */
215    lsquic_packno_t cur_packno = pbt->pbt_packno &
216                        ((1ULL << (packet_len << 3)) - 1);
217    lsquic_packno_t orig_packno = lsquic_restore_packno(cur_packno, packet_len,
218                                                    pbt->pbt_least_unacked);
219    assert(orig_packno == pbt->pbt_packno);
220}
221
222
223struct lsquic_restore_packno_test {
224    int                         rpt_lineno;
225    /* Input */
226    enum packno_bits     rpt_packno_bits;
227    lsquic_packno_t             rpt_cur_packno;
228    lsquic_packno_t             rpt_max_packno;
229    /* Output */
230    lsquic_packno_t             rpt_orig_packno;
231};
232
233static const struct lsquic_restore_packno_test rp_tests[] =
234{
235
236    {   .rpt_lineno         = __LINE__,
237        .rpt_max_packno     = 0,
238        .rpt_cur_packno     = 1,
239        .rpt_packno_bits    = GQUIC_PACKNO_LEN_1,
240        .rpt_orig_packno    = 1,
241    },
242
243};
244
245
246static void
247run_rpt (int i)
248{
249    const struct lsquic_restore_packno_test *const rpt = &rp_tests[i];
250    unsigned packet_len = pf->pf_packno_bits2len(rpt->rpt_packno_bits);
251    lsquic_packno_t orig_packno = lsquic_restore_packno(rpt->rpt_cur_packno,
252                            packet_len, rpt->rpt_max_packno);
253    assert(orig_packno == rpt->rpt_orig_packno);
254}
255
256
257static void
258test_restore (enum packno_bits bits)
259{
260    unsigned len, n;
261    enum { OP_PLUS, OP_MINUS, N_OPS } op;
262    uint64_t epoch, epoch_delta;
263    lsquic_packno_t orig_packno, cur_packno, restored_packno;
264
265#ifdef WIN32
266    orig_packno = 0;
267#endif
268    len = pf->pf_packno_bits2len(bits);
269    epoch_delta = 1ULL << (len << 3);
270    epoch = epoch_delta * 11 /* Just some number */;
271
272    /* Test current epoch: */
273    for (op = 0; op < N_OPS; ++op)
274        for (n = 0; n < 5; ++n)
275        {
276            /* Test at the ends of the epoch */
277            if (op == OP_MINUS)
278                orig_packno = epoch - epoch_delta / 2 + n;
279            else if (op == OP_PLUS)
280                orig_packno = epoch + epoch_delta / 2 - n - 1;
281            else
282                assert(0);
283            cur_packno = orig_packno & (epoch_delta - 1);
284            restored_packno = lsquic_restore_packno(cur_packno, len, epoch);
285            assert(orig_packno == restored_packno);
286            /* Test in the middle of the epoch */
287            if (op == OP_MINUS)
288                orig_packno = epoch - n;
289            else
290                orig_packno = epoch + n;
291            cur_packno = orig_packno & (epoch_delta - 1);
292            restored_packno = lsquic_restore_packno(cur_packno, len, epoch);
293            assert(orig_packno == restored_packno);
294        }
295
296    /* Test previous epoch (max is to the left) */
297    for (n = 0; n < 5; ++n)
298    {
299        /* Test at the end of the epoch */
300        orig_packno = epoch + epoch_delta / 2 - n - 1;
301        cur_packno = orig_packno & (epoch_delta - 1);
302        restored_packno = lsquic_restore_packno(cur_packno, len, epoch - epoch_delta * 3 / 4);
303        assert(orig_packno == restored_packno + epoch_delta);
304        /* Test in the middle of the epoch */
305        orig_packno = epoch + 2 - n;
306        cur_packno = orig_packno & (epoch_delta - 1);
307        restored_packno = lsquic_restore_packno(cur_packno, len, epoch - epoch_delta * 3 / 4);
308        assert(orig_packno == restored_packno + epoch_delta);
309    }
310
311    /* Test previous epoch (max is to the right) */
312    for (n = 0; n < 5; ++n)
313    {
314        /* Test at the end of the epoch */
315        orig_packno = epoch - epoch_delta / 2 + n;
316        cur_packno = orig_packno & (epoch_delta - 1);
317        restored_packno = lsquic_restore_packno(cur_packno, len, epoch + epoch_delta * 3 / 4);
318        assert(orig_packno == restored_packno - epoch_delta);
319        /* Test in the middle of the epoch */
320        orig_packno = epoch + 2 - n;
321        cur_packno = orig_packno & (epoch_delta - 1);
322        restored_packno = lsquic_restore_packno(cur_packno, len, epoch + epoch_delta * 3 / 4);
323        assert(orig_packno == restored_packno - epoch_delta);
324    }
325
326}
327
328
329int
330main (void)
331{
332    unsigned i;
333    for (i = 0; i < sizeof(pb_tests) / sizeof(pb_tests[0]); ++i)
334        run_pbt(i);
335    for (i = 0; i < sizeof(rp_tests) / sizeof(rp_tests[0]); ++i)
336        run_rpt(i);
337    test_restore(GQUIC_PACKNO_LEN_1);
338    test_restore(GQUIC_PACKNO_LEN_2);
339    test_restore(GQUIC_PACKNO_LEN_4);
340    test_restore(GQUIC_PACKNO_LEN_6);
341    return 0;
342}
343