unsigned int *pto);
void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
- struct list *lost_pkts);
+ struct list *lost_pkts, uint32_t *bytes_lost);
int qc_release_lost_pkts(struct quic_conn *qc, struct quic_pktns *pktns,
struct list *pkts, uint64_t now_us);
#endif /* USE_QUIC */
if (tick_isset(pktns->tx.loss_time)) {
struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
- qc_packet_loss_lookup(pktns, qc, &lost_pkts);
+ qc_packet_loss_lookup(pktns, qc, &lost_pkts, NULL);
if (!LIST_ISEMPTY(&lost_pkts))
tasklet_wakeup(qc->wait_event.tasklet);
if (qc_release_lost_pkts(qc, pktns, &lost_pkts, now_ms))
#include <import/eb64tree.h>
+#include <haproxy/quic_cc-t.h>
#include <haproxy/quic_conn-t.h>
#include <haproxy/quic_loss.h>
#include <haproxy/quic_tls.h>
* Always succeeds.
*/
void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
- struct list *lost_pkts)
+ struct list *lost_pkts, uint32_t *bytes_lost)
{
struct eb_root *pkts;
struct eb64_node *node;
ql->nb_reordered_pkt++;
if (tick_is_le(loss_time_limit, now_ms) || reordered) {
+ struct quic_cc *cc = &qc->path->cc;
+
+ if (cc->algo->on_pkt_lost)
+ cc->algo->on_pkt_lost(cc, pkt, pkt->rs.lost);
eb64_delete(&pkt->pn_node);
LIST_APPEND(lost_pkts, &pkt->list);
+ if (bytes_lost)
+ *bytes_lost += pkt->len;
ql->nb_lost_pkt++;
}
else {
if (!close) {
if (newest_lost) {
+ struct quic_cc *cc = &qc->path->cc;
/* Sent a congestion event to the controller */
struct quic_cc_event ev = { };
ev.loss.time_sent = newest_lost->time_sent;
ev.loss.count = tot_lost;
- quic_cc_event(&qc->path->cc, &ev);
+ quic_cc_event(cc, &ev);
+ if (cc->algo->congestion_event)
+ cc->algo->congestion_event(cc, newest_lost->time_sent);
}
/* If an RTT have been already sampled, <rtt_min> has been set.
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))
+ now_ms, qc->max_ack_delay) &&
+ qc->path->cc.algo->slow_start)
qc->path->cc.algo->slow_start(&qc->path->cc);
}
}