diff --git a/test/scenario/network/network_emulation.cc b/test/scenario/network/network_emulation.cc index 4f706cfad3..fe977e56a3 100644 --- a/test/scenario/network/network_emulation.cc +++ b/test/scenario/network/network_emulation.cc @@ -28,48 +28,19 @@ EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from, data(data), arrival_time(arrival_time) {} -void EmulatedNetworkNode::CreateRoute( - rtc::IPAddress receiver_ip, - std::vector nodes, - EmulatedNetworkReceiverInterface* receiver) { - RTC_CHECK(!nodes.empty()); - for (size_t i = 0; i + 1 < nodes.size(); ++i) - nodes[i]->SetReceiver(receiver_ip, nodes[i + 1]); - nodes.back()->SetReceiver(receiver_ip, receiver); -} - -void EmulatedNetworkNode::ClearRoute(rtc::IPAddress receiver_ip, - std::vector nodes) { - for (EmulatedNetworkNode* node : nodes) - node->RemoveReceiver(receiver_ip); -} - -EmulatedNetworkNode::EmulatedNetworkNode( - Clock* clock, - rtc::TaskQueue* task_queue, - std::unique_ptr network_behavior) - : clock_(clock), - task_queue_(task_queue), - network_behavior_(std::move(network_behavior)) {} - -EmulatedNetworkNode::~EmulatedNetworkNode() = default; - -void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) { +void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) { struct Closure { void operator()() { - RTC_DCHECK_RUN_ON(node->task_queue_); - node->HandlePacketReceived(std::move(packet)); + RTC_DCHECK_RUN_ON(link->task_queue_); + link->HandlePacketReceived(std::move(packet)); } - EmulatedNetworkNode* node; + LinkEmulation* link; EmulatedIpPacket packet; }; task_queue_->PostTask(Closure{this, std::move(packet)}); } -void EmulatedNetworkNode::HandlePacketReceived(EmulatedIpPacket packet) { - if (routing_.find(packet.to.ipaddr()) == routing_.end()) { - return; - } +void LinkEmulation::HandlePacketReceived(EmulatedIpPacket packet) { uint64_t packet_id = next_packet_id_++; bool sent = network_behavior_->EnqueuePacket( PacketInFlightInfo(packet.size(), packet.arrival_time.us(), packet_id)); @@ -101,7 +72,7 @@ void EmulatedNetworkNode::HandlePacketReceived(EmulatedIpPacket packet) { }); } -void EmulatedNetworkNode::Process(Timestamp at_time) { +void LinkEmulation::Process(Timestamp at_time) { std::vector delivery_infos = network_behavior_->DequeueDeliverablePackets(at_time.us()); for (PacketDeliveryInfo& delivery_info : delivery_infos) { @@ -114,14 +85,12 @@ void EmulatedNetworkNode::Process(Timestamp at_time) { } RTC_CHECK(packet); RTC_DCHECK(!packet->removed); - auto receiver_it = routing_.find(packet->packet.to.ipaddr()); - RTC_CHECK(receiver_it != routing_.end()); packet->removed = true; if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) { packet->packet.arrival_time = Timestamp::us(delivery_info.receive_time_us); - receiver_it->second->OnPacketReceived(std::move(packet->packet)); + receiver_->OnPacketReceived(std::move(packet->packet)); } while (!packets_.empty() && packets_.front().removed) { packets_.pop_front(); @@ -129,7 +98,21 @@ void EmulatedNetworkNode::Process(Timestamp at_time) { } } -void EmulatedNetworkNode::SetReceiver( +NetworkRouterNode::NetworkRouterNode(rtc::TaskQueue* task_queue) + : task_queue_(task_queue) {} + +void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) { + RTC_DCHECK_RUN_ON(task_queue_); + auto receiver_it = routing_.find(packet.to.ipaddr()); + if (receiver_it == routing_.end()) { + return; + } + RTC_CHECK(receiver_it != routing_.end()); + + receiver_it->second->OnPacketReceived(std::move(packet)); +} + +void NetworkRouterNode::SetReceiver( rtc::IPAddress dest_ip, EmulatedNetworkReceiverInterface* receiver) { task_queue_->PostTask([=] { @@ -141,11 +124,40 @@ void EmulatedNetworkNode::SetReceiver( }); } -void EmulatedNetworkNode::RemoveReceiver(rtc::IPAddress dest_ip) { +void NetworkRouterNode::RemoveReceiver(rtc::IPAddress dest_ip) { RTC_DCHECK_RUN_ON(task_queue_); routing_.erase(dest_ip); } +EmulatedNetworkNode::EmulatedNetworkNode( + Clock* clock, + rtc::TaskQueue* task_queue, + std::unique_ptr network_behavior) + : router_(task_queue), + link_(clock, task_queue, std::move(network_behavior), &router_) {} + +void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) { + link_.OnPacketReceived(std::move(packet)); +} + +void EmulatedNetworkNode::CreateRoute( + rtc::IPAddress receiver_ip, + std::vector nodes, + EmulatedNetworkReceiverInterface* receiver) { + RTC_CHECK(!nodes.empty()); + for (size_t i = 0; i + 1 < nodes.size(); ++i) + nodes[i]->router()->SetReceiver(receiver_ip, nodes[i + 1]); + nodes.back()->router()->SetReceiver(receiver_ip, receiver); +} + +void EmulatedNetworkNode::ClearRoute(rtc::IPAddress receiver_ip, + std::vector nodes) { + for (EmulatedNetworkNode* node : nodes) + node->router()->RemoveReceiver(receiver_ip); +} + +EmulatedNetworkNode::~EmulatedNetworkNode() = default; + EmulatedEndpoint::EmulatedEndpoint(uint64_t id, const rtc::IPAddress& ip, bool is_enabled, diff --git a/test/scenario/network/network_emulation.h b/test/scenario/network/network_emulation.h index 674e39e10a..7505cbdccc 100644 --- a/test/scenario/network/network_emulation.h +++ b/test/scenario/network/network_emulation.h @@ -68,6 +68,52 @@ class EmulatedNetworkReceiverInterface { virtual void OnPacketReceived(EmulatedIpPacket packet) = 0; }; +class LinkEmulation : public EmulatedNetworkReceiverInterface { + public: + LinkEmulation(Clock* clock, + rtc::TaskQueue* task_queue, + std::unique_ptr network_behavior, + EmulatedNetworkReceiverInterface* receiver) + : clock_(clock), + task_queue_(task_queue), + network_behavior_(std::move(network_behavior)), + receiver_(receiver) {} + void OnPacketReceived(EmulatedIpPacket packet) override; + + private: + struct StoredPacket { + uint64_t id; + EmulatedIpPacket packet; + bool removed; + }; + void Process(Timestamp at_time) RTC_RUN_ON(task_queue_); + void HandlePacketReceived(EmulatedIpPacket packet) RTC_RUN_ON(task_queue_); + + Clock* const clock_; + rtc::TaskQueue* const task_queue_; + const std::unique_ptr network_behavior_ + RTC_GUARDED_BY(task_queue_); + EmulatedNetworkReceiverInterface* const receiver_; + RepeatingTaskHandle process_task_ RTC_GUARDED_BY(task_queue_); + std::deque packets_ RTC_GUARDED_BY(task_queue_); + uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1; +}; + +class NetworkRouterNode : public EmulatedNetworkReceiverInterface { + public: + explicit NetworkRouterNode(rtc::TaskQueue* task_queue); + + void OnPacketReceived(EmulatedIpPacket packet) override; + void SetReceiver(rtc::IPAddress dest_ip, + EmulatedNetworkReceiverInterface* receiver); + void RemoveReceiver(rtc::IPAddress dest_ip); + + private: + rtc::TaskQueue* const task_queue_; + std::map routing_ + RTC_GUARDED_BY(task_queue_); +}; + // 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 @@ -79,7 +125,7 @@ class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface { // |network_behavior|. // |task_queue| is used to process packets and to forward the packets when // they are ready. - explicit EmulatedNetworkNode( + EmulatedNetworkNode( Clock* clock, rtc::TaskQueue* task_queue, std::unique_ptr network_behavior); @@ -87,9 +133,9 @@ class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface { RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode); void OnPacketReceived(EmulatedIpPacket packet) override; - void SetReceiver(rtc::IPAddress dest_ip, - EmulatedNetworkReceiverInterface* receiver); - void RemoveReceiver(rtc::IPAddress dest_ip); + + LinkEmulation* link() { return &link_; } + NetworkRouterNode* router() { return &router_; } // Creates a route for the given receiver_ip over all the given nodes to the // given receiver. @@ -100,23 +146,8 @@ class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface { std::vector nodes); private: - void Process(Timestamp at_time) RTC_RUN_ON(task_queue_); - void HandlePacketReceived(EmulatedIpPacket packet) RTC_RUN_ON(task_queue_); - struct StoredPacket { - uint64_t id; - EmulatedIpPacket packet; - bool removed; - }; - Clock* const clock_; - rtc::TaskQueue* const task_queue_; - RepeatingTaskHandle process_task_; - std::map routing_ - RTC_GUARDED_BY(task_queue_); - const std::unique_ptr network_behavior_ - RTC_GUARDED_BY(task_queue_); - std::deque packets_ RTC_GUARDED_BY(task_queue_); - - uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1; + NetworkRouterNode router_; + LinkEmulation link_; }; // Represents single network interface on the device. diff --git a/test/scenario/network/network_emulation_manager.cc b/test/scenario/network/network_emulation_manager.cc index fdcb3e8c24..190a0a856d 100644 --- a/test/scenario/network/network_emulation_manager.cc +++ b/test/scenario/network/network_emulation_manager.cc @@ -112,10 +112,10 @@ EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute( from->SetSendNode(via_nodes[0]); EmulatedNetworkNode* cur_node = via_nodes[0]; for (size_t i = 1; i < via_nodes.size(); ++i) { - cur_node->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]); + cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]); cur_node = via_nodes[i]; } - cur_node->SetReceiver(to->GetPeerLocalAddress(), to); + cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to); std::unique_ptr route = absl::make_unique(from, std::move(via_nodes), to); @@ -129,11 +129,11 @@ void NetworkEmulationManagerImpl::ClearRoute(EmulatedRoute* route) { task_queue_.SendTask([route]() { // Remove receiver from intermediate nodes. for (auto* node : route->via_nodes) { - node->RemoveReceiver(route->to->GetPeerLocalAddress()); + node->router()->RemoveReceiver(route->to->GetPeerLocalAddress()); } // Detach endpoint from current send node. if (route->from->GetSendNode()) { - route->from->GetSendNode()->RemoveReceiver( + route->from->GetSendNode()->router()->RemoveReceiver( route->to->GetPeerLocalAddress()); route->from->SetSendNode(nullptr); } @@ -150,10 +150,11 @@ TrafficRoute* NetworkEmulationManagerImpl::CreateTrafficRoute( // Setup a route via specified nodes. EmulatedNetworkNode* cur_node = via_nodes[0]; for (size_t i = 1; i < via_nodes.size(); ++i) { - cur_node->SetReceiver(endpoint->GetPeerLocalAddress(), via_nodes[i]); + cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(), + via_nodes[i]); cur_node = via_nodes[i]; } - cur_node->SetReceiver(endpoint->GetPeerLocalAddress(), endpoint); + cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(), endpoint); std::unique_ptr traffic_route = absl::make_unique(clock_, via_nodes[0], endpoint);