Skip to content
File

Blob: firmware/vendor/str0m/tests/bwe/recovery.rs

rust191 lines
1//! BWE recovery mechanism tests (AIMD recovery after congestion).
2 
3use std::time::Duration;
4 
5use netem::{DataSize, NetemConfig};
6use str0m::RtcError;
7use str0m::bwe::Bitrate;
8 
9use crate::common::{BweTestContext, Step, connect_with_bwe, init_crypto_default, init_log};
10 
11#[test]
12fn aimd_multiplicative_decrease_on_congestion() -> Result<(), RtcError> {
13 init_log();
14 init_crypto_default();
15 
16 let plan = vec![
17 Step::Conditions {
18 description: "Good network",
19 config: NetemConfig::new()
20 .latency(Duration::from_millis(20))
21 .link(Bitrate::mbps(5), DataSize::kbytes(100))
22 .seed(42),
23 },
24 Step::Media {
25 description: "Send at 2 Mbps",
26 desired_bitrate: Bitrate::mbps(5),
27 media_send_rate: Bitrate::mbps(2),
28 },
29 Step::Run {
30 description: "Establish baseline estimate",
31 duration: Duration::from_secs(5),
32 },
33 Step::Check {
34 description: "Baseline estimate around 2 Mbps",
35 at_least: Bitrate::mbps(2),
36 },
37 // Introduce severe congestion
38 Step::Conditions {
39 description: "High latency causes overuse",
40 config: NetemConfig::new()
41 .latency(Duration::from_millis(150)) // Queuing delay
42 .link(Bitrate::mbps(5), DataSize::kbytes(100))
43 .seed(42),
44 },
45 Step::Run {
46 description: "Wait for overuse detection and AIMD decrease",
47 duration: Duration::from_secs(3),
48 },
49 Step::Check {
50 description: "Estimate dropped via multiplicative decrease",
51 at_least: Bitrate::kbps(500),
52 },
53 ];
54 
55 let (mut l, mut r) = connect_with_bwe(Bitrate::mbps(2), Bitrate::mbps(5));
56 let mut ctx = BweTestContext::new(&mut l, &mut r);
57 ctx.run_plan(&mut l, &mut r, &plan)?;
58 
59 Ok(())
60}
61 
62#[test]
63fn aimd_additive_increase_recovers_estimate() -> Result<(), RtcError> {
64 init_log();
65 init_crypto_default();
66 
67 let plan = vec![
68 Step::Conditions {
69 description: "Good network",
70 config: NetemConfig::new()
71 .latency(Duration::from_millis(20))
72 .link(Bitrate::mbps(5), DataSize::kbytes(100))
73 .seed(42),
74 },
75 Step::Media {
76 description: "Send at 2 Mbps",
77 desired_bitrate: Bitrate::mbps(5),
78 media_send_rate: Bitrate::mbps(2),
79 },
80 Step::Run {
81 description: "Establish baseline",
82 duration: Duration::from_secs(5),
83 },
84 Step::Check {
85 description: "Baseline around 2 Mbps",
86 at_least: Bitrate::mbps(2),
87 },
88 // Cause congestion
89 Step::Conditions {
90 description: "Temporary congestion",
91 config: NetemConfig::new()
92 .latency(Duration::from_millis(150))
93 .link(Bitrate::mbps(5), DataSize::kbytes(100))
94 .seed(42),
95 },
96 Step::Run {
97 description: "Trigger multiplicative decrease",
98 duration: Duration::from_secs(3),
99 },
100 Step::Check {
101 description: "Estimate dropped",
102 at_least: Bitrate::kbps(500),
103 },
104 // Restore good network
105 Step::Conditions {
106 description: "Restore good conditions",
107 config: NetemConfig::new()
108 .latency(Duration::from_millis(20))
109 .link(Bitrate::mbps(5), DataSize::kbytes(100))
110 .seed(42),
111 },
112 Step::Run {
113 description: "Allow AIMD additive increase to recover",
114 duration: Duration::from_secs(10),
115 },
116 Step::Check {
117 description: "Estimate recovers via additive increase",
118 at_least: Bitrate::mbps(1),
119 },
120 ];
121 
122 let (mut l, mut r) = connect_with_bwe(Bitrate::mbps(2), Bitrate::mbps(5));
123 let mut ctx = BweTestContext::new(&mut l, &mut r);
124 ctx.run_plan(&mut l, &mut r, &plan)?;
125 
126 Ok(())
127}
128 
129#[test]
130fn aimd_recovery_reaches_original_estimate() -> Result<(), RtcError> {
131 init_log();
132 init_crypto_default();
133 
134 let plan = vec![
135 Step::Conditions {
136 description: "Good network",
137 config: NetemConfig::new()
138 .latency(Duration::from_millis(20))
139 .link(Bitrate::mbps(3), DataSize::kbytes(100))
140 .seed(42),
141 },
142 Step::Media {
143 description: "Send at 2 Mbps",
144 desired_bitrate: Bitrate::mbps(5),
145 media_send_rate: Bitrate::mbps(2),
146 },
147 Step::Run {
148 description: "Establish baseline",
149 duration: Duration::from_secs(5),
150 },
151 Step::Check {
152 description: "Baseline established",
153 at_least: Bitrate::mbps(2),
154 },
155 // Brief congestion
156 Step::Conditions {
157 description: "Brief congestion event",
158 config: NetemConfig::new()
159 .latency(Duration::from_millis(150))
160 .link(Bitrate::mbps(3), DataSize::kbytes(100))
161 .seed(42),
162 },
163 Step::Run {
164 description: "Drop estimate",
165 duration: Duration::from_secs(2),
166 },
167 // Restore and allow full recovery
168 Step::Conditions {
169 description: "Restore network",
170 config: NetemConfig::new()
171 .latency(Duration::from_millis(20))
172 .link(Bitrate::mbps(3), DataSize::kbytes(100))
173 .seed(42),
174 },
175 Step::Run {
176 description: "Allow full recovery via AIMD + probes",
177 duration: Duration::from_secs(15),
178 },
179 Step::Check {
180 description: "Estimate recovers to original level",
181 at_least: Bitrate::mbps(2),
182 },
183 ];
184 
185 let (mut l, mut r) = connect_with_bwe(Bitrate::mbps(2), Bitrate::mbps(5));
186 let mut ctx = BweTestContext::new(&mut l, &mut r);
187 ctx.run_plan(&mut l, &mut r, &plan)?;
188 
189 Ok(())
190}