traffic-control: Add ARED test and examples
This commit is contained in:
703
src/traffic-control/examples/adaptive-red-tests.cc
Normal file
703
src/traffic-control/examples/adaptive-red-tests.cc
Normal file
@@ -0,0 +1,703 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 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
|
||||
*
|
||||
* Author: Mohit P. Tahiliani <tahiliani@nitk.edu.in>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* NOTE: These validation tests are same as provided in ns-2
|
||||
* (ns/tcl/test/test-suite-adaptive-red.tcl)
|
||||
*
|
||||
* In this code, tests 1, 2, 6, 7, 8, 9, 10, 12, 13, 14 and 15 refer to tests
|
||||
* named red1, red1Adapt, fastlink, fastlinkAutowq, fastlinkAutothresh,
|
||||
* fastlinkAdaptive, fastlinkAllAdapt, fastlinkAllAdapt1, longlink,
|
||||
* longlinkAdapt and longlinkAdapt1, respectively in the ns-2 file
|
||||
* mentioned above.
|
||||
*/
|
||||
|
||||
/** Network topology for tests: 1 and 2
|
||||
*
|
||||
* 10Mb/s, 2ms 10Mb/s, 4ms
|
||||
* n0--------------| |---------------n4
|
||||
* | 1.5Mbps, 20ms |
|
||||
* n2------------------n3
|
||||
* 10Mb/s, 3ms | QueueLimit = 25 | 10Mb/s, 5ms
|
||||
* n1--------------| |---------------n5
|
||||
*
|
||||
*/
|
||||
|
||||
/** Network topology for tests: 6, 7, 8, 9, 10 and 12
|
||||
*
|
||||
* 100Mb/s, 2ms 100Mb/s, 4ms
|
||||
* n0--------------| |---------------n4
|
||||
* | 15Mbps, 20ms |
|
||||
* n2------------------n3
|
||||
* 100Mb/s, 3ms | QueueLimit = 1000 | 100Mb/s, 5ms
|
||||
* n1--------------| |---------------n5
|
||||
*
|
||||
*/
|
||||
|
||||
/** Network topology for tests: 13, 14 and 15
|
||||
*
|
||||
* 10Mb/s, 0ms 10Mb/s, 2ms
|
||||
* n0--------------| |---------------n4
|
||||
* | 1.5Mbps, 100ms |
|
||||
* n2------------------n3
|
||||
* 10Mb/s, 1ms | QueueLimit = 100 | 10Mb/s, 3ms
|
||||
* n1--------------| |---------------n5
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/flow-monitor-helper.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("AdaptiveRedTests");
|
||||
|
||||
uint32_t checkTimes;
|
||||
double avgQueueDiscSize;
|
||||
|
||||
// The times
|
||||
double global_start_time;
|
||||
double global_stop_time;
|
||||
double sink_start_time;
|
||||
double sink_stop_time;
|
||||
double client_start_time;
|
||||
double client_stop_time;
|
||||
|
||||
NodeContainer n0n2;
|
||||
NodeContainer n1n2;
|
||||
NodeContainer n2n3;
|
||||
NodeContainer n3n4;
|
||||
NodeContainer n3n5;
|
||||
|
||||
Ipv4InterfaceContainer i0i2;
|
||||
Ipv4InterfaceContainer i1i2;
|
||||
Ipv4InterfaceContainer i2i3;
|
||||
Ipv4InterfaceContainer i3i4;
|
||||
Ipv4InterfaceContainer i3i5;
|
||||
|
||||
std::stringstream filePlotQueueDisc;
|
||||
std::stringstream filePlotQueueDiscAvg;
|
||||
|
||||
void
|
||||
CheckQueueDiscSize (Ptr<QueueDisc> queue)
|
||||
{
|
||||
uint32_t qSize = StaticCast<RedQueueDisc> (queue)->GetQueueSize ();
|
||||
|
||||
avgQueueDiscSize += qSize;
|
||||
checkTimes++;
|
||||
|
||||
// check queue disc size every 1/100 of a second
|
||||
Simulator::Schedule (Seconds (0.01), &CheckQueueDiscSize, queue);
|
||||
|
||||
std::ofstream fPlotQueueDisc (filePlotQueueDisc.str ().c_str (), std::ios::out | std::ios::app);
|
||||
fPlotQueueDisc << Simulator::Now ().GetSeconds () << " " << qSize << std::endl;
|
||||
fPlotQueueDisc.close ();
|
||||
|
||||
std::ofstream fPlotQueueDiscAvg (filePlotQueueDiscAvg.str ().c_str (), std::ios::out | std::ios::app);
|
||||
fPlotQueueDiscAvg << Simulator::Now ().GetSeconds () << " " << avgQueueDiscSize / checkTimes << std::endl;
|
||||
fPlotQueueDiscAvg.close ();
|
||||
}
|
||||
|
||||
void
|
||||
BuildAppsTest (uint32_t test)
|
||||
{
|
||||
// SINK is in the right side
|
||||
uint16_t port = 50000;
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (n3n4.Get (1));
|
||||
sinkApp.Start (Seconds (sink_start_time));
|
||||
sinkApp.Stop (Seconds (sink_stop_time));
|
||||
|
||||
// Connection one
|
||||
// Clients are in left side
|
||||
/*
|
||||
* Create the OnOff applications to send TCP to the server
|
||||
* onoffhelper is a client that send data to TCP destination
|
||||
*/
|
||||
OnOffHelper clientHelper1 ("ns3::TcpSocketFactory", Address ());
|
||||
clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000));
|
||||
|
||||
// Connection two
|
||||
OnOffHelper clientHelper2 ("ns3::TcpSocketFactory", Address ());
|
||||
clientHelper2.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper2.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
clientHelper2.SetAttribute ("PacketSize", UintegerValue (1000));
|
||||
|
||||
if (test == 6 || test == 7 || test == 8 || test == 9 || test == 10 || test == 12)
|
||||
{
|
||||
clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("100Mb/s")));
|
||||
clientHelper2.SetAttribute ("DataRate", DataRateValue (DataRate ("100Mb/s")));
|
||||
}
|
||||
else
|
||||
{
|
||||
clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("10Mb/s")));
|
||||
clientHelper2.SetAttribute ("DataRate", DataRateValue (DataRate ("10Mb/s")));
|
||||
}
|
||||
|
||||
ApplicationContainer clientApps1;
|
||||
AddressValue remoteAddress (InetSocketAddress (i3i4.GetAddress (1), port));
|
||||
clientHelper1.SetAttribute ("Remote", remoteAddress);
|
||||
clientApps1.Add (clientHelper1.Install (n0n2.Get (0)));
|
||||
clientApps1.Start (Seconds (client_start_time));
|
||||
clientApps1.Stop (Seconds (client_stop_time));
|
||||
|
||||
ApplicationContainer clientApps2;
|
||||
clientHelper2.SetAttribute ("Remote", remoteAddress);
|
||||
clientApps2.Add (clientHelper2.Install (n1n2.Get (0)));
|
||||
clientApps2.Start (Seconds (client_start_time));
|
||||
clientApps2.Stop (Seconds (client_stop_time));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
LogComponentEnable ("RedQueueDisc", LOG_LEVEL_INFO);
|
||||
|
||||
uint32_t aredTest;
|
||||
std::string aredLinkDataRate = "1.5Mbps";
|
||||
std::string aredLinkDelay = "20ms";
|
||||
|
||||
std::string pathOut;
|
||||
bool writeForPlot = false;
|
||||
bool writePcap = false;
|
||||
bool flowMonitor = false;
|
||||
|
||||
bool printAredStats = true;
|
||||
|
||||
global_start_time = 0.0;
|
||||
sink_start_time = global_start_time;
|
||||
client_start_time = global_start_time + 1.5;
|
||||
global_stop_time = 7.0;
|
||||
sink_stop_time = global_stop_time + 3.0;
|
||||
client_stop_time = global_stop_time - 2.0;
|
||||
|
||||
// Configuration and command line parameter parsing
|
||||
aredTest = 1;
|
||||
// Will only save in the directory if enable opts below
|
||||
pathOut = "."; // Current directory
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("testNumber", "Run test 1, 2, 6, 7, 8, 9, 10, 12, 13, 14 or 15", aredTest);
|
||||
cmd.AddValue ("pathOut", "Path to save results from --writeForPlot/--writePcap/--writeFlowMonitor", pathOut);
|
||||
cmd.AddValue ("writeForPlot", "<0/1> to write results for plot (gnuplot)", writeForPlot);
|
||||
cmd.AddValue ("writePcap", "<0/1> to write results in pcapfile", writePcap);
|
||||
cmd.AddValue ("writeFlowMonitor", "<0/1> to enable Flow Monitor and write their results", flowMonitor);
|
||||
|
||||
cmd.Parse (argc, argv);
|
||||
if ( (aredTest != 1) && (aredTest != 2) && (aredTest != 6) && (aredTest != 7) && (aredTest != 8) && (aredTest != 9) && (aredTest != 10) && (aredTest != 12) && (aredTest != 13) && (aredTest != 14) && (aredTest != 15) )
|
||||
{
|
||||
std::cout << "Invalid test number. Supported tests are 1, 2, 6, 7, 8, 9, 10, 12, 13, 14 or 15" << std::endl;
|
||||
exit (1);
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Create nodes");
|
||||
NodeContainer c;
|
||||
c.Create (6);
|
||||
Names::Add ( "N0", c.Get (0));
|
||||
Names::Add ( "N1", c.Get (1));
|
||||
Names::Add ( "N2", c.Get (2));
|
||||
Names::Add ( "N3", c.Get (3));
|
||||
Names::Add ( "N4", c.Get (4));
|
||||
Names::Add ( "N5", c.Get (5));
|
||||
n0n2 = NodeContainer (c.Get (0), c.Get (2));
|
||||
n1n2 = NodeContainer (c.Get (1), c.Get (2));
|
||||
n2n3 = NodeContainer (c.Get (2), c.Get (3));
|
||||
n3n4 = NodeContainer (c.Get (3), c.Get (4));
|
||||
n3n5 = NodeContainer (c.Get (3), c.Get (5));
|
||||
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::TcpNewReno"));
|
||||
// 42 = headers size
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000 - 42));
|
||||
Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1));
|
||||
GlobalValue::Bind ("ChecksumEnabled", BooleanValue (false));
|
||||
|
||||
uint32_t meanPktSize = 1000;
|
||||
|
||||
// RED params
|
||||
NS_LOG_INFO ("Set RED params");
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Mode", StringValue ("QUEUE_MODE_PACKETS"));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (meanPktSize));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Wait", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Gentle", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (0.002));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (5));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (15));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (1000));
|
||||
|
||||
if (aredTest == 1) // test 1: red1
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (25));
|
||||
}
|
||||
else if (aredTest == 2) // test 2: red1Adapt
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (25));
|
||||
}
|
||||
else if (aredTest == 7) // test 7: fastlinkAutowq
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (0.0));
|
||||
}
|
||||
else if (aredTest == 8) // test 8: fastlinkAutothresh
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (0));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (0));
|
||||
}
|
||||
else if (aredTest == 9) // test 9: fastlinkAdaptive
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::AdaptMaxP", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10));
|
||||
}
|
||||
else if (aredTest == 10) // test 10: fastlinkAllAdapt
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10));
|
||||
}
|
||||
else if (aredTest == 12) // test 12: fastlinkAllAdapt1
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::TargetDelay", TimeValue (Seconds (0.2)));
|
||||
}
|
||||
else if (aredTest == 13) // test 13: longlink
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (100));
|
||||
}
|
||||
else if (aredTest == 14) // test 14: longlinkAdapt
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (100));
|
||||
}
|
||||
else if (aredTest == 15) // test 15: longlinkAdapt1
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (-1.0));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (0));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (0));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::AdaptMaxP", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (100));
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Install internet stack on all nodes.");
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
TrafficControlHelper tchPfifo;
|
||||
uint16_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc");
|
||||
tchPfifo.AddInternalQueues (handle, 3, "ns3::DropTailQueue", "MaxPackets", UintegerValue (1000));
|
||||
tchPfifo.AddPacketFilter (handle, "ns3::PfifoFastIpv4PacketFilter");
|
||||
|
||||
TrafficControlHelper tchRed;
|
||||
tchRed.SetRootQueueDisc ("ns3::RedQueueDisc", "LinkBandwidth", StringValue (aredLinkDataRate),
|
||||
"LinkDelay", StringValue (aredLinkDelay));
|
||||
|
||||
NS_LOG_INFO ("Create channels");
|
||||
PointToPointHelper p2p;
|
||||
|
||||
NetDeviceContainer devn0n2;
|
||||
NetDeviceContainer devn1n2;
|
||||
NetDeviceContainer devn2n3;
|
||||
NetDeviceContainer devn3n4;
|
||||
NetDeviceContainer devn3n5;
|
||||
|
||||
QueueDiscContainer queueDiscs;
|
||||
|
||||
if (aredTest == 1 || aredTest == 2)
|
||||
{
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
devn0n2 = p2p.Install (n0n2);
|
||||
tchPfifo.Install (devn0n2);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("3ms"));
|
||||
devn1n2 = p2p.Install (n1n2);
|
||||
tchPfifo.Install (devn1n2);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue (aredLinkDataRate));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue (aredLinkDelay));
|
||||
devn2n3 = p2p.Install (n2n3);
|
||||
// only backbone link has ARED queue disc
|
||||
queueDiscs = tchRed.Install (devn2n3);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("4ms"));
|
||||
devn3n4 = p2p.Install (n3n4);
|
||||
tchPfifo.Install (devn3n4);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("5ms"));
|
||||
devn3n5 = p2p.Install (n3n5);
|
||||
tchPfifo.Install (devn3n5);
|
||||
}
|
||||
else if (aredTest == 13 || aredTest == 14 || aredTest == 15)
|
||||
{
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("0ms"));
|
||||
devn0n2 = p2p.Install (n0n2);
|
||||
tchPfifo.Install (devn0n2);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("1ms"));
|
||||
devn1n2 = p2p.Install (n1n2);
|
||||
tchPfifo.Install (devn1n2);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue (aredLinkDataRate));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("100ms"));
|
||||
devn2n3 = p2p.Install (n2n3);
|
||||
// only backbone link has ARED queue disc
|
||||
queueDiscs = tchRed.Install (devn2n3);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
devn3n4 = p2p.Install (n3n4);
|
||||
tchPfifo.Install (devn3n4);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("3ms"));
|
||||
devn3n5 = p2p.Install (n3n5);
|
||||
tchPfifo.Install (devn3n5);
|
||||
}
|
||||
else if (aredTest == 6 || aredTest == 7 || aredTest == 8 || aredTest == 9 || aredTest == 10 || aredTest == 12)
|
||||
{
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
devn0n2 = p2p.Install (n0n2);
|
||||
tchPfifo.Install (devn0n2);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("3ms"));
|
||||
devn1n2 = p2p.Install (n1n2);
|
||||
tchPfifo.Install (devn1n2);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("15Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue (aredLinkDelay));
|
||||
devn2n3 = p2p.Install (n2n3);
|
||||
// only backbone link has ARED queue disc
|
||||
queueDiscs = tchRed.Install (devn2n3);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("4ms"));
|
||||
devn3n4 = p2p.Install (n3n4);
|
||||
tchPfifo.Install (devn3n4);
|
||||
|
||||
p2p.SetQueue ("ns3::DropTailQueue");
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("5ms"));
|
||||
devn3n5 = p2p.Install (n3n5);
|
||||
tchPfifo.Install (devn3n5);
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Assign IP Addresses");
|
||||
Ipv4AddressHelper ipv4;
|
||||
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
i0i2 = ipv4.Assign (devn0n2);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
i1i2 = ipv4.Assign (devn1n2);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
i2i3 = ipv4.Assign (devn2n3);
|
||||
|
||||
ipv4.SetBase ("10.1.4.0", "255.255.255.0");
|
||||
i3i4 = ipv4.Assign (devn3n4);
|
||||
|
||||
ipv4.SetBase ("10.1.5.0", "255.255.255.0");
|
||||
i3i5 = ipv4.Assign (devn3n5);
|
||||
|
||||
// Set up the routing
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
|
||||
BuildAppsTest (aredTest);
|
||||
|
||||
if (writePcap)
|
||||
{
|
||||
PointToPointHelper ptp;
|
||||
std::stringstream stmp;
|
||||
stmp << pathOut << "/ared";
|
||||
ptp.EnablePcapAll (stmp.str ().c_str ());
|
||||
}
|
||||
|
||||
Ptr<FlowMonitor> flowmon;
|
||||
if (flowMonitor)
|
||||
{
|
||||
FlowMonitorHelper flowmonHelper;
|
||||
flowmon = flowmonHelper.InstallAll ();
|
||||
}
|
||||
|
||||
if (writeForPlot)
|
||||
{
|
||||
filePlotQueueDisc << pathOut << "/" << "ared-queue-disc.plotme";
|
||||
filePlotQueueDiscAvg << pathOut << "/" << "ared-queue-disc_avg.plotme";
|
||||
|
||||
remove (filePlotQueueDisc.str ().c_str ());
|
||||
remove (filePlotQueueDiscAvg.str ().c_str ());
|
||||
Ptr<QueueDisc> queue = queueDiscs.Get (0);
|
||||
Simulator::ScheduleNow (&CheckQueueDiscSize, queue);
|
||||
}
|
||||
|
||||
Simulator::Stop (Seconds (sink_stop_time));
|
||||
Simulator::Run ();
|
||||
|
||||
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
|
||||
|
||||
if (aredTest == 1)
|
||||
{
|
||||
if (st.unforcedDrop > 2)
|
||||
{
|
||||
std::cout << "Drops due to prob mark should be around 1" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 137 || st.forcedDrop > 139)
|
||||
{
|
||||
std::cout << "Drops due to hard mark not in expected range, should be around 138" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop < 137 || st.qLimDrop > 139)
|
||||
{
|
||||
std::cout << "Drops due to queue full not in expected range, should be around 138" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 2)
|
||||
{
|
||||
if (st.unforcedDrop < 6 || st.unforcedDrop > 17)
|
||||
{
|
||||
std::cout << "Drops due to prob mark not in expected range, should be around 14" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 122 || st.forcedDrop > 133)
|
||||
{
|
||||
std::cout << "Drops due to hard mark not in expected range, should be around 126" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop < 122 || st.qLimDrop > 133)
|
||||
{
|
||||
std::cout << "Drops due to queue full not in expected range, should be around 126" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 6)
|
||||
{
|
||||
if (st.unforcedDrop < 32 || st.unforcedDrop > 56)
|
||||
{
|
||||
std::cout << "Drops due to prob mark not in expected range, should be around 48" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 185 || st.forcedDrop > 202)
|
||||
{
|
||||
std::cout << "Drops due to hard mark not in expected range, should be around 201" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 7)
|
||||
{
|
||||
if (st.unforcedDrop < 76 || st.unforcedDrop > 119)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 110" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 133 || st.forcedDrop > 138)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 137" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 8)
|
||||
{
|
||||
if (st.unforcedDrop < 32 || st.unforcedDrop > 56)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 48" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 185 || st.forcedDrop > 202)
|
||||
{
|
||||
std::cout << "Drops due to hard mark not in expected range, should be around 201" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 9)
|
||||
{
|
||||
if (st.unforcedDrop < 38 || st.unforcedDrop > 69)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 61" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 178 || st.forcedDrop > 191)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 187" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 10)
|
||||
{
|
||||
if (st.unforcedDrop < 82 || st.unforcedDrop > 185)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 89" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 129 || st.forcedDrop > 133)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 129" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 12)
|
||||
{
|
||||
if (st.unforcedDrop < 162 || st.unforcedDrop > 204)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 181" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop > 43)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 12" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 13)
|
||||
{
|
||||
if (st.unforcedDrop < 30 || st.unforcedDrop > 49)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 36" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 240 || st.forcedDrop > 259)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 253" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop < 12 || st.qLimDrop > 31)
|
||||
{
|
||||
std::cout << "Number of drops due to queue full is not in expected range, should be around 25" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 14)
|
||||
{
|
||||
if (st.unforcedDrop < 83 || st.unforcedDrop > 90)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 88" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 127 || st.forcedDrop > 132)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 129" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else if (aredTest == 15)
|
||||
{
|
||||
if (st.unforcedDrop < 83 || st.unforcedDrop > 90)
|
||||
{
|
||||
std::cout << "Number of drops due to prob mark is not in expected range, should be around 88" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.forcedDrop < 127 || st.forcedDrop > 132)
|
||||
{
|
||||
std::cout << "Number of drops due to hard mark is not in expected range, should be around 129" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (st.qLimDrop != 0)
|
||||
{
|
||||
std::cout << "There should be no drops due to queue full" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (flowMonitor)
|
||||
{
|
||||
std::stringstream stmp;
|
||||
stmp << pathOut << "/ared.flowmon";
|
||||
|
||||
flowmon->SerializeToXmlFile (stmp.str ().c_str (), false, false);
|
||||
}
|
||||
|
||||
if (printAredStats)
|
||||
{
|
||||
std::cout << "*** ARED stats from Node 2 queue ***" << 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;
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
244
src/traffic-control/examples/red-vs-ared.cc
Normal file
244
src/traffic-control/examples/red-vs-ared.cc
Normal file
@@ -0,0 +1,244 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 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
|
||||
*
|
||||
* Author: 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 ARED", 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 != "ARED"))
|
||||
{
|
||||
std::cout << "Invalid queue disc type: Use --queueDiscType=RED or --queueDiscType=ARED" << std::endl;
|
||||
exit (1);
|
||||
}
|
||||
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (pktSize));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (appDataRate));
|
||||
|
||||
Config::SetDefault ("ns3::Queue::Mode", StringValue ("QUEUE_MODE_PACKETS"));
|
||||
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (maxPackets));
|
||||
|
||||
if (!modeBytes)
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Mode", StringValue ("QUEUE_MODE_PACKETS"));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (queueDiscLimitPackets));
|
||||
}
|
||||
else
|
||||
{
|
||||
Config::SetDefault ("ns3::RedQueueDisc::Mode", StringValue ("QUEUE_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 == "ARED")
|
||||
{
|
||||
// Turn on ARED
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10.0));
|
||||
}
|
||||
|
||||
// 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;
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
|
||||
tchBottleneck.Install (d.GetLeft ()->GetDevice (0));
|
||||
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 ();
|
||||
|
||||
uint32_t totalRxBytesCounter = 0;
|
||||
for (uint32_t i = 0; i < sinkApps.GetN (); i++)
|
||||
{
|
||||
Ptr <Application> app = sinkApps.Get (i);
|
||||
Ptr <PacketSink> pktSink = DynamicCast <PacketSink> (app);
|
||||
totalRxBytesCounter += pktSink->GetTotalRx ();
|
||||
}
|
||||
|
||||
if (queueDiscType == "RED")
|
||||
{
|
||||
if (modeBytes)
|
||||
{
|
||||
if (totalRxBytesCounter > 2772992)
|
||||
{
|
||||
std::cout << "RED Goodput is too high, should be about 10403.2 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (totalRxBytesCounter < 2661888)
|
||||
{
|
||||
std::cout << "RED Goodput is too low, should be about 10403.2 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (totalRxBytesCounter > 2759680)
|
||||
{
|
||||
std::cout << "RED Goodput is too high, should be about 10355.1 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (totalRxBytesCounter < 2666496)
|
||||
{
|
||||
std::cout << "RED Goodput is too low, should be about 10355.1 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (queueDiscType == "ARED")
|
||||
{
|
||||
if (modeBytes)
|
||||
{
|
||||
if (totalRxBytesCounter > 2771968)
|
||||
{
|
||||
std::cout << "ARED Goodput is too high, should be about 10366.7 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (totalRxBytesCounter < 2654208)
|
||||
{
|
||||
std::cout << "ARED Goodput is too low, should be about 10366.7 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (totalRxBytesCounter > 2765824)
|
||||
{
|
||||
std::cout << "ARED Goodput is too high, should be about 10317.4 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
else if (totalRxBytesCounter < 2636800)
|
||||
{
|
||||
std::cout << "ARED Goodput is too low, should be about 10317.4 Bytes/sec" << std::endl;
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "----------------------------\nQueue disc Type:"
|
||||
<< queueDiscType
|
||||
<< "\nGoodput Bytes/sec:"
|
||||
<< totalRxBytesCounter / Simulator::Now ().GetSeconds () << std::endl;
|
||||
std::cout << "----------------------------" << std::endl;
|
||||
std::cout << "Destroying the simulation" << std::endl;
|
||||
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
@@ -6,6 +6,12 @@ def build(bld):
|
||||
obj = bld.create_ns3_program('red-tests', ['point-to-point', 'internet', 'applications', 'flow-monitor', 'traffic-control'])
|
||||
obj.source = 'red-tests.cc'
|
||||
|
||||
obj = bld.create_ns3_program('red-vs-ared', ['point-to-point', 'point-to-point-layout', 'internet', 'applications', 'traffic-control'])
|
||||
obj.source = 'red-vs-ared.cc'
|
||||
|
||||
obj = bld.create_ns3_program('adaptive-red-tests', ['point-to-point', 'internet', 'applications', 'flow-monitor', 'traffic-control'])
|
||||
obj.source = 'adaptive-red-tests.cc'
|
||||
|
||||
obj = bld.create_ns3_program('pfifo-vs-red', ['point-to-point', 'point-to-point-layout', 'internet', 'applications', 'traffic-control'])
|
||||
obj.source = 'pfifo-vs-red.cc'
|
||||
|
||||
|
||||
492
src/traffic-control/test/adaptive-red-queue-disc-test-suite.cc
Normal file
492
src/traffic-control/test/adaptive-red-queue-disc-test-suite.cc
Normal file
@@ -0,0 +1,492 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 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
|
||||
*
|
||||
* Author: Mohit P. Tahiliani (tahiliani@nitk.edu.in)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/red-queue-disc.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/ipv4-queue-disc-item.h"
|
||||
|
||||
#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"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// Tests to verify the working of *automatically set* parameters in ARED
|
||||
class AutoRedQueueDiscTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
AutoRedQueueDiscTestCase ();
|
||||
virtual void DoRun (void);
|
||||
private:
|
||||
void Enqueue (Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt);
|
||||
void RunAutoRedDiscTest (StringValue mode);
|
||||
};
|
||||
|
||||
AutoRedQueueDiscTestCase::AutoRedQueueDiscTestCase ()
|
||||
: TestCase ("Sanity check on automatically set parameters of ARED")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AutoRedQueueDiscTestCase::RunAutoRedDiscTest (StringValue mode)
|
||||
{
|
||||
uint32_t pktSize = 0;
|
||||
uint32_t modeSize = 1; // 1 for packets; pktSize for bytes
|
||||
Ptr<RedQueueDisc> queue = CreateObject<RedQueueDisc> ();
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
|
||||
"Verify that we can actually set the attribute Mode");
|
||||
|
||||
Ipv4Header ipHeader;
|
||||
Address dest;
|
||||
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
pktSize = 500;
|
||||
modeSize = pktSize + ipHeader.GetSerializedSize ();
|
||||
}
|
||||
|
||||
double minTh = 70 * modeSize;
|
||||
double maxTh = 150 * modeSize;
|
||||
uint32_t qSize = 300 * modeSize;
|
||||
|
||||
// test 1: Verify automatic setting of QW. [QW = 0.0 with default LinkBandwidth]
|
||||
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.0)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 2: Verify automatic setting of QW. [QW = 0.0 with lesser LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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.0)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LinkBandwidth", DataRateValue (DataRate ("0.015Mbps"))), true,
|
||||
"Verify that we can actually set the attribute LinkBandwidth");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 44, "There should be 44 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 45, "There should be 45 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 3: Verify automatic setting of QW. [QW = -1.0 with default LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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 (-1.0)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 4: Verify automatic setting of QW. [QW = -1.0 with lesser LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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 (-1.0)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LinkBandwidth", DataRateValue (DataRate ("0.015Mbps"))), true,
|
||||
"Verify that we can actually set the attribute LinkBandwidth");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 32, "There should be 32 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 33, "There should be 33 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 5: Verify automatic setting of QW. [QW = -2.0 with default LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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 (-2.0)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 29, "There should be 29 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 30, "There should be 30 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 6: Verify automatic setting of QW. [QW = -2.0 with lesser LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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 (-2.0)), true,
|
||||
"Verify that we can actually set the attribute QW");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LinkBandwidth", DataRateValue (DataRate ("0.015Mbps"))), true,
|
||||
"Verify that we can actually set the attribute LinkBandwidth");
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 44, "There should be 44 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 46, "There should be 46 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 7: Verify automatic setting of minTh and maxTh. [minTh = maxTh = 0.0, with default LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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 (0.0)), true,
|
||||
"Verify that we can actually set the attribute MinTh");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (0.0)), 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");
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MeanPktSize", UintegerValue (modeSize)), true,
|
||||
"Verify that we can actually set the attribute MeanPktSize");
|
||||
}
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 20, "There should be 20 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 113, "There should be 113 dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 21, "There should be 21 dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 113, "There should be 113 dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
|
||||
|
||||
// test 8: Verify automatic setting of minTh and maxTh. [minTh = maxTh = 0.0, with higher LinkBandwidth]
|
||||
queue = CreateObject<RedQueueDisc> ();
|
||||
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 (0.0)), true,
|
||||
"Verify that we can actually set the attribute MinTh");
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (0.0)), 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 ("LinkBandwidth", DataRateValue (DataRate ("150Mbps"))), true,
|
||||
"Verify that we can actually set the attribute LinkBandwidth");
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MeanPktSize", UintegerValue (modeSize)), true,
|
||||
"Verify that we can actually set the attribute MeanPktSize");
|
||||
}
|
||||
queue->Initialize ();
|
||||
Enqueue (queue, pktSize, 300);
|
||||
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero dropped packets due to probability mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero dropped packets due to hard mark");
|
||||
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should be zero dropped packets due to queue full");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutoRedQueueDiscTestCase::Enqueue (Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt)
|
||||
{
|
||||
Ipv4Header ipHeader;
|
||||
Address dest;
|
||||
for (uint32_t i = 0; i < nPkt; i++)
|
||||
{
|
||||
queue->Enqueue (Create<Ipv4QueueDiscItem> (Create<Packet> (size), dest, 0, ipHeader));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutoRedQueueDiscTestCase::DoRun (void)
|
||||
{
|
||||
RunAutoRedDiscTest (StringValue ("QUEUE_MODE_PACKETS"));
|
||||
RunAutoRedDiscTest (StringValue ("QUEUE_MODE_BYTES"));
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
|
||||
// Tests to verify the working of *adaptive* parameter in ARED
|
||||
class AdaptiveRedQueueDiscTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
AdaptiveRedQueueDiscTestCase ();
|
||||
virtual void DoRun (void);
|
||||
private:
|
||||
void RunAdaptiveRedDiscTest (StringValue mode);
|
||||
};
|
||||
|
||||
AdaptiveRedQueueDiscTestCase::AdaptiveRedQueueDiscTestCase ()
|
||||
: TestCase ("Sanity check on adaptive parameter of ARED")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AdaptiveRedQueueDiscTestCase::RunAdaptiveRedDiscTest (StringValue mode)
|
||||
{
|
||||
uint32_t pktSize = 500;
|
||||
uint32_t modeSize = 1; // 1 for packets; pktSize for bytes
|
||||
uint32_t nLeaf = 3;
|
||||
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (pktSize));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("10Mbps"));
|
||||
|
||||
Ptr<RedQueueDisc> queue = CreateObject<RedQueueDisc> ();
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
|
||||
"Verify that we can actually set the attribute Mode");
|
||||
|
||||
Ipv4Header ipHeader;
|
||||
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
modeSize = pktSize + ipHeader.GetSerializedSize ();
|
||||
}
|
||||
|
||||
uint32_t qSize = 100 * modeSize;
|
||||
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::LInterm", DoubleValue (10.0));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (qSize));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (pktSize + ipHeader.GetSerializedSize ()));
|
||||
|
||||
// Create the point-to-point link helpers
|
||||
PointToPointHelper bottleNeckLink;
|
||||
bottleNeckLink.SetDeviceAttribute ("DataRate", StringValue ("1.5Mbps"));
|
||||
bottleNeckLink.SetChannelAttribute ("Delay", StringValue ("20ms"));
|
||||
|
||||
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;
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
|
||||
tchBottleneck.Install (d.GetLeft ()->GetDevice (0));
|
||||
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 (), 5001));
|
||||
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), 5001));
|
||||
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 ();
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
uint32_t totalRxBytesCounter = 0;
|
||||
for (uint32_t i = 0; i < sinkApps.GetN (); i++)
|
||||
{
|
||||
Ptr <Application> app = sinkApps.Get (i);
|
||||
Ptr <PacketSink> pktSink = DynamicCast <PacketSink> (app);
|
||||
totalRxBytesCounter += pktSink->GetTotalRx ();
|
||||
}
|
||||
|
||||
if (queue->GetMode () == Queue::QUEUE_MODE_PACKETS)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (totalRxBytesCounter, 2605000, "Total received bytes should be 2605000");
|
||||
}
|
||||
else if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ (totalRxBytesCounter, 2557000, "Total received bytes should be 2557000");
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
void
|
||||
AdaptiveRedQueueDiscTestCase::DoRun (void)
|
||||
{
|
||||
RunAdaptiveRedDiscTest (StringValue ("QUEUE_MODE_PACKETS"));
|
||||
RunAdaptiveRedDiscTest (StringValue ("QUEUE_MODE_BYTES"));
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
static class AredQueueDiscTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
AredQueueDiscTestSuite ()
|
||||
: TestSuite ("adaptive-red-queue-disc", UNIT)
|
||||
{
|
||||
AddTestCase (new AutoRedQueueDiscTestCase (), TestCase::QUICK); // Tests for automatically set parameters of ARED
|
||||
AddTestCase (new AdaptiveRedQueueDiscTestCase (), TestCase::QUICK); // Tests for adaptive parameter of ARED
|
||||
}
|
||||
} g_aredQueueDiscTestSuite;
|
||||
@@ -24,6 +24,7 @@ def build(bld):
|
||||
'test/pfifo-fast-queue-disc-test-suite.cc',
|
||||
'test/red-queue-disc-test-suite.cc',
|
||||
'test/codel-queue-disc-test-suite.cc',
|
||||
'test/adaptive-red-queue-disc-test-suite.cc',
|
||||
]
|
||||
|
||||
headers = bld(features='ns3header')
|
||||
|
||||
Reference in New Issue
Block a user