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