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  .SetGroupName("Internet-Apps")
41  .AddConstructor<V4Ping> ()
42  .AddAttribute ("Remote",
43  "The address of the machine we want to ping.",
47  .AddAttribute ("Verbose",
48  "Produce usual output.",
49  BooleanValue (false),
52  .AddAttribute ("Interval", "Wait interval seconds between sending each packet.",
53  TimeValue (Seconds (1)),
55  MakeTimeChecker ())
56  .AddAttribute ("Size", "The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer.",
57  UintegerValue (56),
59  MakeUintegerChecker<uint32_t> (16))
60  .AddTraceSource ("Rtt",
61  "The rtt calculated by the ping.",
63  "ns3::Time::TracedCallback");
64  ;
65  return tid;
66 }
67 
69  : m_interval (Seconds (1)),
70  m_size (56),
71  m_socket (0),
72  m_seq (0),
73  m_verbose (false),
74  m_recv (0)
75 {
76  NS_LOG_FUNCTION (this);
77 }
79 {
80  NS_LOG_FUNCTION (this);
81 }
82 
83 void
85 {
86  NS_LOG_FUNCTION (this);
87 
88  if (m_next.IsRunning ())
89  {
90  StopApplication ();
91  }
92 
93  m_socket = 0;
95 }
96 
97 uint32_t
99 {
100  NS_LOG_FUNCTION (this);
101  Ptr<Node> node = GetNode ();
102  for (uint32_t i = 0; i < node->GetNApplications (); ++i)
103  {
104  if (node->GetApplication (i) == this)
105  {
106  return i;
107  }
108  }
109  NS_ASSERT_MSG (false, "forgot to add application to node");
110  return 0; // quiet compiler
111 }
112 
113 void
115 {
116  NS_LOG_FUNCTION (this << socket);
117  while (m_socket->GetRxAvailable () > 0)
118  {
119  Address from;
120  Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
121  NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
124  NS_ASSERT (realFrom.GetPort () == 1); // protocol should be icmp.
125  Ipv4Header ipv4;
126  p->RemoveHeader (ipv4);
127  uint32_t recvSize = p->GetSize ();
128  NS_ASSERT (ipv4.GetProtocol () == 1); // protocol should be icmp.
129  Icmpv4Header icmp;
130  p->RemoveHeader (icmp);
131  if (icmp.GetType () == Icmpv4Header::ICMPV4_ECHO_REPLY)
132  {
133  Icmpv4Echo echo;
134  p->RemoveHeader (echo);
135  std::map<uint16_t, Time>::iterator i = m_sent.find (echo.GetSequenceNumber ());
136 
137  if (i != m_sent.end () && echo.GetIdentifier () == 0)
138  {
139  uint32_t * buf = new uint32_t [m_size];
140  uint32_t dataSize = echo.GetDataSize ();
141  uint32_t nodeId;
142  uint32_t appId;
143  if (dataSize == m_size)
144  {
145  echo.GetData ((uint8_t *)buf);
146  Read32 ((const uint8_t *) &buf[0], nodeId);
147  Read32 ((const uint8_t *) &buf[1], appId);
148 
149  if (nodeId == GetNode ()->GetId () &&
150  appId == GetApplicationId ())
151  {
152  Time sendTime = i->second;
153  NS_ASSERT (Simulator::Now () >= sendTime);
154  Time delta = Simulator::Now () - sendTime;
155 
156  m_sent.erase (i);
157  m_avgRtt.Update (delta.GetMilliSeconds ());
158  m_recv++;
159  m_traceRtt (delta);
160 
161  if (m_verbose)
162  {
163  std::cout << recvSize << " bytes from " << realFrom.GetIpv4 () << ":"
164  << " icmp_seq=" << echo.GetSequenceNumber ()
165  << " ttl=" << (unsigned)ipv4.GetTtl ()
166  << " time=" << delta.GetMilliSeconds () << " ms\n";
167  }
168  }
169  }
170  delete[] buf;
171  }
172  }
173  }
174 }
175 
176 // Writes data to buffer in little-endian format; least significant byte
177 // of data is at lowest buffer address
178 void
179 V4Ping::Write32 (uint8_t *buffer, const uint32_t data)
180 {
181  NS_LOG_FUNCTION (this << (void *) buffer << data);
182  buffer[0] = (data >> 0) & 0xff;
183  buffer[1] = (data >> 8) & 0xff;
184  buffer[2] = (data >> 16) & 0xff;
185  buffer[3] = (data >> 24) & 0xff;
186 }
187 
188 // Writes data from a little-endian formatted buffer to data
189 void
190 V4Ping::Read32 (const uint8_t *buffer, uint32_t &data)
191 {
192  NS_LOG_FUNCTION (this << (void *) buffer << data);
193  data = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
194 }
195 
196 void
198 {
199  NS_LOG_FUNCTION (this);
200 
201  NS_LOG_INFO ("m_seq=" << m_seq);
202  Ptr<Packet> p = Create<Packet> ();
203  Icmpv4Echo echo;
204  echo.SetSequenceNumber (m_seq);
205  m_seq++;
206  echo.SetIdentifier (0);
207 
208  //
209  // We must write quantities out in some form of network order. Since there
210  // isn't an htonl to work with we just follow the convention in pcap traces
211  // (where any difference would show up anyway) and borrow that code. Don't
212  // be too surprised when you see that this is a little endian convention.
213  //
214  uint8_t* data = new uint8_t[m_size];
215  for (uint32_t i = 0; i < m_size; ++i) data[i] = 0;
216  NS_ASSERT (m_size >= 16);
217 
218  uint32_t tmp = GetNode ()->GetId ();
219  Write32 (&data[0 * sizeof(uint32_t)], tmp);
220 
221  tmp = GetApplicationId ();
222  Write32 (&data[1 * sizeof(uint32_t)], tmp);
223 
224  Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) data, m_size);
225  echo.SetData (dataPacket);
226  p->AddHeader (echo);
227  Icmpv4Header header;
229  header.SetCode (0);
230  if (Node::ChecksumEnabled ())
231  {
232  header.EnableChecksum ();
233  }
234  p->AddHeader (header);
235  m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now ()));
236  m_socket->Send (p, 0);
238  delete[] data;
239 }
240 
241 void
243 {
244  NS_LOG_FUNCTION (this);
245 
247  if (m_verbose)
248  {
249  std::cout << "PING " << m_remote << " 56(84) bytes of data.\n";
250  }
251 
252  m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
253  NS_ASSERT (m_socket != 0);
254  m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp
257  int status;
258  status = m_socket->Bind (src);
259  NS_ASSERT (status != -1);
261  status = m_socket->Connect (dst);
262  NS_ASSERT (status != -1);
263 
264  Send ();
265 }
266 void
268 {
269  NS_LOG_FUNCTION (this);
270 
271  if (m_next.IsRunning ())
272  {
273  m_next.Cancel ();
274  }
275  if (m_socket)
276  {
277  m_socket->Close ();
278  }
279 
280  if (m_verbose)
281  {
282  std::ostringstream os;
283  os.precision (4);
284  os << "--- " << m_remote << " ping statistics ---\n"
285  << m_seq << " packets transmitted, " << m_recv << " received, "
286  << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, "
287  << "time " << (Simulator::Now () - m_started).GetMilliSeconds () << "ms\n";
288 
289  if (m_avgRtt.Count () > 0)
290  os << "rtt min/avg/max/mdev = " << m_avgRtt.Min () << "/" << m_avgRtt.Avg () << "/"
291  << m_avgRtt.Max () << "/" << m_avgRtt.Stddev ()
292  << " ms\n";
293  std::cout << os.str ();
294  }
295 }
296 
297 
298 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
uint32_t GetApplicationId(void) const
Return the application ID in the node.
Definition: v4ping.cc:98
virtual void StartApplication(void)
Application specific startup code.
Definition: v4ping.cc:242
void SetType(uint8_t type)
Set ICMP type.
Definition: icmpv4.cc:109
void Write32(uint8_t *buffer, const uint32_t data)
Writes data to buffer in little-endian format.
Definition: v4ping.cc:179
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
an Inet address class
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 "...
double Avg() const
Sample average.
Definition: average.h:76
AttributeValue implementation for Boolean.
Definition: boolean.h:36
uint32_t GetId(void) const
Definition: node.cc:107
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
T Max() const
Maximum.
Definition: average.h:74
uint32_t GetData(uint8_t payload[]) const
Get the Echo data.
Definition: icmpv4.cc:191
uint32_t GetDataSize(void) const
Get the Echo data size.
Definition: icmpv4.cc:185
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:84
static bool ChecksumEnabled(void)
Definition: node.cc:276
#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_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:278
TracedCallback< Time > m_traceRtt
TracedCallback for RTT measured by ICMP ECHOs.
Definition: v4ping.h:111
Base class for all the ICMP packet headers.
Definition: icmpv4.h:40
V4Ping()
create a pinger applications
Definition: v4ping.cc:68
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:446
void SetCode(uint8_t code)
Set ICMP code.
Definition: icmpv4.cc:115
virtual void DoDispose(void)
Destructor implementation.
Definition: v4ping.cc:84
Packet header for IPv4.
Definition: ipv4-header.h:33
double Stddev() const
Standard deviation.
Definition: average.h:82
void Read32(const uint8_t *buffer, uint32_t &data)
Writes data from a little-endian formatted buffer to data.
Definition: v4ping.cc:190
Time m_started
Start time to report total ping time.
Definition: v4ping.h:117
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1381
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:1076
void Receive(Ptr< Socket > socket)
Receive an ICMP Echo.
Definition: v4ping.cc:114
Ptr< const AttributeChecker > MakeIpv4AddressChecker(void)
void EnableChecksum(void)
Enables ICMP Checksum calculation.
Definition: icmpv4.cc:57
Hold an unsigned integer type.
Definition: uinteger.h:44
uint8_t data[writeSize]
Ptr< Application > GetApplication(uint32_t index) const
Retrieve the index-th Application associated to this node.
Definition: node.cc:168
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
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
Ptr< Node > GetNode() const
Definition: application.cc:104
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
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
uint16_t GetPort(void) const
ICMP Echo header.
Definition: icmpv4.h:107
uint16_t m_seq
ICMP ECHO sequence number.
Definition: v4ping.h:109
AttributeValue implementation for Ipv4Address.
Definition: ipv4-address.h:329
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:1077
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
EventId m_next
Next packet will be sent.
Definition: v4ping.h:121
uint16_t GetSequenceNumber(void) const
Get the Echo sequence number.
Definition: icmpv4.cc:179
virtual void StopApplication(void)
Application specific shutdown code.
Definition: v4ping.cc:267
T Min() const
Minimum.
Definition: average.h:72
void Send()
Send one Ping (ICMP ECHO) to the destination.
Definition: v4ping.cc:197
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:359
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT...
Definition: v4ping.h:43
uint16_t GetIdentifier(void) const
Get the Echo identifier.
Definition: icmpv4.cc:173
void SetSequenceNumber(uint16_t seq)
Set the Echo sequence number.
Definition: icmpv4.cc:146
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:270
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
uint32_t GetNApplications(void) const
Definition: node.cc:176
Time m_interval
Wait interval seconds between sending each packet.
Definition: v4ping.h:100
uint32_t m_recv
received packets counter
Definition: v4ping.h:115
virtual ~V4Ping()
Definition: v4ping.cc:78
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:329
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.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
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:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
uint32_t Count() const
Sample size.
Definition: average.h:70
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:256
Average< double > m_avgRtt
Average rtt is ms.
Definition: v4ping.h:119
Ipv4Address GetIpv4(void) const
Ptr< Socket > m_socket
The socket we send packets from.
Definition: v4ping.h:107
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:824
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