Using NetworkEmulationManager in Scenario tests.

Bug: webrtc:9510
Change-Id: Ib619526269c58f0c46c0c1f01ba6c0efa5f79ba5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132781
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27635}
diff --git a/test/scenario/network_node.cc b/test/scenario/network_node.cc
index e8f325b..e8b7646 100644
--- a/test/scenario/network_node.cc
+++ b/test/scenario/network_node.cc
@@ -33,35 +33,26 @@
 }
 }  // namespace
 
-void NullReceiver::OnPacketReceived(EmulatedIpPacket packet) {}
+SimulationNode::SimulationNode(NetworkSimulationConfig config,
+                               SimulatedNetwork* behavior,
+                               EmulatedNetworkNode* network_node)
+    : config_(config), simulation_(behavior), network_node_(network_node) {}
 
-ActionReceiver::ActionReceiver(std::function<void()> action)
-    : action_(action) {}
-
-void ActionReceiver::OnPacketReceived(EmulatedIpPacket packet) {
-  action_();
-}
-
-std::unique_ptr<SimulationNode> SimulationNode::Create(
-    Clock* clock,
-    rtc::TaskQueue* task_queue,
+std::unique_ptr<SimulatedNetwork> SimulationNode::CreateBehavior(
     NetworkSimulationConfig config) {
   SimulatedNetwork::Config sim_config = CreateSimulationConfig(config);
-  auto network = absl::make_unique<SimulatedNetwork>(sim_config);
-  SimulatedNetwork* simulation_ptr = network.get();
-  return std::unique_ptr<SimulationNode>(new SimulationNode(
-      clock, task_queue, config, std::move(network), simulation_ptr));
+  return absl::make_unique<SimulatedNetwork>(sim_config);
 }
 
 void SimulationNode::UpdateConfig(
     std::function<void(NetworkSimulationConfig*)> modifier) {
   modifier(&config_);
   SimulatedNetwork::Config sim_config = CreateSimulationConfig(config_);
-  simulated_network_->SetConfig(sim_config);
+  simulation_->SetConfig(sim_config);
 }
 
 void SimulationNode::PauseTransmissionUntil(Timestamp until) {
-  simulated_network_->PauseTransmissionUntil(until.us());
+  simulation_->PauseTransmissionUntil(until.us());
 }
 
 ColumnPrinter SimulationNode::ConfigPrinter() const {
@@ -73,15 +64,6 @@
       });
 }
 
-SimulationNode::SimulationNode(
-    Clock* clock,
-    rtc::TaskQueue* task_queue,
-    NetworkSimulationConfig config,
-    std::unique_ptr<NetworkBehaviorInterface> behavior,
-    SimulatedNetwork* simulation)
-    : EmulatedNetworkNode(clock, task_queue, std::move(behavior)),
-      simulated_network_(simulation),
-      config_(config) {}
 
 NetworkNodeTransport::NetworkNodeTransport(Clock* sender_clock,
                                            Call* sender_call)
@@ -162,57 +144,5 @@
   send_net_ = nullptr;
 }
 
