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