Skip to content
3 changes: 2 additions & 1 deletion apps/src/bin/quiche-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,8 +541,9 @@ fn main() {
continue_write = false;
for client in clients.values_mut() {
// Reduce max_send_burst by 25% if loss is increasing more than 0.1%.
let stats = client.conn.stats();
let loss_rate =
client.conn.stats().lost as f64 / client.conn.stats().sent as f64;
stats.lost as f64 / stats.acked as f64 + stats.lost as f64;
Comment thread
xxoo marked this conversation as resolved.
Outdated
if loss_rate > client.loss_rate + 0.001 {
client.max_send_burst = client.max_send_burst / 4 * 3;
// Minimum bound of 10xMSS.
Expand Down
3 changes: 3 additions & 0 deletions quiche/include/quiche.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ typedef struct {
// The number of QUIC packets sent on this connection.
size_t sent;

// The number of QUIC packets that were acked.
size_t acked;

// The number of QUIC packets that were lost.
size_t lost;

Expand Down
2 changes: 2 additions & 0 deletions quiche/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,7 @@ pub extern "C" fn quiche_stream_iter_free(iter: *mut StreamIter) {
pub struct Stats {
recv: usize,
sent: usize,
acked: usize,
lost: usize,
spurious_lost: usize,
retrans: usize,
Expand Down Expand Up @@ -1370,6 +1371,7 @@ pub extern "C" fn quiche_conn_stats(conn: &Connection, out: &mut Stats) {

out.recv = stats.recv;
out.sent = stats.sent;
out.acked = stats.acked;
out.lost = stats.lost;
out.spurious_lost = stats.spurious_lost;
out.retrans = stats.retrans;
Expand Down
10 changes: 10 additions & 0 deletions quiche/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,9 @@ where
/// Total number of sent packets.
sent_count: usize,

/// Total number of acked packets.
acked_count: usize,

/// Total number of lost packets.
lost_count: usize,

Expand Down Expand Up @@ -2110,6 +2113,7 @@ impl<F: BufFactory> Connection<F> {

recv_count: 0,
sent_count: 0,
acked_count: 0,
lost_count: 0,
spurious_lost_count: 0,
retrans_count: 0,
Expand Down Expand Up @@ -7785,6 +7789,7 @@ impl<F: BufFactory> Connection<F> {
Stats {
recv: self.recv_count,
sent: self.sent_count,
acked: self.acked_count,
lost: self.lost_count,
spurious_lost: self.spurious_lost_count,
retrans: self.retrans_count,
Expand Down Expand Up @@ -8299,6 +8304,7 @@ impl<F: BufFactory> Connection<F> {
let OnAckReceivedOutcome {
lost_packets,
lost_bytes,
acked_packets,
acked_bytes,
spurious_losses,
} = p.recovery.on_ack_received(
Expand Down Expand Up @@ -8327,6 +8333,7 @@ impl<F: BufFactory> Connection<F> {

self.lost_count += lost_packets;
self.lost_bytes += lost_bytes as u64;
self.acked_count += acked_packets;
self.acked_bytes += acked_bytes as u64;
self.spurious_lost_count += spurious_losses;
}
Expand Down Expand Up @@ -9355,6 +9362,9 @@ pub struct Stats {
/// The number of QUIC packets sent.
pub sent: usize,

/// The number of QUIC packets that were acked.
pub acked: usize,

/// The number of QUIC packets that were lost.
pub lost: usize,

Expand Down
1 change: 1 addition & 0 deletions quiche/src/recovery/congestion/delivery_rate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ mod tests {
assert_eq!(ack_outcome, OnAckReceivedOutcome {
lost_packets: 0,
lost_bytes: 0,
acked_packets: packet_count,
acked_bytes: mss * packet_count,
spurious_losses: 0,
});
Expand Down
7 changes: 7 additions & 0 deletions quiche/src/recovery/congestion/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct RecoveryEpoch {
}

struct AckedDetectionResult {
acked_packets: usize,
acked_bytes: usize,
spurious_losses: usize,
spurious_pkt_thresh: Option<u64>,
Expand All @@ -119,6 +120,7 @@ impl RecoveryEpoch {
) -> Result<AckedDetectionResult> {
newly_acked.clear();

let mut acked_packets = 0;
let mut acked_bytes = 0;
let mut spurious_losses = 0;
let mut spurious_pkt_thresh = None;
Expand Down Expand Up @@ -176,6 +178,8 @@ impl RecoveryEpoch {
has_in_flight_spurious_loss = true;
}
} else {
acked_packets += 1;

if unacked.in_flight {
self.in_flight_count -= 1;
acked_bytes += unacked.size;
Expand Down Expand Up @@ -207,6 +211,7 @@ impl RecoveryEpoch {
self.drain_acked_and_lost_packets(now - rtt_stats.rtt());

Ok(AckedDetectionResult {
acked_packets,
acked_bytes,
spurious_losses,
spurious_pkt_thresh,
Expand Down Expand Up @@ -638,6 +643,7 @@ impl RecoveryOps for LegacyRecovery {
trace_id: &str,
) -> Result<OnAckReceivedOutcome> {
let AckedDetectionResult {
acked_packets,
acked_bytes,
spurious_losses,
spurious_pkt_thresh,
Expand Down Expand Up @@ -715,6 +721,7 @@ impl RecoveryOps for LegacyRecovery {
Ok(OnAckReceivedOutcome {
lost_packets,
lost_bytes,
acked_packets,
acked_bytes,
spurious_losses,
})
Expand Down
8 changes: 8 additions & 0 deletions quiche/src/recovery/gcongestion/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ struct RecoveryEpoch {
}

struct AckedDetectionResult {
acked_packets: usize,
acked_bytes: usize,
spurious_losses: usize,
spurious_pkt_thresh: Option<u64>,
Expand Down Expand Up @@ -170,6 +171,7 @@ impl RecoveryEpoch {
) -> Result<AckedDetectionResult> {
newly_acked.clear();

let mut acked_packets = 0;
let mut acked_bytes = 0;
let mut spurious_losses = 0;
let mut spurious_pkt_thresh = None;
Expand Down Expand Up @@ -219,6 +221,8 @@ impl RecoveryEpoch {
ack_eliciting,
..
} => {
acked_packets += 1;

if in_flight {
self.pkts_in_flight -= 1;
acked_bytes += sent_bytes;
Expand Down Expand Up @@ -252,6 +256,7 @@ impl RecoveryEpoch {
self.drain_acked_and_lost_packets();

Ok(AckedDetectionResult {
acked_packets,
acked_bytes,
spurious_losses,
spurious_pkt_thresh,
Expand Down Expand Up @@ -777,6 +782,7 @@ impl RecoveryOps for GRecovery {
let prior_in_flight = self.bytes_in_flight.get();

let AckedDetectionResult {
acked_packets,
acked_bytes,
spurious_losses,
spurious_pkt_thresh,
Expand All @@ -795,6 +801,7 @@ impl RecoveryOps for GRecovery {

if self.newly_acked.is_empty() {
return Ok(OnAckReceivedOutcome {
acked_packets,
acked_bytes,
spurious_losses,
..Default::default()
Expand Down Expand Up @@ -851,6 +858,7 @@ impl RecoveryOps for GRecovery {
Ok(OnAckReceivedOutcome {
lost_packets,
lost_bytes,
acked_packets,
acked_bytes,
spurious_losses,
})
Expand Down
Loading