-CrossTrafficSource::CrossTrafficSource(EmulatedNetworkReceiverInterface* target,
-                                       rtc::IPAddress receiver_ip,
-                                       CrossTrafficConfig config)
-    : target_(target),
-      receiver_address_(receiver_ip, 0),
-      config_(config),
-      random_(config.random_seed) {}
-
-CrossTrafficSource::~CrossTrafficSource() = default;
-
-DataRate CrossTrafficSource::TrafficRate() const {
-  return config_.peak_rate * intensity_;
-}
-
-void CrossTrafficSource::Process(Timestamp at_time, TimeDelta delta) {
-  time_since_update_ += delta;
-  if (config_.mode == CrossTrafficConfig::Mode::kRandomWalk) {
-    if (time_since_update_ >= config_.random_walk.update_interval) {
-      intensity_ += random_.Gaussian(config_.random_walk.bias,
-                                     config_.random_walk.variance) *
-                    time_since_update_.seconds<double>();
-      intensity_ = rtc::SafeClamp(intensity_, 0.0, 1.0);
-      time_since_update_ = TimeDelta::Zero();
-    }
-  } else if (config_.mode == CrossTrafficConfig::Mode::kPulsedPeaks) {
-    if (intensity_ == 0 && time_since_update_ >= config_.pulsed.hold_duration) {
-      intensity_ = 1;
-      time_since_update_ = TimeDelta::Zero();
-    } else if (intensity_ == 1 &&
-               time_since_update_ >= config_.pulsed.send_duration) {
-      intensity_ = 0;
-      time_since_update_ = TimeDelta::Zero();
-    }
-  }
-  pending_size_ += TrafficRate() * delta;
-  if (pending_size_ > config_.min_packet_size) {
-    target_->OnPacketReceived(EmulatedIpPacket(
-        /*from=*/rtc::SocketAddress(), receiver_address_,
-        rtc::CopyOnWriteBuffer(pending_size_.bytes()), at_time));
-    pending_size_ = DataSize::Zero();
-  }
-}
-
-ColumnPrinter CrossTrafficSource::StatsPrinter() {
-  return ColumnPrinter::Lambda("cross_traffic_rate",
-                               [this](rtc::SimpleStringBuilder& sb) {
-                                 sb.AppendFormat("%.0lf",
-                                                 TrafficRate().bps() / 8.0);
-                               },
-                               32);
-}
-
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/scenario/network_node.h b/test/scenario/network_node.h
index e324eba..5dcfa52 100644
--- a/test/scenario/network_node.h
+++ b/test/scenario/network_node.h
@@ -30,42 +30,23 @@
 namespace webrtc {
 namespace test {
 
-class NullReceiver : public EmulatedNetworkReceiverInterface {
+class SimulationNode {
  public:
-  void OnPacketReceived(EmulatedIpPacket packet) override;
-};
-class ActionReceiver : public EmulatedNetworkReceiverInterface {
- public:
-  explicit ActionReceiver(std::function<void()> action);
-  virtual ~ActionReceiver() = default;
+  SimulationNode(NetworkSimulationConfig config,
+                 SimulatedNetwork* behavior,
+                 EmulatedNetworkNode* network_node);
+  static std::unique_ptr<SimulatedNetwork> CreateBehavior(
+      NetworkSimulationConfig config);
 
-  void OnPacketReceived(EmulatedIpPacket packet) override;
-
- private:
-  std::function<void()> action_;
-};
-
-class SimulationNode : public EmulatedNetworkNode {
- public:
   void UpdateConfig(std::function<void(NetworkSimulationConfig*)> modifier);
   void PauseTransmissionUntil(Timestamp until);
   ColumnPrinter ConfigPrinter() const;
-  EmulatedNetworkNode* node() { return this; }
+  EmulatedNetworkNode* node() { return network_node_; }
 
  private:
-  friend class Scenario;
-
-  SimulationNode(Clock* clock,
-                 rtc::TaskQueue* task_queue,
-                 NetworkSimulationConfig config,
-                 std::unique_ptr<NetworkBehaviorInterface> behavior,
-                 SimulatedNetwork* simulation);
-  static std::unique_ptr<SimulationNode> Create(Clock* clock,
-                                                rtc::TaskQueue* task_queue,
-                                                NetworkSimulationConfig config);
-
-  SimulatedNetwork* const simulated_network_;
   NetworkSimulationConfig config_;
+  SimulatedNetwork* const simulation_;
+  EmulatedNetworkNode* const network_node_;
 };
 
 class NetworkNodeTransport : public Transport {
@@ -99,31 +80,6 @@
   DataSize packet_overhead_ RTC_GUARDED_BY(crit_sect_) = DataSize::Zero();
   rtc::NetworkRoute current_network_route_ RTC_GUARDED_BY(crit_sect_);
 };
-
-// CrossTrafficSource is created by a Scenario and generates cross traffic. It
-// provides methods to access and print internal state.
-class CrossTrafficSource {
- public:
-  DataRate TrafficRate() const;
-  ColumnPrinter StatsPrinter();
-  ~CrossTrafficSource();
-
- private:
-  friend class Scenario;
-  CrossTrafficSource(EmulatedNetworkReceiverInterface* target,
-                     rtc::IPAddress receiver_ip,
-                     CrossTrafficConfig config);
-  void Process(Timestamp at_time, TimeDelta delta);
-
-  EmulatedNetworkReceiverInterface* const target_;
-  const rtc::SocketAddress receiver_address_;
-  CrossTrafficConfig config_;
-  webrtc::Random random_;
-
-  TimeDelta time_since_update_ = TimeDelta::Zero();
-  double intensity_ = 0;
-  DataSize pending_size_ = DataSize::Zero();
-};
 }  // namespace test
 }  // namespace webrtc
 #endif  // TEST_SCENARIO_NETWORK_NODE_H_
diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc
index 11ff29d..e469fc6 100644
--- a/test/scenario/scenario.cc
+++ b/test/scenario/scenario.cc
@@ -73,6 +73,7 @@
       clock_(time_controller_->GetClock()),
       audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()),
       audio_encoder_factory_(CreateBuiltinAudioEncoderFactory()),
