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
radvd.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2008 Telecom Bretagne
4
* Copyright (c) 2009 Strasbourg University
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation;
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
*
19
* Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
20
* Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
21
*/
22
23
#include "ns3/log.h"
24
#include "ns3/ipv6-address.h"
25
#include "ns3/nstime.h"
26
#include "ns3/simulator.h"
27
#include "ns3/packet.h"
28
#include "ns3/net-device.h"
29
#include "ns3/uinteger.h"
30
#include "ns3/inet6-socket-address.h"
31
#include "ns3/ipv6.h"
32
#include "ns3/ipv6-raw-socket-factory.h"
33
#include "ns3/ipv6-header.h"
34
#include "ns3/icmpv6-header.h"
35
#include "ns3/string.h"
36
#include "ns3/pointer.h"
37
38
#include "
radvd.h
"
39
40
namespace
ns3
41
{
42
43
NS_LOG_COMPONENT_DEFINE
(
"RadvdApplication"
);
44
45
NS_OBJECT_ENSURE_REGISTERED
(Radvd);
46
47
TypeId
Radvd::GetTypeId
()
48
{
49
static
TypeId
tid =
TypeId
(
"ns3::Radvd"
)
50
.
SetParent
<
Application
> ()
51
.AddConstructor<Radvd> ()
52
.AddAttribute (
"AdvertisementJitter"
,
53
"Uniform variable to provide jitter between min and max values of AdvInterval"
,
54
StringValue
(
"ns3::UniformRandomVariable"
),
55
MakePointerAccessor (&
Radvd::m_jitter
),
56
MakePointerChecker<UniformRandomVariable> ());
57
;
58
return
tid;
59
}
60
61
Radvd::Radvd
()
62
{
63
NS_LOG_FUNCTION
(
this
);
64
}
65
66
Radvd::~Radvd
()
67
{
68
NS_LOG_FUNCTION
(
this
);
69
for
(
RadvdInterfaceListI
it =
m_configurations
.begin (); it !=
m_configurations
.end (); ++it)
70
{
71
*it = 0;
72
}
73
m_configurations
.clear ();
74
m_socket
= 0;
75
}
76
77
void
Radvd::DoDispose
()
78
{
79
NS_LOG_FUNCTION
(
this
);
80
Application::DoDispose
();
81
}
82
83
void
Radvd::StartApplication
()
84
{
85
NS_LOG_FUNCTION
(
this
);
86
87
if
(!
m_socket
)
88
{
89
TypeId
tid =
TypeId::LookupByName
(
"ns3::Ipv6RawSocketFactory"
);
90
m_socket
=
Socket::CreateSocket
(
GetNode
(), tid);
91
92
NS_ASSERT
(
m_socket
);
93
94
/* m_socket->Bind (Inet6SocketAddress (m_localAddress, 0)); */
95
/* m_socket->Connect (Inet6SocketAddress (Ipv6Address::GetAllNodesMulticast (), 0)); */
96
m_socket
->
SetAttribute
(
"Protocol"
,
UintegerValue
(
Ipv6Header::IPV6_ICMPV6
));
97
m_socket
->
SetRecvCallback
(
MakeCallback
(&
Radvd::HandleRead
,
this
));
98
}
99
100
for
(
RadvdInterfaceListCI
it =
m_configurations
.begin (); it !=
m_configurations
.end (); it++)
101
{
102
m_eventIds
[(*it)->GetInterface ()] =
EventId
();
103
ScheduleTransmit
(
Seconds
(0.), (*it),
m_eventIds
[(*it)->GetInterface ()],
Ipv6Address::GetAllNodesMulticast
(),
true
);
104
}
105
}
106
107
void
Radvd::StopApplication
()
108
{
109
NS_LOG_FUNCTION
(
this
);
110
111
if
(
m_socket
)
112
{
113
m_socket
->
SetRecvCallback
(
MakeNullCallback
<
void
,
Ptr<Socket>
> ());
114
}
115
116
for
(
EventIdMapI
it =
m_eventIds
.begin (); it !=
m_eventIds
.end (); ++it)
117
{
118
Simulator::Cancel
((*it).second);
119
}
120
m_eventIds
.clear ();
121
}
122
123
void
Radvd::AddConfiguration
(
Ptr<RadvdInterface>
routerInterface)
124
{
125
NS_LOG_FUNCTION
(
this
<< routerInterface);
126
m_configurations
.push_back (routerInterface);
127
}
128
129
int64_t
130
Radvd:: AssignStreams
(int64_t stream)
131
{
132
NS_LOG_FUNCTION
(
this
<< stream);
133
m_jitter
->
SetStream
(stream);
134
return
1;
135
}
136
137
void
Radvd::ScheduleTransmit
(
Time
dt,
Ptr<RadvdInterface>
config,
EventId
& eventId,
Ipv6Address
dst,
bool
reschedule)
138
{
139
NS_LOG_FUNCTION
(
this
<< dt << config << &eventId << dst << reschedule);
140
eventId =
Simulator::Schedule
(dt, &
Radvd::Send
,
this
, config, dst, reschedule);
141
}
142
143
void
Radvd::Send
(
Ptr<RadvdInterface>
config,
Ipv6Address
dst,
bool
reschedule)
144
{
145
NS_LOG_FUNCTION
(
this
<< dst << reschedule);
146
NS_ASSERT
(
m_eventIds
[config->
GetInterface
()].IsExpired ());
147
Icmpv6RA
raHdr;
148
Icmpv6OptionLinkLayerAddress
llaHdr;
149
Icmpv6OptionMtu
mtuHdr;
150
Icmpv6OptionPrefixInformation
prefixHdr;
151
152
if
(
m_eventIds
.size () == 0)
153
{
154
return
;
155
}
156
157
std::list<Ptr<RadvdPrefix> > prefixes = config->
GetPrefixes
();
158
Ptr<Packet>
p = Create<Packet> ();
159
Ptr<Ipv6>
ipv6 =
GetNode
()->
GetObject
<
Ipv6
> ();
160
161
/* set RA header information */
162
raHdr.SetFlagM (config->
IsManagedFlag
());
163
raHdr.SetFlagO (config->
IsOtherConfigFlag
());
164
raHdr.SetFlagH (config->
IsHomeAgentFlag
());
165
raHdr.SetCurHopLimit (config->
GetCurHopLimit
());
166
raHdr.SetLifeTime (config->
GetDefaultLifeTime
());
167
raHdr.SetReachableTime (config->
GetReachableTime
());
168
raHdr.SetRetransmissionTime (config->
GetRetransTimer
());
169
170
if
(config->
IsSourceLLAddress
())
171
{
172
/* Get L2 address from NetDevice */
173
Address
addr = ipv6->GetNetDevice (config->
GetInterface
())->GetAddress ();
174
llaHdr =
Icmpv6OptionLinkLayerAddress
(
true
, addr);
175
p->
AddHeader
(llaHdr);
176
}
177
178
if
(config->
GetLinkMtu
())
179
{
180
NS_ASSERT
(config->
GetLinkMtu
() >= 1280);
181
mtuHdr =
Icmpv6OptionMtu
(config->
GetLinkMtu
());
182
p->
AddHeader
(mtuHdr);
183
}
184
185
/* add list of prefixes */
186
for
(
std::list
<
Ptr<RadvdPrefix>
>::const_iterator jt = prefixes.begin (); jt != prefixes.end (); jt++)
187
{
188
uint8_t flags = 0;
189
prefixHdr =
Icmpv6OptionPrefixInformation
();
190
prefixHdr.
SetPrefix
((*jt)->GetNetwork ());
191
prefixHdr.
SetPrefixLength
((*jt)->GetPrefixLength ());
192
prefixHdr.
SetValidTime
((*jt)->GetValidLifeTime ());
193
prefixHdr.
SetPreferredTime
((*jt)->GetPreferredLifeTime ());
194
195
if
((*jt)->IsOnLinkFlag ())
196
{
197
flags += 1 << 7;
198
}
199
200
if
((*jt)->IsAutonomousFlag ())
201
{
202
flags += 1 << 6;
203
}
204
205
if
((*jt)->IsRouterAddrFlag ())
206
{
207
flags += 1 << 5;
208
}
209
210
prefixHdr.
SetFlags
(flags);
211
212
p->
AddHeader
(prefixHdr);
213
}
214
215
Ipv6Address
src = ipv6->GetAddress (config->
GetInterface
(), 0).GetAddress ();
216
m_socket
->
Bind
(
Inet6SocketAddress
(src, 0));
217
m_socket
->
Connect
(
Inet6SocketAddress
(dst, 0));
218
219
/* as we know interface index that will be used to send RA and
220
* we always send RA with router's link-local address, we can
221
* calculate checksum here.
222
*/
223
raHdr.CalculatePseudoHeaderChecksum (src, dst, p->
GetSize
() + raHdr.GetSerializedSize (), 58
/* ICMPv6 */
);
224
p->
AddHeader
(raHdr);
225
226
/* Router advertisements MUST always have a ttl of 255
227
* The ttl value should be set as a socket option, but this is not yet implemented
228
*/
229
SocketIpTtlTag
ttl;
230
ttl.
SetTtl
(255);
231
p->
AddPacketTag
(ttl);
232
233
/* send RA */
234
NS_LOG_LOGIC
(
"Send RA"
);
235
m_socket
->
Send
(p, 0);
236
237
if
(reschedule)
238
{
239
uint64_t delay =
static_cast<
uint64_t
>
(
m_jitter
->
GetValue
(config->
GetMinRtrAdvInterval
(), config->
GetMaxRtrAdvInterval
()) + 0.5);
240
NS_LOG_INFO
(
"Reschedule in "
<< delay);
241
Time
t =
MilliSeconds
(delay);
242
ScheduleTransmit
(t, config,
m_eventIds
[config->
GetInterface
()],
Ipv6Address::GetAllNodesMulticast
(), reschedule);
243
}
244
}
245
246
void
Radvd::HandleRead
(
Ptr<Socket>
socket)
247
{
248
NS_LOG_FUNCTION
(
this
<< socket);
249
Ptr<Packet>
packet = 0;
250
Address
from;
251
252
while
((packet = socket->
RecvFrom
(from)))
253
{
254
if
(
Inet6SocketAddress::IsMatchingType
(from))
255
{
256
Ipv6Header
hdr;
257
Icmpv6RS
rsHdr;
258
Inet6SocketAddress
address =
Inet6SocketAddress::ConvertFrom
(from);
259
uint64_t delay = 0;
260
Time
t;
261
262
packet->
RemoveHeader
(hdr);
263
uint8_t type;
264
packet->
CopyData
(&type,
sizeof
(type));
265
266
switch
(type)
267
{
268
case
Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION
:
269
packet->
RemoveHeader
(rsHdr);
270
NS_LOG_INFO
(
"Received ICMPv6 Router Solicitation from "
<< hdr.
GetSourceAddress
() <<
" code = "
<< (uint32_t)rsHdr.
GetCode
());
271
272
/* XXX advertise just prefix(es) for the interface not all */
273
for
(
RadvdInterfaceListCI
it =
m_configurations
.begin (); it !=
m_configurations
.end (); it++)
274
{
275
/* calculate minimum delay between RA */
276
delay =
static_cast<
uint64_t
>
(
m_jitter
->
GetValue
(0,
MAX_RA_DELAY_TIME
) + 0.5);
277
t =
Simulator::Now
() +
MilliSeconds
(delay);
/* absolute time of solicited RA */
278
279
/* if our solicited RA is before the next periodic RA, we schedule it */
280
if
(t.
GetTimeStep
() <
static_cast<
int64_t
>
(
m_eventIds
[(*it)->GetInterface ()].GetTs ()))
281
{
282
NS_LOG_INFO
(
"schedule new RA"
);
283
EventId
ei;
284
285
ScheduleTransmit
(
MilliSeconds
(delay), (*it), ei, address.
GetIpv6
(),
false
);
286
}
287
}
288
break
;
289
default
:
290
break
;
291
}
292
}
293
}
294
}
295
296
}
/* namespace ns3 */
297
src
applications
model
radvd.cc
Generated on Tue May 14 2013 11:08:16 for ns-3 by
1.8.1.2