Skip to content

Commit 5530f3c

Browse files
committed
Add RED AQM.
1 parent 2ba9a92 commit 5530f3c

File tree

6 files changed

+137
-6
lines changed

6 files changed

+137
-6
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,8 +99,8 @@ 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' },
100102
{ "uplink-queue-args", required_argument, nullptr, 'a' },
103+
{ "downlink-queue", required_argument, nullptr, 'w' },
101104
{ "downlink-queue-args", required_argument, nullptr, 'b' },
102105
{ 0, 0, nullptr, 0 }
103106
};

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: 36 additions & 5 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

@@ -112,21 +112,52 @@ unsigned int DroppingPacketQueue::get_arg( const string & args, const string & n
112112

113113
/* make sure next char is "=" */
114114
if ( args.substr( offset, 1 ) != "=" ) {
115-
throw runtime_error( "could not parse queue arguments: " + args );
115+
throw runtime_error( "could not parse queue arguments: " + args);
116116
}
117117

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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ public:
4444

4545
std::string to_string( void ) const override;
4646

47+
static std::string parse_number_arg(const std::string & args, const std::string & name, bool isfloat);
4748
static unsigned int get_arg( const std::string & args, const std::string & name );
49+
static double get_float_arg( const std::string & args, const std::string & name );
4850
};
4951

5052
#endif /* DROPPING_PACKET_QUEUE_HH */

src/packet/red_packet_queue.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "red_packet_queue.hh"
2+
#include <algorithm>
3+
4+
using namespace std;
5+
6+
REDPacketQueue::REDPacketQueue( const string & args)
7+
: DroppingPacketQueue(args),
8+
wq_(get_float_arg(args, "wq")),
9+
min_thresh_(get_float_arg(args, "minthresh")),
10+
max_thresh_(get_float_arg(args, "maxthresh"))
11+
{
12+
if ( wq_ == 0.0 || min_thresh_ == 0.0 || max_thresh_ == 0.0 ) {
13+
throw runtime_error( "RED queue must have wq, minthresh, and maxthresh arguments." );
14+
}
15+
16+
}
17+
18+
unsigned int REDPacketQueue::max_queue_depth_packets (void ) const {
19+
if (packet_limit_) {
20+
return packet_limit_;
21+
} else if (byte_limit_ ) {
22+
return byte_limit_ / PACKET_SIZE;
23+
} else {
24+
throw runtime_error( "No queue limit provided");
25+
}
26+
}
27+
28+
void REDPacketQueue::enqueue( QueuedPacket && p )
29+
{
30+
auto instantaneous_queue_size = size_packets();
31+
auto ratio = (weighted_average_)/max_queue_depth_packets();
32+
std::default_random_engine generator (0);
33+
std::uniform_real_distribution<double> distribution (min_thresh_, max_thresh_);
34+
double threshold = distribution(generator);
35+
if (ratio > max_thresh_) {
36+
ratio = 1;
37+
}
38+
if (ratio < min_thresh_) {
39+
ratio = 0;
40+
}
41+
42+
if ( (threshold > ratio) && good_with( size_bytes() + p.contents.size(),
43+
size_packets() + 1 ) ) {
44+
accept( std::move( p ) );
45+
}
46+
47+
weighted_average_ = (instantaneous_queue_size * wq_ ) + (1- wq_) * weighted_average_;
48+
49+
assert( good() );
50+
}

src/packet/red_packet_queue.hh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
30+
const std::string & type( void ) const override
31+
{
32+
static const std::string type_ { "red" };
33+
return type_;
34+
}
35+
36+
double weighted_average_ = 0;
37+
unsigned int max_queue_depth_packets() const;
38+
39+
public:
40+
REDPacketQueue( const std::string & args );
41+
void enqueue( QueuedPacket && p ) override;
42+
};
43+
44+
#endif

0 commit comments

Comments
 (0)