A Discrete-Event Network Simulator
API
fd-emu-onoff.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 University of Washington, 2012 INRIA
4  * 2017 Università' degli Studi di Napoli Federico II
5  * 2019 NITK Surathkal
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation;
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Author: Alina Quereilhac <alina.quereilhac@inria.fr>
21  * Extended by: Pasquale Imputato <p.imputato@gmail.com>
22  * Harsh Patel <thadodaharsh10@gmail.com>
23  * Hrishikesh Hiraskar <hrishihiraskar@gmail.com>
24  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
25  *
26  */
27 
28 // +----------------------+ +-----------------------+
29 // | client host | | server host |
30 // +----------------------+ +-----------------------+
31 // | ns-3 Node 0 | | ns-3 Node 1 |
32 // | +----------------+ | | +----------------+ |
33 // | | ns-3 TCP | | | | ns-3 TCP | |
34 // | +----------------+ | | +----------------+ |
35 // | | ns-3 IPv4 | | | | ns-3 IPv4 | |
36 // | +----------------+ | | +----------------+ |
37 // | | FdNetDevice | | | | FdNetDevice | |
38 // | | or | | | | or | |
39 // | | NetmapNetDevice| | | | NetmapNetDevice| |
40 // | | or | | | | or | |
41 // | | DpdkNetDevice | | | | DpdkNetDevice | |
42 // | | 10.1.1.1 | | | | 10.1.1.2 | |
43 // | +----------------+ | | +----------------+ |
44 // | | fd | | | | fd | |
45 // | | or | | | | or | |
46 // | | EAL | | | | EAL | |
47 // | +----------------+ | | +----------------+ |
48 // | | eth0 | | | | eth0 | |
49 // | | or | | | | or | |
50 // | | 0000:00.1f | | | | 0000:00.1f | |
51 // +----+------------+----+ +-----+------------+----+
52 //
53 // 10.1.1.11 10.1.1.12
54 //
55 // | |
56 // +----------------------------+
57 //
58 // This example is aimed at measuring the throughput of the FdNetDevice
59 // when using the EmuFdNetDeviceHelper. This is achieved by saturating
60 // the channel with TCP traffic. Then the throughput can be obtained from
61 // the generated .pcap files.
62 //
63 // To run this example you will need two hosts (client & server).
64 // Steps to run the experiment:
65 //
66 // 1 - Connect the 2 computers with an Ethernet cable.
67 // 2 - Set the IP addresses on both Ethernet devices.
68 //
69 // client machine: $ sudo ip addr add dev eth0 10.1.1.11/24
70 // server machine: $ sudo ip addr add dev eth0 10.1.1.12/24
71 //
72 // 3 - Set both Ethernet devices to promiscuous mode.
73 //
74 // both machines: $ sudo ip link set eth0 promisc on
75 //
76 // 3' - If you run emulation in netmap or dpdk mode, you need before to load
77 // the netmap.ko or dpdk modules. The user is in charge to configure and
78 // build netmap/dpdk separately.
79 //
80 // 4 - Give root suid to the raw or netmap socket creator binary.
81 // If the --enable-sudo option was used to configure ns-3 with waf, then the following
82 // step will not be necessary.
83 //
84 // both hosts: $ sudo chown root.root build/src/fd-net-device/ns3-dev-raw-sock-creator
85 // both hosts: $ sudo chmod 4755 build/src/fd-net-device/ns3-dev-raw-sock-creator
86 //
87 // or (if you run emulation in netmap mode):
88 // both hosts: $ sudo chown root.root build/src/fd-net-device/ns3-dev-netmap-device-creator
89 // both hosts: $ sudo chmod 4755 build/src/fd-net-device/ns3-dev-netmap-device-creator
90 //
91 // 4' - If you run emulation in dpdk mode, you will need to run example as root.
92 //
93 // 5 - In case of DpdkNetDevice, use device address instead of device name
94 //
95 // For example: 0000:00:1f.6 (can be obtained by lspci)
96 //
97 // 6 - Run the server side:
98 //
99 // server host: $ ./waf --run="fd-emu-onoff --serverMode=1"
100 //
101 // 7 - Run the client side:
102 //
103 // client host: $ ./waf --run="fd-emu-onoff"
104 //
105 
106 #include <iostream>
107 #include <fstream>
108 #include <vector>
109 #include <string>
110 
111 #include "ns3/core-module.h"
112 #include "ns3/network-module.h"
113 #include "ns3/internet-module.h"
114 #include "ns3/applications-module.h"
115 #include "ns3/config-store-module.h"
116 #include "ns3/fd-net-device-module.h"
117 
118 using namespace ns3;
119 
120 NS_LOG_COMPONENT_DEFINE ("EmuFdNetDeviceSaturationExample");
121 
122 int
123 main (int argc, char *argv[])
124 {
125  uint16_t sinkPort = 8000;
126  uint32_t packetSize = 1400; // bytes
127  std::string dataRate ("1000Mb/s");
128  bool serverMode = false;
129 
130  std::string deviceName ("eth0");
131  std::string client ("10.1.1.1");
132  std::string server ("10.1.1.2");
133  std::string netmask ("255.255.255.0");
134  std::string macClient ("00:00:00:00:00:01");
135  std::string macServer ("00:00:00:00:00:02");
136  std::string transportProt = "Tcp";
137  std::string socketType;
138 #ifdef HAVE_PACKET_H
139  std::string emuMode ("raw");
140 #elif HAVE_NETMAP_USER_H
141  std::string emuMode ("netmap");
142 #else // HAVE_DPDK_USER_H is true (otherwise this example is not compiled)
143  std::string emuMode ("dpdk");
144 #endif
145 
146  CommandLine cmd (__FILE__);
147  cmd.AddValue ("deviceName", "Device name (in raw, netmap mode) or Device address (in dpdk mode, eg: 0000:00:1f.6). Use `lspci` to find device address.", deviceName);
148  cmd.AddValue ("client", "Local IP address (dotted decimal only please)", client);
149  cmd.AddValue ("server", "Remote IP address (dotted decimal only please)", server);
150  cmd.AddValue ("localmask", "Local mask address (dotted decimal only please)", netmask);
151  cmd.AddValue ("serverMode", "1:true, 0:false, default client", serverMode);
152  cmd.AddValue ("mac-client", "Mac Address for Server Client : 00:00:00:00:00:01", macClient);
153  cmd.AddValue ("mac-server", "Mac Address for Server Default : 00:00:00:00:00:02", macServer);
154  cmd.AddValue ("data-rate", "Data rate defaults to 1000Mb/s", dataRate);
155  cmd.AddValue ("transportProt", "Transport protocol to use: Tcp, Udp", transportProt);
156  cmd.AddValue ("emuMode", "Emulation mode in {raw, netmap}", emuMode);
157  cmd.Parse (argc, argv);
158 
159  if (transportProt.compare ("Tcp") == 0)
160  {
161  socketType = "ns3::TcpSocketFactory";
162  }
163  else
164  {
165  socketType = "ns3::UdpSocketFactory";
166  }
167 
168  Ipv4Address remoteIp;
169  Ipv4Address localIp;
170  Mac48AddressValue localMac;
171 
172  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (packetSize));
173 
174  if (serverMode)
175  {
176  remoteIp = Ipv4Address (client.c_str ());
177  localIp = Ipv4Address (server.c_str ());
178  localMac = Mac48AddressValue (macServer.c_str ());
179  }
180  else
181  {
182  remoteIp = Ipv4Address (server.c_str ());
183  localIp = Ipv4Address (client.c_str ());
184  localMac = Mac48AddressValue (macClient.c_str ());
185  }
186 
187  Ipv4Mask localMask (netmask.c_str ());
188 
189  GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
190 
191  GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
192 
193  NS_LOG_INFO ("Create Node");
194  Ptr<Node> node = CreateObject<Node> ();
195 
196  NS_LOG_INFO ("Create Device");
197  FdNetDeviceHelper* helper = nullptr;
198 
199 #ifdef HAVE_PACKET_H
200  if (emuMode == "raw")
201  {
203  raw->SetDeviceName (deviceName);
204  helper = raw;
205  }
206 #endif
207 #ifdef HAVE_NETMAP_USER_H
208  if (emuMode == "netmap")
209  {
211  netmap->SetDeviceName (deviceName);
212  helper = netmap;
213  }
214 #endif
215 #ifdef HAVE_DPDK_USER_H
216  if (emuMode == "dpdk")
217  {
219  // Use e1000 driver library (this is for IGb PMD supproting Intel 1GbE NIC)
220  // NOTE: DPDK supports multiple Poll Mode Drivers (PMDs) and you can use it
221  // based on your NIC. You just need to set pmd library as follows:
222  dpdk->SetPmdLibrary ("librte_pmd_e1000.so");
223  // Set dpdk driver to use for the NIC. `uio_pci_generic` supports most NICs.
224  dpdk->SetDpdkDriver ("uio_pci_generic");
225  // Set device name
226  dpdk->SetDeviceName (deviceName);
227  helper = dpdk;
228  }
229 #endif
230 
231  if (helper == nullptr)
232  {
233  NS_ABORT_MSG (emuMode << " not supported.");
234  }
235 
236  NetDeviceContainer devices = helper->Install (node);
237  Ptr<NetDevice> device = devices.Get (0);
238  device->SetAttribute ("Address", localMac);
239 
240  NS_LOG_INFO ("Add Internet Stack");
241  InternetStackHelper internetStackHelper;
242  internetStackHelper.SetIpv4StackInstall (true);
243  internetStackHelper.Install (node);
244 
245  NS_LOG_INFO ("Create IPv4 Interface");
246  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
247  uint32_t interface = ipv4->AddInterface (device);
248  Ipv4InterfaceAddress address = Ipv4InterfaceAddress (localIp, localMask);
249  ipv4->AddAddress (interface, address);
250  ipv4->SetMetric (interface, 1);
251  ipv4->SetUp (interface);
252 
253  if (serverMode)
254  {
255  Address sinkLocalAddress (InetSocketAddress (localIp, sinkPort));
256  PacketSinkHelper sinkHelper (socketType, sinkLocalAddress);
257  ApplicationContainer sinkApp = sinkHelper.Install (node);
258  sinkApp.Start (Seconds (1.0));
259  sinkApp.Stop (Seconds (60.0));
260 
261  helper->EnablePcap ("fd-server", device);
262  }
263  else
264  {
265  AddressValue remoteAddress (InetSocketAddress (remoteIp, sinkPort));
266  OnOffHelper onoff (socketType, Address ());
267  onoff.SetAttribute ("Remote", remoteAddress);
268  onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
269  onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
270  onoff.SetAttribute ("DataRate", DataRateValue (dataRate));
271  onoff.SetAttribute ("PacketSize", UintegerValue (packetSize));
272 
273  ApplicationContainer clientApps = onoff.Install (node);
274  clientApps.Start (Seconds (4.0));
275  clientApps.Stop (Seconds (58.0));
276 
277  helper->EnablePcap ("fd-client", device);
278  }
279 
280  Simulator::Stop (Seconds (61.0));
281  Simulator::Run ();
283  delete helper;
284 
285  return 0;
286 }
287 
holds a vector of ns3::Application pointers.
an Inet address class
AttributeValue implementation for Boolean.
Definition: boolean.h:36
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
Hold variables of type string.
Definition: string.h:41
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:269
static const uint32_t packetSize
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.
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
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes...
cmd
Definition: second.py:35
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:42
a polymophic address class
Definition: address.h:90
build a DpdkNetDevice object attached to a physical network interface
virtual NetDeviceContainer Install(Ptr< Node > node) const
This method creates a FdNetDevice and associates it to a node.
virtual void SetUp(uint32_t interface)=0
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetIpv4StackInstall(bool enable)
Enable/disable IPv4 stack install.
holds a vector of ns3::NetDevice pointers
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...
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter...
Parse command-line arguments.
Definition: command-line.h:226
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.
address
Definition: first.py:44
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
AttributeValue implementation for Address.
Definition: address.h:278
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter...
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 DataRate.
Definition: data-rate.h:229
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
void SetDpdkDriver(std::string dpdkDriver)
Sets DPDK Driver to bind NIC to.
clientApps
Definition: first.py:61
virtual bool AddAddress(uint32_t interface, Ipv4InterfaceAddress address)=0
void SetPmdLibrary(std::string pmdLibrary)
Sets PMD Library to be used for the NIC.
void EnablePcap(std::string prefix, Ptr< NetDevice > nd, bool promiscuous=false, bool explicitFilename=false)
Enable pcap output the indicated net device.
devices
Definition: first.py:39
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