summaryrefslogtreecommitdiffstats
path: root/third_party/rust/neqo-transport/src/cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/neqo-transport/src/cc')
-rw-r--r--third_party/rust/neqo-transport/src/cc/classic_cc.rs105
-rw-r--r--third_party/rust/neqo-transport/src/cc/mod.rs3
-rw-r--r--third_party/rust/neqo-transport/src/cc/tests/cubic.rs34
-rw-r--r--third_party/rust/neqo-transport/src/cc/tests/new_reno.rs89
4 files changed, 143 insertions, 88 deletions
diff --git a/third_party/rust/neqo-transport/src/cc/classic_cc.rs b/third_party/rust/neqo-transport/src/cc/classic_cc.rs
index f8bcee6722..6914e91f67 100644
--- a/third_party/rust/neqo-transport/src/cc/classic_cc.rs
+++ b/third_party/rust/neqo-transport/src/cc/classic_cc.rs
@@ -298,6 +298,14 @@ impl<T: WindowAdjustment> CongestionControl for ClassicCongestionControl<T> {
congestion || persistent_congestion
}
+ /// Report received ECN CE mark(s) to the congestion controller as a
+ /// congestion event.
+ ///
+ /// See <https://datatracker.ietf.org/doc/html/rfc9002#section-b.7>.
+ fn on_ecn_ce_received(&mut self, largest_acked_pkt: &SentPacket) -> bool {
+ self.on_congestion_event(largest_acked_pkt)
+ }
+
fn discard(&mut self, pkt: &SentPacket) {
if pkt.cc_outstanding() {
assert!(self.bytes_in_flight >= pkt.size);
@@ -488,8 +496,8 @@ impl<T: WindowAdjustment> ClassicCongestionControl<T> {
/// Handle a congestion event.
/// Returns true if this was a true congestion event.
fn on_congestion_event(&mut self, last_packet: &SentPacket) -> bool {
- // Start a new congestion event if lost packet was sent after the start
- // of the previous congestion recovery period.
+ // Start a new congestion event if lost or ECN CE marked packet was sent
+ // after the start of the previous congestion recovery period.
if !self.after_recovery_start(last_packet) {
return false;
}
@@ -538,7 +546,7 @@ impl<T: WindowAdjustment> ClassicCongestionControl<T> {
mod tests {
use std::time::{Duration, Instant};
- use neqo_common::qinfo;
+ use neqo_common::{qinfo, IpTosEcn};
use test_fixture::now;
use super::{
@@ -582,6 +590,7 @@ mod tests {
SentPacket::new(
PacketType::Short,
pn,
+ IpTosEcn::default(),
now() + t,
ack_eliciting,
Vec::new(),
@@ -795,6 +804,7 @@ mod tests {
SentPacket::new(
PacketType::Short,
u64::try_from(i).unwrap(),
+ IpTosEcn::default(),
by_pto(t),
true,
Vec::new(),
@@ -915,6 +925,7 @@ mod tests {
lost[0] = SentPacket::new(
lost[0].pt,
lost[0].pn,
+ lost[0].ecn_mark,
lost[0].time_sent,
false,
Vec::new(),
@@ -1015,11 +1026,12 @@ mod tests {
for _ in 0..packet_burst_size {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1039,11 +1051,12 @@ mod tests {
for _ in 0..ABOVE_APP_LIMIT_PKTS {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1082,11 +1095,12 @@ mod tests {
let p_lost = SentPacket::new(
PacketType::Short,
- 1, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 1,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packet_sent(&p_lost);
cwnd_is_default(&cc);
@@ -1095,11 +1109,12 @@ mod tests {
cwnd_is_halved(&cc);
let p_not_lost = SentPacket::new(
PacketType::Short,
- 2, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 2,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packet_sent(&p_not_lost);
now += RTT;
@@ -1118,11 +1133,12 @@ mod tests {
for _ in 0..packet_burst_size {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1148,11 +1164,12 @@ mod tests {
for _ in 0..ABOVE_APP_LIMIT_PKTS {
let p = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
next_pn += 1;
cc.on_packet_sent(&p);
@@ -1180,4 +1197,26 @@ mod tests {
last_acked_bytes = cc.acked_bytes;
}
}
+
+ #[test]
+ fn ecn_ce() {
+ let mut cc = ClassicCongestionControl::new(NewReno::default());
+ let p_ce = SentPacket::new(
+ PacketType::Short,
+ 1,
+ IpTosEcn::default(),
+ now(),
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
+ );
+ cc.on_packet_sent(&p_ce);
+ cwnd_is_default(&cc);
+ assert_eq!(cc.state, State::SlowStart);
+
+ // Signal congestion (ECN CE) and thus change state to recovery start.
+ cc.on_ecn_ce_received(&p_ce);
+ cwnd_is_halved(&cc);
+ assert_eq!(cc.state, State::RecoveryStart);
+ }
}
diff --git a/third_party/rust/neqo-transport/src/cc/mod.rs b/third_party/rust/neqo-transport/src/cc/mod.rs
index 486d15e67e..2adffbc0c4 100644
--- a/third_party/rust/neqo-transport/src/cc/mod.rs
+++ b/third_party/rust/neqo-transport/src/cc/mod.rs
@@ -53,6 +53,9 @@ pub trait CongestionControl: Display + Debug {
lost_packets: &[SentPacket],
) -> bool;
+ /// Returns true if the congestion window was reduced.
+ fn on_ecn_ce_received(&mut self, largest_acked_pkt: &SentPacket) -> bool;
+
#[must_use]
fn recovery_packet(&self) -> bool;
diff --git a/third_party/rust/neqo-transport/src/cc/tests/cubic.rs b/third_party/rust/neqo-transport/src/cc/tests/cubic.rs
index 2e0200fd6d..8ff591cb47 100644
--- a/third_party/rust/neqo-transport/src/cc/tests/cubic.rs
+++ b/third_party/rust/neqo-transport/src/cc/tests/cubic.rs
@@ -12,6 +12,7 @@ use std::{
time::{Duration, Instant},
};
+use neqo_common::IpTosEcn;
use test_fixture::now;
use crate::{
@@ -41,11 +42,12 @@ fn fill_cwnd(cc: &mut ClassicCongestionControl<Cubic>, mut next_pn: u64, now: In
while cc.bytes_in_flight() < cc.cwnd() {
let sent = SentPacket::new(
PacketType::Short,
- next_pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ next_pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packet_sent(&sent);
next_pn += 1;
@@ -56,11 +58,12 @@ fn fill_cwnd(cc: &mut ClassicCongestionControl<Cubic>, mut next_pn: u64, now: In
fn ack_packet(cc: &mut ClassicCongestionControl<Cubic>, pn: u64, now: Instant) {
let acked = SentPacket::new(
PacketType::Short,
- pn, // pn
- now, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packets_acked(&[acked], &RTT_ESTIMATE, now);
}
@@ -69,11 +72,12 @@ fn packet_lost(cc: &mut ClassicCongestionControl<Cubic>, pn: u64) {
const PTO: Duration = Duration::from_millis(120);
let p_lost = SentPacket::new(
PacketType::Short,
- pn, // pn
- now(), // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ pn,
+ IpTosEcn::default(),
+ now(),
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
cc.on_packets_lost(None, None, PTO, &[p_lost]);
}
diff --git a/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs b/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs
index 4cc20de5a7..0cc560bf2b 100644
--- a/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs
+++ b/third_party/rust/neqo-transport/src/cc/tests/new_reno.rs
@@ -8,6 +8,7 @@
use std::time::Duration;
+use neqo_common::IpTosEcn;
use test_fixture::now;
use crate::{
@@ -44,59 +45,66 @@ fn issue_876() {
let sent_packets = &[
SentPacket::new(
PacketType::Short,
- 1, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE - 1, // size
+ 1,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE - 1,
),
SentPacket::new(
PacketType::Short,
- 2, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE - 2, // size
+ 2,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE - 2,
),
SentPacket::new(
PacketType::Short,
- 3, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 3,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 4, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 4,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 5, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 5,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 6, // pn
- time_before, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ 6,
+ IpTosEcn::default(),
+ time_before,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
),
SentPacket::new(
PacketType::Short,
- 7, // pn
- time_after, // time sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE - 3, // size
+ 7,
+ IpTosEcn::default(),
+ time_after,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE - 3,
),
];
@@ -146,11 +154,12 @@ fn issue_1465() {
let mut next_packet = |now| {
let p = SentPacket::new(
PacketType::Short,
- pn, // pn
- now, // time_sent
- true, // ack eliciting
- Vec::new(), // tokens
- MAX_DATAGRAM_SIZE, // size
+ pn,
+ IpTosEcn::default(),
+ now,
+ true,
+ Vec::new(),
+ MAX_DATAGRAM_SIZE,
);
pn += 1;
p