Add cross trafic emulation api

Bug: webrtc:12344
Change-Id: I958dc4deda4af4576818600c31aecdf48285172f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/200981
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Andrey Logvin <landrey@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32989}
This commit is contained in:
Andrey Logvin
2021-01-14 09:50:32 +00:00
committed by Commit Bot
parent a7ccacc87f
commit f9ee0e08ec
24 changed files with 352 additions and 190 deletions

View File

@ -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",
]
}

View File

@ -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 <memory>
#include "rtc_base/task_utils/repeating_task.h"
#include "test/network/cross_traffic.h"
namespace webrtc {
std::unique_ptr<CrossTrafficGenerator> CreateRandomWalkCrossTraffic(
CrossTrafficRoute* traffic_route,
RandomWalkConfig config) {
return std::make_unique<test::RandomWalkCrossTraffic>(config, traffic_route);
}
std::unique_ptr<CrossTrafficGenerator> CreatePulsedPeaksCrossTraffic(
CrossTrafficRoute* traffic_route,
PulsedPeaksConfig config) {
return std::make_unique<test::PulsedPeaksCrossTraffic>(config, traffic_route);
}
std::unique_ptr<CrossTrafficGenerator> CreateFakeTcpCrossTraffic(
EmulatedRoute* send_route,
EmulatedRoute* ret_route,
FakeTcpConfig config) {
return std::make_unique<test::FakeTcpCrossTraffic>(config, send_route,
ret_route);
}
} // namespace webrtc

View File

@ -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 <memory>
#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<CrossTrafficGenerator> CreateRandomWalkCrossTraffic(
CrossTrafficRoute* traffic_route,
RandomWalkConfig config);
std::unique_ptr<CrossTrafficGenerator> CreatePulsedPeaksCrossTraffic(
CrossTrafficRoute* traffic_route,
PulsedPeaksConfig config);
std::unique_ptr<CrossTrafficGenerator> CreateFakeTcpCrossTraffic(
EmulatedRoute* send_route,
EmulatedRoute* ret_route,
FakeTcpConfig config);
} // namespace webrtc
#endif // API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_

View File

@ -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<void()> 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_

View File

