blob: 25fb1c1399af6ff2a82f926ca41d503f3b9e2be8 [file] [log] [blame]
Sebastian Jansson2b08e312019-02-25 10:24:46 +01001/*
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 */
Jonas Olssona4d87372019-07-05 19:08:33 +020010#include "call/simulated_network.h"
11
12#include <algorithm>
Sebastian Jansson2b08e312019-02-25 10:24:46 +010013#include <map>
14#include <set>
15#include <vector>
16
Sebastian Jansson2b08e312019-02-25 10:24:46 +010017#include "absl/algorithm/container.h"
18#include "api/units/data_rate.h"
Sebastian Jansson2b08e312019-02-25 10:24:46 +010019#include "test/gtest.h"
20
21namespace webrtc {
22namespace {
23constexpr int kNotReceived = PacketDeliveryInfo::kNotReceived;
24}
25
26TEST(SimulatedNetworkTest, CodelDoesNothingAtCapacity) {
27 const TimeDelta kRuntime = TimeDelta::seconds(30);
28
29 DataRate link_capacity = DataRate::kbps(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::ms(1);
41
42 // Send at capacity and see we get no loss.
43 Timestamp start_time = Timestamp::ms(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::us(*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
79TEST(SimulatedNetworkTest, CodelLimitsDelayAndDropsPacketsOnOverload) {
80 const TimeDelta kRuntime = TimeDelta::seconds(30);
81 const TimeDelta kCheckInterval = TimeDelta::ms(2000);
82
83 DataRate link_capacity = DataRate::kbps(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::ms(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::us(*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::us(absl::c_accumulate(delays_us, 0)) / delays_us.size();
134 double loss_ratio = static_cast<double>(lost) / (lost + delays_us.size());
135 EXPECT_LT(average_delay.ms(), 200)
136 << "Time " << (current_time - start_time).ms() << "\n";
137 EXPECT_GT(loss_ratio, 0.5 * (overload_rate - 1));
138 }
139 }
140 while (network.NextDeliveryTimeUs()) {
141 for (PacketDeliveryInfo packet :
142 network.DequeueDeliverablePackets(*network.NextDeliveryTimeUs())) {
143 send_times_us.erase(packet.packet_id);
144 }
145 }
146 EXPECT_EQ(send_times_us.size(), 0u);
147}
148} // namespace webrtc