A Discrete-Event Network Simulator
API
v4ping.cc
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation;
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 */
15
16#include "v4ping.h"
17
18#include "ns3/assert.h"
19#include "ns3/boolean.h"
20#include "ns3/icmpv4.h"
21#include "ns3/inet-socket-address.h"
22#include "ns3/ipv4-address.h"
23#include "ns3/log.h"
24#include "ns3/packet.h"
25#include "ns3/socket.h"
26#include "ns3/trace-source-accessor.h"
27#include "ns3/uinteger.h"
28
29namespace ns3
30{
31
33
35
36TypeId
38{
39 static TypeId tid = TypeId("ns3::V4Ping")
41 .SetGroupName("Internet-Apps")
42 .AddConstructor<V4Ping>()
43 .AddAttribute("Remote",
44 "The address of the machine we want to ping.",
46 MakeIpv4AddressAccessor(&V4Ping::m_remote),
47 MakeIpv4AddressChecker())
48 .AddAttribute("Verbose",
49 "Produce usual output.",
50 BooleanValue(false),
53 .AddAttribute("Interval",
54 "Wait interval seconds between sending each packet.",
58 .AddAttribute("Size",
59 "The number of data bytes to be sent, real packet will "
60 "be 8 (ICMP) + 20 (IP) bytes longer.",
61 UintegerValue(56),
63 MakeUintegerChecker<uint32_t>(16))
64 .AddTraceSource("Rtt",
65 "The rtt calculated by the ping.",
67 "ns3::Time::TracedCallback");
68 ;
69 return tid;
70}
71
73 : m_interval(Seconds(1)),
74 m_size(56),
75 m_socket(nullptr),
76 m_seq(0),
77 m_verbose(false),
78 m_recv(0)
79{
80 NS_LOG_FUNCTION(this);
81}
82
84{
85 NS_LOG_FUNCTION(this);
86}
87
88void
90{
91 NS_LOG_FUNCTION(this);
92
93 if (m_next.IsRunning())
94 {
96 }
97
98 m_socket = nullptr;
100}
101
104{
105 NS_LOG_FUNCTION(this);
106 Ptr<Node> node = GetNode();
107 for (uint32_t i = 0; i < node->GetNApplications(); ++i)
108 {
109 if (node->GetApplication(i) == this)
110 {
111 return i;
112 }
113 }
114 NS_ASSERT_MSG(false, "forgot to add application to node");
115 return 0; // quiet compiler
116}
117
118void
120{
121 NS_LOG_FUNCTION(this << socket);
122 while (m_socket->GetRxAvailable() > 0)
123 {
124 Address from;
125 Ptr<Packet> p = m_socket->RecvFrom(0xffffffff, 0, from);
126 NS_LOG_DEBUG("recv " << p->GetSize() << " bytes");
129 NS_ASSERT(realFrom.GetPort() == 1); // protocol should be icmp.
130 Ipv4Header ipv4;
131 p->RemoveHeader(ipv4);
132 uint32_t recvSize = p->GetSize();
133 NS_ASSERT(ipv4.GetProtocol() == 1); // protocol should be icmp.
134 Icmpv4Header icmp;
135 p->RemoveHeader(icmp);
137 {
138 Icmpv4Echo echo;
139 p->RemoveHeader(echo);
140 std::map<uint16_t, Time>::iterator i = m_sent.find(echo.GetSequenceNumber());
141
142 if (i != m_sent.end() && echo.GetIdentifier() == 0)
143 {
144 uint32_t* buf = new uint32_t[m_size];
145 uint32_t dataSize = echo.GetDataSize();
146 uint32_t nodeId;
147 uint32_t appId;
148 if (dataSize == m_size)
149 {
150 echo.GetData((uint8_t*)buf);
151 Read32((const uint8_t*)&buf[0], nodeId);
152 Read32((const uint8_t*)&buf[1], appId);
153
154 if (nodeId == GetNode()->GetId() && appId == GetApplicationId())
155 {
156 Time sendTime = i->second;
157 NS_ASSERT(Simulator::Now() >= sendTime);
158 Time delta = Simulator::Now() - sendTime;
159
160 m_sent.erase(i);
162 m_recv++;
163 m_traceRtt(delta);
164
165 if (m_verbose)
166 {
167 std::cout << recvSize << " bytes from " << realFrom.GetIpv4() << ":"
168 << " icmp_seq=" << echo.GetSequenceNumber()
169 << " ttl=" << (unsigned)ipv4.GetTtl()
170 << " time=" << delta.As(Time::MS) << "\n";
171 }
172 }
173 }
174 delete[] buf;
175 }
176 }
177 }
178}
179
180// Writes data to buffer in little-endian format; least significant byte
181// of data is at lowest buffer address
182void
183V4Ping::Write32(uint8_t* buffer, const uint32_t data)
184{
185 NS_LOG_FUNCTION(this << (void*)buffer << data);
186 buffer[0] = (data >> 0) & 0xff;
187 buffer[1] = (data >> 8) & 0xff;
188 buffer[2] = (data >> 16) & 0xff;
189 buffer[3] = (data >> 24) & 0xff;
190}
191
192// Writes data from a little-endian formatted buffer to data
193void
194V4Ping::Read32(const uint8_t* buffer, uint32_t& data)
195{
196 NS_LOG_FUNCTION(this << (void*)buffer << data);
197 data = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
198}
199
200void
202{
203 NS_LOG_FUNCTION(this);
204
205 NS_LOG_INFO("m_seq=" << m_seq);
206 Ptr<Packet> p = Create<Packet>();
207 Icmpv4Echo echo;
209 m_seq++;
210 echo.SetIdentifier(0);
211
212 //
213 // We must write quantities out in some form of network order. Since there
214 // isn't an htonl to work with we just follow the convention in pcap traces
215 // (where any difference would show up anyway) and borrow that code. Don't
216 // be too surprised when you see that this is a little endian convention.
217 //
218 uint8_t* data = new uint8_t[m_size];
219 for (uint32_t i = 0; i < m_size; ++i)
220 {
221 data[i] = 0;
222 }
223 NS_ASSERT(m_size >= 16);
224
225 uint32_t tmp = GetNode()->GetId();
226 Write32(&data[0 * sizeof(uint32_t)], tmp);
227
228 tmp = GetApplicationId();
229 Write32(&data[1 * sizeof(uint32_t)], tmp);
230
231 Ptr<Packet> dataPacket = Create<Packet>((uint8_t*)data, m_size);
232 echo.SetData(dataPacket);
233 p->AddHeader(echo);
234 Icmpv4Header header;
236 header.SetCode(0);
238 {
239 header.EnableChecksum();
240 }
241 p->AddHeader(header);
242 m_sent.insert(std::make_pair(m_seq - 1, Simulator::Now()));
243 m_socket->Send(p, 0);
245 delete[] data;
246}
247
248void
250{
251 NS_LOG_FUNCTION(this);
252
254 if (m_verbose)
255 {
256 std::cout << "PING " << m_remote << " - " << m_size << " bytes of data - " << m_size + 28
257 << " bytes including ICMP and IPv4 headers.\n";
258 }
259
260 m_socket = Socket::CreateSocket(GetNode(), TypeId::LookupByName("ns3::Ipv4RawSocketFactory"));
262 m_socket->SetAttribute("Protocol", UintegerValue(1)); // icmp
265 int status;
266 status = m_socket->Bind(src);
267 NS_ASSERT(status != -1);
269 status = m_socket->Connect(dst);
270 NS_ASSERT(status != -1);
271
272 Send();
273}
274
275void
277{
278 NS_LOG_FUNCTION(this);
279
280 if (m_next.IsRunning())
281 {
282 m_next.Cancel();
283 }
284 if (m_socket)
285 {
286 m_socket->Close();
287 }
288
289 if (m_verbose)
290 {
291 std::ostringstream os;
292 os.precision(4);
293 os << "--- " << m_remote << " ping statistics ---\n"
294 << m_seq << " packets transmitted, " << m_recv << " received, "
295 << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, "
296 << "time " << (Simulator::Now() - m_started).As(Time::MS) << "\n";
297
298 if (m_avgRtt.Count() > 0)
299 {
300 os << "rtt min/avg/max/mdev = " << m_avgRtt.Min() << "/" << m_avgRtt.Avg() << "/"
301 << m_avgRtt.Max() << "/" << m_avgRtt.Stddev() << " ms\n";
302 }
303 std::cout << os.str();
304 }
305}
306
307} // namespace ns3
a polymophic address class
Definition: address.h:92
The base class for all ns3 applications.
Definition: application.h:61
void DoDispose() override
Destructor implementation.
Definition: application.cc:85
Ptr< Node > GetNode() const
Definition: application.cc:107
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
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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 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
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
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.
static Ipv4Address GetAny()
AttributeValue implementation for Ipv4Address.
Packet header for IPv4.
Definition: ipv4-header.h:34
uint8_t GetProtocol() const
Definition: ipv4-header.cc:281
uint8_t GetTtl() const
Definition: ipv4-header.cc:274
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:258
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
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
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 uint32_t GetRxAvailable() const =0
Return number of bytes which can be returned from one or multiple calls to Recv.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
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.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:407
@ MS
millisecond
Definition: nstime.h:117
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:417
AttributeValue implementation for Time.
Definition: nstime.h:1425
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
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
Definition: v4ping.h:43
void Read32(const uint8_t *buffer, uint32_t &data)
Writes data from a little-endian formatted buffer to data.
Definition: v4ping.cc:194
Average< double > m_avgRtt
Average rtt is ms.
Definition: v4ping.h:119
bool m_verbose
produce ping-style output if true
Definition: v4ping.h:113
EventId m_next
Next packet will be sent.
Definition: v4ping.h:121
uint32_t m_size
Specifies the number of data bytes to be sent.
Definition: v4ping.h:105
void StartApplication() override
Application specific startup code.
Definition: v4ping.cc:249
Ptr< Socket > m_socket
The socket we send packets from.
Definition: v4ping.h:107
uint32_t m_recv
received packets counter
Definition: v4ping.h:115
void StopApplication() override
Application specific shutdown code.
Definition: v4ping.cc:276
void Send()
Send one Ping (ICMP ECHO) to the destination.
Definition: v4ping.cc:201
Ipv4Address m_remote
Remote address.
Definition: v4ping.h:97
uint16_t m_seq
ICMP ECHO sequence number.
Definition: v4ping.h:109
void Write32(uint8_t *buffer, const uint32_t data)
Writes data to buffer in little-endian format.
Definition: v4ping.cc:183
void Receive(Ptr< Socket > socket)
Receive an ICMP Echo.
Definition: v4ping.cc:119
static TypeId GetTypeId()
Get the type ID.
Definition: v4ping.cc:37
V4Ping()
create a pinger applications
Definition: v4ping.cc:72
void DoDispose() override
Destructor implementation.
Definition: v4ping.cc:89
TracedCallback< Time > m_traceRtt
TracedCallback for RTT measured by ICMP ECHOs.
Definition: v4ping.h:111
uint32_t GetApplicationId() const
Return the application ID in the node.
Definition: v4ping.cc:103
std::map< uint16_t, Time > m_sent
All sent but not answered packets. Map icmp seqno -> when sent.
Definition: v4ping.h:123
~V4Ping() override
Definition: v4ping.cc:83
Time m_interval
Wait interval seconds between sending each packet.
Definition: v4ping.h:99
Time m_started
Start time to report total ping time.
Definition: v4ping.h:117
#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 > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1426
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#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:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
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.
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:691
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]