traffic-control: Add ARED test and examples

This commit is contained in:
M P Tahiliani
2016-03-08 10:48:41 -08:00
parent 9e11878f7d
commit b0b03f081c
5 changed files with 1446 additions and 0 deletions

View 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;
}

View 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;
}

View File

@@ -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'

View 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;

View File

@@ -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')