1 /*
2  * Copyright (c) 2021 Fastly, Kazuho Oku
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 
23 #ifndef quicly_rate_h
24 #define quicly_rate_h
25 
26 #include <stdint.h>
27 #include "quicly/ranges.h"
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 #ifndef QUICLY_DELIVERY_RATE_SAMPLE_PERIOD
34 /**
35  * sampling period of delivery rate, in milliseconds
36  */
37 #define QUICLY_DELIVERY_RATE_SAMPLE_PERIOD 50
38 #endif
39 
40 #ifndef QUICLY_DELIVERY_RATE_SAMPLE_COUNT
41 /**
42  * number of samples to retain (and to calculate average from)
43  */
44 #define QUICLY_DELIVERY_RATE_SAMPLE_COUNT 10
45 #endif
46 
47 struct st_quicly_rate_sample_t {
48     uint32_t elapsed;
49     uint32_t bytes_acked;
50 };
51 
52 /**
53  * State used for estimating the delivery rate.
54  */
55 typedef struct st_quicly_ratemeter_t {
56     /**
57      * ring buffer retaining the most recent samples
58      */
59     struct {
60         struct st_quicly_rate_sample_t entries[QUICLY_DELIVERY_RATE_SAMPLE_COUNT];
61         size_t latest;
62     } past_samples;
63     /**
64      * packet number range within which the flow has been CWND-limited
65      */
66     quicly_range_t pn_cwnd_limited;
67     /**
68      * Current sample being collected, if any. When running, `start.at` and `start.bytes_acked` retains the values at the start of
69      * the current sampling period. When not, `start.at` is set to INT64_MAX, and `sample` is zero-cleared.
70      */
71     struct {
72         struct {
73             int64_t at;
74             uint64_t bytes_acked;
75         } start;
76         struct st_quicly_rate_sample_t sample;
77     } current;
78 } quicly_ratemeter_t;
79 
80 /**
81  * Estimated delivery rate, in bytes / second.
82  */
83 typedef struct st_quicly_rate_t {
84     uint64_t latest;
85     uint64_t smoothed;
86     uint64_t stdev;
87 } quicly_rate_t;
88 
89 /**
90  *
91  */
92 void quicly_ratemeter_init(quicly_ratemeter_t *meter);
93 /**
94  * Notifies the estimator that the flow is CWND-limited at the point of sending packets *starting* from packet number `pn`.
95  */
96 void quicly_ratemeter_in_cwnd_limited(quicly_ratemeter_t *meter, uint64_t pn);
97 /**
98  * Notifies that the estimator that the flow is not CWND-limited when the packet number of the next packet will be `pn`.
99  */
100 void quicly_ratemeter_not_cwnd_limited(quicly_ratemeter_t *meter, uint64_t pn);
101 /**
102  * Given three values, update the estimation.
103  * @param bytes_acked  total number of bytes being acked from the beginning of the connection; i.e.,
104  *                     `quicly_stats_t::num_bytes.ack_received`
105  */
106 void quicly_ratemeter_on_ack(quicly_ratemeter_t *meter, int64_t now, uint64_t bytes_acked, uint64_t pn);
107 /**
108  * Returns the delivery rate estimate
109  */
110 void quicly_ratemeter_report(quicly_ratemeter_t *meter, quicly_rate_t *rate);
111 
112 #ifdef __cplusplus
113 }
114 #endif
115 
116 #endif
117