1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <queue>
12
13 #include "api/transport/goog_cc_factory.h"
14 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
15 #include "test/field_trial.h"
16 #include "test/gtest.h"
17 #include "test/scenario/scenario.h"
18
19 using ::testing::_;
20 using ::testing::Field;
21 using ::testing::Matcher;
22 using ::testing::NiceMock;
23 using ::testing::Property;
24
25 namespace webrtc {
26 namespace test {
27 namespace {
28 // Count dips from a constant high bandwidth level within a short window.
CountBandwidthDips(std::queue<DataRate> bandwidth_history,DataRate threshold)29 int CountBandwidthDips(std::queue<DataRate> bandwidth_history,
30 DataRate threshold) {
31 if (bandwidth_history.empty())
32 return true;
33 DataRate first = bandwidth_history.front();
34 bandwidth_history.pop();
35
36 int dips = 0;
37 bool state_high = true;
38 while (!bandwidth_history.empty()) {
39 if (bandwidth_history.front() + threshold < first && state_high) {
40 ++dips;
41 state_high = false;
42 } else if (bandwidth_history.front() == first) {
43 state_high = true;
44 } else if (bandwidth_history.front() > first) {
45 // If this is toggling we will catch it later when front becomes first.
46 state_high = false;
47 }
48 bandwidth_history.pop();
49 }
50 return dips;
51 }
CreateFeedbackOnlyFactory()52 GoogCcNetworkControllerFactory CreateFeedbackOnlyFactory() {
53 GoogCcFactoryConfig config;
54 config.feedback_only = true;
55 return GoogCcNetworkControllerFactory(std::move(config));
56 }
57
58 const uint32_t kInitialBitrateKbps = 60;
59 const DataRate kInitialBitrate = DataRate::KilobitsPerSec(kInitialBitrateKbps);
60 const float kDefaultPacingRate = 2.5f;
61
CreateVideoSendingClient(Scenario * s,CallClientConfig config,std::vector<EmulatedNetworkNode * > send_link,std::vector<EmulatedNetworkNode * > return_link)62 CallClient* CreateVideoSendingClient(
63 Scenario* s,
64 CallClientConfig config,
65 std::vector<EmulatedNetworkNode*> send_link,
66 std::vector<EmulatedNetworkNode*> return_link) {
67 auto* client = s->CreateClient("send", std::move(config));
68 auto* route = s->CreateRoutes(client, send_link,
69 s->CreateClient("return", CallClientConfig()),
70 return_link);
71 s->CreateVideoStream(route->forward(), VideoStreamConfig());
72 return client;
73 }
74
UpdatesTargetRateBasedOnLinkCapacity(std::string test_name="")75 void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") {
76 ScopedFieldTrials trial("WebRTC-SendSideBwe-WithOverhead/Enabled/");
77 auto factory = CreateFeedbackOnlyFactory();
78 Scenario s("googcc_unit/target_capacity" + test_name, false);
79 CallClientConfig config;
80 config.transport.cc_factory = &factory;
81 config.transport.rates.min_rate = DataRate::KilobitsPerSec(10);
82 config.transport.rates.max_rate = DataRate::KilobitsPerSec(1500);
83 config.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
84 auto send_net = s.CreateMutableSimulationNode([](NetworkSimulationConfig* c) {
85 c->bandwidth = DataRate::KilobitsPerSec(500);
86 c->delay = TimeDelta::Millis(100);
87 c->loss_rate = 0.0;
88 });
89 auto ret_net = s.CreateMutableSimulationNode(
90 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(100); });
91 StatesPrinter* truth = s.CreatePrinter(
92 "send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
93
94 auto* client = CreateVideoSendingClient(&s, config, {send_net->node()},
95 {ret_net->node()});
96
97 truth->PrintRow();
98 s.RunFor(TimeDelta::Seconds(25));
99 truth->PrintRow();
100 EXPECT_NEAR(client->target_rate().kbps(), 450, 100);
101
102 send_net->UpdateConfig([](NetworkSimulationConfig* c) {
103 c->bandwidth = DataRate::KilobitsPerSec(800);
104 c->delay = TimeDelta::Millis(100);
105 });
106
107 truth->PrintRow();
108 s.RunFor(TimeDelta::Seconds(20));
109 truth->PrintRow();
110 EXPECT_NEAR(client->target_rate().kbps(), 750, 150);
111
112 send_net->UpdateConfig([](NetworkSimulationConfig* c) {
113 c->bandwidth = DataRate::KilobitsPerSec(100);
114 c->delay = TimeDelta::Millis(200);
115 });
116 ret_net->UpdateConfig(
117 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(200); });
118
119 truth->PrintRow();
120 s.RunFor(TimeDelta::Seconds(50));
121 truth->PrintRow();
122 EXPECT_NEAR(client->target_rate().kbps(), 90, 25);
123 }
124 } // namespace
125
126 class GoogCcNetworkControllerTest : public ::testing::Test {
127 protected:
GoogCcNetworkControllerTest()128 GoogCcNetworkControllerTest()
129 : current_time_(Timestamp::Millis(123456)), factory_() {}
~GoogCcNetworkControllerTest()130 ~GoogCcNetworkControllerTest() override {}
131
SetUp()132 void SetUp() override {
133 controller_ = factory_.Create(InitialConfig());
134 NetworkControlUpdate update =
135 controller_->OnProcessInterval(DefaultInterval());
136 EXPECT_EQ(update.target_rate->target_rate, kInitialBitrate);
137 EXPECT_EQ(update.pacer_config->data_rate(),
138 kInitialBitrate * kDefaultPacingRate);
139
140 EXPECT_EQ(update.probe_cluster_configs[0].target_data_rate,
141 kInitialBitrate * 3);
142 EXPECT_EQ(update.probe_cluster_configs[1].target_data_rate,
143 kInitialBitrate * 5);
144 }
145 // Custom setup - use an observer that tracks the target bitrate, without
146 // prescribing on which iterations it must change (like a mock would).
TargetBitrateTrackingSetup()147 void TargetBitrateTrackingSetup() {
148 controller_ = factory_.Create(InitialConfig());
149 OnUpdate(controller_->OnProcessInterval(DefaultInterval()));
150 }
151
InitialConfig(int starting_bandwidth_kbps=kInitialBitrateKbps,int min_data_rate_kbps=0,int max_data_rate_kbps=5* kInitialBitrateKbps)152 NetworkControllerConfig InitialConfig(
153 int starting_bandwidth_kbps = kInitialBitrateKbps,
154 int min_data_rate_kbps = 0,
155 int max_data_rate_kbps = 5 * kInitialBitrateKbps) {
156 NetworkControllerConfig config;
157 config.constraints.at_time = current_time_;
158 config.constraints.min_data_rate =
159 DataRate::KilobitsPerSec(min_data_rate_kbps);
160 config.constraints.max_data_rate =
161 DataRate::KilobitsPerSec(max_data_rate_kbps);
162 config.constraints.starting_rate =
163 DataRate::KilobitsPerSec(starting_bandwidth_kbps);
164 config.event_log = &event_log_;
165 return config;
166 }
DefaultInterval()167 ProcessInterval DefaultInterval() {
168 ProcessInterval interval;
169 interval.at_time = current_time_;
170 return interval;
171 }
CreateBitrateReport(DataRate rate)172 RemoteBitrateReport CreateBitrateReport(DataRate rate) {
173 RemoteBitrateReport report;
174 report.receive_time = current_time_;
175 report.bandwidth = rate;
176 return report;
177 }
CreateResult(int64_t arrival_time_ms,int64_t send_time_ms,size_t payload_size,PacedPacketInfo pacing_info)178 PacketResult CreateResult(int64_t arrival_time_ms,
179 int64_t send_time_ms,
180 size_t payload_size,
181 PacedPacketInfo pacing_info) {
182 PacketResult packet_result;
183 packet_result.sent_packet = SentPacket();
184 packet_result.sent_packet.send_time = Timestamp::Millis(send_time_ms);
185 packet_result.sent_packet.size = DataSize::Bytes(payload_size);
186 packet_result.sent_packet.pacing_info = pacing_info;
187 packet_result.receive_time = Timestamp::Millis(arrival_time_ms);
188 return packet_result;
189 }
190
CreateRouteChange(absl::optional<DataRate> start_rate=absl::nullopt,absl::optional<DataRate> min_rate=absl::nullopt,absl::optional<DataRate> max_rate=absl::nullopt)191 NetworkRouteChange CreateRouteChange(
192 absl::optional<DataRate> start_rate = absl::nullopt,
193 absl::optional<DataRate> min_rate = absl::nullopt,
194 absl::optional<DataRate> max_rate = absl::nullopt) {
195 NetworkRouteChange route_change;
196 route_change.at_time = current_time_;
197 route_change.constraints.at_time = current_time_;
198 route_change.constraints.min_data_rate = min_rate;
199 route_change.constraints.max_data_rate = max_rate;
200 route_change.constraints.starting_rate = start_rate;
201 return route_change;
202 }
203
AdvanceTimeMilliseconds(int timedelta_ms)204 void AdvanceTimeMilliseconds(int timedelta_ms) {
205 current_time_ += TimeDelta::Millis(timedelta_ms);
206 }
207
OnUpdate(NetworkControlUpdate update)208 void OnUpdate(NetworkControlUpdate update) {
209 if (update.target_rate)
210 target_bitrate_ = update.target_rate->target_rate;
211 }
212
PacketTransmissionAndFeedbackBlock(int64_t runtime_ms,int64_t delay)213 void PacketTransmissionAndFeedbackBlock(int64_t runtime_ms, int64_t delay) {
214 int64_t delay_buildup = 0;
215 int64_t start_time_ms = current_time_.ms();
216 while (current_time_.ms() - start_time_ms < runtime_ms) {
217 constexpr size_t kPayloadSize = 1000;
218 PacketResult packet =
219 CreateResult(current_time_.ms() + delay_buildup, current_time_.ms(),
220 kPayloadSize, PacedPacketInfo());
221 delay_buildup += delay;
222 OnUpdate(controller_->OnSentPacket(packet.sent_packet));
223 TransportPacketsFeedback feedback;
224 feedback.feedback_time = packet.receive_time;
225 feedback.packet_feedbacks.push_back(packet);
226 OnUpdate(controller_->OnTransportPacketsFeedback(feedback));
227 AdvanceTimeMilliseconds(50);
228 OnUpdate(controller_->OnProcessInterval(DefaultInterval()));
229 }
230 }
231 Timestamp current_time_;
232 absl::optional<DataRate> target_bitrate_;
233 NiceMock<MockRtcEventLog> event_log_;
234 GoogCcNetworkControllerFactory factory_;
235 std::unique_ptr<NetworkControllerInterface> controller_;
236 };
237
TEST_F(GoogCcNetworkControllerTest,ReactsToChangedNetworkConditions)238 TEST_F(GoogCcNetworkControllerTest, ReactsToChangedNetworkConditions) {
239 // Test no change.
240 AdvanceTimeMilliseconds(25);
241 OnUpdate(controller_->OnProcessInterval(DefaultInterval()));
242
243 NetworkControlUpdate update;
244 OnUpdate(controller_->OnRemoteBitrateReport(
245 CreateBitrateReport(kInitialBitrate * 2)));
246 AdvanceTimeMilliseconds(25);
247 update = controller_->OnProcessInterval(DefaultInterval());
248 EXPECT_EQ(update.target_rate->target_rate, kInitialBitrate * 2);
249 EXPECT_EQ(update.pacer_config->data_rate(),
250 kInitialBitrate * 2 * kDefaultPacingRate);
251
252 OnUpdate(
253 controller_->OnRemoteBitrateReport(CreateBitrateReport(kInitialBitrate)));
254 AdvanceTimeMilliseconds(25);
255 update = controller_->OnProcessInterval(DefaultInterval());
256 EXPECT_EQ(update.target_rate->target_rate, kInitialBitrate);
257 EXPECT_EQ(update.pacer_config->data_rate(),
258 kInitialBitrate * kDefaultPacingRate);
259 }
260
261 // Test congestion window pushback on network delay happens.
TEST_F(GoogCcNetworkControllerTest,CongestionWindowPushbackOnNetworkDelay)262 TEST_F(GoogCcNetworkControllerTest, CongestionWindowPushbackOnNetworkDelay) {
263 auto factory = CreateFeedbackOnlyFactory();
264 ScopedFieldTrials trial(
265 "WebRTC-CongestionWindow/QueueSize:800,MinBitrate:30000/");
266 Scenario s("googcc_unit/cwnd_on_delay", false);
267 auto send_net =
268 s.CreateMutableSimulationNode([=](NetworkSimulationConfig* c) {
269 c->bandwidth = DataRate::KilobitsPerSec(1000);
270 c->delay = TimeDelta::Millis(100);
271 });
272 auto ret_net = s.CreateSimulationNode(
273 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(100); });
274 CallClientConfig config;
275 config.transport.cc_factory = &factory;
276 // Start high so bandwidth drop has max effect.
277 config.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
278 config.transport.rates.max_rate = DataRate::KilobitsPerSec(2000);
279 config.transport.rates.min_rate = DataRate::KilobitsPerSec(10);
280
281 auto* client = CreateVideoSendingClient(&s, std::move(config),
282 {send_net->node()}, {ret_net});
283
284 s.RunFor(TimeDelta::Seconds(10));
285 send_net->PauseTransmissionUntil(s.Now() + TimeDelta::Seconds(10));
286 s.RunFor(TimeDelta::Seconds(3));
287
288 // After 3 seconds without feedback from any sent packets, we expect that the
289 // target rate is reduced to the minimum pushback threshold
290 // kDefaultMinPushbackTargetBitrateBps, which is defined as 30 kbps in
291 // congestion_window_pushback_controller.
292 EXPECT_LT(client->target_rate().kbps(), 40);
293 }
294
295 // Test congestion window pushback on network delay happens.
TEST_F(GoogCcNetworkControllerTest,CongestionWindowPushbackDropFrameOnNetworkDelay)296 TEST_F(GoogCcNetworkControllerTest,
297 CongestionWindowPushbackDropFrameOnNetworkDelay) {
298 auto factory = CreateFeedbackOnlyFactory();
299 ScopedFieldTrials trial(
300 "WebRTC-CongestionWindow/QueueSize:800,MinBitrate:30000,DropFrame:true/");
301 Scenario s("googcc_unit/cwnd_on_delay", false);
302 auto send_net =
303 s.CreateMutableSimulationNode([=](NetworkSimulationConfig* c) {
304 c->bandwidth = DataRate::KilobitsPerSec(1000);
305 c->delay = TimeDelta::Millis(100);
306 });
307 auto ret_net = s.CreateSimulationNode(
308 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(100); });
309 CallClientConfig config;
310 config.transport.cc_factory = &factory;
311 // Start high so bandwidth drop has max effect.
312 config.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
313 config.transport.rates.max_rate = DataRate::KilobitsPerSec(2000);
314 config.transport.rates.min_rate = DataRate::KilobitsPerSec(10);
315
316 auto* client = CreateVideoSendingClient(&s, std::move(config),
317 {send_net->node()}, {ret_net});
318
319 s.RunFor(TimeDelta::Seconds(10));
320 send_net->PauseTransmissionUntil(s.Now() + TimeDelta::Seconds(10));
321 s.RunFor(TimeDelta::Seconds(3));
322
323 // As the dropframe is set, after 3 seconds without feedback from any sent
324 // packets, we expect that the target rate is not reduced by congestion
325 // window.
326 EXPECT_GT(client->target_rate().kbps(), 300);
327 }
328
TEST_F(GoogCcNetworkControllerTest,OnNetworkRouteChanged)329 TEST_F(GoogCcNetworkControllerTest, OnNetworkRouteChanged) {
330 NetworkControlUpdate update;
331 DataRate new_bitrate = DataRate::BitsPerSec(200000);
332 update = controller_->OnNetworkRouteChange(CreateRouteChange(new_bitrate));
333 EXPECT_EQ(update.target_rate->target_rate, new_bitrate);
334 EXPECT_EQ(update.pacer_config->data_rate(), new_bitrate * kDefaultPacingRate);
335 EXPECT_EQ(update.probe_cluster_configs.size(), 2u);
336
337 // If the bitrate is reset to -1, the new starting bitrate will be
338 // the minimum default bitrate.
339 const DataRate kDefaultMinBitrate = DataRate::KilobitsPerSec(5);
340 update = controller_->OnNetworkRouteChange(CreateRouteChange());
341 EXPECT_EQ(update.target_rate->target_rate, kDefaultMinBitrate);
342 EXPECT_NEAR(update.pacer_config->data_rate().bps<double>(),
343 kDefaultMinBitrate.bps<double>() * kDefaultPacingRate, 10);
344 EXPECT_EQ(update.probe_cluster_configs.size(), 2u);
345 }
346
TEST_F(GoogCcNetworkControllerTest,ProbeOnRouteChange)347 TEST_F(GoogCcNetworkControllerTest, ProbeOnRouteChange) {
348 NetworkControlUpdate update;
349 update = controller_->OnNetworkRouteChange(CreateRouteChange(
350 2 * kInitialBitrate, DataRate::Zero(), 20 * kInitialBitrate));
351
352 EXPECT_TRUE(update.pacer_config.has_value());
353 EXPECT_EQ(update.target_rate->target_rate, kInitialBitrate * 2);
354 EXPECT_EQ(update.probe_cluster_configs.size(), 2u);
355 EXPECT_EQ(update.probe_cluster_configs[0].target_data_rate,
356 kInitialBitrate * 6);
357 EXPECT_EQ(update.probe_cluster_configs[1].target_data_rate,
358 kInitialBitrate * 12);
359
360 update = controller_->OnProcessInterval(DefaultInterval());
361 }
362
363 // Bandwidth estimation is updated when feedbacks are received.
364 // Feedbacks which show an increasing delay cause the estimation to be reduced.
TEST_F(GoogCcNetworkControllerTest,UpdatesDelayBasedEstimate)365 TEST_F(GoogCcNetworkControllerTest, UpdatesDelayBasedEstimate) {
366 TargetBitrateTrackingSetup();
367 const int64_t kRunTimeMs = 6000;
368
369 // The test must run and insert packets/feedback long enough that the
370 // BWE computes a valid estimate. This is first done in an environment which
371 // simulates no bandwidth limitation, and therefore not built-up delay.
372 PacketTransmissionAndFeedbackBlock(kRunTimeMs, 0);
373 ASSERT_TRUE(target_bitrate_.has_value());
374
375 // Repeat, but this time with a building delay, and make sure that the
376 // estimation is adjusted downwards.
377 DataRate bitrate_before_delay = *target_bitrate_;
378 PacketTransmissionAndFeedbackBlock(kRunTimeMs, 50);
379 EXPECT_LT(*target_bitrate_, bitrate_before_delay);
380 }
381
TEST_F(GoogCcNetworkControllerTest,PaddingRateLimitedByCongestionWindowInTrial)382 TEST_F(GoogCcNetworkControllerTest,
383 PaddingRateLimitedByCongestionWindowInTrial) {
384 ScopedFieldTrials trial(
385 "WebRTC-CongestionWindow/QueueSize:200,MinBitrate:30000/");
386
387 Scenario s("googcc_unit/padding_limited", false);
388 auto send_net =
389 s.CreateMutableSimulationNode([=](NetworkSimulationConfig* c) {
390 c->bandwidth = DataRate::KilobitsPerSec(1000);
391 c->delay = TimeDelta::Millis(100);
392 });
393 auto ret_net = s.CreateSimulationNode(
394 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(100); });
395 CallClientConfig config;
396 // Start high so bandwidth drop has max effect.
397 config.transport.rates.start_rate = DataRate::KilobitsPerSec(1000);
398 config.transport.rates.max_rate = DataRate::KilobitsPerSec(2000);
399 auto* client = s.CreateClient("send", config);
400 auto* route =
401 s.CreateRoutes(client, {send_net->node()},
402 s.CreateClient("return", CallClientConfig()), {ret_net});
403 VideoStreamConfig video;
404 video.stream.pad_to_rate = config.transport.rates.max_rate;
405 s.CreateVideoStream(route->forward(), video);
406
407 // Run for a few seconds to allow the controller to stabilize.
408 s.RunFor(TimeDelta::Seconds(10));
409
410 // Check that padding rate matches target rate.
411 EXPECT_NEAR(client->padding_rate().kbps(), client->target_rate().kbps(), 1);
412
413 // Check this is also the case when congestion window pushback kicks in.
414 send_net->PauseTransmissionUntil(s.Now() + TimeDelta::Seconds(1));
415 EXPECT_NEAR(client->padding_rate().kbps(), client->target_rate().kbps(), 1);
416 }
417
TEST_F(GoogCcNetworkControllerTest,LimitsToFloorIfRttIsHighInTrial)418 TEST_F(GoogCcNetworkControllerTest, LimitsToFloorIfRttIsHighInTrial) {
419 // The field trial limits maximum RTT to 2 seconds, higher RTT means that the
420 // controller backs off until it reaches the minimum configured bitrate. This
421 // allows the RTT to recover faster than the regular control mechanism would
422 // achieve.
423 const DataRate kBandwidthFloor = DataRate::KilobitsPerSec(50);
424 ScopedFieldTrials trial("WebRTC-Bwe-MaxRttLimit/limit:2s,floor:" +
425 std::to_string(kBandwidthFloor.kbps()) + "kbps/");
426 // In the test case, we limit the capacity and add a cross traffic packet
427 // burst that blocks media from being sent. This causes the RTT to quickly
428 // increase above the threshold in the trial.
429 const DataRate kLinkCapacity = DataRate::KilobitsPerSec(100);
430 const TimeDelta kBufferBloatDuration = TimeDelta::Seconds(10);
431 Scenario s("googcc_unit/limit_trial", false);
432 auto send_net = s.CreateSimulationNode([=](NetworkSimulationConfig* c) {
433 c->bandwidth = kLinkCapacity;
434 c->delay = TimeDelta::Millis(100);
435 });
436 auto ret_net = s.CreateSimulationNode(
437 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(100); });
438 CallClientConfig config;
439 config.transport.rates.start_rate = kLinkCapacity;
440
441 auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net});
442 // Run for a few seconds to allow the controller to stabilize.
443 s.RunFor(TimeDelta::Seconds(10));
444 const DataSize kBloatPacketSize = DataSize::Bytes(1000);
445 const int kBloatPacketCount =
446 static_cast<int>(kBufferBloatDuration * kLinkCapacity / kBloatPacketSize);
447 // This will cause the RTT to be large for a while.
448 s.TriggerPacketBurst({send_net}, kBloatPacketCount, kBloatPacketSize.bytes());
449 // Wait to allow the high RTT to be detected and acted upon.
450 s.RunFor(TimeDelta::Seconds(6));
451 // By now the target rate should have dropped to the minimum configured rate.
452 EXPECT_NEAR(client->target_rate().kbps(), kBandwidthFloor.kbps(), 5);
453 }
454
TEST_F(GoogCcNetworkControllerTest,UpdatesTargetRateBasedOnLinkCapacity)455 TEST_F(GoogCcNetworkControllerTest, UpdatesTargetRateBasedOnLinkCapacity) {
456 UpdatesTargetRateBasedOnLinkCapacity();
457 }
458
TEST_F(GoogCcNetworkControllerTest,StableEstimateDoesNotVaryInSteadyState)459 TEST_F(GoogCcNetworkControllerTest, StableEstimateDoesNotVaryInSteadyState) {
460 auto factory = CreateFeedbackOnlyFactory();
461 Scenario s("googcc_unit/stable_target", false);
462 CallClientConfig config;
463 config.transport.cc_factory = &factory;
464 NetworkSimulationConfig net_conf;
465 net_conf.bandwidth = DataRate::KilobitsPerSec(500);
466 net_conf.delay = TimeDelta::Millis(100);
467 auto send_net = s.CreateSimulationNode(net_conf);
468 auto ret_net = s.CreateSimulationNode(net_conf);
469
470 auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net});
471 // Run for a while to allow the estimate to stabilize.
472 s.RunFor(TimeDelta::Seconds(30));
473 DataRate min_stable_target = DataRate::PlusInfinity();
474 DataRate max_stable_target = DataRate::MinusInfinity();
475 DataRate min_target = DataRate::PlusInfinity();
476 DataRate max_target = DataRate::MinusInfinity();
477
478 // Measure variation in steady state.
479 for (int i = 0; i < 20; ++i) {
480 auto stable_target_rate = client->stable_target_rate();
481 auto target_rate = client->target_rate();
482 EXPECT_LE(stable_target_rate, target_rate);
483
484 min_stable_target = std::min(min_stable_target, stable_target_rate);
485 max_stable_target = std::max(max_stable_target, stable_target_rate);
486 min_target = std::min(min_target, target_rate);
487 max_target = std::max(max_target, target_rate);
488 s.RunFor(TimeDelta::Seconds(1));
489 }
490 // We should expect drops by at least 15% (default backoff.)
491 EXPECT_LT(min_target / max_target, 0.85);
492 // We should expect the stable target to be more stable than the immediate one
493 EXPECT_GE(min_stable_target / max_stable_target, min_target / max_target);
494 }
495
TEST_F(GoogCcNetworkControllerTest,LossBasedControlUpdatesTargetRateBasedOnLinkCapacity)496 TEST_F(GoogCcNetworkControllerTest,
497 LossBasedControlUpdatesTargetRateBasedOnLinkCapacity) {
498 ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
499 // TODO(srte): Should the behavior be unaffected at low loss rates?
500 UpdatesTargetRateBasedOnLinkCapacity("_loss_based");
501 }
502
TEST_F(GoogCcNetworkControllerTest,LossBasedControlDoesModestBackoffToHighLoss)503 TEST_F(GoogCcNetworkControllerTest,
504 LossBasedControlDoesModestBackoffToHighLoss) {
505 ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
506 Scenario s("googcc_unit/high_loss_channel", false);
507 CallClientConfig config;
508 config.transport.rates.min_rate = DataRate::KilobitsPerSec(10);
509 config.transport.rates.max_rate = DataRate::KilobitsPerSec(1500);
510 config.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
511 auto send_net = s.CreateSimulationNode([](NetworkSimulationConfig* c) {
512 c->bandwidth = DataRate::KilobitsPerSec(2000);
513 c->delay = TimeDelta::Millis(200);
514 c->loss_rate = 0.1;
515 });
516 auto ret_net = s.CreateSimulationNode(
517 [](NetworkSimulationConfig* c) { c->delay = TimeDelta::Millis(200); });
518
519 auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net});
520
521 s.RunFor(TimeDelta::Seconds(120));
522 // Without LossBasedControl trial, bandwidth drops to ~10 kbps.
523 EXPECT_GT(client->target_rate().kbps(), 100);
524 }
525
AverageBitrateAfterCrossInducedLoss(std::string name)526 DataRate AverageBitrateAfterCrossInducedLoss(std::string name) {
527 Scenario s(name, false);
528 NetworkSimulationConfig net_conf;
529 net_conf.bandwidth = DataRate::KilobitsPerSec(1000);
530 net_conf.delay = TimeDelta::Millis(100);
531 // Short queue length means that we'll induce loss when sudden TCP traffic
532 // spikes are induced. This corresponds to ca 200 ms for a packet size of 1000
533 // bytes. Such limited buffers are common on for instance wifi routers.
534 net_conf.packet_queue_length_limit = 25;
535
536 auto send_net = {s.CreateSimulationNode(net_conf)};
537 auto ret_net = {s.CreateSimulationNode(net_conf)};
538
539 auto* client = s.CreateClient("send", CallClientConfig());
540 auto* callee = s.CreateClient("return", CallClientConfig());
541 auto* route = s.CreateRoutes(client, send_net, callee, ret_net);
542 // TODO(srte): Make this work with RTX enabled or remove it.
543 auto* video = s.CreateVideoStream(route->forward(), [](VideoStreamConfig* c) {
544 c->stream.use_rtx = false;
545 });
546 s.RunFor(TimeDelta::Seconds(10));
547 for (int i = 0; i < 4; ++i) {
548 // Sends TCP cross traffic inducing loss.
549 auto* tcp_traffic =
550 s.net()->StartFakeTcpCrossTraffic(send_net, ret_net, FakeTcpConfig());
551 s.RunFor(TimeDelta::Seconds(2));
552 // Allow the ccongestion controller to recover.
553 s.net()->StopCrossTraffic(tcp_traffic);
554 s.RunFor(TimeDelta::Seconds(20));
555 }
556
557 // Querying the video stats from within the expected runtime environment
558 // (i.e. the TQ that belongs to the CallClient, not the Scenario TQ that
559 // we're currently on).
560 VideoReceiveStream::Stats video_receive_stats;
561 auto* video_stream = video->receive();
562 callee->SendTask([&video_stream, &video_receive_stats]() {
563 video_receive_stats = video_stream->GetStats();
564 });
565 return DataSize::Bytes(
566 video_receive_stats.rtp_stats.packet_counter.TotalBytes()) /
567 s.TimeSinceStart();
568 }
569
TEST_F(GoogCcNetworkControllerTest,NoLossBasedRecoversSlowerAfterCrossInducedLoss)570 TEST_F(GoogCcNetworkControllerTest,
571 NoLossBasedRecoversSlowerAfterCrossInducedLoss) {
572 // This test acts as a reference for the test below, showing that without the
573 // trial, we have worse behavior.
574 DataRate average_bitrate =
575 AverageBitrateAfterCrossInducedLoss("googcc_unit/no_cross_loss_based");
576 RTC_DCHECK_LE(average_bitrate, DataRate::KilobitsPerSec(650));
577 }
578
TEST_F(GoogCcNetworkControllerTest,LossBasedRecoversFasterAfterCrossInducedLoss)579 TEST_F(GoogCcNetworkControllerTest,
580 LossBasedRecoversFasterAfterCrossInducedLoss) {
581 // We recover bitrate better when subject to loss spikes from cross traffic
582 // when loss based controller is used.
583 ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
584 DataRate average_bitrate =
585 AverageBitrateAfterCrossInducedLoss("googcc_unit/cross_loss_based");
586 RTC_DCHECK_GE(average_bitrate, DataRate::KilobitsPerSec(750));
587 }
588
TEST_F(GoogCcNetworkControllerTest,LossBasedEstimatorCapsRateAtModerateLoss)589 TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
590 ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
591 Scenario s("googcc_unit/moderate_loss_channel", false);
592 CallClientConfig config;
593 config.transport.rates.min_rate = DataRate::KilobitsPerSec(10);
594 config.transport.rates.max_rate = DataRate::KilobitsPerSec(5000);
595 config.transport.rates.start_rate = DataRate::KilobitsPerSec(1000);
596
597 NetworkSimulationConfig network;
598 network.bandwidth = DataRate::KilobitsPerSec(2000);
599 network.delay = TimeDelta::Millis(100);
600 // 3% loss rate is in the moderate loss rate region at 2000 kbps, limiting the
601 // bitrate increase.
602 network.loss_rate = 0.03;
603 auto send_net = s.CreateMutableSimulationNode(network);
604 auto* client = s.CreateClient("send", std::move(config));
605 auto* route = s.CreateRoutes(client, {send_net->node()},
606 s.CreateClient("return", CallClientConfig()),
607 {s.CreateSimulationNode(network)});
608 s.CreateVideoStream(route->forward(), VideoStreamConfig());
609 // Allow the controller to stabilize at the lower bitrate.
610 s.RunFor(TimeDelta::Seconds(1));
611 // This increase in capacity would cause the target bitrate to increase to
612 // over 4000 kbps without LossBasedControl.
613 send_net->UpdateConfig([](NetworkSimulationConfig* c) {
614 c->bandwidth = DataRate::KilobitsPerSec(5000);
615 });
616 s.RunFor(TimeDelta::Seconds(20));
617 // Using LossBasedControl, the bitrate will not increase over 2500 kbps since
618 // we have detected moderate loss.
619 EXPECT_LT(client->target_rate().kbps(), 2500);
620 }
621
TEST_F(GoogCcNetworkControllerTest,MaintainsLowRateInSafeResetTrial)622 TEST_F(GoogCcNetworkControllerTest, MaintainsLowRateInSafeResetTrial) {
623 const DataRate kLinkCapacity = DataRate::KilobitsPerSec(200);
624 const DataRate kStartRate = DataRate::KilobitsPerSec(300);
625
626 ScopedFieldTrials trial("WebRTC-Bwe-SafeResetOnRouteChange/Enabled/");
627 Scenario s("googcc_unit/safe_reset_low");
628 auto* send_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
629 c->bandwidth = kLinkCapacity;
630 c->delay = TimeDelta::Millis(10);
631 });
632 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
633 c->transport.rates.start_rate = kStartRate;
634 });
635 auto* route = s.CreateRoutes(
636 client, {send_net}, s.CreateClient("return", CallClientConfig()),
637 {s.CreateSimulationNode(NetworkSimulationConfig())});
638 s.CreateVideoStream(route->forward(), VideoStreamConfig());
639 // Allow the controller to stabilize.
640 s.RunFor(TimeDelta::Millis(500));
641 EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 50);
642 s.ChangeRoute(route->forward(), {send_net});
643 // Allow new settings to propagate.
644 s.RunFor(TimeDelta::Millis(100));
645 // Under the trial, the target should be unchanged for low rates.
646 EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 50);
647 }
648
TEST_F(GoogCcNetworkControllerTest,CutsHighRateInSafeResetTrial)649 TEST_F(GoogCcNetworkControllerTest, CutsHighRateInSafeResetTrial) {
650 const DataRate kLinkCapacity = DataRate::KilobitsPerSec(1000);
651 const DataRate kStartRate = DataRate::KilobitsPerSec(300);
652
653 ScopedFieldTrials trial("WebRTC-Bwe-SafeResetOnRouteChange/Enabled/");
654 Scenario s("googcc_unit/safe_reset_high_cut");
655 auto send_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
656 c->bandwidth = kLinkCapacity;
657 c->delay = TimeDelta::Millis(50);
658 });
659 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
660 c->transport.rates.start_rate = kStartRate;
661 });
662 auto* route = s.CreateRoutes(
663 client, {send_net}, s.CreateClient("return", CallClientConfig()),
664 {s.CreateSimulationNode(NetworkSimulationConfig())});
665 s.CreateVideoStream(route->forward(), VideoStreamConfig());
666 // Allow the controller to stabilize.
667 s.RunFor(TimeDelta::Millis(500));
668 EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 300);
669 s.ChangeRoute(route->forward(), {send_net});
670 // Allow new settings to propagate.
671 s.RunFor(TimeDelta::Millis(50));
672 // Under the trial, the target should be reset from high values.
673 EXPECT_NEAR(client->send_bandwidth().kbps(), kStartRate.kbps(), 30);
674 }
675
TEST_F(GoogCcNetworkControllerTest,DetectsHighRateInSafeResetTrial)676 TEST_F(GoogCcNetworkControllerTest, DetectsHighRateInSafeResetTrial) {
677 ScopedFieldTrials trial(
678 "WebRTC-Bwe-SafeResetOnRouteChange/Enabled,ack/"
679 "WebRTC-SendSideBwe-WithOverhead/Enabled/");
680 const DataRate kInitialLinkCapacity = DataRate::KilobitsPerSec(200);
681 const DataRate kNewLinkCapacity = DataRate::KilobitsPerSec(800);
682 const DataRate kStartRate = DataRate::KilobitsPerSec(300);
683
684 Scenario s("googcc_unit/safe_reset_high_detect");
685 auto* initial_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
686 c->bandwidth = kInitialLinkCapacity;
687 c->delay = TimeDelta::Millis(50);
688 });
689 auto* new_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
690 c->bandwidth = kNewLinkCapacity;
691 c->delay = TimeDelta::Millis(50);
692 });
693 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
694 c->transport.rates.start_rate = kStartRate;
695 });
696 auto* route = s.CreateRoutes(
697 client, {initial_net}, s.CreateClient("return", CallClientConfig()),
698 {s.CreateSimulationNode(NetworkSimulationConfig())});
699 s.CreateVideoStream(route->forward(), VideoStreamConfig());
700 // Allow the controller to stabilize.
701 s.RunFor(TimeDelta::Millis(1000));
702 EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
703 s.ChangeRoute(route->forward(), {new_net});
704 // Allow new settings to propagate, but not probes to be received.
705 s.RunFor(TimeDelta::Millis(50));
706 // Under the field trial, the target rate should be unchanged since it's lower
707 // than the starting rate.
708 EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
709 // However, probing should have made us detect the higher rate.
710 // NOTE: This test causes high loss rate, and the loss-based estimator reduces
711 // the bitrate, making the test fail if we wait longer than one second here.
712 s.RunFor(TimeDelta::Millis(1000));
713 EXPECT_GT(client->send_bandwidth().kbps(), kNewLinkCapacity.kbps() - 300);
714 }
715
TEST_F(GoogCcNetworkControllerTest,TargetRateReducedOnPacingBufferBuildupInTrial)716 TEST_F(GoogCcNetworkControllerTest,
717 TargetRateReducedOnPacingBufferBuildupInTrial) {
718 // Configure strict pacing to ensure build-up.
719 ScopedFieldTrials trial(
720 "WebRTC-CongestionWindow/QueueSize:100,MinBitrate:30000/"
721 "WebRTC-Video-Pacing/factor:1.0/"
722 "WebRTC-AddPacingToCongestionWindowPushback/Enabled/");
723
724 const DataRate kLinkCapacity = DataRate::KilobitsPerSec(1000);
725 const DataRate kStartRate = DataRate::KilobitsPerSec(1000);
726
727 Scenario s("googcc_unit/pacing_buffer_buildup");
728 auto* net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
729 c->bandwidth = kLinkCapacity;
730 c->delay = TimeDelta::Millis(50);
731 });
732 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
733 c->transport.rates.start_rate = kStartRate;
734 });
735 auto* route = s.CreateRoutes(
736 client, {net}, s.CreateClient("return", CallClientConfig()),
737 {s.CreateSimulationNode(NetworkSimulationConfig())});
738 s.CreateVideoStream(route->forward(), VideoStreamConfig());
739 // Allow some time for the buffer to build up.
740 s.RunFor(TimeDelta::Seconds(5));
741
742 // Without trial, pacer delay reaches ~250 ms.
743 EXPECT_LT(client->GetStats().pacer_delay_ms, 150);
744 }
745
TEST_F(GoogCcNetworkControllerTest,NoBandwidthTogglingInLossControlTrial)746 TEST_F(GoogCcNetworkControllerTest, NoBandwidthTogglingInLossControlTrial) {
747 ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
748 Scenario s("googcc_unit/no_toggling");
749 auto* send_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
750 c->bandwidth = DataRate::KilobitsPerSec(2000);
751 c->loss_rate = 0.2;
752 c->delay = TimeDelta::Millis(10);
753 });
754
755 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
756 c->transport.rates.start_rate = DataRate::KilobitsPerSec(300);
757 });
758 auto* route = s.CreateRoutes(
759 client, {send_net}, s.CreateClient("return", CallClientConfig()),
760 {s.CreateSimulationNode(NetworkSimulationConfig())});
761 s.CreateVideoStream(route->forward(), VideoStreamConfig());
762 // Allow the controller to initialize.
763 s.RunFor(TimeDelta::Millis(250));
764
765 std::queue<DataRate> bandwidth_history;
766 const TimeDelta step = TimeDelta::Millis(50);
767 for (TimeDelta time = TimeDelta::Zero(); time < TimeDelta::Millis(2000);
768 time += step) {
769 s.RunFor(step);
770 const TimeDelta window = TimeDelta::Millis(500);
771 if (bandwidth_history.size() >= window / step)
772 bandwidth_history.pop();
773 bandwidth_history.push(client->send_bandwidth());
774 EXPECT_LT(
775 CountBandwidthDips(bandwidth_history, DataRate::KilobitsPerSec(100)),
776 2);
777 }
778 }
779
TEST_F(GoogCcNetworkControllerTest,NoRttBackoffCollapseWhenVideoStops)780 TEST_F(GoogCcNetworkControllerTest, NoRttBackoffCollapseWhenVideoStops) {
781 ScopedFieldTrials trial("WebRTC-Bwe-MaxRttLimit/limit:2s/");
782 Scenario s("googcc_unit/rttbackoff_video_stop");
783 auto* send_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
784 c->bandwidth = DataRate::KilobitsPerSec(2000);
785 c->delay = TimeDelta::Millis(100);
786 });
787
788 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
789 c->transport.rates.start_rate = DataRate::KilobitsPerSec(1000);
790 });
791 auto* route = s.CreateRoutes(
792 client, {send_net}, s.CreateClient("return", CallClientConfig()),
793 {s.CreateSimulationNode(NetworkSimulationConfig())});
794 auto* video = s.CreateVideoStream(route->forward(), VideoStreamConfig());
795 // Allow the controller to initialize, then stop video.
796 s.RunFor(TimeDelta::Seconds(1));
797 video->send()->Stop();
798 s.RunFor(TimeDelta::Seconds(4));
799 EXPECT_GT(client->send_bandwidth().kbps(), 1000);
800 }
801
TEST_F(GoogCcNetworkControllerTest,NoCrashOnVeryLateFeedback)802 TEST_F(GoogCcNetworkControllerTest, NoCrashOnVeryLateFeedback) {
803 Scenario s;
804 auto ret_net = s.CreateMutableSimulationNode(NetworkSimulationConfig());
805 auto* route = s.CreateRoutes(
806 s.CreateClient("send", CallClientConfig()),
807 {s.CreateSimulationNode(NetworkSimulationConfig())},
808 s.CreateClient("return", CallClientConfig()), {ret_net->node()});
809 auto* video = s.CreateVideoStream(route->forward(), VideoStreamConfig());
810 s.RunFor(TimeDelta::Seconds(5));
811 // Delay feedback by several minutes. This will cause removal of the send time
812 // history for the packets as long as kSendTimeHistoryWindow is configured for
813 // a shorter time span.
814 ret_net->PauseTransmissionUntil(s.Now() + TimeDelta::Seconds(300));
815 // Stopping video stream while waiting to save test execution time.
816 video->send()->Stop();
817 s.RunFor(TimeDelta::Seconds(299));
818 // Starting to cause addition of new packet to history, which cause old
819 // packets to be removed.
820 video->send()->Start();
821 // Runs until the lost packets are received. We expect that this will run
822 // without causing any runtime failures.
823 s.RunFor(TimeDelta::Seconds(2));
824 }
825
TEST_F(GoogCcNetworkControllerTest,IsFairToTCP)826 TEST_F(GoogCcNetworkControllerTest, IsFairToTCP) {
827 Scenario s("googcc_unit/tcp_fairness");
828 NetworkSimulationConfig net_conf;
829 net_conf.bandwidth = DataRate::KilobitsPerSec(1000);
830 net_conf.delay = TimeDelta::Millis(50);
831 auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
832 c->transport.rates.start_rate = DataRate::KilobitsPerSec(1000);
833 });
834 auto send_net = {s.CreateSimulationNode(net_conf)};
835 auto ret_net = {s.CreateSimulationNode(net_conf)};
836 auto* route = s.CreateRoutes(
837 client, send_net, s.CreateClient("return", CallClientConfig()), ret_net);
838 s.CreateVideoStream(route->forward(), VideoStreamConfig());
839 s.net()->StartFakeTcpCrossTraffic(send_net, ret_net, FakeTcpConfig());
840 s.RunFor(TimeDelta::Seconds(10));
841
842 // Currently only testing for the upper limit as we in practice back out
843 // quite a lot in this scenario. If this behavior is fixed, we should add a
844 // lower bound to ensure it stays fixed.
845 EXPECT_LT(client->send_bandwidth().kbps(), 750);
846 }
847
848 } // namespace test
849 } // namespace webrtc
850