From ab82fab442dca5f71ac29a4f0289b333418e5c69 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Mon, 18 Nov 2024 14:57:39 +0100 Subject: [PATCH] MINOR: quic/pacing: implement quic_pacer engine Extend quic_pacer engine to support pacing emission. Several functions are defined. * quic_pacing_sent_done() to notify engine about an emission of one or several datagrams * quic_pacing_expired() to check if emission should be delayed or can be conducted immediately --- include/haproxy/quic_cc-t.h | 3 +++ include/haproxy/quic_cc.h | 4 +++- include/haproxy/quic_pacing-t.h | 1 + include/haproxy/quic_pacing.h | 5 +++++ src/quic_cc.c | 7 +++++++ src/quic_pacing.c | 14 ++++++++++++++ 6 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/haproxy/quic_cc-t.h b/include/haproxy/quic_cc-t.h index b4e72e78dc..d06b221169 100644 --- a/include/haproxy/quic_cc-t.h +++ b/include/haproxy/quic_cc-t.h @@ -123,6 +123,9 @@ struct quic_cc_algo { void (*state_trace)(struct buffer *buf, const struct quic_cc *cc); void (*state_cli)(struct buffer *buf, const struct quic_cc_path *path); void (*hystart_start_round)(struct quic_cc *cc, uint64_t pn); + + /* Defined only if pacing is used. */ + uint (*pacing_rate)(const struct quic_cc *cc); }; #endif /* USE_QUIC */ diff --git a/include/haproxy/quic_cc.h b/include/haproxy/quic_cc.h index 269a931016..b9ae6ccd39 100644 --- a/include/haproxy/quic_cc.h +++ b/include/haproxy/quic_cc.h @@ -37,6 +37,9 @@ void quic_cc_init(struct quic_cc *cc, struct quic_cc_algo *algo, struct quic_con void quic_cc_event(struct quic_cc *cc, struct quic_cc_event *ev); void quic_cc_state_trace(struct buffer *buf, const struct quic_cc *cc); +/* Pacing callbacks */ +uint quic_cc_default_pacing_rate(const struct quic_cc *cc); + static inline const char *quic_cc_state_str(enum quic_cc_algo_state_type state) { switch (state) { @@ -107,6 +110,5 @@ static inline size_t quic_cc_path_prep_data(struct quic_cc_path *path) return path->cwnd - path->prep_in_flight; } - #endif /* USE_QUIC */ #endif /* _PROTO_QUIC_CC_H */ diff --git a/include/haproxy/quic_pacing-t.h b/include/haproxy/quic_pacing-t.h index 2315c2f65e..01e3776fd4 100644 --- a/include/haproxy/quic_pacing-t.h +++ b/include/haproxy/quic_pacing-t.h @@ -6,6 +6,7 @@ struct quic_pacer { const struct quic_cc *cc; /* Congestion controler algo used for this connection */ + ullong next; /* Nanosecond timestamp at which the next emission should be conducted */ }; #endif /* _HAPROXY_QUIC_PACING_T_H */ diff --git a/include/haproxy/quic_pacing.h b/include/haproxy/quic_pacing.h index 5ef11a5319..f6e9228f01 100644 --- a/include/haproxy/quic_pacing.h +++ b/include/haproxy/quic_pacing.h @@ -10,6 +10,11 @@ static inline void quic_pacing_init(struct quic_pacer *pacer, const struct quic_cc *cc) { pacer->cc = cc; + pacer->next = 0; } +int quic_pacing_expired(const struct quic_pacer *pacer); + +void quic_pacing_sent_done(struct quic_pacer *pacer); + #endif /* _HAPROXY_QUIC_PACING_H */ diff --git a/src/quic_cc.c b/src/quic_cc.c index 8fd99d3c19..c09b9d890e 100644 --- a/src/quic_cc.c +++ b/src/quic_cc.c @@ -47,3 +47,10 @@ void quic_cc_state_trace(struct buffer *buf, const struct quic_cc *cc) { cc->algo->state_trace(buf, cc); } + +/* Return rate in nanoseconds between each datagram emission for a smooth pacing. */ +uint quic_cc_default_pacing_rate(const struct quic_cc *cc) +{ + struct quic_cc_path *path = container_of(cc, struct quic_cc_path, cc); + return path->loss.srtt * 1000000 / (path->cwnd / path->mtu + 1); +} diff --git a/src/quic_pacing.c b/src/quic_pacing.c index faee5e81c2..9afe957092 100644 --- a/src/quic_pacing.c +++ b/src/quic_pacing.c @@ -1 +1,15 @@ #include + +#include + +/* Returns true if timer is expired and emission can be retried. */ +int quic_pacing_expired(const struct quic_pacer *pacer) +{ + return !pacer->next || pacer->next <= now_mono_time(); +} + +/* Notify about an emission of one datagram. */ +void quic_pacing_sent_done(struct quic_pacer *pacer) +{ + pacer->next = now_mono_time() + pacer->cc->algo->pacing_rate(pacer->cc); +}