MINOR: quic: moving code for QUIC loss detection

qc_qc_packet_loss_lookup() is definitively a QUIC loss detection function.
This commit is contained in:
Frédéric Lécaille 2022-04-29 15:07:48 +02:00 committed by Amaury Denoyelle
parent 88e5741c53
commit 1601395063
3 changed files with 62 additions and 58 deletions

View File

@ -81,5 +81,7 @@ struct quic_pktns *quic_pto_pktns(struct quic_conn *qc,
int handshake_completed,
unsigned int *pto);
void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
struct list *lost_pkts);
#endif /* USE_QUIC */
#endif /* _PROTO_QUIC_LOSS_H */

View File

@ -1,3 +1,5 @@
#include <import/eb64tree.h>
#include <haproxy/quic_loss.h>
#include <haproxy/ticks.h>
@ -127,3 +129,61 @@ struct quic_pktns *quic_pto_pktns(struct quic_conn *qc,
return pktns;
}
/* Look for packet loss from sent packets for <qel> encryption level of a
* connection with <ctx> as I/O handler context. If remove is true, remove them from
* their tree if deemed as lost or set the <loss_time> value the packet number
* space if any not deemed lost.
* Should be called after having received an ACK frame with newly acknowledged
* packets or when the the loss detection timer has expired.
* Always succeeds.
*/
void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
struct list *lost_pkts)
{
struct eb_root *pkts;
struct eb64_node *node;
struct quic_loss *ql;
unsigned int loss_delay;
TRACE_ENTER(QUIC_EV_CONN_PKTLOSS, qc, pktns);
pkts = &pktns->tx.pkts;
pktns->tx.loss_time = TICK_ETERNITY;
if (eb_is_empty(pkts))
goto out;
ql = &qc->path->loss;
loss_delay = QUIC_MAX(ql->latest_rtt, ql->srtt >> 3);
loss_delay = QUIC_MAX(loss_delay, MS_TO_TICKS(QUIC_TIMER_GRANULARITY));
node = eb64_first(pkts);
while (node) {
struct quic_tx_packet *pkt;
int64_t largest_acked_pn;
unsigned int loss_time_limit, time_sent;
pkt = eb64_entry(&node->node, struct quic_tx_packet, pn_node);
largest_acked_pn = pktns->rx.largest_acked_pn;
node = eb64_next(node);
if ((int64_t)pkt->pn_node.key > largest_acked_pn)
break;
time_sent = pkt->time_sent;
loss_time_limit = tick_add(time_sent, loss_delay);
if (tick_is_le(time_sent, now_ms) ||
(int64_t)largest_acked_pn >= pkt->pn_node.key + QUIC_LOSS_PACKET_THRESHOLD) {
eb64_delete(&pkt->pn_node);
LIST_APPEND(lost_pkts, &pkt->list);
}
else {
if (tick_isset(pktns->tx.loss_time))
pktns->tx.loss_time = tick_first(pktns->tx.loss_time, loss_time_limit);
else
pktns->tx.loss_time = loss_time_limit;
}
}
out:
TRACE_LEAVE(QUIC_EV_CONN_PKTLOSS, qc, pktns, lost_pkts);
}

View File

@ -1906,64 +1906,6 @@ static inline void qc_release_lost_pkts(struct quic_conn *qc,
}
}
/* Look for packet loss from sent packets for <qel> encryption level of a
* connection with <ctx> as I/O handler context. If remove is true, remove them from
* their tree if deemed as lost or set the <loss_time> value the packet number
* space if any not deemed lost.
* Should be called after having received an ACK frame with newly acknowledged
* packets or when the the loss detection timer has expired.
* Always succeeds.
*/
static void qc_packet_loss_lookup(struct quic_pktns *pktns,
struct quic_conn *qc,
struct list *lost_pkts)
{
struct eb_root *pkts;
struct eb64_node *node;
struct quic_loss *ql;
unsigned int loss_delay;
TRACE_ENTER(QUIC_EV_CONN_PKTLOSS, qc, pktns);
pkts = &pktns->tx.pkts;
pktns->tx.loss_time = TICK_ETERNITY;
if (eb_is_empty(pkts))
goto out;
ql = &qc->path->loss;
loss_delay = QUIC_MAX(ql->latest_rtt, ql->srtt >> 3);
loss_delay = QUIC_MAX(loss_delay, MS_TO_TICKS(QUIC_TIMER_GRANULARITY));
node = eb64_first(pkts);
while (node) {
struct quic_tx_packet *pkt;
int64_t largest_acked_pn;
unsigned int loss_time_limit, time_sent;
pkt = eb64_entry(&node->node, struct quic_tx_packet, pn_node);
largest_acked_pn = pktns->rx.largest_acked_pn;
node = eb64_next(node);
if ((int64_t)pkt->pn_node.key > largest_acked_pn)
break;
time_sent = pkt->time_sent;
loss_time_limit = tick_add(time_sent, loss_delay);
if (tick_is_le(time_sent, now_ms) ||
(int64_t)largest_acked_pn >= pkt->pn_node.key + QUIC_LOSS_PACKET_THRESHOLD) {
eb64_delete(&pkt->pn_node);
LIST_APPEND(lost_pkts, &pkt->list);
}
else {
if (tick_isset(pktns->tx.loss_time))
pktns->tx.loss_time = tick_first(pktns->tx.loss_time, loss_time_limit);
else
pktns->tx.loss_time = loss_time_limit;
}
}
out:
TRACE_LEAVE(QUIC_EV_CONN_PKTLOSS, qc, pktns, lost_pkts);
}
/* 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