lsquic_senhist.h revision 06b2a236
1/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_senhist.h -- History sent packets.
4 *
5 * We need to keep track of packet numbers in order to verify ACKs.  To
6 * speed up processing, we make sure that there is never a gap in the
7 * packet number sequence we generate.
8 */
9
10#ifndef LSQUIC_SENHIST_H
11#define LSQUIC_SENHIST_H 1
12
13#ifndef LSQUIC_SENHIST_FATAL
14#   define LSQUIC_SENHIST_FATAL 0
15#endif
16
17typedef struct lsquic_senhist {
18    lsquic_packno_t             sh_last_sent;
19    lsquic_packno_t             sh_warn_thresh;
20    enum {
21#if !LSQUIC_SENHIST_FATAL
22        SH_WARNED   = 1 << 0,   /* Warn once */
23#endif
24        SH_GAP_OK   = 1 << 1,   /* Before connection is just about to close or
25                                 * during mini/full packet handoff.
26                                 */
27    }                           sh_flags;
28} lsquic_senhist_t;
29
30#define lsquic_senhist_init(hist, is_ietf) do {                         \
31    if (is_ietf)                                                        \
32        (hist)->sh_last_sent = ~0ull;                                   \
33    else                                                                \
34        (hist)->sh_last_sent = 0;                                       \
35} while (0)
36
37#define lsquic_senhist_cleanup(hist)
38
39#if LSQUIC_SENHIST_FATAL
40#define lsquic_senhist_add(hist, packno) do {                           \
41    if (!((hist)->sh_flags & SH_GAP_OK)                                 \
42                        && (packno) > (hist)->sh_warn_thresh)           \
43        assert((hist)->sh_last_sent == packno - 1);                     \
44    if ((int64_t) (packno) > (int64_t) (hist)->sh_last_sent)            \
45        (hist)->sh_last_sent = packno;                                  \
46} while (0)
47#else
48#define lsquic_senhist_add(hist, packno) do {                           \
49    if ((hist)->sh_last_sent != packno - 1)                             \
50    {                                                                   \
51        if (!((hist)->sh_flags & (SH_WARNED|SH_GAP_OK))                 \
52                        && (packno) > (hist)->sh_warn_thresh)           \
53        {                                                               \
54            LSQ_WARN("send history gap %"PRIu64" - %"PRIu64,            \
55                (hist)->sh_last_sent, packno);                          \
56            (hist)->sh_flags |= SH_WARNED;                              \
57        }                                                               \
58    }                                                                   \
59    if ((int64_t) (packno) > (int64_t) (hist)->sh_last_sent)            \
60        (hist)->sh_last_sent = packno;                                  \
61} while (0)
62#endif
63
64/* Returns 0 if no packets have been sent yet */
65#define lsquic_senhist_largest(hist) (+(hist)->sh_last_sent)
66
67void
68lsquic_senhist_tostr (lsquic_senhist_t *hist, char *buf, size_t bufsz);
69
70#define lsquic_senhist_mem_used(hist) (sizeof(*(hist)))
71
72#endif
73