diff --git a/src/quic_conn.c b/src/quic_conn.c index 7c2ee6492..61acd72c3 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -2536,6 +2536,11 @@ static void qc_dup_pkt_frms(struct quic_conn *qc, list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) { struct quic_frame *dup_frm, *origin; + if (frm->flags & QUIC_FL_TX_FRAME_ACKED) { + TRACE_DEVEL("already acknowledged frame", QUIC_EV_CONN_PRSAFRM, qc, frm); + continue; + } + switch (frm->type) { case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F: { @@ -2598,6 +2603,20 @@ static void qc_dup_pkt_frms(struct quic_conn *qc, TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc); } +/* Boolean function which return 1 if TX packet is only made of + * already acknowledged frame. + */ +static inline int qc_pkt_with_only_acked_frms(struct quic_tx_packet *pkt) +{ + struct quic_frame *frm; + + list_for_each_entry(frm, &pkt->frms, list) + if (!(frm->flags & QUIC_FL_TX_FRAME_ACKED)) + return 0; + + return 1; +} + /* Prepare a fast retransmission from encryption level */ static void qc_prep_fast_retrans(struct quic_conn *qc, struct quic_enc_level *qel, @@ -2622,9 +2641,10 @@ static void qc_prep_fast_retrans(struct quic_conn *qc, node = eb64_next(node); /* Skip the empty and coalesced packets */ TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0, - "--> pn=%llu (%d %d)", (ull)p->pn_node.key, - LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED)); - if (!LIST_ISEMPTY(&p->frms)) { + "--> pn=%llu (%d %d %d)", (ull)p->pn_node.key, + LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED), + qc_pkt_with_only_acked_frms(p)); + if (!LIST_ISEMPTY(&p->frms) && !qc_pkt_with_only_acked_frms(p)) { pkt = p; break; } @@ -2684,7 +2704,8 @@ static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc, TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0, "--> pn=%llu (%d %d)", (ull)p->pn_node.key, LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED)); - if (!LIST_ISEMPTY(&p->frms) && !(p->flags & QUIC_FL_TX_PACKET_COALESCED)) { + if (!LIST_ISEMPTY(&p->frms) && !(p->flags & QUIC_FL_TX_PACKET_COALESCED) && + !qc_pkt_with_only_acked_frms(p)) { pkt = p; break; }