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_NOARGS
();
64
}
65
66
Radvd::~Radvd
()
67
{
68
NS_LOG_FUNCTION_NOARGS
();
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_NOARGS
();
80
Application::DoDispose
();
81
}
82
83
void
Radvd::StartApplication
()
84
{
85
NS_LOG_FUNCTION_NOARGS
();
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_NOARGS
();
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
m_configurations
.push_back (routerInterface);
126
}
127
128
int64_t
129
Radvd:: AssignStreams
(int64_t stream)
130
{
131
NS_LOG_FUNCTION
(
this
<< stream);
132
m_jitter
->
SetStream
(stream);
133
return
1;
134
}
135
136
void
Radvd::ScheduleTransmit
(
Time
dt,
Ptr<RadvdInterface>
config,
EventId
& eventId,
Ipv6Address
dst,
bool
reschedule)
137
{
138
NS_LOG_FUNCTION
(
this
<< dt);
139
eventId =
Simulator::Schedule
(dt, &
Radvd::Send
,
this
, config, dst, reschedule);
140
}
141
142
void
Radvd::Send
(
Ptr<RadvdInterface>
config,
Ipv6Address
dst,
bool
reschedule)
143
{
144
NS_LOG_FUNCTION
(
this
<< dst);
145
NS_ASSERT
(
m_eventIds
[config->
GetInterface
()].IsExpired ());
146
Icmpv6RA
raHdr;
147
Icmpv6OptionLinkLayerAddress
llaHdr;
148
Icmpv6OptionMtu
mtuHdr;
149
Icmpv6OptionPrefixInformation
prefixHdr;
150
151
if
(
m_eventIds
.size () == 0)
152
{
153
return
;
154
}
155
156
std::list<Ptr<RadvdPrefix> > prefixes = config->
GetPrefixes
();
157
Ptr<Packet>
p = Create<Packet> ();
158
Ptr<Ipv6>
ipv6 =
GetNode
()->
GetObject
<
Ipv6
> ();
159
160
/* set RA header information */
161
raHdr.SetFlagM (config->
IsManagedFlag
());
162
raHdr.SetFlagO (config->
IsOtherConfigFlag
());
163
raHdr.SetFlagH (config->
IsHomeAgentFlag
());
164
raHdr.SetCurHopLimit (config->
GetCurHopLimit
());
165
raHdr.SetLifeTime (config->
GetDefaultLifeTime
());
166
raHdr.SetReachableTime (config->
GetReachableTime
());
167
raHdr.SetRetransmissionTime (config->
GetRetransTimer
());
168
169
if
(config->
IsSourceLLAddress
())
170
{
171
/* Get L2 address from NetDevice */
172
Address
addr = ipv6->GetNetDevice (config->
GetInterface
())->GetAddress ();
173
llaHdr =
Icmpv6OptionLinkLayerAddress
(
true
, addr);
174
p->
AddHeader
(llaHdr);
175
}
176
177
if
(config->
GetLinkMtu
())
178
{
179
NS_ASSERT
(config->
GetLinkMtu
() >= 1280);
180
mtuHdr =
Icmpv6OptionMtu
(config->
GetLinkMtu
());
181
p->
AddHeader
(mtuHdr);
182
}
183
184
/* add list of prefixes */
185
for
(
std::list
<
Ptr<RadvdPrefix>
>::const_iterator jt = prefixes.begin (); jt != prefixes.end (); jt++)
186
{
187
uint8_t flags = 0;
188
prefixHdr =
Icmpv6OptionPrefixInformation
();
189
prefixHdr.
SetPrefix
((*jt)->GetNetwork ());
190
prefixHdr.
SetPrefixLength
((*jt)->GetPrefixLength ());
191
prefixHdr.
SetValidTime
((*jt)->GetValidLifeTime ());
192
prefixHdr.
SetPreferredTime
((*jt)->GetPreferredLifeTime ());
193
194
if
((*jt)->IsOnLinkFlag ())
195
{
196
flags += 1 << 7;
197
}
198
199
if
((*jt)->IsAutonomousFlag ())
200
{
201
flags += 1 << 6;
202
}
203
204
if
((*jt)->IsRouterAddrFlag ())
205
{
206
flags += 1 << 5;
207
}
208
209
prefixHdr.
SetFlags
(flags);
210
211
p->
AddHeader
(prefixHdr);
212
}
213
214
Ipv6Address
src = ipv6->GetAddress (config->
GetInterface
(), 0).GetAddress ();
215
m_socket
->
Bind
(
Inet6SocketAddress
(src, 0));
216
m_socket
->
Connect
(
Inet6SocketAddress
(dst, 0));
217
218
/* as we know interface index that will be used to send RA and
219
* we always send RA with router's link-local address, we can
220
* calculate checksum here.
221
*/
222
raHdr.CalculatePseudoHeaderChecksum (src, dst, p->
GetSize
() + raHdr.GetSerializedSize (), 58
/* ICMPv6 */
);
223
p->
AddHeader
(raHdr);
224
225
/* Router advertisements MUST always have a ttl of 255
226
* The ttl value should be set as a socket option, but this is not yet implemented
227
*/
228
SocketIpTtlTag
ttl;
229
ttl.
SetTtl
(255);
230
p->
AddPacketTag
(ttl);
231
232
/* send RA */
233
NS_LOG_LOGIC
(
"Send RA"
);
234
m_socket
->
Send
(p, 0);
235
236
if
(reschedule)
237
{
238
uint64_t delay =
static_cast<
uint64_t
>
(
m_jitter
->
GetValue
(config->
GetMinRtrAdvInterval
(), config->
GetMaxRtrAdvInterval
()) + 0.5);
239
NS_LOG_INFO
(
"Reschedule in "
<< delay);
240
Time
t =
MilliSeconds
(delay);
241
ScheduleTransmit
(t, config,
m_eventIds
[config->
GetInterface
()],
Ipv6Address::GetAllNodesMulticast
(), reschedule);
242
}
243
}
244
245
void
Radvd::HandleRead
(
Ptr<Socket>
socket)
246
{
247
NS_LOG_FUNCTION
(
this
<< socket);
248
Ptr<Packet>
packet = 0;
249
Address
from;
250
251
while
((packet = socket->
RecvFrom
(from)))
252
{
253
if
(
Inet6SocketAddress::IsMatchingType
(from))
254
{
255
Ipv6Header
hdr;
256
Icmpv6RS
rsHdr;
257
Inet6SocketAddress
address =
Inet6SocketAddress::ConvertFrom
(from);
258
uint64_t delay = 0;
259
Time
t;
260
261
packet->
RemoveHeader
(hdr);
262
uint8_t type;
263
packet->
CopyData
(&type,
sizeof
(type));
264
265
switch
(type)
266
{
267
case
Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION
:
268
packet->
RemoveHeader
(rsHdr);
269
NS_LOG_INFO
(
"Received ICMPv6 Router Solicitation from "
<< hdr.
GetSourceAddress
() <<
" code = "
<< (uint32_t)rsHdr.
GetCode
());
270
271
/* XXX advertise just prefix(es) for the interface not all */
272
for
(
RadvdInterfaceListCI
it =
m_configurations
.begin (); it !=
m_configurations
.end (); it++)
273
{
274
/* calculate minimum delay between RA */
275
delay =
static_cast<
uint64_t
>
(
m_jitter
->
GetValue
(0,
MAX_RA_DELAY_TIME
) + 0.5);
276
t =
Simulator::Now
() +
MilliSeconds
(delay);
/* absolute time of solicited RA */
277
278
/* if our solicited RA is before the next periodic RA, we schedule it */
279
if
(t.
GetTimeStep
() <
static_cast<
int64_t
>
(
m_eventIds
[(*it)->GetInterface ()].GetTs ()))
280
{
281
NS_LOG_INFO
(
"schedule new RA"
);
282
EventId
ei;
283
284
ScheduleTransmit
(
MilliSeconds
(delay), (*it), ei, address.
GetIpv6
(),
false
);
285
}
286
}
287
break
;
288
default
:
289
break
;
290
}
291
}
292
}
293
}
294
295
}
/* namespace ns3 */
296
src
applications
model
radvd.cc
Generated on Tue Oct 9 2012 16:45:33 for ns-3 by
1.8.1.2