A Discrete-Event Network Simulator
API
v4ping.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  */
16 
17 #include "v4ping.h"
18 #include "ns3/icmpv4.h"
19 #include "ns3/assert.h"
20 #include "ns3/log.h"
21 #include "ns3/ipv4-address.h"
22 #include "ns3/socket.h"
23 #include "ns3/uinteger.h"
24 #include "ns3/boolean.h"
25 #include "ns3/inet-socket-address.h"
26 #include "ns3/packet.h"
27 #include "ns3/trace-source-accessor.h"
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("V4Ping");
32 
34 
35 TypeId
37 {
38  static TypeId tid = TypeId ("ns3::V4Ping")
40  .AddConstructor<V4Ping> ()
41  .AddAttribute ("Remote",
42  "The address of the machine we want to ping.",
46  .AddAttribute ("Verbose",
47  "Produce usual output.",
48  BooleanValue (false),
51  .AddAttribute ("Interval", "Wait interval seconds between sending each packet.",
52  TimeValue (Seconds (1)),
54  MakeTimeChecker ())
55  .AddAttribute ("Size", "The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer.",
56  UintegerValue (56),
58  MakeUintegerChecker<uint32_t> (16))
59  .AddTraceSource ("Rtt",
60  "The rtt calculated by the ping.",
62  "ns3::Time::TracedCallback");
63  ;
64  return tid;
65 }
66 
68  : m_interval (Seconds (1)),
69  m_size (56),
70  m_socket (0),
71  m_seq (0),
72  m_verbose (false),
73  m_recv (0)
74 {
75  NS_LOG_FUNCTION (this);
76 }
78 {
79  NS_LOG_FUNCTION (this);
80 }
81 
82 void
84 {
85  NS_LOG_FUNCTION (this);
86  m_socket = 0;
88 }
89 
90 uint32_t
92 {
93  NS_LOG_FUNCTION (this);
94  Ptr<Node> node = GetNode ();
95  for (uint32_t i = 0; i < node->GetNApplications (); ++i)
96  {
97  if (node->GetApplication (i) == this)
98  {
99  return i;
100  }
101  }
102  NS_ASSERT_MSG (false, "forgot to add application to node");
103  return 0; // quiet compiler
104 }
105 
106 void
108 {
109  NS_LOG_FUNCTION (this << socket);
110  while (m_socket->GetRxAvailable () > 0)
111  {
112  Address from;
113  Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
114  NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
117  NS_ASSERT (realFrom.GetPort () == 1); // protocol should be icmp.
118  Ipv4Header ipv4;
119  p->RemoveHeader (ipv4);
120  uint32_t recvSize = p->GetSize ();
121  NS_ASSERT (ipv4.GetProtocol () == 1); // protocol should be icmp.
122  Icmpv4Header icmp;
123  p->RemoveHeader (icmp);
124  if (icmp.GetType () == Icmpv4Header::ECHO_REPLY)
125  {
126  Icmpv4Echo echo;
127  p->RemoveHeader (echo);
128  std::map<uint16_t, Time>::iterator i = m_sent.find (echo.GetSequenceNumber ());
129 
130  if (i != m_sent.end () && echo.GetIdentifier () == 0)
131  {
132  uint32_t * buf = new uint32_t [m_size];
133  uint32_t dataSize = echo.GetDataSize ();
134  uint32_t nodeId;
135  uint32_t appId;
136  if (dataSize == m_size)
137  {
138  echo.GetData ((uint8_t *)buf);
139  Read32 ((const uint8_t *) &buf[0], nodeId);
140  Read32 ((const uint8_t *) &buf[1], appId);
141 
142  if (nodeId == GetNode ()->GetId () &&
143  appId == GetApplicationId ())
144  {
145  Time sendTime = i->second;
146  NS_ASSERT (Simulator::Now () >= sendTime);
147  Time delta = Simulator::Now () - sendTime;
148 
149  m_sent.erase (i);
150  m_avgRtt.Update (delta.GetMilliSeconds ());
151  m_recv++;
152  m_traceRtt (delta);
153 
154  if (m_verbose)
155  {
156  std::cout << recvSize << " bytes from " << realFrom.GetIpv4 () << ":"
157  << " icmp_seq=" << echo.GetSequenceNumber ()
158  << " ttl=" << (unsigned)ipv4.GetTtl ()
159  << " time=" << delta.GetMilliSeconds () << " ms\n";
160  }
161  }
162  }
163  delete[] buf;
164  }
165  }
166  }
167 }
168 
169 // Writes data to buffer in little-endian format; least significant byte
170 // of data is at lowest buffer address
171 void
172 V4Ping::Write32 (uint8_t *buffer, const uint32_t data)
173 {
174  NS_LOG_FUNCTION (this << buffer << data);
175  buffer[0] = (data >> 0) & 0xff;
176  buffer[1] = (data >> 8) & 0xff;
177  buffer[2] = (data >> 16) & 0xff;
178  buffer[3] = (data >> 24) & 0xff;
179 }
180 
181 // Writes data from a little-endian formatted buffer to data
182 void
183 V4Ping::Read32 (const uint8_t *buffer, uint32_t &data)
184 {
185  NS_LOG_FUNCTION (this << buffer << data);
186  data = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
187 }
188 
189 void
191 {
192  NS_LOG_FUNCTION (this);
193 
194  NS_LOG_INFO ("m_seq=" << m_seq);
195  Ptr<Packet> p = Create<Packet> ();
196  Icmpv4Echo echo;
197  echo.SetSequenceNumber (m_seq);
198  m_seq++;
199  echo.SetIdentifier (0);
200 
201  //
202  // We must write quantities out in some form of network order. Since there
203  // isn't an htonl to work with we just follow the convention in pcap traces
204  // (where any difference would show up anyway) and borrow that code. Don't
205  // be too surprised when you see that this is a little endian convention.
206  //
207  uint8_t* data = new uint8_t[m_size];
208  for (uint32_t i = 0; i < m_size; ++i) data[i] = 0;
209  NS_ASSERT (m_size >= 16);
210 
211  uint32_t tmp = GetNode ()->GetId ();
212  Write32 (&data[0 * sizeof(uint32_t)], tmp);
213 
214  tmp = GetApplicationId ();
215  Write32 (&data[1 * sizeof(uint32_t)], tmp);
216 
217  Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) data, m_size);
218  echo.SetData (dataPacket);
219  p->AddHeader (echo);
220  Icmpv4Header header;
221  header.SetType (Icmpv4Header::ECHO);
222  header.SetCode (0);
223  if (Node::ChecksumEnabled ())
224  {
225  header.EnableChecksum ();
226  }
227  p->AddHeader (header);
228  m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now ()));
229  m_socket->Send (p, 0);
231  delete[] data;
232 }
233 
234 void
236 {
237  NS_LOG_FUNCTION (this);
238 
240  if (m_verbose)
241  {
242  std::cout << "PING " << m_remote << " 56(84) bytes of data.\n";
243  }
244 
245  m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
246  NS_ASSERT (m_socket != 0);
247  m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp
250  int status;
251  status = m_socket->Bind (src);
252  NS_ASSERT (status != -1);
254  status = m_socket->Connect (dst);
255  NS_ASSERT (status != -1);
256 
257  Send ();
258 }
259 void
261 {
262  NS_LOG_FUNCTION (this);
263  m_next.Cancel ();
264  m_socket->Close ();
265 
266  if (m_verbose)
267  {
268  std::ostringstream os;
269  os.precision (4);
270  os << "--- " << m_remote << " ping statistics ---\n"
271  << m_seq << " packets transmitted, " << m_recv << " received, "
272  << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, "
273  << "time " << (Simulator::Now () - m_started).GetMilliSeconds () << "ms\n";
274 
275  if (m_avgRtt.Count () > 0)
276  os << "rtt min/avg/max/mdev = " << m_avgRtt.Min () << "/" << m_avgRtt.Avg () << "/"
277  << m_avgRtt.Max () << "/" << m_avgRtt.Stddev ()
278  << " ms\n";
279  std::cout << os.str ();
280  }
281 }
282 
283 
284 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
virtual void StartApplication(void)
Application specific startup code.
Definition: v4ping.cc:235
T Max() const
Maximum.
Definition: average.h:74
void SetType(uint8_t type)
Set ICMP type.
Definition: icmpv4.cc:108
void Write32(uint8_t *buffer, const uint32_t data)
Writes data to buffer in little-endian format.
Definition: v4ping.cc:172
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:95
an Inet address class
Ipv4Address GetIpv4(void) const
static Ipv4Address GetAny(void)
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
AttributeValue implementation for Boolean.
Definition: boolean.h:34
uint32_t GetNApplications(void) const
Definition: node.cc:168
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
double Stddev() const
Standard deviation.
Definition: average.h:82
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:81
static bool ChecksumEnabled(void)
Definition: node.cc:268
uint32_t GetDataSize(void) const
Get the Echo data size.
Definition: icmpv4.cc:184
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:766
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
TracedCallback< Time > m_traceRtt
TracedCallback for RTT measured by ICMP ECHOs.
Definition: v4ping.h:111
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
uint32_t GetApplicationId(void) const
Return the application ID in the node.
Definition: v4ping.cc:91
double Avg() const
Sample average.
Definition: average.h:76
Introspection did not find any typical Config paths.
Definition: icmpv4.h:33
uint16_t GetIdentifier(void) const
Get the Echo identifier.
Definition: icmpv4.cc:172
V4Ping()
create a pinger applications
Definition: v4ping.cc:67
a polymophic address class
Definition: address.h:90
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:439
void SetCode(uint8_t code)
Set ICMP code.
Definition: icmpv4.cc:114
virtual void DoDispose(void)
Destructor implementation.
Definition: v4ping.cc:83
Packet header for IPv4.
Definition: ipv4-header.h:31
Ptr< Application > GetApplication(uint32_t index) const
Retrieve the index-th Application associated to this node.
Definition: node.cc:160
void Read32(const uint8_t *buffer, uint32_t &data)
Writes data from a little-endian formatted buffer to data.
Definition: v4ping.cc:183
Time m_started
Start time to report total ping time.
Definition: v4ping.h:117
static TypeId GetTypeId(void)
Get the type ID.
Definition: v4ping.cc:36
The base class for all ns3 applications.
Definition: application.h:60
AttributeValue implementation for Time.
Definition: nstime.h:921
void Receive(Ptr< Socket > socket)
Receive an ICMP Echo.
Definition: v4ping.cc:107
Ptr< const AttributeChecker > MakeIpv4AddressChecker(void)
void EnableChecksum(void)
Enables ICMP Checksum calculation.
Definition: icmpv4.cc:56
Hold an unsigned integer type.
Definition: uinteger.h:44
uint8_t data[writeSize]
Ptr< Node > GetNode() const
Definition: application.cc:103
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1290
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:127
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:70
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:82
T Min() const
Minimum.
Definition: average.h:72
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
std::map< uint16_t, Time > m_sent
All sent but not answered packets. Map icmp seqno -> when sent.
Definition: v4ping.h:123
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
bool m_verbose
produce ping-style output if true
Definition: v4ping.h:113
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Introspection did not find any typical Config paths.
Definition: icmpv4.h:91
uint16_t m_seq
ICMP ECHO sequence number.
Definition: v4ping.h:109
uint32_t GetData(uint8_t payload[]) const
Get the Echo data.
Definition: icmpv4.cc:190
AttributeValue implementation for Ipv4Address.
Definition: ipv4-address.h:296
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:922
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
EventId m_next
Next packet will be sent.
Definition: v4ping.h:121
#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:84
virtual void StopApplication(void)
Application specific shutdown code.
Definition: v4ping.cc:260
uint32_t GetId(void) const
Definition: node.cc:106
void Send()
Send one Ping (ICMP ECHO) to the destination.
Definition: v4ping.cc:190
void SetSequenceNumber(uint16_t seq)
Set the Echo sequence number.
Definition: icmpv4.cc:145
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:859
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
uint16_t GetSequenceNumber(void) const
Get the Echo sequence number.
Definition: icmpv4.cc:178
Time m_interval
Wait interval seconds between sending each packet.
Definition: v4ping.h:100
uint16_t GetPort(void) const
uint32_t m_recv
received packets counter
Definition: v4ping.h:115
virtual ~V4Ping()
Definition: v4ping.cc:77
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.
Ptr< const AttributeAccessor > MakeIpv4AddressAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: ipv4-address.h:296
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
Ipv4Address m_remote
Remote address.
Definition: v4ping.h:98
virtual int Close(void)=0
Close a socket.
uint32_t Count() const
Sample size.
Definition: average.h:70
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:190
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:45
a unique identifier for an interface.
Definition: type-id.h:51
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:331
TypeId SetParent(TypeId tid)
Definition: type-id.cc:631
static bool IsMatchingType(const Address &address)
uint32_t m_size
Specifies the number of data bytes to be sent.
Definition: v4ping.h:105
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
Average< double > m_avgRtt
Average rtt is ms.
Definition: v4ping.h:119
Ptr< Socket > m_socket
The socket we send packets from.
Definition: v4ping.h:107
static TypeId LookupByName(std::string name)
Definition: type-id.cc:556
virtual uint32_t GetRxAvailable(void) const =0
Return number of bytes which can be returned from one or multiple calls to Recv.
void Update(T const &x)
Add new sample.
Definition: average.h:49