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 */
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) {
return path->cwnd - path->prep_in_flight;
}
-
#endif /* USE_QUIC */
#endif /* _PROTO_QUIC_CC_H */
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 */
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 */
{
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);
+}
#include <haproxy/quic_pacing.h>
+
+#include <haproxy/quic_tx.h>
+
+/* Returns true if <pacer> 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 <pacer> 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);
+}