From 66fc5622f4c4abe64b60aef454b7cd29531104ac Mon Sep 17 00:00:00 2001 From: "Shravya K.S" Date: Fri, 24 Jan 2020 09:49:56 -0800 Subject: [PATCH] tcp: Add DCTCP example --- examples/tcp/dctcp-example.cc | 265 ++++++++++++++++++++++++++++++++++ examples/tcp/wscript | 4 + 2 files changed, 269 insertions(+) create mode 100644 examples/tcp/dctcp-example.cc diff --git a/examples/tcp/dctcp-example.cc b/examples/tcp/dctcp-example.cc new file mode 100644 index 000000000..e7c2d0d54 --- /dev/null +++ b/examples/tcp/dctcp-example.cc @@ -0,0 +1,265 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 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: Shravya K.S. + * + */ + +// The network topology used in this example is based on the Fig. 17 described in +// Mohammad Alizadeh, Albert Greenberg, David A. Maltz, Jitendra Padhye, +// Parveen Patel, Balaji Prabhakar, Sudipta Sengupta, and Murari Sridharan. +// "Data Center TCP (DCTCP)." In ACM SIGCOMM Computer Communication Review, +// Vol. 40, No. 4, pp. 63-74. ACM, 2010. + +#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/traffic-control-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("DctcpExample"); + +std::stringstream filePlotQueue1; +std::stringstream filePlotQueue2; + +void +PrintPayload ( Ptr< const Packet > p) +{ + std::ofstream fPlotQueue ("throughput.dat", std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now ().GetSeconds () << " " << p->GetSize () << std::endl; + fPlotQueue.close (); +} + +void +CheckQueueSize (Ptr queue, std::string filePlotQueue) +{ + uint32_t qSize = queue->GetCurrentSize ().GetValue (); + + // check queue size every 1/100 of a second + Simulator::Schedule (Seconds (0.01), &CheckQueueSize, queue, filePlotQueue); + + std::ofstream fPlotQueue (filePlotQueue.c_str (), std::ios::out | std::ios::app); + fPlotQueue << Simulator::Now ().GetSeconds () << " " << qSize << std::endl; + fPlotQueue.close (); +} + +int main (int argc, char *argv[]) +{ + + LogComponentEnable ("DctcpExample", LOG_LEVEL_INFO); + + std::string pathOut = "."; + bool writeForPlot = false; + bool writePcap = false; + + CommandLine cmd; + cmd.AddValue ("pathOut", "path to save results from --writeForPlot/--writePcap", pathOut); + cmd.AddValue ("writeForPlot", "write results for plot (gnuplot)", writeForPlot); + cmd.AddValue ("writePcap", "write results in pcapfile", writePcap); + cmd.Parse (argc, argv); + + double global_start_time = 0.0; + double global_stop_time = 11; + double sink_start_time = global_start_time; + double sink_stop_time = global_stop_time + 3.0; + double client_start_time = sink_start_time + 0.2; + double client_stop_time = global_stop_time - 2.0; + + NodeContainer S1, S2, S3, R1, R2, T1, T2; + T1.Create (2); + T2.Create (1); + T2.Add (T1.Get (1)); + R1.Create (1); + R1.Add (T2.Get (0)); + S1.Create (10); + S1.Add (T1.Get (0)); + S2.Create (20); + S2.Add (T1.Get (0)); + S3.Create (10); + S3.Add (T2.Get (0)); + R2.Create (20); + R2.Add (T2.Get (0)); + + Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::TcpDctcp")); + Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000)); + Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1)); + GlobalValue::Bind ("ChecksumEnabled", BooleanValue (false)); + + uint32_t meanPktSize = 1000; + + Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (meanPktSize)); + + // DCTCP tracks instantaneous queue length only; so set QW = 1 + Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (1)); + + // Triumph and Scorpion switches used in DCTCP Paper have 4 MB of buffer + // If every packet is 1000 bytes, 4195 packets can be stored in 4 MB + Config::SetDefault ("ns3::RedQueueDisc::MaxSize", QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, 4195))); + + // MinTh = MaxTh = 17% of QueueLimit as recommended in ACM SIGCOMM 2010 DCTCP Paper + Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (713)); + Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (713)); + + // Setting ECN is mandatory for DCTCP + Config::SetDefault ("ns3::RedQueueDisc::UseEcn", BooleanValue (true)); + + PointToPointHelper pointToPointSR; + pointToPointSR.SetDeviceAttribute ("DataRate", StringValue ("1000Mbps")); + pointToPointSR.SetChannelAttribute ("Delay", StringValue ("0.01ms")); + + PointToPointHelper pointToPointT; + pointToPointT.SetDeviceAttribute ("DataRate", StringValue ("10000Mbps")); + pointToPointT.SetChannelAttribute ("Delay", StringValue ("0.01ms")); + + TrafficControlHelper tchRed; + tchRed.SetRootQueueDisc ("ns3::RedQueueDisc", "LinkBandwidth", StringValue ("10000Mbps"), + "LinkDelay", StringValue ("0.01ms")); + + NetDeviceContainer S1dev, S2dev, S3dev, R1dev, R2dev, T1dev, T2dev; + R1dev = pointToPointSR.Install (R1); + T1dev = pointToPointT.Install (T1); + T2dev = pointToPointT.Install (T2); + + T1dev.Get (0)->TraceConnectWithoutContext ("MacRx", MakeCallback (&PrintPayload)); + + for (uint32_t i = 0; i < 10; i++) + { + S1dev.Add (pointToPointSR.Install (S1.Get (i), T1.Get (0))); + S3dev.Add (pointToPointSR.Install (S3.Get (i), T2.Get (0))); + S2dev.Add (pointToPointSR.Install (S2.Get (i * 2), T1.Get (0))); + S2dev.Add (pointToPointSR.Install (S2.Get (2 * i + 1), T1.Get (0))); + R2dev.Add (pointToPointSR.Install (R2.Get (i * 2), T2.Get (0))); + R2dev.Add (pointToPointSR.Install (R2.Get (2 * i + 1), T2.Get (0))); + } + + InternetStackHelper stack; + stack.Install (S2); + stack.Install (R2); + stack.Install (T1.Get (1)); + stack.Install (R1.Get (0)); + + QueueDiscContainer queueDiscs1 = tchRed.Install (T1dev); + QueueDiscContainer queueDiscs2 = tchRed.Install (T2dev); + + for (uint32_t i = 0; i < 10; i++) + { + stack.Install (S1.Get (i)); + stack.Install (S3.Get (i)); + } + + Ipv4AddressHelper address; + Ipv4InterfaceContainer S1Int, S2Int, S3Int, R1Int, R2Int, T1Int, T2Int; + + address.SetBase ("10.1.1.0", "255.255.255.0"); + S1Int = address.Assign (S1dev); + + address.SetBase ("10.1.2.0", "255.255.255.0"); + S2Int = address.Assign (S2dev); + + address.SetBase ("10.1.3.0", "255.255.255.0"); + S3Int = address.Assign (S3dev); + + address.SetBase ("10.2.1.0", "255.255.255.0"); + R1Int = address.Assign (R1dev); + + address.SetBase ("10.2.2.0", "255.255.255.0"); + R2Int = address.Assign (R2dev); + + address.SetBase ("10.3.1.0", "255.255.255.0"); + T1Int = address.Assign (T1dev); + + address.SetBase ("10.3.2.0", "255.255.255.0"); + T2Int = address.Assign (T2dev); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + uint16_t port = 50000; + Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port)); + PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress); + ApplicationContainer sinkApp = sinkHelper.Install (R1.Get (0)); + sinkApp.Start (Seconds (sink_start_time)); + sinkApp.Stop (Seconds (sink_stop_time)); + + OnOffHelper clientHelper1 ("ns3::TcpSocketFactory", Address ()); + clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("1000Mb/s"))); + clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000)); + + ApplicationContainer clientApps1; + AddressValue remoteAddress (InetSocketAddress (R1Int.GetAddress (0), port)); + clientHelper1.SetAttribute ("Remote", remoteAddress); + for (uint32_t i = 0; i < 10; i++) + { + clientApps1.Add (clientHelper1.Install (S1.Get (i))); + clientApps1.Add (clientHelper1.Install (S3.Get (i))); + } + clientApps1.Start (Seconds (client_start_time)); + clientApps1.Stop (Seconds (client_stop_time)); + + for (uint32_t i = 0; i < 20; i++) + { + Address sinkLocalAddress2 (InetSocketAddress (Ipv4Address::GetAny (), port)); + PacketSinkHelper sinkHelper2 ("ns3::TcpSocketFactory", sinkLocalAddress2); + ApplicationContainer sinkApp2 = sinkHelper.Install (R2.Get (i)); + sinkApp2.Start (Seconds (sink_start_time)); + sinkApp2.Stop (Seconds (sink_stop_time)); + + OnOffHelper clientHelper2 ("ns3::TcpSocketFactory", Address ()); + clientHelper2.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); + clientHelper2.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); + clientHelper2.SetAttribute ("DataRate", DataRateValue (DataRate ("1000Mb/s"))); + clientHelper2.SetAttribute ("PacketSize", UintegerValue (1000)); + + ApplicationContainer clientApps2; + AddressValue remoteAddress2 (InetSocketAddress (R2Int.GetAddress (i), port)); + clientHelper2.SetAttribute ("Remote", remoteAddress2); + clientApps2.Add (clientHelper2.Install (S2.Get (i))); + clientApps2.Start (Seconds (client_start_time)); + clientApps2.Stop (Seconds (client_stop_time)); + } + + if (writePcap) + { + PointToPointHelper ptp; + std::stringstream stmp; + stmp << pathOut << "/dctcp-example"; + ptp.EnablePcapAll (stmp.str ().c_str ()); + } + + if (writeForPlot) + { + filePlotQueue1 << pathOut << "/" << "dctcp-example-queue-1.plotme"; + remove (filePlotQueue1.str ().c_str ()); + Ptr queue1 = queueDiscs1.Get (0); + Simulator::ScheduleNow (&CheckQueueSize, queue1, filePlotQueue1.str ()); + + filePlotQueue2 << pathOut << "/" << "dctcp-example-queue-2.plotme"; + remove (filePlotQueue2.str ().c_str ()); + Ptr queue2 = queueDiscs2.Get (0); + Simulator::ScheduleNow (&CheckQueueSize, queue2, filePlotQueue2.str ()); + + } + + Simulator::Stop (Seconds (sink_stop_time)); + Simulator::Run (); + Simulator::Destroy (); + return 0; +} diff --git a/examples/tcp/wscript b/examples/tcp/wscript index cec810b22..970a71fab 100644 --- a/examples/tcp/wscript +++ b/examples/tcp/wscript @@ -43,3 +43,7 @@ def build(bld): ['point-to-point', 'internet', 'applications', 'flow-monitor']) obj.source = 'tcp-pacing.cc' + + obj = bld.create_ns3_program('dctcp-example', + ['core', 'network', 'internet', 'point-to-point', 'applications', 'traffic-control']) + obj.source = 'dctcp-example.cc'