diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index 22fd1b910..de68a40ff 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -68,6 +68,7 @@ struct qcc { struct { struct quic_fctl fc; /* stream flow control applied on sending */ int avail_bufs; /* count of available buffers for this connection */ + uint64_t buf_in_flight; /* sum of currently allocated Tx buffer sizes */ } tx; uint64_t largest_bidi_r; /* largest remote bidi stream ID opened. */ diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index c61044760..f1ed218a5 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -23,7 +23,7 @@ int qcs_is_close_remote(struct qcs *qcs); int qcs_subscribe(struct qcs *qcs, int event_type, struct wait_event *es); void qcs_notify_recv(struct qcs *qcs); void qcs_notify_send(struct qcs *qcs); -void qcc_notify_buf(struct qcc *qcc, int free_count); +void qcc_notify_buf(struct qcc *qcc, int free_count, uint64_t free_size); struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs); struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err); diff --git a/src/mux_quic.c b/src/mux_quic.c index dd315d078..d30ca2976 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -524,10 +524,10 @@ void qcs_notify_send(struct qcs *qcs) } } -/* Report that stream-desc buffer have been released for - * connection. +/* Report that one or several stream-desc buffers have been released for + * connection. represent the sum of freed buffers sizes. */ -void qcc_notify_buf(struct qcc *qcc, int free_count) +void qcc_notify_buf(struct qcc *qcc, int free_count, uint64_t free_size) { struct qcs *qcs; @@ -536,6 +536,10 @@ void qcc_notify_buf(struct qcc *qcc, int free_count) BUG_ON(qcc->tx.avail_bufs + free_count > global.tune.quic_streams_buf); qcc->tx.avail_bufs += free_count; + /* Cannot have a negative buf_in_flight counter */ + BUG_ON(qcc->tx.buf_in_flight < free_size); + qcc->tx.buf_in_flight -= free_size; + if (qcc->flags & QC_CF_CONN_FULL) { TRACE_STATE("new stream desc buffer available", QMUX_EV_QCC_WAKE, qcc->conn); qcc->flags &= ~QC_CF_CONN_FULL; @@ -1059,8 +1063,10 @@ struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err) goto out; } - if (likely(!unlimited)) + if (likely(!unlimited)) { --qcc->tx.avail_bufs; + qcc->tx.buf_in_flight += global.tune.bufsize; + } } out: @@ -2728,6 +2734,7 @@ static int qmux_init(struct connection *conn, struct proxy *prx, qcc->rfctl.msd_uni_l = rparams->initial_max_stream_data_uni; qcc->tx.avail_bufs = global.tune.quic_streams_buf; + qcc->tx.buf_in_flight = 0; if (conn_is_back(conn)) { qcc->next_bidi_l = 0x00; diff --git a/src/quic_stream.c b/src/quic_stream.c index a0baa0b98..c99266978 100644 --- a/src/quic_stream.c +++ b/src/quic_stream.c @@ -28,6 +28,7 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream, { struct quic_conn *qc = stream->qc; struct buffer *buf = &(*stream_buf)->buf; + uint64_t free_size; LIST_DEL_INIT(&(*stream_buf)->list); @@ -35,6 +36,7 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream, if (*stream_buf == stream->buf) stream->buf = NULL; + free_size = b_size(buf); b_free(buf); offer_buffers(NULL, 1); pool_free(pool_head_quic_stream_buf, *stream_buf); @@ -44,7 +46,7 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream, if (qc->mux_state == QC_MUX_READY) { if (!(stream->flags & QC_SD_FL_OOB_BUF)) { /* notify MUX about available buffers. */ - qcc_notify_buf(qc->qcc, 1); + qcc_notify_buf(qc->qcc, 1, free_size); } } } @@ -200,6 +202,7 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing) struct quic_conn *qc = stream->qc; struct eb64_node *frm_node; unsigned int free_count = 0; + uint64_t free_size = 0; /* This function only deals with released streams. */ BUG_ON(!(stream->flags & QC_SD_FL_RELEASE)); @@ -207,6 +210,7 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing) /* free remaining stream buffers */ list_for_each_entry_safe(buf, buf_back, &stream->buf_list, list) { if (!(b_data(&buf->buf)) || closing) { + free_size += b_size(&buf->buf); b_free(&buf->buf); LIST_DELETE(&buf->list); pool_free(pool_head_quic_stream_buf, buf); @@ -220,7 +224,7 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing) if (qc->mux_state == QC_MUX_READY) { if (!(stream->flags & QC_SD_FL_OOB_BUF)) { /* notify MUX about available buffers. */ - qcc_notify_buf(qc->qcc, free_count); + qcc_notify_buf(qc->qcc, free_count, free_size); } } }