+      network_manager_(time_controller_.get()),
       task_queue_(time_controller_->GetTaskQueueFactory()->CreateTaskQueue(
           "Scenario",
           TaskQueueFactory::Priority::NORMAL)) {}
@@ -192,6 +193,7 @@
   simulated_time_clients_.emplace_back(client);
   return client;
 }
+
 EmulatedNetworkNode* Scenario::CreateSimulationNode(
     std::function<void(NetworkSimulationConfig*)> config_modifier) {
   NetworkSimulationConfig config;
@@ -201,7 +203,8 @@
 
 EmulatedNetworkNode* Scenario::CreateSimulationNode(
     NetworkSimulationConfig config) {
-  return CreateMutableSimulationNode(config);
+  return network_manager_.CreateEmulatedNode(
+      SimulationNode::CreateBehavior(config));
 }
 
 SimulationNode* Scenario::CreateMutableSimulationNode(
@@ -213,55 +216,29 @@
 
 SimulationNode* Scenario::CreateMutableSimulationNode(
     NetworkSimulationConfig config) {
-  auto network_node = SimulationNode::Create(clock_, &task_queue_, config);
-  SimulationNode* sim_node = network_node.get();
-  network_nodes_.emplace_back(std::move(network_node));
-  return sim_node;
+  std::unique_ptr<SimulatedNetwork> behavior =
+      SimulationNode::CreateBehavior(config);
+  SimulatedNetwork* behavior_ptr = behavior.get();
+  auto* emulated_node =
+      network_manager_.CreateEmulatedNode(std::move(behavior));
+  simulation_nodes_.emplace_back(
+      new SimulationNode(config, behavior_ptr, emulated_node));
+  return simulation_nodes_.back().get();
 }
 
 void Scenario::TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes,
                                   size_t num_packets,
                                   size_t packet_size) {
-  rtc::IPAddress route_ip(next_route_id_++);
-  EmulatedNetworkNode::CreateRoute(route_ip, over_nodes, &null_receiver_);
-  for (size_t i = 0; i < num_packets; ++i)
-    over_nodes[0]->OnPacketReceived(EmulatedIpPacket(
-        /*from=*/rtc::SocketAddress(), /*to=*/rtc::SocketAddress(route_ip, 0),
-        rtc::CopyOnWriteBuffer(packet_size), Now()));
+  network_manager_.CreateTrafficRoute(over_nodes)
+      ->TriggerPacketBurst(num_packets, packet_size);
 }
 
 void Scenario::NetworkDelayedAction(
     std::vector<EmulatedNetworkNode*> over_nodes,
     size_t packet_size,
     std::function<void()> action) {
-  rtc::IPAddress route_ip(next_route_id_++);
-  action_receivers_.emplace_back(new ActionReceiver(action));
-  EmulatedNetworkNode::CreateRoute(route_ip, over_nodes,
-                                   action_receivers_.back().get());
-  over_nodes[0]->OnPacketReceived(EmulatedIpPacket(
-      /*from=*/rtc::SocketAddress(), /*to=*/rtc::SocketAddress(route_ip, 0),
-      rtc::CopyOnWriteBuffer(packet_size), Now()));
-}
-
-CrossTrafficSource* Scenario::CreateCrossTraffic(
-    std::vector<EmulatedNetworkNode*> over_nodes,
-    std::function<void(CrossTrafficConfig*)> config_modifier) {
-  CrossTrafficConfig cross_config;
-  config_modifier(&cross_config);
-  return CreateCrossTraffic(over_nodes, cross_config);
-}
-
-CrossTrafficSource* Scenario::CreateCrossTraffic(
-    std::vector<EmulatedNetworkNode*> over_nodes,
-    CrossTrafficConfig config) {
-  rtc::IPAddress route_ip(next_route_id_++);
-  cross_traffic_sources_.emplace_back(
-      new CrossTrafficSource(over_nodes.front(), route_ip, config));
-  CrossTrafficSource* node = cross_traffic_sources_.back().get();
-  EmulatedNetworkNode::CreateRoute(route_ip, over_nodes, &null_receiver_);
-  Every(config.min_packet_interval,
-        [this, node](TimeDelta delta) { node->Process(Now(), delta); });
-  return node;
+  network_manager_.CreateTrafficRoute(over_nodes)
+      ->NetworkDelayedAction(packet_size, action);
 }
 
 VideoStreamPair* Scenario::CreateVideoStream(
diff --git a/test/scenario/scenario.h b/test/scenario/scenario.h
index fb4f0bb..1799ef3 100644
--- a/test/scenario/scenario.h
+++ b/test/scenario/scenario.h
@@ -23,6 +23,7 @@
 #include "test/scenario/audio_stream.h"
 #include "test/scenario/call_client.h"
 #include "test/scenario/column_printer.h"
+#include "test/scenario/network/network_emulation_manager.h"
 #include "test/scenario/network_node.h"
 #include "test/scenario/scenario_config.h"
 #include "test/scenario/simulated_time.h"
@@ -48,6 +49,7 @@
            bool real_time);
   RTC_DISALLOW_COPY_AND_ASSIGN(Scenario);
   ~Scenario();
+  NetworkEmulationManagerImpl* net() { return &network_manager_; }
 
   EmulatedNetworkNode* CreateSimulationNode(NetworkSimulationConfig config);
   EmulatedNetworkNode* CreateSimulationNode(
@@ -102,13 +104,6 @@
       std::pair<CallClient*, CallClient*> clients,
       AudioStreamConfig config);
 
-  CrossTrafficSource* CreateCrossTraffic(
-      std::vector<EmulatedNetworkNode*> over_nodes,
-      std::function<void(CrossTrafficConfig*)> config_modifier);
-  CrossTrafficSource* CreateCrossTraffic(
-      std::vector<EmulatedNetworkNode*> over_nodes,
-      CrossTrafficConfig config);
-
   // Runs the provided function with a fixed interval. For real time tests,
   // |function| starts being called after |interval| from the call to Every().
   void Every(TimeDelta interval, std::function<void(TimeDelta)> function);
@@ -168,21 +163,16 @@
  private:
   TimeDelta TimeUntilTarget(TimeDelta target_time_offset);
 
-  NullReceiver null_receiver_;
   const std::unique_ptr<LogWriterFactoryInterface> log_writer_factory_;
   std::unique_ptr<TimeController> time_controller_;
   Clock* clock_;
 
   std::vector<std::unique_ptr<CallClient>> clients_;
   std::vector<std::unique_ptr<CallClientPair>> client_pairs_;
-  std::vector<std::unique_ptr<EmulatedNetworkNode>> network_nodes_;
-  std::vector<std::unique_ptr<CrossTrafficSource>> cross_traffic_sources_;
   std::vector<std::unique_ptr<VideoStreamPair>> video_streams_;
   std::vector<std::unique_ptr<AudioStreamPair>> audio_streams_;
-
   std::vector<std::unique_ptr<SimulatedTimeClient>> simulated_time_clients_;
-
-  std::vector<std::unique_ptr<ActionReceiver>> action_receivers_;
+  std::vector<std::unique_ptr<SimulationNode>> simulation_nodes_;
   std::vector<std::unique_ptr<StatesPrinter>> printers_;
 
   int64_t next_route_id_ = 40000;
@@ -190,6 +180,7 @@
   rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_;
 
   Timestamp start_time_ = Timestamp::PlusInfinity();
+  NetworkEmulationManagerImpl network_manager_;
   // Defined last so it's destroyed first.
   rtc::TaskQueue task_queue_;
 };
