diff --git a/examples/traffic-control/cobalt-vs-codel.cc b/examples/traffic-control/cobalt-vs-codel.cc new file mode 100644 index 000000000..4fb4eba14 --- /dev/null +++ b/examples/traffic-control/cobalt-vs-codel.cc @@ -0,0 +1,256 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2019 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: Shefali Gupta + * Jendaipou Palmei + * Mohit P. Tahiliani + */ + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/applications-module.h" +#include +#include "ns3/ipv6-static-routing-helper.h" +#include "ns3/ipv6-routing-table-entry.h" +#include "ns3/internet-module.h" +#include "ns3/flow-monitor-module.h" +#include "ns3/tcp-header.h" +#include "ns3/traffic-control-module.h" +#include + +// Dumbbell topology with 7 senders and 1 receiver +// is used for this example. On successful completion, +// the Congestion window and Queue size traces get stored +// in MixTraffic/ directory, inside cwndTraces and +// queueTraces sub-directories, respectively. + +using namespace ns3; + +std::string dir = "MixTraffic/"; + +void +CheckQueueSize (Ptr queue,std::string queue_disc_type) +{ + double qSize = queue->GetCurrentSize ().GetValue (); + // check queue size every 1/10 of a second + Simulator::Schedule (Seconds (0.1), &CheckQueueSize, queue, queue_disc_type); + + std::ofstream fPlotQueue (dir + queue_disc_type + "/queueTraces/queue.plotme", std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now ().GetSeconds () << " " << qSize << std::endl; + fPlotQueue.close (); +} + +static void +CwndTrace (Ptr stream, uint32_t oldCwnd, uint32_t newCwnd) +{ + *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newCwnd / 1446.0 << std::endl; +} + +static void +TraceCwnd (std::string queue_disc_type) +{ + for (uint8_t i = 0; i < 5; i++) + { + AsciiTraceHelper asciiTraceHelper; + Ptr stream = asciiTraceHelper.CreateFileStream (dir + queue_disc_type + "/cwndTraces/S1-" + std::to_string (i + 1) + ".plotme"); + Config::ConnectWithoutContext ("/NodeList/" + std::to_string (i) + "/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&CwndTrace,stream)); + } +} + +void experiment (std::string queue_disc_type) +{ + // Set the simulation stop time in seconds + double stopTime = 101; + std::string queue_disc = std::string ("ns3::") + queue_disc_type; + + std::string bottleneckBandwidth = "10Mbps"; + std::string bottleneckDelay = "50ms"; + + std::string accessBandwidth = "10Mbps"; + std::string accessDelay = "5ms"; + + // Create sender + NodeContainer tcpSender; + tcpSender.Create (5); + + NodeContainer udpSender; + udpSender.Create (2); + + // Create gateway + NodeContainer gateway; + gateway.Create (2); + + // Create sink + NodeContainer sink; + sink.Create (1); + + Config::SetDefault ("ns3::TcpSocket::SndBufSize", UintegerValue (1 << 20)); + Config::SetDefault ("ns3::TcpSocket::RcvBufSize", UintegerValue (1 << 20)); + Config::SetDefault ("ns3::TcpSocket::DelAckTimeout", TimeValue (Seconds (0))); + Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (1)); + Config::SetDefault ("ns3::TcpSocketBase::LimitedTransmit", BooleanValue (false)); + Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1446)); + Config::SetDefault ("ns3::TcpSocketBase::WindowScaling", BooleanValue (true)); + Config::SetDefault (queue_disc + "::MaxSize", QueueSizeValue (QueueSize ("200p"))); + + InternetStackHelper internet; + internet.InstallAll (); + + TrafficControlHelper tchPfifo; + uint16_t handle = tchPfifo.SetRootQueueDisc ("ns3::PfifoFastQueueDisc"); + tchPfifo.AddInternalQueues (handle, 3, "ns3::DropTailQueue", "MaxSize", StringValue ("1000p")); + + TrafficControlHelper tch; + tch.SetRootQueueDisc (queue_disc); + + PointToPointHelper accessLink; + accessLink.SetDeviceAttribute ("DataRate", StringValue (accessBandwidth)); + accessLink.SetChannelAttribute ("Delay", StringValue (accessDelay)); + + // Configure the senders and sinks net devices + // and the channels between the senders/sinks and the gateways + NetDeviceContainer devices [5]; + for (uint8_t i = 0; i < 5; i++) + { + devices [i] = accessLink.Install (tcpSender.Get (i), gateway.Get (0)); + tchPfifo.Install (devices [i]); + } + + NetDeviceContainer devices_sink; + devices_sink = accessLink.Install (gateway.Get (1), sink.Get (0)); + tchPfifo.Install (devices_sink); + + PointToPointHelper bottleneckLink; + bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bottleneckBandwidth)); + bottleneckLink.SetChannelAttribute ("Delay", StringValue (bottleneckDelay)); + + NetDeviceContainer devices_gateway; + devices_gateway = bottleneckLink.Install (gateway.Get (0), gateway.Get (1)); + // Install QueueDisc at gateway + QueueDiscContainer queueDiscs = tch.Install (devices_gateway); + + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.255.255.0"); + + Ipv4InterfaceContainer interfaces [5]; + Ipv4InterfaceContainer interfaces_sink; + Ipv4InterfaceContainer interfaces_gateway; + Ipv4InterfaceContainer udpinterfaces [2]; + + NetDeviceContainer udpdevices [2]; + + for (uint8_t i = 0; i < 5; i++) + { + address.NewNetwork (); + interfaces [i] = address.Assign (devices [i]); + } + + for (uint8_t i = 0; i < 2; i++) + { + udpdevices [i] = accessLink.Install (udpSender.Get (i), gateway.Get (0)); + address.NewNetwork (); + udpinterfaces [i] = address.Assign (udpdevices [i]); + } + + address.NewNetwork (); + interfaces_gateway = address.Assign (devices_gateway); + + address.NewNetwork (); + interfaces_sink = address.Assign (devices_sink); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + uint16_t port = 50000; + uint16_t port1 = 50001; + Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port)); + Address sinkLocalAddress1 (InetSocketAddress (Ipv4Address::GetAny (), port1)); + PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress); + PacketSinkHelper sinkHelper1 ("ns3::UdpSocketFactory", sinkLocalAddress1); + + AddressValue remoteAddress (InetSocketAddress (interfaces_sink.GetAddress (1), port)); + AddressValue remoteAddress1 (InetSocketAddress (interfaces_sink.GetAddress (1), port1)); + + BulkSendHelper ftp ("ns3::TcpSocketFactory", Address ()); + ftp.SetAttribute ("Remote", remoteAddress); + ftp.SetAttribute ("SendSize", UintegerValue (1000)); + + ApplicationContainer sourceApp = ftp.Install (tcpSender); + sourceApp.Start (Seconds (0)); + sourceApp.Stop (Seconds (stopTime - 1)); + + sinkHelper.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ())); + ApplicationContainer sinkApp = sinkHelper.Install (sink); + sinkApp.Start (Seconds (0)); + sinkApp.Stop (Seconds (stopTime)); + + OnOffHelper clientHelper6 ("ns3::UdpSocketFactory", Address ()); + clientHelper6.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + clientHelper6.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + clientHelper6.SetAttribute ("DataRate", DataRateValue (DataRate ("10Mb/s"))); + clientHelper6.SetAttribute ("PacketSize", UintegerValue (1000)); + + ApplicationContainer clientApps6; + clientHelper6.SetAttribute ("Remote", remoteAddress1); + clientApps6.Add (clientHelper6.Install (udpSender.Get (0))); + clientApps6.Start (Seconds (0)); + clientApps6.Stop (Seconds (stopTime - 1)); + + OnOffHelper clientHelper7 ("ns3::UdpSocketFactory", Address ()); + clientHelper7.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + clientHelper7.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + clientHelper7.SetAttribute ("DataRate", DataRateValue (DataRate ("10Mb/s"))); + clientHelper7.SetAttribute ("PacketSize", UintegerValue (1000)); + + ApplicationContainer clientApps7; + clientHelper7.SetAttribute ("Remote", remoteAddress1); + clientApps7.Add (clientHelper7.Install (udpSender.Get (1))); + clientApps7.Start (Seconds (0)); + clientApps7.Stop (Seconds (stopTime - 1)); + + sinkHelper1.SetAttribute ("Protocol", TypeIdValue (UdpSocketFactory::GetTypeId ())); + ApplicationContainer sinkApp1 = sinkHelper1.Install (sink); + sinkApp1.Start (Seconds (0)); + sinkApp1.Stop (Seconds (stopTime)); + + Ptr queue = queueDiscs.Get (0); + Simulator::ScheduleNow (&CheckQueueSize, queue,queue_disc_type); + + std::string dirToSave = "mkdir -p " + dir + queue_disc_type; + system (dirToSave.c_str ()); + system ((dirToSave + "/cwndTraces/").c_str ()); + system ((dirToSave + "/queueTraces/").c_str ()); + + Simulator::Schedule (Seconds (0.1), &TraceCwnd,queue_disc_type); + + Simulator::Stop (Seconds (stopTime)); + Simulator::Run (); + Simulator::Destroy (); +} + +int main (int argc, char **argv) +{ + std::cout << "Simulation with COBALT QueueDisc: Start\n" << std::flush; + experiment ("CobaltQueueDisc"); + std::cout << "Simulation with COBALT QueueDisc: End\n" << std::flush; + std::cout << "------------------------------------------------\n"; + std::cout << "Simulation with CoDel QueueDisc: Start\n"; + experiment ("CoDelQueueDisc"); + std::cout << "Simulation with CoDel QueueDisc: End\n"; + + return 0; +} diff --git a/examples/traffic-control/wscript b/examples/traffic-control/wscript index 0808c4b6b..f743ecb1a 100644 --- a/examples/traffic-control/wscript +++ b/examples/traffic-control/wscript @@ -18,3 +18,8 @@ def build(bld): obj = bld.create_ns3_program('tbf-example', ['internet', 'point-to-point', 'applications', 'traffic-control']) obj.source = 'tbf-example.cc' + + obj = bld.create_ns3_program('cobalt-vs-codel', + ['internet', 'point-to-point', 'applications', 'traffic-control']) + obj.source = 'cobalt-vs-codel.cc' +