diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index e56045b575..a0f8e0dbdf 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -71,6 +71,7 @@ struct qcc { uint64_t buf_in_flight; /* sum of currently allocated Tx buffer sizes */ struct list frms; /* list of STREAM frames ready for sent */ struct quic_pacer pacer; /* engine used to pace emission */ + int paced_sent_ctr; /* counter for when emission is interrupted due to pacing */ } tx; uint64_t largest_bidi_r; /* largest remote bidi stream ID opened. */ diff --git a/include/haproxy/quic_pacing-t.h b/include/haproxy/quic_pacing-t.h index 01e3776fd4..2c7d9338f8 100644 --- a/include/haproxy/quic_pacing-t.h +++ b/include/haproxy/quic_pacing-t.h @@ -7,6 +7,8 @@ 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 */ + + int last_sent; /* Number of datagrams sent during last paced emission */ }; #endif /* _HAPROXY_QUIC_PACING_T_H */ diff --git a/src/mux_quic.c b/src/mux_quic.c index 4c1d1c4dc4..1210ed2866 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -2443,6 +2443,7 @@ static int qcc_io_send(struct qcc *qcc) /* qcc_send_frames cannot return 1 if pacing not used. */ BUG_ON(!qcc_is_pacing_active(qcc->conn)); qcc_wakeup_pacing(qcc); + ++qcc->tx.paced_sent_ctr; } else if (!LIST_ISEMPTY(&qcc->tx.frms)) { /* Deallocate frames that the transport layer has rejected. */ @@ -2799,17 +2800,22 @@ static void qcc_purge_sending(struct qcc *qcc) struct quic_pacer *pacer = &qcc->tx.pacer; struct list *frms = &qcc->tx.frms; enum quic_tx_err ret = QUIC_TX_ERR_PACING; + int sent = 0; /* This function is reserved for pacing usage. */ BUG_ON(!qcc_is_pacing_active(qcc->conn)); /* Only restart emission if pacing delay is reached. */ - if (quic_pacing_expired(pacer)) + if (quic_pacing_expired(pacer)) { ret = qc_send_mux(qcc->conn->handle.qc, frms, pacer); + sent = 1; + } if (ret == QUIC_TX_ERR_PACING) { BUG_ON(LIST_ISEMPTY(frms)); qcc_wakeup_pacing(qcc); + if (sent) + ++qcc->tx.paced_sent_ctr; } else if (ret == QUIC_TX_ERR_FATAL) { TRACE_DEVEL("error on sending", QMUX_EV_QCC_SEND, qcc->conn); @@ -2960,8 +2966,10 @@ static int qmux_init(struct connection *conn, struct proxy *prx, qcc->tx.buf_in_flight = 0; - if (qcc_is_pacing_active(conn)) + if (qcc_is_pacing_active(conn)) { quic_pacing_init(&qcc->tx.pacer, &conn->handle.qc->path->cc); + qcc->tx.paced_sent_ctr = 0; + } if (conn_is_back(conn)) { qcc->next_bidi_l = 0x00; @@ -3594,6 +3602,12 @@ void qcc_show_quic(struct qcc *qcc) qcc, qcc->flags, (ullong)qcc->nb_sc, (ullong)qcc->nb_hreq, (ullong)qcc->tx.buf_in_flight, (ullong)qc->path->cwnd); + if (qcc_is_pacing_active(qcc->conn)) { + chunk_appendf(&trash, " pacing int_sent=%d last_sent=%d\n", + qcc->tx.paced_sent_ctr, + qcc->tx.pacer.last_sent); + } + node = eb64_first(&qcc->streams_by_id); while (node) { struct qcs *qcs = eb64_entry(node, struct qcs, by_id); diff --git a/src/quic_pacing.c b/src/quic_pacing.c index e719b6b18d..7b1e5b9dc1 100644 --- a/src/quic_pacing.c +++ b/src/quic_pacing.c @@ -12,4 +12,5 @@ int quic_pacing_expired(const struct quic_pacer *pacer) void quic_pacing_sent_done(struct quic_pacer *pacer, int sent) { pacer->next = now_mono_time() + pacer->cc->algo->pacing_rate(pacer->cc) * sent; + pacer->last_sent = sent; }