Skip to content

Commit

Permalink
Add burst parameter to DropRateErrorModel (#134)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
larseggert authored Aug 27, 2024
1 parent cba6bba commit de21ef0
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 12 deletions.
11 changes: 9 additions & 2 deletions sim/scenarios/drop-rate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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"
```
50 changes: 42 additions & 8 deletions sim/scenarios/drop-rate/drop-rate-error-model.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <iomanip>

#include "../helper/quic-packet.h"
#include "drop-rate-error-model.h"

Expand All @@ -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<Packet> 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;
}
7 changes: 7 additions & 0 deletions sim/scenarios/drop-rate/drop-rate-error-model.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Packet> p);
void DoReset(void);
Expand Down
15 changes: 13 additions & 2 deletions sim/scenarios/drop-rate/drop-rate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<DropRateErrorModel> client_drops = CreateObject<DropRateErrorModel>();
Expand All @@ -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");
Expand All @@ -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;

Expand Down

0 comments on commit de21ef0

Please sign in to comment.