@ -17,6 +17,7 @@
#include <vector>
#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<EmulatedNetworkNode*>& via_nodes) = 0;
// Starts generating cross traffic using given |generator|. Takes ownership
// over the generator.
virtual CrossTrafficGenerator* StartCrossTraffic(
std::unique_ptr<CrossTrafficGenerator> 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

View File

@ -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",

View File

@ -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",

View File

@ -10,6 +10,8 @@
#include <queue>
#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

View File

@ -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.

View File

@ -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 += [

View File

@ -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) {

View File

@ -15,41 +15,34 @@
#include <map>
#include <memory>
#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<int, int>::TrafficHandlerInterface {
: public TwoWayFakeTrafficRoute<int, int>::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<int, int> 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

View File

@ -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);

View File

@ -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<TcpMessageRouteImpl>(
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<EmulatedNetworkNode*>& 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<TrafficRoute> traffic_route =
std::make_unique<TrafficRoute>(clock_, via_nodes[0], endpoint);
TrafficRoute* out = traffic_route.get();
std::unique_ptr<CrossTrafficRoute> traffic_route =
std::make_unique<CrossTrafficRouteImpl>(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<RandomWalkCrossTraffic>(config, traffic_route);
RandomWalkCrossTraffic* out = traffic.get();
CrossTrafficGenerator* NetworkEmulationManagerImpl::StartCrossTraffic(
std::unique_ptr<CrossTrafficGenerator> 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<PulsedPeaksCrossTraffic>(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<EmulatedNetworkNode*> send_link,
std::vector<EmulatedNetworkNode*> ret_link,
FakeTcpConfig config) {
auto traffic = std::make_unique<FakeTcpCrossTraffic>(
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<TcpMessageRouteImpl>(
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<FakeTcpCrossTraffic>& 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);
});
}

View File

@ -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<EmulatedNetworkNode*>& via_nodes);
RandomWalkCrossTraffic* CreateRandomWalkCrossTraffic(
TrafficRoute* traffic_route,
RandomWalkConfig config);
PulsedPeaksCrossTraffic* CreatePulsedPeaksCrossTraffic(
TrafficRoute* traffic_route,
PulsedPeaksConfig config);
FakeTcpCrossTraffic* StartFakeTcpCrossTraffic(
std::vector<EmulatedNetworkNode*> send_link,
std::vector<EmulatedNetworkNode*> ret_link,
FakeTcpConfig config);
TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
EmulatedRoute* ret_route) override;
void StopCrossTraffic(FakeTcpCrossTraffic* traffic);
CrossTrafficRoute* CreateCrossTrafficRoute(
const std::vector<EmulatedNetworkNode*>& via_nodes) override;
CrossTrafficGenerator* StartCrossTraffic(
std::unique_ptr<CrossTrafficGenerator> generator) override;
void StopCrossTraffic(CrossTrafficGenerator* generator) override;
EmulatedNetworkManagerInterface* CreateEmulatedNetworkManagerInterface(
const std::vector<EmulatedEndpoint*>& endpoints) override;
@ -97,6 +88,9 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
EmulatedTURNServerConfig config) override;
private:
using CrossTrafficSource =
std::pair<std::unique_ptr<CrossTrafficGenerator>, RepeatingTaskHandle>;
absl::optional<rtc::IPAddress> GetNextIPv4Address();
const std::unique_ptr<TimeController> time_controller_;
Clock* const clock_;
@ -111,10 +105,8 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
std::vector<std::unique_ptr<EmulatedEndpoint>> endpoints_;
std::vector<std::unique_ptr<EmulatedNetworkNode>> network_nodes_;
std::vector<std::unique_ptr<EmulatedRoute>> routes_;
std::vector<std::unique_ptr<TrafficRoute>> traffic_routes_;
std::vector<std::unique_ptr<RandomWalkCrossTraffic>> random_cross_traffics_;
std::vector<std::unique_ptr<PulsedPeaksCrossTraffic>> pulsed_cross_traffics_;
std::list<std::unique_ptr<FakeTcpCrossTraffic>> tcp_cross_traffics_;
std::vector<std::unique_ptr<CrossTrafficRoute>> traffic_routes_;
std::vector<CrossTrafficSource> cross_traffics_;
std::list<std::unique_ptr<TcpMessageRouteImpl>> tcp_message_routes_;
std::vector<std::unique_ptr<EndpointsContainer>> endpoints_containers_;
std::vector<std::unique_ptr<EmulatedNetworkManager>> network_managers_;

View File

@ -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<NullReceiver>();
absl::optional<uint16_t> 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<void()> action) {
void CrossTrafficRouteImpl::NetworkDelayedAction(size_t packet_size,
std::function<void()> action) {
auto action_receiver = std::make_unique<ActionReceiver>(action, endpoint_);
absl::optional<uint16_t> 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(

View File

@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#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<void()> action);
void NetworkDelayedAction(size_t packet_size,
std::function<void()> 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);

View File

@ -77,8 +77,8 @@ SignalingRoute PeerScenario::ConnectSignaling(
PeerScenarioClient* callee,
std::vector<EmulatedNetworkNode*> send_link,
std::vector<EmulatedNetworkNode*> 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(

View File

@ -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<void(SessionDescriptionInterface* offer)> munge_offer,
std::function<void(SessionDescriptionInterface*)> modify_offer,
std::function<void(const SessionDescriptionInterface&)> 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),

View File

@ -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

View File

@ -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",

View File

@ -198,7 +198,7 @@ SimulationNode* Scenario::CreateMutableSimulationNode(
void Scenario::TriggerPacketBurst(std::vector<EmulatedNetworkNode*> 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<EmulatedNetworkNode*> over_nodes,
size_t packet_size,
std::function<void()> action) {
network_manager_.CreateTrafficRoute(over_nodes)
network_manager_.CreateCrossTrafficRoute(over_nodes)
->NetworkDelayedAction(packet_size, action);
}

View File

@ -11,6 +11,8 @@
#include <atomic>
#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; });

View File

@ -9,6 +9,8 @@
*/
#include <atomic>
#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;