1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * lsquic_senhist.h -- History sent packets.
450aadb33SDmitri Tikhonov *
516a9b66aSDmitri Tikhonov * We need to keep track of packet numbers in order to verify ACKs.  To
616a9b66aSDmitri Tikhonov * speed up processing, we make sure that there is never a gap in the
716a9b66aSDmitri Tikhonov * packet number sequence we generate.
850aadb33SDmitri Tikhonov */
950aadb33SDmitri Tikhonov
1050aadb33SDmitri Tikhonov#ifndef LSQUIC_SENHIST_H
1150aadb33SDmitri Tikhonov#define LSQUIC_SENHIST_H 1
1250aadb33SDmitri Tikhonov
1316a9b66aSDmitri Tikhonov#ifndef LSQUIC_SENHIST_FATAL
1416a9b66aSDmitri Tikhonov#   define LSQUIC_SENHIST_FATAL 0
1516a9b66aSDmitri Tikhonov#endif
1650aadb33SDmitri Tikhonov
1750aadb33SDmitri Tikhonovtypedef struct lsquic_senhist {
1816a9b66aSDmitri Tikhonov    lsquic_packno_t             sh_last_sent;
198ae5ecb4SDmitri Tikhonov    lsquic_packno_t             sh_warn_thresh;
2016a9b66aSDmitri Tikhonov    enum {
215392f7a3SLiteSpeed Tech#if !LSQUIC_SENHIST_FATAL
2216a9b66aSDmitri Tikhonov        SH_WARNED   = 1 << 0,   /* Warn once */
2316a9b66aSDmitri Tikhonov#endif
248ae5ecb4SDmitri Tikhonov        SH_GAP_OK   = 1 << 1,   /* Before connection is just about to close or
258ae5ecb4SDmitri Tikhonov                                 * during mini/full packet handoff.
268ae5ecb4SDmitri Tikhonov                                 */
275392f7a3SLiteSpeed Tech    }                           sh_flags;
2850aadb33SDmitri Tikhonov} lsquic_senhist_t;
2950aadb33SDmitri Tikhonov
305392f7a3SLiteSpeed Tech#define lsquic_senhist_init(hist, is_ietf) do {                         \
315392f7a3SLiteSpeed Tech    if (is_ietf)                                                        \
325392f7a3SLiteSpeed Tech        (hist)->sh_last_sent = ~0ull;                                   \
335392f7a3SLiteSpeed Tech    else                                                                \
345392f7a3SLiteSpeed Tech        (hist)->sh_last_sent = 0;                                       \
3516a9b66aSDmitri Tikhonov} while (0)
3616a9b66aSDmitri Tikhonov
3716a9b66aSDmitri Tikhonov#define lsquic_senhist_cleanup(hist)
3816a9b66aSDmitri Tikhonov
3916a9b66aSDmitri Tikhonov#if LSQUIC_SENHIST_FATAL
4016a9b66aSDmitri Tikhonov#define lsquic_senhist_add(hist, packno) do {                           \
418ae5ecb4SDmitri Tikhonov    if (!((hist)->sh_flags & SH_GAP_OK)                                 \
428ae5ecb4SDmitri Tikhonov                        && (packno) > (hist)->sh_warn_thresh)           \
435392f7a3SLiteSpeed Tech        assert((hist)->sh_last_sent == packno - 1);                     \
445392f7a3SLiteSpeed Tech    if ((int64_t) (packno) > (int64_t) (hist)->sh_last_sent)            \
455392f7a3SLiteSpeed Tech        (hist)->sh_last_sent = packno;                                  \
4616a9b66aSDmitri Tikhonov} while (0)
4716a9b66aSDmitri Tikhonov#else
4816a9b66aSDmitri Tikhonov#define lsquic_senhist_add(hist, packno) do {                           \
495392f7a3SLiteSpeed Tech    if ((hist)->sh_last_sent != packno - 1)                             \
5016a9b66aSDmitri Tikhonov    {                                                                   \
518ae5ecb4SDmitri Tikhonov        if (!((hist)->sh_flags & (SH_WARNED|SH_GAP_OK))                 \
528ae5ecb4SDmitri Tikhonov                        && (packno) > (hist)->sh_warn_thresh)           \
5316a9b66aSDmitri Tikhonov        {                                                               \
5416a9b66aSDmitri Tikhonov            LSQ_WARN("send history gap %"PRIu64" - %"PRIu64,            \
5516a9b66aSDmitri Tikhonov                (hist)->sh_last_sent, packno);                          \
5616a9b66aSDmitri Tikhonov            (hist)->sh_flags |= SH_WARNED;                              \
5716a9b66aSDmitri Tikhonov        }                                                               \
5816a9b66aSDmitri Tikhonov    }                                                                   \
595392f7a3SLiteSpeed Tech    if ((int64_t) (packno) > (int64_t) (hist)->sh_last_sent)            \
605392f7a3SLiteSpeed Tech        (hist)->sh_last_sent = packno;                                  \
6116a9b66aSDmitri Tikhonov} while (0)
6216a9b66aSDmitri Tikhonov#endif
6350aadb33SDmitri Tikhonov
6450aadb33SDmitri Tikhonov/* Returns 0 if no packets have been sent yet */
6516a9b66aSDmitri Tikhonov#define lsquic_senhist_largest(hist) (+(hist)->sh_last_sent)
6650aadb33SDmitri Tikhonov
6750aadb33SDmitri Tikhonovvoid
6850aadb33SDmitri Tikhonovlsquic_senhist_tostr (lsquic_senhist_t *hist, char *buf, size_t bufsz);
6950aadb33SDmitri Tikhonov
7016a9b66aSDmitri Tikhonov#define lsquic_senhist_mem_used(hist) (sizeof(*(hist)))
71c51ce338SDmitri Tikhonov
7250aadb33SDmitri Tikhonov#endif
73