traffic-control: Add Nonlinear RED
This commit is contained in:
192
examples/traffic-control/red-vs-nlred.cc
Normal file
192
examples/traffic-control/red-vs-nlred.cc
Normal file
@@ -0,0 +1,192 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 NITK Surathkal
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Phani Kiran S V S <phanikiran.harithas@gmail.com>
|
||||
* Nichit Bodhak Goel <nichit93@gmail.com>
|
||||
* Mohit P. Tahiliani <tahiliani@nitk.edu.in>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/point-to-point-layout-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
uint32_t nLeaf = 10;
|
||||
uint32_t maxPackets = 100;
|
||||
bool modeBytes = false;
|
||||
uint32_t queueDiscLimitPackets = 1000;
|
||||
double minTh = 5;
|
||||
double maxTh = 15;
|
||||
uint32_t pktSize = 512;
|
||||
std::string appDataRate = "10Mbps";
|
||||
std::string queueDiscType = "RED";
|
||||
uint16_t port = 5001;
|
||||
std::string bottleNeckLinkBw = "1Mbps";
|
||||
std::string bottleNeckLinkDelay = "50ms";
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("nLeaf", "Number of left and right side leaf nodes", nLeaf);
|
||||
cmd.AddValue ("maxPackets","Max Packets allowed in the device queue", maxPackets);
|
||||
cmd.AddValue ("queueDiscLimitPackets","Max Packets allowed in the queue disc", queueDiscLimitPackets);
|
||||
cmd.AddValue ("queueDiscType", "Set Queue disc type to RED or NLRED", queueDiscType);
|
||||
cmd.AddValue ("appPktSize", "Set OnOff App Packet Size", pktSize);
|
||||
cmd.AddValue ("appDataRate", "Set OnOff App DataRate", appDataRate);
|
||||
cmd.AddValue ("modeBytes", "Set Queue disc mode to Packets <false> or bytes <true>", modeBytes);
|
||||
|
||||
cmd.AddValue ("redMinTh", "RED queue minimum threshold", minTh);
|
||||
cmd.AddValue ("redMaxTh", "RED queue maximum threshold", maxTh);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
if ((queueDiscType != "RED") && (queueDiscType != "NLRED"))
|
||||
{
|
||||
std::cout << "Invalid queue disc type: Use --queueDiscType=RED or --queueDiscType=NLRED" << std::endl;
|
||||
exit (1);
|
||||
}
|
||||
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (pktSize));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (appDataRate));
|
||||
|
||||
Config::SetDefault ("ns3::QueueBase::Mode", StringValue ("QUEUE_MODE_PACKETS"));
|
||||
Config::SetDefault ("ns3::QueueBase::MaxPackets", UintegerValue (maxPackets));
|
||||
|
||||
if (!modeBytes)
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Mode", StringValue ("QUEUE_DISC_MODE_PACKETS"));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (queueDiscLimitPackets));
|
||||
}
|
||||
else
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Mode", StringValue ("QUEUE_DISC_MODE_BYTES"));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (queueDiscLimitPackets * pktSize));
|
||||
minTh *= pktSize;
|
||||
maxTh *= pktSize;
|
||||
}
|
||||
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (minTh));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (maxTh));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LinkBandwidth", StringValue (bottleNeckLinkBw));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LinkDelay", StringValue (bottleNeckLinkDelay));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (pktSize));
|
||||
|
||||
if (queueDiscType == "NLRED")
|
||||
{
|
||||
// Turn on NLRED
|
||||
Config::SetDefault ("ns3::RedQueueDisc::NLRED", BooleanValue (true));
|
||||
}
|
||||
|
||||
// Create the point-to-point link helpers
|
||||
PointToPointHelper bottleNeckLink;
|
||||
bottleNeckLink.SetDeviceAttribute ("DataRate", StringValue (bottleNeckLinkBw));
|
||||
bottleNeckLink.SetChannelAttribute ("Delay", StringValue (bottleNeckLinkDelay));
|
||||
|
||||
PointToPointHelper pointToPointLeaf;
|
||||
pointToPointLeaf.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
pointToPointLeaf.SetChannelAttribute ("Delay", StringValue ("1ms"));
|
||||
|
||||
PointToPointDumbbellHelper d (nLeaf, pointToPointLeaf,
|
||||
nLeaf, pointToPointLeaf,
|
||||
bottleNeckLink);
|
||||
|
||||
// Install Stack
|
||||
InternetStackHelper stack;
|
||||
for (uint32_t i = 0; i < d.LeftCount (); ++i)
|
||||
{
|
||||
stack.Install (d.GetLeft (i));
|
||||
}
|
||||
for (uint32_t i = 0; i < d.RightCount (); ++i)
|
||||
{
|
||||
stack.Install (d.GetRight (i));
|
||||
}
|
||||
|
||||
stack.Install (d.GetLeft ());
|
||||
stack.Install (d.GetRight ());
|
||||
TrafficControlHelper tchBottleneck;
|
||||
QueueDiscContainer queueDiscs;
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
|
||||
tchBottleneck.Install (d.GetLeft ()->GetDevice (0));
|
||||
queueDiscs = tchBottleneck.Install (d.GetRight ()->GetDevice (0));
|
||||
|
||||
// Assign IP Addresses
|
||||
d.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"),
|
||||
Ipv4AddressHelper ("10.2.1.0", "255.255.255.0"),
|
||||
Ipv4AddressHelper ("10.3.1.0", "255.255.255.0"));
|
||||
|
||||
// Install on/off app on all right side nodes
|
||||
OnOffHelper clientHelper ("ns3::TcpSocketFactory", Address ());
|
||||
clientHelper.SetAttribute ("OnTime", StringValue ("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
|
||||
clientHelper.SetAttribute ("OffTime", StringValue ("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApps;
|
||||
for (uint32_t i = 0; i < d.LeftCount (); ++i)
|
||||
{
|
||||
sinkApps.Add (packetSinkHelper.Install (d.GetLeft (i)));
|
||||
}
|
||||
sinkApps.Start (Seconds (0.0));
|
||||
sinkApps.Stop (Seconds (30.0));
|
||||
|
||||
ApplicationContainer clientApps;
|
||||
for (uint32_t i = 0; i < d.RightCount (); ++i)
|
||||
{
|
||||
// Create an on/off app sending packets to the left side
|
||||
AddressValue remoteAddress (InetSocketAddress (d.GetLeftIpv4Address (i), port));
|
||||
clientHelper.SetAttribute ("Remote", remoteAddress);
|
||||
clientApps.Add (clientHelper.Install (d.GetRight (i)));
|
||||
}
|
||||
clientApps.Start (Seconds (1.0)); // Start 1 second after sink
|
||||
clientApps.Stop (Seconds (15.0)); // Stop before the sink
|
||||
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
|
||||
std::cout << "Running the simulation" << std::endl;
|
||||
Simulator::Run ();
|
||||
|
||||
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
|
||||
|
||||
if (st.unforcedDrop == 0)
|
||||
{
|
||||
std::cout << "There should be some unforced drops" << std::endl;
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be zero drops due to queue full" << std::endl;
|
||||
exit (1);
|
||||
}
|
||||
|
||||
std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl;
|
||||
std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl;
|
||||
std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl;
|
||||
std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl;
|
||||
std::cout << "Destroying the simulation" << std::endl;
|
||||
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
@@ -11,3 +11,6 @@ def build(bld):
|
||||
|
||||
obj = bld.create_ns3_program('red-vs-fengadaptive', ['point-to-point', 'point-to-point-layout', 'internet', 'applications', 'traffic-control'])
|
||||
obj.source = 'red-vs-fengadaptive.cc'
|
||||
|
||||
obj = bld.create_ns3_program('red-vs-nlred', ['point-to-point', 'point-to-point-layout', 'internet', 'applications', 'traffic-control'])
|
||||
obj.source = 'red-vs-nlred.cc'
|
||||
|
||||
@@ -41,6 +41,12 @@ Feng's Adaptive RED is a variant of RED that adapts the maximum drop
|
||||
probability. The model in ns-3 contains implementation of this feature, and is a
|
||||
port of ns-2 Feng's Adaptive RED model.
|
||||
|
||||
Nonlinear Random Early Detection (NLRED)
|
||||
========================================
|
||||
NLRED is a variant of RED in which the linear packet dropping function of
|
||||
RED is replaced by a nonlinear quadratic function. This approach makes packet
|
||||
dropping gentler for light traffic load and aggressive for heavy traffic load.
|
||||
|
||||
Explicit Congestion Notification (ECN)
|
||||
======================================
|
||||
This RED model supports an ECN mode of operation to notify endpoints of
|
||||
@@ -73,6 +79,9 @@ Feng's Adaptive RED queue implementation is based on the algorithm
|
||||
provided in:
|
||||
W. C. Feng et al, http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=752150
|
||||
|
||||
NLRED queue implementation is based on the algorithm provided in:
|
||||
Kaiyu Zhou et al, http://www.sciencedirect.com/science/article/pii/S1389128606000879
|
||||
|
||||
The addition of explicit congestion notification (ECN) to IP:
|
||||
K. K. Ramakrishnan et al, https://tools.ietf.org/html/rfc3168
|
||||
|
||||
@@ -117,6 +126,10 @@ attributes:
|
||||
* FengAlpha (increment parameter for m_curMaxP, Default: 3)
|
||||
* FengBeta (decrement parameter for m_curMaxP, Default: 2)
|
||||
|
||||
The following attribute should be turned on to simulate NLRED queue disc:
|
||||
|
||||
* NLRED (Boolean attribute. Default: false)
|
||||
|
||||
Consult the ns-3 documentation for explanation of these attributes.
|
||||
|
||||
Simulating ARED
|
||||
@@ -161,6 +174,16 @@ set to true, as done in ``examples/traffic-control/red-vs-fengadaptive.cc``:
|
||||
|
||||
Config::SetDefault ("ns3::RedQueueDisc::FengAdaptive", BooleanValue (true));
|
||||
|
||||
Simulating NLRED
|
||||
================
|
||||
|
||||
To switch on NLRED algorithm, the attribute NLRED must be set to true,
|
||||
as shown below:
|
||||
|
||||
.. sourcecode:: cpp
|
||||
|
||||
Config::SetDefault ("ns3::RedQueueDisc::NLRED", BooleanValue (true));
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
@@ -173,6 +196,9 @@ ARED queue examples can be found at:
|
||||
Feng's Adaptive RED example can be found at:
|
||||
``examples/traffic-control/red-vs-fengadaptive.cc``
|
||||
|
||||
NLRED queue example can be found at:
|
||||
``examples/traffic-control/red-vs-nlred.cc``
|
||||
|
||||
Validation
|
||||
**********
|
||||
|
||||
|
||||
@@ -119,6 +119,11 @@ TypeId RedQueueDisc::GetTypeId (void)
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&RedQueueDisc::m_isFengAdaptive),
|
||||
MakeBooleanChecker ())
|
||||
.AddAttribute ("NLRED",
|
||||
"True to enable Nonlinear RED",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&RedQueueDisc::m_isNonlinear),
|
||||
MakeBooleanChecker ())
|
||||
.AddAttribute ("MinTh",
|
||||
"Minimum average length threshold in packets/bytes",
|
||||
DoubleValue (5),
|
||||
@@ -792,6 +797,12 @@ RedQueueDisc::CalculatePNew (double qAvg, double maxTh, bool isGentle, double vA
|
||||
* th_min to th_max
|
||||
*/
|
||||
p = vA * qAvg + vB;
|
||||
|
||||
if (m_isNonlinear)
|
||||
{
|
||||
p *= p * 1.5;
|
||||
}
|
||||
|
||||
p *= maxP;
|
||||
}
|
||||
|
||||
|
||||
@@ -346,6 +346,7 @@ private:
|
||||
double m_beta; //!< Decrement parameter for m_curMaxP in ARED
|
||||
Time m_rtt; //!< Rtt to be considered while automatically setting m_bottom in ARED
|
||||
bool m_isFengAdaptive; //!< True to enable Feng's Adaptive RED
|
||||
bool m_isNonlinear; //!< True to enable Nonlinear RED
|
||||
double m_b; //!< Increment parameter for m_curMaxP in Feng's Adaptive RED
|
||||
double m_a; //!< Decrement parameter for m_curMaxP in Feng's Adaptive RED
|
||||
bool m_isNs1Compat; //!< Ns-1 compatibility
|
||||
|
||||
@@ -239,6 +239,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
|
||||
uint32_t test7;
|
||||
uint32_t test11;
|
||||
uint32_t test12;
|
||||
uint32_t test13;
|
||||
uint32_t test14;
|
||||
} drop;
|
||||
|
||||
|
||||
@@ -473,6 +475,59 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
drop.test12 = st.unforcedDrop;
|
||||
NS_TEST_EXPECT_MSG_LT (drop.test12, drop.test11, "Test 12 should have less drops due to probability mark than test 11");
|
||||
|
||||
|
||||
// test 11: RED with Linear drop probability
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
minTh = 30 * modeSize;
|
||||
maxTh = 90 * modeSize;
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
|
||||
"Verify that we can actually set the attribute Mode");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
|
||||
"Verify that we can actually set the attribute MinTh");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
|
||||
"Verify that we can actually set the attribute MaxTh");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
|
||||
"Verify that we can actually set the attribute QueueLimit");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
|
||||
"Verify that we can actually set the attribute LInterm");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
|
||||
"Verify that we can actually set the attribute Gentle");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300, false);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
drop.test13 = st.unforcedDrop;
|
||||
NS_TEST_EXPECT_MSG_NE (drop.test13, 0, "There should some dropped packets due to probability mark");
|
||||
|
||||
|
||||
// test 14: RED with Nonlinear drop probability
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
minTh = 30 * modeSize;
|
||||
maxTh = 90 * modeSize;
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
|
||||
"Verify that we can actually set the attribute Mode");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
|
||||
"Verify that we can actually set the attribute MinTh");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
|
||||
"Verify that we can actually set the attribute MaxTh");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
|
||||
"Verify that we can actually set the attribute QueueLimit");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
|
||||
"Verify that we can actually set the attribute LInterm");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
|
||||
"Verify that we can actually set the attribute Gentle");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("NLRED", BooleanValue (true)), true,
|
||||
"Verify that we can actually set the attribute NLRED");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300, false);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
drop.test14 = st.unforcedDrop;
|
||||
NS_TEST_EXPECT_MSG_LT (drop.test14, drop.test13, "Test 14 should have less drops due to probability mark than test 13");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user