A Discrete-Event Network Simulator
API
ping.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022 Chandrakant Jena
3  * Copyright (c) 2007-2009 Strasbourg University (original Ping6 code)
4  * Copyright (c) 2008 INRIA (original Ping code)
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  * Author: Chandrakant Jena <chandrakant.barcelona@gmail.com>
20  * Tommaso Pecorella <tommaso.pecorella@unifi.it>
21  *
22  * Derived from original v4Ping application (author: Mathieu Lacage)
23  * Derived from original ping6 application (author: Sebastien Vincent)
24  */
25 
26 #include "ping.h"
27 
28 #include "ns3/abort.h"
29 #include "ns3/assert.h"
30 #include "ns3/boolean.h"
31 #include "ns3/enum.h"
32 #include "ns3/icmpv4.h"
33 #include "ns3/icmpv6-header.h"
34 #include "ns3/inet-socket-address.h"
35 #include "ns3/ipv4-address.h"
36 #include "ns3/ipv6-extension-header.h"
37 #include "ns3/ipv6-header.h"
38 #include "ns3/ipv6-l3-protocol.h"
39 #include "ns3/ipv6-packet-info-tag.h"
40 #include "ns3/log.h"
41 #include "ns3/packet.h"
42 #include "ns3/socket.h"
43 #include "ns3/trace-source-accessor.h"
44 #include "ns3/uinteger.h"
45 
46 namespace ns3
47 {
48 
50 
52 
54 constexpr uint16_t PING_ID{0xbeef};
55 
56 TypeId
58 {
59  static TypeId tid =
60  TypeId("ns3::Ping")
62  .SetGroupName("Internet-Apps")
63  .AddConstructor<Ping>()
64  .AddAttribute("Destination",
65  "The unicast IPv4 or IPv6 address of the machine we want to ping",
66  AddressValue(),
67  MakeAddressAccessor(&Ping::m_destination),
68  MakeAddressChecker())
69  .AddAttribute("VerboseMode",
70  "Configure verbose, quiet, or silent output",
71  EnumValue(VerboseMode::VERBOSE),
73  MakeEnumChecker(VerboseMode::VERBOSE,
74  "Verbose",
75  VerboseMode::QUIET,
76  "Quiet",
77  VerboseMode::SILENT,
78  "Silent"))
79  .AddAttribute("Interval",
80  "Time interval between sending each packet",
81  TimeValue(Seconds(1)),
84  .AddAttribute(
85  "Size",
86  "The number of data bytes to be sent, before ICMP and IP headers are added",
87  UintegerValue(56),
89  MakeUintegerChecker<uint32_t>(16))
90  .AddAttribute(
91  "Count",
92  "The maximum number of packets the application will send (zero means no limits)",
93  UintegerValue(0),
95  MakeUintegerChecker<uint32_t>())
96  .AddAttribute("InterfaceAddress",
97  "Local address of the sender",
98  AddressValue(),
99  MakeAddressAccessor(&Ping::m_interfaceAddress),
100  MakeAddressChecker())
101  .AddAttribute("Timeout",
102  "Time to wait for a response if no RTT samples are available",
103  TimeValue(Seconds(1)),
105  MakeTimeChecker())
106  .AddTraceSource("Tx",
107  "The sequence number and ICMP echo response packet.",
109  "ns3::Ping::TxTrace")
110  .AddTraceSource("Rtt",
111  "The sequence number and RTT sample.",
113  "ns3::Ping::RttTrace")
114  .AddTraceSource("Drop",
115  "Drop events due to destination unreachable or other errors.",
117  "ns3::Ping::DropTrace")
118  .AddTraceSource("Report",
119  "Summary report at close of application.",
121  "ns3::Ping::ReportTrace");
122  return tid;
123 }
124 
126 {
127  NS_LOG_FUNCTION(this);
128 }
129 
131 {
132  NS_LOG_FUNCTION(this);
133 }
134 
135 void
137 {
138  NS_LOG_FUNCTION(this);
139  StopApplication();
140  m_socket = nullptr;
142 }
143 
144 uint64_t
146 {
147  NS_LOG_FUNCTION(this);
148 
149  uint64_t appSignature = GetNode()->GetId();
150  appSignature <<= 32;
151 
152  Ptr<Node> node = GetNode();
153  for (uint32_t i = 0; i < node->GetNApplications(); ++i)
154  {
155  if (node->GetApplication(i) == this)
156  {
157  appSignature += i;
158  return appSignature;
159  }
160  }
161  NS_ASSERT_MSG(false, "forgot to add application to node");
162  return 0; // quiet compiler
163 }
164 
165 void
167 {
168  NS_LOG_FUNCTION(this << socket);
169 
170  while (m_socket->GetRxAvailable() > 0)
171  {
172  Address from;
173  Ptr<Packet> packet = m_socket->RecvFrom(from);
174  uint32_t recvSize = packet->GetSize();
175  NS_LOG_DEBUG("recv " << recvSize << " bytes " << *packet);
176 
178  {
180  Ipv4Header ipv4Hdr;
181  packet->RemoveHeader(ipv4Hdr);
182  recvSize -= ipv4Hdr.GetSerializedSize();
183  Icmpv4Header icmp;
184  packet->RemoveHeader(icmp);
185 
186  switch (icmp.GetType())
187  {
189  Icmpv4Echo echo;
190  packet->RemoveHeader(echo);
191 
192  if (echo.GetIdentifier() != PING_ID)
193  {
194  return;
195  }
196 
197  NS_LOG_INFO("Received Echo Reply size = "
198  << std::dec << recvSize << " bytes from " << realFrom.GetIpv4()
199  << " id = " << echo.GetIdentifier()
200  << " seq = " << echo.GetSequenceNumber()
201  << " TTL = " << static_cast<uint16_t>(ipv4Hdr.GetTtl()));
202 
203  uint32_t dataSize = echo.GetDataSize();
204  if (dataSize < 8)
205  {
206  NS_LOG_INFO("Packet too short, discarding");
207  return;
208  }
209  uint8_t* buf = new uint8_t[dataSize];
210  echo.GetData(buf);
211  uint64_t appSignature = Read64(buf);
212  delete[] buf;
213 
214  if (appSignature == m_appSignature)
215  {
216  Time sendTime = m_sent.at(echo.GetSequenceNumber()).txTime;
217  NS_ASSERT(Simulator::Now() >= sendTime);
218  Time delta = Simulator::Now() - sendTime;
219 
220  bool dupReply = false;
221  if (m_sent.at(echo.GetSequenceNumber()).acked)
222  {
223  m_duplicate++;
224  dupReply = true;
225  }
226  else
227  {
228  m_recv++;
229  m_sent.at(echo.GetSequenceNumber()).acked = true;
230  }
231 
232  m_avgRtt.Update(delta.GetMilliSeconds());
234 
235  if (m_verbose == VerboseMode::VERBOSE)
236  {
237  std::cout << recvSize << " bytes from " << realFrom.GetIpv4() << ":"
238  << " icmp_seq=" << echo.GetSequenceNumber()
239  << " ttl=" << static_cast<uint16_t>(ipv4Hdr.GetTtl())
240  << " time=" << delta.GetMicroSeconds() / 1000.0 << " ms";
241  if (dupReply && !m_multipleDestinations)
242  {
243  std::cout << " (DUP!)";
244  }
245  std::cout << "\n";
246  }
247  }
248 
249  break;
250  }
252  Icmpv4DestinationUnreachable destUnreach;
253  packet->RemoveHeader(destUnreach);
254 
255  NS_LOG_INFO("Received Destination Unreachable from " << realFrom.GetIpv4());
256  break;
257  }
259  Icmpv4TimeExceeded timeExceeded;
260  packet->RemoveHeader(timeExceeded);
261 
262  NS_LOG_INFO("Received Time Exceeded from " << realFrom.GetIpv4());
263  break;
264  }
265  default:
266  break;
267  }
268  }
269  else if (Inet6SocketAddress::IsMatchingType(from))
270  {
272  Ipv6Header ipv6Hdr;
273 
274  // We need the IP interface index.
275  Ipv6PacketInfoTag infoTag;
276  packet->RemovePacketTag(infoTag);
278  Ipv6Address myAddr = infoTag.GetAddress();
279  int32_t ipIfIndex = ipv6->GetInterfaceForAddress(myAddr);
280 
281  packet->RemoveHeader(ipv6Hdr);
282  recvSize -= ipv6Hdr.GetSerializedSize();
283  uint8_t type;
284  packet->CopyData(&type, sizeof(type));
285 
286  switch (type)
287  {
289  Icmpv6Echo echo(0);
290  packet->RemoveHeader(echo);
291 
292  if (echo.GetId() != PING_ID)
293  {
294  return;
295  }
296 
297  NS_LOG_INFO("Received Echo Reply size = "
298  << std::dec << recvSize << " bytes from " << realFrom.GetIpv6()
299  << " id = " << echo.GetId() << " seq = " << echo.GetSeq()
300  << " Hop Count = " << static_cast<uint16_t>(ipv6Hdr.GetHopLimit()));
301 
302  uint32_t dataSize = packet->GetSize();
303  if (dataSize < 8)
304  {
305  NS_LOG_INFO("Packet too short, discarding");
306  return;
307  }
308  uint8_t* buf = new uint8_t[dataSize];
309  packet->CopyData(buf, dataSize);
310  uint64_t appSignature = Read64(buf);
311  delete[] buf;
312 
313  if (appSignature == m_appSignature)
314  {
315  Time sendTime = m_sent.at(echo.GetSeq()).txTime;
316  NS_ASSERT(Simulator::Now() >= sendTime);
317  Time delta = Simulator::Now() - sendTime;
318 
319  bool dupReply = false;
320  if (m_sent.at(echo.GetSeq()).acked)
321  {
322  m_duplicate++;
323  dupReply = true;
324  }
325  else
326  {
327  m_recv++;
328  m_sent.at(echo.GetSeq()).acked = true;
329  }
330 
331  m_avgRtt.Update(delta.GetMilliSeconds());
332  m_rttTrace(echo.GetSeq(), delta);
333 
334  if (m_verbose == VerboseMode::VERBOSE)
335  {
336  std::cout << recvSize << " bytes from (" << realFrom.GetIpv6() << "):"
337  << " icmp_seq=" << echo.GetSeq()
338  << " ttl=" << static_cast<uint16_t>(ipv6Hdr.GetHopLimit())
339  << " time=" << delta.GetMicroSeconds() / 1000.0 << " ms";
340  if (dupReply)
341  {
342  std::cout << " (DUP!)";
343  }
344  std::cout << "\n";
345  }
346  }
347  ipv6->ReachabilityHint(ipIfIndex, realFrom.GetIpv6());
348  break;
349  }
351  Icmpv6DestinationUnreachable destUnreach;
352  packet->RemoveHeader(destUnreach);
353 
354  NS_LOG_INFO("Received Destination Unreachable from " << realFrom.GetIpv6());
355  break;
356  }
358  Icmpv6TimeExceeded timeExceeded;
359  packet->RemoveHeader(timeExceeded);
360 
361  NS_LOG_INFO("Received Time Exceeded from " << realFrom.GetIpv6());
362  break;
363  }
364  default:
365  break;
366  }
367  }
368  }
369 
370  if (!m_multipleDestinations && m_count > 0 && m_recv == m_count)
371  {
373  }
374 }
375 
376 // Writes data to buffer in little-endian format; least significant byte
377 // of data is at lowest buffer address
378 void
379 Ping::Write64(uint8_t* buffer, const uint64_t data)
380 {
381  NS_LOG_FUNCTION(this << (void*)buffer << data);
382  buffer[0] = (data >> 0) & 0xff;
383  buffer[1] = (data >> 8) & 0xff;
384  buffer[2] = (data >> 16) & 0xff;
385  buffer[3] = (data >> 24) & 0xff;
386  buffer[4] = (data >> 32) & 0xff;
387  buffer[5] = (data >> 40) & 0xff;
388  buffer[6] = (data >> 48) & 0xff;
389  buffer[7] = (data >> 56) & 0xff;
390 }
391 
392 // Read data from a little-endian formatted buffer to data
393 uint64_t
394 Ping::Read64(const uint8_t* buffer)
395 {
396  NS_LOG_FUNCTION(this << (void*)buffer);
397  uint64_t data = buffer[7];
398  data <<= 8;
399  data |= buffer[6];
400  data <<= 8;
401  data |= buffer[5];
402  data <<= 8;
403  data |= buffer[4];
404  data <<= 8;
405  data |= buffer[3];
406  data <<= 8;
407  data |= buffer[2];
408  data <<= 8;
409  data |= buffer[1];
410  data <<= 8;
411  data |= buffer[0];
412 
413  return data;
414 }
415 
416 void
418 {
419  NS_LOG_FUNCTION(this);
420 
421  NS_LOG_INFO("m_seq=" << m_seq);
422 
423  // Prepare the payload.
424  // We must write quantities out in some form of network order. Since there
425  // isn't an htonl to work with we just follow the convention in pcap traces
426  // (where any difference would show up anyway) and borrow that code. Don't
427  // be too surprised when you see that this is a little endian convention.
428  //
429  uint8_t* data = new uint8_t[m_size];
430  memset(data, 0, m_size);
431  NS_ASSERT_MSG(m_size >= 16, "ECHO Payload size must be at least 16 bytes");
432 
434  Ptr<Packet> dataPacket = Create<Packet>(data, m_size);
435 
436  Ptr<Packet> p = Create<Packet>();
437  int returnValue = 0;
438 
439  if (!m_useIpv6)
440  {
441  // Using IPv4
442  Icmpv4Echo echo;
443  echo.SetSequenceNumber(m_seq);
444  echo.SetIdentifier(PING_ID);
445 
446  // In the Icmpv4Echo the payload is part of the header.
447  echo.SetData(dataPacket);
448 
449  p->AddHeader(echo);
450  Icmpv4Header header;
452  header.SetCode(0);
453  if (Node::ChecksumEnabled())
454  {
455  header.EnableChecksum();
456  }
457  p->AddHeader(header);
458  returnValue =
460  }
461  else
462  {
463  // Using IPv6
464  Icmpv6Echo echo(true);
465 
466  echo.SetSeq(m_seq);
467  echo.SetId(PING_ID);
468 
469  // In the Icmpv6Echo the payload is just the content of the packet.
470  p = dataPacket->Copy();
471 
472  p->AddHeader(echo);
473 
474  /* use Loose Routing (routing type 0) */
475  if (!m_routers.empty())
476  {
477  Ipv6ExtensionLooseRoutingHeader routingHeader;
478  routingHeader.SetNextHeader(Ipv6Header::IPV6_ICMPV6);
479  routingHeader.SetTypeRouting(0);
480  routingHeader.SetSegmentsLeft(m_routers.size());
481  routingHeader.SetRoutersAddress(m_routers);
482  p->AddHeader(routingHeader);
484  }
485 
486  returnValue =
488 
489  // Loose routing could have changed (temporarily) the protocol. Set it again to receive the
490  // replies.
492  }
493  if (returnValue > 0)
494  {
495  m_sent.emplace_back(Simulator::Now(), false);
496  m_txTrace(m_seq, p);
497  }
498  else
499  {
500  NS_LOG_INFO("Send failure; socket return value: " << returnValue);
501  }
502  m_seq++;
503  delete[] data;
504 
505  if (m_count == 0 || m_seq < m_count)
506  {
508  }
509 
510  // We have sent all the requests. Schedule a shutdown after the linger time
511  if (m_count > 0 && m_seq == m_count)
512  {
513  Time lingerTime = m_avgRtt.Count() > 0 ? MilliSeconds(2 * m_avgRtt.Max()) : m_timeout;
514  Simulator::Schedule(lingerTime, &Ping::StopApplication, this);
515  }
516 }
517 
518 void
520 {
521  NS_LOG_FUNCTION(this);
522 
523  if (m_destination.IsInvalid())
524  {
525  NS_ABORT_MSG("Destination Address value must be set when starting application");
526  }
527 
529 
531  m_reportPrinted = false;
532  if (m_verbose == VerboseMode::VERBOSE || m_verbose == VerboseMode::QUIET)
533  {
535  {
537  std::cout << "PING " << realFrom.GetIpv4() << " - " << m_size << " bytes of data; "
538  << m_size + 28 << " bytes including ICMP and IPv4 headers.\n";
539  }
541  {
543  std::cout << "PING " << realFrom.GetIpv6() << " - " << m_size << " bytes of data; "
544  << m_size + 48 << " bytes including ICMP and IPv6 headers.\n";
545  }
546  else
547  {
548  NS_ABORT_MSG("Invalid Address");
549  }
550  }
551 
553  {
554  m_socket =
555  Socket::CreateSocket(GetNode(), TypeId::LookupByName("ns3::Ipv4RawSocketFactory"));
556  NS_ASSERT_MSG(m_socket, "Ping::StartApplication: can not create socket.");
557  m_socket->SetAttribute("Protocol", UintegerValue(1)); // icmp
559  m_useIpv6 = false;
560 
563  }
565  {
566  m_socket =
567  Socket::CreateSocket(GetNode(), TypeId::LookupByName("ns3::Ipv6RawSocketFactory"));
568  NS_ASSERT_MSG(m_socket, "Ping::StartApplication: can not create socket.");
571  m_socket->SetRecvPktInfo(true);
572  m_useIpv6 = true;
573 
576  }
577  else
578  {
579  NS_ABORT_MSG("Destination Address value must be of type Ipv4 or Ipv6");
580  }
581 
583  {
585  {
586  InetSocketAddress senderInet =
588  int status = m_socket->Bind(senderInet);
589  NS_ASSERT_MSG(status == 0, "Failed to bind IPv4 socket");
590  }
592  {
593  Inet6SocketAddress senderInet =
595  int status = m_socket->Bind(senderInet);
596  NS_ASSERT_MSG(status == 0, "Failed to bind IPv6 socket");
597  }
598  else
599  {
600  NS_ABORT_MSG("Sender Address value must be of type Ipv4 or Ipv6");
601  }
602  }
603 
604  // Guess how large should be the data storage and pre-book it.
605  if (m_count == 0)
606  {
607  Time delta = m_stopTime - Now();
608  int64_t guessedTx = Div(delta, m_interval) + 1;
609  m_sent.reserve(guessedTx);
610  }
611  else
612  {
613  m_sent.reserve(m_count);
614  }
615 
616  Send();
617 }
618 
619 void
621 {
622  NS_LOG_FUNCTION(this);
623  if (m_stopEvent.IsRunning())
624  {
626  }
627  if (m_next.IsRunning())
628  {
629  m_next.Cancel();
630  }
631  if (m_socket)
632  {
633  m_socket->Close();
634  }
635  PrintReport();
636 }
637 
638 void
640 {
641  if (m_reportPrinted)
642  {
643  return;
644  }
645  m_reportPrinted = true;
646 
647  if (m_verbose == VerboseMode::VERBOSE || m_verbose == VerboseMode::QUIET)
648  {
649  std::ostringstream os;
650  os.precision(4);
652  {
654  os << "\n--- " << realFrom.GetIpv4() << " ping statistics ---\n";
655  }
657  {
659  os << "\n--- " << realFrom.GetIpv6() << " ping statistics ---\n";
660  }
661  os << m_seq << " packets transmitted, " << m_recv << " received, ";
662  if (m_duplicate)
663  {
664  os << m_duplicate << " duplicates, ";
665  }
666 
667  // note: integer math to match Linux implementation and avoid turning a 99.9% into a 100%.
668  os << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, "
669  << "time " << (Simulator::Now() - m_started).GetMilliSeconds() << "ms\n";
670 
671  if (m_avgRtt.Count() > 0)
672  {
673  os << "rtt min/avg/max/mdev = " << m_avgRtt.Min() << "/" << m_avgRtt.Avg() << "/"
674  << m_avgRtt.Max() << "/" << m_avgRtt.Stddev() << " ms\n";
675  }
676  std::cout << os.str();
677  }
678  PingReport report;
679  report.m_transmitted = m_seq;
680  report.m_received = m_recv;
681  // note: integer math to match Linux implementation and avoid turning a 99.9% into a 100%.
682  report.m_loss = (m_seq - m_recv) * 100 / m_seq;
683  report.m_duration = (Simulator::Now() - m_started);
684  report.m_rttMin = m_avgRtt.Min();
685  report.m_rttAvg = m_avgRtt.Avg();
686  report.m_rttMax = m_avgRtt.Max();
687  report.m_rttMdev = m_avgRtt.Stddev();
688  m_reportTrace(report);
689 }
690 
691 void
692 Ping::SetRouters(const std::vector<Ipv6Address>& routers)
693 {
694  m_routers = routers;
695 }
696 
697 } // namespace ns3
a polymophic address class
Definition: address.h:100
bool IsInvalid() const
Definition: address.cc:71
AttributeValue implementation for Address.
The base class for all ns3 applications.
Definition: application.h:61
void DoDispose() override
Destructor implementation.
Definition: application.cc:85
Time m_stopTime
The simulation time that the application will end.
Definition: application.h:150
EventId m_stopEvent
The event that will fire at m_stopTime to end the application.
Definition: application.h:152
Ptr< Node > GetNode() const
Definition: application.cc:107
Ptr< Node > m_node
The node that this application is installed on.
Definition: application.h:148
double Avg() const
Sample average.
Definition: average.h:107
T Min() const
Sample minimum.
Definition: average.h:89
T Max() const
Sample maximum.
Definition: average.h:98
void Update(const T &x)
Add new sample.
Definition: average.h:55
uint32_t Count() const
Sample size.
Definition: average.h:80
double Stddev() const
Sample standard deviation.
Definition: average.h:134
Hold variables of type enum.
Definition: enum.h:56
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
ICMP Destination Unreachable header.
Definition: icmpv4.h:174
ICMP Echo header.
Definition: icmpv4.h:109
uint32_t GetData(uint8_t payload[]) const
Get the Echo data.
Definition: icmpv4.cc:207
void SetIdentifier(uint16_t id)
Set the Echo identifier.
Definition: icmpv4.cc:150
void SetData(Ptr< const Packet > data)
Set the Echo data.
Definition: icmpv4.cc:164
uint16_t GetIdentifier() const
Get the Echo identifier.
Definition: icmpv4.cc:186
void SetSequenceNumber(uint16_t seq)
Set the Echo sequence number.
Definition: icmpv4.cc:157
uint32_t GetDataSize() const
Get the Echo data size.
Definition: icmpv4.cc:200
uint16_t GetSequenceNumber() const
Get the Echo sequence number.
Definition: icmpv4.cc:193
Base class for all the ICMP packet headers.
Definition: icmpv4.h:42
@ ICMPV4_TIME_EXCEEDED
Definition: icmpv4.h:52
@ ICMPV4_DEST_UNREACH
Definition: icmpv4.h:50
void SetCode(uint8_t code)
Set ICMP code.
Definition: icmpv4.cc:123
void SetType(uint8_t type)
Set ICMP type.
Definition: icmpv4.cc:116
void EnableChecksum()
Enables ICMP Checksum calculation.
Definition: icmpv4.cc:60
uint8_t GetType() const
Get ICMP type.
Definition: icmpv4.cc:130
ICMP Time Exceeded header.
Definition: icmpv4.h:249
ICMPv6 Error Destination Unreachable header.
ICMPv6 Echo message.
void SetId(uint16_t id)
Set the ID of the packet.
uint16_t GetId() const
Get the ID of the packet.
void SetSeq(uint16_t seq)
Set the sequence number.
uint16_t GetSeq() const
Get the sequence number.
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
Definition: icmpv6-header.h:45
ICMPv6 Error Time Exceeded header.
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6() const
Get the IPv6 address.
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
bool IsMulticast() const
static Ipv4Address ConvertFrom(const Address &address)
static bool IsMatchingType(const Address &address)
bool IsBroadcast() const
Packet header for IPv4.
Definition: ipv4-header.h:34
uint32_t GetSerializedSize() const override
Definition: ipv4-header.cc:384
uint8_t GetTtl() const
Definition: ipv4-header.cc:274
Describes an IPv6 address.
Definition: ipv6-address.h:50
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
static Ipv6Address ConvertFrom(const Address &address)
Convert the Address object into an Ipv6Address ones.
static bool IsMatchingType(const Address &address)
If the Address matches the type.
void SetNextHeader(uint8_t nextHeader)
Set the "Next header" field.
Header of IPv6 Extension Routing : Type 0 (Loose Routing)
void SetRoutersAddress(std::vector< Ipv6Address > routersAddress)
Set the vector of routers' address.
void SetTypeRouting(uint8_t typeRouting)
Set the "Type of Routing" field.
void SetSegmentsLeft(uint8_t segmentsLeft)
Set the "Segments left" field.
Packet header for IPv6.
Definition: ipv6-header.h:36
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:100
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ipv6-header.cc:159
IPv6 layer implementation.
This class implements a tag that carries socket ancillary data to the socket interface.
Ipv6Address GetAddress() const
Get the tag's address.
uint32_t GetNApplications() const
Definition: node.cc:190
Ptr< Application > GetApplication(uint32_t index) const
Retrieve the index-th Application associated to this node.
Definition: node.cc:180
uint32_t GetId() const
Definition: node.cc:117
static bool ChecksumEnabled()
Definition: node.cc:290
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
This application behaves similarly to the Unix ping application, although with fewer options supporte...
Definition: ping.h:56
uint32_t m_size
Specifies the number of data bytes to be sent.
Definition: ping.h:213
uint32_t m_recv
Received packets counter.
Definition: ping.h:229
Time m_started
Start time to report total ping time.
Definition: ping.h:233
bool m_reportPrinted
True if the report has been printed already.
Definition: ping.h:268
std::vector< EchoRequestData > m_sent
All sent but not answered packets. Map icmp seqno -> when sent, acked at least once.
Definition: ping.h:261
uint64_t Read64(const uint8_t *buffer)
Writes data from a little-endian formatted buffer to data.
Definition: ping.cc:394
bool m_useIpv6
Use IPv4 (false) or IPv6 (true)
Definition: ping.h:270
void SetRouters(const std::vector< Ipv6Address > &routers)
Set routers for IPv6 routing type 0 (loose routing).
Definition: ping.cc:692
std::vector< Ipv6Address > m_routers
Routers addresses for IPv6 routing type 0.
Definition: ping.h:275
~Ping() override
Destructor.
Definition: ping.cc:130
TracedCallback< uint16_t, Ptr< Packet > > m_txTrace
Callbacks for tracing the packet Tx events.
Definition: ping.h:219
uint64_t m_appSignature
App signature: ID of the node where the app is installed || ID of the Application.
Definition: ping.h:278
uint32_t m_count
Number of packets to be sent.
Definition: ping.h:263
uint64_t GetApplicationSignature() const
Return the application signatiure.
Definition: ping.cc:145
void Send()
Send one Ping (ICMPv4 ECHO or ICMPv6 ECHO) to the destination.
Definition: ping.cc:417
void DoDispose() override
Destructor implementation.
Definition: ping.cc:136
void StartApplication() override
Application specific startup code.
Definition: ping.cc:519
void StopApplication() override
Application specific shutdown code.
Definition: ping.cc:620
Average< double > m_avgRtt
Average rtt is ms.
Definition: ping.h:235
void PrintReport()
Print the report.
Definition: ping.cc:639
Ping()
Constructor.
Definition: ping.cc:125
Time m_interval
Wait interval between ECHO requests.
Definition: ping.h:206
static TypeId GetTypeId()
Get the type ID.
Definition: ping.cc:57
bool m_multipleDestinations
Destination is Broadcast or Multicast.
Definition: ping.h:272
uint16_t m_seq
ICMP ECHO sequence number.
Definition: ping.h:217
uint32_t m_duplicate
Duplicate packets counter.
Definition: ping.h:231
Address m_interfaceAddress
Sender Local Address.
Definition: ping.h:202
void Receive(Ptr< Socket > socket)
Receive an ICMPv4 or an ICMPv6 Echo reply.
Definition: ping.cc:166
void Write64(uint8_t *buffer, const uint64_t data)
Writes data to buffer in little-endian format.
Definition: ping.cc:379
Address m_destination
Remote address.
Definition: ping.h:204
EventId m_next
Next packet will be sent.
Definition: ping.h:237
Ptr< Socket > m_socket
The socket we send packets from.
Definition: ping.h:215
VerboseMode m_verbose
Variable to stor verbose mode.
Definition: ping.h:227
TracedCallback< const struct PingReport & > m_reportTrace
TracedCallback for final ping report.
Definition: ping.h:225
TracedCallback< uint16_t, DropReason > m_dropTrace
TracedCallback for drop events.
Definition: ping.h:223
Time m_timeout
Time to wait for a response, in seconds.
Definition: ping.h:266
TracedCallback< uint16_t, Time > m_rttTrace
TracedCallback for RTT samples.
Definition: ping.h:221
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:606
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:352
virtual uint32_t GetRxAvailable() const =0
Return number of bytes which can be returned from one or multiple calls to Recv.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:126
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:72
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
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 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:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:60
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: enum.h:205
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
int64_t Div(const Length &numerator, const Length &denominator, Length *remainder)
Calculate how many times numerator can be split into denominator sized pieces.
Definition: length.cc:482
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr uint16_t PING_ID
This value is used to quickly identify ECHO packets generated by this app.
Definition: ping.cc:54
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:707
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:163
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
uint8_t data[writeSize]
A ping report provides all of the data that is typically output to the terminal when the application ...
Definition: ping.h:92
Time m_duration
Duration of the application.
Definition: ping.h:96
uint16_t m_loss
Percentage of lost packets (decimal value 0-100)
Definition: ping.h:95
double m_rttAvg
rtt avg value
Definition: ping.h:98
double m_rttMdev
rtt mdev value
Definition: ping.h:100
uint32_t m_received
Number of echo replies received.
Definition: ping.h:94
double m_rttMin
rtt min value
Definition: ping.h:97
uint32_t m_transmitted
Number of echo requests sent.
Definition: ping.h:93
double m_rttMax
rtt max value
Definition: ping.h:99