From ef39a74f4aa557fc4dc2285d1b214f8c66c0416e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Tue, 13 Jun 2023 08:17:23 +0200 Subject: [PATCH] MINOR: quic: Move packet number space related functions Move packet number space related functions from quic_conn.h to quic_tls.h. Should be backported as far as 2.6 to ease future backports to come. --- include/haproxy/quic_conn-t.h | 46 ----------------- include/haproxy/quic_conn.h | 90 --------------------------------- include/haproxy/quic_frame.h | 1 + include/haproxy/quic_tls-t.h | 47 ++++++++++++++++++ include/haproxy/quic_tls.h | 93 ++++++++++++++++++++++++++++++++++- 5 files changed, 140 insertions(+), 137 deletions(-) diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index a2dd9b1e9..3107ed5dd 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -322,19 +322,6 @@ struct quic_arng_node { uint64_t last; }; -/* The maximum number of ack ranges to be built in ACK frames */ -#define QUIC_MAX_ACK_RANGES 32 - -/* Structure to maintain a set of ACK ranges to be used to build ACK frames. */ -struct quic_arngs { - /* ebtree of ACK ranges organized by their first value. */ - struct eb_root root; - /* The number of ACK ranges is this tree */ - size_t sz; - /* The number of bytes required to encode this ACK ranges lists. */ - size_t enc_sz; -}; - /* Flag the packet number space as having received a packet */ #define QUIC_FL_PKTNS_PKT_RECEIVED (1UL << 0) /* Flag the packet number space as requiring an ACK frame to be sent. */ @@ -349,39 +336,6 @@ struct quic_arngs { /* The maximum number of dgrams which may be sent upon PTO expirations. */ #define QUIC_MAX_NB_PTO_DGRAMS 2 -/* QUIC packet number space */ -struct quic_pktns { - struct { - /* List of frames to send. */ - struct list frms; - /* Next packet number to use for transmissions. */ - int64_t next_pn; - /* The packet which has been sent. */ - struct eb_root pkts; - /* The time the most recent ack-eliciting packer was sent. */ - unsigned int time_of_last_eliciting; - /* The time this packet number space has experienced packet loss. */ - unsigned int loss_time; - /* Boolean to denote if we must send probe packet. */ - unsigned int pto_probe; - /* In flight bytes for this packet number space. */ - size_t in_flight; - /* The acknowledgement delay of the packet with the largest packet number */ - uint64_t ack_delay; - } tx; - struct { - /* Largest packet number */ - int64_t largest_pn; - /* Largest acked sent packet. */ - int64_t largest_acked_pn; - struct quic_arngs arngs; - unsigned int nb_aepkts_since_last_ack; - /* The time the packet with the largest packet number was received */ - uint64_t largest_time_received; - } rx; - unsigned int flags; -}; - /* QUIC datagram */ struct quic_dgram { void *owner; diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 9bfdc7346..e3c60325b 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -406,42 +406,6 @@ static inline uint64_t quic_compute_ack_delay_us(unsigned int time_received, return ((now_ms - time_received) * 1000) >> conn->tx.params.ack_delay_exponent; } -/* Initialize a QUIC packet number space. - * Never fails. - */ -static inline void quic_pktns_init(struct quic_pktns *pktns) -{ - LIST_INIT(&pktns->tx.frms); - pktns->tx.next_pn = -1; - pktns->tx.pkts = EB_ROOT_UNIQUE; - pktns->tx.time_of_last_eliciting = 0; - pktns->tx.loss_time = TICK_ETERNITY; - pktns->tx.pto_probe = 0; - pktns->tx.in_flight = 0; - pktns->tx.ack_delay = 0; - - pktns->rx.largest_pn = -1; - pktns->rx.largest_acked_pn = -1; - pktns->rx.arngs.root = EB_ROOT_UNIQUE; - pktns->rx.arngs.sz = 0; - pktns->rx.arngs.enc_sz = 0; - pktns->rx.nb_aepkts_since_last_ack = 0; - pktns->rx.largest_time_received = 0; - - pktns->flags = 0; -} - -/* Returns the current largest acknowledged packet number if exists, -1 if not */ -static inline int64_t quic_pktns_get_largest_acked_pn(struct quic_pktns *pktns) -{ - struct eb64_node *ar = eb64_last(&pktns->rx.arngs.root); - - if (!ar) - return -1; - - return eb64_entry(ar, struct quic_arng_node, first)->last; -} - /* The TX packets sent in the same datagram are linked to each others in * the order they are built. This function detach a packet from its successor * and predecessor in the same datagram. @@ -474,51 +438,6 @@ static inline void quic_tx_packet_refdec(struct quic_tx_packet *pkt) } } -static inline void quic_pktns_tx_pkts_release(struct quic_pktns *pktns, struct quic_conn *qc) -{ - struct eb64_node *node; - - node = eb64_first(&pktns->tx.pkts); - while (node) { - struct quic_tx_packet *pkt; - struct quic_frame *frm, *frmbak; - - pkt = eb64_entry(node, struct quic_tx_packet, pn_node); - node = eb64_next(node); - if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) - qc->path->ifae_pkts--; - list_for_each_entry_safe(frm, frmbak, &pkt->frms, list) { - qc_frm_unref(frm, qc); - LIST_DEL_INIT(&frm->list); - quic_tx_packet_refdec(frm->pkt); - qc_frm_free(&frm); - } - eb64_delete(&pkt->pn_node); - quic_tx_packet_refdec(pkt); - } -} - -/* Discard packet number space attached to QUIC connection. - * Its loss information are reset. Deduce the outstanding bytes for this - * packet number space from the outstanding bytes for the path of this - * connection. - * Note that all the non acknowledged TX packets and their frames are freed. - * Always succeeds. - */ -static inline void quic_pktns_discard(struct quic_pktns *pktns, - struct quic_conn *qc) -{ - qc->path->in_flight -= pktns->tx.in_flight; - qc->path->prep_in_flight -= pktns->tx.in_flight; - qc->path->loss.pto_count = 0; - - pktns->tx.time_of_last_eliciting = 0; - pktns->tx.loss_time = TICK_ETERNITY; - pktns->tx.pto_probe = 0; - pktns->tx.in_flight = 0; - quic_pktns_tx_pkts_release(pktns, qc); -} - /* Initialize

