mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-28 07:32:15 +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,
|
||||
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 */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
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;
|
||||
}
|
||||
|
||||
/* 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,11 +354,8 @@ 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,
|
||||
/* 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,14 +380,14 @@ 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,
|
||||
int qc_handle_frms_of_lost_pkt(struct quic_conn *qc,
|
||||
struct quic_tx_packet *pkt,
|
||||
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.
|
||||
* 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 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
|
||||
* 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);
|
||||
|
Loading…
Reference in New Issue
Block a user