Skip to content

Commit c4fbfe6

Browse files
squidarthSidharth Shanker
authored andcommitted
Add RED AQM.
Enforce & require the Red packet queue to have packet_limit.
1 parent 7af3475 commit c4fbfe6

File tree

6 files changed

+156
-7
lines changed

6 files changed

+156
-7
lines changed

src/frontend/linkshell.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "drop_head_packet_queue.hh"
88
#include "codel_packet_queue.hh"
99
#include "pie_packet_queue.hh"
10+
#include "red_packet_queue.hh"
1011
#include "link_queue.hh"
1112
#include "packetshell.cc"
1213

@@ -44,6 +45,8 @@ unique_ptr<AbstractPacketQueue> get_packet_queue( const string & type, const str
4445
return unique_ptr<AbstractPacketQueue>( new CODELPacketQueue( args ) );
4546
} else if ( type == "pie" ) {
4647
return unique_ptr<AbstractPacketQueue>( new PIEPacketQueue( args ) );
48+
} else if ( type == "red" ) {
49+
return unique_ptr<AbstractPacketQueue>( new REDPacketQueue( args ) );
4750
} else {
4851
cerr << "Unknown queue type: " << type << endl;
4952
}
@@ -96,7 +99,7 @@ int main( int argc, char *argv[] )
9699
{ "meter-downlink-delay", no_argument, nullptr, 'y' },
97100
{ "meter-all", no_argument, nullptr, 'z' },
98101
{ "uplink-queue", required_argument, nullptr, 'q' },
99-
{ "downlink-queue", required_argument, nullptr, 'w' },
102+
{ "downlink-queue", required_argument, nullptr, 'w' },
100103
{ "uplink-queue-args", required_argument, nullptr, 'a' },
101104
{ "downlink-queue-args", required_argument, nullptr, 'b' },
102105
{ 0, 0, nullptr, 0 }

src/packet/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ libpacket_a_SOURCES = packetshell.hh packetshell.cc queued_packet.hh \
77
abstract_packet_queue.hh dropping_packet_queue.hh dropping_packet_queue.cc infinite_packet_queue.hh \
88
drop_tail_packet_queue.hh drop_head_packet_queue.hh \
99
codel_packet_queue.cc codel_packet_queue.hh \
10+
red_packet_queue.cc red_packet_queue.hh \
1011
pie_packet_queue.cc pie_packet_queue.hh \
1112
bindworkaround.hh

src/packet/dropping_packet_queue.cc

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ string DroppingPacketQueue::to_string( void ) const
9999
return ret;
100100
}
101101

102-
unsigned int DroppingPacketQueue::get_arg( const string & args, const string & name )
102+
string DroppingPacketQueue::parse_number_arg(const string & args, const string & name, bool isfloat)
103103
{
104104
auto offset = args.find( name );
105105
if ( offset == string::npos ) {
106-
return 0; /* default value */
106+
return ""; /* default value */
107107
} else {
108108
/* extract the value */
109109

@@ -118,15 +118,46 @@ unsigned int DroppingPacketQueue::get_arg( const string & args, const string & n
118118
/* advance by length of "=" */
119119
offset++;
120120

121-
/* find the first non-digit character */
122-
auto offset2 = args.substr( offset ).find_first_not_of( "0123456789" );
121+
/* find the first non-valid character */
122+
string validchars;
123+
if (isfloat) {
124+
validchars = "0123456789.";
125+
} else {
126+
validchars = "0123456789";
127+
}
128+
auto offset2 = args.substr( offset ).find_first_not_of( validchars );
123129

124130
auto digit_string = args.substr( offset ).substr( 0, offset2 );
125131

126132
if ( digit_string.empty() ) {
127133
throw runtime_error( "could not parse queue arguments: " + args );
128134
}
135+
return digit_string;
136+
}
137+
}
138+
139+
unsigned int DroppingPacketQueue::get_arg( const string & args, const string & name)
140+
{
141+
auto offset = args.find( name );
142+
if ( offset == string::npos ) {
143+
return 0; /* default value */
144+
} else {
145+
auto digit_string = parse_number_arg(args, name, false);
129146

130147
return myatoi( digit_string );
131148
}
132149
}
150+
151+
double DroppingPacketQueue::get_float_arg( const string & args, const string & name)
152+
{
153+
auto offset = args.find( name );
154+
if ( offset == string::npos ) {
155+
return 0; /* default value */
156+
} else {
157+
auto digit_string = parse_number_arg(args, name, true);
158+
return myatof( digit_string );
159+
}
160+
161+
}
162+
163+

src/packet/dropping_packet_queue.hh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,13 @@ public:
4141

4242
std::string to_string( void ) const override;
4343

44-
static unsigned int get_arg( const std::string & args, const std::string & name );
45-
44+
static std::string parse_number_arg(const std::string & args, const std::string & name, bool isfloat);
4645
unsigned int size_bytes( void ) const override;
4746
unsigned int size_packets( void ) const override;
47+
48+
static unsigned int get_arg( const std::string & args, const std::string & name );
49+
50+
static double get_float_arg( const std::string & args, const std::string & name );
4851
};
4952

