1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_BW_SAMPLER_H
3#define LSQUIC_BW_SAMPLER_H 1
4
5/* Translated from Chromium. */
6// Copyright 2016 The Chromium Authors. All rights reserved.
7
8struct lsquic_packet_out;
9
10/* This struct provides a type for bits per second units.  It's made into
11 * a struct so that it is a little harder to make a mistake.  The Chromium
12 * equivalent of this is QuicBandwidth.  Use macros to operate.
13 */
14struct bandwidth
15{
16    uint64_t            value;  /* Bits per second */
17};
18
19#define BW_INFINITE() ((struct bandwidth) { .value = UINT64_MAX, })
20#define BW_ZERO() ((struct bandwidth) { .value = 0, })
21#define BW_FROM_BYTES_AND_DELTA(bytes_, usecs_) \
22    ((struct bandwidth) { .value = (bytes_) * 8 * 1000000 / (usecs_), })
23#define BW_IS_ZERO(bw_) ((bw_)->value == 0)
24#define BW_TO_BYTES_PER_SEC(bw_) ((bw_)->value / 8)
25#define BW_VALUE(bw_) (+(bw_)->value)
26#define BW_TIMES(bw_, factor_) \
27                ((struct bandwidth) { .value = BW_VALUE(bw_) * (factor_), })
28#define BW(initial_value_) ((struct bandwidth) { .value = (initial_value_) })
29
30struct bw_sampler
31{
32    struct lsquic_conn *bws_conn;
33    uint64_t            bws_total_sent,
34                        bws_total_acked,
35                        bws_total_lost;
36    /* Value of bws_total_sent at the time last ACKed packet was sent.  Only
37     * valid if bws_last_acked_sent_time is valid.
38     */
39    uint64_t            bws_last_acked_total_sent;
40    /* Time when last acked packet was sent.  Zero if no valid timestamp is
41     * available.
42     */
43    lsquic_time_t       bws_last_acked_sent_time;
44    lsquic_time_t       bws_last_acked_packet_time;
45    lsquic_packno_t     bws_last_sent_packno;
46    lsquic_packno_t     bws_end_of_app_limited_phase;
47    struct malo        *bws_malo;   /* For struct osp_state objects */
48    enum quic_ft_bit    bws_retx_frames;
49    enum {
50        BWS_CONN_ABORTED    = 1 << 0,
51        BWS_WARNED          = 1 << 1,
52        BWS_APP_LIMITED     = 1 << 2,
53    }                   bws_flags;
54};
55
56struct bw_sample
57{
58    TAILQ_ENTRY(bw_sample)      next;
59    struct bandwidth            bandwidth;
60    lsquic_time_t               rtt;
61    int                         is_app_limited;
62};
63
64int
65lsquic_bw_sampler_init (struct bw_sampler *, struct lsquic_conn *,
66                                                            enum quic_ft_bit);
67
68void
69lsquic_bw_sampler_packet_sent (struct bw_sampler *, struct lsquic_packet_out *,
70                                                            uint64_t in_flight);
71
72/* Free returned sample via lsquic_malo_put() after you're done */
73struct bw_sample *
74lsquic_bw_sampler_packet_acked (struct bw_sampler *, struct lsquic_packet_out *,
75                            lsquic_time_t ack_time);
76
77void
78lsquic_bw_sampler_packet_lost (struct bw_sampler *, struct lsquic_packet_out *);
79
80void
81lsquic_bw_sampler_app_limited (struct bw_sampler *);
82
83void
84lsquic_bw_sampler_cleanup (struct bw_sampler *);
85
86unsigned
87lsquic_bw_sampler_entry_count (const struct bw_sampler *);
88
89#define lsquic_bw_sampler_total_acked(sampler_) (+(sampler_)->bws_total_acked)
90
91/* The following types are exposed in the header file because of unit tests.
92 * Do not use outside of lsquic_bw_sampler.c.
93 */
94struct bwps_send_state
95{
96    uint64_t    total_bytes_sent,
97                total_bytes_acked,
98                total_bytes_lost;
99    int         is_app_limited;
100};
101
102struct bwp_state    /* BWP State stands for Bandwidth Packet State */
103{
104    struct bwps_send_state      bwps_send_state;
105    uint64_t                    bwps_sent_at_last_ack;
106    lsquic_time_t               bwps_last_ack_sent_time;
107    lsquic_time_t               bwps_last_ack_ack_time;
108    unsigned short              bwps_packet_size;
109};
110
111#endif
112