A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
fd-emu-tc.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Pasquale Imputato <p.imputato@gmail.com>
7 */
8
9/*
10 * node
11 * --------------------------------------------------
12 * | |
13 * | pfifo_fast queueDiscType [pfifo_fast]|
14 * | bql [false] |
15 * | interface 0 interface 1 |
16 * | | | |
17 * --------------------------------------------------
18 * | |
19 * 1 Gbps access incoming link | | 100 Mbps bottleneck outgoing link
20 * ----------------------------------- -----------------------------------
21 *
22 * This example builds a node with two interfaces in emulation mode in
23 * either {raw, netmap}. The aim is to explore different qdiscs behaviours
24 * on the backlog of a device emulated bottleneck side.
25 *
26 * If you run emulation in netmap mode, you need before to load the
27 * netmap.ko module. The user is responsible for configuring and building
28 * netmap separately.
29 */
30
31#include "ns3/abort.h"
32#include "ns3/core-module.h"
33#include "ns3/fd-net-device-module.h"
34#include "ns3/internet-apps-module.h"
35#include "ns3/internet-module.h"
36#include "ns3/ipv4-list-routing-helper.h"
37#include "ns3/network-module.h"
38#include "ns3/traffic-control-module.h"
39
40using namespace ns3;
41
42NS_LOG_COMPONENT_DEFINE("TrafficControlEmu");
43
44void
46{
47 Simulator::Schedule(Seconds(0.001), &TcPacketsInQueue, q, stream);
48 *stream->GetStream() << Simulator::Now().GetSeconds() << " backlog " << q->GetNPackets() << "p "
49 << q->GetNBytes() << "b "
50 << " dropped " << q->GetStats().nTotalDroppedPackets << "p "
51 << q->GetStats().nTotalDroppedBytes << "b " << std::endl;
52}
53
54#ifdef HAVE_NETMAP_USER_H
55void
57{
58 Simulator::Schedule(Seconds(0.001), &Inflight, dev, stream);
59 *stream->GetStream() << dev->GetBytesInNetmapTxRing() << std::endl;
60}
61#endif
62
63int
64main(int argc, char* argv[])
65{
66 NS_LOG_INFO("Traffic Control Emulation Example");
67
68 std::string deviceName0("enx503f56005a2a");
69 std::string deviceName1("eno1");
70 std::string ip0("10.0.1.2");
71 std::string ip1("10.0.2.1");
72 std::string mask0("255.255.255.0");
73 std::string mask1("255.255.255.0");
74 std::string m0("00:00:00:aa:00:01");
75 std::string m1("00:00:00:aa:00:02");
76 std::string queueDiscType = "PfifoFast";
77 bool bql = false;
78
79 uint32_t index = 0;
80 bool writer = true;
81#ifdef HAVE_PACKET_H
82 std::string emuMode("raw");
83#else // HAVE_NETMAP_USER_H is true (otherwise this example is not compiled)
84 std::string emuMode("netmap");
85#endif
86
88 cmd.AddValue("deviceName0", "Device name", deviceName0);
89 cmd.AddValue("deviceName1", "Device name", deviceName1);
90 cmd.AddValue("ip0", "Local IP address", ip0);
91 cmd.AddValue("ip1", "Local IP address", ip1);
92 cmd.AddValue("mask0", "Local mask", mask0);
93 cmd.AddValue("mask1", "Local mask", mask1);
94 cmd.AddValue("m0", "Mac address", m0);
95 cmd.AddValue("m1", "Mac address", m1);
96 cmd.AddValue("writer", "Enable write stats", writer);
97 cmd.AddValue("queueDiscType",
98 "Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE}",
99 queueDiscType);
100 cmd.AddValue("bql", "Enable byte queue limits on bottleneck netdevice", bql);
101 cmd.AddValue("index", "Experiment index", index);
102 cmd.AddValue("emuMode", "Emulation mode in {raw, netmap}", emuMode);
103 cmd.Parse(argc, argv);
104
105 Ipv4Address localIp0(ip0.c_str());
106 Ipv4Address localIp1(ip1.c_str());
107 Ipv4Mask netmask0(mask0.c_str());
108 Ipv4Mask netmask1(mask1.c_str());
109 Mac48AddressValue mac0(m0.c_str());
110 Mac48AddressValue mac1(m1.c_str());
111
112 //
113 // Since we are using a real piece of hardware we need to use the realtime
114 // simulator.
115 //
116 GlobalValue::Bind("SimulatorImplementationType", StringValue("ns3::RealtimeSimulatorImpl"));
117
118 //
119 // Since we are going to be talking to real-world machines, we need to enable
120 // calculation of checksums in our protocols.
121 //
122 GlobalValue::Bind("ChecksumEnabled", BooleanValue(true));
123
124 //
125 // In such a simple topology, the use of the helper API can be a hindrance
126 // so we drop down into the low level API and do it manually.
127 //
128 // First we need a single node.
129 //
130 NS_LOG_INFO("Create Node");
132
133 //
134 // Create an emu device, allocate a MAC address and point the device to the
135 // Linux device name. The device needs a transmit queueing discipline so
136 // create a droptail queue and give it to the device. Finally, "install"
137 // the device into the node.
138 //
139 // Do understand that the ns-3 allocated MAC address will be sent out over
140 // your network since the emu net device will spoof it. By default, this
141 // address will have an Organizationally Unique Identifier (OUI) of zero.
142 // The Internet Assigned Number Authority IANA
143 //
144 // https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.txt
145 //
146 // reports that this OUI is unassigned, and so should not conflict with
147 // real hardware on your net. It may raise all kinds of red flags in a
148 // real environment to have packets from a device with an obviously bogus
149 // OUI flying around. Be aware.
150 //
151
152 NS_LOG_INFO("Create Devices");
153
154 FdNetDeviceHelper* helper0 = nullptr;
155 FdNetDeviceHelper* helper1 = nullptr;
156
157#ifdef HAVE_PACKET_H
158 if (emuMode == "raw")
159 {
160 auto raw0 = new EmuFdNetDeviceHelper;
161 raw0->SetDeviceName(deviceName0);
162 helper0 = raw0;
163
164 auto raw1 = new EmuFdNetDeviceHelper;
165 raw1->SetDeviceName(deviceName1);
166 helper1 = raw1;
167 }
168#endif
169#ifdef HAVE_NETMAP_USER_H
170 if (emuMode == "netmap")
171 {
173 netmap0->SetDeviceName(deviceName0);
174 helper0 = netmap0;
175
177 netmap1->SetDeviceName(deviceName1);
178 helper1 = netmap1;
179 }
180#endif
181
182 if ((helper0 == nullptr) || (helper1 == nullptr))
183 {
184 NS_ABORT_MSG(emuMode << " not supported.");
185 }
186
187 NetDeviceContainer devices0 = helper0->Install(node);
188 NetDeviceContainer devices1 = helper1->Install(node);
189
190 Ptr<NetDevice> device0 = devices0.Get(0);
191 device0->SetAttribute("Address", mac0);
192
193 Ptr<NetDevice> device1 = devices1.Get(0);
194 device1->SetAttribute("Address", mac1);
195
196 //
197 // Add a default internet stack to the node. This gets us the ns-3 versions
198 // of ARP, IPv4, ICMP, UDP and TCP.
199 //
200 NS_LOG_INFO("Add Internet Stack");
201 InternetStackHelper internetStackHelper;
202 internetStackHelper.Install(node);
203
204 Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
205
206 NS_LOG_INFO("Create IPv4 Interface 0");
207 uint32_t interface0 = ipv4->AddInterface(device0);
208 Ipv4InterfaceAddress address0 = Ipv4InterfaceAddress(localIp0, netmask0);
209 ipv4->AddAddress(interface0, address0);
210 ipv4->SetMetric(interface0, 0);
211 ipv4->SetForwarding(interface0, true);
212 ipv4->SetUp(interface0);
213
214 NS_LOG_INFO("Create IPv4 Interface 1");
215 uint32_t interface1 = ipv4->AddInterface(device1);
216 Ipv4InterfaceAddress address1 = Ipv4InterfaceAddress(localIp1, netmask1);
217 ipv4->AddAddress(interface1, address1);
218 ipv4->SetMetric(interface1, 0);
219 ipv4->SetForwarding(interface1, true);
220 ipv4->SetUp(interface1);
221
223
224 // Traffic control configurations
225 // Access link side
227 tch0.SetRootQueueDisc("ns3::PfifoFastQueueDisc", "MaxSize", StringValue("1000p"));
228 tch0.Install(devices0);
229
230 // Bottleneck link side
232
233 if (queueDiscType == "PfifoFast")
234 {
235 tch1.SetRootQueueDisc("ns3::PfifoFastQueueDisc", "MaxSize", StringValue("1000p"));
236 }
237 else if (queueDiscType == "ARED")
238 {
239 tch1.SetRootQueueDisc("ns3::RedQueueDisc");
240 Config::SetDefault("ns3::RedQueueDisc::ARED", BooleanValue(true));
241 Config::SetDefault("ns3::RedQueueDisc::MaxSize",
242 QueueSizeValue(QueueSize(QueueSizeUnit::BYTES, 1000000)));
243 Config::SetDefault("ns3::RedQueueDisc::MeanPktSize", UintegerValue(1000));
244 Config::SetDefault("ns3::RedQueueDisc::LinkBandwidth", StringValue("100Mbps"));
245 Config::SetDefault("ns3::RedQueueDisc::MinTh", DoubleValue(83333));
246 Config::SetDefault("ns3::RedQueueDisc::MinTh", DoubleValue(250000));
247 }
248 else if (queueDiscType == "CoDel")
249 {
250 tch1.SetRootQueueDisc("ns3::CoDelQueueDisc");
251 }
252 else if (queueDiscType == "FqCoDel")
253 {
254 tch1.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
255 }
256 else if (queueDiscType == "PIE")
257 {
258 tch1.SetRootQueueDisc("ns3::PieQueueDisc");
259 Config::SetDefault("ns3::PieQueueDisc::MaxSize",
260 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, 1000)));
261 Config::SetDefault("ns3::PieQueueDisc::QueueDelayReference", TimeValue(Seconds(0.02)));
262 Config::SetDefault("ns3::PieQueueDisc::Tupdate", TimeValue(Seconds(0.032)));
263 Config::SetDefault("ns3::PieQueueDisc::A", DoubleValue(2));
264 Config::SetDefault("ns3::PieQueueDisc::B", DoubleValue(20));
265 }
266 else
267 {
268 NS_ABORT_MSG("--queueDiscType not valid");
269 }
270
271 if (bql)
272 {
273 tch1.SetQueueLimits("ns3::DynamicQueueLimits");
274 }
275
276 QueueDiscContainer qdiscs = tch1.Install(devices1);
277 Ptr<QueueDisc> q = qdiscs.Get(0);
278
279 if (writer)
280 {
281 AsciiTraceHelper ascii;
283 ascii.CreateFileStream("exp-" + std::to_string(index) + "-router-tc-stats.txt");
284 Simulator::Schedule(Seconds(0.001), &TcPacketsInQueue, q, stream);
285
286#ifdef HAVE_NETMAP_USER_H
287 if (emuMode.compare("netmap") == 0)
288 {
291 ascii.CreateFileStream("exp-" + std::to_string(index) + "-router-inflight.txt");
292 Simulator::Schedule(Seconds(0.001), &Inflight, dev, stream2);
293 }
294#endif
295
296 Ptr<OutputStreamWrapper> routingStream =
297 Create<OutputStreamWrapper>("router-routes.txt", std::ios::out);
299 }
300
301 NS_LOG_INFO("Run Emulation.");
305 delete helper0;
306 delete helper1;
307 NS_LOG_INFO("Done.");
308
309 return 0;
310}
Manage ASCII trace files for device models.
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.
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
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.
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...
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.
static void PopulateRoutingTables()
Build a routing database and initialize the routing tables of the nodes in the simulation.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition ipv4.h:69
a class to store IPv4 address information on an interface
a class to represent an Ipv4 address mask
static void PrintRoutingTableAllAt(Time printTime, Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S)
prints the routing tables of all nodes at a particular time.
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.
Smart pointer class similar to boost::intrusive_ptr.
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.
Class for representing queue sizes.
Definition queue-size.h:85
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Hold variables of type string.
Definition string.h:45
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
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:34
void TcPacketsInQueue(Ptr< QueueDisc > q, Ptr< OutputStreamWrapper > stream)
Definition fd-emu-tc.cc:45
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:883
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
const double m1
First component modulus, 232 - 209.
Definition rng-stream.cc:49
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587