A Discrete-Event Network Simulator
API
fd-emu-ping.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 
21 // Allow ns-3 to ping a real host somewhere, using emulation mode
22 //
23 // +--------------------------+
24 // | host |
25 // +--------------------------+
26 // | ns-3 simulation |
27 // +--------------------------+
28 // | ns-3 Node |
29 // | +--------------------+ |
30 // | | ns-3 TCP | |
31 // | +--------------------+ |
32 // | | ns-3 IPv4 | |
33 // | +--------------------+ |
34 // | | FdNetDevice or | |
35 // | | NetmapNetDevice or | |
36 // | | DpdkNetDevice | |
37 // |--+--------------------+--+
38 // | | eth0 | |
39 // | +------+ |
40 // | | |
41 // +------------|-------------+
42 // |
43 // | +---------+
44 // .-------| GW host |--- (Internet) -----
45 // +---------+
46 //
48 // 1) You need to decide on a physical device on your real system, and either
49 // overwrite the hard-configured device name below (eth0) or pass this
50 // device name in as a command-line argument
51 // 1') If you run emulation in dpdk mode, use device address (eg. 0000:00.1f.6)
52 // as device name. This address can be obtained by running `lspci`
53 // 2) The host device must be set to promiscuous mode
54 // (e.g. "sudo ifconfig eth0 promisc")
55 // 2') If you run emulation in netmap or dpdk mode, you need before to load
56 // the netmap.ko or dpdk modules. The user is in charge to configure and
57 // build netmap/dpdk separately.
58 // 3) Be aware that ns-3 will generate a fake mac address, and that in
59 // some enterprise networks, this may be considered bad form to be
60 // sending packets out of your device with "unauthorized" mac addresses
61 // 4) You will need to assign an IP address to the ns-3 simulation node that
62 // is consistent with the subnet that is active on the host device's link.
63 // That is, you will have to assign an IP address to the ns-3 node as if
64 // it were on your real subnet. Search for "Ipv4Address localIp" and
65 // replace the string "1.2.3.4" with a valid IP address.
66 // 5) You will need to configure a default route in the ns-3 node to tell it
67 // how to get off of your subnet. One thing you could do is a
68 // 'netstat -rn' command and find the IP address of the default gateway
69 // on your host. Search for "Ipv4Address gateway" and replace the string
70 // "1.2.3.4" string with the gateway IP address.
71 // 6) Give root suid to the raw or netmap socket creator binary.
72 // If the --enable-sudo option was used to configure ns-3 with ns3, then the following
73 // step will not be necessary.
74 //
75 // $ sudo chown root.root build/src/fd-net-device/ns3-dev-raw-sock-creator
76 // $ sudo chmod 4755 build/src/fd-net-device/ns3-dev-raw-sock-creator
77 //
78 // or (if you run emulation in netmap mode):
79 // $ sudo chown root.root build/src/fd-net-device/ns3-dev-netmap-device-creator
80 // $ sudo chmod 4755 build/src/fd-net-device/ns3-dev-netmap-device-creator
81 // 6') If you run emulation in dpdk mode, you will need to run example as root.
82 //
83 
84 #include "ns3/abort.h"
85 #include "ns3/core-module.h"
86 #include "ns3/internet-module.h"
87 #include "ns3/network-module.h"
88 #include "ns3/fd-net-device-module.h"
89 #include "ns3/internet-apps-module.h"
90 #include "ns3/ipv4-static-routing-helper.h"
91 #include "ns3/ipv4-list-routing-helper.h"
92 
93 using namespace ns3;
94 
95 NS_LOG_COMPONENT_DEFINE ("PingEmulationExample");
96 
97 static void
98 PingRtt (std::string context, Time rtt)
99 {
100  NS_LOG_UNCOND ("Received Response with RTT = " << rtt);
101 }
102 
103 int
104 main (int argc, char *argv[])
105 {
106  NS_LOG_INFO ("Ping Emulation Example");
107 
108  std::string deviceName ("eth0");
109  std::string remote ("8.8.8.8");
110  std::string localAddress ("1.2.3.4");
111  std::string localGateway ("1.2.3.4");
112 #ifdef HAVE_PACKET_H
113  std::string emuMode ("raw");
114 #elif HAVE_NETMAP_USER_H
115  std::string emuMode ("netmap");
116 #else // HAVE_DPDK_USER_H is true (otherwise this example is not compiled)
117  std::string emuMode ("dpdk");
118 #endif
119 
120  //
121  // Allow the user to override any of the defaults at run-time, via
122  // command-line arguments
123  //
124  CommandLine cmd (__FILE__);
125  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);
126  cmd.AddValue ("remote", "Remote IP address (dotted decimal only please)", remote);
127  cmd.AddValue ("localIp", "Local IP address (dotted decimal only please)", localAddress);
128  cmd.AddValue ("gateway", "Gateway address (dotted decimal only please)", localGateway);
129  cmd.AddValue ("emuMode", "Emulation mode in {raw, netmap, dpdk}", emuMode);
130  cmd.Parse (argc, argv);
131 
132  Ipv4Address remoteIp (remote.c_str ());
133  Ipv4Address localIp (localAddress.c_str ());
134  NS_ABORT_MSG_IF (localIp == "1.2.3.4", "You must change the local IP address before running this example");
135 
136  Ipv4Mask localMask ("255.255.255.0");
137 
138  //
139  // Since we are using a real piece of hardware we need to use the realtime
140  // simulator.
141  //
142  GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
143 
144  //
145  // Since we are going to be talking to real-world machines, we need to enable
146  // calculation of checksums in our protocols.
147  //
148  GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
149 
150  //
151  // In such a simple topology, the use of the helper API can be a hindrance
152  // so we drop down into the low level API and do it manually.
153  //
154  // First we need a single node.
155  //
156  NS_LOG_INFO ("Create Node");
157  Ptr<Node> node = CreateObject<Node> ();
158 
159  //
160  // Create an emu device, allocate a MAC address and point the device to the
161  // Linux device name. The device needs a transmit queueing discipline so
162  // create a droptail queue and give it to the device. Finally, "install"
163  // the device into the node.
164  //
165  // Do understand that the ns-3 allocated MAC address will be sent out over
166  // your network since the emu net device will spoof it. By default, this
167  // address will have an Organizationally Unique Identifier (OUI) of zero.
168  // The Internet Assigned Number Authority IANA
169  //
170  // http://www.iana.org/assignments/ethernet-numbers
171  //
172  // reports that this OUI is unassigned, and so should not conflict with
173  // real hardware on your net. It may raise all kinds of red flags in a
174  // real environment to have packets from a device with an obviously bogus
175  // OUI flying around. Be aware.
176  //
177  NS_LOG_INFO ("Create Device");
178 
179  FdNetDeviceHelper* helper = nullptr;
180 
181 #ifdef HAVE_PACKET_H
182  if (emuMode == "raw")
183  {
185  raw->SetDeviceName (deviceName);
186  helper = raw;
187  }
188 #endif
189 #ifdef HAVE_NETMAP_USER_H
190  if (emuMode == "netmap")
191  {
193  netmap->SetDeviceName (deviceName);
194  helper = netmap;
195  }
196 #endif
197 #ifdef HAVE_DPDK_USER_H
198  if (emuMode == "dpdk")
199  {
201  // Use e1000 driver library (this is for IGb PMD supproting Intel 1GbE NIC)
202  // NOTE: DPDK supports multiple Poll Mode Drivers (PMDs) and you can use it
203  // based on your NIC. You just need to set pmd library as follows:
204  dpdk->SetPmdLibrary ("librte_pmd_e1000.so");
205  // Set dpdk driver to use for the NIC. `uio_pci_generic` supports most NICs.
206  dpdk->SetDpdkDriver ("uio_pci_generic");
207  // Set device name
208  dpdk->SetDeviceName (deviceName);
209  helper = dpdk;
210  }
211 #endif
212 
213  if (helper == nullptr)
214  {
215  NS_ABORT_MSG (emuMode << " not supported.");
216  }
217 
218  NetDeviceContainer devices = helper->Install (node);
219  Ptr<NetDevice> device = devices.Get (0);
220  device->SetAttribute ("Address", Mac48AddressValue (Mac48Address::Allocate ()));
221 
222  //Ptr<Queue> queue = CreateObject<DropTailQueue> ();
223  //device->SetQueue (queue);
224  //node->AddDevice (device);
225 
226  //
227  // Add a default internet stack to the node. This gets us the ns-3 versions
228  // of ARP, IPv4, ICMP, UDP and TCP.
229  //
230  NS_LOG_INFO ("Add Internet Stack");
231  InternetStackHelper internetStackHelper;
232  internetStackHelper.Install (node);
233 
234  NS_LOG_INFO ("Create IPv4 Interface");
235  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
236  uint32_t interface = ipv4->AddInterface (device);
237  Ipv4InterfaceAddress address = Ipv4InterfaceAddress (localIp, localMask);
238  ipv4->AddAddress (interface, address);
239  ipv4->SetMetric (interface, 1);
240  ipv4->SetUp (interface);
241 
242  //
243  // When the ping application sends its ICMP packet, it will happily send it
244  // down the ns-3 protocol stack. We set the IP address of the destination
245  // to the address corresponding to example.com above. This address is off
246  // our local network so we have got to provide some kind of default route
247  // to ns-3 to be able to get that ICMP packet forwarded off of our network.
248  //
249  // You have got to provide an IP address of a real host that you can send
250  // real packets to and have them forwarded off of your local network. One
251  // thing you could do is a 'netstat -rn' command and find the IP address of
252  // the default gateway on your host and add it below, replacing the
253  // "1.2.3.4" string.
254  //
255  Ipv4Address gateway (localGateway.c_str ());
256  NS_ABORT_MSG_IF (gateway == "1.2.3.4", "You must change the gateway IP address before running this example");
257 
258  Ipv4StaticRoutingHelper ipv4RoutingHelper;
259  Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4);
260  staticRouting->SetDefaultRoute (gateway, interface);
261 
262  //
263  // Create the ping application. This application knows how to send
264  // ICMP echo requests. Setting up the packet sink manually is a bit
265  // of a hassle and since there is no law that says we cannot mix the
266  // helper API with the low level API, let's just use the helper.
267  //
268  NS_LOG_INFO ("Create V4Ping Appliation");
269  Ptr<V4Ping> app = CreateObject<V4Ping> ();
270  app->SetAttribute ("Remote", Ipv4AddressValue (remoteIp));
271  app->SetAttribute ("Verbose", BooleanValue (true) );
272  node->AddApplication (app);
273  app->SetStartTime (Seconds (1.0));
274  app->SetStopTime (Seconds (22.0));
275 
276  //
277  // Give the application a name. This makes life much easier when constructing
278  // config paths.
279  //
280  Names::Add ("app", app);
281 
282  //
283  // Hook a trace to print something when the response comes back.
284  //
285  Config::Connect ("/Names/app/Rtt", MakeCallback (&PingRtt));
286 
287  //
288  // Enable a promiscuous pcap trace to see what is coming and going on our device.
289  //
290  helper->EnablePcap (emuMode + "-emu-ping", device, true);
291 
292  //
293  // Now, do the actual emulation.
294  //
295  NS_LOG_INFO ("Run Emulation in " << emuMode << " mode.");
296  Simulator::Stop (Seconds (23.0));
297  Simulator::Run ();
299  delete helper;
300  NS_LOG_INFO ("Done.");
301 }
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:229
build a DpdkNetDevice object attached to a physical network interface
void SetPmdLibrary(std::string pmdLibrary)
Sets PMD Library to be used for the NIC.
void SetDpdkDriver(std::string dpdkDriver)
Sets DPDK Driver to bind NIC to.
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.
Definition: ipv4-address.h:41
AttributeValue implementation for Ipv4Address.
Definition: ipv4-address.h:341
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
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
static Mac48Address Allocate(void)
Allocate a new Mac48Address.
AttributeValue implementation for Mac48Address.
static void Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr<Object> obj.
Definition: names.cc:768
holds a vector of ns3::NetDevice pointers
build a set of FdNetDevice objects attached to a physical network interface
void SetDeviceName(std::string deviceName)
Set the device name of this device.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:159
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
void EnablePcap(std::string prefix, Ptr< NetDevice > nd, bool promiscuous=false, bool explicitFilename=false)
Enable pcap output the indicated net device.
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 void Run(void)
Run the simulation.
Definition: simulator.cc:172
Hold variables of type string.
Definition: string.h:41
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
static void PingRtt(std::string context, Time rtt)
Definition: fd-emu-ping.cc:98
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionally.
#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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
address
Definition: first.py:44
devices
Definition: first.py:39
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