test_packno_len.c revision 06b2a236
1/* Copyright (c) 2017 - 2021 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
17static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043);
18
19
20struct packno_bits_test {
21    int             pbt_lineno;
22    /* Inputs: */
23    lsquic_packno_t pbt_packno,
24                    pbt_least_unacked;
25    uint64_t        pbt_n_in_flight;
26    /* Output: */
27    enum packno_bits pbt_packno_bits;
28};
29
30
31static const struct packno_bits_test pb_tests[] = {
32
33    {   .pbt_lineno         = __LINE__,
34        .pbt_packno         = 1,
35        .pbt_least_unacked  = 0,
36        .pbt_n_in_flight    = 0,
37        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
38    },
39
40    {   .pbt_lineno         = __LINE__,
41        .pbt_packno         = 101,
42        .pbt_least_unacked  = 100,
43        .pbt_n_in_flight    = 0,
44        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
45    },
46
47    {   .pbt_lineno         = __LINE__,
48        .pbt_packno         = 10001,
49        .pbt_least_unacked  = 10000,
50        .pbt_n_in_flight    = 1 << 6,
51        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
52    },
53
54    {   .pbt_lineno         = __LINE__,
55        .pbt_packno         = 10001,
56        .pbt_least_unacked  = 10000,
57        .pbt_n_in_flight    = (1 << 6) + 1,
58        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
59    },
60
61    {   .pbt_lineno         = __LINE__,
62        .pbt_packno         = (1 << 16) + 1,
63        .pbt_least_unacked  = 1 << 16,
64        .pbt_n_in_flight    = 1 << 14,
65        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
66    },
67
68    {   .pbt_lineno         = __LINE__,
69        .pbt_packno         = (1 << 16) + 1,
70        .pbt_least_unacked  = 1 << 16,
71        .pbt_n_in_flight    = (1 << 14) + 1,
72        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
73    },
74
75    {   .pbt_lineno         = __LINE__,
76        .pbt_packno         = (1ULL << 33) + 1,
77        .pbt_least_unacked  = 1ULL << 33,
78        .pbt_n_in_flight    = 1ULL << 30,
79        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
80    },
81
82    {   .pbt_lineno         = __LINE__,
83        .pbt_packno         = (1ULL << 33) + 1,
84        .pbt_least_unacked  = 1ULL << 33,
85        .pbt_n_in_flight    = (1ULL << 30) + 1,
86        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
87    },
88
89    {   .pbt_lineno         = __LINE__,
90        .pbt_packno         = 100,
91        .pbt_least_unacked  = 1,
92        .pbt_n_in_flight    = 3,
93        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
94    },
95
96    {   .pbt_lineno         = __LINE__,
97        .pbt_packno         = 100,
98        .pbt_least_unacked  = 1,
99        .pbt_n_in_flight    = 99,
100        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
101    },
102
103    {   .pbt_lineno         = __LINE__,
104        .pbt_packno         = 1 + (1 << 6),
105        .pbt_least_unacked  = 1,
106        .pbt_n_in_flight    = 0,
107        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
108    },
109
110    {   .pbt_lineno         = __LINE__,
111        .pbt_packno         = 1 + (1 << 6) + 1,
112        .pbt_least_unacked  = 1,
113        .pbt_n_in_flight    = 0,
114        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
115    },
116
117    {   .pbt_lineno         = __LINE__,
118        .pbt_packno         = (1 << 20) + (1 << 14),
119        .pbt_least_unacked  = 1 << 20,
120        .pbt_n_in_flight    = 0,
121        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
122    },
123
124    {   .pbt_lineno         = __LINE__,
125        .pbt_packno         = (1 << 20) + (1 << 14) + 1,
126        .pbt_least_unacked  = 1 << 20,
127        .pbt_n_in_flight    = 0,
128        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
129    },
130
131    {   .pbt_lineno         = __LINE__,
132        .pbt_packno         = (1 << 20) + (1ULL << 30),
133        .pbt_least_unacked  = 1 << 20,
134        .pbt_n_in_flight    = 0,
135        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
136    },
137
138    {   .pbt_lineno         = __LINE__,
139        .pbt_packno         = (1 << 20) + (1ULL << 30) + 1,
140        .pbt_least_unacked  = 1 << 20,
141        .pbt_n_in_flight    = 0,
142        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
143    },
144
145    /* Tests from Chrome: */
146    {   .pbt_lineno         = __LINE__,
147        .pbt_packno         = 65,
148        .pbt_least_unacked  = 2,
149        .pbt_n_in_flight    = 7,
150        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
151    },
152
153    {   .pbt_lineno         = __LINE__,
154        .pbt_packno         = 64 * 256 - 1,
155        .pbt_least_unacked  = 2,
156        .pbt_n_in_flight    = 7,
157        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
158    },
159
160    {   .pbt_lineno         = __LINE__,
161        .pbt_packno         = 64 * 256 * 256 - 1,
162        .pbt_least_unacked  = 2,
163        .pbt_n_in_flight    = 7,
164        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
165    },
166
167    {   .pbt_lineno         = __LINE__,
168        .pbt_packno         = 64ULL * 256 * 256 * 256 * 256 - 1,
169        .pbt_least_unacked  = 2,
170        .pbt_n_in_flight    = 7,
171        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
172    },
173
174    {   .pbt_lineno         = __LINE__,
175        .pbt_packno         = 2,
176        .pbt_least_unacked  = 1,
177        .pbt_n_in_flight    = 7,
178        .pbt_packno_bits    = GQUIC_PACKNO_LEN_1,
179    },
180
181    {   .pbt_lineno         = __LINE__,
182        .pbt_packno         = 2,
183        .pbt_least_unacked  = 1,
184        .pbt_n_in_flight    = 1896,
185        .pbt_packno_bits    = GQUIC_PACKNO_LEN_2,
186    },
187
188    {   .pbt_lineno         = __LINE__,
189        .pbt_packno         = 2,
190        .pbt_least_unacked  = 1,
191        .pbt_n_in_flight    = 48545,
192        .pbt_packno_bits    = GQUIC_PACKNO_LEN_4,
193    },
194
195    {   .pbt_lineno         = __LINE__,
196        .pbt_packno         = 2,
197        .pbt_least_unacked  = 1,
198        .pbt_n_in_flight    = 3181457256ULL,
199        .pbt_packno_bits    = GQUIC_PACKNO_LEN_6,
200    },
201
202};
203
204
205static void
206run_pbt (int i)
207{
208    const struct parse_funcs *pf = select_pf_by_ver(LSQVER_043);
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