blob: b13c6a9b3f1a7750595c8481add2f3c071d26f99 [file] [log] [blame]
Artem Titov40f51152019-01-04 15:45:01 +01001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Artem Titov386802e2019-07-05 10:48:17 +020011#include "test/network/network_emulation.h"
Artem Titov40f51152019-01-04 15:45:01 +010012
Artem Titov386802e2019-07-05 10:48:17 +020013#include <algorithm>
Artem Titov0774bd92019-01-30 15:26:05 +010014#include <limits>
Artem Titov40f51152019-01-04 15:45:01 +010015#include <memory>
16
Artem Titov806299e2019-04-12 12:17:19 +020017#include "api/units/data_size.h"
Artem Titov0774bd92019-01-30 15:26:05 +010018#include "rtc_base/bind.h"
Artem Titov37d18482019-01-08 15:41:45 +010019#include "rtc_base/logging.h"
20
Artem Titov40f51152019-01-04 15:45:01 +010021namespace webrtc {
22
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020023void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +020024 task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
25 RTC_DCHECK_RUN_ON(task_queue_);
Sebastian Jansson4124dab2019-04-01 14:33:53 +020026
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +020027 uint64_t packet_id = next_packet_id_++;
Niels Möller7536bc52019-10-04 13:54:39 +020028 bool sent = network_behavior_->EnqueuePacket(PacketInFlightInfo(
29 packet.ip_packet_size(), packet.arrival_time.us(), packet_id));
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +020030 if (sent) {
31 packets_.emplace_back(StoredPacket{packet_id, std::move(packet), false});
32 }
33 if (process_task_.Running())
34 return;
35 absl::optional<int64_t> next_time_us =
36 network_behavior_->NextDeliveryTimeUs();
37 if (!next_time_us)
38 return;
39 Timestamp current_time = clock_->CurrentTime();
40 process_task_ = RepeatingTaskHandle::DelayedStart(
41 task_queue_->Get(),
42 std::max(TimeDelta::Zero(),
43 Timestamp::us(*next_time_us) - current_time),
44 [this]() {
45 RTC_DCHECK_RUN_ON(task_queue_);
46 Timestamp current_time = clock_->CurrentTime();
47 Process(current_time);
48 absl::optional<int64_t> next_time_us =
49 network_behavior_->NextDeliveryTimeUs();
50 if (!next_time_us) {
51 process_task_.Stop();
52 return TimeDelta::Zero(); // This is ignored.
53 }
54 RTC_DCHECK_GE(*next_time_us, current_time.us());
55 return Timestamp::us(*next_time_us) - current_time;
56 });
57 });
Artem Titov37d18482019-01-08 15:41:45 +010058}
59
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020060void LinkEmulation::Process(Timestamp at_time) {
Sebastian Jansson4124dab2019-04-01 14:33:53 +020061 std::vector<PacketDeliveryInfo> delivery_infos =
62 network_behavior_->DequeueDeliverablePackets(at_time.us());
Artem Titov37d18482019-01-08 15:41:45 +010063 for (PacketDeliveryInfo& delivery_info : delivery_infos) {
64 StoredPacket* packet = nullptr;
Sebastian Jansson4124dab2019-04-01 14:33:53 +020065 for (auto& stored_packet : packets_) {
66 if (stored_packet.id == delivery_info.packet_id) {
67 packet = &stored_packet;
68 break;
Artem Titov37d18482019-01-08 15:41:45 +010069 }
Artem Titov37d18482019-01-08 15:41:45 +010070 }
Sebastian Jansson4124dab2019-04-01 14:33:53 +020071 RTC_CHECK(packet);
72 RTC_DCHECK(!packet->removed);
Sebastian Jansson4124dab2019-04-01 14:33:53 +020073 packet->removed = true;
74
Johannes Krona8f9e252019-01-24 15:38:23 +010075 if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) {
76 packet->packet.arrival_time =
77 Timestamp::us(delivery_info.receive_time_us);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020078 receiver_->OnPacketReceived(std::move(packet->packet));
Johannes Krona8f9e252019-01-24 15:38:23 +010079 }
Sebastian Jansson4124dab2019-04-01 14:33:53 +020080 while (!packets_.empty() && packets_.front().removed) {
81 packets_.pop_front();
Artem Titov37d18482019-01-08 15:41:45 +010082 }
83 }
84}
85
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020086NetworkRouterNode::NetworkRouterNode(rtc::TaskQueue* task_queue)
87 : task_queue_(task_queue) {}
88
89void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) {
90 RTC_DCHECK_RUN_ON(task_queue_);
Sebastian Jansson71c6b562019-08-14 11:31:02 +020091 if (watcher_) {
92 watcher_(packet);
93 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +020094 auto receiver_it = routing_.find(packet.to.ipaddr());
95 if (receiver_it == routing_.end()) {
96 return;
97 }
98 RTC_CHECK(receiver_it != routing_.end());
99
100 receiver_it->second->OnPacketReceived(std::move(packet));
101}
102
103void NetworkRouterNode::SetReceiver(
Yves Gerey2257c082020-01-03 12:37:56 +0100104 const rtc::IPAddress& dest_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100105 EmulatedNetworkReceiverInterface* receiver) {
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200106 task_queue_->PostTask([=] {
107 RTC_DCHECK_RUN_ON(task_queue_);
108 EmulatedNetworkReceiverInterface* cur_receiver = routing_[dest_ip];
109 RTC_CHECK(cur_receiver == nullptr || cur_receiver == receiver)
110 << "Routing for dest_ip=" << dest_ip.ToString() << " already exists";
111 routing_[dest_ip] = receiver;
112 });
Artem Titov37d18482019-01-08 15:41:45 +0100113}
114
Yves Gerey2257c082020-01-03 12:37:56 +0100115void NetworkRouterNode::RemoveReceiver(const rtc::IPAddress& dest_ip) {
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200116 RTC_DCHECK_RUN_ON(task_queue_);
Artem Titov4cd433e2019-04-01 11:01:16 +0200117 routing_.erase(dest_ip);
Artem Titov37d18482019-01-08 15:41:45 +0100118}
119
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200120void NetworkRouterNode::SetWatcher(
121 std::function<void(const EmulatedIpPacket&)> watcher) {
122 task_queue_->PostTask([=] {
123 RTC_DCHECK_RUN_ON(task_queue_);
124 watcher_ = watcher;
125 });
126}
127
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200128EmulatedNetworkNode::EmulatedNetworkNode(
129 Clock* clock,
130 rtc::TaskQueue* task_queue,
131 std::unique_ptr<NetworkBehaviorInterface> network_behavior)
132 : router_(task_queue),
133 link_(clock, task_queue, std::move(network_behavior), &router_) {}
134
135void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) {
136 link_.OnPacketReceived(std::move(packet));
137}
138
139void EmulatedNetworkNode::CreateRoute(
Yves Gerey2257c082020-01-03 12:37:56 +0100140 const rtc::IPAddress& receiver_ip,
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200141 std::vector<EmulatedNetworkNode*> nodes,
142 EmulatedNetworkReceiverInterface* receiver) {
143 RTC_CHECK(!nodes.empty());
144 for (size_t i = 0; i + 1 < nodes.size(); ++i)
145 nodes[i]->router()->SetReceiver(receiver_ip, nodes[i + 1]);
146 nodes.back()->router()->SetReceiver(receiver_ip, receiver);
147}
148
Yves Gerey2257c082020-01-03 12:37:56 +0100149void EmulatedNetworkNode::ClearRoute(const rtc::IPAddress& receiver_ip,
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200150 std::vector<EmulatedNetworkNode*> nodes) {
151 for (EmulatedNetworkNode* node : nodes)
152 node->router()->RemoveReceiver(receiver_ip);
153}
154
155EmulatedNetworkNode::~EmulatedNetworkNode() = default;
156
Sebastian Janssoncec24332019-12-04 14:26:50 +0100157EmulatedEndpointImpl::EmulatedEndpointImpl(uint64_t id,
158 const rtc::IPAddress& ip,
159 bool is_enabled,
160 rtc::TaskQueue* task_queue,
161 Clock* clock)
Artem Titov0774bd92019-01-30 15:26:05 +0100162 : id_(id),
163 peer_local_addr_(ip),
Artem Titove5cc85b2019-03-28 12:11:09 +0100164 is_enabled_(is_enabled),
Artem Titov0774bd92019-01-30 15:26:05 +0100165 clock_(clock),
Artem Titovff393122019-04-05 11:19:52 +0200166 task_queue_(task_queue),
167 router_(task_queue_),
Artem Titov4cd433e2019-04-01 11:01:16 +0200168 next_port_(kFirstEphemeralPort) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100169 constexpr int kIPv4NetworkPrefixLength = 24;
170 constexpr int kIPv6NetworkPrefixLength = 64;
171
172 int prefix_length = 0;
173 if (ip.family() == AF_INET) {
174 prefix_length = kIPv4NetworkPrefixLength;
175 } else if (ip.family() == AF_INET6) {
176 prefix_length = kIPv6NetworkPrefixLength;
177 }
178 rtc::IPAddress prefix = TruncateIP(ip, prefix_length);
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200179 network_ = std::make_unique<rtc::Network>(
Artem Titove5cc85b2019-03-28 12:11:09 +0100180 ip.ToString(), "Endpoint id=" + std::to_string(id_), prefix,
181 prefix_length, rtc::AdapterType::ADAPTER_TYPE_UNKNOWN);
182 network_->AddIP(ip);
183
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200184 enabled_state_checker_.Detach();
Artem Titove5cc85b2019-03-28 12:11:09 +0100185}
Sebastian Janssoncec24332019-12-04 14:26:50 +0100186EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
Artem Titov0774bd92019-01-30 15:26:05 +0100187
Sebastian Janssoncec24332019-12-04 14:26:50 +0100188uint64_t EmulatedEndpointImpl::GetId() const {
Artem Titov0774bd92019-01-30 15:26:05 +0100189 return id_;
190}
191
Sebastian Janssoncec24332019-12-04 14:26:50 +0100192void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
193 const rtc::SocketAddress& to,
194 rtc::CopyOnWriteBuffer packet_data) {
Artem Titov0774bd92019-01-30 15:26:05 +0100195 RTC_CHECK(from.ipaddr() == peer_local_addr_);
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200196 EmulatedIpPacket packet(from, to, std::move(packet_data),
197 clock_->CurrentTime());
198 task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
199 RTC_DCHECK_RUN_ON(task_queue_);
200 Timestamp current_time = clock_->CurrentTime();
201 if (stats_.first_packet_sent_time.IsInfinite()) {
202 stats_.first_packet_sent_time = current_time;
Niels Möller7536bc52019-10-04 13:54:39 +0200203 stats_.first_sent_packet_size = DataSize::bytes(packet.ip_packet_size());
Artem Titov806299e2019-04-12 12:17:19 +0200204 }
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200205 stats_.last_packet_sent_time = current_time;
206 stats_.packets_sent++;
Niels Möller7536bc52019-10-04 13:54:39 +0200207 stats_.bytes_sent += DataSize::bytes(packet.ip_packet_size());
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200208
209 router_.OnPacketReceived(std::move(packet));
210 });
Artem Titov0774bd92019-01-30 15:26:05 +0100211}
212
Sebastian Janssoncec24332019-12-04 14:26:50 +0100213absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver(
Artem Titov0774bd92019-01-30 15:26:05 +0100214 uint16_t desired_port,
215 EmulatedNetworkReceiverInterface* receiver) {
216 rtc::CritScope crit(&receiver_lock_);
217 uint16_t port = desired_port;
218 if (port == 0) {
219 // Because client can specify its own port, next_port_ can be already in
220 // use, so we need to find next available port.
221 int ports_pool_size =
222 std::numeric_limits<uint16_t>::max() - kFirstEphemeralPort + 1;
223 for (int i = 0; i < ports_pool_size; ++i) {
224 uint16_t next_port = NextPort();
225 if (port_to_receiver_.find(next_port) == port_to_receiver_.end()) {
226 port = next_port;
227 break;
228 }
229 }
230 }
231 RTC_CHECK(port != 0) << "Can't find free port for receiver in endpoint "
232 << id_;
233 bool result = port_to_receiver_.insert({port, receiver}).second;
234 if (!result) {
235 RTC_LOG(INFO) << "Can't bind receiver to used port " << desired_port
236 << " in endpoint " << id_;
237 return absl::nullopt;
238 }
239 RTC_LOG(INFO) << "New receiver is binded to endpoint " << id_ << " on port "
240 << port;
241 return port;
242}
243
Sebastian Janssoncec24332019-12-04 14:26:50 +0100244uint16_t EmulatedEndpointImpl::NextPort() {
Artem Titov0774bd92019-01-30 15:26:05 +0100245 uint16_t out = next_port_;
246 if (next_port_ == std::numeric_limits<uint16_t>::max()) {
247 next_port_ = kFirstEphemeralPort;
248 } else {
249 next_port_++;
250 }
251 return out;
252}
253
Sebastian Janssoncec24332019-12-04 14:26:50 +0100254void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) {
Artem Titov0774bd92019-01-30 15:26:05 +0100255 rtc::CritScope crit(&receiver_lock_);
256 port_to_receiver_.erase(port);
257}
258
Sebastian Janssoncec24332019-12-04 14:26:50 +0100259rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const {
Artem Titov0774bd92019-01-30 15:26:05 +0100260 return peer_local_addr_;
261}
262
Sebastian Janssoncec24332019-12-04 14:26:50 +0100263void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
Artem Titov806299e2019-04-12 12:17:19 +0200264 RTC_DCHECK_RUN_ON(task_queue_);
Artem Titov4cd433e2019-04-01 11:01:16 +0200265 RTC_CHECK(packet.to.ipaddr() == peer_local_addr_)
266 << "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: "
267 << packet.to.ipaddr().ToString()
268 << "; Receiver peer_local_addr_=" << peer_local_addr_.ToString();
Artem Titov0774bd92019-01-30 15:26:05 +0100269 rtc::CritScope crit(&receiver_lock_);
Artem Titov806299e2019-04-12 12:17:19 +0200270 UpdateReceiveStats(packet);
Artem Titov0774bd92019-01-30 15:26:05 +0100271 auto it = port_to_receiver_.find(packet.to.port());
272 if (it == port_to_receiver_.end()) {
273 // It can happen, that remote peer closed connection, but there still some
274 // packets, that are going to it. It can happen during peer connection close
275 // process: one peer closed connection, second still sending data.
Artem Titov806299e2019-04-12 12:17:19 +0200276 RTC_LOG(INFO) << "Drop packet: no receiver registered in " << id_
277 << " on port " << packet.to.port();
278 stats_.packets_dropped++;
Niels Möller7536bc52019-10-04 13:54:39 +0200279 stats_.bytes_dropped += DataSize::bytes(packet.ip_packet_size());
Artem Titov0774bd92019-01-30 15:26:05 +0100280 return;
281 }
282 // Endpoint assumes frequent calls to bind and unbind methods, so it holds
283 // lock during packet processing to ensure that receiver won't be deleted
284 // before call to OnPacketReceived.
285 it->second->OnPacketReceived(std::move(packet));
286}
287
Sebastian Janssoncec24332019-12-04 14:26:50 +0100288void EmulatedEndpointImpl::Enable() {
Artem Titove5cc85b2019-03-28 12:11:09 +0100289 RTC_DCHECK_RUN_ON(&enabled_state_checker_);
290 RTC_CHECK(!is_enabled_);
291 is_enabled_ = true;
292}
293
Sebastian Janssoncec24332019-12-04 14:26:50 +0100294void EmulatedEndpointImpl::Disable() {
Artem Titove5cc85b2019-03-28 12:11:09 +0100295 RTC_DCHECK_RUN_ON(&enabled_state_checker_);
296 RTC_CHECK(is_enabled_);
297 is_enabled_ = false;
298}
299
Sebastian Janssoncec24332019-12-04 14:26:50 +0100300bool EmulatedEndpointImpl::Enabled() const {
Artem Titove5cc85b2019-03-28 12:11:09 +0100301 RTC_DCHECK_RUN_ON(&enabled_state_checker_);
302 return is_enabled_;
303}
304
Sebastian Janssoncec24332019-12-04 14:26:50 +0100305EmulatedNetworkStats EmulatedEndpointImpl::stats() {
Artem Titov806299e2019-04-12 12:17:19 +0200306 RTC_DCHECK_RUN_ON(task_queue_);
307 return stats_;
308}
309
Sebastian Janssoncec24332019-12-04 14:26:50 +0100310void EmulatedEndpointImpl::UpdateReceiveStats(const EmulatedIpPacket& packet) {
Artem Titov806299e2019-04-12 12:17:19 +0200311 RTC_DCHECK_RUN_ON(task_queue_);
Sebastian Janssonb64ad0e2019-06-19 09:39:34 +0200312 Timestamp current_time = clock_->CurrentTime();
Artem Titov806299e2019-04-12 12:17:19 +0200313 if (stats_.first_packet_received_time.IsInfinite()) {
314 stats_.first_packet_received_time = current_time;
Niels Möller7536bc52019-10-04 13:54:39 +0200315 stats_.first_received_packet_size =
316 DataSize::bytes(packet.ip_packet_size());
Artem Titov806299e2019-04-12 12:17:19 +0200317 }
318 stats_.last_packet_received_time = current_time;
319 stats_.packets_received++;
Niels Möller7536bc52019-10-04 13:54:39 +0200320 stats_.bytes_received += DataSize::bytes(packet.ip_packet_size());
Artem Titov806299e2019-04-12 12:17:19 +0200321}
322
Artem Titove5cc85b2019-03-28 12:11:09 +0100323EndpointsContainer::EndpointsContainer(
Sebastian Janssoncec24332019-12-04 14:26:50 +0100324 const std::vector<EmulatedEndpointImpl*>& endpoints)
Artem Titove5cc85b2019-03-28 12:11:09 +0100325 : endpoints_(endpoints) {}
326
Sebastian Janssoncec24332019-12-04 14:26:50 +0100327EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress(
Artem Titove5cc85b2019-03-28 12:11:09 +0100328 const rtc::IPAddress& local_ip) const {
329 for (auto* endpoint : endpoints_) {
Artem Titov4cd433e2019-04-01 11:01:16 +0200330 rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress();
331 if (peer_local_address == local_ip) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100332 return endpoint;
333 }
334 }
335 RTC_CHECK(false) << "No network found for address" << local_ip.ToString();
336}
337
Sebastian Janssoncec24332019-12-04 14:26:50 +0100338bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const {
Artem Titove5cc85b2019-03-28 12:11:09 +0100339 for (auto* e : endpoints_) {
340 if (e->GetId() == endpoint->GetId()) {
341 return true;
342 }
343 }
344 return false;
345}
346
347std::vector<std::unique_ptr<rtc::Network>>
348EndpointsContainer::GetEnabledNetworks() const {
349 std::vector<std::unique_ptr<rtc::Network>> networks;
350 for (auto* endpoint : endpoints_) {
351 if (endpoint->Enabled()) {
352 networks.emplace_back(
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200353 std::make_unique<rtc::Network>(endpoint->network()));
Artem Titove5cc85b2019-03-28 12:11:09 +0100354 }
355 }
356 return networks;
357}
358
Artem Titov806299e2019-04-12 12:17:19 +0200359EmulatedNetworkStats EndpointsContainer::GetStats() const {
360 EmulatedNetworkStats stats;
361 for (auto* endpoint : endpoints_) {
362 EmulatedNetworkStats endpoint_stats = endpoint->stats();
363 stats.packets_sent += endpoint_stats.packets_sent;
364 stats.bytes_sent += endpoint_stats.bytes_sent;
365 stats.packets_received += endpoint_stats.packets_received;
366 stats.bytes_received += endpoint_stats.bytes_received;
367 stats.packets_dropped += endpoint_stats.packets_dropped;
368 stats.bytes_dropped += endpoint_stats.bytes_dropped;
369 if (stats.first_packet_received_time >
370 endpoint_stats.first_packet_received_time) {
371 stats.first_packet_received_time =
372 endpoint_stats.first_packet_received_time;
373 stats.first_received_packet_size =
374 endpoint_stats.first_received_packet_size;
375 }
376 if (stats.first_packet_sent_time > endpoint_stats.first_packet_sent_time) {
377 stats.first_packet_sent_time = endpoint_stats.first_packet_sent_time;
378 stats.first_sent_packet_size = endpoint_stats.first_sent_packet_size;
379 }
380 if (stats.last_packet_received_time.IsInfinite() ||
381 stats.last_packet_received_time <
382 endpoint_stats.last_packet_received_time) {
383 stats.last_packet_received_time =
384 endpoint_stats.last_packet_received_time;
385 }
386 if (stats.last_packet_sent_time.IsInfinite() ||
387 stats.last_packet_sent_time < endpoint_stats.last_packet_sent_time) {
388 stats.last_packet_sent_time = endpoint_stats.last_packet_sent_time;
389 }
390 }
391 return stats;
392}
393
Artem Titov40f51152019-01-04 15:45:01 +0100394} // namespace webrtc