BUG/MINOR: quic: Stop removing ACK ranges when building packets
Since this commit:
BUG/MINOR: quic: Possible wrapped values used as ACK tree purging limit.
There are more chances that ack ranges may be removed from their trees when
building a packet. It is preferable to impose a limit to these trees. This
will be the subject of the a next commit to come.
For now on, it is sufficient to stop deleting ack range from their trees.
Remove quic_ack_frm_reduce_sz() and quic_rm_last_ack_ranges() which were
there to do that.
Make qc_frm_len() support ACK frames and calls it to ensure an ACK frame
may be added to a packet before building it.
Must be backported to 2.6 and 2.7.
diff --git a/include/haproxy/quic_frame.h b/include/haproxy/quic_frame.h
index aae45c9..fd6bad7 100644
--- a/include/haproxy/quic_frame.h
+++ b/include/haproxy/quic_frame.h
@@ -48,6 +48,27 @@
size_t len = 0;
switch (frm->type) {
+ case QUIC_FT_ACK: {
+ struct quic_tx_ack *tx_ack = &frm->tx_ack;
+ struct eb64_node *ar, *prev_ar;
+ struct quic_arng_node *ar_node, *prev_ar_node;
+
+ ar = eb64_last(&tx_ack->arngs->root);
+ ar_node = eb64_entry(ar, struct quic_arng_node, first);
+ len += 1 + quic_int_getsize(ar_node->last);
+ len += quic_int_getsize(tx_ack->ack_delay);
+ len += quic_int_getsize(tx_ack->arngs->sz - 1);
+ len += quic_int_getsize(ar_node->last - ar_node->first.key);
+
+ while ((prev_ar = eb64_prev(ar))) {
+ prev_ar_node = eb64_entry(prev_ar, struct quic_arng_node, first);
+ len += quic_int_getsize(ar_node->first.key - prev_ar_node->last - 2);
+ len += quic_int_getsize(prev_ar_node->last - prev_ar_node->first.key);
+ ar = prev_ar;
+ ar_node = eb64_entry(ar, struct quic_arng_node, first);
+ }
+ break;
+ }
case QUIC_FT_RESET_STREAM: {
struct quic_reset_stream *f = &frm->reset_stream;
len += 1 + quic_int_getsize(f->id) +
diff --git a/src/quic_conn.c b/src/quic_conn.c
index 02e4044..2992ba0 100644
--- a/src/quic_conn.c
+++ b/src/quic_conn.c
@@ -4206,46 +4206,6 @@
return p->first.key - q->last - 2;
}
-
-/* Remove the last elements of <ack_ranges> list of ack range updating its
- * encoded size until it goes below <limit>.
- * Returns 1 if succeeded, 0 if not (no more element to remove).
- */
-static int quic_rm_last_ack_ranges(struct quic_conn *qc,
- struct quic_arngs *arngs, size_t limit)
-{
- int ret = 0;
- struct eb64_node *last, *prev;
-
- TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
-
- last = eb64_last(&arngs->root);
- while (last && arngs->enc_sz > limit) {
- struct quic_arng_node *last_node, *prev_node;
-
- prev = eb64_prev(last);
- if (!prev) {
- TRACE_DEVEL("<last> not found", QUIC_EV_CONN_TXPKT, qc);
- goto out;
- }
-
- last_node = eb64_entry(last, struct quic_arng_node, first);
- prev_node = eb64_entry(prev, struct quic_arng_node, first);
- arngs->enc_sz -= quic_int_getsize(last_node->last - last_node->first.key);
- arngs->enc_sz -= quic_int_getsize(sack_gap(prev_node, last_node));
- arngs->enc_sz -= quic_decint_size_diff(arngs->sz);
- --arngs->sz;
- eb64_delete(last);
- pool_free(pool_head_quic_arng, last);
- last = prev;
- }
-
- ret = 1;
- out:
- TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
- return ret;
-}
-
/* Set the encoded size of <arngs> QUIC ack ranges. */
static void quic_arngs_set_enc_sz(struct quic_conn *qc, struct quic_arngs *arngs)
{
@@ -7407,33 +7367,6 @@
return ret;
}
-/* Reduce the encoded size of <ack_frm> ACK frame removing the last
- * ACK ranges if needed to a value below <limit> in bytes.
- * Return 1 if succeeded, 0 if not.
- */
-static int quic_ack_frm_reduce_sz(struct quic_conn *qc,
- struct quic_frame *ack_frm, size_t limit)
-{
- size_t room, ack_delay_sz;
- int ret = 0;
-
- TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
-
- ack_delay_sz = quic_int_getsize(ack_frm->tx_ack.ack_delay);
- if (limit <= ack_delay_sz - 1)
- goto leave;
-
- /* A frame is made of 1 byte for the frame type. */
- room = limit - ack_delay_sz - 1;
- if (!quic_rm_last_ack_ranges(qc, ack_frm->tx_ack.arngs, room))
- goto leave;
-
- ret = 1 + ack_delay_sz + ack_frm->tx_ack.arngs->enc_sz;
- leave:
- TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
- return ret;
-}
-
/* Prepare into <outlist> as most as possible ack-eliciting frame from their
* <inlist> prebuilt frames for <qel> encryption level to be encoded in a buffer
* with <room> as available room, and <*len> the packet Length field initialized
@@ -7853,8 +7786,8 @@
if (end - pos <= 1 + *pn_len)
goto no_room;
- ack_frm_len = quic_ack_frm_reduce_sz(qc, &ack_frm, end - 1 - *pn_len - pos);
- if (!ack_frm_len)
+ ack_frm_len = qc_frm_len(&ack_frm);
+ if (ack_frm_len > end - 1 - *pn_len - pos)
goto no_room;
}