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
ping6.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2007-2009 Strasbourg University
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation;
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
*
18
* Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19
*/
20
21
#include "ns3/log.h"
22
#include "ns3/nstime.h"
23
#include "ns3/simulator.h"
24
#include "ns3/socket-factory.h"
25
#include "ns3/packet.h"
26
#include "ns3/socket.h"
27
#include "ns3/uinteger.h"
28
#include "ns3/ipv6.h"
29
#include "ns3/ipv6-address.h"
30
#include "ns3/inet6-socket-address.h"
31
#include "ns3/icmpv6-header.h"
32
#include "ns3/ipv6-raw-socket-factory.h"
33
#include "ns3/ipv6-header.h"
34
#include "ns3/ipv6-extension-header.h"
35
36
#include "
ping6.h
"
37
38
namespace
ns3
39
{
40
41
NS_LOG_COMPONENT_DEFINE
(
"Ping6Application"
);
42
43
NS_OBJECT_ENSURE_REGISTERED
(Ping6);
44
45
TypeId
Ping6::GetTypeId
()
46
{
47
static
TypeId
tid =
TypeId
(
"ns3::Ping6"
)
48
.
SetParent
<
Application
>()
49
.AddConstructor<Ping6>()
50
.AddAttribute (
"MaxPackets"
,
51
"The maximum number of packets the application will send"
,
52
UintegerValue
(100),
53
MakeUintegerAccessor (&
Ping6::m_count
),
54
MakeUintegerChecker<uint32_t>())
55
.AddAttribute (
"Interval"
,
56
"The time to wait between packets"
,
57
TimeValue
(Seconds (1.0)),
58
MakeTimeAccessor (&
Ping6::m_interval
),
59
MakeTimeChecker
())
60
.AddAttribute (
"RemoteIpv6"
,
61
"The Ipv6Address of the outbound packets"
,
62
Ipv6AddressValue
(),
63
MakeIpv6AddressAccessor (&
Ping6::m_peerAddress
),
64
MakeIpv6AddressChecker ())
65
.AddAttribute (
"LocalIpv6"
,
66
"Local Ipv6Address of the sender"
,
67
Ipv6AddressValue
(),
68
MakeIpv6AddressAccessor (&
Ping6::m_localAddress
),
69
MakeIpv6AddressChecker ())
70
.AddAttribute (
"PacketSize"
,
71
"Size of packets generated"
,
72
UintegerValue
(100),
73
MakeUintegerAccessor (&
Ping6::m_size
),
74
MakeUintegerChecker<uint32_t>())
75
;
76
return
tid;
77
}
78
79
Ping6::Ping6
()
80
{
81
NS_LOG_FUNCTION_NOARGS
();
82
m_sent
= 0;
83
m_socket
= 0;
84
m_seq
= 0;
85
m_sendEvent
=
EventId
();
86
}
87
88
Ping6::~Ping6
()
89
{
90
NS_LOG_FUNCTION_NOARGS
();
91
m_socket
= 0;
92
}
93
94
void
Ping6::DoDispose
()
95
{
96
NS_LOG_FUNCTION_NOARGS
();
97
Application::DoDispose
();
98
}
99
100
void
Ping6::StartApplication
()
101
{
102
NS_LOG_FUNCTION_NOARGS
();
103
104
if
(!
m_socket
)
105
{
106
TypeId
tid =
TypeId::LookupByName
(
"ns3::Ipv6RawSocketFactory"
);
107
m_socket
=
Socket::CreateSocket
(
GetNode
(), tid);
108
109
NS_ASSERT
(
m_socket
);
110
111
m_socket
->
Bind
(
Inet6SocketAddress
(
m_localAddress
, 0));
112
m_socket
->
Connect
(
Inet6SocketAddress
(
m_peerAddress
, 0));
113
m_socket
->
SetAttribute
(
"Protocol"
,
UintegerValue
(
Ipv6Header::IPV6_ICMPV6
));
114
m_socket
->
SetRecvCallback
(
MakeCallback
(&
Ping6::HandleRead
,
this
));
115
}
116
117
ScheduleTransmit
(Seconds (0.));
118
}
119
120
void
Ping6::SetLocal
(
Ipv6Address
ipv6)
121
{
122
NS_LOG_FUNCTION
(
this
<< ipv6);
123
m_localAddress
= ipv6;
124
}
125
126
void
Ping6::SetRemote
(
Ipv6Address
ipv6)
127
{
128
NS_LOG_FUNCTION
(
this
<< ipv6);
129
m_peerAddress
= ipv6;
130
}
131
132
void
Ping6::StopApplication
()
133
{
134
NS_LOG_FUNCTION_NOARGS
();
135
136
if
(
m_socket
)
137
{
138
m_socket
->
SetRecvCallback
(
MakeNullCallback
<
void
,
Ptr<Socket>
>());
139
}
140
141
Simulator::Cancel
(
m_sendEvent
);
142
}
143
144
void
Ping6::SetIfIndex
(uint32_t ifIndex)
145
{
146
m_ifIndex
= ifIndex;
147
}
148
149
void
Ping6::ScheduleTransmit
(
Time
dt)
150
{
151
NS_LOG_FUNCTION
(
this
<< dt);
152
m_sendEvent
=
Simulator::Schedule
(dt, &
Ping6::Send
,
this
);
153
}
154
155
void
Ping6::SetRouters
(std::vector<Ipv6Address> routers)
156
{
157
m_routers
= routers;
158
}
159
160
void
Ping6::Send
()
161
{
162
NS_LOG_FUNCTION_NOARGS
();
163
NS_ASSERT
(
m_sendEvent
.
IsExpired
());
164
Ptr<Packet>
p = 0;
165
uint8_t*
data
=
new
uint8_t[
m_size
];
166
Ipv6Address
src;
167
Ptr<Ipv6>
ipv6 =
GetNode
()->
GetObject
<
Ipv6
> ();
168
169
if
(
m_ifIndex
> 0)
170
{
171
/* hack to have ifIndex in Ipv6RawSocketImpl
172
* maybe add a SetIfIndex in Ipv6RawSocketImpl directly
173
*/
174
Ipv6InterfaceAddress
dstIa (
m_peerAddress
);
175
for
(uint32_t i = 0; i <
GetNode
()->
GetObject
<
Ipv6
> ()->GetNAddresses (
m_ifIndex
); i++)
176
{
177
src =
GetNode
()->
GetObject
<
Ipv6
> ()->GetAddress (
m_ifIndex
, i).
GetAddress
();
178
Ipv6InterfaceAddress
srcIa (src);
179
if
( srcIa.
GetScope
() == dstIa.
GetScope
() )
180
{
181
break
;
182
}
183
}
184
}
185
else
186
{
187
src =
m_localAddress
;
188
}
189
190
NS_ASSERT_MSG
(
m_size
>= 4,
"ICMPv6 echo request payload size must be >= 4"
);
191
data[0] = 0xDE;
192
data[1] = 0xAD;
193
data[2] = 0xBE;
194
data[3] = 0xEF;
195
196
p = Create<Packet> (
data
, 4);
197
p->AddAtEnd (Create<Packet> (
m_size
- 4));
198
Icmpv6Echo
req (1);
199
200
req.
SetId
(0xBEEF);
201
req.
SetSeq
(
m_seq
);
202
m_seq
++;
203
204
/* we do not calculate pseudo header checksum here, because we are not sure about
205
* source IPv6 address. Checksum is calculated in Ipv6RawSocketImpl.
206
*/
207
208
p->AddHeader (req);
209
m_socket
->
Bind
(
Inet6SocketAddress
(src, 0));
210
211
/* use Loose Routing (routing type 0) */
212
if
(
m_routers
.size ())
213
{
214
Ipv6ExtensionLooseRoutingHeader
routingHeader;
215
routingHeader.
SetNextHeader
(
Ipv6Header::IPV6_ICMPV6
);
216
routingHeader.
SetLength
(
m_routers
.size () * 16 + 8);
217
routingHeader.
SetTypeRouting
(0);
218
routingHeader.
SetSegmentsLeft
(
m_routers
.size ());
219
routingHeader.
SetRoutersAddress
(
m_routers
);
220
p->AddHeader (routingHeader);
221
m_socket
->
SetAttribute
(
"Protocol"
,
UintegerValue
(
Ipv6Header::IPV6_EXT_ROUTING
));
222
}
223
224
m_socket
->
Send
(p, 0);
225
++
m_sent
;
226
227
NS_LOG_INFO
(
"Sent "
<< p->GetSize () <<
" bytes to "
<<
m_peerAddress
);
228
229
if
(
m_sent
<
m_count
)
230
{
231
ScheduleTransmit
(
m_interval
);
232
}
233
234
delete
[]
data
;
235
}
236
237
void
Ping6::HandleRead
(
Ptr<Socket>
socket)
238
{
239
NS_LOG_FUNCTION
(
this
<< socket);
240
241
Ptr<Packet>
packet=0;
242
Address
from;
243
while
((packet = socket->
RecvFrom
(from)))
244
{
245
if
(
Inet6SocketAddress::IsMatchingType
(from))
246
{
247
Ipv6Header
hdr;
248
Icmpv6Echo
reply (0);
249
Inet6SocketAddress
address
=
Inet6SocketAddress::ConvertFrom
(from);
250
251
packet->
RemoveHeader
(hdr);
252
253
uint8_t type;
254
packet->
CopyData
(&type,
sizeof
(type));
255
256
switch
(type)
257
{
258
case
Icmpv6Header::ICMPV6_ECHO_REPLY
:
259
packet->
RemoveHeader
(reply);
260
261
NS_LOG_INFO
(
"Received Echo Reply size = "
<< std::dec << packet->
GetSize
() <<
" bytes from "
<< address.
GetIpv6
() <<
" id = "
<< (uint16_t)reply.
GetId
() <<
" seq = "
<< (uint16_t)reply.
GetSeq
());
262
break
;
263
default
:
264
/* other type, discard */
265
break
;
266
}
267
}
268
}
269
}
270
271
}
/* namespace ns3 */
272
src
applications
model
ping6.cc
Generated on Fri Aug 30 2013 01:42:44 for ns-3 by
1.8.1.2