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
}
73
V4Ping::~V4Ping
()
74
{
75
}
76
77
void
78
V4Ping::DoDispose
(
void
)
79
{
80
NS_LOG_FUNCTION
(
this
);
81
m_socket
= 0;
82
Application::DoDispose
();
83
}
84
85
uint32_t
86
V4Ping::GetApplicationId
(
void
)
const
87
{
88
Ptr<Node>
node =
GetNode
();
89
for
(uint32_t i = 0; i < node->
GetNApplications
(); ++i)
90
{
91
if
(node->
GetApplication
(i) ==
this
)
92
{
93
return
i;
94
}
95
}
96
NS_ASSERT_MSG
(
false
,
"forgot to add application to node"
);
97
return
0;
// quiet compiler
98
}
99
100
void
101
V4Ping::Receive
(
Ptr<Socket>
socket)
102
{
103
NS_LOG_FUNCTION
(
this
<< socket);
104
while
(
m_socket
->
GetRxAvailable
() > 0)
105
{
106
Address
from;
107
Ptr<Packet>
p =
m_socket
->
RecvFrom
(0xffffffff, 0, from);
108
NS_LOG_DEBUG
(
"recv "
<< p->
GetSize
() <<
" bytes"
);
109
NS_ASSERT
(
InetSocketAddress::IsMatchingType
(from));
110
InetSocketAddress
realFrom =
InetSocketAddress::ConvertFrom
(from);
111
NS_ASSERT
(realFrom.
GetPort
() == 1);
// protocol should be icmp.
112
Ipv4Header
ipv4;
113
p->
RemoveHeader
(ipv4);
114
uint32_t recvSize = p->
GetSize
();
115
NS_ASSERT
(ipv4.GetProtocol () == 1);
// protocol should be icmp.
116
Icmpv4Header
icmp;
117
p->
RemoveHeader
(icmp);
118
if
(icmp.GetType () ==
Icmpv4Header::ECHO_REPLY
)
119
{
120
Icmpv4Echo
echo;
121
p->
RemoveHeader
(echo);
122
std::map<uint16_t, Time>::iterator i =
m_sent
.find (echo.
GetSequenceNumber
());
123
124
if
(i !=
m_sent
.end () && echo.
GetIdentifier
() == 0)
125
{
126
uint32_t * buf =
new
uint32_t [
m_size
];
127
uint32_t dataSize = echo.
GetDataSize
();
128
uint32_t nodeId;
129
uint32_t appId;
130
if
(dataSize ==
m_size
)
131
{
132
echo.
GetData
((uint8_t *)buf);
133
Read32
((
const
uint8_t *) &buf[0], nodeId);
134
Read32
((
const
uint8_t *) &buf[1], appId);
135
136
if
(nodeId ==
GetNode
()->GetId () &&
137
appId ==
GetApplicationId
())
138
{
139
Time
sendTime = i->second;
140
NS_ASSERT
(
Simulator::Now
() >= sendTime);
141
Time
delta =
Simulator::Now
() - sendTime;
142
143
m_sent
.erase (i);
144
m_avgRtt
.
Update
(delta.
GetMilliSeconds
());
145
m_recv
++;
146
m_traceRtt
(delta);
147
148
if
(
m_verbose
)
149
{
150
std::cout << recvSize <<
" bytes from "
<< realFrom.
GetIpv4
() <<
":"
151
<<
" icmp_seq="
<< echo.
GetSequenceNumber
()
152
<<
" ttl="
<< (unsigned)ipv4.GetTtl ()
153
<<
" time="
<< delta.
GetMilliSeconds
() <<
" ms\n"
;
154
}
155
}
156
}
157
delete
[] buf;
158
}
159
}
160
}
161
}
162
163
// Writes data to buffer in little-endian format; least significant byte
164
// of data is at lowest buffer address
165
void
166
V4Ping::Write32
(uint8_t *buffer,
const
uint32_t
data
)
167
{
168
buffer[0] = (data >> 0) & 0xff;
169
buffer[1] = (data >> 8) & 0xff;
170
buffer[2] = (data >> 16) & 0xff;
171
buffer[3] = (data >> 24) & 0xff;
172
}
173
174
// Writes data from a little-endian formatted buffer to data
175
void
176
V4Ping::Read32
(
const
uint8_t *buffer, uint32_t &
data
)
177
{
178
data = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
179
}
180
181
void
182
V4Ping::Send
()
183
{
184
NS_LOG_FUNCTION
(
m_seq
);
185
Ptr<Packet>
p = Create<Packet> ();
186
Icmpv4Echo
echo;
187
echo.
SetSequenceNumber
(
m_seq
);
188
m_seq
++;
189
echo.SetIdentifier (0);
190
191
//
192
// We must write quantities out in some form of network order. Since there
193
// isn't an htonl to work with we just follow the convention in pcap traces
194
// (where any difference would show up anyway) and borrow that code. Don't
195
// be too surprised when you see that this is a little endian convention.
196
//
197
uint8_t*
data
=
new
uint8_t[
m_size
];
198
for
(uint32_t i = 0; i <
m_size
; ++i) data[i] = 0;
199
NS_ASSERT
(m_size >= 16);
200
201
uint32_t tmp =
GetNode
()->
GetId
();
202
Write32
(&data[0 *
sizeof
(uint32_t)], tmp);
203
204
tmp =
GetApplicationId
();
205
Write32
(&data[1 *
sizeof
(uint32_t)], tmp);
206
207
Ptr<Packet>
dataPacket = Create<Packet> ((uint8_t *) data, m_size);
208
echo.SetData (dataPacket);
209
p->
AddHeader
(echo);
210
Icmpv4Header
header;
211
header.
SetType
(
Icmpv4Header::ECHO
);
212
header.
SetCode
(0);
213
if
(
Node::ChecksumEnabled
())
214
{
215
header.
EnableChecksum
();
216
}
217
p->
AddHeader
(header);
218
m_sent
.insert (std::make_pair (
m_seq
- 1,
Simulator::Now
()));
219
m_socket
->
Send
(p, 0);
220
m_next
=
Simulator::Schedule
(
m_interval
, &
V4Ping::Send
,
this
);
221
delete
[]
data
;
222
}
223
224
void
225
V4Ping::StartApplication
(
void
)
226
{
227
NS_LOG_FUNCTION
(
this
);
228
229
m_started
=
Simulator::Now
();
230
if
(
m_verbose
)
231
{
232
std::cout <<
"PING "
<<
m_remote
<<
" 56(84) bytes of data.\n"
;
233
}
234
235
m_socket
=
Socket::CreateSocket
(
GetNode
(),
TypeId::LookupByName
(
"ns3::Ipv4RawSocketFactory"
));
236
NS_ASSERT
(
m_socket
!= 0);
237
m_socket
->
SetAttribute
(
"Protocol"
,
UintegerValue
(1));
// icmp
238
m_socket
->
SetRecvCallback
(
MakeCallback
(&
V4Ping::Receive
,
this
));
239
InetSocketAddress
src =
InetSocketAddress
(
Ipv4Address::GetAny
(), 0);
240
int
status;
241
status =
m_socket
->
Bind
(src);
242
NS_ASSERT
(status != -1);
243
InetSocketAddress
dst =
InetSocketAddress
(
m_remote
, 0);
244
status =
m_socket
->
Connect
(dst);
245
NS_ASSERT
(status != -1);
246
247
Send
();
248
}
249
void
250
V4Ping::StopApplication
(
void
)
251
{
252
NS_LOG_FUNCTION
(
this
);
253
m_next
.
Cancel
();
254
m_socket
->
Close
();
255
256
if
(
m_verbose
)
257
{
258
std::ostringstream os;
259
os.precision (4);
260
os <<
"--- "
<<
m_remote
<<
" ping statistics ---\n"
261
<<
m_seq
<<
" packets transmitted, "
<<
m_recv
<<
" received, "
262
<< ((
m_seq
-
m_recv
) * 100 /
m_seq
) <<
"% packet loss, "
263
<<
"time "
<< (
Simulator::Now
() -
m_started
).GetMilliSeconds () <<
"ms\n"
;
264
265
if
(
m_avgRtt
.
Count
() > 0)
266
os <<
"rtt min/avg/max/mdev = "
<<
m_avgRtt
.
Min
() <<
"/"
<<
m_avgRtt
.
Avg
() <<
"/"
267
<<
m_avgRtt
.
Max
() <<
"/"
<<
m_avgRtt
.
Stddev
()
268
<<
" ms\n"
;
269
std::cout << os.str ();
270
}
271
}
272
273
274
}
// namespace ns3
src
applications
model
v4ping.cc
Generated on Tue Oct 9 2012 16:45:33 for ns-3 by
1.8.1.2