A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
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
#include "
v4ping.h
"
17
#include "ns3/icmpv4.h"
18
#include "ns3/assert.h"
19
#include "ns3/log.h"
20
#include "ns3/ipv4-address.h"
21
#include "ns3/socket.h"
22
#include "ns3/uinteger.h"
23
#include "ns3/boolean.h"
24
#include "ns3/inet-socket-address.h"
25
#include "ns3/packet.h"
26
#include "ns3/trace-source-accessor.h"
27
28
namespace
ns3 {
29
30
NS_LOG_COMPONENT_DEFINE
(
"V4Ping"
);
31
NS_OBJECT_ENSURE_REGISTERED
(V4Ping);
32
33
TypeId
34
V4Ping::GetTypeId
(
void
)
35
{
36
static
TypeId
tid =
TypeId
(
"ns3::V4Ping"
)
37
.
SetParent
<
Application
> ()
38
.AddConstructor<V4Ping> ()
39
.AddAttribute (
"Remote"
,
40
"The address of the machine we want to ping."
,
41
Ipv4AddressValue
(),
42
MakeIpv4AddressAccessor (&
V4Ping::m_remote
),
43
MakeIpv4AddressChecker ())
44
.AddAttribute (
"Verbose"
,
45
"Produce usual output."
,
46
BooleanValue
(
false
),
47
MakeBooleanAccessor (&
V4Ping::m_verbose
),
48
MakeBooleanChecker ())
49
.AddAttribute (
"Interval"
,
"Wait interval seconds between sending each packet."
,
50
TimeValue
(
Seconds
(1)),
51
MakeTimeAccessor (&
V4Ping::m_interval
),
52
MakeTimeChecker ())
53
.AddAttribute (
"Size"
,
"The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer."
,
54
UintegerValue
(56),
55
MakeUintegerAccessor (&
V4Ping::m_size
),
56
MakeUintegerChecker<uint32_t> (16))
57
.AddTraceSource (
"Rtt"
,
58
"The rtt calculated by the ping."
,
59
MakeTraceSourceAccessor
(&
V4Ping::m_traceRtt
));
60
;
61
return
tid;
62
}
63
64
V4Ping::V4Ping
()
65
: m_interval (
Seconds
(1)),
66
m_size (56),
67
m_socket (0),
68
m_seq (0),
69
m_verbose (false),
70
m_recv (0)
71
{
72
NS_LOG_FUNCTION
(
this
);
73
}
74
V4Ping::~V4Ping
()
75
{
76
NS_LOG_FUNCTION
(
this
);
77
}
78
79
void
80
V4Ping::DoDispose
(
void
)
81
{
82
NS_LOG_FUNCTION
(
this
);
83
m_socket
= 0;
84
Application::DoDispose
();
85
}
86
87
uint32_t
88
V4Ping::GetApplicationId
(
void
)
const
89
{
90
NS_LOG_FUNCTION
(
this
);
91
Ptr<Node>
node =
GetNode
();
92
for
(uint32_t i = 0; i < node->
GetNApplications
(); ++i)
93
{
94
if
(node->
GetApplication
(i) ==
this
)
95
{
96
return
i;
97
}
98
}
99
NS_ASSERT_MSG
(
false
,
"forgot to add application to node"
);
100
return
0;
// quiet compiler
101
}
102
103
void
104
V4Ping::Receive
(
Ptr<Socket>
socket)
105
{
106
NS_LOG_FUNCTION
(
this
<< socket);
107
while
(
m_socket
->
GetRxAvailable
() > 0)
108
{
109
Address
from;
110
Ptr<Packet>
p =
m_socket
->
RecvFrom
(0xffffffff, 0, from);
111
NS_LOG_DEBUG
(
"recv "
<< p->
GetSize
() <<
" bytes"
);
112
NS_ASSERT
(
InetSocketAddress::IsMatchingType
(from));
113
InetSocketAddress
realFrom =
InetSocketAddress::ConvertFrom
(from);
114
NS_ASSERT
(realFrom.
GetPort
() == 1);
// protocol should be icmp.
115
Ipv4Header
ipv4;
116
p->
RemoveHeader
(ipv4);
117
uint32_t recvSize = p->
GetSize
();
118
NS_ASSERT
(ipv4.GetProtocol () == 1);
// protocol should be icmp.
119
Icmpv4Header
icmp;
120
p->
RemoveHeader
(icmp);
121
if
(icmp.GetType () ==
Icmpv4Header::ECHO_REPLY
)
122
{
123
Icmpv4Echo
echo;
124
p->
RemoveHeader
(echo);
125
std::map<uint16_t, Time>::iterator i =
m_sent
.find (echo.
GetSequenceNumber
());
126
127
if
(i !=
m_sent
.end () && echo.
GetIdentifier
() == 0)
128
{
129
uint32_t * buf =
new
uint32_t [
m_size
];
130
uint32_t dataSize = echo.
GetDataSize
();
131
uint32_t nodeId;
132
uint32_t appId;
133
if
(dataSize ==
m_size
)
134
{
135
echo.
GetData
((uint8_t *)buf);
136
Read32
((
const
uint8_t *) &buf[0], nodeId);
137
Read32
((
const
uint8_t *) &buf[1], appId);
138
139
if
(nodeId ==
GetNode
()->GetId () &&
140
appId ==
GetApplicationId
())
141
{
142
Time
sendTime = i->second;
143
NS_ASSERT
(
Simulator::Now
() >= sendTime);
144
Time
delta =
Simulator::Now
() - sendTime;
145
146
m_sent
.erase (i);
147
m_avgRtt
.
Update
(delta.
GetMilliSeconds
());
148
m_recv
++;
149
m_traceRtt
(delta);
150
151
if
(
m_verbose
)
152
{
153
std::cout << recvSize <<
" bytes from "
<< realFrom.
GetIpv4
() <<
":"
154
<<
" icmp_seq="
<< echo.
GetSequenceNumber
()
155
<<
" ttl="
<< (unsigned)ipv4.GetTtl ()
156
<<
" time="
<< delta.
GetMilliSeconds
() <<
" ms\n"
;
157
}
158
}
159
}
160
delete
[] buf;
161
}
162
}
163
}
164
}
165
166
// Writes data to buffer in little-endian format; least significant byte
167
// of data is at lowest buffer address
168
void
169
V4Ping::Write32
(uint8_t *buffer,
const
uint32_t
data
)
170
{
171
NS_LOG_FUNCTION
(
this
<< buffer << data);
172
buffer[0] = (data >> 0) & 0xff;
173
buffer[1] = (data >> 8) & 0xff;
174
buffer[2] = (data >> 16) & 0xff;
175
buffer[3] = (data >> 24) & 0xff;
176
}
177
178
// Writes data from a little-endian formatted buffer to data
179
void
180
V4Ping::Read32
(
const
uint8_t *buffer, uint32_t &
data
)
181
{
182
NS_LOG_FUNCTION
(
this
<< buffer << data);
183
data = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
184
}
185
186
void
187
V4Ping::Send
()
188
{
189
NS_LOG_FUNCTION
(
this
);
190
191
NS_LOG_INFO
(
"m_seq="
<<
m_seq
);
192
Ptr<Packet>
p = Create<Packet> ();
193
Icmpv4Echo
echo;
194
echo.
SetSequenceNumber
(
m_seq
);
195
m_seq
++;
196
echo.SetIdentifier (0);
197
198
//
199
// We must write quantities out in some form of network order. Since there
200
// isn't an htonl to work with we just follow the convention in pcap traces
201
// (where any difference would show up anyway) and borrow that code. Don't
202
// be too surprised when you see that this is a little endian convention.
203
//
204
uint8_t*
data
=
new
uint8_t[
m_size
];
205
for
(uint32_t i = 0; i <
m_size
; ++i) data[i] = 0;
206
NS_ASSERT
(m_size >= 16);
207
208
uint32_t tmp =
GetNode
()->
GetId
();
209
Write32
(&data[0 *
sizeof
(uint32_t)], tmp);
210
211
tmp =
GetApplicationId
();
212
Write32
(&data[1 *
sizeof
(uint32_t)], tmp);
213
214
Ptr<Packet>
dataPacket = Create<Packet> ((uint8_t *) data, m_size);
215
echo.SetData (dataPacket);
216
p->
AddHeader
(echo);
217
Icmpv4Header
header;
218
header.
SetType
(
Icmpv4Header::ECHO
);
219
header.
SetCode
(0);
220
if
(
Node::ChecksumEnabled
())
221
{
222
header.
EnableChecksum
();
223
}
224
p->
AddHeader
(header);
225
m_sent
.insert (std::make_pair (
m_seq
- 1,
Simulator::Now
()));
226
m_socket
->
Send
(p, 0);
227
m_next
=
Simulator::Schedule
(
m_interval
, &
V4Ping::Send
,
this
);
228
delete
[]
data
;
229
}
230
231
void
232
V4Ping::StartApplication
(
void
)
233
{
234
NS_LOG_FUNCTION
(
this
);
235
236
m_started
=
Simulator::Now
();
237
if
(
m_verbose
)
238
{
239
std::cout <<
"PING "
<<
m_remote
<<
" 56(84) bytes of data.\n"
;
240
}
241
242
m_socket
=
Socket::CreateSocket
(
GetNode
(),
TypeId::LookupByName
(
"ns3::Ipv4RawSocketFactory"
));
243
NS_ASSERT
(
m_socket
!= 0);
244
m_socket
->
SetAttribute
(
"Protocol"
,
UintegerValue
(1));
// icmp
245
m_socket
->
SetRecvCallback
(
MakeCallback
(&
V4Ping::Receive
,
this
));
246
InetSocketAddress
src =
InetSocketAddress
(
Ipv4Address::GetAny
(), 0);
247
int
status;
248
status =
m_socket
->
Bind
(src);
249
NS_ASSERT
(status != -1);
250
InetSocketAddress
dst =
InetSocketAddress
(
m_remote
, 0);
251
status =
m_socket
->
Connect
(dst);
252
NS_ASSERT
(status != -1);
253
254
Send
();
255
}
256
void
257
V4Ping::StopApplication
(
void
)
258
{
259
NS_LOG_FUNCTION
(
this
);
260
m_next
.
Cancel
();
261
m_socket
->
Close
();
262
263
if
(
m_verbose
)
264
{
265
std::ostringstream os;
266
os.precision (4);
267
os <<
"--- "
<<
m_remote
<<
" ping statistics ---\n"
268
<<
m_seq
<<
" packets transmitted, "
<<
m_recv
<<
" received, "
269
<< ((
m_seq
-
m_recv
) * 100 /
m_seq
) <<
"% packet loss, "
270
<<
"time "
<< (
Simulator::Now
() -
m_started
).GetMilliSeconds () <<
"ms\n"
;
271
272
if
(
m_avgRtt
.
Count
() > 0)
273
os <<
"rtt min/avg/max/mdev = "
<<
m_avgRtt
.
Min
() <<
"/"
<<
m_avgRtt
.
Avg
() <<
"/"
274
<<
m_avgRtt
.
Max
() <<
"/"
<<
m_avgRtt
.
Stddev
()
275
<<
" ms\n"
;
276
std::cout << os.str ();
277
}
278
}
279
280
281
}
// namespace ns3
src
applications
model
v4ping.cc
Generated on Tue May 14 2013 11:08:16 for ns-3 by
1.8.1.2