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