examples: Add an example to evaluate the performance of various queue discs
This commit is contained in:
288
examples/traffic-control/queue-discs-benchmark.cc
Normal file
288
examples/traffic-control/queue-discs-benchmark.cc
Normal file
@@ -0,0 +1,288 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Pasquale Imputato <p.imputato@gmail.com>
|
||||
* Stefano Avallone <stefano.avallone@unina.it>
|
||||
*/
|
||||
|
||||
// This example serves as a benchmark for all the queue discs (with BQL enabled or not)
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// 192.168.1.0 192.168.2.0
|
||||
// n1 ------------------------------------ n2 ----------------------------------- n3
|
||||
// point-to-point (access link) point-to-point (bottleneck link)
|
||||
// 100 Mbps, 0.1 ms bandwidth [10 Mbps], delay [5 ms]
|
||||
// qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel} [PfifoFast]
|
||||
// of 1000 packets with capacity of queueDiscSize packets [1000]
|
||||
// netdevices queues with size of 100 packets netdevices queues with size of netdevicesQueueSize packets [100]
|
||||
// without BQL bql BQL [false]
|
||||
// *** fixed configuration ***
|
||||
//
|
||||
// The output will consist of a number of ping Rtt such as:
|
||||
//
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=110 ms
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=112 ms
|
||||
// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
|
||||
//
|
||||
// The files output will consist of a trace file with bytes in queue and of a trace file for limits
|
||||
// (when BQL is enabled) both for bottleneck NetDevice on n2, two files with upload and download
|
||||
// goodput for flows configuration and a file with flow monitor stats.
|
||||
//
|
||||
// If you use an AQM as queue disc on the bottleneck netdevices, you can observe that the ping Rtt
|
||||
// decrease. A further decrease can be observed when you enable BQL.
|
||||
|
||||
#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/internet-apps-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
#include "ns3/flow-monitor-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("BenchmarkQueueDiscs");
|
||||
|
||||
void
|
||||
LimitsTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
|
||||
{
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
BytesInQueueTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
|
||||
{
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
GoodputSampling (std::string fileName, ApplicationContainer app, Ptr<OutputStreamWrapper> stream, float period)
|
||||
{
|
||||
Simulator::Schedule (Seconds (period), &GoodputSampling, fileName, app, stream, period);
|
||||
double goodput;
|
||||
uint32_t totalPackets = DynamicCast<PacketSink> (app.Get (0))->GetTotalRx ();
|
||||
goodput = totalPackets * 8 / (Simulator::Now ().GetSeconds () * 1024); // Kbit/s
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << goodput << std::endl;
|
||||
}
|
||||
|
||||
static void PingRtt (std::string context, Time rtt)
|
||||
{
|
||||
std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
std::string bandwidth = "10Mbps";
|
||||
std::string delay = "5ms";
|
||||
std::string queueDiscType = "PfifoFast";
|
||||
uint32_t queueDiscSize = 1000;
|
||||
uint32_t netdevicesQueueSize = 100;
|
||||
bool bql = false;
|
||||
|
||||
std::string flowsDatarate = "20Mbps";
|
||||
uint32_t flowsPacketsSize = 1000;
|
||||
|
||||
float startTime = 0.1; // in s
|
||||
float simDuration = 60;
|
||||
float samplingPeriod = 1;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("bandwidth", "Bottleneck bandwidth", bandwidth);
|
||||
cmd.AddValue ("delay", "Bottleneck delay", delay);
|
||||
cmd.AddValue ("queueDiscType", "Bottleneck queue disc type in {PfifoFast, ARED, CoDel}", queueDiscType);
|
||||
cmd.AddValue ("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
|
||||
cmd.AddValue ("netdevicesQueueSize", "Bottleneck netdevices queue size in packets", netdevicesQueueSize);
|
||||
cmd.AddValue ("bql", "Enable byte queue limits on bottleneck netdevices", bql);
|
||||
cmd.AddValue ("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
|
||||
cmd.AddValue ("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
|
||||
cmd.AddValue ("startTime", "Simulation start time", startTime);
|
||||
cmd.AddValue ("simDuration", "Simulation duration in seconds", simDuration);
|
||||
cmd.AddValue ("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
float stopTime = startTime + simDuration;
|
||||
|
||||
// Create nodes
|
||||
NodeContainer n1, n2, n3;
|
||||
n1.Create (1);
|
||||
n2.Create (1);
|
||||
n3.Create (1);
|
||||
|
||||
// Create and configure access link and bottleneck link
|
||||
PointToPointHelper accessLink;
|
||||
accessLink.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
accessLink.SetChannelAttribute ("Delay", StringValue ("0.1ms"));
|
||||
|
||||
PointToPointHelper bottleneckLink;
|
||||
bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bandwidth));
|
||||
bottleneckLink.SetChannelAttribute ("Delay", StringValue (delay));
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.InstallAll ();
|
||||
|
||||
// Access link traffic control configuration
|
||||
TrafficControlHelper tchPfifoFastAccess;
|
||||
uint32_t handle = tchPfifoFastAccess.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (1000));
|
||||
|
||||
// Bottleneck link traffic control configuration
|
||||
TrafficControlHelper tchBottleneck;
|
||||
|
||||
if (queueDiscType.compare ("PfifoFast") == 0)
|
||||
{
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (queueDiscSize));
|
||||
}
|
||||
else if (queueDiscType.compare ("ARED") == 0)
|
||||
{
|
||||
handle = tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
tchBottleneck.AddInternalQueues (handle, 1, "ns3::DropTailQueue", "MaxPackets", UintegerValue (queueDiscSize));
|
||||
}
|
||||
else if (queueDiscType.compare ("CoDel") == 0)
|
||||
{
|
||||
handle = tchBottleneck.SetRootQueueDisc ("ns3::CoDelQueueDisc");
|
||||
Config::SetDefault ("ns3::CoDelQueueDisc::Mode", EnumValue (Queue::QUEUE_MODE_PACKETS));
|
||||
tchBottleneck.AddInternalQueues (handle, 1, "ns3::DropTailQueue", "MaxPackets", UintegerValue (queueDiscSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("--queueDiscType not valid");
|
||||
}
|
||||
|
||||
if (bql)
|
||||
{
|
||||
tchBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits");
|
||||
}
|
||||
|
||||
Config::SetDefault ("ns3::Queue::Mode", StringValue ("QUEUE_MODE_PACKETS"));
|
||||
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (100));
|
||||
|
||||
NetDeviceContainer devicesAccessLink = accessLink.Install (n1.Get (0), n2.Get (0));
|
||||
tchPfifoFastAccess.Install (devicesAccessLink);
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("192.168.0.0", "255.255.255.0");
|
||||
address.NewNetwork ();
|
||||
Ipv4InterfaceContainer interfacesAccess = address.Assign (devicesAccessLink);
|
||||
|
||||
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (netdevicesQueueSize));
|
||||
|
||||
NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install (n2.Get (0), n3.Get (0));
|
||||
QueueDiscContainer qdiscs;
|
||||
qdiscs = tchBottleneck.Install (devicesBottleneckLink);
|
||||
|
||||
address.NewNetwork ();
|
||||
Ipv4InterfaceContainer interfacesBottleneck = address.Assign (devicesBottleneckLink);
|
||||
|
||||
Ptr<NetDeviceQueueInterface> interface = devicesBottleneckLink.Get (0)->GetObject<NetDeviceQueueInterface> ();
|
||||
Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue (0);
|
||||
Ptr<DynamicQueueLimits> queueLimits = StaticCast<DynamicQueueLimits> (queueInterface->GetQueueLimits ());
|
||||
|
||||
AsciiTraceHelper ascii;
|
||||
if (bql)
|
||||
{
|
||||
queueDiscType = queueDiscType + "-bql";
|
||||
Ptr<OutputStreamWrapper> streamLimits = ascii.CreateFileStream (queueDiscType + "-limits.txt");
|
||||
queueLimits->TraceConnectWithoutContext ("Limit",MakeBoundCallback (&LimitsTrace, streamLimits));
|
||||
}
|
||||
Ptr<Queue> queue = StaticCast<PointToPointNetDevice> (devicesBottleneckLink.Get (0))->GetQueue ();
|
||||
Ptr<OutputStreamWrapper> streamBytesInQueue = ascii.CreateFileStream (queueDiscType + "-bytesInQueue.txt");
|
||||
queue->TraceConnectWithoutContext ("BytesInQueue",MakeBoundCallback (&BytesInQueueTrace, streamBytesInQueue));
|
||||
|
||||
Ipv4InterfaceContainer n1Interface;
|
||||
n1Interface.Add (interfacesAccess.Get (0));
|
||||
|
||||
Ipv4InterfaceContainer n3Interface;
|
||||
n3Interface.Add (interfacesBottleneck.Get (1));
|
||||
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (flowsPacketsSize));
|
||||
|
||||
// Flows configuration
|
||||
// Bidirectional TCP streams with ping like flent tcp_bidirectional test.
|
||||
uint16_t port = 7;
|
||||
ApplicationContainer uploadApp, downloadApp, sourceApps;
|
||||
// Configure and install upload flow
|
||||
Address addUp (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelperUp ("ns3::TcpSocketFactory", addUp);
|
||||
sinkHelperUp.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
|
||||
uploadApp.Add (sinkHelperUp.Install (n3));
|
||||
|
||||
InetSocketAddress socketAddressUp = InetSocketAddress (n3Interface.GetAddress (0), port);
|
||||
OnOffHelper onOffHelperUp ("ns3::TcpSocketFactory", Address ());
|
||||
onOffHelperUp.SetAttribute ("Remote", AddressValue (socketAddressUp));
|
||||
onOffHelperUp.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onOffHelperUp.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onOffHelperUp.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
|
||||
onOffHelperUp.SetAttribute ("DataRate", StringValue (flowsDatarate));
|
||||
sourceApps.Add (onOffHelperUp.Install (n1));
|
||||
|
||||
port = 8;
|
||||
// Configure and install download flow
|
||||
Address addDown (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelperDown ("ns3::TcpSocketFactory", addDown);
|
||||
sinkHelperDown.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
|
||||
downloadApp.Add (sinkHelperDown.Install (n1));
|
||||
|
||||
InetSocketAddress socketAddressDown = InetSocketAddress (n1Interface.GetAddress (0), port);
|
||||
OnOffHelper onOffHelperDown ("ns3::TcpSocketFactory", Address ());
|
||||
onOffHelperDown.SetAttribute ("Remote", AddressValue (socketAddressDown));
|
||||
onOffHelperDown.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onOffHelperDown.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onOffHelperDown.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
|
||||
onOffHelperDown.SetAttribute ("DataRate", StringValue (flowsDatarate));
|
||||
sourceApps.Add (onOffHelperDown.Install (n3));
|
||||
|
||||
// Configure and install ping
|
||||
V4PingHelper ping = V4PingHelper (n3Interface.GetAddress (0));
|
||||
ping.Install (n1);
|
||||
|
||||
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback (&PingRtt));
|
||||
|
||||
uploadApp.Start (Seconds (0));
|
||||
uploadApp.Stop (Seconds (stopTime));
|
||||
downloadApp.Start (Seconds (0));
|
||||
downloadApp.Stop (Seconds (stopTime));
|
||||
|
||||
sourceApps.Start (Seconds (0 + 0.1));
|
||||
sourceApps.Stop (Seconds (stopTime - 0.1));
|
||||
|
||||
Ptr<OutputStreamWrapper> uploadGoodputStream = ascii.CreateFileStream (queueDiscType + "-upGoodput.txt");
|
||||
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-upGoodput.txt", uploadApp,
|
||||
uploadGoodputStream, samplingPeriod);
|
||||
Ptr<OutputStreamWrapper> downloadGoodputStream = ascii.CreateFileStream (queueDiscType + "-downGoodput.txt");
|
||||
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-downGoodput.txt", downloadApp,
|
||||
downloadGoodputStream, samplingPeriod);
|
||||
|
||||
// Flow monitor
|
||||
Ptr<FlowMonitor> flowMonitor;
|
||||
FlowMonitorHelper flowHelper;
|
||||
flowMonitor = flowHelper.InstallAll();
|
||||
|
||||
Simulator::Stop (Seconds (stopTime));
|
||||
Simulator::Run ();
|
||||
|
||||
flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
|
||||
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
@@ -4,3 +4,7 @@ def build(bld):
|
||||
obj = bld.create_ns3_program('traffic-control',
|
||||
['internet', 'point-to-point', 'applications', 'traffic-control'])
|
||||
obj.source = 'traffic-control.cc'
|
||||
|
||||
obj = bld.create_ns3_program('queue-discs-benchmark',
|
||||
['internet', 'point-to-point', 'applications', 'internet-apps', 'traffic-control', 'flow-monitor'])
|
||||
obj.source = 'queue-discs-benchmark.cc'
|
||||
|
||||
Reference in New Issue
Block a user