A Discrete-Event Network Simulator
API
tcp-linux-reno.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 NITK Surathkal
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Apoorva Bhargava <apoorvabhargava13@gmail.com>
19  */
20 
21 // Network topology
22 //
23 // n0 ---------- n1 ---------- n2 ---------- n3
24 // 10 Mbps 1 Mbps 10 Mbps
25 // 1 ms 10 ms 1 ms
26 //
27 // - TCP flow from n0 to n3 using BulkSendApplication.
28 // - The following simulation output is stored in results/ in ns-3 top-level directory:
29 // - cwnd traces are stored in cwndTraces folder
30 // - queue length statistics are stored in queue-size.dat file
31 // - pcaps are stored in pcap folder
32 // - queueTraces folder contain the drop statistics at queue
33 // - queueStats.txt file contains the queue stats and config.txt file contains
34 // the simulation configuration.
35 // - The cwnd and queue length traces obtained from this example were tested against
36 // the respective traces obtained from Linux Reno by using ns-3 Direct Code Execution.
37 // See internet/doc/tcp.rst for more details.
38 
39 #include <iostream>
40 #include <string>
41 #include <fstream>
42 #include <sys/stat.h>
43 #include "ns3/core-module.h"
44 #include "ns3/network-module.h"
45 #include "ns3/internet-module.h"
46 #include "ns3/point-to-point-module.h"
47 #include "ns3/applications-module.h"
48 #include "ns3/traffic-control-module.h"
49 
50 using namespace ns3;
51 std::string dir = "results/";
53 uint32_t segmentSize = 524;
54 
55 // Function to check queue length of Router 1
56 void
58 {
59  uint32_t qSize = queue->GetCurrentSize ().GetValue ();
60 
61  // Check queue size every 1/100 of a second
62  Simulator::Schedule (Seconds (0.001), &CheckQueueSize, queue);
63  std::ofstream fPlotQueue (std::stringstream (dir + "queue-size.dat").str ().c_str (), std::ios::out | std::ios::app);
64  fPlotQueue << Simulator::Now ().GetSeconds () << " " << qSize << std::endl;
65  fPlotQueue.close ();
66 }
67 
68 // Function to trace change in cwnd at n0
69 static void
70 CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
71 {
72  std::ofstream fPlotQueue (dir + "cwndTraces/n0.dat", std::ios::out | std::ios::app);
73  fPlotQueue << Simulator::Now ().GetSeconds () << " " << newCwnd / segmentSize << std::endl;
74  fPlotQueue.close ();
75 }
76 
77 // Function to calculate drops in a particular Queue
78 static void
80 {
81  *stream->GetStream () << Simulator::Now ().GetSeconds () << " 1" << std::endl;
82 }
83 
84 // Trace Function for cwnd
85 void
86 TraceCwnd (uint32_t node, uint32_t cwndWindow,
88 {
89  Config::ConnectWithoutContext ("/NodeList/" + std::to_string (node) + "/$ns3::TcpL4Protocol/SocketList/" + std::to_string (cwndWindow) + "/CongestionWindow", CwndTrace);
90 }
91 
92 // Function to install BulkSend application
93 void InstallBulkSend (Ptr<Node> node, Ipv4Address address, uint16_t port, std::string socketFactory,
94  uint32_t nodeId, uint32_t cwndWindow,
96 {
97  BulkSendHelper source (socketFactory, InetSocketAddress (address, port));
98  source.SetAttribute ("MaxBytes", UintegerValue (0));
99  ApplicationContainer sourceApps = source.Install (node);
100  sourceApps.Start (Seconds (10.0));
101  Simulator::Schedule (Seconds (10.0) + Seconds (0.001), &TraceCwnd, nodeId, cwndWindow, CwndTrace);
102  sourceApps.Stop (stopTime);
103 }
104 
105 // Function to install sink application
106 void InstallPacketSink (Ptr<Node> node, uint16_t port, std::string socketFactory)
107 {
109  ApplicationContainer sinkApps = sink.Install (node);
110  sinkApps.Start (Seconds (10.0));
111  sinkApps.Stop (stopTime);
112 }
113 
114 int main (int argc, char *argv[])
115 {
116  uint32_t stream = 1;
117  std::string socketFactory = "ns3::TcpSocketFactory";
118  std::string tcpTypeId = "ns3::TcpLinuxReno";
119  std::string qdiscTypeId = "ns3::FifoQueueDisc";
120  bool isSack = true;
121  uint32_t delAckCount = 1;
122  std::string recovery = "ns3::TcpClassicRecovery";
123 
125  cmd.AddValue ("tcpTypeId", "TCP variant to use (e.g., ns3::TcpNewReno, ns3::TcpLinuxReno, etc.)", tcpTypeId);
126  cmd.AddValue ("qdiscTypeId", "Queue disc for gateway (e.g., ns3::CoDelQueueDisc)", qdiscTypeId);
127  cmd.AddValue ("segmentSize", "TCP segment size (bytes)", segmentSize);
128  cmd.AddValue ("delAckCount", "Delayed ack count", delAckCount);
129  cmd.AddValue ("enableSack", "Flag to enable/disable sack in TCP", isSack);
130  cmd.AddValue ("stopTime", "Stop time for applications / simulation time will be stopTime", stopTime);
131  cmd.AddValue ("recovery", "Recovery algorithm type to use (e.g., ns3::TcpPrrRecovery", recovery);
132  cmd.Parse (argc, argv);
133 
134  TypeId qdTid;
135  NS_ABORT_MSG_UNLESS (TypeId::LookupByNameFailSafe (qdiscTypeId, &qdTid), "TypeId " << qdiscTypeId << " not found");
136 
137  // Set recovery algorithm and TCP variant
138  Config::SetDefault ("ns3::TcpL4Protocol::RecoveryType", TypeIdValue (TypeId::LookupByName (recovery)));
139  if (tcpTypeId.compare ("ns3::TcpWestwoodPlus") == 0)
140  {
141  // TcpWestwoodPlus is not an actual TypeId name; we need TcpWestwood here
142  Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpWestwood::GetTypeId ()));
143  // the default protocol type in ns3::TcpWestwood is WESTWOOD
144  Config::SetDefault ("ns3::TcpWestwood::ProtocolType", EnumValue (TcpWestwood::WESTWOODPLUS));
145  }
146  else
147  {
148  TypeId tcpTid;
149  NS_ABORT_MSG_UNLESS (TypeId::LookupByNameFailSafe (tcpTypeId, &tcpTid), "TypeId " << tcpTypeId << " not found");
150  Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TypeId::LookupByName (tcpTypeId)));
151  }
152 
153  // Create nodes
154  NodeContainer leftNodes, rightNodes, routers;
155  routers.Create (2);
156  leftNodes.Create (1);
157  rightNodes.Create (1);
158 
159  std::vector <NetDeviceContainer> leftToRouter;
160  std::vector <NetDeviceContainer> routerToRight;
161 
162  // Create the point-to-point link helpers and connect two router nodes
163  PointToPointHelper pointToPointRouter;
164  pointToPointRouter.SetDeviceAttribute ("DataRate", StringValue ("1Mbps"));
165  pointToPointRouter.SetChannelAttribute ("Delay", StringValue ("10ms"));
166  NetDeviceContainer r1r2ND = pointToPointRouter.Install (routers.Get (0), routers.Get (1));
167 
168  // Create the point-to-point link helpers and connect leaf nodes to router
169  PointToPointHelper pointToPointLeaf;
170  pointToPointLeaf.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
171  pointToPointLeaf.SetChannelAttribute ("Delay", StringValue ("1ms"));
172  leftToRouter.push_back (pointToPointLeaf.Install (leftNodes.Get (0), routers.Get (0)));
173  routerToRight.push_back (pointToPointLeaf.Install (routers.Get (1), rightNodes.Get (0)));
174 
175  InternetStackHelper internetStack;
176 
177  internetStack.Install (leftNodes);
178  internetStack.Install (rightNodes);
179  internetStack.Install (routers);
180 
181  // Assign IP addresses to all the network devices
182  Ipv4AddressHelper ipAddresses ("10.0.0.0", "255.255.255.0");
183 
184  Ipv4InterfaceContainer r1r2IPAddress = ipAddresses.Assign (r1r2ND);
185  ipAddresses.NewNetwork ();
186 
187  std::vector <Ipv4InterfaceContainer> leftToRouterIPAddress;
188  leftToRouterIPAddress.push_back (ipAddresses.Assign (leftToRouter [0]));
189  ipAddresses.NewNetwork ();
190 
191  std::vector <Ipv4InterfaceContainer> routerToRightIPAddress;
192  routerToRightIPAddress.push_back (ipAddresses.Assign (routerToRight [0]));
193 
195 
196  // Set default sender and receiver buffer size as 1MB
197  Config::SetDefault ("ns3::TcpSocket::SndBufSize", UintegerValue (1 << 20));
198  Config::SetDefault ("ns3::TcpSocket::RcvBufSize", UintegerValue (1 << 20));
199 
200  // Set default initial congestion window as 10 segments
201  Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (10));
202 
203  // Set default delayed ack count to a specified value
204  Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (delAckCount));
205 
206  // Set default segment size of TCP packet to a specified value
207  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (segmentSize));
208 
209  // Enable/Disable SACK in TCP
210  Config::SetDefault ("ns3::TcpSocketBase::Sack", BooleanValue (isSack));
211 
212  // Create directories to store dat files
213  struct stat buffer;
214  int retVal;
215  if ((stat (dir.c_str (), &buffer)) == 0)
216  {
217  std::string dirToRemove = "rm -rf " + dir;
218  retVal = system (dirToRemove.c_str ());
219  NS_ASSERT_MSG (retVal == 0, "Error in return value");
220  }
221  std::string dirToSave = "mkdir -p " + dir;
222  retVal = system (dirToSave.c_str ());
223  NS_ASSERT_MSG (retVal == 0, "Error in return value");
224  retVal = system ((dirToSave + "/pcap/").c_str ());
225  NS_ASSERT_MSG (retVal == 0, "Error in return value");
226  retVal = system ((dirToSave + "/queueTraces/").c_str ());
227  NS_ASSERT_MSG (retVal == 0, "Error in return value");
228  retVal = system ((dirToSave + "/cwndTraces/").c_str ());
229  NS_ASSERT_MSG (retVal == 0, "Error in return value");
230  NS_UNUSED (retVal);
231 
232  // Set default parameters for queue discipline
233  Config::SetDefault (qdiscTypeId + "::MaxSize", QueueSizeValue (QueueSize ("100p")));
234 
235  // Install queue discipline on router
237  tch.SetRootQueueDisc (qdiscTypeId);
239  tch.Uninstall (routers.Get (0)->GetDevice (0));
240  qd.Add (tch.Install (routers.Get (0)->GetDevice (0)).Get (0));
241 
242  // Enable BQL
243  tch.SetQueueLimits ("ns3::DynamicQueueLimits");
244 
245  // Calls function to check queue size
247 
248  AsciiTraceHelper asciiTraceHelper;
249  Ptr<OutputStreamWrapper> streamWrapper;
250 
251  // Create dat to store packets dropped and marked at the router
252  streamWrapper = asciiTraceHelper.CreateFileStream (dir + "/queueTraces/drop-0.dat");
253  qd.Get (0)->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DropAtQueue, streamWrapper));
254 
255  // Install packet sink at receiver side
256  uint16_t port = 50000;
257  InstallPacketSink (rightNodes.Get (0), port, "ns3::TcpSocketFactory");
258 
259  // Install BulkSend application
260  InstallBulkSend (leftNodes.Get (0), routerToRightIPAddress [0].GetAddress (1), port, socketFactory, 2, 0, MakeCallback (&CwndChange));
261 
262  // Enable PCAP on all the point to point interfaces
263  pointToPointLeaf.EnablePcapAll (dir + "pcap/ns-3", true);
264 
266  Simulator::Run ();
267 
268  // Store queue stats in a file
269  std::ofstream myfile;
270  myfile.open (dir + "queueStats.txt", std::fstream::in | std::fstream::out | std::fstream::app);
271  myfile << std::endl;
272  myfile << "Stat for Queue 1";
273  myfile << qd.Get (0)->GetStats ();
274  myfile.close ();
275 
276  // Store configuration of the simulation in a file
277  myfile.open (dir + "config.txt", std::fstream::in | std::fstream::out | std::fstream::app);
278  myfile << "qdiscTypeId " << qdiscTypeId << "\n";
279  myfile << "stream " << stream << "\n";
280  myfile << "segmentSize " << segmentSize << "\n";
281  myfile << "delAckCount " << delAckCount << "\n";
282  myfile << "stopTime " << stopTime.As (Time::S) << "\n";
283  myfile.close ();
284 
286 
287  return 0;
288 }
holds a vector of ns3::Application pointers.
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
Manage ASCII trace files for device models.
Definition: trace-helper.h:163
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
void SetAttribute(std::string name, const AttributeValue &value)
Helper function used to set the underlying application attributes, not the socket attributes.
ApplicationContainer Install(NodeContainer c) const
Install an ns3::BulkSendApplication on each node of the input container configured with all the attri...
Callback template class.
Definition: callback.h:1279
Parse command-line arguments.
Definition: command-line.h:229
Hold variables of type enum.
Definition: enum.h:55
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static Ipv4Address GetAny(void)
static void PopulateRoutingTables(void)
Build a routing database and initialize the routing tables of the nodes in the simulation.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
Holds a vector of ns3::QueueDisc pointers.
void Add(QueueDiscContainer other)
Append the contents of another QueueDiscContainer to the end of this container.
Ptr< QueueDisc > Get(std::size_t i) const
Get the Ptr<QueueDisc> stored in this container at a given index.
QueueSize GetCurrentSize(void)
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets,...
Definition: queue-disc.cc:521
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:419
Class for representing queue sizes.
Definition: queue-size.h:95
uint32_t GetValue() const
Get the underlying value.
Definition: queue-size.cc:174
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:587
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Hold variables of type string.
Definition: string.h:41
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-westwood.cc:47
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
@ S
second
Definition: nstime.h:114
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:418
Build a set of QueueDisc objects.
QueueDiscContainer Install(NetDeviceContainer c)
uint16_t SetRootQueueDisc(const std::string &type, Args &&... args)
Helper function used to set a root queue disc of the given type and with the given attributes.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
void Uninstall(NetDeviceContainer c)
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:829
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition: type-id.cc:837
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Hold an unsigned integer type.
Definition: uinteger.h:44
static void CwndTrace(Ptr< OutputStreamWrapper > stream, uint32_t oldCwnd, uint32_t newCwnd)
uint16_t port
Definition: dsdv-manet.cc:45
void InstallBulkSend(Ptr< Node > node, Ipv4Address address, uint16_t port, std::string socketFactory, uint32_t nodeId, uint32_t cwndWindow, Callback< void, uint32_t, uint32_t > CwndTrace)
void TraceCwnd(uint32_t node, uint32_t cwndWindow, Callback< void, uint32_t, uint32_t > CwndTrace)
uint32_t segmentSize
void InstallPacketSink(Ptr< Node > node, uint16_t port, std::string socketFactory)
static void DropAtQueue(Ptr< OutputStreamWrapper > stream, Ptr< const QueueDiscItem > item)
void CheckQueueSize(Ptr< QueueDisc > queue)
Time stopTime
static void CwndChange(uint32_t oldCwnd, uint32_t newCwnd)
std::string dir
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:901
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:51
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
address
Definition: first.py:44
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
cmd
Definition: second.py:35
Ptr< PacketSink > sink
Definition: wifi-tcp.cc:56