]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG: quic: Rename some functions used upon ACK receipt
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 27 Nov 2023 15:25:53 +0000 (16:25 +0100)
committerFrédéric Lécaille <flecaille@haproxy.com>
Tue, 28 Nov 2023 14:37:50 +0000 (15:37 +0100)
Rename some functions to reflect more their jobs.
Move qc_release_lost_pkts() to quic_loss.c

include/haproxy/quic_loss.h
include/haproxy/quic_rx.h
src/quic_loss.c
src/quic_rx.c

index 9f0b085474b9768c4879b486f9d0b15d91cef409..d2a0e776ba3016869d57aaebd19659d0cddbe663 100644 (file)
@@ -85,5 +85,7 @@ struct quic_pktns *quic_pto_pktns(struct quic_conn *qc,
 
 void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
                            struct list *lost_pkts);
+int qc_release_lost_pkts(struct quic_conn *qc, struct quic_pktns *pktns,
+                         struct list *pkts, uint64_t now_us);
 #endif /* USE_QUIC */
 #endif /* _PROTO_QUIC_LOSS_H */
index 8c017724e3bdce8c0659ef469993eab56c0772dc..4cde1ad9d2d610495e4361b9f375093a5f57e236 100644 (file)
@@ -31,10 +31,11 @@ int qc_treat_rx_pkts(struct quic_conn *qc);
 int qc_parse_hd_form(struct quic_rx_packet *pkt,
                      unsigned char **pos, const unsigned char *end);
 void quic_free_ncbuf(struct ncbuf *ncbuf);
-int qc_release_lost_pkts(struct quic_conn *qc, struct quic_pktns *pktns,
-                         struct list *pkts, uint64_t now_us);
 int qc_treat_rx_crypto_frms(struct quic_conn *qc, struct quic_enc_level *el,
                             struct ssl_sock_ctx *ctx);
+int qc_handle_frms_of_lost_pkt(struct quic_conn *qc,
+                               struct quic_tx_packet *pkt,
+                               struct list *pktns_frm_list);
 
 /* Increment the reference counter of <pkt> */
 static inline void quic_rx_packet_refinc(struct quic_rx_packet *pkt)
index 0eab03d4292037abbb450ec53bfd0266bfaad98d..7d47b6af0411ab4673eb452989ed9703d93fe1f9 100644 (file)
@@ -204,3 +204,82 @@ void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
        TRACE_LEAVE(QUIC_EV_CONN_PKTLOSS, qc);
 }
 
+/* Handle <pkts> list of lost packets detected at <now_us> handling their TX
+ * frames. Send a packet loss event to the congestion controller if in flight
+ * packet have been lost. Also frees the packet in <pkts> list.
+ *
+ * Returns 1 on success else 0 if loss limit has been exceeded. A
+ * CONNECTION_CLOSE was prepared to close the connection ASAP.
+ */
+int qc_release_lost_pkts(struct quic_conn *qc, struct quic_pktns *pktns,
+                         struct list *pkts, uint64_t now_us)
+{
+       struct quic_tx_packet *pkt, *tmp, *oldest_lost, *newest_lost;
+       int close = 0;
+
+       TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
+
+       if (LIST_ISEMPTY(pkts))
+               goto leave;
+
+       oldest_lost = newest_lost = NULL;
+       list_for_each_entry_safe(pkt, tmp, pkts, list) {
+               struct list tmp = LIST_HEAD_INIT(tmp);
+
+               pkt->pktns->tx.in_flight -= pkt->in_flight_len;
+               qc->path->prep_in_flight -= pkt->in_flight_len;
+               qc->path->in_flight -= pkt->in_flight_len;
+               if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
+                       qc->path->ifae_pkts--;
+               /* Treat the frames of this lost packet. */
+               if (!qc_handle_frms_of_lost_pkt(qc, pkt, &pktns->tx.frms))
+                       close = 1;
+               LIST_DELETE(&pkt->list);
+               if (!oldest_lost) {
+                       oldest_lost = newest_lost = pkt;
+               }
+               else {
+                       if (newest_lost != oldest_lost)
+                               quic_tx_packet_refdec(newest_lost);
+                       newest_lost = pkt;
+               }
+       }
+
+       if (!close) {
+               if (newest_lost) {
+                       /* Sent a congestion event to the controller */
+                       struct quic_cc_event ev = { };
+
+                       ev.type = QUIC_CC_EVT_LOSS;
+                       ev.loss.time_sent = newest_lost->time_sent;
+
+                       quic_cc_event(&qc->path->cc, &ev);
+               }
+
+               /* If an RTT have been already sampled, <rtt_min> has been set.
+                * We must check if we are experiencing a persistent congestion.
+                * If this is the case, the congestion controller must re-enter
+                * slow start state.
+                */
+               if (qc->path->loss.rtt_min && newest_lost != oldest_lost) {
+                       unsigned int period = newest_lost->time_sent - oldest_lost->time_sent;
+
+                       if (quic_loss_persistent_congestion(&qc->path->loss, period,
+                                                           now_ms, qc->max_ack_delay))
+                               qc->path->cc.algo->slow_start(&qc->path->cc);
+               }
+       }
+
+       /* <oldest_lost> cannot be NULL at this stage because we have ensured
+        * that <pkts> list is not empty. Without this, GCC 12.2.0 reports a
+        * possible overflow on a 0 byte region with O2 optimization.
+        */
+       ALREADY_CHECKED(oldest_lost);
+       quic_tx_packet_refdec(oldest_lost);
+       if (newest_lost != oldest_lost)
+               quic_tx_packet_refdec(newest_lost);
+
+ leave:
+       TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
+       return !close;
+}
index 5bb130160f6e6ec9aea80a49e767c993fc3c1675..995755012036d931e98d6b79e754a0d08bd1cd96 100644 (file)
@@ -252,8 +252,11 @@ static int quic_stream_try_to_consume(struct quic_conn *qc,
        return ret;
 }
 