diff --git a/test/scenario/scenario_config.cc b/test/scenario/scenario_config.cc
index 82c82c2..3f8a70a 100644
--- a/test/scenario/scenario_config.cc
+++ b/test/scenario/scenario_config.cc
@@ -43,9 +43,5 @@
 AudioStreamConfig::Stream::Stream(const AudioStreamConfig::Stream&) = default;
 AudioStreamConfig::Stream::~Stream() = default;
 
-CrossTrafficConfig::CrossTrafficConfig() = default;
-CrossTrafficConfig::CrossTrafficConfig(const CrossTrafficConfig&) = default;
-CrossTrafficConfig::~CrossTrafficConfig() = default;
-
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/scenario/scenario_config.h b/test/scenario/scenario_config.h
index d530d30..18e34a7 100644
--- a/test/scenario/scenario_config.h
+++ b/test/scenario/scenario_config.h
@@ -237,26 +237,6 @@
   bool codel_active_queue_management = false;
   DataSize packet_overhead = DataSize::Zero();
 };
-
-struct CrossTrafficConfig {
-  CrossTrafficConfig();
-  CrossTrafficConfig(const CrossTrafficConfig&);
-  ~CrossTrafficConfig();
-  enum Mode { kRandomWalk, kPulsedPeaks } mode = kRandomWalk;
-  int random_seed = 1;
-  DataRate peak_rate = DataRate::kbps(100);
-  DataSize min_packet_size = DataSize::bytes(200);
-  TimeDelta min_packet_interval = TimeDelta::ms(1);
-  struct RandomWalk {
-    TimeDelta update_interval = TimeDelta::ms(200);
-    double variance = 0.6;
-    double bias = -0.1;
-  } random_walk;
-  struct PulsedPeaks {
-    TimeDelta send_duration = TimeDelta::ms(100);
-    TimeDelta hold_duration = TimeDelta::ms(2000);
-  } pulsed;
-};
 }  // namespace test
 }  // namespace webrtc
 
