diff --git a/api/test/network_emulation/BUILD.gn b/api/test/network_emulation/BUILD.gn index fb7bedc003..58cd27d45e 100644 --- a/api/test/network_emulation/BUILD.gn +++ b/api/test/network_emulation/BUILD.gn @@ -12,6 +12,7 @@ rtc_library("network_emulation") { visibility = [ "*" ] sources = [ + "cross_traffic.h", "network_emulation_interfaces.cc", "network_emulation_interfaces.h", ] @@ -22,9 +23,28 @@ rtc_library("network_emulation") { "../../../rtc_base:checks", "../../../rtc_base:rtc_base_approved", "../../numerics", + "../../task_queue", "../../units:data_rate", "../../units:data_size", + "../../units:time_delta", "../../units:timestamp", ] absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] } + +rtc_library("create_cross_traffic") { + visibility = [ "*" ] + testonly = true + + sources = [ + "create_cross_traffic.cc", + "create_cross_traffic.h", + ] + + deps = [ + ":network_emulation", + "../..:network_emulation_manager_api", + "../../../rtc_base/task_utils:repeating_task", + "../../../test/network:emulated_network", + ] +} diff --git a/api/test/network_emulation/create_cross_traffic.cc b/api/test/network_emulation/create_cross_traffic.cc new file mode 100644 index 0000000000..36a535cec6 --- /dev/null +++ b/api/test/network_emulation/create_cross_traffic.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "api/test/network_emulation/create_cross_traffic.h" + +#include + +#include "rtc_base/task_utils/repeating_task.h" +#include "test/network/cross_traffic.h" + +namespace webrtc { + +std::unique_ptr CreateRandomWalkCrossTraffic( + CrossTrafficRoute* traffic_route, + RandomWalkConfig config) { + return std::make_unique(config, traffic_route); +} + +std::unique_ptr CreatePulsedPeaksCrossTraffic( + CrossTrafficRoute* traffic_route, + PulsedPeaksConfig config) { + return std::make_unique(config, traffic_route); +} + +std::unique_ptr CreateFakeTcpCrossTraffic( + EmulatedRoute* send_route, + EmulatedRoute* ret_route, + FakeTcpConfig config) { + return std::make_unique(config, send_route, + ret_route); +} + +} // namespace webrtc diff --git a/api/test/network_emulation/create_cross_traffic.h b/api/test/network_emulation/create_cross_traffic.h new file mode 100644 index 0000000000..42fc855392 --- /dev/null +++ b/api/test/network_emulation/create_cross_traffic.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_ +#define API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_ + +#include + +#include "api/test/network_emulation/cross_traffic.h" +#include "api/test/network_emulation_manager.h" + +namespace webrtc { + +// This API is still in development and can be changed without prior notice. + +std::unique_ptr CreateRandomWalkCrossTraffic( + CrossTrafficRoute* traffic_route, + RandomWalkConfig config); + +std::unique_ptr CreatePulsedPeaksCrossTraffic( + CrossTrafficRoute* traffic_route, + PulsedPeaksConfig config); + +std::unique_ptr CreateFakeTcpCrossTraffic( + EmulatedRoute* send_route, + EmulatedRoute* ret_route, + FakeTcpConfig config); + +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_ diff --git a/api/test/network_emulation/cross_traffic.h b/api/test/network_emulation/cross_traffic.h new file mode 100644 index 0000000000..85343e44d2 --- /dev/null +++ b/api/test/network_emulation/cross_traffic.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef API_TEST_NETWORK_EMULATION_CROSS_TRAFFIC_H_ +#define API_TEST_NETWORK_EMULATION_CROSS_TRAFFIC_H_ + +#include "api/task_queue/task_queue_base.h" +#include "api/test/network_emulation/network_emulation_interfaces.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" + +namespace webrtc { + +// This API is still in development and can be changed without prior notice. + +// Represents the endpoint for cross traffic that is going through the network. +// It can be used to emulate unexpected network load. +class CrossTrafficRoute { + public: + virtual ~CrossTrafficRoute() = default; + + // Triggers sending of dummy packets with size |packet_size| bytes. + virtual void TriggerPacketBurst(size_t num_packets, size_t packet_size) = 0; + // Sends a packet over the nodes. The content of the packet is unspecified; + // only the size metter for the emulation purposes. + virtual void SendPacket(size_t packet_size) = 0; + // Sends a packet over the nodes and runs |action| when it has been delivered. + virtual void NetworkDelayedAction(size_t packet_size, + std::function action) = 0; +}; + +// Describes a way of generating cross traffic on some route. Used by +// NetworkEmulationManager to produce cross traffic during some period of time. +class CrossTrafficGenerator { + public: + virtual ~CrossTrafficGenerator() = default; + + // Time between Process calls. + virtual TimeDelta GetProcessInterval() const = 0; + + // Called periodically by NetworkEmulationManager. Generates traffic on the + // route. + virtual void Process(Timestamp at_time) = 0; +}; + +// Config of a cross traffic generator. Generated traffic rises and falls +// randomly. +struct RandomWalkConfig { + int random_seed = 1; + DataRate peak_rate = DataRate::KilobitsPerSec(100); + DataSize min_packet_size = DataSize::Bytes(200); + TimeDelta min_packet_interval = TimeDelta::Millis(1); + TimeDelta update_interval = TimeDelta::Millis(200); + double variance = 0.6; + double bias = -0.1; +}; + +// Config of a cross traffic generator. Generated traffic has form of periodic +// peaks alternating with periods of silence. +struct PulsedPeaksConfig { + DataRate peak_rate = DataRate::KilobitsPerSec(100); + DataSize min_packet_size = DataSize::Bytes(200); + TimeDelta min_packet_interval = TimeDelta::Millis(1); + TimeDelta send_duration = TimeDelta::Millis(100); + TimeDelta hold_duration = TimeDelta::Millis(2000); +}; + +struct FakeTcpConfig { + DataSize packet_size = DataSize::Bytes(1200); + DataSize send_limit = DataSize::PlusInfinity(); + TimeDelta process_interval = TimeDelta::Millis(200); + TimeDelta packet_timeout = TimeDelta::Seconds(1); +}; + +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_CROSS_TRAFFIC_H_ diff --git a/api/test/network_emulation_manager.h b/api/test/network_emulation_manager.h index 80efb0e7d8..4857c872e2 100644 --- a/api/test/network_emulation_manager.h +++ b/api/test/network_emulation_manager.h @@ -17,6 +17,7 @@ #include #include "api/array_view.h" +#include "api/test/network_emulation/cross_traffic.h" #include "api/test/network_emulation/network_emulation_interfaces.h" #include "api/test/simulated_network.h" #include "api/test/time_controller.h" @@ -223,7 +224,8 @@ class NetworkEmulationManager { // Removes route previously created by CreateRoute(...). // Caller mustn't call this function with route, that have been already - // removed earlier. + // removed earlier. Removing a route that is currently in use will lead to + // packets being dropped. virtual void ClearRoute(EmulatedRoute* route) = 0; // Creates a simulated TCP connection using |send_route| for traffic and @@ -233,6 +235,20 @@ class NetworkEmulationManager { virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route, EmulatedRoute* ret_route) = 0; + // Creates a route over the given |via_nodes|. Returns an object that can be + // used to emulate network load with cross traffic over the created route. + virtual CrossTrafficRoute* CreateCrossTrafficRoute( + const std::vector& via_nodes) = 0; + + // Starts generating cross traffic using given |generator|. Takes ownership + // over the generator. + virtual CrossTrafficGenerator* StartCrossTraffic( + std::unique_ptr generator) = 0; + + // Stops generating cross traffic that was started using given |generator|. + // The |generator| shouldn't be used after and the reference may be invalid. + virtual void StopCrossTraffic(CrossTrafficGenerator* generator) = 0; + // Creates EmulatedNetworkManagerInterface which can be used then to inject // network emulation layer into PeerConnection. |endpoints| - are available // network interfaces for PeerConnection. If endpoint is enabled, it will be diff --git a/modules/congestion_controller/BUILD.gn b/modules/congestion_controller/BUILD.gn index 231ff5e0dd..750e9109ae 100644 --- a/modules/congestion_controller/BUILD.gn +++ b/modules/congestion_controller/BUILD.gn @@ -46,6 +46,8 @@ if (rtc_include_tests) { sources = [ "receive_side_congestion_controller_unittest.cc" ] deps = [ ":congestion_controller", + "../../api/test/network_emulation", + "../../api/test/network_emulation:create_cross_traffic", "../../system_wrappers", "../../test:test_support", "../../test/scenario", diff --git a/modules/congestion_controller/goog_cc/BUILD.gn b/modules/congestion_controller/goog_cc/BUILD.gn index e3be246347..a5bcf57e34 100644 --- a/modules/congestion_controller/goog_cc/BUILD.gn +++ b/modules/congestion_controller/goog_cc/BUILD.gn @@ -283,6 +283,8 @@ if (rtc_include_tests) { ":probe_controller", ":pushback_controller", "../../../api/rtc_event_log", + "../../../api/test/network_emulation", + "../../../api/test/network_emulation:create_cross_traffic", "../../../api/transport:field_trial_based_config", "../../../api/transport:goog_cc", "../../../api/transport:network_control", 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 0510cb99b7..8eb4a00431 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 @@ -10,6 +10,8 @@ #include +#include "api/test/network_emulation/create_cross_traffic.h" +#include "api/test/network_emulation/cross_traffic.h" #include "api/transport/goog_cc_factory.h" #include "api/units/data_rate.h" #include "logging/rtc_event_log/mock/mock_rtc_event_log.h" @@ -547,8 +549,9 @@ DataRate AverageBitrateAfterCrossInducedLoss(std::string name) { 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()); + auto* tcp_traffic = s.net()->StartCrossTraffic(CreateFakeTcpCrossTraffic( + s.net()->CreateRoute(send_net), s.net()->CreateRoute(ret_net), + FakeTcpConfig())); s.RunFor(TimeDelta::Seconds(2)); // Allow the ccongestion controller to recover. s.net()->StopCrossTraffic(tcp_traffic); @@ -836,7 +839,9 @@ TEST_F(GoogCcNetworkControllerTest, IsFairToTCP) { auto* route = s.CreateRoutes( client, send_net, s.CreateClient("return", CallClientConfig()), ret_net); s.CreateVideoStream(route->forward(), VideoStreamConfig()); - s.net()->StartFakeTcpCrossTraffic(send_net, ret_net, FakeTcpConfig()); + s.net()->StartCrossTraffic(CreateFakeTcpCrossTraffic( + s.net()->CreateRoute(send_net), s.net()->CreateRoute(ret_net), + FakeTcpConfig())); s.RunFor(TimeDelta::Seconds(10)); // Currently only testing for the upper limit as we in practice back out diff --git a/modules/congestion_controller/receive_side_congestion_controller_unittest.cc b/modules/congestion_controller/receive_side_congestion_controller_unittest.cc index b5846237ee..5622c84689 100644 --- a/modules/congestion_controller/receive_side_congestion_controller_unittest.cc +++ b/modules/congestion_controller/receive_side_congestion_controller_unittest.cc @@ -10,6 +10,8 @@ #include "modules/congestion_controller/include/receive_side_congestion_controller.h" +#include "api/test/network_emulation/create_cross_traffic.h" +#include "api/test/network_emulation/cross_traffic.h" #include "modules/pacing/packet_router.h" #include "system_wrappers/include/clock.h" #include "test/gmock.h" @@ -109,7 +111,9 @@ TEST(ReceiveSideCongestionControllerTest, IsFairToTCP) { VideoStreamConfig video; video.stream.packet_feedback = false; s.CreateVideoStream(route->forward(), video); - s.net()->StartFakeTcpCrossTraffic(send_net, ret_net, FakeTcpConfig()); + s.net()->StartCrossTraffic(CreateFakeTcpCrossTraffic( + s.net()->CreateRoute(send_net), s.net()->CreateRoute(ret_net), + FakeTcpConfig())); s.RunFor(TimeDelta::Seconds(30)); // For some reason we get outcompeted by TCP here, this should probably be // fixed and a lower bound should be added to the test. diff --git a/test/network/BUILD.gn b/test/network/BUILD.gn index 383f149699..e250ccbd51 100644 --- a/test/network/BUILD.gn +++ b/test/network/BUILD.gn @@ -12,6 +12,7 @@ rtc_library("emulated_network") { visibility = [ ":*", "../../api:create_network_emulation_manager", + "../../api/test/network_emulation:create_cross_traffic", ] if (rtc_include_tests) { visibility += [ diff --git a/test/network/cross_traffic.cc b/test/network/cross_traffic.cc index 56e7635142..ae5b156376 100644 --- a/test/network/cross_traffic.cc +++ b/test/network/cross_traffic.cc @@ -24,7 +24,7 @@ namespace webrtc { namespace test { RandomWalkCrossTraffic::RandomWalkCrossTraffic(RandomWalkConfig config, - TrafficRoute* traffic_route) + CrossTrafficRoute* traffic_route) : config_(config), traffic_route_(traffic_route), random_(config_.random_seed) { @@ -56,6 +56,10 @@ void RandomWalkCrossTraffic::Process(Timestamp at_time) { } } +TimeDelta RandomWalkCrossTraffic::GetProcessInterval() const { + return config_.min_packet_interval; +} + DataRate RandomWalkCrossTraffic::TrafficRate() const { RTC_DCHECK_RUN_ON(&sequence_checker_); return config_.peak_rate * intensity_; @@ -70,8 +74,9 @@ ColumnPrinter RandomWalkCrossTraffic::StatsPrinter() { 32); } -PulsedPeaksCrossTraffic::PulsedPeaksCrossTraffic(PulsedPeaksConfig config, - TrafficRoute* traffic_route) +PulsedPeaksCrossTraffic::PulsedPeaksCrossTraffic( + PulsedPeaksConfig config, + CrossTrafficRoute* traffic_route) : config_(config), traffic_route_(traffic_route) { sequence_checker_.Detach(); } @@ -102,6 +107,10 @@ void PulsedPeaksCrossTraffic::Process(Timestamp at_time) { } } +TimeDelta PulsedPeaksCrossTraffic::GetProcessInterval() const { + return config_.min_packet_interval; +} + DataRate PulsedPeaksCrossTraffic::TrafficRate() const { RTC_DCHECK_RUN_ON(&sequence_checker_); return sending_ ? config_.peak_rate : DataRate::Zero(); @@ -240,21 +249,13 @@ void TcpMessageRouteImpl::HandlePacketTimeout(int seq_num, Timestamp at_time) { } } -FakeTcpCrossTraffic::FakeTcpCrossTraffic(Clock* clock, - FakeTcpConfig config, +FakeTcpCrossTraffic::FakeTcpCrossTraffic(FakeTcpConfig config, EmulatedRoute* send_route, EmulatedRoute* ret_route) - : clock_(clock), conf_(config), route_(this, send_route, ret_route) {} + : conf_(config), route_(this, send_route, ret_route) {} -void FakeTcpCrossTraffic::Start(TaskQueueBase* task_queue) { - repeating_task_handle_ = RepeatingTaskHandle::Start(task_queue, [this] { - Process(clock_->CurrentTime()); - return conf_.process_interval; - }); -} - -void FakeTcpCrossTraffic::Stop() { - repeating_task_handle_.Stop(); +TimeDelta FakeTcpCrossTraffic::GetProcessInterval() const { + return conf_.process_interval; } void FakeTcpCrossTraffic::Process(Timestamp at_time) { diff --git a/test/network/cross_traffic.h b/test/network/cross_traffic.h index 942b863bbf..9ed41a90d5 100644 --- a/test/network/cross_traffic.h +++ b/test/network/cross_traffic.h @@ -15,41 +15,34 @@ #include #include +#include "api/test/network_emulation_manager.h" #include "api/units/data_rate.h" #include "api/units/data_size.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "rtc_base/random.h" #include "rtc_base/synchronization/sequence_checker.h" -#include "test/network/traffic_route.h" +#include "test/network/network_emulation.h" #include "test/scenario/column_printer.h" namespace webrtc { namespace test { -struct RandomWalkConfig { - int random_seed = 1; - DataRate peak_rate = DataRate::KilobitsPerSec(100); - DataSize min_packet_size = DataSize::Bytes(200); - TimeDelta min_packet_interval = TimeDelta::Millis(1); - TimeDelta update_interval = TimeDelta::Millis(200); - double variance = 0.6; - double bias = -0.1; -}; - -class RandomWalkCrossTraffic { +class RandomWalkCrossTraffic final : public CrossTrafficGenerator { public: - RandomWalkCrossTraffic(RandomWalkConfig config, TrafficRoute* traffic_route); + RandomWalkCrossTraffic(RandomWalkConfig config, + CrossTrafficRoute* traffic_route); ~RandomWalkCrossTraffic(); - void Process(Timestamp at_time); + void Process(Timestamp at_time) override; + TimeDelta GetProcessInterval() const override; DataRate TrafficRate() const; ColumnPrinter StatsPrinter(); private: SequenceChecker sequence_checker_; const RandomWalkConfig config_; - TrafficRoute* const traffic_route_ RTC_PT_GUARDED_BY(sequence_checker_); + CrossTrafficRoute* const traffic_route_ RTC_PT_GUARDED_BY(sequence_checker_); webrtc::Random random_ RTC_GUARDED_BY(sequence_checker_); Timestamp last_process_time_ RTC_GUARDED_BY(sequence_checker_) = @@ -62,28 +55,21 @@ class RandomWalkCrossTraffic { DataSize pending_size_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero(); }; -struct PulsedPeaksConfig { - DataRate peak_rate = DataRate::KilobitsPerSec(100); - DataSize min_packet_size = DataSize::Bytes(200); - TimeDelta min_packet_interval = TimeDelta::Millis(1); - TimeDelta send_duration = TimeDelta::Millis(100); - TimeDelta hold_duration = TimeDelta::Millis(2000); -}; - -class PulsedPeaksCrossTraffic { +class PulsedPeaksCrossTraffic final : public CrossTrafficGenerator { public: PulsedPeaksCrossTraffic(PulsedPeaksConfig config, - TrafficRoute* traffic_route); + CrossTrafficRoute* traffic_route); ~PulsedPeaksCrossTraffic(); - void Process(Timestamp at_time); + void Process(Timestamp at_time) override; + TimeDelta GetProcessInterval() const override; DataRate TrafficRate() const; ColumnPrinter StatsPrinter(); private: SequenceChecker sequence_checker_; const PulsedPeaksConfig config_; - TrafficRoute* const traffic_route_ RTC_PT_GUARDED_BY(sequence_checker_); + CrossTrafficRoute* const traffic_route_ RTC_PT_GUARDED_BY(sequence_checker_); Timestamp last_update_time_ RTC_GUARDED_BY(sequence_checker_) = Timestamp::MinusInfinity(); @@ -149,23 +135,17 @@ class TcpMessageRouteImpl final : public TcpMessageRoute { TimeDelta last_rtt_ = TimeDelta::Zero(); }; -struct FakeTcpConfig { - DataSize packet_size = DataSize::Bytes(1200); - DataSize send_limit = DataSize::PlusInfinity(); - TimeDelta process_interval = TimeDelta::Millis(200); - TimeDelta packet_timeout = TimeDelta::Seconds(1); -}; - class FakeTcpCrossTraffic - : public TwoWayFakeTrafficRoute::TrafficHandlerInterface { + : public TwoWayFakeTrafficRoute::TrafficHandlerInterface, + public CrossTrafficGenerator { public: - FakeTcpCrossTraffic(Clock* clock, - FakeTcpConfig config, + FakeTcpCrossTraffic(FakeTcpConfig config, EmulatedRoute* send_route, EmulatedRoute* ret_route); - void Start(TaskQueueBase* task_queue); - void Stop(); - void Process(Timestamp at_time); + + TimeDelta GetProcessInterval() const override; + void Process(Timestamp at_time) override; + void OnRequest(int sequence_number, Timestamp at_time) override; void OnResponse(int sequence_number, Timestamp at_time) override; @@ -174,7 +154,6 @@ class FakeTcpCrossTraffic void SendPackets(Timestamp at_time); private: - Clock* const clock_; const FakeTcpConfig conf_; TwoWayFakeTrafficRoute route_; @@ -187,7 +166,6 @@ class FakeTcpCrossTraffic Timestamp last_reduction_time_ = Timestamp::MinusInfinity(); TimeDelta last_rtt_ = TimeDelta::Zero(); DataSize total_sent_ = DataSize::Zero(); - RepeatingTaskHandle repeating_task_handle_; }; } // namespace test diff --git a/test/network/cross_traffic_unittest.cc b/test/network/cross_traffic_unittest.cc index c8d848f154..c8191a3d27 100644 --- a/test/network/cross_traffic_unittest.cc +++ b/test/network/cross_traffic_unittest.cc @@ -25,6 +25,7 @@ #include "test/gmock.h" #include "test/gtest.h" #include "test/network/network_emulation_manager.h" +#include "test/network/traffic_route.h" #include "test/time_controller/simulated_time_controller.h" namespace webrtc { @@ -61,7 +62,8 @@ struct TrafficCounterFixture { TEST(CrossTrafficTest, TriggerPacketBurst) { TrafficCounterFixture fixture; - TrafficRoute traffic(&fixture.clock, &fixture.counter, &fixture.endpoint); + CrossTrafficRouteImpl traffic(&fixture.clock, &fixture.counter, + &fixture.endpoint); traffic.TriggerPacketBurst(100, 1000); EXPECT_EQ(fixture.counter.packets_count_, 100); @@ -70,7 +72,8 @@ TEST(CrossTrafficTest, TriggerPacketBurst) { TEST(CrossTrafficTest, PulsedPeaksCrossTraffic) { TrafficCounterFixture fixture; - TrafficRoute traffic(&fixture.clock, &fixture.counter, &fixture.endpoint); + CrossTrafficRouteImpl traffic(&fixture.clock, &fixture.counter, + &fixture.endpoint); PulsedPeaksConfig config; config.peak_rate = DataRate::KilobitsPerSec(1000); @@ -95,7 +98,8 @@ TEST(CrossTrafficTest, PulsedPeaksCrossTraffic) { TEST(CrossTrafficTest, RandomWalkCrossTraffic) { TrafficCounterFixture fixture; - TrafficRoute traffic(&fixture.clock, &fixture.counter, &fixture.endpoint); + CrossTrafficRouteImpl traffic(&fixture.clock, &fixture.counter, + &fixture.endpoint); RandomWalkConfig config; config.peak_rate = DataRate::KilobitsPerSec(1000); diff --git a/test/network/network_emulation_manager.cc b/test/network/network_emulation_manager.cc index 57706fc782..9ffe9e3aa7 100644 --- a/test/network/network_emulation_manager.cc +++ b/test/network/network_emulation_manager.cc @@ -18,6 +18,7 @@ #include "call/simulated_network.h" #include "rtc_base/fake_network.h" #include "test/network/emulated_turn_server.h" +#include "test/network/traffic_route.h" #include "test/time_controller/real_time_controller.h" #include "test/time_controller/simulated_time_controller.h" @@ -175,7 +176,19 @@ void NetworkEmulationManagerImpl::ClearRoute(EmulatedRoute* route) { RTC_FROM_HERE); } -TrafficRoute* NetworkEmulationManagerImpl::CreateTrafficRoute( +TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute( + EmulatedRoute* send_route, + EmulatedRoute* ret_route) { + auto tcp_route = std::make_unique( + clock_, task_queue_.Get(), send_route, ret_route); + auto* route_ptr = tcp_route.get(); + task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable { + tcp_message_routes_.push_back(std::move(tcp_route)); + }); + return route_ptr; +} + +CrossTrafficRoute* NetworkEmulationManagerImpl::CreateCrossTrafficRoute( const std::vector& via_nodes) { RTC_CHECK(!via_nodes.empty()); EmulatedEndpoint* endpoint = CreateEndpoint(EmulatedEndpointConfig()); @@ -189,88 +202,40 @@ TrafficRoute* NetworkEmulationManagerImpl::CreateTrafficRoute( } cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(), endpoint); - std::unique_ptr traffic_route = - std::make_unique(clock_, via_nodes[0], endpoint); - TrafficRoute* out = traffic_route.get(); + std::unique_ptr traffic_route = + std::make_unique(clock_, via_nodes[0], endpoint); + CrossTrafficRoute* out = traffic_route.get(); traffic_routes_.push_back(std::move(traffic_route)); return out; } -RandomWalkCrossTraffic* -NetworkEmulationManagerImpl::CreateRandomWalkCrossTraffic( - TrafficRoute* traffic_route, - RandomWalkConfig config) { - auto traffic = - std::make_unique(config, traffic_route); - RandomWalkCrossTraffic* out = traffic.get(); +CrossTrafficGenerator* NetworkEmulationManagerImpl::StartCrossTraffic( + std::unique_ptr generator) { + CrossTrafficGenerator* out = generator.get(); + task_queue_.PostTask([this, generator = std::move(generator)]() mutable { + auto* generator_ptr = generator.get(); - task_queue_.PostTask( - [this, config, traffic = std::move(traffic)]() mutable { - auto* traffic_ptr = traffic.get(); - random_cross_traffics_.push_back(std::move(traffic)); - RepeatingTaskHandle::Start(task_queue_.Get(), - [this, config, traffic_ptr] { - traffic_ptr->Process(Now()); - return config.min_packet_interval; - }); - }); - return out; -} + auto repeating_task_handle = + RepeatingTaskHandle::Start(task_queue_.Get(), [this, generator_ptr] { + generator_ptr->Process(Now()); + return generator_ptr->GetProcessInterval(); + }); -PulsedPeaksCrossTraffic* -NetworkEmulationManagerImpl::CreatePulsedPeaksCrossTraffic( - TrafficRoute* traffic_route, - PulsedPeaksConfig config) { - auto traffic = - std::make_unique(config, traffic_route); - PulsedPeaksCrossTraffic* out = traffic.get(); - task_queue_.PostTask( - [this, config, traffic = std::move(traffic)]() mutable { - auto* traffic_ptr = traffic.get(); - pulsed_cross_traffics_.push_back(std::move(traffic)); - RepeatingTaskHandle::Start(task_queue_.Get(), - [this, config, traffic_ptr] { - traffic_ptr->Process(Now()); - return config.min_packet_interval; - }); - }); - return out; -} - -FakeTcpCrossTraffic* NetworkEmulationManagerImpl::StartFakeTcpCrossTraffic( - std::vector send_link, - std::vector ret_link, - FakeTcpConfig config) { - auto traffic = std::make_unique( - clock_, config, CreateRoute(send_link), CreateRoute(ret_link)); - auto* traffic_ptr = traffic.get(); - task_queue_.PostTask([this, traffic = std::move(traffic)]() mutable { - traffic->Start(task_queue_.Get()); - tcp_cross_traffics_.push_back(std::move(traffic)); + cross_traffics_.push_back(CrossTrafficSource( + std::move(generator), std::move(repeating_task_handle))); }); - return traffic_ptr; -} - -TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute( - EmulatedRoute* send_route, - EmulatedRoute* ret_route) { - auto tcp_route = std::make_unique( - clock_, task_queue_.Get(), send_route, ret_route); - auto* route_ptr = tcp_route.get(); - task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable { - tcp_message_routes_.push_back(std::move(tcp_route)); - }); - return route_ptr; + return out; } void NetworkEmulationManagerImpl::StopCrossTraffic( - FakeTcpCrossTraffic* traffic) { + CrossTrafficGenerator* generator) { task_queue_.PostTask([=]() { - traffic->Stop(); - tcp_cross_traffics_.remove_if( - [=](const std::unique_ptr& ptr) { - return ptr.get() == traffic; - }); + auto it = std::find_if(cross_traffics_.begin(), cross_traffics_.end(), + [=](const CrossTrafficSource& el) { + return el.first.get() == generator; + }); + it->second.Stop(); + cross_traffics_.erase(it); }); } diff --git a/test/network/network_emulation_manager.h b/test/network/network_emulation_manager.h index b2b41b34a2..d6e8786c4f 100644 --- a/test/network/network_emulation_manager.h +++ b/test/network/network_emulation_manager.h @@ -34,7 +34,6 @@ #include "test/network/emulated_turn_server.h" #include "test/network/fake_network_socket_server.h" #include "test/network/network_emulation.h" -#include "test/network/traffic_route.h" namespace webrtc { namespace test { @@ -64,23 +63,15 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager { void ClearRoute(EmulatedRoute* route) override; - TrafficRoute* CreateTrafficRoute( - const std::vector& via_nodes); - RandomWalkCrossTraffic* CreateRandomWalkCrossTraffic( - TrafficRoute* traffic_route, - RandomWalkConfig config); - PulsedPeaksCrossTraffic* CreatePulsedPeaksCrossTraffic( - TrafficRoute* traffic_route, - PulsedPeaksConfig config); - FakeTcpCrossTraffic* StartFakeTcpCrossTraffic( - std::vector send_link, - std::vector ret_link, - FakeTcpConfig config); - TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route, EmulatedRoute* ret_route) override; - void StopCrossTraffic(FakeTcpCrossTraffic* traffic); + CrossTrafficRoute* CreateCrossTrafficRoute( + const std::vector& via_nodes) override; + + CrossTrafficGenerator* StartCrossTraffic( + std::unique_ptr generator) override; + void StopCrossTraffic(CrossTrafficGenerator* generator) override; EmulatedNetworkManagerInterface* CreateEmulatedNetworkManagerInterface( const std::vector& endpoints) override; @@ -97,6 +88,9 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager { EmulatedTURNServerConfig config) override; private: + using CrossTrafficSource = + std::pair, RepeatingTaskHandle>; + absl::optional GetNextIPv4Address(); const std::unique_ptr time_controller_; Clock* const clock_; @@ -111,10 +105,8 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager { std::vector> endpoints_; std::vector> network_nodes_; std::vector> routes_; - std::vector> traffic_routes_; - std::vector> random_cross_traffics_; - std::vector> pulsed_cross_traffics_; - std::list> tcp_cross_traffics_; + std::vector> traffic_routes_; + std::vector cross_traffics_; std::list> tcp_message_routes_; std::vector> endpoints_containers_; std::vector> network_managers_; diff --git a/test/network/traffic_route.cc b/test/network/traffic_route.cc index 98586337b9..d42d8e21bb 100644 --- a/test/network/traffic_route.cc +++ b/test/network/traffic_route.cc @@ -53,9 +53,10 @@ class ActionReceiver : public EmulatedNetworkReceiverInterface { } // namespace -TrafficRoute::TrafficRoute(Clock* clock, - EmulatedNetworkReceiverInterface* receiver, - EmulatedEndpoint* endpoint) +CrossTrafficRouteImpl::CrossTrafficRouteImpl( + Clock* clock, + EmulatedNetworkReceiverInterface* receiver, + EmulatedEndpoint* endpoint) : clock_(clock), receiver_(receiver), endpoint_(endpoint) { null_receiver_ = std::make_unique(); absl::optional port = @@ -63,16 +64,17 @@ TrafficRoute::TrafficRoute(Clock* clock, RTC_DCHECK(port); null_receiver_port_ = port.value(); } -TrafficRoute::~TrafficRoute() = default; +CrossTrafficRouteImpl::~CrossTrafficRouteImpl() = default; -void TrafficRoute::TriggerPacketBurst(size_t num_packets, size_t packet_size) { +void CrossTrafficRouteImpl::TriggerPacketBurst(size_t num_packets, + size_t packet_size) { for (size_t i = 0; i < num_packets; ++i) { SendPacket(packet_size); } } -void TrafficRoute::NetworkDelayedAction(size_t packet_size, - std::function action) { +void CrossTrafficRouteImpl::NetworkDelayedAction(size_t packet_size, + std::function action) { auto action_receiver = std::make_unique(action, endpoint_); absl::optional port = endpoint_->BindReceiver(0, action_receiver.get()); @@ -82,11 +84,11 @@ void TrafficRoute::NetworkDelayedAction(size_t packet_size, SendPacket(packet_size, port.value()); } -void TrafficRoute::SendPacket(size_t packet_size) { +void CrossTrafficRouteImpl::SendPacket(size_t packet_size) { SendPacket(packet_size, null_receiver_port_); } -void TrafficRoute::SendPacket(size_t packet_size, uint16_t dest_port) { +void CrossTrafficRouteImpl::SendPacket(size_t packet_size, uint16_t dest_port) { rtc::CopyOnWriteBuffer data(packet_size); std::fill_n(data.MutableData(), data.size(), 0); receiver_->OnPacketReceived(EmulatedIpPacket( diff --git a/test/network/traffic_route.h b/test/network/traffic_route.h index 1bb34c6b6c..513f487226 100644 --- a/test/network/traffic_route.h +++ b/test/network/traffic_route.h @@ -14,6 +14,7 @@ #include #include +#include "api/test/network_emulation_manager.h" #include "rtc_base/copy_on_write_buffer.h" #include "system_wrappers/include/clock.h" #include "test/network/network_emulation.h" @@ -23,19 +24,20 @@ namespace test { // Represents the endpoint for cross traffic that is going through the network. // It can be used to emulate unexpected network load. -class TrafficRoute { +class CrossTrafficRouteImpl final : public CrossTrafficRoute { public: - TrafficRoute(Clock* clock, - EmulatedNetworkReceiverInterface* receiver, - EmulatedEndpoint* endpoint); - ~TrafficRoute(); + CrossTrafficRouteImpl(Clock* clock, + EmulatedNetworkReceiverInterface* receiver, + EmulatedEndpoint* endpoint); + ~CrossTrafficRouteImpl(); // Triggers sending of dummy packets with size |packet_size| bytes. - void TriggerPacketBurst(size_t num_packets, size_t packet_size); + void TriggerPacketBurst(size_t num_packets, size_t packet_size) override; // Sends a packet over the nodes and runs |action| when it has been delivered. - void NetworkDelayedAction(size_t packet_size, std::function action); + void NetworkDelayedAction(size_t packet_size, + std::function action) override; - void SendPacket(size_t packet_size); + void SendPacket(size_t packet_size) override; private: void SendPacket(size_t packet_size, uint16_t dest_port); diff --git a/test/peer_scenario/peer_scenario.cc b/test/peer_scenario/peer_scenario.cc index c3443aa185..ea959c943a 100644 --- a/test/peer_scenario/peer_scenario.cc +++ b/test/peer_scenario/peer_scenario.cc @@ -77,8 +77,8 @@ SignalingRoute PeerScenario::ConnectSignaling( PeerScenarioClient* callee, std::vector send_link, std::vector ret_link) { - return SignalingRoute(caller, callee, net_.CreateTrafficRoute(send_link), - net_.CreateTrafficRoute(ret_link)); + return SignalingRoute(caller, callee, net_.CreateCrossTrafficRoute(send_link), + net_.CreateCrossTrafficRoute(ret_link)); } void PeerScenario::SimpleConnection( diff --git a/test/peer_scenario/signaling_route.cc b/test/peer_scenario/signaling_route.cc index 2e0213df16..908d405461 100644 --- a/test/peer_scenario/signaling_route.cc +++ b/test/peer_scenario/signaling_route.cc @@ -41,7 +41,7 @@ struct IceMessage { void StartIceSignalingForRoute(PeerScenarioClient* caller, PeerScenarioClient* callee, - TrafficRoute* send_route) { + CrossTrafficRoute* send_route) { caller->handlers()->on_ice_candidate.push_back( [=](const IceCandidateInterface* candidate) { IceMessage msg(candidate); @@ -56,8 +56,8 @@ void StartIceSignalingForRoute(PeerScenarioClient* caller, void StartSdpNegotiation( PeerScenarioClient* caller, PeerScenarioClient* callee, - TrafficRoute* send_route, - TrafficRoute* ret_route, + CrossTrafficRoute* send_route, + CrossTrafficRoute* ret_route, std::function munge_offer, std::function modify_offer, std::function exchange_finished) { @@ -80,8 +80,8 @@ void StartSdpNegotiation( SignalingRoute::SignalingRoute(PeerScenarioClient* caller, PeerScenarioClient* callee, - TrafficRoute* send_route, - TrafficRoute* ret_route) + CrossTrafficRoute* send_route, + CrossTrafficRoute* ret_route) : caller_(caller), callee_(callee), send_route_(send_route), diff --git a/test/peer_scenario/signaling_route.h b/test/peer_scenario/signaling_route.h index 7434551d3f..021fc4989b 100644 --- a/test/peer_scenario/signaling_route.h +++ b/test/peer_scenario/signaling_route.h @@ -25,8 +25,8 @@ class SignalingRoute { public: SignalingRoute(PeerScenarioClient* caller, PeerScenarioClient* callee, - TrafficRoute* send_route, - TrafficRoute* ret_route); + CrossTrafficRoute* send_route, + CrossTrafficRoute* ret_route); void StartIceSignaling(); @@ -57,8 +57,8 @@ class SignalingRoute { private: PeerScenarioClient* const caller_; PeerScenarioClient* const callee_; - TrafficRoute* const send_route_; - TrafficRoute* const ret_route_; + CrossTrafficRoute* const send_route_; + CrossTrafficRoute* const ret_route_; }; } // namespace test diff --git a/test/scenario/BUILD.gn b/test/scenario/BUILD.gn index f5c22fcafb..ede93c68ff 100644 --- a/test/scenario/BUILD.gn +++ b/test/scenario/BUILD.gn @@ -174,6 +174,8 @@ if (rtc_include_tests) { ] deps = [ ":scenario", + "../../api/test/network_emulation", + "../../api/test/network_emulation:create_cross_traffic", "../../logging:mocks", "../../rtc_base:checks", "../../rtc_base:rtc_base_approved", diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc index c1c664a754..239aad9dfe 100644 --- a/test/scenario/scenario.cc +++ b/test/scenario/scenario.cc @@ -198,7 +198,7 @@ SimulationNode* Scenario::CreateMutableSimulationNode( void Scenario::TriggerPacketBurst(std::vector over_nodes, size_t num_packets, size_t packet_size) { - network_manager_.CreateTrafficRoute(over_nodes) + network_manager_.CreateCrossTrafficRoute(over_nodes) ->TriggerPacketBurst(num_packets, packet_size); } @@ -206,7 +206,7 @@ void Scenario::NetworkDelayedAction( std::vector over_nodes, size_t packet_size, std::function action) { - network_manager_.CreateTrafficRoute(over_nodes) + network_manager_.CreateCrossTrafficRoute(over_nodes) ->NetworkDelayedAction(packet_size, action); } diff --git a/test/scenario/scenario_unittest.cc b/test/scenario/scenario_unittest.cc index 177ac27373..fc370fba77 100644 --- a/test/scenario/scenario_unittest.cc +++ b/test/scenario/scenario_unittest.cc @@ -11,6 +11,8 @@ #include +#include "api/test/network_emulation/create_cross_traffic.h" +#include "api/test/network_emulation/cross_traffic.h" #include "test/field_trial.h" #include "test/gtest.h" #include "test/logging/memory_log_writer.h" @@ -44,8 +46,8 @@ TEST(ScenarioTest, StartsAndStopsWithoutErrors) { s.CreateAudioStream(route->reverse(), audio_stream_config); RandomWalkConfig cross_traffic_config; - s.net()->CreateRandomWalkCrossTraffic( - s.net()->CreateTrafficRoute({alice_net}), cross_traffic_config); + s.net()->StartCrossTraffic(CreateRandomWalkCrossTraffic( + s.net()->CreateCrossTrafficRoute({alice_net}), cross_traffic_config)); s.NetworkDelayedAction({alice_net, bob_net}, 100, [&packet_received] { packet_received = true; }); diff --git a/test/scenario/video_stream_unittest.cc b/test/scenario/video_stream_unittest.cc index 52be3f82ff..95936c763f 100644 --- a/test/scenario/video_stream_unittest.cc +++ b/test/scenario/video_stream_unittest.cc @@ -9,6 +9,8 @@ */ #include +#include "api/test/network_emulation/create_cross_traffic.h" +#include "api/test/network_emulation/cross_traffic.h" #include "test/field_trial.h" #include "test/gtest.h" #include "test/scenario/scenario.h" @@ -217,8 +219,9 @@ TEST(VideoStreamTest, ResolutionAdaptsToAvailableBandwidth) { // Trigger cross traffic, run until we have seen 3 consecutive // seconds with no VGA frames due to reduced available bandwidth. - auto cross_traffic = - s.net()->StartFakeTcpCrossTraffic(send_net, ret_net, FakeTcpConfig()); + auto cross_traffic = s.net()->StartCrossTraffic(CreateFakeTcpCrossTraffic( + s.net()->CreateRoute(send_net), s.net()->CreateRoute(ret_net), + FakeTcpConfig())); int num_seconds_without_vga = 0; int num_iterations = 0;