-/* Treat <frm> frame whose packet it is attached to has just been acknowledged. */
-static void qc_treat_acked_tx_frm(struct quic_conn *qc, struct quic_frame *frm)
+/* Handle <frm> frame whose packet it is attached to has just been acknowledged. The memory allocated
+ * for this frame will be at least released in every cases.
+ * Never fail.
+ */
+static void qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *frm)
 {
        TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
        TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
@@ -351,12 +354,9 @@ static void qc_newly_acked_pkts(struct quic_conn *qc, struct eb_root *pkts,
        TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
 }
 
-/* Remove <largest> down to <smallest> node entries from <pkts> tree of TX packet,
- * deallocating them, and their TX frames.
- * May be NULL if <largest> node could not be found.
- */
-static void qc_ackrng_pkts(struct quic_conn *qc,
-                           unsigned int *pkt_flags, struct list *newly_acked_pkts)
+/* Handle <newly_acked_pkts> list of newly acknowledged TX packets */
+static void qc_handle_newly_acked_pkts(struct quic_conn *qc,
+                                       unsigned int *pkt_flags, struct list *newly_acked_pkts)
 {
        struct quic_tx_packet *pkt, *tmp;
 
@@ -368,7 +368,7 @@ static void qc_ackrng_pkts(struct quic_conn *qc,
                *pkt_flags |= pkt->flags;
                TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
                list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
-                       qc_treat_acked_tx_frm(qc, frm);
+                       qc_handle_newly_acked_frm(qc, frm);
                /* If there are others packet in the same datagram <pkt> is attached to,
                 * detach the previous one and the next one from <pkt>.
                 */
@@ -380,16 +380,16 @@ static void qc_ackrng_pkts(struct quic_conn *qc,
        TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
 }
 
-/* Remove all frames from <pkt_frm_list> and reinsert them in the same order
+/* Handle all frames sent from <pkt> packet and reinsert them in the same order
  * they have been sent into <pktns_frm_list>. The loss counter of each frame is
  * incremented and checked if it does not exceed retransmission limit.
  *
  * Returns 1 on success, 0 if a frame loss limit is exceeded. A
  * CONNECTION_CLOSE is scheduled in this case.
  */
-static int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
-                                         struct quic_tx_packet *pkt,
-                                         struct list *pktns_frm_list)
+int qc_handle_frms_of_lost_pkt(struct quic_conn *qc,
+                               struct quic_tx_packet *pkt,
+                               struct list *pktns_frm_list)
 {
        struct quic_frame *frm, *frmbak;
        struct list *pkt_frm_list = &pkt->frms;
@@ -482,8 +482,8 @@ static int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
  * <newly_acked_pkts> list and free them.
  * Always succeeds.
  */
-static void qc_treat_newly_acked_pkts(struct quic_conn *qc,
-                                      struct list *newly_acked_pkts)
+static void qc_notify_cc_of_newly_acked_pkts(struct quic_conn *qc,
+                                             struct list *newly_acked_pkts)
 {
        struct quic_tx_packet *pkt, *tmp;
        struct quic_cc_event ev = { .type = QUIC_CC_EVT_ACK, };
@@ -513,86 +513,6 @@ static void qc_treat_newly_acked_pkts(struct quic_conn *qc,
 
 }
 
-/* Handle <pkts> list of lost packets detected at <now_us> handling their TX
- * frames. Send a packet loss event to the congestion controller if in flight
- * packet have been lost. Also frees the packet in <pkts> list.
- *
- * Returns 1 on success else 0 if loss limit has been exceeded. A
- * CONNECTION_CLOSE was prepared to close the connection ASAP.
- */
-int qc_release_lost_pkts(struct quic_conn *qc, struct quic_pktns *pktns,
-                         struct list *pkts, uint64_t now_us)
-{
-       struct quic_tx_packet *pkt, *tmp, *oldest_lost, *newest_lost;
-       int close = 0;
-
-       TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
-
-       if (LIST_ISEMPTY(pkts))
-               goto leave;
-
-       oldest_lost = newest_lost = NULL;
-       list_for_each_entry_safe(pkt, tmp, pkts, list) {
-               struct list tmp = LIST_HEAD_INIT(tmp);
-
-               pkt->pktns->tx.in_flight -= pkt->in_flight_len;
-               qc->path->prep_in_flight -= pkt->in_flight_len;
-               qc->path->in_flight -= pkt->in_flight_len;
-               if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
-                       qc->path->ifae_pkts--;
-               /* Treat the frames of this lost packet. */
-               if (!qc_requeue_nacked_pkt_tx_frms(qc, pkt, &pktns->tx.frms))
-                       close = 1;
-               LIST_DELETE(&pkt->list);
-               if (!oldest_lost) {
-                       oldest_lost = newest_lost = pkt;
-               }
-               else {
-                       if (newest_lost != oldest_lost)
-                               quic_tx_packet_refdec(newest_lost);
-                       newest_lost = pkt;
-               }
-       }
-
-       if (!close) {
-               if (newest_lost) {
-                       /* Sent a congestion event to the controller */
-                       struct quic_cc_event ev = { };
-
-                       ev.type = QUIC_CC_EVT_LOSS;
-                       ev.loss.time_sent = newest_lost->time_sent;
-
-                       quic_cc_event(&qc->path->cc, &ev);
-               }
-
-               /* If an RTT have been already sampled, <rtt_min> has been set.
-                * We must check if we are experiencing a persistent congestion.
-                * If this is the case, the congestion controller must re-enter
-                * slow start state.
-                */
-               if (qc->path->loss.rtt_min && newest_lost != oldest_lost) {
-                       unsigned int period = newest_lost->time_sent - oldest_lost->time_sent;
-
-                       if (quic_loss_persistent_congestion(&qc->path->loss, period,
-                                                           now_ms, qc->max_ack_delay))
-                               qc->path->cc.algo->slow_start(&qc->path->cc);
-               }
-       }
-
-       /* <oldest_lost> cannot be NULL at this stage because we have ensured
-        * that <pkts> list is not empty. Without this, GCC 12.2.0 reports a
-        * possible overflow on a 0 byte region with O2 optimization.
-        */
-       ALREADY_CHECKED(oldest_lost);
-       quic_tx_packet_refdec(oldest_lost);
-       if (newest_lost != oldest_lost)
-               quic_tx_packet_refdec(newest_lost);
-
- leave:
-       TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
-       return !close;
-}
-
 /* Parse ACK frame into <frm> from a buffer at <buf> address with <end> being at
  * one byte past the end of this buffer. Also update <rtt_sample> if needed, i.e.
  * if the largest acked packet was newly acked and if there was at least one newly
@@ -692,7 +612,7 @@ static int qc_parse_ack_frm(struct quic_conn *qc,
        } while (1);
 
        if (!LIST_ISEMPTY(&newly_acked_pkts)) {
-               qc_ackrng_pkts(qc, &pkt_flags, &newly_acked_pkts);
+               qc_handle_newly_acked_pkts(qc, &pkt_flags, &newly_acked_pkts);
                if (new_largest_acked_pn && (pkt_flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
                        *rtt_sample = tick_remain(time_sent, now_ms);
                        qel->pktns->rx.largest_acked_pn = ack_frm->largest_ack;
@@ -703,7 +623,7 @@ static int qc_parse_ack_frm(struct quic_conn *qc,
                        if (!qc_release_lost_pkts(qc, qel->pktns, &lost_pkts, now_ms))
                                goto leave;
                }
-               qc_treat_newly_acked_pkts(qc, &newly_acked_pkts);
+               qc_notify_cc_of_newly_acked_pkts(qc, &newly_acked_pkts);
                if (quic_peer_validated_addr(qc))
                        qc->path->loss.pto_count = 0;
                qc_set_timer(qc);