Remove CoDel from webrtc::SimulatedNetwork.

This is unused at the moment and webrtc::SimulatedNetwork is going
through a refactoring, to keep things simple and well tested this CL
removes CoDel but nothing blocks us from re-implementing it when needed.

No-Try: True
Bug: webrtc:14426
Change-Id: Ie7d40d20a66d3939fc7d3251c47e4f13f3869a27
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/274407
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Auto-Submit: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38032}
This commit is contained in:
Mirko Bonadei 2022-09-07 15:31:46 +02:00 committed by WebRTC LUCI CQ
parent 871ad523fa
commit 399a2b5ef6
8 changed files with 1 additions and 256 deletions

View File

@ -62,8 +62,6 @@ struct BuiltInNetworkBehaviorConfig {
int avg_burst_loss_length = -1;
// Additional bytes to add to packet size.
int packet_overhead = 0;
// Enable CoDel active queue management.
bool codel_active_queue_management = false;
};
class NetworkBehaviorInterface {

View File

@ -645,10 +645,7 @@ if (rtc_include_tests) {
rtc_library("fake_network_pipe_unittests") {
testonly = true
sources = [
"fake_network_pipe_unittest.cc",
"simulated_network_unittest.cc",
]
sources = [ "fake_network_pipe_unittest.cc" ]
deps = [
":fake_network",
":simulated_network",

View File

@ -67,10 +67,6 @@ std::vector<TimeScopedNetworkConfig> GetNetworkConfigs(
FieldTrialStructMember(
"packet_overhead",
[](TimeScopedNetworkConfig* p) { return &p->packet_overhead; }),
FieldTrialStructMember("codel_active_queue_management",
[](TimeScopedNetworkConfig* p) {
return &p->codel_active_queue_management;
}),
FieldTrialStructMember(
"duration",
[](TimeScopedNetworkConfig* p) { return &p->duration; })},

View File

@ -24,62 +24,6 @@ namespace {
constexpr TimeDelta kDefaultProcessDelay = TimeDelta::Millis(5);
} // namespace
CoDelSimulation::CoDelSimulation() = default;
CoDelSimulation::~CoDelSimulation() = default;
bool CoDelSimulation::DropDequeuedPacket(Timestamp now,
Timestamp enqueing_time,
DataSize packet_size,
DataSize queue_size) {
constexpr TimeDelta kWindow = TimeDelta::Millis(100);
constexpr TimeDelta kDelayThreshold = TimeDelta::Millis(5);
constexpr TimeDelta kDropCountMemory = TimeDelta::Millis(1600);
constexpr DataSize kMaxPacketSize = DataSize::Bytes(1500);
// Compensates for process interval in simulation; not part of standard CoDel.
TimeDelta queuing_time = now - enqueing_time - kDefaultProcessDelay;
if (queue_size < kMaxPacketSize || queuing_time < kDelayThreshold) {
enter_drop_state_at_ = Timestamp::PlusInfinity();
state_ = kNormal;
return false;
}
switch (state_) {
case kNormal:
enter_drop_state_at_ = now + kWindow;
state_ = kPending;
return false;
case kPending:
if (now >= enter_drop_state_at_) {
state_ = kDropping;
// Starting the drop counter with the drops made during the most recent
// drop state period.
drop_count_ = drop_count_ - previous_drop_count_;
if (now >= last_drop_at_ + kDropCountMemory)
drop_count_ = 0;
previous_drop_count_ = drop_count_;
last_drop_at_ = now;
++drop_count_;
return true;
}
return false;
case kDropping:
TimeDelta drop_delay = kWindow / sqrt(static_cast<double>(drop_count_));
Timestamp next_drop_at = last_drop_at_ + drop_delay;
if (now >= next_drop_at) {
if (queue_size - packet_size < kMaxPacketSize)
state_ = kPending;
last_drop_at_ = next_drop_at;
++drop_count_;
return true;
}
return false;
}
RTC_CHECK_NOTREACHED();
}
SimulatedNetwork::SimulatedNetwork(Config config, uint64_t random_seed)
: random_(random_seed), bursting_(false) {
SetConfig(config);
@ -195,20 +139,6 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state,
capacity_link_.pop();
time_us += time_until_front_exits_us;
if (state.config.codel_active_queue_management) {
while (!capacity_link_.empty() &&
codel_controller_.DropDequeuedPacket(
Timestamp::Micros(time_us),
Timestamp::Micros(capacity_link_.front().packet.send_time_us),
DataSize::Bytes(capacity_link_.front().packet.size),
DataSize::Bytes(queue_size_bytes_))) {
PacketInfo dropped = capacity_link_.front();
capacity_link_.pop();
queue_size_bytes_ -= dropped.packet.size;
dropped.arrival_time_us = PacketDeliveryInfo::kNotReceived;
delay_link_.emplace_back(dropped);
}
}
RTC_DCHECK(time_us >= packet.packet.send_time_us);
packet.arrival_time_us =
std::max(state.pause_transmission_until_us, time_us);

View File

@ -27,29 +27,6 @@
#include "rtc_base/thread_annotations.h"
namespace webrtc {
// Implementation of the CoDel active queue management algorithm. Loosely based
// on CoDel pseudocode from ACMQueue. CoDel keeps queuing delays low by dropping
// packets when delay is high. For each packet ready for dequeue, call
// DropDequeuePacket with the packet parameters to update the CoDel state.
class CoDelSimulation {
public:
CoDelSimulation();
~CoDelSimulation();
// Returns true if packet should be dropped.
bool DropDequeuedPacket(Timestamp now,
Timestamp enqueing_time,
DataSize packet_size,
DataSize queue_size);
private:
enum State { kNormal, kPending, kDropping };
Timestamp enter_drop_state_at_ = Timestamp::PlusInfinity();
Timestamp last_drop_at_ = Timestamp::MinusInfinity();
int drop_count_ = 0;
int previous_drop_count_ = 0;
State state_ = State::kNormal;
};
// Class simulating a network link. This is a simple and naive solution just
// faking capacity and adding an extra transport delay in addition to the
@ -101,7 +78,6 @@ class SimulatedNetwork : public SimulatedNetworkInterface {
// `process_checker_` guards the data structures involved in delay and loss
// processes, such as the packet queues.
rtc::RaceChecker process_checker_;
CoDelSimulation codel_controller_ RTC_GUARDED_BY(process_checker_);
std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_);
Random random_;

View File

@ -1,149 +0,0 @@
/*
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "call/simulated_network.h"
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include "absl/algorithm/container.h"
#include "api/units/data_rate.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr int kNotReceived = PacketDeliveryInfo::kNotReceived;
}
TEST(SimulatedNetworkTest, CodelDoesNothingAtCapacity) {
const TimeDelta kRuntime = TimeDelta::Seconds(30);
DataRate link_capacity = DataRate::KilobitsPerSec(1000);
const DataSize packet_size = DataSize::Bytes(1000);
SimulatedNetwork::Config config;
config.codel_active_queue_management = true;
config.queue_delay_ms = 10;
config.link_capacity_kbps = link_capacity.kbps();
SimulatedNetwork network(config);
// Need to round up here as otherwise we actually will choke.
const TimeDelta packet_inverval =
packet_size / link_capacity + TimeDelta::Millis(1);
// Send at capacity and see we get no loss.
Timestamp start_time = Timestamp::Zero();
Timestamp current_time = start_time;
Timestamp next_packet_time = start_time;
uint64_t next_id = 0;
std::set<uint64_t> pending;
while (current_time - start_time < kRuntime) {
if (current_time >= next_packet_time) {
bool success = network.EnqueuePacket(PacketInFlightInfo{
packet_size.bytes<size_t>(), current_time.us(), next_id});
EXPECT_TRUE(success);
pending.insert(next_id);
++next_id;
next_packet_time += packet_inverval;
}
Timestamp next_delivery = Timestamp::PlusInfinity();
if (network.NextDeliveryTimeUs())
next_delivery = Timestamp::Micros(*network.NextDeliveryTimeUs());
current_time = std::min(next_packet_time, next_delivery);
if (current_time >= next_delivery) {
for (PacketDeliveryInfo packet :
network.DequeueDeliverablePackets(current_time.us())) {
EXPECT_NE(packet.receive_time_us, kNotReceived);
pending.erase(packet.packet_id);
}
}
}
while (network.NextDeliveryTimeUs()) {
for (PacketDeliveryInfo packet :
network.DequeueDeliverablePackets(*network.NextDeliveryTimeUs())) {
EXPECT_NE(packet.receive_time_us, kNotReceived);
pending.erase(packet.packet_id);
}
}
EXPECT_EQ(pending.size(), 0u);
}
TEST(SimulatedNetworkTest, CodelLimitsDelayAndDropsPacketsOnOverload) {
const TimeDelta kRuntime = TimeDelta::Seconds(30);
const TimeDelta kCheckInterval = TimeDelta::Millis(2000);
DataRate link_capacity = DataRate::KilobitsPerSec(1000);
const DataSize rough_packet_size = DataSize::Bytes(1500);
const double overload_rate = 1.5;
SimulatedNetwork::Config config;
config.codel_active_queue_management = true;
config.queue_delay_ms = 10;
config.link_capacity_kbps = link_capacity.kbps();
SimulatedNetwork network(config);
const TimeDelta packet_inverval = rough_packet_size / link_capacity;
const DataSize packet_size = overload_rate * link_capacity * packet_inverval;
// Send above capacity and see delays are still controlled at the cost of
// packet loss.
Timestamp start_time = Timestamp::Zero();
Timestamp current_time = start_time;
Timestamp next_packet_time = start_time;
Timestamp last_check = start_time;
uint64_t next_id = 1;
std::map<uint64_t, int64_t> send_times_us;
int lost = 0;
std::vector<int64_t> delays_us;
while (current_time - start_time < kRuntime) {
if (current_time >= next_packet_time) {
bool success = network.EnqueuePacket(PacketInFlightInfo{
packet_size.bytes<size_t>(), current_time.us(), next_id});
send_times_us.insert({next_id, current_time.us()});
++next_id;
EXPECT_TRUE(success);
next_packet_time += packet_inverval;
}
Timestamp next_delivery = Timestamp::PlusInfinity();
if (network.NextDeliveryTimeUs())
next_delivery = Timestamp::Micros(*network.NextDeliveryTimeUs());
current_time = std::min(next_packet_time, next_delivery);
if (current_time >= next_delivery) {
for (PacketDeliveryInfo packet :
network.DequeueDeliverablePackets(current_time.us())) {
if (packet.receive_time_us == kNotReceived) {
++lost;
} else {
delays_us.push_back(packet.receive_time_us -
send_times_us[packet.packet_id]);
}
send_times_us.erase(packet.packet_id);
}
}
if (current_time > last_check + kCheckInterval) {
last_check = current_time;
TimeDelta average_delay =
TimeDelta::Micros(absl::c_accumulate(delays_us, 0)) /
delays_us.size();
double loss_ratio = static_cast<double>(lost) / (lost + delays_us.size());
EXPECT_LT(average_delay.ms(), 200)
<< "Time " << (current_time - start_time).ms() << "\n";
EXPECT_GT(loss_ratio, 0.5 * (overload_rate - 1));
}
}
while (network.NextDeliveryTimeUs()) {
for (PacketDeliveryInfo packet :
network.DequeueDeliverablePackets(*network.NextDeliveryTimeUs())) {
send_times_us.erase(packet.packet_id);
}
}
EXPECT_EQ(send_times_us.size(), 0u);
}
} // namespace webrtc

View File

@ -28,8 +28,6 @@ SimulatedNetwork::Config CreateSimulationConfig(
sim_config.queue_delay_ms = config.delay.ms();
sim_config.delay_standard_deviation_ms = config.delay_std_dev.ms();
sim_config.packet_overhead = config.packet_overhead.bytes<int>();
sim_config.codel_active_queue_management =
config.codel_active_queue_management;
sim_config.queue_length_packets =
config.packet_queue_length_limit.value_or(0);
return sim_config;

View File

@ -217,7 +217,6 @@ struct NetworkSimulationConfig {
TimeDelta delay = TimeDelta::Zero();
TimeDelta delay_std_dev = TimeDelta::Zero();
double loss_rate = 0;
bool codel_active_queue_management = false;
absl::optional<int> packet_queue_length_limit;
DataSize packet_overhead = DataSize::Zero();
};