A Discrete-Event Network Simulator
API
fd-emu-tc.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017 Universita' degli Studi di Napoli Federico II
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  * Author: Pasquale Imputato <p.imputato@gmail.com>
19  */
20 
21 /*
22  * node
23  * --------------------------------------------------
24  * | |
25  * | pfifo_fast queueDiscType [pfifo_fast]|
26  * | bql [false] |
27  * | interface 0 interface 1 |
28  * | | | |
29  * --------------------------------------------------
30  * | |
31  * 1 Gbps access incoming link | | 100 Mbps bottleneck outgoing link
32  * ----------------------------------- -----------------------------------
33  *
34  * This example builds a node with two interfaces in emulation mode in
35  * either {raw, netmap}. The aim is to explore different qdiscs behaviours
36  * on the backlog of a device emulated bottleneck side.
37  *
38  * If you run emulation in netmap mode, you need before to load the
39  * netmap.ko module. The user is responsible for configuring and building
40  * netmap separately.
41  */
42 
43 #include "ns3/abort.h"
44 #include "ns3/core-module.h"
45 #include "ns3/internet-module.h"
46 #include "ns3/network-module.h"
47 #include "ns3/fd-net-device-module.h"
48 #include "ns3/internet-apps-module.h"
49 #include "ns3/ipv4-list-routing-helper.h"
50 #include "ns3/traffic-control-module.h"
51 
52 using namespace ns3;
53 
54 NS_LOG_COMPONENT_DEFINE ("TrafficControlEmu");
55 
56 void
58 {
59  Simulator::Schedule (Seconds (0.001), &TcPacketsInQueue, q, stream);
60  *stream->GetStream () << Simulator::Now ().GetSeconds () << " backlog " << q->GetNPackets () << "p " << q->GetNBytes () << "b " << " dropped "
61  << q->GetStats ().nTotalDroppedPackets << "p " << q->GetStats ().nTotalDroppedBytes << "b " << std::endl;
62 }
63 
64 #ifdef HAVE_NETMAP_USER_H
65 void
67 {
68  Simulator::Schedule (Seconds (0.001), &Inflight, dev, stream);
69  *stream->GetStream () << dev->GetBytesInNetmapTxRing () << std::endl;
70 }
71 #endif
72 
73 int
74 main (int argc, char *argv[])
75 {
76  NS_LOG_INFO ("Traffic Control Emulation Example");
77 
78  std::string deviceName0 ("enx503f56005a2a");
79  std::string deviceName1 ("eno1");
80  std::string ip0 ("10.0.1.2");
81  std::string ip1 ("10.0.2.1");
82  std::string mask0 ("255.255.255.0");
83  std::string mask1 ("255.255.255.0");
84  std::string m0 ("00:00:00:aa:00:01");
85  std::string m1 ("00:00:00:aa:00:02");
86  std::string queueDiscType = "PfifoFast";
87  bool bql = false;
88 
89  uint32_t index = 0;
90  bool writer = true;
91 #ifdef HAVE_PACKET_H
92  std::string emuMode ("raw");
93 #else // HAVE_NETMAP_USER_H is true (otherwise this example is not compiled)
94  std::string emuMode ("netmap");
95 #endif
96 
98  cmd.AddValue ("deviceName0", "Device name", deviceName0);
99  cmd.AddValue ("deviceName1", "Device name", deviceName1);
100  cmd.AddValue ("ip0", "Local IP address", ip0);
101  cmd.AddValue ("ip1", "Local IP address", ip1);
102  cmd.AddValue ("mask0", "Local mask", mask0);
103  cmd.AddValue ("mask1", "Local mask", mask1);
104  cmd.AddValue ("m0", "Mac address", m0);
105  cmd.AddValue ("m1", "Mac address", m1);
106  cmd.AddValue ("writer", "Enable write stats", writer);
107  cmd.AddValue ("queueDiscType", "Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE}", queueDiscType);
108  cmd.AddValue ("bql", "Enable byte queue limits on bottleneck netdevice", bql);
109  cmd.AddValue ("index", "Experiment index", index);
110  cmd.AddValue ("emuMode", "Emulation mode in {raw, netmap}", emuMode);
111  cmd.Parse (argc, argv);
112 
113  Ipv4Address localIp0 (ip0.c_str ());
114  Ipv4Address localIp1 (ip1.c_str ());
115  Ipv4Mask netmask0 (mask0.c_str ());
116  Ipv4Mask netmask1 (mask1.c_str ());
117  Mac48AddressValue mac0 (m0.c_str ());
118  Mac48AddressValue mac1 (m1.c_str ());
119 
120  //
121  // Since we are using a real piece of hardware we need to use the realtime
122  // simulator.
123  //
124  GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
125 
126  //
127  // Since we are going to be talking to real-world machines, we need to enable
128  // calculation of checksums in our protocols.
129  //
130  GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
131 
132  //
133  // In such a simple topology, the use of the helper API can be a hindrance
134  // so we drop down into the low level API and do it manually.
135  //
136  // First we need a single node.
137  //
138  NS_LOG_INFO ("Create Node");
139  Ptr<Node> node = CreateObject<Node> ();
140 
141  //
142  // Create an emu device, allocate a MAC address and point the device to the
143  // Linux device name. The device needs a transmit queueing discipline so
144  // create a droptail queue and give it to the device. Finally, "install"
145  // the device into the node.
146  //
147  // Do understand that the ns-3 allocated MAC address will be sent out over
148  // your network since the emu net device will spoof it. By default, this
149  // address will have an Organizationally Unique Identifier (OUI) of zero.
150  // The Internet Assigned Number Authority IANA
151  //
152  // http://www.iana.org/assignments/ethernet-numberslocalIp
153  //
154  // reports that this OUI is unassigned, and so should not conflict with
155  // real hardware on your net. It may raise all kinds of red flags in a
156  // real environment to have packets from a device with an obviously bogus
157  // OUI flying around. Be aware.
158  //
159 
160  NS_LOG_INFO ("Create Devices");
161 
162  FdNetDeviceHelper *helper0 = nullptr;
163  FdNetDeviceHelper *helper1 = nullptr;
164 
165 #ifdef HAVE_PACKET_H
166  if (emuMode == "raw")
167  {
169  raw0->SetDeviceName (deviceName0);
170  helper0 = raw0;
171 
173  raw1->SetDeviceName (deviceName1);
174  helper1 = raw1;
175  }
176 #endif
177 #ifdef HAVE_NETMAP_USER_H
178  if (emuMode == "netmap")
179  {
181  netmap0->SetDeviceName (deviceName0);
182  helper0 = netmap0;
183 
185  netmap1->SetDeviceName (deviceName1);
186  helper1 = netmap1;
187  }
188 #endif
189 
190  if ((helper0 == nullptr) || (helper1 == nullptr))
191  {
192  NS_ABORT_MSG (emuMode << " not supported.");
193  }
194 
195  NetDeviceContainer devices0 = helper0->Install (node);
196  NetDeviceContainer devices1 = helper1->Install (node);
197 
198  Ptr<NetDevice> device0 = devices0.Get (0);
199  device0->SetAttribute ("Address", mac0);
200 
201  Ptr<NetDevice> device1 = devices1.Get (0);
202  device1->SetAttribute ("Address", mac1);
203 
204  //
205  // Add a default internet stack to the node. This gets us the ns-3 versions
206  // of ARP, IPv4, ICMP, UDP and TCP.
207  //
208  NS_LOG_INFO ("Add Internet Stack");
209  InternetStackHelper internetStackHelper;
210  internetStackHelper.Install (node);
211 
212  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
213 
214  NS_LOG_INFO ("Create IPv4 Interface 0");
215  uint32_t interface0 = ipv4->AddInterface (device0);
216  Ipv4InterfaceAddress address0 = Ipv4InterfaceAddress (localIp0, netmask0);
217  ipv4->AddAddress (interface0, address0);
218  ipv4->SetMetric (interface0, 0);
219  ipv4->SetForwarding (interface0, true);
220  ipv4->SetUp (interface0);
221 
222  NS_LOG_INFO ("Create IPv4 Interface 1");
223  uint32_t interface1 = ipv4->AddInterface (device1);
224  Ipv4InterfaceAddress address1 = Ipv4InterfaceAddress (localIp1, netmask1);
225  ipv4->AddAddress (interface1, address1);
226  ipv4->SetMetric (interface1, 0);
227  ipv4->SetForwarding (interface1, true);
228  ipv4->SetUp (interface1);
229 
231 
232  // Traffic control configurations
233  // Access link side
235  tch0.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "MaxSize", StringValue ("1000p"));
236  tch0.Install (devices0);
237 
238  // Bottleneck link side
240 
241  if (queueDiscType.compare ("PfifoFast") == 0)
242  {
243  tch1.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "MaxSize", StringValue ("1000p"));
244  }
245  else if (queueDiscType.compare ("ARED") == 0)
246  {
247  tch1.SetRootQueueDisc ("ns3::RedQueueDisc");
248  Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
249  Config::SetDefault ("ns3::RedQueueDisc::MaxSize",
251  Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (1000));
252  Config::SetDefault ("ns3::RedQueueDisc::LinkBandwidth", StringValue ("100Mbps"));
253  Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (83333));
254  Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (250000));
255  }
256  else if (queueDiscType.compare ("CoDel") == 0)
257  {
258  tch1.SetRootQueueDisc ("ns3::CoDelQueueDisc");
259  }
260  else if (queueDiscType.compare ("FqCoDel") == 0)
261  {
262  tch1.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
263  }
264  else if (queueDiscType.compare ("PIE") == 0)
265  {
266  tch1.SetRootQueueDisc ("ns3::PieQueueDisc");
267  Config::SetDefault ("ns3::PieQueueDisc::MaxSize",
269  Config::SetDefault ("ns3::PieQueueDisc::QueueDelayReference", TimeValue (Seconds (0.02)));
270  Config::SetDefault ("ns3::PieQueueDisc::Tupdate", TimeValue (Seconds (0.032)));
271  Config::SetDefault ("ns3::PieQueueDisc::A", DoubleValue (2));
272  Config::SetDefault ("ns3::PieQueueDisc::B", DoubleValue (20));
273  }
274  else
275  {
276  NS_ABORT_MSG ("--queueDiscType not valid");
277  }
278 
279  if (bql)
280  {
281  tch1.SetQueueLimits ("ns3::DynamicQueueLimits");
282  }
283 
284  QueueDiscContainer qdiscs = tch1.Install (devices1);
285  Ptr<QueueDisc> q = qdiscs.Get (0);
286 
287  if (writer)
288  {
289  AsciiTraceHelper ascii;
290  Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("exp-" + std::to_string (index) + "-router-tc-stats.txt");
291  Simulator::Schedule (Seconds (0.001), &TcPacketsInQueue, q, stream);
292 
293 #ifdef HAVE_NETMAP_USER_H
294  if (emuMode.compare ("netmap") == 0)
295  {
296  Ptr<NetmapNetDevice> dev = StaticCast <NetmapNetDevice> (device1);
297  Ptr<OutputStreamWrapper> stream2 = ascii.CreateFileStream ("exp-" + std::to_string (index) + "-router-inflight.txt");
298  Simulator::Schedule (Seconds (0.001), &Inflight, dev, stream2);
299  }
300 #endif
301 
303  Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("router-routes.txt", std::ios::out);
304  g.PrintRoutingTableAllAt (Seconds (3), routingStream);
305  }
306 
307  NS_LOG_INFO ("Run Emulation.");
308  Simulator::Stop (Seconds (50.0));
309  Simulator::Run ();
311  delete helper0;
312  delete helper1;
313  NS_LOG_INFO ("Done.");
314 }
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual uint32_t AddInterface(Ptr< NetDevice > device)=0
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:440
Manage ASCII trace files for device models.
Definition: trace-helper.h:161
AttributeValue implementation for Boolean.
Definition: boolean.h:36
QueueDiscContainer Install(NetDeviceContainer c)
Class for representing queue sizes.
Definition: queue-size.h:94
uint32_t nTotalDroppedPackets
Total dropped packets.
Definition: queue-disc.h:204
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
static void PopulateRoutingTables(void)
Build a routing database and initialize the routing tables of the nodes in the simulation.
Hold variables of type string.
Definition: string.h:41
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:269
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices...
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
aggregate IP/TCP/UDP functionality to existing Nodes.
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:447
build a set of FdNetDevice objects Normally we eschew multiple inheritance, however, the classes PcapUserHelperForDevice and AsciiTraceUserHelperForDevice are treated as "mixins".
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
cmd
Definition: second.py:35
const double m1
First component modulus, 232 - 209.
Definition: rng-stream.cc:58
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we&#39;ll use to write the traced bits. ...
uint32_t GetBytesInNetmapTxRing()
Get the number of bytes currently in the netmap transmission ring.
virtual void SetForwarding(uint32_t interface, bool val)=0
Holds a vector of ns3::QueueDisc pointers.
void TcPacketsInQueue(Ptr< QueueDisc > q, Ptr< OutputStreamWrapper > stream)
Definition: fd-emu-tc.cc:57
virtual NetDeviceContainer Install(Ptr< Node > node) const
This method creates a FdNetDevice and associates it to a node.
AttributeValue implementation for Time.
Definition: nstime.h:1342
virtual void SetUp(uint32_t interface)=0
Hold an unsigned integer type.
Definition: uinteger.h:44
Use number of packets for queue size.
Definition: queue-size.h:44
holds a vector of ns3::NetDevice pointers
Build a set of QueueDisc objects.
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:421
static void Bind(std::string name, const AttributeValue &value)
Iterate over the set of GlobalValues until a matching name is found and then set its value with Globa...
Parse command-line arguments.
Definition: command-line.h:226
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...
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void SetDeviceName(std::string deviceName)
Set the device name of this device.
build a set of FdNetDevice objects attached to a physical network interface
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< QueueDisc > Get(std::size_t i) const
Get the Ptr<QueueDisc> stored in this container at a given index.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
void SetDeviceName(std::string deviceName)
Set the device name of this device.
a class to store IPv4 address information on an interface
AttributeValue implementation for Mac48Address.
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
virtual void SetMetric(uint32_t interface, uint16_t metric)=0
Helper class that adds ns3::Ipv4GlobalRouting objects.
virtual bool AddAddress(uint32_t interface, Ipv4InterfaceAddress address)=0
uint64_t nTotalDroppedBytes
Total dropped bytes.
Definition: queue-disc.h:214
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
build a set of FdNetDevice objects attached to a physical network interface
Use number of bytes for queue size.
Definition: queue-size.h:45
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
static void PrintRoutingTableAllAt(Time printTime, Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S)
prints the routing tables of all nodes at a particular time.