Skip to content

Commit 4a94a01

Browse files
committed
MINOR: mux-quic: define a tx STREAM frame list member
For STREAM emission, MUX QUIC previously used a local list defined under qcc_io_send(). This was suitable as either all frames were sent, or emission must be interrupted due to transport congestion or fatal error. In the latter case, the list was emptied anyway and a new frame list was built on future qcc_io_send() invokation. For pacing, MUX QUIC may have to save the frame list if pacing should be applied across emission. This is necessary to avoid to unnecessarily rebuilt stream frame list between each paced emission. To support this, STREAM list is now stored as a member of QCC structure. Ensure frame list is always deleted, even on QCC release, using newly defined utility function qcc_tx_frms_free().
1 parent 886a7c4 commit 4a94a01

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

include/haproxy/mux_quic-t.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct qcc {
6868
struct {
6969
struct quic_fctl fc; /* stream flow control applied on sending */
7070
uint64_t buf_in_flight; /* sum of currently allocated Tx buffer sizes */
71+
struct list frms; /* list of STREAM frames ready for sent */
7172
} tx;
7273

7374
uint64_t largest_bidi_r; /* largest remote bidi stream ID opened. */

src/mux_quic.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ DECLARE_POOL(pool_head_qcs, "qcs", sizeof(struct qcs));
3636
static void qmux_ctrl_send(struct qc_stream_desc *, uint64_t data, uint64_t offset);
3737
static void qmux_ctrl_room(struct qc_stream_desc *, uint64_t room);
3838

39+
/* Free <qcc> STREAM frames in Tx list. */
40+
static void qcc_tx_frms_free(struct qcc *qcc)
41+
{
42+
while (!LIST_ISEMPTY(&qcc->tx.frms)) {
43+
struct quic_frame *frm = LIST_ELEM(qcc->tx.frms.n, struct quic_frame *, list);
44+
qc_frm_free(qcc->conn->handle.qc, &frm);
45+
}
46+
}
47+
3948
static void qcs_free_ncbuf(struct qcs *qcs, struct ncbuf *ncbuf)
4049
{
4150
struct buffer buf;
@@ -2247,7 +2256,7 @@ static int qcs_send(struct qcs *qcs, struct list *frms, uint64_t window_conn)
22472256
*/
22482257
static int qcc_io_send(struct qcc *qcc)
22492258
{
2250-
struct list frms = LIST_HEAD_INIT(frms);
2259+
struct list *frms = &qcc->tx.frms;
22512260
/* Temporary list for QCS on error. */
22522261
struct list qcs_failed = LIST_HEAD_INIT(qcs_failed);
22532262
struct qcs *qcs, *qcs_tmp, *first_qcs = NULL;
@@ -2341,7 +2350,7 @@ static int qcc_io_send(struct qcc *qcc)
23412350

23422351
if (!qfctl_rblocked(&qcc->tx.fc) &&
23432352
!qfctl_rblocked(&qcs->tx.fc) && window_conn > total) {
2344-
if ((ret = qcs_send(qcs, &frms, window_conn - total)) < 0) {
2353+
if ((ret = qcs_send(qcs, frms, window_conn - total)) < 0) {
23452354
/* Temporarily remove QCS from send-list. */
23462355
LIST_DEL_INIT(&qcs->el_send);
23472356
LIST_APPEND(&qcs_failed, &qcs->el_send);
@@ -2365,7 +2374,7 @@ static int qcc_io_send(struct qcc *qcc)
23652374
/* Retry sending until no frame to send, data rejected or connection
23662375
* flow-control limit reached.
23672376
*/
2368-
while (qcc_send_frames(qcc, &frms) == 0 && !qfctl_rblocked(&qcc->tx.fc)) {
2377+
while (qcc_send_frames(qcc, frms) == 0 && !qfctl_rblocked(&qcc->tx.fc)) {
23692378
window_conn = qfctl_rcap(&qcc->tx.fc);
23702379
resent = 0;
23712380

@@ -2383,7 +2392,7 @@ static int qcc_io_send(struct qcc *qcc)
23832392
BUG_ON(resent > window_conn);
23842393

23852394
if (!qfctl_rblocked(&qcs->tx.fc) && window_conn > resent) {
2386-
if ((ret = qcs_send(qcs, &frms, window_conn - resent)) < 0) {
2395+
if ((ret = qcs_send(qcs, frms, window_conn - resent)) < 0) {
23872396
LIST_DEL_INIT(&qcs->el_send);
23882397
LIST_APPEND(&qcs_failed, &qcs->el_send);
23892398
continue;
@@ -2397,12 +2406,7 @@ static int qcc_io_send(struct qcc *qcc)
23972406

23982407
sent_done:
23992408
/* Deallocate frames that the transport layer has rejected. */
2400-
if (!LIST_ISEMPTY(&frms)) {
2401-
struct quic_frame *frm, *frm2;
2402-
2403-
list_for_each_entry_safe(frm, frm2, &frms, list)
2404-
qc_frm_free(qcc->conn->handle.qc, &frm);
2405-
}
2409+
qcc_tx_frms_free(qcc);
24062410

24072411
/* Re-insert on-error QCS at the end of the send-list. */
24082412
if (!LIST_ISEMPTY(&qcs_failed)) {
@@ -2722,6 +2726,8 @@ static void qcc_release(struct qcc *qcc)
27222726
qc_frm_free(qcc->conn->handle.qc, &frm);
27232727
}
27242728

2729+
qcc_tx_frms_free(qcc);
2730+
27252731
if (qcc->app_ops && qcc->app_ops->release)
27262732
qcc->app_ops->release(qcc->ctx);
27272733
TRACE_PROTO("application layer released", QMUX_EV_QCC_END, conn);
@@ -2835,6 +2841,7 @@ static void _qcc_init(struct qcc *qcc)
28352841
qcc->app_ops = NULL;
28362842
qcc->streams_by_id = EB_ROOT_UNIQUE;
28372843
LIST_INIT(&qcc->lfctl.frms);
2844+
LIST_INIT(&qcc->tx.frms);
28382845
}
28392846

28402847
static int qmux_init(struct connection *conn, struct proxy *prx,

0 commit comments

Comments
 (0)