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
52using namespace ns3;
53
54NS_LOG_COMPONENT_DEFINE ("TrafficControlEmu");
55
56void
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
65void
67{
68 Simulator::Schedule (Seconds (0.001), &Inflight, dev, stream);
69 *stream->GetStream () << dev->GetBytesInNetmapTxRing () << std::endl;
70}
71#endif
72
73int
74main (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 // https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.txt
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
230 Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
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));
310 Simulator::Destroy ();
311 delete helper0;
312 delete helper1;
313 NS_LOG_INFO ("Done.");
314}
void Run(ObjectFactory &factory, uint32_t pop, uint32_t total, uint32_t runs, Ptr< RandomVariableStream > eventStream, bool calRev)
Perform the runs for a single scheduler type.
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
Parse command-line arguments.
Definition: command-line.h:229
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
build a set of FdNetDevice objects attached to a physical network interface
void SetDeviceName(std::string deviceName)
Set the device name of this device.
build a set of FdNetDevice objects Normally we eschew multiple inheritance, however,...
virtual NetDeviceContainer Install(Ptr< Node > node) const
This method creates a FdNetDevice and associates it to a node.
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...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Helper class that adds ns3::Ipv4GlobalRouting objects.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:77
a class to store IPv4 address information on an interface
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:256
static void PrintRoutingTableAllAt(Time printTime, Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S)
prints the routing tables of all nodes at a particular time.
AttributeValue implementation for Mac48Address.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
build a set of FdNetDevice objects attached to a physical network interface
void SetDeviceName(std::string deviceName)
Set the device name of this device.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
Holds a vector of ns3::QueueDisc pointers.
Ptr< QueueDisc > Get(std::size_t i) const
Get the Ptr<QueueDisc> stored in this container at a given index.
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:445
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:438
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:419
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
Hold variables of type string.
Definition: string.h:41
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
AttributeValue implementation for Time.
Definition: nstime.h:1309
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.
Hold an unsigned integer type.
Definition: uinteger.h:44
void TcPacketsInQueue(Ptr< QueueDisc > q, Ptr< OutputStreamWrapper > stream)
Definition: fd-emu-tc.cc:57
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
@ BYTES
Use number of bytes for queue size.
Definition: queue-size.h:45
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:44
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
const double m1
First component modulus, 232 - 209.
Definition: rng-stream.cc:58
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:43
uint32_t nTotalDroppedPackets
Total dropped packets.
Definition: queue-disc.h:204
uint64_t nTotalDroppedBytes
Total dropped bytes.
Definition: queue-disc.h:214