diff --git a/include/haproxy/proto_quic.h b/include/haproxy/proto_quic.h index b6f473c6d..1da8da8fe 100644 --- a/include/haproxy/proto_quic.h +++ b/include/haproxy/proto_quic.h @@ -30,4 +30,6 @@ extern struct protocol proto_quic6; extern struct quic_dghdlr *quic_dghdlrs; +extern THREAD_LOCAL struct cshared quic_mem_diff; + #endif /* _HAPROXY_PROTO_QUIC_H */ diff --git a/include/haproxy/quic_cc.h b/include/haproxy/quic_cc.h index 6569799ff..4360a5af0 100644 --- a/include/haproxy/quic_cc.h +++ b/include/haproxy/quic_cc.h @@ -29,9 +29,11 @@ #include #include #include +#include #include #include #include +#include void quic_cc_init(struct quic_cc *cc, struct quic_cc_algo *algo, struct quic_conn *qc); void quic_cc_event(struct quic_cc *cc, struct quic_cc_event *ev); @@ -91,6 +93,7 @@ static inline void quic_cc_path_init(struct quic_cc_path *path, int ipv4, unsign *(size_t *)&path->mtu = max_dgram_sz; path->initial_wnd = QUIC_MIN(10 * max_dgram_sz, QUIC_MAX(max_dgram_sz << 1, 14720U)); path->cwnd = path->initial_wnd; + cshared_add(&quic_mem_diff, path->cwnd); path->cwnd_last_max = path->cwnd; path->limit_max = max_cwnd; path->limit_min = max_dgram_sz << 1; diff --git a/src/proto_quic.c b/src/proto_quic.c index a0e9812c7..7dfe5fd32 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -48,11 +48,15 @@ #include #include #include +#include #include /* per-thread quic datagram handlers */ struct quic_dghdlr *quic_dghdlrs; +static uint64_t quic_mem_global; +THREAD_LOCAL struct cshared quic_mem_diff; + /* Size of the internal buffer of QUIC RX buffer at the fd level */ #define QUIC_RX_BUFSZ (1UL << 18) @@ -659,6 +663,14 @@ static void quic_bind_tid_reset(struct connection *conn) qc_bind_tid_reset(qc); } +static int quic_init_mem(void) +{ + /* 1024 is enough to limit modification on global counter but keeping it precise enough even with a lot of threads */ + cshared_init(&quic_mem_diff, &quic_mem_global, 1024); + return 1; +} +REGISTER_PER_THREAD_INIT(quic_init_mem); + static int quic_alloc_dghdlrs(void) { int i; diff --git a/src/quic_cc.c b/src/quic_cc.c index 0d9151ebb..31bb6e797 100644 --- a/src/quic_cc.c +++ b/src/quic_cc.c @@ -20,8 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include +#include struct quic_cc_algo *default_quic_cc_algo = &quic_cc_algo_cubic; @@ -79,14 +81,19 @@ static int quic_cwnd_may_increase(const struct quic_cc_path *path) /* Restore congestion window for to its minimal value. */ void quic_cc_path_reset(struct quic_cc_path *path) { + const uint64_t old = path->cwnd; path->cwnd = path->limit_min; + cshared_add(&quic_mem_diff, path->cwnd - old); } /* Set congestion window for to . Min and max limits are enforced. */ void quic_cc_path_set(struct quic_cc_path *path, uint64_t val) { + const uint64_t old = path->cwnd; + path->cwnd = QUIC_MIN(val, path->limit_max); path->cwnd = QUIC_MAX(path->cwnd, path->limit_min); + cshared_add(&quic_mem_diff, path->cwnd - old); path->cwnd_last_max = QUIC_MAX(path->cwnd, path->cwnd_last_max); } @@ -97,9 +104,12 @@ void quic_cc_path_set(struct quic_cc_path *path, uint64_t val) */ void quic_cc_path_inc(struct quic_cc_path *path, uint64_t val) { + const uint64_t old = path->cwnd; + if (quic_cwnd_may_increase(path)) { path->cwnd = QUIC_MIN(path->cwnd + val, path->limit_max); path->cwnd = QUIC_MAX(path->cwnd, path->limit_min); + cshared_add(&quic_mem_diff, path->cwnd - old); path->cwnd_last_max = QUIC_MAX(path->cwnd, path->cwnd_last_max); } diff --git a/src/quic_conn.c b/src/quic_conn.c index 547c89817..51ace545f 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -1442,6 +1442,10 @@ void quic_conn_release(struct quic_conn *qc) HA_ATOMIC_DEC(&qc->li->rx.quic_curr_accept); } + /* Substract last congestion window from global memory counter. */ + cshared_add(&quic_mem_diff, -qc->path->cwnd); + qc->path->cwnd = 0; + /* free remaining stream descriptors */ node = eb64_first(&qc->streams_by_id); while (node) {