Allow FakeNetworkPipe to drop packets in bursts.
The fake network pipe will still only drop packets at an average rate of |loss_percent| but in bursts at an average length specified by |avg_burst_loss_length|. Also added the flag -avg_burst_loss_length to video loopback. BUG= Review-Url: https://codereview.webrtc.org/1995683003 Cr-Commit-Position: refs/heads/master@{#12969}
This commit is contained in:
@ -13,7 +13,9 @@
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "webrtc/call.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
@ -34,7 +36,27 @@ FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
|
||||
dropped_packets_(0),
|
||||
sent_packets_(0),
|
||||
total_packet_delay_(0),
|
||||
next_process_time_(clock_->TimeInMilliseconds()) {}
|
||||
bursting_(false),
|
||||
next_process_time_(clock_->TimeInMilliseconds()) {
|
||||
double prob_loss = config.loss_percent / 100.0;
|
||||
if (config_.avg_burst_loss_length == -1) {
|
||||
// Uniform loss
|
||||
prob_loss_bursting_ = prob_loss;
|
||||
prob_start_bursting_ = prob_loss;
|
||||
} else {
|
||||
// Lose packets according to a gilbert-elliot model.
|
||||
int avg_burst_loss_length = config.avg_burst_loss_length;
|
||||
int min_avg_burst_loss_length = std::ceil(prob_loss / (1 - prob_loss));
|
||||
|
||||
RTC_CHECK_GT(avg_burst_loss_length, min_avg_burst_loss_length)
|
||||
<< "For a total packet loss of " << config.loss_percent << "%% then"
|
||||
<< " avg_burst_loss_length must be " << min_avg_burst_loss_length + 1
|
||||
<< " or higher.";
|
||||
|
||||
prob_loss_bursting_ = (1.0 - 1.0 / avg_burst_loss_length);
|
||||
prob_start_bursting_ = prob_loss / (1 - prob_loss) / avg_burst_loss_length;
|
||||
}
|
||||
}
|
||||
|
||||
FakeNetworkPipe::~FakeNetworkPipe() {
|
||||
while (!capacity_link_.empty()) {
|
||||
@ -118,10 +140,15 @@ void FakeNetworkPipe::Process() {
|
||||
NetworkPacket* packet = capacity_link_.front();
|
||||
capacity_link_.pop();
|
||||
|
||||
// Packets are randomly dropped after being affected by the bottleneck.
|
||||
if (random_.Rand(100) < static_cast<uint32_t>(config_.loss_percent)) {
|
||||
// Drop packets at an average rate of |config_.loss_percent| with
|
||||
// and average loss burst length of |config_.avg_burst_loss_length|.
|
||||
if ((bursting_ && random_.Rand<double>() < prob_loss_bursting_) ||
|
||||
(!bursting_ && random_.Rand<double>() < prob_start_bursting_)) {
|
||||
bursting_ = true;
|
||||
delete packet;
|
||||
continue;
|
||||
} else {
|
||||
bursting_ = false;
|
||||
}
|
||||
|
||||
int arrival_time_jitter = random_.Gaussian(
|
||||
|
||||
@ -80,6 +80,8 @@ class FakeNetworkPipe {
|
||||
int loss_percent = 0;
|
||||
// If packets are allowed to be reordered.
|
||||
bool allow_reordering = false;
|
||||
// The average length of a burst of lost packets.
|
||||
int avg_burst_loss_length = -1;
|
||||
};
|
||||
|
||||
FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config);
|
||||
@ -133,6 +135,16 @@ class FakeNetworkPipe {
|
||||
size_t sent_packets_;
|
||||
int64_t total_packet_delay_;
|
||||
|
||||
// Are we currently dropping a burst of packets?
|
||||
bool bursting_;
|
||||
|
||||
// The probability to drop the packet if we are currently dropping a
|
||||
// burst of packet
|
||||
double prob_loss_bursting_;
|
||||
|
||||
// The probability to drop a burst of packets.
|
||||
double prob_start_bursting_;
|
||||
|
||||
int64_t next_process_time_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe);
|
||||
|
||||
@ -379,4 +379,45 @@ TEST_F(FakeNetworkPipeTest, DisallowReorderingThenAllowReordering) {
|
||||
}
|
||||
EXPECT_TRUE(reordering_has_occured);
|
||||
}
|
||||
|
||||
TEST_F(FakeNetworkPipeTest, BurstLoss) {
|
||||
const int kLossPercent = 5;
|
||||
const int kAvgBurstLength = 3;
|
||||
const int kNumPackets = 10000;
|
||||
const int kPacketSize = 10;
|
||||
|
||||
FakeNetworkPipe::Config config;
|
||||
config.queue_length_packets = kNumPackets;
|
||||
config.loss_percent = kLossPercent;
|
||||
config.avg_burst_loss_length = kAvgBurstLength;
|
||||
std::unique_ptr<FakeNetworkPipe> pipe(
|
||||
new FakeNetworkPipe(&fake_clock_, config));
|
||||
ReorderTestReceiver* receiver = new ReorderTestReceiver();
|
||||
receiver_.reset(receiver);
|
||||
pipe->SetReceiver(receiver_.get());
|
||||
|
||||
SendPackets(pipe.get(), kNumPackets, kPacketSize);
|
||||
fake_clock_.AdvanceTimeMilliseconds(1000);
|
||||
pipe->Process();
|
||||
|
||||
// Check that the average loss is |kLossPercent| percent.
|
||||
int lost_packets = kNumPackets - receiver->delivered_sequence_numbers_.size();
|
||||
double loss_fraction = lost_packets / static_cast<double>(kNumPackets);
|
||||
|
||||
EXPECT_NEAR(kLossPercent / 100.0, loss_fraction, 0.05);
|
||||
|
||||
// Find the number of bursts that has occurred.
|
||||
size_t received_packets = receiver->delivered_sequence_numbers_.size();
|
||||
int num_bursts = 0;
|
||||
for (size_t i = 0; i < received_packets - 1; ++i) {
|
||||
int diff = receiver->delivered_sequence_numbers_[i + 1] -
|
||||
receiver->delivered_sequence_numbers_[i];
|
||||
if (diff > 1)
|
||||
++num_bursts;
|
||||
}
|
||||
|
||||
double average_burst_length = static_cast<double>(lost_packets) / num_bursts;
|
||||
|
||||
EXPECT_NEAR(kAvgBurstLength, average_burst_length, 0.3);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -101,6 +101,11 @@ int LossPercent() {
|
||||
return static_cast<int>(FLAGS_loss_percent);
|
||||
}
|
||||
|
||||
DEFINE_int32(avg_burst_loss_length, 1, "Average burst length of lost packets.");
|
||||
int AvgBurstLossLength() {
|
||||
return static_cast<int>(FLAGS_avg_burst_loss_length);
|
||||
}
|
||||
|
||||
DEFINE_int32(link_capacity,
|
||||
0,
|
||||
"Capacity (kbps) of the fake link. 0 means infinite.");
|
||||
@ -201,6 +206,7 @@ std::string Clip() {
|
||||
void Loopback() {
|
||||
FakeNetworkPipe::Config pipe_config;
|
||||
pipe_config.loss_percent = flags::LossPercent();
|
||||
pipe_config.avg_burst_loss_length = flags::AvgBurstLossLength();
|
||||
pipe_config.link_capacity_kbps = flags::LinkCapacityKbps();
|
||||
pipe_config.queue_length_packets = flags::QueueSize();
|
||||
pipe_config.queue_delay_ms = flags::AvgPropagationDelayMs();
|
||||
|
||||
Reference in New Issue
Block a user