From de21ef07aeac544e3440f9738a90f52e6de503ce Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Tue, 27 Aug 2024 05:32:45 +0300 Subject: [PATCH] Add burst parameter to DropRateErrorModel (#134) * Add burst parameter to DropRateErrorModel This makes it so that the error model doesn't create loss bursts that are longer than the burst parameter. This should prevent idle timeouts when loss bursts are too long. It will however lower the overall loss rate below what is configured, because we're not adjusting the drop rate upward to compensate for breaking loss bursts (by forcing a forward). * Minimize diff * Simplify * Suggestions from @marten-seemann --- sim/scenarios/drop-rate/README.md | 11 +++- .../drop-rate/drop-rate-error-model.cc | 50 ++++++++++++++++--- .../drop-rate/drop-rate-error-model.h | 7 +++ sim/scenarios/drop-rate/drop-rate.cc | 15 +++++- 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/sim/scenarios/drop-rate/README.md b/sim/scenarios/drop-rate/README.md index 0a7bb44..0944348 100644 --- a/sim/scenarios/drop-rate/README.md +++ b/sim/scenarios/drop-rate/README.md @@ -3,7 +3,8 @@ This scenario uses a bottleneck link similar to the [simple-p2p](../simple-p2p) scenario and optionally allows configuring the link to drop packets in either direction. Packets to be dropped are chosen randomly in both directions, based -on rates specified by the user. +on rates specified by the user, but no more than a given number of packets are +dropped in a row. This scenario has the following configurable properties: @@ -21,9 +22,15 @@ This scenario has the following configurable properties: (in percentage) in the server to client direction. This is a required parameter. For example, `--rate_to_client=10`. +* `--burst_to_client`: The maximum number of packets that will be dropped in a + row in the server to client direction. This is an optional parameter. For + example, `--burst_to_client=3`. + * `--rate_to_server`: Same as `rate_to_client` but in the other direction. +* `--burst_to_server`: Same as `burst_to_client` but in the other direction. + For example, ```bash -./run.sh "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_client=10 --rate_to_server=20" +./run.sh "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_client=10 --rate_to_server=20 --burst_to_client=3 --burst_to_server=3" ``` diff --git a/sim/scenarios/drop-rate/drop-rate-error-model.cc b/sim/scenarios/drop-rate/drop-rate-error-model.cc index 62c561c..58903d3 100644 --- a/sim/scenarios/drop-rate/drop-rate-error-model.cc +++ b/sim/scenarios/drop-rate/drop-rate-error-model.cc @@ -1,3 +1,5 @@ +#include + #include "../helper/quic-packet.h" #include "drop-rate-error-model.h" @@ -12,30 +14,62 @@ TypeId DropRateErrorModel::GetTypeId(void) { ; return tid; } - + DropRateErrorModel::DropRateErrorModel() - : rate(0), distr(0, 99) { + : rate(0), distr(0, 99), burst(INT_MAX), dropped_in_a_row(0), dropped(0), forwarded(0) +{ std::random_device rd; rng = new std::mt19937(rd()); } -void DropRateErrorModel::DoReset(void) { } +void DropRateErrorModel::DoReset(void) { + dropped_in_a_row = 0; + dropped = 0; + forwarded = 0; +} bool DropRateErrorModel::DoCorrupt(Ptr p) { if(!IsUDPPacket(p)) return false; + bool shouldDrop = false; + if (dropped_in_a_row >= burst) { + dropped_in_a_row = 0; + shouldDrop = false; + } else if (distr(*rng) < rate) { + dropped_in_a_row++; + shouldDrop = true; + } else { + dropped_in_a_row = 0; + shouldDrop = false; + } + QuicPacket qp = QuicPacket(p); - if (distr(*rng) >= rate) { - cout << "Forwarding packet (" << qp.GetUdpPayload().size() << " bytes) from " << qp.GetIpv4Header().GetSource() << endl; + if (shouldDrop) { + cout << "Dropping "; + dropped++; + } else { + cout << "Forwarding "; + forwarded++; qp.ReassemblePacket(); - return false; } + cout << qp.GetUdpPayload().size() + << " bytes " << qp.GetIpv4Header().GetSource() << ":" + << qp.GetUdpHeader().GetSourcePort() << " -> " + << qp.GetIpv4Header().GetDestination() << ":" + << qp.GetUdpHeader().GetDestinationPort() + << ", dropped " << dropped << "/" << dropped + forwarded << " (" + << fixed << setprecision(1) + << (double)dropped / (dropped + forwarded) * 100 + << "%)" << endl; - cout << "Dropping packet (" << qp.GetUdpPayload().size() << " bytes) from " << qp.GetIpv4Header().GetSource() << endl; - return true; + return shouldDrop; } void DropRateErrorModel::SetDropRate(int rate_in) { rate = rate_in; } + +void DropRateErrorModel::SetMaxDropBurst(int burst_in) { + burst = burst_in; +} diff --git a/sim/scenarios/drop-rate/drop-rate-error-model.h b/sim/scenarios/drop-rate/drop-rate-error-model.h index 91c2313..4925d7c 100644 --- a/sim/scenarios/drop-rate/drop-rate-error-model.h +++ b/sim/scenarios/drop-rate/drop-rate-error-model.h @@ -8,16 +8,23 @@ using namespace ns3; // The DropRateErrorModel drops random packets, at a user-specified drop rate. +// But no more than a user-specified number of packets in a row. class DropRateErrorModel : public ErrorModel { public: static TypeId GetTypeId(void); DropRateErrorModel(); void SetDropRate(int perc); + void SetMaxDropBurst(int burst); private: int rate; std::mt19937 *rng; std::uniform_int_distribution<> distr; + int next_rate; + int burst; + int dropped_in_a_row; + int dropped; + int forwarded; bool DoCorrupt (Ptr p); void DoReset(void); diff --git a/sim/scenarios/drop-rate/drop-rate.cc b/sim/scenarios/drop-rate/drop-rate.cc index 0f4497b..2758493 100644 --- a/sim/scenarios/drop-rate/drop-rate.cc +++ b/sim/scenarios/drop-rate/drop-rate.cc @@ -12,7 +12,8 @@ using namespace std; NS_LOG_COMPONENT_DEFINE("ns3 simulator"); int main(int argc, char *argv[]) { - std::string delay, bandwidth, queue, client_rate, server_rate; + std::string delay, bandwidth, queue, client_rate, server_rate, + client_burst, server_burst; std::random_device rand_dev; std::mt19937 generator(rand_dev()); // Seed random number generator first Ptr client_drops = CreateObject(); @@ -24,6 +25,12 @@ int main(int argc, char *argv[]) { cmd.AddValue("queue", "queue size of the p2p link (in packets)", queue); cmd.AddValue("rate_to_client", "packet drop rate (towards client)", client_rate); cmd.AddValue("rate_to_server", "packet drop rate (towards server)", server_rate); + cmd.AddValue("burst_to_client", + "max. packet drop burst length (towards client)", + client_burst); + cmd.AddValue("burst_to_server", + "max. packet drop burst length (towards server)", + server_burst); cmd.Parse (argc, argv); NS_ABORT_MSG_IF(delay.length() == 0, "Missing parameter: delay"); @@ -32,9 +39,13 @@ int main(int argc, char *argv[]) { NS_ABORT_MSG_IF(client_rate.length() == 0, "Missing parameter: rate_to_client"); NS_ABORT_MSG_IF(server_rate.length() == 0, "Missing parameter: rate_to_server"); - // Set client and server drop rates. + // Set client and server drop rates and drop bursts. client_drops->SetDropRate(stoi(client_rate)); + if (client_burst.length() > 0) + client_drops->SetMaxDropBurst(stoi(client_burst)); server_drops->SetDropRate(stoi(server_rate)); + if (server_burst.length() > 0) + server_drops->SetMaxDropBurst(stoi(server_burst)); QuicNetworkSimulatorHelper sim;