mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-28 15:42:30 +00:00
REORG: quic: Rename some functions used upon ACK receipt
Rename some functions to reflect more their jobs. Move qc_release_lost_pkts() to quic_loss.c
This commit is contained in:
parent
f74d882ef0
commit
f32fc26b62
@ -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,
|
void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
|
||||||
struct list *lost_pkts);
|
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 /* USE_QUIC */
|
||||||
#endif /* _PROTO_QUIC_LOSS_H */
|
#endif /* _PROTO_QUIC_LOSS_H */
|
||||||
|
@ -31,10 +31,11 @@ int qc_treat_rx_pkts(struct quic_conn *qc);
|
|||||||
int qc_parse_hd_form(struct quic_rx_packet *pkt,
|
int qc_parse_hd_form(struct quic_rx_packet *pkt,
|
||||||
unsigned char **pos, const unsigned char *end);
|
unsigned char **pos, const unsigned char *end);
|
||||||
void quic_free_ncbuf(struct ncbuf *ncbuf);
|
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,
|
int qc_treat_rx_crypto_frms(struct quic_conn *qc, struct quic_enc_level *el,
|
||||||
struct ssl_sock_ctx *ctx);
|
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> */
|
/* Increment the reference counter of <pkt> */
|
||||||
static inline void quic_rx_packet_refinc(struct quic_rx_packet *pkt)
|
static inline void quic_rx_packet_refinc(struct quic_rx_packet *pkt)
|
||||||
|
@ -204,3 +204,82 @@ void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
|
|||||||
TRACE_LEAVE(QUIC_EV_CONN_PKTLOSS, 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;
|
||||||
|
}
|
||||||
|
106
src/quic_rx.c
106
src/quic_rx.c
@ -252,8 +252,11 @@ static int quic_stream_try_to_consume(struct quic_conn *qc,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Treat <frm> frame whose packet it is attached to has just been acknowledged. */
|
/* Handle <frm> frame whose packet it is attached to has just been acknowledged. The memory allocated
|
||||||
static void qc_treat_acked_tx_frm(struct quic_conn *qc, struct quic_frame *frm)
|
* 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_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
|
||||||
TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
|
TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
|
||||||
@ -351,11 +354,8 @@ static void qc_newly_acked_pkts(struct quic_conn *qc, struct eb_root *pkts,
|
|||||||
TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
|
TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove <largest> down to <smallest> node entries from <pkts> tree of TX packet,
|
/* Handle <newly_acked_pkts> list of newly acknowledged TX packets */
|
||||||
* deallocating them, and their TX frames.
|
static void qc_handle_newly_acked_pkts(struct quic_conn *qc,
|
||||||
* 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)
|
unsigned int *pkt_flags, struct list *newly_acked_pkts)
|
||||||
{
|
{
|
||||||
struct quic_tx_packet *pkt, *tmp;
|
struct quic_tx_packet *pkt, *tmp;
|
||||||
@ -368,7 +368,7 @@ static void qc_ackrng_pkts(struct quic_conn *qc,
|
|||||||
*pkt_flags |= pkt->flags;
|
*pkt_flags |= pkt->flags;
|
||||||
TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
|
TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
|
||||||
list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
|
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,
|
/* If there are others packet in the same datagram <pkt> is attached to,
|
||||||
* detach the previous one and the next one from <pkt>.
|
* detach the previous one and the next one from <pkt>.
|
||||||
*/
|
*/
|
||||||
@ -380,14 +380,14 @@ static void qc_ackrng_pkts(struct quic_conn *qc,
|
|||||||
TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, 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
|
* 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.
|
* incremented and checked if it does not exceed retransmission limit.
|
||||||
*
|
*
|
||||||
* Returns 1 on success, 0 if a frame loss limit is exceeded. A
|
* Returns 1 on success, 0 if a frame loss limit is exceeded. A
|
||||||
* CONNECTION_CLOSE is scheduled in this case.
|
* CONNECTION_CLOSE is scheduled in this case.
|
||||||
*/
|
*/
|
||||||
static int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
|
int qc_handle_frms_of_lost_pkt(struct quic_conn *qc,
|
||||||
struct quic_tx_packet *pkt,
|
struct quic_tx_packet *pkt,
|
||||||
struct list *pktns_frm_list)
|
struct list *pktns_frm_list)
|
||||||
{
|
{
|
||||||
@ -482,7 +482,7 @@ static int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
|
|||||||
* <newly_acked_pkts> list and free them.
|
* <newly_acked_pkts> list and free them.
|
||||||
* Always succeeds.
|
* Always succeeds.
|
||||||
*/
|
*/
|
||||||
static void qc_treat_newly_acked_pkts(struct quic_conn *qc,
|
static void qc_notify_cc_of_newly_acked_pkts(struct quic_conn *qc,
|
||||||
struct list *newly_acked_pkts)
|
struct list *newly_acked_pkts)
|
||||||
{
|
{
|
||||||
struct quic_tx_packet *pkt, *tmp;
|
struct quic_tx_packet *pkt, *tmp;
|
||||||
@ -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
|
/* 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.
|
* 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
|
* 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);
|
} while (1);
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&newly_acked_pkts)) {
|
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)) {
|
if (new_largest_acked_pn && (pkt_flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
|
||||||
*rtt_sample = tick_remain(time_sent, now_ms);
|
*rtt_sample = tick_remain(time_sent, now_ms);
|
||||||
qel->pktns->rx.largest_acked_pn = ack_frm->largest_ack;
|
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))
|
if (!qc_release_lost_pkts(qc, qel->pktns, &lost_pkts, now_ms))
|
||||||
goto leave;
|
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))
|
if (quic_peer_validated_addr(qc))
|
||||||
qc->path->loss.pto_count = 0;
|
qc->path->loss.pto_count = 0;
|
||||||
qc_set_timer(qc);
|
qc_set_timer(qc);
|
||||||
|
Loading…
Reference in New Issue
Block a user