diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index f6fcf95e5..cf6a4e509 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -592,10 +592,10 @@ enum qc_mux_state { #define QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT (1U << 2) #define QUIC_FL_CONN_LISTENER (1U << 3) #define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4) -/* gap here */ +#define QUIC_FL_CONN_RETRANS_LOST_DATA (1U << 5) /* retransmission in progress for lost data */ #define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6) #define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7) -#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) +#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */ #define QUIC_FL_CONN_TLS_ALERT (1U << 9) /* gap here */ #define QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED (1U << 11) /* The half-open connection counter was decremented */ diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 55001e8f4..b9f274256 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -3884,7 +3884,9 @@ static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel) /* Try to send application frames from list on connection . * - * Use qc_send_app_probing wrapper when probing with old data. + * For retransmission you must use wrapper depending on the sending condition : + * - use qc_send_app_retransmit to send data detected as lost + * - use qc_send_app_probing when probing with already sent data * * Returns 1 on success. Some data might not have been sent due to congestion, * in this case they are left in input list. The caller may subscribe on @@ -3940,6 +3942,27 @@ int qc_send_app_pkts(struct quic_conn *qc, struct list *frms) goto leave; } +/* Try to send application frames from list on connection . Use this + * function when retransmitting lost frames. + * + * Returns the result from qc_send_app_pkts function. + */ +static forceinline int qc_send_app_retransmit(struct quic_conn *qc, + struct list *frms) +{ + int ret; + + TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc); + + TRACE_STATE("preparing lost data (retransmission)", QUIC_EV_CONN_TXPKT, qc); + qc->flags |= QUIC_FL_CONN_RETRANS_LOST_DATA; + ret = qc_send_app_pkts(qc, frms); + qc->flags &= ~QUIC_FL_CONN_RETRANS_LOST_DATA; + + TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc); + return ret; +} + /* Try to send application frames from list on connection . Use this * function when probing is required. * @@ -4131,8 +4154,8 @@ static struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned } /* XXX TODO: how to limit the list frames to send */ - if (!qc_send_app_pkts(qc, &qel->pktns->tx.frms)) { - TRACE_DEVEL("qc_send_app_pkts() failed", QUIC_EV_CONN_IO_CB, qc); + if (!qc_send_app_retransmit(qc, &qel->pktns->tx.frms)) { + TRACE_DEVEL("qc_send_app_retransmit() failed", QUIC_EV_CONN_IO_CB, qc); goto out; } @@ -6462,12 +6485,9 @@ static inline int qc_build_frms(struct list *outlist, struct list *inlist, LIST_DELETE(&cf->list); LIST_APPEND(outlist, &cf->list); - /* The MUX stream might be released at this - * stage. This can most notably happen on - * retransmission. - */ - if (qc->mux_state == QC_MUX_READY && - !cf->stream.stream->release) { + /* Do not notify MUX on retransmission. */ + if (!(qc->flags & (QUIC_FL_CONN_RETRANS_LOST_DATA|QUIC_FL_CONN_RETRANS_OLD_DATA))) { + BUG_ON(qc->mux_state != QC_MUX_READY); /* MUX must be the caller if not on retransmission. */ qcc_streams_sent_done(cf->stream.stream->ctx, cf->stream.len, cf->stream.offset.key); @@ -6505,12 +6525,9 @@ static inline int qc_build_frms(struct list *outlist, struct list *inlist, cf->stream.offset.key += dlen; cf->stream.data = (unsigned char *)b_peek(&cf_buf, dlen); - /* The MUX stream might be released at this - * stage. This can most notably happen on - * retransmission. - */ - if (qc->mux_state == QC_MUX_READY && - !cf->stream.stream->release) { + /* Do not notify MUX on retransmission. */ + if (!(qc->flags & (QUIC_FL_CONN_RETRANS_LOST_DATA|QUIC_FL_CONN_RETRANS_OLD_DATA))) { + BUG_ON(qc->mux_state != QC_MUX_READY); /* MUX must be the caller if not on retransmission. */ qcc_streams_sent_done(new_cf->stream.stream->ctx, new_cf->stream.len, new_cf->stream.offset.key);