Skip to content

Commit c08b877

Browse files
committed
MINOR: window_filter: Implement windowed filter (only max)
Implement the Kathleen Nichols' algorithm used by several congestion control algorithm implementation (TCP/BBR in Linux kernel, QUIC/BBR in quiche) to track the maximum value of a data type during a fixe time interval. In this implementation, counters which are periodically reset are used in place of timestamps. Only the max part has been implemented. (see lib/minmax.c implemenation for Linux kernel).
1 parent 7bbe882 commit c08b877

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

include/haproxy/window_filter.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#ifndef _HAPROXY_WINDOW_FILTER_H
2+
#define _HAPROXY_WINDOW_FILTER_H
3+
4+
/* Kathleen Nichols' algorithm to track the maximum values of a data type during
5+
* a fixed time interval. This algorithm makes usage of three samples to track
6+
* the best, second best and third best values with 1st >= 2nd >= 3rd as
7+
* invariant.
8+
*
9+
* This code is used in Linux kernel in linux/win_minmax.c to track both
10+
* minimal and maximum values.
11+
*
12+
* Here the code has been adapted to track 64 bits values and only their
13+
* maximum.
14+
*
15+
* Note that these windowed filters are used by BBR to filter the maximum
16+
* estimated bandwidth with counters as time values. A length has been
17+
* added to simulate the fixed time interval with counter which are
18+
* monotonically increasing.
19+
*/
20+
21+
/* Windowed filter sample */
22+
struct wf_smp {
23+
uint64_t v;
24+
uint32_t t;
25+
};
26+
27+
/* Windowed filter */
28+
struct wf {
29+
size_t len;
30+
struct wf_smp smp[3];
31+
};
32+
33+
/* Reset all the <wf> windowed filter samples with <v> and <t> as value and
34+
* time value respectively.
35+
*/
36+
static inline uint64_t wf_reset(struct wf *wf, uint64_t v, uint32_t t)
37+
{
38+
struct wf_smp smp = { .v = v, .t = t };
39+
40+
wf->smp[2] = wf->smp[1] = wf->smp[0] = smp;
41+
42+
return wf->smp[0].v;
43+
}
44+
45+
/* Initialize <wf> windowed filter to track maximum values, with <len> as
46+
* length and <v> and <t> as value and time value respectively.
47+
*/
48+
static inline void wf_init(struct wf *wf, size_t len, uint64_t v, uint32_t t)
49+
{
50+
wf->len = len;
51+
wf_reset(wf, v, t);
52+
}
53+
54+
/* Similar to minmax_running_max() Linux kernel function to update the best
55+
* estimation of <wf> windowed filted with <v> and <t> as value and time value
56+
* respectively
57+
*/
58+
static inline uint64_t wf_max_update(struct wf *wf, uint64_t v, uint32_t t)
59+
{
60+
uint64_t delta_t;
61+
struct wf_smp smp = { .v = v, .t = t };
62+
63+
/* Reset all estimates if they have not yet been initialized, if new
64+
sample is a new best, or if the newest recorded estimate is too
65+
old. */
66+
if (unlikely(v > wf->smp[0].v) || unlikely(t - wf->smp[2].t > wf->len))
67+
return wf_reset(wf, v, t);
68+
69+
if (unlikely(v > wf->smp[1].v))
70+
wf->smp[2] = wf->smp[1] = smp;
71+
else if (unlikely(v > wf->smp[2].v))
72+
wf->smp[2] = smp;
73+
74+
delta_t = t - wf->smp[0].t;
75+
/* From here, similar to minmax_subwin_update() from Linux kernel. */
76+
if (unlikely(delta_t > wf->len)) {
77+
wf->smp[0] = wf->smp[1];
78+
wf->smp[1] = wf->smp[2];
79+
wf->smp[2].v = v;
80+
wf->smp[2].t = t;
81+
82+
if (unlikely(t - wf->smp[0].t > wf->len)) {
83+
wf->smp[0] = wf->smp[1];
84+
wf->smp[1] = wf->smp[2];
85+
}
86+
} else if (unlikely(wf->smp[1].v == wf->smp[0].v) && delta_t > wf->len / 4) {
87+
wf->smp[2].v = v;
88+
wf->smp[2].t = t;
89+
wf->smp[1] = wf->smp[2];
90+
} else if (unlikely(wf->smp[2].v == wf->smp[1].v) && delta_t > wf->len / 2) {
91+
wf->smp[2].v = v;
92+
wf->smp[2].t = t;
93+
}
94+
95+
return wf->smp[0].v;
96+
}
97+
98+
/* Return <wf> windowed filter best maximum estimation. */
99+
static inline uint64_t wf_get_max(struct wf *wf)
100+
{
101+
return wf->smp[0].v;
102+
}
103+
104+
#endif /* _HAPROXY_WINDOW_FILTER_H */

0 commit comments

Comments
 (0)