5053
#endif /* DROPPING_PACKET_QUEUE_HH */

src/packet/red_packet_queue.cc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "red_packet_queue.hh"
2+
#include <algorithm>
3+
#include "timestamp.hh"
4+
5+
using namespace std;
6+
7+
REDPacketQueue::REDPacketQueue( const string & args)
8+
: DroppingPacketQueue(args),
9+
wq_(get_float_arg(args, "wq")),
10+
min_thresh_(get_float_arg(args, "minthresh")),
11+
max_thresh_(get_float_arg(args, "maxthresh")),
12+
time_at_zero_q_(0)
13+
{
14+
if (packet_limit_ == 0) {
15+
throw runtime_error( "RED queue must have packet limit." );
16+
}
17+
18+
if ( wq_ == 0.0 || min_thresh_ == 0.0 || max_thresh_ == 0.0 ) {
19+
throw runtime_error( "RED queue must have wq, minthresh, and maxthresh arguments." );
20+
}
21+
22+
}
23+
24+
QueuedPacket REDPacketQueue::dequeue( void )
25+
{
26+
auto packet = DroppingPacketQueue::dequeue();
27+
if (size_packets() == 0) {
28+
time_at_zero_q_ = timestamp();
29+
}
30+
31+
return packet;
32+
}
33+
34+
void REDPacketQueue::enqueue( QueuedPacket && p )
35+
{
36+
int s = 4;
37+
auto instantaneous_queue_size = size_packets();
38+
39+
/* If the queue is empty, decay the weighted average by
40+
* the amount of time that the queue has been
41+
* empty. */
42+
if (size_packets() == 0) {
43+
weighted_average_ = powf((1 - wq_), (timestamp() - time_at_zero_q_)/s) * weighted_average_;
44+
} else {
45+
weighted_average_ = (instantaneous_queue_size * wq_ ) + (1- wq_) * weighted_average_;
46+
}
47+
48+
auto ratio = (weighted_average_)/packet_limit_;
49+
std::default_random_engine generator (0);
50+
std::uniform_real_distribution<double> distribution (min_thresh_, max_thresh_);
51+
double threshold = distribution(generator);
52+
if (ratio > max_thresh_) {
53+
ratio = 1;
54+
}
55+
if (ratio < min_thresh_) {
56+
ratio = 0;
57+
}
58+
59+
if ( (threshold > ratio) && good_with( size_bytes() + p.contents.size(),
60+
size_packets() + 1 ) ) {
61+
accept( std::move( p ) );
62+
}
63+
64+
assert( good() );
65+
}

src/packet/red_packet_queue.hh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* -*-mode:c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
#ifndef RED_PACKET_QUEUE_HH
4+
#define RED_PACKET_QUEUE_HH
5+
6+
#include <string>
7+
#include "util.hh"
8+
#include <iostream>
9+
10+
#include <fstream>
11+
#include <memory>
12+
#include <deque>
13+
#include <random>
14+
#include "dropping_packet_queue.hh"
15+
16+
/*
17+
Random Early Detection (RED) AQM Implementation.
18+
See section 3 of https://tools.ietf.org/html/rfc2309#ref-Jacobson88
19+
for a description of the queuing discipline.
20+
j
21+
22+
*/
23+
class REDPacketQueue : public DroppingPacketQueue
24+
{
25+
private:
26+
//Configuration parameters
27+
const static unsigned int PACKET_SIZE = 1504;
28+
double wq_, min_thresh_, max_thresh_;
29+
uint64_t time_at_zero_q_;
30+
31+
const std::string & type( void ) const override
32+
{
33+
static const std::string type_ { "red" };
34+
return type_;
35+
}
36+
37+
double weighted_average_ = 0;
38+
unsigned int max_queue_depth_packets() const;
39+
40+
public:
41+
REDPacketQueue( const std::string & args );
42+
QueuedPacket dequeue( void ) override;
43+
void enqueue( QueuedPacket && p ) override;
44+
};
45+
46+
#endif

0 commit comments

Comments
 (0)