Extract NetworkNode abstraction.
Extract NetworkNode abstraction and introduce cleaner structure for emulation based on abstract NetworkBehaviorInterface. Bug: webrtc:10138 Change-Id: I89cdae2f3792da34ce169f14592c53515c8ba3ac Reviewed-on: https://webrtc-review.googlesource.com/c/116181 Commit-Queue: Artem Titov <titovartem@webrtc.org> Reviewed-by: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26159}
This commit is contained in:
@ -14,8 +14,10 @@ rtc_source_set("emulated_network") {
|
||||
"network_emulation.h",
|
||||
]
|
||||
deps = [
|
||||
"../../../api:simulated_network_api",
|
||||
"../../../api/units:timestamp",
|
||||
"../../../rtc_base:rtc_base",
|
||||
"//third_party/abseil-cpp/absl/memory:memory",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
@ -12,7 +12,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
|
||||
const rtc::SocketAddress& to,
|
||||
@ -29,4 +33,98 @@ EmulatedIpPacket::~EmulatedIpPacket() = default;
|
||||
|
||||
EmulatedIpPacket::EmulatedIpPacket(EmulatedIpPacket&&) = default;
|
||||
|
||||
void EmulatedNetworkNode::CreateRoute(
|
||||
uint64_t receiver_id,
|
||||
std::vector<EmulatedNetworkNode*> nodes,
|
||||
EmulatedNetworkReceiverInterface* receiver) {
|
||||
RTC_CHECK(!nodes.empty());
|
||||
for (size_t i = 0; i + 1 < nodes.size(); ++i)
|
||||
nodes[i]->SetReceiver(receiver_id, nodes[i + 1]);
|
||||
nodes.back()->SetReceiver(receiver_id, receiver);
|
||||
}
|
||||
|
||||
void EmulatedNetworkNode::ClearRoute(uint64_t receiver_id,
|
||||
std::vector<EmulatedNetworkNode*> nodes) {
|
||||
for (EmulatedNetworkNode* node : nodes)
|
||||
node->RemoveReceiver(receiver_id);
|
||||
}
|
||||
|
||||
EmulatedNetworkNode::EmulatedNetworkNode(
|
||||
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
|
||||
size_t packet_overhead)
|
||||
: network_behavior_(std::move(network_behavior)),
|
||||
packet_overhead_(packet_overhead) {}
|
||||
|
||||
EmulatedNetworkNode::~EmulatedNetworkNode() = default;
|
||||
|
||||
void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
rtc::CritScope crit(&lock_);
|
||||
if (routing_.find(packet.dest_endpoint_id) == routing_.end())
|
||||
return;
|
||||
uint64_t packet_id = next_packet_id_++;
|
||||
bool sent = network_behavior_->EnqueuePacket(PacketInFlightInfo(
|
||||
packet.size() + packet_overhead_, packet.arrival_time.us(), packet_id));
|
||||
if (sent) {
|
||||
packets_.emplace_back(StoredPacket{packet_id, std::move(packet), false});
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedNetworkNode::Process(Timestamp at_time) {
|
||||
std::vector<PacketDeliveryInfo> delivery_infos;
|
||||
{
|
||||
rtc::CritScope crit(&lock_);
|
||||
absl::optional<int64_t> delivery_us =
|
||||
network_behavior_->NextDeliveryTimeUs();
|
||||
if (delivery_us && *delivery_us > at_time.us())
|
||||
return;
|
||||
|
||||
delivery_infos = network_behavior_->DequeueDeliverablePackets(at_time.us());
|
||||
}
|
||||
for (PacketDeliveryInfo& delivery_info : delivery_infos) {
|
||||
StoredPacket* packet = nullptr;
|
||||
EmulatedNetworkReceiverInterface* receiver = nullptr;
|
||||
{
|
||||
rtc::CritScope crit(&lock_);
|
||||
for (auto& stored_packet : packets_) {
|
||||
if (stored_packet.id == delivery_info.packet_id) {
|
||||
packet = &stored_packet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RTC_CHECK(packet);
|
||||
RTC_DCHECK(!packet->removed);
|
||||
receiver = routing_[packet->packet.dest_endpoint_id];
|
||||
packet->removed = true;
|
||||
}
|
||||
RTC_CHECK(receiver);
|
||||
// We don't want to keep the lock here. Otherwise we would get a deadlock if
|
||||
// the receiver tries to push a new packet.
|
||||
packet->packet.arrival_time = Timestamp::us(delivery_info.receive_time_us);
|
||||
receiver->OnPacketReceived(std::move(packet->packet));
|
||||
{
|
||||
rtc::CritScope crit(&lock_);
|
||||
while (!packets_.empty() && packets_.front().removed) {
|
||||
packets_.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedNetworkNode::SetReceiver(
|
||||
uint64_t dest_endpoint_id,
|
||||
EmulatedNetworkReceiverInterface* receiver) {
|
||||
rtc::CritScope crit(&lock_);
|
||||
RTC_CHECK(routing_
|
||||
.insert(std::pair<uint64_t, EmulatedNetworkReceiverInterface*>(
|
||||
dest_endpoint_id, receiver))
|
||||
.second)
|
||||
<< "Such routing already exists";
|
||||
}
|
||||
|
||||
void EmulatedNetworkNode::RemoveReceiver(uint64_t dest_endpoint_id) {
|
||||
rtc::CritScope crit(&lock_);
|
||||
routing_.erase(dest_endpoint_id);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
@ -12,12 +12,14 @@
|
||||
#define TEST_SCENARIO_NETWORK_NETWORK_EMULATION_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/test/simulated_network.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/asyncsocket.h"
|
||||
#include "rtc_base/copyonwritebuffer.h"
|
||||
@ -25,6 +27,7 @@
|
||||
#include "rtc_base/thread.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
struct EmulatedIpPacket {
|
||||
public:
|
||||
@ -59,6 +62,54 @@ class EmulatedNetworkReceiverInterface {
|
||||
virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
|
||||
};
|
||||
|
||||
// Represents node in the emulated network. Nodes can be connected with each
|
||||
// other to form different networks with different behavior. The behavior of
|
||||
// the node itself is determined by a concrete implementation of
|
||||
// NetworkBehaviorInterface that is provided on construction.
|
||||
class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
// Creates node based on |network_behavior|. The specified |packet_overhead|
|
||||
// is added to the size of each packet in the information provided to
|
||||
// |network_behavior|.
|
||||
EmulatedNetworkNode(
|
||||
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
|
||||
size_t packet_overhead = 0);
|
||||
~EmulatedNetworkNode() override;
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
|
||||
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
void Process(Timestamp at_time);
|
||||
void SetReceiver(uint64_t dest_endpoint_id,
|
||||
EmulatedNetworkReceiverInterface* receiver);
|
||||
void RemoveReceiver(uint64_t dest_endpoint_id);
|
||||
|
||||
// Creates a route for the given receiver_id over all the given nodes to the
|
||||
// given receiver.
|
||||
static void CreateRoute(uint64_t receiver_id,
|
||||
std::vector<EmulatedNetworkNode*> nodes,
|
||||
EmulatedNetworkReceiverInterface* receiver);
|
||||
static void ClearRoute(uint64_t receiver_id,
|
||||
std::vector<EmulatedNetworkNode*> nodes);
|
||||
|
||||
private:
|
||||
struct StoredPacket {
|
||||
uint64_t id;
|
||||
EmulatedIpPacket packet;
|
||||
bool removed;
|
||||
};
|
||||
|
||||
rtc::CriticalSection lock_;
|
||||
std::map<uint64_t, EmulatedNetworkReceiverInterface*> routing_
|
||||
RTC_GUARDED_BY(lock_);
|
||||
const std::unique_ptr<NetworkBehaviorInterface> network_behavior_
|
||||
RTC_GUARDED_BY(lock_);
|
||||
const size_t packet_overhead_ RTC_GUARDED_BY(lock_);
|
||||
std::deque<StoredPacket> packets_ RTC_GUARDED_BY(lock_);
|
||||
|
||||
uint64_t next_packet_id_ RTC_GUARDED_BY(lock_) = 1;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_SCENARIO_NETWORK_NETWORK_EMULATION_H_
|
||||
|
@ -36,91 +36,6 @@ void ActionReceiver::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
action_();
|
||||
}
|
||||
|
||||
NetworkNode::~NetworkNode() = default;
|
||||
|
||||
NetworkNode::NetworkNode(NetworkNodeConfig config,
|
||||
std::unique_ptr<NetworkBehaviorInterface> behavior)
|
||||
: packet_overhead_(config.packet_overhead.bytes()),
|
||||
behavior_(std::move(behavior)) {}
|
||||
|
||||
void NetworkNode::SetRoute(uint64_t receiver,
|
||||
EmulatedNetworkReceiverInterface* node) {
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
routing_[receiver] = node;
|
||||
}
|
||||
|
||||
void NetworkNode::ClearRoute(uint64_t receiver_id) {
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
auto it = routing_.find(receiver_id);
|
||||
routing_.erase(it);
|
||||
}
|
||||
|
||||
void NetworkNode::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
if (routing_.find(packet.dest_endpoint_id) == routing_.end())
|
||||
return;
|
||||
uint64_t packet_id = next_packet_id_++;
|
||||
if (behavior_->EnqueuePacket(
|
||||
PacketInFlightInfo(packet.data.size() + packet_overhead_,
|
||||
packet.arrival_time.us(), packet_id))) {
|
||||
packets_.emplace_back(StoredPacket{std::move(packet), packet_id, false});
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkNode::Process(Timestamp at_time) {
|
||||
std::vector<PacketDeliveryInfo> delivery_infos;
|
||||
{
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
absl::optional<int64_t> delivery_us = behavior_->NextDeliveryTimeUs();
|
||||
if (delivery_us && *delivery_us > at_time.us())
|
||||
return;
|
||||
|
||||
delivery_infos = behavior_->DequeueDeliverablePackets(at_time.us());
|
||||
}
|
||||
for (PacketDeliveryInfo& delivery_info : delivery_infos) {
|
||||
StoredPacket* packet = nullptr;
|
||||
EmulatedNetworkReceiverInterface* receiver = nullptr;
|
||||
{
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
for (StoredPacket& stored_packet : packets_) {
|
||||
if (stored_packet.id == delivery_info.packet_id) {
|
||||
packet = &stored_packet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RTC_CHECK(packet);
|
||||
RTC_DCHECK(!packet->removed);
|
||||
receiver = routing_[packet->packet.dest_endpoint_id];
|
||||
packet->removed = true;
|
||||
}
|
||||
// We don't want to keep the lock here. Otherwise we would get a deadlock if
|
||||
// the receiver tries to push a new packet.
|
||||
packet->packet.arrival_time = Timestamp::us(delivery_info.receive_time_us);
|
||||
receiver->OnPacketReceived(std::move(packet->packet));
|
||||
{
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
while (!packets_.empty() && packets_.front().removed) {
|
||||
packets_.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkNode::Route(uint64_t receiver_id,
|
||||
std::vector<NetworkNode*> nodes,
|
||||
EmulatedNetworkReceiverInterface* receiver) {
|
||||
RTC_CHECK(!nodes.empty());
|
||||
for (size_t i = 0; i + 1 < nodes.size(); ++i)
|
||||
nodes[i]->SetRoute(receiver_id, nodes[i + 1]);
|
||||
nodes.back()->SetRoute(receiver_id, receiver);
|
||||
}
|
||||
|
||||
void NetworkNode::ClearRoute(uint64_t receiver_id,
|
||||
std::vector<NetworkNode*> nodes) {
|
||||
for (NetworkNode* node : nodes)
|
||||
node->ClearRoute(receiver_id);
|
||||
}
|
||||
|
||||
std::unique_ptr<SimulationNode> SimulationNode::Create(
|
||||
NetworkNodeConfig config) {
|
||||
RTC_DCHECK(config.mode == NetworkNodeConfig::TrafficMode::kSimulation);
|
||||
@ -157,7 +72,8 @@ SimulationNode::SimulationNode(
|
||||
NetworkNodeConfig config,
|
||||
std::unique_ptr<NetworkBehaviorInterface> behavior,
|
||||
SimulatedNetwork* simulation)
|
||||
: NetworkNode(config, std::move(behavior)),
|
||||
: EmulatedNetworkNode(std::move(behavior),
|
||||
config.packet_overhead.bytes_or(0)),
|
||||
simulated_network_(simulation),
|
||||
config_(config) {}
|
||||
|
||||
@ -206,7 +122,7 @@ bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetworkNodeTransport::Connect(NetworkNode* send_node,
|
||||
void NetworkNodeTransport::Connect(EmulatedNetworkNode* send_node,
|
||||
uint64_t receiver_id,
|
||||
DataSize packet_overhead) {
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
|
@ -44,51 +44,9 @@ class ActionReceiver : public EmulatedNetworkReceiverInterface {
|
||||
std::function<void()> action_;
|
||||
};
|
||||
|
||||
// NetworkNode represents one link in a simulated network. It is created by a
|
||||
// scenario and can be used when setting up audio and video stream sessions.
|
||||
class NetworkNode : public EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
~NetworkNode() override;
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(NetworkNode);
|
||||
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
// Creates a route for the given receiver_id over all the given nodes to the
|
||||
// given receiver.
|
||||
static void Route(uint64_t receiver_id,
|
||||
std::vector<NetworkNode*> nodes,
|
||||
EmulatedNetworkReceiverInterface* receiver);
|
||||
|
||||
protected:
|
||||
friend class Scenario;
|
||||
friend class AudioStreamPair;
|
||||
friend class VideoStreamPair;
|
||||
|
||||
NetworkNode(NetworkNodeConfig config,
|
||||
std::unique_ptr<NetworkBehaviorInterface> simulation);
|
||||
static void ClearRoute(uint64_t receiver_id, std::vector<NetworkNode*> nodes);
|
||||
void Process(Timestamp at_time);
|
||||
|
||||
private:
|
||||
struct StoredPacket {
|
||||
EmulatedIpPacket packet;
|
||||
uint64_t id;
|
||||
bool removed;
|
||||
};
|
||||
void SetRoute(uint64_t receiver, EmulatedNetworkReceiverInterface* node);
|
||||
void ClearRoute(uint64_t receiver_id);
|
||||
rtc::CriticalSection crit_sect_;
|
||||
size_t packet_overhead_ RTC_GUARDED_BY(crit_sect_);
|
||||
const std::unique_ptr<NetworkBehaviorInterface> behavior_
|
||||
RTC_GUARDED_BY(crit_sect_);
|
||||
std::map<uint64_t, EmulatedNetworkReceiverInterface*> routing_
|
||||
RTC_GUARDED_BY(crit_sect_);
|
||||
std::deque<StoredPacket> packets_ RTC_GUARDED_BY(crit_sect_);
|
||||
|
||||
uint64_t next_packet_id_ RTC_GUARDED_BY(crit_sect_) = 1;
|
||||
};
|
||||
// SimulationNode is a NetworkNode that expose an interface for changing run
|
||||
// time behavior of the underlying simulation.
|
||||
class SimulationNode : public NetworkNode {
|
||||
// SimulationNode is a EmulatedNetworkNode that expose an interface for changing
|
||||
// run time behavior of the underlying simulation.
|
||||
class SimulationNode : public EmulatedNetworkNode {
|
||||
public:
|
||||
void UpdateConfig(std::function<void(NetworkNodeConfig*)> modifier);
|
||||
void PauseTransmissionUntil(Timestamp until);
|
||||
@ -101,6 +59,7 @@ class SimulationNode : public NetworkNode {
|
||||
std::unique_ptr<NetworkBehaviorInterface> behavior,
|
||||
SimulatedNetwork* simulation);
|
||||
static std::unique_ptr<SimulationNode> Create(NetworkNodeConfig config);
|
||||
|
||||
SimulatedNetwork* const simulated_network_;
|
||||
NetworkNodeConfig config_;
|
||||
};
|
||||
@ -115,7 +74,7 @@ class NetworkNodeTransport : public Transport {
|
||||
const PacketOptions& options) override;
|
||||
bool SendRtcp(const uint8_t* packet, size_t length) override;
|
||||
|
||||
void Connect(NetworkNode* send_node,
|
||||
void Connect(EmulatedNetworkNode* send_node,
|
||||
uint64_t receiver_id,
|
||||
DataSize packet_overhead);
|
||||
|
||||
@ -128,7 +87,7 @@ class NetworkNodeTransport : public Transport {
|
||||
rtc::CriticalSection crit_sect_;
|
||||
const Clock* const sender_clock_;
|
||||
Call* const sender_call_;
|
||||
NetworkNode* send_net_ RTC_GUARDED_BY(crit_sect_) = nullptr;
|
||||
EmulatedNetworkNode* send_net_ RTC_GUARDED_BY(crit_sect_) = nullptr;
|
||||
uint64_t receiver_id_ RTC_GUARDED_BY(crit_sect_) = 0;
|
||||
DataSize packet_overhead_ RTC_GUARDED_BY(crit_sect_) = DataSize::Zero();
|
||||
};
|
||||
|
@ -135,21 +135,23 @@ CallClient* Scenario::CreateClient(
|
||||
return CreateClient(name, config);
|
||||
}
|
||||
|
||||
CallClientPair* Scenario::CreateRoutes(CallClient* first,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
CallClient* second,
|
||||
std::vector<NetworkNode*> return_link) {
|
||||
CallClientPair* Scenario::CreateRoutes(
|
||||
CallClient* first,
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
CallClient* second,
|
||||
std::vector<EmulatedNetworkNode*> return_link) {
|
||||
return CreateRoutes(first, send_link,
|
||||
DataSize::bytes(PacketOverhead::kDefault), second,
|
||||
return_link, DataSize::bytes(PacketOverhead::kDefault));
|
||||
}
|
||||
|
||||
CallClientPair* Scenario::CreateRoutes(CallClient* first,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
DataSize first_overhead,
|
||||
CallClient* second,
|
||||
std::vector<NetworkNode*> return_link,
|
||||
DataSize second_overhead) {
|
||||
CallClientPair* Scenario::CreateRoutes(
|
||||
CallClient* first,
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
DataSize first_overhead,
|
||||
CallClient* second,
|
||||
std::vector<EmulatedNetworkNode*> return_link,
|
||||
DataSize second_overhead) {
|
||||
CallClientPair* client_pair = new CallClientPair(first, second);
|
||||
ChangeRoute(client_pair->forward(), send_link, first_overhead);
|
||||
ChangeRoute(client_pair->reverse(), return_link, second_overhead);
|
||||
@ -158,16 +160,16 @@ CallClientPair* Scenario::CreateRoutes(CallClient* first,
|
||||
}
|
||||
|
||||
void Scenario::ChangeRoute(std::pair<CallClient*, CallClient*> clients,
|
||||
std::vector<NetworkNode*> over_nodes) {
|
||||
std::vector<EmulatedNetworkNode*> over_nodes) {
|
||||
ChangeRoute(clients, over_nodes, DataSize::bytes(PacketOverhead::kDefault));
|
||||
}
|
||||
|
||||
void Scenario::ChangeRoute(std::pair<CallClient*, CallClient*> clients,
|
||||
std::vector<NetworkNode*> over_nodes,
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
DataSize overhead) {
|
||||
uint64_t route_id = next_route_id_++;
|
||||
clients.second->route_overhead_.insert({route_id, overhead});
|
||||
NetworkNode::Route(route_id, over_nodes, clients.second);
|
||||
EmulatedNetworkNode::CreateRoute(route_id, over_nodes, clients.second);
|
||||
clients.first->transport_.Connect(over_nodes.front(), route_id, overhead);
|
||||
}
|
||||
|
||||
@ -175,8 +177,8 @@ SimulatedTimeClient* Scenario::CreateSimulatedTimeClient(
|
||||
std::string name,
|
||||
SimulatedTimeClientConfig config,
|
||||
std::vector<PacketStreamConfig> stream_configs,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
std::vector<NetworkNode*> return_link) {
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
std::vector<EmulatedNetworkNode*> return_link) {
|
||||
uint64_t send_id = next_route_id_++;
|
||||
uint64_t return_id = next_route_id_++;
|
||||
SimulatedTimeClient* client = new SimulatedTimeClient(
|
||||
@ -213,41 +215,44 @@ SimulationNode* Scenario::CreateSimulationNode(NetworkNodeConfig config) {
|
||||
return sim_node;
|
||||
}
|
||||
|
||||
NetworkNode* Scenario::CreateNetworkNode(
|
||||
EmulatedNetworkNode* Scenario::CreateNetworkNode(
|
||||
NetworkNodeConfig config,
|
||||
std::unique_ptr<NetworkBehaviorInterface> behavior) {
|
||||
RTC_DCHECK(config.mode == NetworkNodeConfig::TrafficMode::kCustom);
|
||||
network_nodes_.emplace_back(new NetworkNode(config, std::move(behavior)));
|
||||
NetworkNode* network_node = network_nodes_.back().get();
|
||||
network_nodes_.emplace_back(new EmulatedNetworkNode(
|
||||
std::move(behavior), config.packet_overhead.bytes_or(0)));
|
||||
EmulatedNetworkNode* network_node = network_nodes_.back().get();
|
||||
Every(config.update_frequency,
|
||||
[this, network_node] { network_node->Process(Now()); });
|
||||
return network_node;
|
||||
}
|
||||
|
||||
void Scenario::TriggerPacketBurst(std::vector<NetworkNode*> over_nodes,
|
||||
void Scenario::TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
size_t num_packets,
|
||||
size_t packet_size) {
|
||||
uint64_t route_id = next_route_id_++;
|
||||
NetworkNode::Route(route_id, over_nodes, &null_receiver_);
|
||||
EmulatedNetworkNode::CreateRoute(route_id, over_nodes, &null_receiver_);
|
||||
for (size_t i = 0; i < num_packets; ++i)
|
||||
over_nodes[0]->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress(), /*to*/
|
||||
route_id, rtc::CopyOnWriteBuffer(packet_size), Now()));
|
||||
}
|
||||
|
||||
void Scenario::NetworkDelayedAction(std::vector<NetworkNode*> over_nodes,
|
||||
size_t packet_size,
|
||||
std::function<void()> action) {
|
||||
void Scenario::NetworkDelayedAction(
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
size_t packet_size,
|
||||
std::function<void()> action) {
|
||||
uint64_t route_id = next_route_id_++;
|
||||
action_receivers_.emplace_back(new ActionReceiver(action));
|
||||
NetworkNode::Route(route_id, over_nodes, action_receivers_.back().get());
|
||||
EmulatedNetworkNode::CreateRoute(route_id, over_nodes,
|
||||
action_receivers_.back().get());
|
||||
over_nodes[0]->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/, route_id,
|
||||
rtc::CopyOnWriteBuffer(packet_size), Now()));
|
||||
}
|
||||
|
||||
CrossTrafficSource* Scenario::CreateCrossTraffic(
|
||||
std::vector<NetworkNode*> over_nodes,
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
std::function<void(CrossTrafficConfig*)> config_modifier) {
|
||||
CrossTrafficConfig cross_config;
|
||||
config_modifier(&cross_config);
|
||||
@ -255,13 +260,13 @@ CrossTrafficSource* Scenario::CreateCrossTraffic(
|
||||
}
|
||||
|
||||
CrossTrafficSource* Scenario::CreateCrossTraffic(
|
||||
std::vector<NetworkNode*> over_nodes,
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
CrossTrafficConfig config) {
|
||||
uint64_t route_id = next_route_id_++;
|
||||
cross_traffic_sources_.emplace_back(
|
||||
new CrossTrafficSource(over_nodes.front(), route_id, config));
|
||||
CrossTrafficSource* node = cross_traffic_sources_.back().get();
|
||||
NetworkNode::Route(route_id, over_nodes, &null_receiver_);
|
||||
EmulatedNetworkNode::CreateRoute(route_id, over_nodes, &null_receiver_);
|
||||
Every(config.min_packet_interval,
|
||||
[this, node](TimeDelta delta) { node->Process(Now(), delta); });
|
||||
return node;
|
||||
|
@ -69,7 +69,7 @@ class Scenario {
|
||||
SimulationNode* CreateSimulationNode(NetworkNodeConfig config);
|
||||
SimulationNode* CreateSimulationNode(
|
||||
std::function<void(NetworkNodeConfig*)> config_modifier);
|
||||
NetworkNode* CreateNetworkNode(
|
||||
EmulatedNetworkNode* CreateNetworkNode(
|
||||
NetworkNodeConfig config,
|
||||
std::unique_ptr<NetworkBehaviorInterface> behavior);
|
||||
|
||||
@ -79,30 +79,30 @@ class Scenario {
|
||||
std::function<void(CallClientConfig*)> config_modifier);
|
||||
|
||||
CallClientPair* CreateRoutes(CallClient* first,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
CallClient* second,
|
||||
std::vector<NetworkNode*> return_link);
|
||||
std::vector<EmulatedNetworkNode*> return_link);
|
||||
|
||||
CallClientPair* CreateRoutes(CallClient* first,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
DataSize first_overhead,
|
||||
CallClient* second,
|
||||
std::vector<NetworkNode*> return_link,
|
||||
std::vector<EmulatedNetworkNode*> return_link,
|
||||
DataSize second_overhead);
|
||||
|
||||
void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
|
||||
std::vector<NetworkNode*> over_nodes);
|
||||
std::vector<EmulatedNetworkNode*> over_nodes);
|
||||
|
||||
void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
|
||||
std::vector<NetworkNode*> over_nodes,
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
DataSize overhead);
|
||||
|
||||
SimulatedTimeClient* CreateSimulatedTimeClient(
|
||||
std::string name,
|
||||
SimulatedTimeClientConfig config,
|
||||
std::vector<PacketStreamConfig> stream_configs,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
std::vector<NetworkNode*> return_link);
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
std::vector<EmulatedNetworkNode*> return_link);
|
||||
|
||||
VideoStreamPair* CreateVideoStream(
|
||||
std::pair<CallClient*, CallClient*> clients,
|
||||
@ -119,10 +119,11 @@ class Scenario {
|
||||
AudioStreamConfig config);
|
||||
|
||||
CrossTrafficSource* CreateCrossTraffic(
|
||||
std::vector<NetworkNode*> over_nodes,
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
std::function<void(CrossTrafficConfig*)> config_modifier);
|
||||
CrossTrafficSource* CreateCrossTraffic(std::vector<NetworkNode*> over_nodes,
|
||||
CrossTrafficConfig config);
|
||||
CrossTrafficSource* CreateCrossTraffic(
|
||||
std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
CrossTrafficConfig config);
|
||||
|
||||
// Runs the provided function with a fixed interval.
|
||||
RepeatedActivity* Every(TimeDelta interval,
|
||||
@ -133,7 +134,7 @@ class Scenario {
|
||||
void At(TimeDelta offset, std::function<void()> function);
|
||||
|
||||
// Sends a packet over the nodes and runs |action| when it has been delivered.
|
||||
void NetworkDelayedAction(std::vector<NetworkNode*> over_nodes,
|
||||
void NetworkDelayedAction(std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
size_t packet_size,
|
||||
std::function<void()> action);
|
||||
|
||||
@ -148,7 +149,7 @@ class Scenario {
|
||||
void Stop();
|
||||
|
||||
// Triggers sending of dummy packets over the given nodes.
|
||||
void TriggerPacketBurst(std::vector<NetworkNode*> over_nodes,
|
||||
void TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes,
|
||||
size_t num_packets,
|
||||
size_t packet_size);
|
||||
|
||||
@ -180,7 +181,7 @@ class Scenario {
|
||||
|
||||
std::vector<std::unique_ptr<CallClient>> clients_;
|
||||
std::vector<std::unique_ptr<CallClientPair>> client_pairs_;
|
||||
std::vector<std::unique_ptr<NetworkNode>> network_nodes_;
|
||||
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_;
|
||||
|
@ -111,7 +111,7 @@ rtc::CopyOnWriteBuffer FeedbackToBuffer(
|
||||
sizeof(RawFeedbackReportPacket));
|
||||
}
|
||||
|
||||
SimulatedSender::SimulatedSender(NetworkNode* send_node,
|
||||
SimulatedSender::SimulatedSender(EmulatedNetworkNode* send_node,
|
||||
uint64_t send_receiver_id)
|
||||
: send_node_(send_node), send_receiver_id_(send_receiver_id) {}
|
||||
|
||||
@ -204,7 +204,7 @@ void SimulatedSender::Update(NetworkControlUpdate update) {
|
||||
|
||||
SimulatedFeedback::SimulatedFeedback(SimulatedTimeClientConfig config,
|
||||
uint64_t return_receiver_id,
|
||||
NetworkNode* return_node)
|
||||
EmulatedNetworkNode* return_node)
|
||||
: config_(config),
|
||||
return_receiver_id_(return_receiver_id),
|
||||
return_node_(return_node) {}
|
||||
@ -248,8 +248,8 @@ SimulatedTimeClient::SimulatedTimeClient(
|
||||
std::string log_filename,
|
||||
SimulatedTimeClientConfig config,
|
||||
std::vector<PacketStreamConfig> stream_configs,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
std::vector<NetworkNode*> return_link,
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
std::vector<EmulatedNetworkNode*> return_link,
|
||||
uint64_t send_receiver_id,
|
||||
uint64_t return_receiver_id,
|
||||
Timestamp at_time)
|
||||
@ -269,8 +269,8 @@ SimulatedTimeClient::SimulatedTimeClient(
|
||||
congestion_controller_ = network_controller_factory_.Create(initial_config);
|
||||
for (auto& stream_config : stream_configs)
|
||||
packet_streams_.emplace_back(new PacketStream(stream_config));
|
||||
NetworkNode::Route(send_receiver_id, send_link, &feedback_);
|
||||
NetworkNode::Route(return_receiver_id, return_link, this);
|
||||
EmulatedNetworkNode::CreateRoute(send_receiver_id, send_link, &feedback_);
|
||||
EmulatedNetworkNode::CreateRoute(return_receiver_id, return_link, this);
|
||||
|
||||
CongestionProcess(at_time);
|
||||
network_controller_factory_.LogCongestionControllerStats(at_time);
|
||||
|
@ -51,7 +51,7 @@ class SimulatedFeedback : EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
SimulatedFeedback(SimulatedTimeClientConfig config,
|
||||
uint64_t return_receiver_id,
|
||||
NetworkNode* return_node);
|
||||
EmulatedNetworkNode* return_node);
|
||||
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
|
||||
@ -59,7 +59,7 @@ class SimulatedFeedback : EmulatedNetworkReceiverInterface {
|
||||
friend class SimulatedTimeClient;
|
||||
const SimulatedTimeClientConfig config_;
|
||||
const uint64_t return_receiver_id_;
|
||||
NetworkNode* return_node_;
|
||||
EmulatedNetworkNode* return_node_;
|
||||
Timestamp last_feedback_time_ = Timestamp::MinusInfinity();
|
||||
int32_t next_feedback_seq_num_ = 1;
|
||||
std::map<int64_t, Timestamp> receive_times_;
|
||||
@ -88,7 +88,7 @@ class SimulatedSender {
|
||||
int64_t size;
|
||||
};
|
||||
|
||||
SimulatedSender(NetworkNode* send_node, uint64_t send_receiver_id);
|
||||
SimulatedSender(EmulatedNetworkNode* send_node, uint64_t send_receiver_id);
|
||||
SimulatedSender(const SimulatedSender&) = delete;
|
||||
~SimulatedSender();
|
||||
TransportPacketsFeedback PullFeedbackReport(SimpleFeedbackReportPacket report,
|
||||
@ -98,7 +98,7 @@ class SimulatedSender {
|
||||
|
||||
private:
|
||||
friend class SimulatedTimeClient;
|
||||
NetworkNode* send_node_;
|
||||
EmulatedNetworkNode* send_node_;
|
||||
uint64_t send_receiver_id_;
|
||||
PacerConfig pacer_config_;
|
||||
DataSize max_in_flight_ = DataSize::Infinity();
|
||||
@ -123,8 +123,8 @@ class SimulatedTimeClient : EmulatedNetworkReceiverInterface {
|
||||
SimulatedTimeClient(std::string log_filename,
|
||||
SimulatedTimeClientConfig config,
|
||||
std::vector<PacketStreamConfig> stream_configs,
|
||||
std::vector<NetworkNode*> send_link,
|
||||
std::vector<NetworkNode*> return_link,
|
||||
std::vector<EmulatedNetworkNode*> send_link,
|
||||
std::vector<EmulatedNetworkNode*> return_link,
|
||||
uint64_t send_receiver_id,
|
||||
uint64_t return_receiver_id,
|
||||
Timestamp at_time);
|
||||
@ -146,8 +146,8 @@ class SimulatedTimeClient : EmulatedNetworkReceiverInterface {
|
||||
friend class Scenario;
|
||||
LoggingNetworkControllerFactory network_controller_factory_;
|
||||
std::unique_ptr<NetworkControllerInterface> congestion_controller_;
|
||||
std::vector<NetworkNode*> send_link_;
|
||||
std::vector<NetworkNode*> return_link_;
|
||||
std::vector<EmulatedNetworkNode*> send_link_;
|
||||
std::vector<EmulatedNetworkNode*> return_link_;
|
||||
SimulatedSender sender_;
|
||||
SimulatedFeedback feedback_;
|
||||
TargetRateConstraints current_contraints_;
|
||||
|
Reference in New Issue
Block a user