1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * lsquic_eng_hist.h - Engine history.
450aadb33SDmitri Tikhonov *
550aadb33SDmitri Tikhonov * Keep track of new and destroyed connections, packets in and packets out.
650aadb33SDmitri Tikhonov */
750aadb33SDmitri Tikhonov
850aadb33SDmitri Tikhonov#ifndef LSQUIC_ENG_HIST
950aadb33SDmitri Tikhonov#define LSQUIC_ENG_HIST
1050aadb33SDmitri Tikhonov
1150aadb33SDmitri Tikhonov#define ENG_HIST_ENABLED 1
1250aadb33SDmitri Tikhonov
1350aadb33SDmitri Tikhonov#define ENG_HIST_BITS    2
1450aadb33SDmitri Tikhonov#define ENG_HIST_NELEMS (1 << ENG_HIST_BITS)
1550aadb33SDmitri Tikhonov
1650aadb33SDmitri Tikhonov#ifndef ENG_HIST_N_TO_PRINT
1750aadb33SDmitri Tikhonov    /* By default, we do not print the whole history every second just
1850aadb33SDmitri Tikhonov     * the latest entry.
1950aadb33SDmitri Tikhonov     */
2050aadb33SDmitri Tikhonov#   define ENG_HIST_N_TO_PRINT 1
2150aadb33SDmitri Tikhonov#endif
2250aadb33SDmitri Tikhonov
2350aadb33SDmitri Tikhonov
2450aadb33SDmitri Tikhonov/* Keeps history per slice of time -- one second */
2550aadb33SDmitri Tikhonovstruct hist_slice
2650aadb33SDmitri Tikhonov{
2750aadb33SDmitri Tikhonov    unsigned    sl_packets_in,
2850aadb33SDmitri Tikhonov                sl_packets_out,
2950aadb33SDmitri Tikhonov                sl_new_full_conns,
3050aadb33SDmitri Tikhonov                sl_new_mini_conns,
3150aadb33SDmitri Tikhonov                sl_del_full_conns,
3250aadb33SDmitri Tikhonov                sl_del_mini_conns;
3350aadb33SDmitri Tikhonov};
3450aadb33SDmitri Tikhonov
3550aadb33SDmitri Tikhonov
3650aadb33SDmitri Tikhonovstruct eng_hist
3750aadb33SDmitri Tikhonov{
3850aadb33SDmitri Tikhonov    struct hist_slice   eh_slices[ENG_HIST_NELEMS];
3950aadb33SDmitri Tikhonov    unsigned            eh_cur_idx,
4050aadb33SDmitri Tikhonov                        eh_prev_idx;
4150aadb33SDmitri Tikhonov};
4250aadb33SDmitri Tikhonov
4350aadb33SDmitri Tikhonov
4450aadb33SDmitri Tikhonov#if ENG_HIST_ENABLED
4550aadb33SDmitri Tikhonov
4650aadb33SDmitri Tikhonov/* Initialize engine history */
4750aadb33SDmitri Tikhonov#define eng_hist_init(eh) do {                                              \
4850aadb33SDmitri Tikhonov    memset(eh, 0, sizeof(*(eh)));                                           \
4950aadb33SDmitri Tikhonov    (eh)->eh_cur_idx = (eh)->eh_prev_idx =                                  \
5050aadb33SDmitri Tikhonov                            time(NULL) & (ENG_HIST_NELEMS - 1);             \
5150aadb33SDmitri Tikhonov} while (0)
5250aadb33SDmitri Tikhonov
5350aadb33SDmitri Tikhonov
5450aadb33SDmitri Tikhonov/* Clear slice at current index */
5550aadb33SDmitri Tikhonov#define eng_hist_clear_cur(eh) do {                                         \
5650aadb33SDmitri Tikhonov    memset(&(eh)->eh_slices[(eh)->eh_cur_idx], 0,                           \
5750aadb33SDmitri Tikhonov                                    sizeof(struct hist_slice));             \
5850aadb33SDmitri Tikhonov} while (0)
5950aadb33SDmitri Tikhonov
6050aadb33SDmitri Tikhonov
6150aadb33SDmitri Tikhonovvoid
62a5fa05f9SDmitri Tikhonovlsquic_eng_hist_log (const struct eng_hist *);
6350aadb33SDmitri Tikhonov
6450aadb33SDmitri Tikhonov
6550aadb33SDmitri Tikhonov/* Switch to next slice if necessary */
6650aadb33SDmitri Tikhonov#define eng_hist_tick(eh, now) do {                                         \
6750aadb33SDmitri Tikhonov    if (0 == (now))                                                         \
6850aadb33SDmitri Tikhonov        (eh)->eh_cur_idx = time(NULL)        & (ENG_HIST_NELEMS - 1);       \
6950aadb33SDmitri Tikhonov    else                                                                    \
7050aadb33SDmitri Tikhonov        (eh)->eh_cur_idx = ((now) / 1000000) & (ENG_HIST_NELEMS - 1);       \
7150aadb33SDmitri Tikhonov    if ((eh)->eh_cur_idx != (eh)->eh_prev_idx)                              \
7250aadb33SDmitri Tikhonov    {                                                                       \
73a5fa05f9SDmitri Tikhonov        lsquic_eng_hist_log(eh);                                            \
7450aadb33SDmitri Tikhonov        eng_hist_clear_cur(eh);                                             \
7550aadb33SDmitri Tikhonov        (eh)->eh_prev_idx = (eh)->eh_cur_idx;                               \
7650aadb33SDmitri Tikhonov    }                                                                       \
7750aadb33SDmitri Tikhonov} while (0)
7850aadb33SDmitri Tikhonov
7950aadb33SDmitri Tikhonov
8050aadb33SDmitri Tikhonov/* Increment element `what'.  Slice increment is handled in this macro, too. */
8150aadb33SDmitri Tikhonov#define eng_hist_inc(eh, now, what) do {                                    \
8250aadb33SDmitri Tikhonov    eng_hist_tick(eh, now);                                                 \
8350aadb33SDmitri Tikhonov    ++(eh)->eh_slices[(eh)->eh_cur_idx].what;                               \
8450aadb33SDmitri Tikhonov} while (0)
8550aadb33SDmitri Tikhonov
8650aadb33SDmitri Tikhonov#else /* !ENG_HIST_ENABLED */
8750aadb33SDmitri Tikhonov
8850aadb33SDmitri Tikhonov#define eng_hist_init(eh)
8950aadb33SDmitri Tikhonov#define eng_hist_clear_cur(eh)
9050aadb33SDmitri Tikhonov#define eng_hist_tick(eh, now)
9150aadb33SDmitri Tikhonov#define eng_hist_inc(eh, now, what)
92a5fa05f9SDmitri Tikhonov#define lsquic_eng_hist_log(eh)
9350aadb33SDmitri Tikhonov
9450aadb33SDmitri Tikhonov#endif  /* ENG_HIST_ENABLED */
9550aadb33SDmitri Tikhonov
9650aadb33SDmitri Tikhonov#endif  /* LSQUIC_ENG_HIST */
97