A Discrete-Event Network Simulator
API
v4traceroute.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alberto Gallegos Ramonet
19 *
20 * Traceroute uses ICMPV4 echo messages to trace all the middle hops to a given destination.
21 * It also shows the delay time it takes for a round trip to complete for each
22 * set probe (default 3).
23 *
24 */
25
26
27#include "v4traceroute.h"
28#include "ns3/icmpv4.h"
29#include "ns3/icmpv4-l4-protocol.h"
30#include "ns3/assert.h"
31#include "ns3/log.h"
32#include "ns3/ipv4-address.h"
33#include "ns3/socket.h"
34#include "ns3/uinteger.h"
35#include "ns3/boolean.h"
36#include "ns3/inet-socket-address.h"
37#include "ns3/packet.h"
38#include "ns3/trace-source-accessor.h"
39
40
41namespace ns3 {
42
43NS_LOG_COMPONENT_DEFINE ("V4TraceRoute");
44NS_OBJECT_ENSURE_REGISTERED (V4TraceRoute);
45
46TypeId
48{
49 static TypeId tid = TypeId ("ns3::V4TraceRoute")
51 .SetGroupName ("Internet-Apps")
52 .AddConstructor<V4TraceRoute> ()
53 .AddAttribute ("Remote",
54 "The address of the machine we want to trace.",
56 MakeIpv4AddressAccessor (&V4TraceRoute::m_remote),
57 MakeIpv4AddressChecker ())
58 .AddAttribute ("Verbose",
59 "Produce usual output.",
60 BooleanValue (true),
63 .AddAttribute ("Interval", "Wait interval between sent packets.",
64 TimeValue (Seconds (0)),
67 .AddAttribute ("Size", "The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer.",
68 UintegerValue (56),
70 MakeUintegerChecker<uint32_t> ())
71 .AddAttribute ("MaxHop", "The maximum number of hops to trace.",
72 UintegerValue (30),
74 MakeUintegerChecker<uint32_t> ())
75 .AddAttribute ("ProbeNum", "The number of packets send to each hop.",
76 UintegerValue (3),
78 MakeUintegerChecker<uint16_t> ())
79 .AddAttribute ("Timeout", "The waiting time for a route response before a timeout.",
80 TimeValue (Seconds (5)),
83 ;
84 return tid;
85}
86
87
89 : m_interval (Seconds (0)),
90 m_size (56),
91 m_socket (0),
92 m_seq (0),
93 m_verbose (true),
94 m_probeCount (0),
95 m_maxProbes (3),
96 m_ttl (1),
97 m_maxTtl (30),
98 m_waitIcmpReplyTimeout (Seconds (5))
99{
100 m_osRoute.clear ();
101 m_routeIpv4.clear ();
102}
103
105{
106
107}
108
109
110void
112{
113 m_printStream = stream;
114}
115
116void
118{
119 NS_LOG_FUNCTION (this);
120 NS_LOG_LOGIC ("Application started");
122
123 if (m_verbose)
124 {
125 NS_LOG_UNCOND("Traceroute to " << m_remote << ", "
126 << m_maxTtl << " hops Max, "
127 << m_size << " bytes of data.");
128 }
129
130 if (m_printStream != NULL)
131 {
132 *m_printStream->GetStream () << "Traceroute to " << m_remote << ", "
133 << m_maxTtl << " hops Max, "
134 << m_size << " bytes of data.\n";
135 }
136
137
138 m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
140
141
142 NS_ASSERT (m_socket != 0);
144
146 int status;
147 status = m_socket->Bind (src);
148 NS_ASSERT (status != -1);
149
151}
152
153
154
155void
157{
158 NS_LOG_FUNCTION (this);
159
160 if (m_next.IsRunning ())
161 {
162 m_next.Cancel ();
163 }
164
166 {
168 }
169
170 if (m_socket)
171 {
172 m_socket->Close ();
173 }
174}
175
176void
178{
179 NS_LOG_FUNCTION (this);
180
182 {
184 }
185
186 m_socket = 0;
188}
189
190
193{
194 NS_LOG_FUNCTION (this);
195 Ptr<Node> node = GetNode ();
196 for (uint32_t i = 0; i < node->GetNApplications (); ++i)
197 {
198 if (node->GetApplication (i) == this)
199 {
200 return i;
201 }
202 }
203 NS_ASSERT_MSG (false, "forgot to add application to node");
204 return 0;
205}
206
207void
209{
210 NS_LOG_FUNCTION (this << socket);
211
212 while (m_socket->GetRxAvailable () > 0)
213 {
214 Address from;
215 Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
216 NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
219 NS_ASSERT (realFrom.GetPort () == 1);
220 Ipv4Header ipv4;
221 p->RemoveHeader (ipv4);
223 Icmpv4Header icmp;
224 p->RemoveHeader (icmp);
225
226
227
229 {
230
231 Icmpv4TimeExceeded timeoutResp;
232 p->RemoveHeader (timeoutResp);
233
234 // GetData () gets 64 bits of data, but the received packet
235 // only contains 32 bits of data.
236 uint8_t data [8];
237 timeoutResp.GetData (data);
238
239 // Get the 7th and 8th Octect to obtain the Sequence number from
240 // the original packet.
241 uint16_t recvSeq;
242 recvSeq = (uint16_t) data[7] << 0;
243 recvSeq |= (uint16_t) data [6] << 8;
244
245
246 std::map<uint16_t, Time>::iterator i = m_sent.find (recvSeq);
247 if (i != m_sent.end ())
248 {
249 Time sendTime = i->second;
250 NS_ASSERT (Simulator::Now () >= sendTime);
251 Time delta = Simulator::Now () - sendTime;
252
253 m_routeIpv4.str ("");
254 m_routeIpv4.clear ();
255 m_routeIpv4 << realFrom.GetIpv4 ();
256 m_osRoute << delta.As (Time::MS);
258 {
259 if (m_verbose)
260 {
261 NS_LOG_UNCOND(m_ttl << " " << m_routeIpv4.str () << " " << m_osRoute.str ());
262 }
263
264 if (m_printStream != NULL)
265 {
266 *m_printStream->GetStream () << m_ttl << " "
267 << m_routeIpv4.str () << " "
268 << m_osRoute.str () << "\n";
269 }
270 m_osRoute.str ("");
271 m_osRoute.clear ();
272 m_routeIpv4.str ("");
273 m_routeIpv4.clear ();
274 }
275 else
276 {
277 m_osRoute << " ";
278 }
279
281
282 if (m_ttl < m_maxTtl + 1)
283 {
285 }
286 }
287
288 }
289 else if (icmp.GetType () == Icmpv4Header::ICMPV4_ECHO_REPLY && m_remote == realFrom.GetIpv4 ())
290 {
291 // When UDP is used, TraceRoute should stop until ICMPV4_DEST_UNREACH
292 // (with code (3) PORT_UNREACH) is received, however, the current
293 // ns-3 implementation does not include the UDP version of traceroute.
294 // The traceroute ICMP version (the current version) stops until max_ttl is reached
295 // or until an ICMP ECHO REPLY is received m_maxProbes times.
296
297 Icmpv4Echo echo;
298 p->RemoveHeader (echo);
299 std::map<uint16_t, Time>::iterator i = m_sent.find (echo.GetSequenceNumber ());
300
301 if (i != m_sent.end () && echo.GetIdentifier () == 0)
302 {
303 uint32_t dataSize = echo.GetDataSize ();
304
305 if (dataSize == m_size)
306 {
307 Time sendTime = i->second;
308 NS_ASSERT (Simulator::Now () >= sendTime);
309 Time delta = Simulator::Now () - sendTime;
310
311 m_sent.erase (i);
312
313 if (m_verbose)
314 {
315 m_routeIpv4.str ("");
316 m_routeIpv4.clear ();
317 m_routeIpv4 << realFrom.GetIpv4 ();
318 m_osRoute << delta.As (Time::MS);
319
321 {
322 NS_LOG_UNCOND(m_ttl << " " << m_routeIpv4.str () << " " << m_osRoute.str ());
323 if (m_printStream != NULL)
324 {
325 *m_printStream->GetStream () << m_ttl << " "
326 << m_routeIpv4.str () << " "
327 << m_osRoute.str () << "\n";
328 }
329
330 m_osRoute.clear ();
331 m_routeIpv4.clear ();
332 }
333 else
334 {
335 m_osRoute << " ";
336 }
337 }
338 }
339 }
340
343 {
344 if (m_verbose)
345 {
346 NS_LOG_UNCOND ("\nTrace Complete");
347 }
348
349 if (m_printStream != NULL)
350 {
351 *m_printStream->GetStream () << "Trace Complete\n" << std::endl;
352 }
354 }
355 else if (m_ttl < m_maxTtl + 1)
356 {
358 }
359 }
360 }
361}
362
363
364
365
366void
368{
369 NS_LOG_INFO ("m_seq=" << m_seq);
370 Ptr<Packet> p = Create<Packet> ();
371 Icmpv4Echo echo;
373 m_seq++;
374 echo.SetIdentifier (0);
375
376 //
377 // We must write quantities out in some form of network order. Since there
378 // isn't an htonl to work with we just follow the convention in pcap traces
379 // (where any difference would show up anyway) and borrow that code. Don't
380 // be too surprised when you see that this is a little endian convention.
381 //
382 NS_ASSERT (m_size >= 16);
383
384 Ptr<Packet> dataPacket = Create<Packet> (m_size);
385 echo.SetData (dataPacket);
386 p->AddHeader (echo);
387 Icmpv4Header header;
389 header.SetCode (0);
391 {
392 header.EnableChecksum ();
393 }
394
395 p->AddHeader (header);
396
398 {
399 m_probeCount++;
400 }
401 else
402 {
403 m_probeCount = 1;
404 m_ttl++;
405 }
406
407 m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now ()));
409
410
412 m_socket->SendTo (p, 0, dst);
413}
414
415
416void
418{
419 NS_LOG_FUNCTION (this);
421 {
422 NS_LOG_LOGIC ("Starting WaitIcmpReplyTimer at " << Simulator::Now () << " for " <<
424
427 Send ();
428 }
429}
430
431
432void
434{
435 if (m_ttl < m_maxTtl + 1)
436 {
438 }
439
440 m_osRoute << "* ";
442 {
443 if (m_verbose)
444 {
445 NS_LOG_UNCOND(m_ttl << " " << m_routeIpv4.str () << " " << m_osRoute.str ());
446 }
447
448 if (m_printStream != NULL)
449 {
451 << " " << m_routeIpv4.str () << " "
452 << m_osRoute.str () << "\n";
453 }
454 m_osRoute.str ("");
455 m_osRoute.clear ();
456 m_routeIpv4.str ("");
457 m_routeIpv4.clear ();
458 }
459}
460
461
462} // ns3 namespace
a polymophic address class
Definition: address.h:91
The base class for all ns3 applications.
Definition: application.h:61
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
Ptr< Node > GetNode() const
Definition: application.cc:104
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
ICMP Echo header.
Definition: icmpv4.h:108
uint16_t GetSequenceNumber(void) const
Get the Echo sequence number.
Definition: icmpv4.cc:179
void SetIdentifier(uint16_t id)
Set the Echo identifier.
Definition: icmpv4.cc:140
void SetData(Ptr< const Packet > data)
Set the Echo data.
Definition: icmpv4.cc:152
uint16_t GetIdentifier(void) const
Get the Echo identifier.
Definition: icmpv4.cc:173
uint32_t GetDataSize(void) const
Get the Echo data size.
Definition: icmpv4.cc:185
void SetSequenceNumber(uint16_t seq)
Set the Echo sequence number.
Definition: icmpv4.cc:146
Base class for all the ICMP packet headers.
Definition: icmpv4.h:41
@ ICMPV4_TIME_EXCEEDED
Definition: icmpv4.h:51
void SetCode(uint8_t code)
Set ICMP code.
Definition: icmpv4.cc:115
void SetType(uint8_t type)
Set ICMP type.
Definition: icmpv4.cc:109
uint8_t GetType(void) const
Get ICMP type.
Definition: icmpv4.cc:121
void EnableChecksum(void)
Enables ICMP Checksum calculation.
Definition: icmpv4.cc:57
static const uint8_t PROT_NUMBER
ICMP protocol number (0x1)
ICMP Time Exceeded header.
Definition: icmpv4.h:247
void GetData(uint8_t payload[8]) const
Get the ICMP carried data.
Definition: icmpv4.cc:438
an Inet address class
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
static Ipv4Address GetAny(void)
AttributeValue implementation for Ipv4Address.
Packet header for IPv4.
Definition: ipv4-header.h:34
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
static bool ChecksumEnabled(void)
Definition: node.cc:278
uint32_t GetNApplications(void) const
Definition: node.cc:178
Ptr< Application > GetApplication(uint32_t index) const
Retrieve the index-th Application associated to this node.
Definition: node.cc:170
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:587
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual void SetIpTtl(uint8_t ipTtl)
Manually set IP Time to Live field.
Definition: socket.cc:513
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual int Close(void)=0
Close a socket.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual uint32_t GetRxAvailable(void) const =0
Return number of bytes which can be returned from one or multiple calls to Recv.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ MS
millisecond
Definition: nstime.h:115
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:432
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:829
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
Traceroute application sends one ICMP ECHO request with TTL=1, and after receiving an ICMP TIME EXCEE...
Definition: v4traceroute.h:51
Ipv4Address m_remote
Remote address.
Definition: v4traceroute.h:95
void HandleWaitReplyTimeout()
Triggers an action if an ICMP TIME EXCEED have not being received in the time defined by StartWaitRep...
virtual void StopApplication(void)
Application specific shutdown code.
uint32_t GetApplicationId(void) const
Return the application ID in the node.
EventId m_next
Next packet will be sent.
Definition: v4traceroute.h:114
std::ostringstream m_routeIpv4
The Ipv4 address of the latest hop found.
Definition: v4traceroute.h:133
Ptr< OutputStreamWrapper > m_printStream
Stream of the traceroute used for the output file.
Definition: v4traceroute.h:135
uint32_t m_probeCount
The Current probe value.
Definition: v4traceroute.h:116
static TypeId GetTypeId(void)
Get the type ID.
Definition: v4traceroute.cc:47
uint16_t m_seq
ICMP ECHO sequence number.
Definition: v4traceroute.h:108
virtual void DoDispose(void)
Destructor implementation.
uint16_t m_ttl
The current TTL value.
Definition: v4traceroute.h:120
std::map< uint16_t, Time > m_sent
All sent but not answered packets. Map icmp seqno -> when sent.
Definition: v4traceroute.h:128
Ptr< Socket > m_socket
The socket we send packets from.
Definition: v4traceroute.h:106
uint32_t m_maxTtl
The maximium Ttl (Max number of hops to trace)
Definition: v4traceroute.h:122
Time m_interval
Wait interval seconds between sending each packet.
Definition: v4traceroute.h:98
void Print(Ptr< OutputStreamWrapper > stream)
Prints the application traced routes into a given OutputStream.
virtual ~V4TraceRoute()
std::ostringstream m_osRoute
Stream of characters used for printing a single route.
Definition: v4traceroute.h:131
virtual void StartApplication(void)
Application specific startup code.
Time m_started
Start time to report total ping time.
Definition: v4traceroute.h:112
EventId m_waitIcmpReplyTimer
The timer used to wait for the probes ICMP replies.
Definition: v4traceroute.h:126
uint32_t m_size
Specifies the number of data bytes to be sent.
Definition: v4traceroute.h:104
uint16_t m_maxProbes
The maximum number of probe packets per hop.
Definition: v4traceroute.h:118
Time m_waitIcmpReplyTimeout
The wait time until the response is considered lost.
Definition: v4traceroute.h:124
void Receive(Ptr< Socket > socket)
Receive an ICMP Echo.
void StartWaitReplyTimer()
Starts a timer after sending an ICMP ECHO.
bool m_verbose
produce traceroute style output if true
Definition: v4traceroute.h:110
void Send()
Send one (ICMP ECHO) to the destination.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:536
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
uint8_t data[writeSize]