Skip to content

Commit 954bdce

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 4cb20f8 commit 954bdce

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-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: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ 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+
static void qcc_tx_frms_free(struct qcc *qcc)
40+
{
41+
while (!LIST_ISEMPTY(&qcc->tx.frms)) {
42+
struct quic_frame *frm = LIST_ELEM(qcc->tx.frms.n, struct quic_frame *, list);
43+
qc_frm_free(qcc->conn->handle.qc, &frm);
44+
}
45+
}
46+
3947
static void qcs_free_ncbuf(struct qcs *qcs, struct ncbuf *ncbuf)
4048
{
4149
struct buffer buf;
@@ -2247,7 +2255,7 @@ static int qcs_send(struct qcs *qcs, struct list *frms, uint64_t window_conn)
22472255
*/
22482256
static int qcc_io_send(struct qcc *qcc)
22492257
{
2250-
struct list frms = LIST_HEAD_INIT(frms);
2258+
struct list *frms = &qcc->tx.frms;
22512259
/* Temporary list for QCS on error. */
22522260
struct list qcs_failed = LIST_HEAD_INIT(qcs_failed);
22532261
struct qcs *qcs, *qcs_tmp, *first_qcs = NULL;
@@ -2341,7 +2349,7 @@ static int qcc_io_send(struct qcc *qcc)
23412349

23422350
if (!qfctl_rblocked(&qcc->tx.fc) &&
23432351
!qfctl_rblocked(&qcs->tx.fc) && window_conn > total) {
2344-
if ((ret = qcs_send(qcs, &frms, window_conn - total)) < 0) {
2352+
if ((ret = qcs_send(qcs, frms, window_conn - total)) < 0) {
23452353
/* Temporarily remove QCS from send-list. */
23462354
LIST_DEL_INIT(&qcs->el_send);
23472355
LIST_APPEND(&qcs_failed, &qcs->el_send);
@@ -2365,7 +2373,7 @@ static int qcc_io_send(struct qcc *qcc)
23652373
/* Retry sending until no frame to send, data rejected or connection
23662374
* flow-control limit reached.
23672375
*/
2368-
while (qcc_send_frames(qcc, &frms) == 0 && !qfctl_rblocked(&qcc->tx.fc)) {
2376+
while (qcc_send_frames(qcc, frms) == 0 && !qfctl_rblocked(&qcc->tx.fc)) {
23692377
window_conn = qfctl_rcap(&qcc->tx.fc);
23702378
resent = 0;
23712379

@@ -2383,7 +2391,7 @@ static int qcc_io_send(struct qcc *qcc)
23832391
BUG_ON(resent > window_conn);
23842392

23852393
if (!qfctl_rblocked(&qcs->tx.fc) && window_conn > resent) {
2386-
if ((ret = qcs_send(qcs, &frms, window_conn - resent)) < 0) {
2394+
if ((ret = qcs_send(qcs, frms, window_conn - resent)) < 0) {
23872395
LIST_DEL_INIT(&qcs->el_send);
23882396
LIST_APPEND(&qcs_failed, &qcs->el_send);
23892397
continue;
@@ -2397,12 +2405,7 @@ static int qcc_io_send(struct qcc *qcc)
23972405

23982406
sent_done:
23992407
/* 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-
}
2408+
qcc_tx_frms_free(qcc);
24062409

24072410
/* Re-insert on-error QCS at the end of the send-list. */
24082411
if (!LIST_ISEMPTY(&qcs_failed)) {
@@ -2722,6 +2725,8 @@ static void qcc_release(struct qcc *qcc)
27222725
qc_frm_free(qcc->conn->handle.qc, &frm);
27232726
}
27242727

2728+
qcc_tx_frms_free(qcc);
2729+
27252730
if (qcc->app_ops && qcc->app_ops->release)
27262731
qcc->app_ops->release(qcc->ctx);
27272732
TRACE_PROTO("application layer released", QMUX_EV_QCC_END, conn);
@@ -2835,6 +2840,7 @@ static void _qcc_init(struct qcc *qcc)
28352840
qcc->app_ops = NULL;
28362841
qcc->streams_by_id = EB_ROOT_UNIQUE;
28372842
LIST_INIT(&qcc->lfctl.frms);
2843+
LIST_INIT(&qcc->tx.frms);
28382844
}
28392845

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

0 commit comments

Comments
 (0)