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
29namespace ns3 {
30
32
34
35TypeId
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.",
45 MakeIpv4AddressAccessor (&V4Ping::m_remote),
46 MakeIpv4AddressChecker ())
47 .AddAttribute ("Verbose",
48 "Produce usual output.",
49 BooleanValue (false),
52 .AddAttribute ("Interval", "Wait interval seconds between sending each packet.",
53 TimeValue (Seconds (1)),
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
83void
85{
86 NS_LOG_FUNCTION (this);
87
88 if (m_next.IsRunning ())
89 {
91 }
92
93 m_socket = 0;
95}
96
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
113void
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);
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);
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.As (Time::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
178void
179V4Ping::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
189void
190V4Ping::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
196void
198{
199 NS_LOG_FUNCTION (this);
200
201 NS_LOG_INFO ("m_seq=" << m_seq);
202 Ptr<Packet> p = Create<Packet> ();
203 Icmpv4Echo echo;
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);
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
241void
243{
244 NS_LOG_FUNCTION (this);
245
247 if (m_verbose)
248 {
249 std::cout << "PING " << m_remote << " - " << m_size << " bytes of data - " << m_size + 28 << " bytes including ICMP and IPv4 headers.\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}
266void
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).As (Time::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
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
double Avg() const
Sample average.
Definition: average.h:91
void Update(T const &x)
Add new sample.
Definition: average.h:52
T Min() const
Sample minimum.
Definition: average.h:81
T Max() const
Sample maximum.
Definition: average.h:86
uint32_t Count() const
Sample size.
Definition: average.h:76
double Stddev() const
Sample standard deviation.
Definition: average.h:106
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
uint32_t GetData(uint8_t payload[]) const
Get the Echo data.
Definition: icmpv4.cc:191
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
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
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
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
static bool ChecksumEnabled(void)
Definition: node.cc:278
uint32_t GetId(void) const
Definition: node.cc:109
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
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 Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
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 Connect(const Address &address)=0
Initiate a connection to a remote host.
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.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ MS
millisecond
Definition: nstime.h:115
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:383
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
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
Definition: v4ping.h:42
void Read32(const uint8_t *buffer, uint32_t &data)
Writes data from a little-endian formatted buffer to data.
Definition: v4ping.cc:190
Average< double > m_avgRtt
Average rtt is ms.
Definition: v4ping.h:117
bool m_verbose
produce ping-style output if true
Definition: v4ping.h:111
EventId m_next
Next packet will be sent.
Definition: v4ping.h:119
uint32_t m_size
Specifies the number of data bytes to be sent.
Definition: v4ping.h:103
Ptr< Socket > m_socket
The socket we send packets from.
Definition: v4ping.h:105
uint32_t m_recv
received packets counter
Definition: v4ping.h:113
void Send()
Send one Ping (ICMP ECHO) to the destination.
Definition: v4ping.cc:197
Ipv4Address m_remote
Remote address.
Definition: v4ping.h:96
virtual ~V4Ping()
Definition: v4ping.cc:78
uint16_t m_seq
ICMP ECHO sequence number.
Definition: v4ping.h:107
uint32_t GetApplicationId(void) const
Return the application ID in the node.
Definition: v4ping.cc:98
void Write32(uint8_t *buffer, const uint32_t data)
Writes data to buffer in little-endian format.
Definition: v4ping.cc:179
virtual void DoDispose(void)
Destructor implementation.
Definition: v4ping.cc:84
void Receive(Ptr< Socket > socket)
Receive an ICMP Echo.
Definition: v4ping.cc:114
V4Ping()
create a pinger applications
Definition: v4ping.cc:68
TracedCallback< Time > m_traceRtt
TracedCallback for RTT measured by ICMP ECHOs.
Definition: v4ping.h:109
virtual void StartApplication(void)
Application specific startup code.
Definition: v4ping.cc:242
std::map< uint16_t, Time > m_sent
All sent but not answered packets. Map icmp seqno -> when sent.
Definition: v4ping.h:121
static TypeId GetTypeId(void)
Get the type ID.
Definition: v4ping.cc:36
Time m_interval
Wait interval seconds between sending each packet.
Definition: v4ping.h:98
Time m_started
Start time to report total ping time.
Definition: v4ping.h:115
virtual void StopApplication(void)
Application specific shutdown code.
Definition: v4ping.cc:267
#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_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_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
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.
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]