• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2019 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 #include "call/simulated_network.h"
11 
12 #include <algorithm>
13 #include <map>
14 #include <set>
15 #include <vector>
16 
17 #include "absl/algorithm/container.h"
18 #include "api/units/data_rate.h"
19 #include "test/gtest.h"
20 
21 namespace webrtc {
22 namespace {
23 constexpr int kNotReceived = PacketDeliveryInfo::kNotReceived;
24 }
25 
TEST(SimulatedNetworkTest,CodelDoesNothingAtCapacity)26 TEST(SimulatedNetworkTest, CodelDoesNothingAtCapacity) {
27   const TimeDelta kRuntime = TimeDelta::Seconds(30);
28 
29   DataRate link_capacity = DataRate::KilobitsPerSec(1000);
30   const DataSize packet_size = DataSize::Bytes(1000);
31 
32   SimulatedNetwork::Config config;
33   config.codel_active_queue_management = true;
34   config.queue_delay_ms = 10;
35   config.link_capacity_kbps = link_capacity.kbps();
36   SimulatedNetwork network(config);
37 
38   // Need to round up here as otherwise we actually will choke.
39   const TimeDelta packet_inverval =
40       packet_size / link_capacity + TimeDelta::Millis(1);
41 
42   // Send at capacity and see we get no loss.
43   Timestamp start_time = Timestamp::Millis(0);
44   Timestamp current_time = start_time;
45   Timestamp next_packet_time = start_time;
46   uint64_t next_id = 0;
47   std::set<uint64_t> pending;
48   while (current_time - start_time < kRuntime) {
49     if (current_time >= next_packet_time) {
50       bool success = network.EnqueuePacket(PacketInFlightInfo{
51           packet_size.bytes<size_t>(), current_time.us(), next_id});
52       EXPECT_TRUE(success);
53       pending.insert(next_id);
54       ++next_id;
55       next_packet_time += packet_inverval;
56     }
57     Timestamp next_delivery = Timestamp::PlusInfinity();
58     if (network.NextDeliveryTimeUs())
59       next_delivery = Timestamp::Micros(*network.NextDeliveryTimeUs());
60     current_time = std::min(next_packet_time, next_delivery);
61     if (current_time >= next_delivery) {
62       for (PacketDeliveryInfo packet :
63            network.DequeueDeliverablePackets(current_time.us())) {
64         EXPECT_NE(packet.receive_time_us, kNotReceived);
65         pending.erase(packet.packet_id);
66       }
67     }
68   }
69   while (network.NextDeliveryTimeUs()) {
70     for (PacketDeliveryInfo packet :
71          network.DequeueDeliverablePackets(*network.NextDeliveryTimeUs())) {
72       EXPECT_NE(packet.receive_time_us, kNotReceived);
73       pending.erase(packet.packet_id);
74     }
75   }
76   EXPECT_EQ(pending.size(), 0u);
77 }
78 
TEST(SimulatedNetworkTest,CodelLimitsDelayAndDropsPacketsOnOverload)79 TEST(SimulatedNetworkTest, CodelLimitsDelayAndDropsPacketsOnOverload) {
80   const TimeDelta kRuntime = TimeDelta::Seconds(30);
81   const TimeDelta kCheckInterval = TimeDelta::Millis(2000);
82 
83   DataRate link_capacity = DataRate::KilobitsPerSec(1000);
84   const DataSize rough_packet_size = DataSize::Bytes(1500);
85   const double overload_rate = 1.5;
86 
87   SimulatedNetwork::Config config;
88   config.codel_active_queue_management = true;
89   config.queue_delay_ms = 10;
90   config.link_capacity_kbps = link_capacity.kbps();
91   SimulatedNetwork network(config);
92 
93   const TimeDelta packet_inverval = rough_packet_size / link_capacity;
94   const DataSize packet_size = overload_rate * link_capacity * packet_inverval;
95   // Send above capacity and see delays are still controlled at the cost of
96   // packet loss.
97   Timestamp start_time = Timestamp::Millis(0);
98   Timestamp current_time = start_time;
99   Timestamp next_packet_time = start_time;
100   Timestamp last_check = start_time;
101   uint64_t next_id = 1;
102   std::map<uint64_t, int64_t> send_times_us;
103   int lost = 0;
104   std::vector<int64_t> delays_us;
105   while (current_time - start_time < kRuntime) {
106     if (current_time >= next_packet_time) {
107       bool success = network.EnqueuePacket(PacketInFlightInfo{
108           packet_size.bytes<size_t>(), current_time.us(), next_id});
109       send_times_us.insert({next_id, current_time.us()});
110       ++next_id;
111       EXPECT_TRUE(success);
112       next_packet_time += packet_inverval;
113     }
114     Timestamp next_delivery = Timestamp::PlusInfinity();
115     if (network.NextDeliveryTimeUs())
116       next_delivery = Timestamp::Micros(*network.NextDeliveryTimeUs());
117     current_time = std::min(next_packet_time, next_delivery);
118     if (current_time >= next_delivery) {
119       for (PacketDeliveryInfo packet :
120            network.DequeueDeliverablePackets(current_time.us())) {
121         if (packet.receive_time_us == kNotReceived) {
122           ++lost;
123         } else {
124           delays_us.push_back(packet.receive_time_us -
125                               send_times_us[packet.packet_id]);
126         }
127         send_times_us.erase(packet.packet_id);
128       }
129     }
130     if (current_time > last_check + kCheckInterval) {
131       last_check = current_time;
132       TimeDelta average_delay =
133           TimeDelta::Micros(absl::c_accumulate(delays_us, 0)) /
134           delays_us.size();
135       double loss_ratio = static_cast<double>(lost) / (lost + delays_us.size());
136       EXPECT_LT(average_delay.ms(), 200)
137           << "Time " << (current_time - start_time).ms() << "\n";
138       EXPECT_GT(loss_ratio, 0.5 * (overload_rate - 1));
139     }
140   }
141   while (network.NextDeliveryTimeUs()) {
142     for (PacketDeliveryInfo packet :
143          network.DequeueDeliverablePackets(*network.NextDeliveryTimeUs())) {
144       send_times_us.erase(packet.packet_id);
145     }
146   }
147   EXPECT_EQ(send_times_us.size(), 0u);
148 }
149 }  // namespace webrtc
150