diff --git a/test/scenario/scenario_tests/bbr_performance.cc b/test/scenario/scenario_tests/bbr_performance.cc
index 8ab22f8..2e2efa2 100644
--- a/test/scenario/scenario_tests/bbr_performance.cc
+++ b/test/scenario/scenario_tests/bbr_performance.cc
@@ -191,11 +191,11 @@
       }
     });
   }
-  CrossTrafficConfig cross_config;
+  RandomWalkConfig cross_config;
   cross_config.peak_rate = conf_.scenario.cross_traffic;
   cross_config.random_seed = conf_.scenario.random_seed;
-  CrossTrafficSource* cross_traffic =
-      s.CreateCrossTraffic({send_net}, cross_config);
+  auto* cross_traffic = s.net()->CreateRandomWalkCrossTraffic(
+      s.net()->CreateTrafficRoute({send_net->node()}), cross_config);
 
   s.CreatePrinter("send.stats.txt", TimeDelta::ms(100),
                   {alice->StatsPrinter(), alice_video->send()->StatsPrinter(),
diff --git a/test/scenario/scenario_unittest.cc b/test/scenario/scenario_unittest.cc
index eafb4c8..eea8d59 100644
--- a/test/scenario/scenario_unittest.cc
+++ b/test/scenario/scenario_unittest.cc
@@ -40,8 +40,9 @@
   s.CreateAudioStream(route->forward(), audio_stream_config);
   s.CreateAudioStream(route->reverse(), audio_stream_config);
 
-  CrossTrafficConfig cross_traffic_config;
-  s.CreateCrossTraffic({alice_net}, cross_traffic_config);
+  RandomWalkConfig cross_traffic_config;
+  s.net()->CreateRandomWalkCrossTraffic(
+      s.net()->CreateTrafficRoute({alice_net}), cross_traffic_config);
 
   s.NetworkDelayedAction({alice_net, bob_net}, 100,
                          [&packet_received] { packet_received = true; });