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
mesh-wifi-interface-mac.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2009 IITP RAS
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
* Authors: Kirill Andreev <andreev@iitp.ru>
19
* Pavel Boyko <boyko@iitp.ru>
20
*/
21
22
#include "ns3/mesh-wifi-interface-mac.h"
23
#include "ns3/mesh-wifi-beacon.h"
24
#include "ns3/log.h"
25
#include "ns3/boolean.h"
26
#include "ns3/wifi-phy.h"
27
#include "ns3/dcf-manager.h"
28
#include "ns3/mac-rx-middle.h"
29
#include "ns3/mac-low.h"
30
#include "ns3/dca-txop.h"
31
#include "ns3/random-variable-stream.h"
32
#include "ns3/simulator.h"
33
#include "ns3/yans-wifi-phy.h"
34
#include "ns3/pointer.h"
35
#include "ns3/double.h"
36
#include "ns3/trace-source-accessor.h"
37
#include "ns3/qos-tag.h"
38
39
NS_LOG_COMPONENT_DEFINE
(
"MeshWifiInterfaceMac"
);
40
41
namespace
ns3 {
42
43
NS_OBJECT_ENSURE_REGISTERED
(MeshWifiInterfaceMac);
44
45
TypeId
46
MeshWifiInterfaceMac::GetTypeId
()
47
{
48
static
TypeId
tid =
TypeId
(
"ns3::MeshWifiInterfaceMac"
)
49
.
SetParent
<
RegularWifiMac
> ()
50
.AddConstructor<MeshWifiInterfaceMac> ()
51
.AddAttribute (
"BeaconInterval"
,
52
"Beacon Interval"
,
53
TimeValue
(
Seconds
(0.5)),
54
55
MakeTimeAccessor (
56
&
MeshWifiInterfaceMac::m_beaconInterval
),
57
MakeTimeChecker ()
58
)
59
.AddAttribute (
"RandomStart"
,
60
"Window when beacon generating starts (uniform random) in seconds"
,
61
TimeValue
(
Seconds
(0.5)),
62
MakeTimeAccessor (
63
&
MeshWifiInterfaceMac::m_randomStart
),
64
MakeTimeChecker ()
65
)
66
.AddAttribute (
"BeaconGeneration"
,
67
"Enable/Disable Beaconing."
,
68
BooleanValue
(
true
),
69
MakeBooleanAccessor (
70
&
MeshWifiInterfaceMac::SetBeaconGeneration
, &
MeshWifiInterfaceMac::GetBeaconGeneration
),
71
MakeBooleanChecker ()
72
)
73
;
74
return
tid;
75
}
76
MeshWifiInterfaceMac::MeshWifiInterfaceMac
() :
77
m_standard (
WIFI_PHY_STANDARD_80211a
)
78
{
79
NS_LOG_FUNCTION
(
this
);
80
81
// Let the lower layers know that we are acting as a mesh node
82
SetTypeOfStation
(
MESH
);
83
m_coefficient
= CreateObject<UniformRandomVariable> ();
84
}
85
MeshWifiInterfaceMac::~MeshWifiInterfaceMac
()
86
{
87
NS_LOG_FUNCTION
(
this
);
88
}
89
//-----------------------------------------------------------------------------
90
// WifiMac inherited
91
//-----------------------------------------------------------------------------
92
void
93
MeshWifiInterfaceMac::Enqueue
(
Ptr<const Packet>
packet,
Mac48Address
to,
Mac48Address
from)
94
{
95
NS_LOG_FUNCTION
(
this
<< packet << to << from);
96
ForwardDown
(packet, from, to);
97
}
98
void
99
MeshWifiInterfaceMac::Enqueue
(
Ptr<const Packet>
packet,
Mac48Address
to)
100
{
101
NS_LOG_FUNCTION
(
this
<< packet << to);
102
ForwardDown
(packet,
m_low
->
GetAddress
(), to);
103
}
104
bool
105
MeshWifiInterfaceMac::SupportsSendFrom
()
const
106
{
107
return
true
;
108
}
109
void
110
MeshWifiInterfaceMac::SetLinkUpCallback
(
Callback<void>
linkUp)
111
{
112
NS_LOG_FUNCTION
(
this
);
113
RegularWifiMac::SetLinkUpCallback
(linkUp);
114
115
// The approach taken here is that, from the point of view of a mesh
116
// node, the link is always up, so we immediately invoke the
117
// callback if one is set
118
linkUp ();
119
}
120
void
121
MeshWifiInterfaceMac::DoDispose
()
122
{
123
NS_LOG_FUNCTION
(
this
);
124
m_plugins
.clear ();
125
m_beaconSendEvent
.
Cancel
();
126
127
RegularWifiMac::DoDispose
();
128
}
129
void
130
MeshWifiInterfaceMac::DoInitialize
()
131
{
132
m_coefficient
->
SetAttribute
(
"Max"
,
DoubleValue
(
m_randomStart
.
GetSeconds
()));
133
if
(
m_beaconEnable
)
134
{
135
Time
randomStart =
Seconds
(
m_coefficient
->
GetValue
());
136
// Now start sending beacons after some random delay (to avoid collisions)
137
NS_ASSERT
(!
m_beaconSendEvent
.
IsRunning
());
138
m_beaconSendEvent
=
Simulator::Schedule
(randomStart, &
MeshWifiInterfaceMac::SendBeacon
,
this
);
139
m_tbtt
=
Simulator::Now
() + randomStart;
140
}
141
else
142
{
143
// stop sending beacons
144
m_beaconSendEvent
.
Cancel
();
145
}
146
}
147
148
int64_t
149
MeshWifiInterfaceMac::AssignStreams
(int64_t stream)
150
{
151
NS_LOG_FUNCTION
(
this
<< stream);
152
int64_t currentStream = stream;
153
m_coefficient
->
SetStream
(currentStream++);
154
for
(PluginList::const_iterator i =
m_plugins
.begin (); i <
m_plugins
.end (); i++)
155
{
156
currentStream += (*i)->AssignStreams (currentStream);
157
}
158
return
(currentStream - stream);
159
}
160
161
//-----------------------------------------------------------------------------
162
// Plugins
163
//-----------------------------------------------------------------------------
164
void
165
MeshWifiInterfaceMac::InstallPlugin
(
Ptr<MeshWifiInterfaceMacPlugin>
plugin)
166
{
167
NS_LOG_FUNCTION
(
this
);
168
169
plugin->
SetParent
(
this
);
170
m_plugins
.push_back (plugin);
171
}
172
//-----------------------------------------------------------------------------
173
// Switch channels
174
//-----------------------------------------------------------------------------
175
uint16_t
176
MeshWifiInterfaceMac::GetFrequencyChannel
()
const
177
{
178
NS_LOG_FUNCTION
(
this
);
179
NS_ASSERT
(
m_phy
!= 0);
// need PHY to set/get channel
180
181
Ptr<YansWifiPhy>
phy =
m_phy
->
GetObject
<
YansWifiPhy
> ();
182
if
(phy != 0)
183
{
184
return
phy->
GetChannelNumber
();
185
}
186
else
187
{
188
return
0;
189
}
190
}
191
void
192
MeshWifiInterfaceMac::SwitchFrequencyChannel
(uint16_t new_id)
193
{
194
NS_LOG_FUNCTION
(
this
);
195
NS_ASSERT
(
m_phy
!= 0);
// need PHY to set/get channel
196
/* TODO
197
*
198
* Correct channel switching is:
199
*
200
* 1. Interface down, e.g. to stop packets from layer 3
201
* 2. Wait before all output queues will be empty
202
* 3. Switch PHY channel
203
* 4. Interface up
204
*
205
* Now we use dirty channel switch -- just change frequency
206
*/
207
Ptr<YansWifiPhy>
phy =
m_phy
->
GetObject
<
YansWifiPhy
> ();
208
phy->
SetChannelNumber
(new_id);
209
// Don't know NAV on new channel
210
m_dcfManager
->
NotifyNavResetNow
(
Seconds
(0));
211
}
212
//-----------------------------------------------------------------------------
213
// Forward frame down
214
//-----------------------------------------------------------------------------
215
void
216
MeshWifiInterfaceMac::ForwardDown
(
Ptr<const Packet>
const_packet,
Mac48Address
from,
Mac48Address
to)
217
{
218
// copy packet to allow modifications
219
Ptr<Packet>
packet = const_packet->
Copy
();
220
WifiMacHeader
hdr;
221
hdr.
SetTypeData
();
222
hdr.
SetAddr2
(
GetAddress
());
223
hdr.
SetAddr3
(to);
224
hdr.
SetAddr4
(from);
225
hdr.
SetDsFrom
();
226
hdr.
SetDsTo
();
227
// Fill QoS fields:
228
hdr.
SetQosAckPolicy
(
WifiMacHeader::NORMAL_ACK
);
229
hdr.
SetQosNoEosp
();
230
hdr.
SetQosNoAmsdu
();
231
hdr.
SetQosTxopLimit
(0);
232
// Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
233
hdr.
SetAddr1
(
Mac48Address
());
234
// Filter packet through all installed plugins
235
for
(PluginList::const_iterator i =
m_plugins
.end () - 1; i !=
m_plugins
.begin () - 1; i--)
236
{
237
bool
drop = !((*i)->UpdateOutcomingFrame (packet, hdr, from, to));
238
if
(drop)
239
{
240
return
;
// plugin drops frame
241
}
242
}
243
// Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
244
NS_ASSERT
(hdr.
GetAddr1
() !=
Mac48Address
());
245
// Queue frame
246
if
(
m_stationManager
->
IsBrandNew
(hdr.
GetAddr1
()))
247
{
248
// in adhoc mode, we assume that every destination
249
// supports all the rates we support.
250
for
(uint32_t i = 0; i <
m_phy
->
GetNModes
(); i++)
251
{
252
m_stationManager
->
AddSupportedMode
(hdr.
GetAddr1
(),
m_phy
->
GetMode
(i));
253
}
254
m_stationManager
->
RecordDisassociated
(hdr.
GetAddr1
());
255
}
256
//Classify: application sets a tag, which is removed here
257
// Get Qos tag:
258
AcIndex
ac =
AC_BE
;
259
QosTag
tag;
260
if
(packet->
RemovePacketTag
(tag))
261
{
262
hdr.
SetType
(
WIFI_MAC_QOSDATA
);
263
hdr.
SetQosTid
(tag.
GetTid
());
264
//Aftre setting type DsFrom and DsTo fields are reset.
265
hdr.
SetDsFrom
();
266
hdr.
SetDsTo
();
267
ac =
QosUtilsMapTidToAc
(tag.
GetTid
());
268
}
269
m_stats
.
sentFrames
++;
270
m_stats
.
sentBytes
+= packet->
GetSize
();
271
NS_ASSERT
(
m_edca
.find (ac) !=
m_edca
.end ());
272
m_edca
[ac]->Queue (packet, hdr);
273
}
274
void
275
MeshWifiInterfaceMac::SendManagementFrame
(
Ptr<Packet>
packet,
const
WifiMacHeader
& hdr)
276
{
277
//Filter management frames:
278
WifiMacHeader
header = hdr;
279
for
(PluginList::const_iterator i =
m_plugins
.end () - 1; i !=
m_plugins
.begin () - 1; i--)
280
{
281
bool
drop = !((*i)->UpdateOutcomingFrame (packet, header,
Mac48Address
(),
Mac48Address
()));
282
if
(drop)
283
{
284
return
;
// plugin drops frame
285
}
286
}
287
m_stats
.
sentFrames
++;
288
m_stats
.
sentBytes
+= packet->
GetSize
();
289
if
((
m_edca
.find (
AC_VO
) ==
m_edca
.end ()) || (
m_edca
.find (
AC_BK
) ==
m_edca
.end ()))
290
{
291
NS_FATAL_ERROR
(
"Voice or Background queue is not set up!"
);
292
}
293
/*
294
* When we send a management frame - it is better to enqueue it to
295
* priority queue. But when we send a broadcast management frame,
296
* like PREQ, little MinCw value may cause collisions during
297
* retransmissions (two neighbor stations may choose the same window
298
* size, and two packets will be collided). So, broadcast management
299
* frames go to BK queue.
300
*/
301
if
(hdr.
GetAddr1
() !=
Mac48Address::GetBroadcast
())
302
{
303
m_edca
[
AC_VO
]->Queue (packet, header);
304
}
305
else
306
{
307
m_edca
[
AC_BK
]->Queue (packet, header);
308
}
309
}
310
SupportedRates
311
MeshWifiInterfaceMac::GetSupportedRates
()
const
312
{
313
// set the set of supported rates and make sure that we indicate
314
// the Basic Rate set in this set of supported rates.
315
SupportedRates
rates;
316
for
(uint32_t i = 0; i <
m_phy
->
GetNModes
(); i++)
317
{
318
WifiMode
mode =
m_phy
->
GetMode
(i);
319
rates.
AddSupportedRate
(mode.
GetDataRate
());
320
}
321
// set the basic rates
322
for
(uint32_t j = 0; j <
m_stationManager
->
GetNBasicModes
(); j++)
323
{
324
WifiMode
mode =
m_stationManager
->
GetBasicMode
(j);
325
rates.
SetBasicRate
(mode.
GetDataRate
());
326
}
327
return
rates;
328
}
329
bool
330
MeshWifiInterfaceMac::CheckSupportedRates
(
SupportedRates
rates)
const
331
{
332
for
(uint32_t i = 0; i <
m_stationManager
->
GetNBasicModes
(); i++)
333
{
334
WifiMode
mode =
m_stationManager
->
GetBasicMode
(i);
335
if
(!rates.
IsSupportedRate
(mode.
GetDataRate
()))
336
{
337
return
false
;
338
}
339
}
340
return
true
;
341
}
342
//-----------------------------------------------------------------------------
343
// Beacons
344
//-----------------------------------------------------------------------------
345
void
346
MeshWifiInterfaceMac::SetRandomStartDelay
(
Time
interval)
347
{
348
NS_LOG_FUNCTION
(
this
<< interval);
349
m_randomStart
= interval;
350
}
351
void
352
MeshWifiInterfaceMac::SetBeaconInterval
(
Time
interval)
353
{
354
NS_LOG_FUNCTION
(
this
<< interval);
355
m_beaconInterval
= interval;
356
}
357
Time
358
MeshWifiInterfaceMac::GetBeaconInterval
()
const
359
{
360
return
m_beaconInterval
;
361
}
362
void
363
MeshWifiInterfaceMac::SetBeaconGeneration
(
bool
enable)
364
{
365
NS_LOG_FUNCTION
(
this
<< enable);
366
m_beaconEnable
= enable;
367
}
368
bool
369
MeshWifiInterfaceMac::GetBeaconGeneration
()
const
370
{
371
return
m_beaconSendEvent
.
IsRunning
();
372
}
373
Time
374
MeshWifiInterfaceMac::GetTbtt
()
const
375
{
376
return
m_tbtt
;
377
}
378
void
379
MeshWifiInterfaceMac::ShiftTbtt
(
Time
shift)
380
{
381
// User of ShiftTbtt () must take care don't shift it to the past
382
NS_ASSERT
(
GetTbtt
() + shift >
Simulator::Now
());
383
384
m_tbtt
+= shift;
385
// Shift scheduled event
386
Simulator::Cancel
(
m_beaconSendEvent
);
387
m_beaconSendEvent
=
Simulator::Schedule
(
GetTbtt
() -
Simulator::Now
(), &
MeshWifiInterfaceMac::SendBeacon
,
388
this
);
389
}
390
void
391
MeshWifiInterfaceMac::ScheduleNextBeacon
()
392
{
393
m_tbtt
+=
GetBeaconInterval
();
394
m_beaconSendEvent
=
Simulator::Schedule
(
GetBeaconInterval
(), &
MeshWifiInterfaceMac::SendBeacon
,
this
);
395
}
396
void
397
MeshWifiInterfaceMac::SendBeacon
()
398
{
399
NS_LOG_FUNCTION
(
this
);
400
NS_LOG_DEBUG
(
GetAddress
() <<
" is sending beacon"
);
401
402
NS_ASSERT
(!
m_beaconSendEvent
.
IsRunning
());
403
404
// Form & send beacon
405
MeshWifiBeacon
beacon (
GetSsid
(),
GetSupportedRates
(),
m_beaconInterval
.
GetMicroSeconds
());
406
407
// Ask all plugins to add their specific information elements to beacon
408
for
(PluginList::const_iterator i =
m_plugins
.begin (); i !=
m_plugins
.end (); ++i)
409
{
410
(*i)->UpdateBeacon (beacon);
411
}
412
m_dca
->
Queue
(beacon.CreatePacket (), beacon.CreateHeader (
GetAddress
(),
GetMeshPointAddress
()));
413
414
ScheduleNextBeacon
();
415
}
416
void
417
MeshWifiInterfaceMac::Receive
(
Ptr<Packet>
packet,
WifiMacHeader
const
*hdr)
418
{
419
// Process beacon
420
if
((hdr->
GetAddr1
() !=
GetAddress
()) && (hdr->
GetAddr1
() !=
Mac48Address::GetBroadcast
()))
421
{
422
return
;
423
}
424
if
(hdr->
IsBeacon
())
425
{
426
m_stats
.
recvBeacons
++;
427
MgtBeaconHeader
beacon_hdr;
428
429
packet->
PeekHeader
(beacon_hdr);
430
431
NS_LOG_DEBUG
(
"Beacon received from "
<< hdr->
GetAddr2
() <<
" I am "
<<
GetAddress
() <<
" at "
432
<<
Simulator::Now
().
GetMicroSeconds
() <<
" microseconds"
);
433
434
// update supported rates
435
if
(beacon_hdr.
GetSsid
().
IsEqual
(
GetSsid
()))
436
{
437
SupportedRates
rates = beacon_hdr.
GetSupportedRates
();
438
439
for
(uint32_t i = 0; i <
m_phy
->
GetNModes
(); i++)
440
{
441
WifiMode
mode =
m_phy
->
GetMode
(i);
442
if
(rates.
IsSupportedRate
(mode.
GetDataRate
()))
443
{
444
m_stationManager
->
AddSupportedMode
(hdr->
GetAddr2
(), mode);
445
if
(rates.
IsBasicRate
(mode.
GetDataRate
()))
446
{
447
m_stationManager
->
AddBasicMode
(mode);
448
}
449
}
450
}
451
}
452
}
453
else
454
{
455
m_stats
.
recvBytes
+= packet->
GetSize
();
456
m_stats
.
recvFrames
++;
457
}
458
// Filter frame through all installed plugins
459
for
(PluginList::iterator i =
m_plugins
.begin (); i !=
m_plugins
.end (); ++i)
460
{
461
bool
drop = !((*i)->Receive (packet, *hdr));
462
if
(drop)
463
{
464
return
;
// plugin drops frame
465
}
466
}
467
// Check if QoS tag exists and add it:
468
if
(hdr->
IsQosData
())
469
{
470
packet->
AddPacketTag
(
QosTag
(hdr->
GetQosTid
()));
471
}
472
// Forward data up
473
if
(hdr->
IsData
())
474
{
475
ForwardUp
(packet, hdr->
GetAddr4
(), hdr->
GetAddr3
());
476
}
477
478
// We don't bother invoking RegularWifiMac::Receive() here, because
479
// we've explicitly handled all the frames we care about. This is in
480
// contrast to most classes which derive from RegularWifiMac.
481
}
482
uint32_t
483
MeshWifiInterfaceMac::GetLinkMetric
(
Mac48Address
peerAddress)
484
{
485
uint32_t metric = 1;
486
if
(!
m_linkMetricCallback
.
IsNull
())
487
{
488
metric =
m_linkMetricCallback
(peerAddress,
this
);
489
}
490
return
metric;
491
}
492
void
493
MeshWifiInterfaceMac::SetLinkMetricCallback
(
Callback
<uint32_t,
Mac48Address
,
Ptr<MeshWifiInterfaceMac>
> cb)
494
{
495
m_linkMetricCallback
= cb;
496
}
497
void
498
MeshWifiInterfaceMac::SetMeshPointAddress
(
Mac48Address
a)
499
{
500
m_mpAddress
= a;
501
}
502
Mac48Address
503
MeshWifiInterfaceMac::GetMeshPointAddress
()
const
504
{
505
return
m_mpAddress
;
506
}
507
//Statistics:
508
MeshWifiInterfaceMac::Statistics::Statistics
() :
509
recvBeacons (0), sentFrames (0), sentBytes (0), recvFrames (0), recvBytes (0)
510
{
511
}
512
void
513
MeshWifiInterfaceMac::Statistics::Print
(std::ostream & os)
const
514
{
515
os <<
"<Statistics "
516
// TODO txBeacons
517
"rxBeacons=\""
<< recvBeacons <<
"\" "
518
"txFrames=\""
<< sentFrames <<
"\" "
519
"txBytes=\""
<< sentBytes <<
"\" "
520
"rxFrames=\""
<< recvFrames <<
"\" "
521
"rxBytes=\""
<< recvBytes <<
"\"/>"
<< std::endl;
522
}
523
void
524
MeshWifiInterfaceMac::Report
(std::ostream & os)
const
525
{
526
os <<
"<Interface "
527
"BeaconInterval=\""
<<
GetBeaconInterval
().
GetSeconds
() <<
"\" "
528
"Channel=\""
<<
GetFrequencyChannel
() <<
"\" "
529
"Address = \""
<<
GetAddress
() <<
"\">"
<< std::endl;
530
m_stats
.
Print
(os);
531
os <<
"</Interface>"
<< std::endl;
532
}
533
void
534
MeshWifiInterfaceMac::ResetStats
()
535
{
536
m_stats
=
Statistics
();
537
}
538
539
void
540
MeshWifiInterfaceMac::FinishConfigureStandard
(
enum
WifiPhyStandard
standard)
541
{
542
RegularWifiMac::FinishConfigureStandard
(standard);
543
m_standard
= standard;
544
545
// We use the single DCF provided by WifiMac for the purpose of
546
// Beacon transmission. For this we need to reconfigure the channel
547
// access parameters slightly, and do so here.
548
m_dca
->
SetMinCw
(0);
549
m_dca
->
SetMaxCw
(0);
550
m_dca
->
SetAifsn
(1);
551
}
552
WifiPhyStandard
553
MeshWifiInterfaceMac::GetPhyStandard
()
const
554
{
555
return
m_standard
;
556
}
557
}
// namespace ns3
558
src
mesh
model
mesh-wifi-interface-mac.cc
Generated on Tue May 14 2013 11:08:29 for ns-3 by
1.8.1.2