A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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");
33 
34 TypeId
36 {
37  static TypeId tid = TypeId ("ns3::V4Ping")
39  .AddConstructor<V4Ping> ()
40  .AddAttribute ("Remote",
41  "The address of the machine we want to ping.",
43  MakeIpv4AddressAccessor (&V4Ping::m_remote),
44  MakeIpv4AddressChecker ())
45  .AddAttribute ("Verbose",
46  "Produce usual output.",
47  BooleanValue (false),
48  MakeBooleanAccessor (&V4Ping::m_verbose),
49  MakeBooleanChecker ())
50  .AddAttribute ("Interval", "Wait interval seconds between sending each packet.",
51  TimeValue (Seconds (1)),
52  MakeTimeAccessor (&V4Ping::m_interval),
53  MakeTimeChecker ())
54  .AddAttribute ("Size", "The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer.",
55  UintegerValue (56),
56  MakeUintegerAccessor (&V4Ping::m_size),
57  MakeUintegerChecker<uint32_t> (16))
58  .AddTraceSource ("Rtt",
59  "The rtt calculated by the ping.",
61  ;
62  return tid;
63 }
64 
66  : m_interval (Seconds (1)),
67  m_size (56),
68  m_socket (0),
69  m_seq (0),
70  m_verbose (false),
71  m_recv (0)
72 {
73  NS_LOG_FUNCTION (this);
74 }
76 {
77  NS_LOG_FUNCTION (this);
78 }
79 
80 void
82 {
83  NS_LOG_FUNCTION (this);
84  m_socket = 0;
86 }
87 
88 uint32_t
90 {
91  NS_LOG_FUNCTION (this);
92  Ptr<Node> node = GetNode ();
93  for (uint32_t i = 0; i < node->GetNApplications (); ++i)
94  {
95  if (node->GetApplication (i) == this)
96  {
97  return i;
98  }
99  }
100  NS_ASSERT_MSG (false, "forgot to add application to node");
101  return 0; // quiet compiler
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION (this << socket);
108  while (m_socket->GetRxAvailable () > 0)
109  {
110  Address from;
111  Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
112  NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
115  NS_ASSERT (realFrom.GetPort () == 1); // protocol should be icmp.
116  Ipv4Header ipv4;
117  p->RemoveHeader (ipv4);
118  uint32_t recvSize = p->GetSize ();
119  NS_ASSERT (ipv4.GetProtocol () == 1); // protocol should be icmp.
120  Icmpv4Header icmp;
121  p->RemoveHeader (icmp);
122  if (icmp.GetType () == Icmpv4Header::ECHO_REPLY)
123  {
124  Icmpv4Echo echo;
125  p->RemoveHeader (echo);
126  std::map<uint16_t, Time>::iterator i = m_sent.find (echo.GetSequenceNumber ());
127 
128  if (i != m_sent.end () && echo.GetIdentifier () == 0)
129  {
130  uint32_t * buf = new uint32_t [m_size];
131  uint32_t dataSize = echo.GetDataSize ();
132  uint32_t nodeId;
133  uint32_t appId;
134  if (dataSize == m_size)
135  {
136  echo.GetData ((uint8_t *)buf);
137  Read32 ((const uint8_t *) &buf[0], nodeId);
138  Read32 ((const uint8_t *) &buf[1], appId);
139 
140  if (nodeId == GetNode ()->GetId () &&
141  appId == GetApplicationId ())
142  {
143  Time sendTime = i->second;
144  NS_ASSERT (Simulator::Now () >= sendTime);
145  Time delta = Simulator::Now () - sendTime;
146 
147  m_sent.erase (i);
148  m_avgRtt.Update (delta.GetMilliSeconds ());
149  m_recv++;
150  m_traceRtt (delta);
151 
152  if (m_verbose)
153  {
154  std::cout << recvSize << " bytes from " << realFrom.GetIpv4 () << ":"
155  << " icmp_seq=" << echo.GetSequenceNumber ()
156  << " ttl=" << (unsigned)ipv4.GetTtl ()
157  << " time=" << delta.GetMilliSeconds () << " ms\n";
158  }
159  }
160  }
161  delete[] buf;
162  }
163  }
164  }
165 }
166 
167 // Writes data to buffer in little-endian format; least significant byte
168 // of data is at lowest buffer address
169 void
170 V4Ping::Write32 (uint8_t *buffer, const uint32_t data)
171 {
172  NS_LOG_FUNCTION (this << buffer << data);
173  buffer[0] = (data >> 0) & 0xff;
174  buffer[1] = (data >> 8) & 0xff;
175  buffer[2] = (data >> 16) & 0xff;
176  buffer[3] = (data >> 24) & 0xff;
177 }
178 
179 // Writes data from a little-endian formatted buffer to data
180 void
181 V4Ping::Read32 (const uint8_t *buffer, uint32_t &data)
182 {
183  NS_LOG_FUNCTION (this << buffer << data);
184  data = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
185 }
186 
187 void
189 {
190  NS_LOG_FUNCTION (this);
191 
192  NS_LOG_INFO ("m_seq=" << m_seq);
193  Ptr<Packet> p = Create<Packet> ();
194  Icmpv4Echo echo;
195  echo.SetSequenceNumber (m_seq);
196  m_seq++;
197  echo.SetIdentifier (0);
198 
199  //
200  // We must write quantities out in some form of network order. Since there
201  // isn't an htonl to work with we just follow the convention in pcap traces
202  // (where any difference would show up anyway) and borrow that code. Don't
203  // be too surprised when you see that this is a little endian convention.
204  //
205  uint8_t* data = new uint8_t[m_size];
206  for (uint32_t i = 0; i < m_size; ++i) data[i] = 0;
207  NS_ASSERT (m_size >= 16);
208 
209  uint32_t tmp = GetNode ()->GetId ();
210  Write32 (&data[0 * sizeof(uint32_t)], tmp);
211 
212  tmp = GetApplicationId ();
213  Write32 (&data[1 * sizeof(uint32_t)], tmp);
214 
215  Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) data, m_size);
216  echo.SetData (dataPacket);
217  p->AddHeader (echo);
218  Icmpv4Header header;
219  header.SetType (Icmpv4Header::ECHO);
220  header.SetCode (0);
221  if (Node::ChecksumEnabled ())
222  {
223  header.EnableChecksum ();
224  }
225  p->AddHeader (header);
226  m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now ()));
227  m_socket->Send (p, 0);
229  delete[] data;
230 }
231 
232 void
234 {
235  NS_LOG_FUNCTION (this);
236 
238  if (m_verbose)
239  {
240  std::cout << "PING " << m_remote << " 56(84) bytes of data.\n";
241  }
242 
243  m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
244  NS_ASSERT (m_socket != 0);
245  m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp
248  int status;
249  status = m_socket->Bind (src);
250  NS_ASSERT (status != -1);
252  status = m_socket->Connect (dst);
253  NS_ASSERT (status != -1);
254 
255  Send ();
256 }
257 void
259 {
260  NS_LOG_FUNCTION (this);
261  m_next.Cancel ();
262  m_socket->Close ();
263 
264  if (m_verbose)
265  {
266  std::ostringstream os;
267  os.precision (4);
268  os << "--- " << m_remote << " ping statistics ---\n"
269  << m_seq << " packets transmitted, " << m_recv << " received, "
270  << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, "
271  << "time " << (Simulator::Now () - m_started).GetMilliSeconds () << "ms\n";
272 
273  if (m_avgRtt.Count () > 0)
274  os << "rtt min/avg/max/mdev = " << m_avgRtt.Min () << "/" << m_avgRtt.Avg () << "/"
275  << m_avgRtt.Max () << "/" << m_avgRtt.Stddev ()
276  << " ms\n";
277  std::cout << os.str ();
278  }
279 }
280 
281 
282 } // 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:233
T Max() const
Maximum.
Definition: average.h:75
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:170
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
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 "...
Hold a bool native type.
Definition: boolean.h:38
uint32_t GetNApplications(void) const
Definition: node.cc:168
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
double Stddev() const
Standard deviation.
Definition: average.h:83
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:170
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:223
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:825
uint32_t GetApplicationId(void) const
Return the application ID in the node.
Definition: v4ping.cc:89
double Avg() const
Sample average.
Definition: average.h:77
Doxygen 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:65
a polymophic address class
Definition: address.h:86
void SetCode(uint8_t code)
Set ICMP code.
Definition: icmpv4.cc:114
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: v4ping.cc:81
Packet header for IPv4.
Definition: ipv4-header.h:31
Ptr< Application > GetApplication(uint32_t index) const
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:181
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:35
The base class for all ns3 applications.
Definition: application.h:60
hold objects of type ns3::Time
Definition: nstime.h:1008
void Receive(Ptr< Socket > socket)
Receive an ICMP Echo.
Definition: v4ping.cc:105
void EnableChecksum(void)
Enables ICMP Checksum calculation.
Definition: icmpv4.cc:56
Hold an unsigned integer type.
Definition: uinteger.h:46
uint8_t data[writeSize]
Ptr< Node > GetNode() const
Definition: application.cc:103
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1242
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)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: application.cc:82
T Min() const
Minimum.
Definition: average.h:73
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
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 TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Doxygen 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
hold objects of type ns3::Ipv4Address
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
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:258
uint32_t GetId(void) const
Definition: node.cc:106
void Send()
Send one Ping (ICMP ECHO) to the destination.
Definition: v4ping.cc:188
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:213
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::cancel method.
Definition: event-id.cc:47
uint16_t GetSequenceNumber(void) const
Get the Echo sequence number.
Definition: icmpv4.cc:178
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:441
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:75
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 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:71
void SetAttribute(std::string name, const AttributeValue &value)
Definition: object-base.cc:176
a unique identifier for an interface.
Definition: type-id.h:49
int64_t GetMilliSeconds(void) const
Definition: nstime.h:281
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
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:535
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