QUIC network path depending on boolean * which is true for an IPv4 path, if not false for an IPv6 path. */ @@ -562,15 +481,6 @@ static inline size_t quic_path_prep_data(struct quic_path *path) return path->cwnd - path->prep_in_flight; } -/* Return 1 if matches with the Application packet number space of - * connection which is common to the 0-RTT and 1-RTT encryption levels, 0 - * if not (handshake packets). - */ -static inline int quic_application_pktns(struct quic_pktns *pktns, struct quic_conn *conn) -{ - return pktns == &conn->pktns[QUIC_TLS_PKTNS_01RTT]; -} - /* CRYPTO data buffer handling functions. */ static inline unsigned char *c_buf_getpos(struct quic_enc_level *qel, uint64_t offset) { diff --git a/include/haproxy/quic_frame.h b/include/haproxy/quic_frame.h index 48befbb3d..95df7db17 100644 --- a/include/haproxy/quic_frame.h +++ b/include/haproxy/quic_frame.h @@ -26,6 +26,7 @@ #error "Must define USE_OPENSSL" #endif +#include #include #include #include diff --git a/include/haproxy/quic_tls-t.h b/include/haproxy/quic_tls-t.h index 55e990184..dddb0d4e9 100644 --- a/include/haproxy/quic_tls-t.h +++ b/include/haproxy/quic_tls-t.h @@ -120,6 +120,53 @@ extern const unsigned char initial_salt_draft_29[20]; extern const unsigned char initial_salt_v1[20]; extern const unsigned char initial_salt_v2[20]; +/* The maximum number of ack ranges to be built in ACK frames */ +#define QUIC_MAX_ACK_RANGES 32 + +/* Structure to maintain a set of ACK ranges to be used to build ACK frames. */ +struct quic_arngs { + /* ebtree of ACK ranges organized by their first value. */ + struct eb_root root; + /* The number of ACK ranges is this tree */ + size_t sz; + /* The number of bytes required to encode this ACK ranges lists. */ + size_t enc_sz; +}; + +/* QUIC packet number space */ +struct quic_pktns { + struct list list; + struct { + /* List of frames to send. */ + struct list frms; + /* Next packet number to use for transmissions. */ + int64_t next_pn; + /* The packet which has been sent. */ + struct eb_root pkts; + /* The time the most recent ack-eliciting packer was sent. */ + unsigned int time_of_last_eliciting; + /* The time this packet number space has experienced packet loss. */ + unsigned int loss_time; + /* Boolean to denote if we must send probe packet. */ + unsigned int pto_probe; + /* In flight bytes for this packet number space. */ + size_t in_flight; + /* The acknowledgement delay of the packet with the largest packet number */ + uint64_t ack_delay; + } tx; + struct { + /* Largest packet number */ + int64_t largest_pn; + /* Largest acked sent packet. */ + int64_t largest_acked_pn; + struct quic_arngs arngs; + unsigned int nb_aepkts_since_last_ack; + /* The time the packet with the largest packet number was received */ + uint64_t largest_time_received; + } rx; + unsigned int flags; +}; + /* Key phase used for Key Update */ struct quic_tls_kp { EVP_CIPHER_CTX *ctx; diff --git a/include/haproxy/quic_tls.h b/include/haproxy/quic_tls.h index 74a436a0f..77f54deee 100644 --- a/include/haproxy/quic_tls.h +++ b/include/haproxy/quic_tls.h @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include #include #include @@ -322,6 +323,96 @@ static inline char quic_packet_type_enc_level_char(int packet_type) } } +/* Initialize a QUIC packet number space. + * Never fails. + */ +static inline void quic_pktns_init(struct quic_pktns *pktns) +{ + LIST_INIT(&pktns->tx.frms); + pktns->tx.next_pn = -1; + pktns->tx.pkts = EB_ROOT_UNIQUE; + pktns->tx.time_of_last_eliciting = 0; + pktns->tx.loss_time = TICK_ETERNITY; + pktns->tx.pto_probe = 0; + pktns->tx.in_flight = 0; + pktns->tx.ack_delay = 0; + + pktns->rx.largest_pn = -1; + pktns->rx.largest_acked_pn = -1; + pktns->rx.arngs.root = EB_ROOT_UNIQUE; + pktns->rx.arngs.sz = 0; + pktns->rx.arngs.enc_sz = 0; + pktns->rx.nb_aepkts_since_last_ack = 0; + pktns->rx.largest_time_received = 0; + + pktns->flags = 0; +} + +static inline void quic_pktns_tx_pkts_release(struct quic_pktns *pktns, struct quic_conn *qc) +{ + struct eb64_node *node; + + node = eb64_first(&pktns->tx.pkts); + while (node) { + struct quic_tx_packet *pkt; + struct quic_frame *frm, *frmbak; + + pkt = eb64_entry(node, struct quic_tx_packet, pn_node); + node = eb64_next(node); + if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) + qc->path->ifae_pkts--; + list_for_each_entry_safe(frm, frmbak, &pkt->frms, list) { + qc_frm_unref(frm, qc); + LIST_DEL_INIT(&frm->list); + quic_tx_packet_refdec(frm->pkt); + qc_frm_free(&frm); + } + eb64_delete(&pkt->pn_node); + quic_tx_packet_refdec(pkt); + } +} + +/* Discard packet number space attached to QUIC connection. + * Its loss information are reset. Deduce the outstanding bytes for this + * packet number space from the outstanding bytes for the path of this + * connection. + * Note that all the non acknowledged TX packets and their frames are freed. + * Always succeeds. + */ +static inline void quic_pktns_discard(struct quic_pktns *pktns, + struct quic_conn *qc) +{ + qc->path->in_flight -= pktns->tx.in_flight; + qc->path->prep_in_flight -= pktns->tx.in_flight; + qc->path->loss.pto_count = 0; + + pktns->tx.time_of_last_eliciting = 0; + pktns->tx.loss_time = TICK_ETERNITY; + pktns->tx.pto_probe = 0; + pktns->tx.in_flight = 0; + quic_pktns_tx_pkts_release(pktns, qc); +} + +/* Return 1 if matches with the Application packet number space of + * connection which is common to the 0-RTT and 1-RTT encryption levels, 0 + * if not (handshake packets). + */ +static inline int quic_application_pktns(struct quic_pktns *pktns, struct quic_conn *qc) +{ + return pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT]; +} + +/* Returns the current largest acknowledged packet number if exists, -1 if not */ +static inline int64_t quic_pktns_get_largest_acked_pn(struct quic_pktns *pktns) +{ + struct eb64_node *ar = eb64_last(&pktns->rx.arngs.root); + + if (!ar) + return -1; + + return eb64_entry(ar, struct quic_arng_node, first)->last; +} + /* Return a character to identify the packet number space of QUIC * connection. 'I' for Initial packet number space, 'H' for Handshake packet * space, and 'A' for Application data number space, or '-' if not found.