Adds test for loss based controller under cross traffic induced loss.
Bug: webrtc:9883
Change-Id: I85a83dd15afe523e0ba5b3a723979317f0b98ab7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156501
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29465}
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index 51f3cd7..9503ada 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -555,6 +555,58 @@
EXPECT_GT(client->target_rate().kbps(), 100);
}
+DataRate AverageBitrateAfterCrossInducedLoss(std::string name) {
+ Scenario s(name, false);
+ NetworkSimulationConfig net_conf;
+ net_conf.bandwidth = DataRate::kbps(1000);
+ net_conf.delay = TimeDelta::ms(100);
+ // Short queue length means that we'll induce loss when sudden TCP traffic
+ // spikes are induced. This corresponds to ca 200 ms for a packet size of 1000
+ // bytes. Such limited buffers are common on for instance wifi routers.
+ net_conf.packet_queue_length_limit = 25;
+
+ auto send_net = {s.CreateSimulationNode(net_conf)};
+ auto ret_net = {s.CreateSimulationNode(net_conf)};
+
+ auto* client = s.CreateClient("send", CallClientConfig());
+ auto* route = s.CreateRoutes(
+ client, send_net, s.CreateClient("return", CallClientConfig()), ret_net);
+ auto* video = s.CreateVideoStream(route->forward(), VideoStreamConfig());
+ s.RunFor(TimeDelta::seconds(10));
+ for (int i = 0; i < 4; ++i) {
+ // Sends TCP cross traffic inducing loss.
+ auto* tcp_traffic =
+ s.net()->StartFakeTcpCrossTraffic(send_net, ret_net, FakeTcpConfig());
+ s.RunFor(TimeDelta::seconds(2));
+ // Allow the ccongestion controller to recover.
+ s.net()->StopCrossTraffic(tcp_traffic);
+ s.RunFor(TimeDelta::seconds(20));
+ }
+ return DataSize::bytes(video->receive()
+ ->GetStats()
+ .rtp_stats.packet_counter.TotalBytes()) /
+ s.TimeSinceStart();
+}
+
+TEST_F(GoogCcNetworkControllerTest,
+ NoLossBasedRecoversSlowerAfterCrossInducedLoss) {
+ // This test acts as a reference for the test below, showing that wihtout the
+ // trial, we have worse behavior.
+ DataRate average_bitrate =
+ AverageBitrateAfterCrossInducedLoss("googcc_unit/no_cross_loss_based");
+ RTC_DCHECK_LE(average_bitrate, DataRate::kbps(650));
+}
+
+TEST_F(GoogCcNetworkControllerTest,
+ LossBasedRecoversFasterAfterCrossInducedLoss) {
+ // We recover bitrate better when subject to loss spikes from cross traffic
+ // when loss based controller is used.
+ ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+ DataRate average_bitrate =
+ AverageBitrateAfterCrossInducedLoss("googcc_unit/cross_loss_based");
+ RTC_DCHECK_GE(average_bitrate, DataRate::kbps(750));
+}
+
TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
Scenario s("googcc_unit/moderate_loss_channel", false);
diff --git a/test/scenario/network_node.cc b/test/scenario/network_node.cc
index b936fcb..d381152 100644
--- a/test/scenario/network_node.cc
+++ b/test/scenario/network_node.cc
@@ -29,6 +29,8 @@
sim_config.packet_overhead = config.packet_overhead.bytes<int>();
sim_config.codel_active_queue_management =
config.codel_active_queue_management;
+ sim_config.queue_length_packets =
+ config.packet_queue_length_limit.value_or(0);
return sim_config;
}
} // namespace
diff --git a/test/scenario/scenario_config.h b/test/scenario/scenario_config.h
index 13d85c3..e769e80 100644
--- a/test/scenario/scenario_config.h
+++ b/test/scenario/scenario_config.h
@@ -223,6 +223,7 @@
TimeDelta delay_std_dev = TimeDelta::Zero();
double loss_rate = 0;
bool codel_active_queue_management = false;
+ absl::optional<int> packet_queue_length_limit;
DataSize packet_overhead = DataSize::Zero();
};
} // namespace test