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
ap-wifi-mac.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2006, 2009 INRIA
4
* Copyright (c) 2009 MIRKO BANCHI
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20
* Author: Mirko Banchi <mk.banchi@gmail.com>
21
*/
22
#include "
ap-wifi-mac.h
"
23
24
#include "ns3/assert.h"
25
#include "ns3/log.h"
26
#include "ns3/simulator.h"
27
#include "ns3/string.h"
28
#include "ns3/pointer.h"
29
#include "ns3/boolean.h"
30
31
#include "
qos-tag.h
"
32
#include "
wifi-phy.h
"
33
#include "
dcf-manager.h
"
34
#include "
mac-rx-middle.h
"
35
#include "
mac-tx-middle.h
"
36
#include "
mgt-headers.h
"
37
#include "
mac-low.h
"
38
#include "
amsdu-subframe-header.h
"
39
#include "
msdu-aggregator.h
"
40
41
NS_LOG_COMPONENT_DEFINE
(
"ApWifiMac"
);
42
43
namespace
ns3 {
44
45
NS_OBJECT_ENSURE_REGISTERED
(ApWifiMac);
46
47
TypeId
48
ApWifiMac::GetTypeId
(
void
)
49
{
50
static
TypeId
tid =
TypeId
(
"ns3::ApWifiMac"
)
51
.
SetParent
<
RegularWifiMac
> ()
52
.AddConstructor<ApWifiMac> ()
53
.AddAttribute (
"BeaconInterval"
,
"Delay between two beacons"
,
54
TimeValue
(
MicroSeconds
(102400)),
55
MakeTimeAccessor (&
ApWifiMac::GetBeaconInterval
,
56
&
ApWifiMac::SetBeaconInterval
),
57
MakeTimeChecker ())
58
.AddAttribute (
"BeaconGeneration"
,
"Whether or not beacons are generated."
,
59
BooleanValue
(
true
),
60
MakeBooleanAccessor (&
ApWifiMac::SetBeaconGeneration
,
61
&
ApWifiMac::GetBeaconGeneration
),
62
MakeBooleanChecker ())
63
;
64
return
tid;
65
}
66
67
ApWifiMac::ApWifiMac
()
68
{
69
NS_LOG_FUNCTION
(
this
);
70
m_beaconDca
= CreateObject<DcaTxop> ();
71
m_beaconDca
->
SetAifsn
(1);
72
m_beaconDca
->
SetMinCw
(0);
73
m_beaconDca
->
SetMaxCw
(0);
74
m_beaconDca
->
SetLow
(
m_low
);
75
m_beaconDca
->
SetManager
(
m_dcfManager
);
76
77
// Let the lower layers know that we are acting as an AP.
78
SetTypeOfStation
(
AP
);
79
80
m_enableBeaconGeneration
=
false
;
81
}
82
83
ApWifiMac::~ApWifiMac
()
84
{
85
NS_LOG_FUNCTION
(
this
);
86
}
87
88
void
89
ApWifiMac::DoDispose
()
90
{
91
NS_LOG_FUNCTION
(
this
);
92
m_beaconDca
= 0;
93
m_enableBeaconGeneration
=
false
;
94
m_beaconEvent
.
Cancel
();
95
RegularWifiMac::DoDispose
();
96
}
97
98
void
99
ApWifiMac::SetAddress
(
Mac48Address
address)
100
{
101
NS_LOG_FUNCTION
(
this
<< address);
102
// As an AP, our MAC address is also the BSSID. Hence we are
103
// overriding this function and setting both in our parent class.
104
RegularWifiMac::SetAddress
(address);
105
RegularWifiMac::SetBssid
(address);
106
}
107
108
void
109
ApWifiMac::SetBeaconGeneration
(
bool
enable)
110
{
111
NS_LOG_FUNCTION
(
this
<< enable);
112
if
(!enable)
113
{
114
m_beaconEvent
.
Cancel
();
115
}
116
else
if
(enable && !
m_enableBeaconGeneration
)
117
{
118
m_beaconEvent
=
Simulator::ScheduleNow
(&
ApWifiMac::SendOneBeacon
,
this
);
119
}
120
m_enableBeaconGeneration
= enable;
121
}
122
123
bool
124
ApWifiMac::GetBeaconGeneration
(
void
)
const
125
{
126
NS_LOG_FUNCTION
(
this
);
127
return
m_enableBeaconGeneration
;
128
}
129
130
Time
131
ApWifiMac::GetBeaconInterval
(
void
)
const
132
{
133
NS_LOG_FUNCTION
(
this
);
134
return
m_beaconInterval
;
135
}
136
137
void
138
ApWifiMac::SetWifiRemoteStationManager
(
Ptr<WifiRemoteStationManager>
stationManager)
139
{
140
NS_LOG_FUNCTION
(
this
<< stationManager);
141
m_beaconDca
->
SetWifiRemoteStationManager
(stationManager);
142
RegularWifiMac::SetWifiRemoteStationManager
(stationManager);
143
}
144
145
void
146
ApWifiMac::SetLinkUpCallback
(
Callback<void>
linkUp)
147
{
148
NS_LOG_FUNCTION
(
this
<< &linkUp);
149
RegularWifiMac::SetLinkUpCallback
(linkUp);
150
151
// The approach taken here is that, from the point of view of an AP,
152
// the link is always up, so we immediately invoke the callback if
153
// one is set
154
linkUp ();
155
}
156
157
void
158
ApWifiMac::SetBeaconInterval
(
Time
interval)
159
{
160
NS_LOG_FUNCTION
(
this
<< interval);
161
if
((interval.
GetMicroSeconds
() % 1024) != 0)
162
{
163
NS_LOG_WARN
(
"beacon interval should be multiple of 1024us, see IEEE Std. 802.11-2007, section 11.1.1.1"
);
164
}
165
m_beaconInterval
= interval;
166
}
167
168
void
169
ApWifiMac::StartBeaconing
(
void
)
170
{
171
NS_LOG_FUNCTION
(
this
);
172
SendOneBeacon
();
173
}
174
175
void
176
ApWifiMac::ForwardDown
(
Ptr<const Packet>
packet,
Mac48Address
from,
177
Mac48Address
to)
178
{
179
NS_LOG_FUNCTION
(
this
<< packet << from << to);
180
// If we are not a QoS AP then we definitely want to use AC_BE to
181
// transmit the packet. A TID of zero will map to AC_BE (through \c
182
// QosUtilsMapTidToAc()), so we use that as our default here.
183
uint8_t tid = 0;
184
185
// If we are a QoS AP then we attempt to get a TID for this packet
186
if
(
m_qosSupported
)
187
{
188
tid =
QosUtilsGetTidForPacket
(packet);
189
// Any value greater than 7 is invalid and likely indicates that
190
// the packet had no QoS tag, so we revert to zero, which'll
191
// mean that AC_BE is used.
192
if
(tid >= 7)
193
{
194
tid = 0;
195
}
196
}
197
198
ForwardDown
(packet, from, to, tid);
199
}
200
201
void
202
ApWifiMac::ForwardDown
(
Ptr<const Packet>
packet,
Mac48Address
from,
203
Mac48Address
to, uint8_t tid)
204
{
205
NS_LOG_FUNCTION
(
this
<< packet << from << to << static_cast<uint32_t> (tid));
206
WifiMacHeader
hdr;
207
208
// For now, an AP that supports QoS does not support non-QoS
209
// associations, and vice versa. In future the AP model should
210
// support simultaneously associated QoS and non-QoS STAs, at which
211
// point there will need to be per-association QoS state maintained
212
// by the association state machine, and consulted here.
213
if
(
m_qosSupported
)
214
{
215
hdr.
SetType
(
WIFI_MAC_QOSDATA
);
216
hdr.
SetQosAckPolicy
(
WifiMacHeader::NORMAL_ACK
);
217
hdr.
SetQosNoEosp
();
218
hdr.
SetQosNoAmsdu
();
219
// Transmission of multiple frames in the same TXOP is not
220
// supported for now
221
hdr.
SetQosTxopLimit
(0);
222
// Fill in the QoS control field in the MAC header
223
hdr.
SetQosTid
(tid);
224
}
225
else
226
{
227
hdr.
SetTypeData
();
228
}
229
230
hdr.
SetAddr1
(to);
231
hdr.
SetAddr2
(
GetAddress
());
232
hdr.
SetAddr3
(from);
233
hdr.
SetDsFrom
();
234
hdr.
SetDsNotTo
();
235
236
if
(
m_qosSupported
)
237
{
238
// Sanity check that the TID is valid
239
NS_ASSERT
(tid < 8);
240
m_edca
[
QosUtilsMapTidToAc
(tid)]->Queue (packet, hdr);
241
}
242
else
243
{
244
m_dca
->
Queue
(packet, hdr);
245
}
246
}
247
248
void
249
ApWifiMac::Enqueue
(
Ptr<const Packet>
packet,
Mac48Address
to,
Mac48Address
from)
250
{
251
NS_LOG_FUNCTION
(
this
<< packet << to << from);
252
if
(to.
IsBroadcast
() ||
m_stationManager
->
IsAssociated
(to))
253
{
254
ForwardDown
(packet, from, to);
255
}
256
}
257
258
void
259
ApWifiMac::Enqueue
(
Ptr<const Packet>
packet,
Mac48Address
to)
260
{
261
NS_LOG_FUNCTION
(
this
<< packet << to);
262
// We're sending this packet with a from address that is our own. We
263
// get that address from the lower MAC and make use of the
264
// from-spoofing Enqueue() method to avoid duplicated code.
265
Enqueue
(packet, to,
m_low
->
GetAddress
());
266
}
267
268
bool
269
ApWifiMac::SupportsSendFrom
(
void
)
const
270
{
271
NS_LOG_FUNCTION
(
this
);
272
return
true
;
273
}
274
275
SupportedRates
276
ApWifiMac::GetSupportedRates
(
void
)
const
277
{
278
NS_LOG_FUNCTION
(
this
);
279
// send the set of supported rates and make sure that we indicate
280
// the Basic Rate set in this set of supported rates.
281
SupportedRates
rates;
282
for
(uint32_t i = 0; i <
m_phy
->
GetNModes
(); i++)
283
{
284
WifiMode
mode =
m_phy
->
GetMode
(i);
285
rates.
AddSupportedRate
(mode.
GetDataRate
());
286
}
287
// set the basic rates
288
for
(uint32_t j = 0; j <
m_stationManager
->
GetNBasicModes
(); j++)
289
{
290
WifiMode
mode =
m_stationManager
->
GetBasicMode
(j);
291
rates.
SetBasicRate
(mode.
GetDataRate
());
292
}
293
return
rates;
294
}
295
296
void
297
ApWifiMac::SendProbeResp
(
Mac48Address
to)
298
{
299
NS_LOG_FUNCTION
(
this
<< to);
300
WifiMacHeader
hdr;
301
hdr.
SetProbeResp
();
302
hdr.
SetAddr1
(to);
303
hdr.
SetAddr2
(
GetAddress
());
304
hdr.
SetAddr3
(
GetAddress
());
305
hdr.
SetDsNotFrom
();
306
hdr.
SetDsNotTo
();
307
Ptr<Packet>
packet = Create<Packet> ();
308
MgtProbeResponseHeader
probe;
309
probe.
SetSsid
(
GetSsid
());
310
probe.SetSupportedRates (
GetSupportedRates
());
311
probe.SetBeaconIntervalUs (
m_beaconInterval
.
GetMicroSeconds
());
312
packet->
AddHeader
(probe);
313
314
// The standard is not clear on the correct queue for management
315
// frames if we are a QoS AP. The approach taken here is to always
316
// use the DCF for these regardless of whether we have a QoS
317
// association or not.
318
m_dca
->
Queue
(packet, hdr);
319
}
320
321
void
322
ApWifiMac::SendAssocResp
(
Mac48Address
to,
bool
success)
323
{
324
NS_LOG_FUNCTION
(
this
<< to << success);
325
WifiMacHeader
hdr;
326
hdr.
SetAssocResp
();
327
hdr.
SetAddr1
(to);
328
hdr.
SetAddr2
(
GetAddress
());
329
hdr.
SetAddr3
(
GetAddress
());
330
hdr.
SetDsNotFrom
();
331
hdr.
SetDsNotTo
();
332
Ptr<Packet>
packet = Create<Packet> ();
333
MgtAssocResponseHeader
assoc;
334
StatusCode
code;
335
if
(success)
336
{
337
code.
SetSuccess
();
338
}
339
else
340
{
341
code.
SetFailure
();
342
}
343
assoc.SetSupportedRates (
GetSupportedRates
());
344
assoc.SetStatusCode (code);
345
packet->
AddHeader
(assoc);
346
347
// The standard is not clear on the correct queue for management
348
// frames if we are a QoS AP. The approach taken here is to always
349
// use the DCF for these regardless of whether we have a QoS
350
// association or not.
351
m_dca
->
Queue
(packet, hdr);
352
}
353
354
void
355
ApWifiMac::SendOneBeacon
(
void
)
356
{
357
NS_LOG_FUNCTION
(
this
);
358
WifiMacHeader
hdr;
359
hdr.
SetBeacon
();
360
hdr.
SetAddr1
(
Mac48Address::GetBroadcast
());
361
hdr.
SetAddr2
(
GetAddress
());
362
hdr.
SetAddr3
(
GetAddress
());
363
hdr.
SetDsNotFrom
();
364
hdr.
SetDsNotTo
();
365
Ptr<Packet>
packet = Create<Packet> ();
366
MgtBeaconHeader
beacon;
367
beacon.
SetSsid
(
GetSsid
());
368
beacon.SetSupportedRates (
GetSupportedRates
());
369
beacon.SetBeaconIntervalUs (
m_beaconInterval
.
GetMicroSeconds
());
370
371
packet->
AddHeader
(beacon);
372
373
// The beacon has it's own special queue, so we load it in there
374
m_beaconDca
->
Queue
(packet, hdr);
375
m_beaconEvent
=
Simulator::Schedule
(
m_beaconInterval
, &
ApWifiMac::SendOneBeacon
,
this
);
376
}
377
378
void
379
ApWifiMac::TxOk
(
const
WifiMacHeader
&hdr)
380
{
381
NS_LOG_FUNCTION
(
this
);
382
RegularWifiMac::TxOk
(hdr);
383
384
if
(hdr.
IsAssocResp
()
385
&&
m_stationManager
->
IsWaitAssocTxOk
(hdr.
GetAddr1
()))
386
{
387
NS_LOG_DEBUG
(
"associated with sta="
<< hdr.
GetAddr1
());
388
m_stationManager
->
RecordGotAssocTxOk
(hdr.
GetAddr1
());
389
}
390
}
391
392
void
393
ApWifiMac::TxFailed
(
const
WifiMacHeader
&hdr)
394
{
395
NS_LOG_FUNCTION
(
this
);
396
RegularWifiMac::TxFailed
(hdr);
397
398
if
(hdr.
IsAssocResp
()
399
&&
m_stationManager
->
IsWaitAssocTxOk
(hdr.
GetAddr1
()))
400
{
401
NS_LOG_DEBUG
(
"assoc failed with sta="
<< hdr.
GetAddr1
());
402
m_stationManager
->
RecordGotAssocTxFailed
(hdr.
GetAddr1
());
403
}
404
}
405
406
void
407
ApWifiMac::Receive
(
Ptr<Packet>
packet,
const
WifiMacHeader
*hdr)
408
{
409
NS_LOG_FUNCTION
(
this
<< packet << hdr);
410
411
Mac48Address
from = hdr->
GetAddr2
();
412
413
if
(hdr->
IsData
())
414
{
415
Mac48Address
bssid = hdr->
GetAddr1
();
416
if
(!hdr->
IsFromDs
()
417
&& hdr->
IsToDs
()
418
&& bssid ==
GetAddress
()
419
&&
m_stationManager
->
IsAssociated
(from))
420
{
421
Mac48Address
to = hdr->
GetAddr3
();
422
if
(to ==
GetAddress
())
423
{
424
NS_LOG_DEBUG
(
"frame for me from="
<< from);
425
if
(hdr->
IsQosData
())
426
{
427
if
(hdr->
IsQosAmsdu
())
428
{
429
NS_LOG_DEBUG
(
"Received A-MSDU from="
<< from <<
", size="
<< packet->
GetSize
());
430
DeaggregateAmsduAndForward
(packet, hdr);
431
packet = 0;
432
}
433
else
434
{
435
ForwardUp
(packet, from, bssid);
436
}
437
}
438
else
439
{
440
ForwardUp
(packet, from, bssid);
441
}
442
}
443
else
if
(to.
IsGroup
()
444
||
m_stationManager
->
IsAssociated
(to))
445
{
446
NS_LOG_DEBUG
(
"forwarding frame from="
<< from <<
", to="
<< to);
447
Ptr<Packet>
copy = packet->
Copy
();
448
449
// If the frame we are forwarding is of type QoS Data,
450
// then we need to preserve the UP in the QoS control
451
// header...
452
if
(hdr->
IsQosData
())
453
{
454
ForwardDown
(packet, from, to, hdr->
GetQosTid
());
455
}
456
else
457
{
458
ForwardDown
(packet, from, to);
459
}
460
ForwardUp
(copy, from, to);
461
}
462
else
463
{
464
ForwardUp
(packet, from, to);
465
}
466
}
467
else
if
(hdr->
IsFromDs
()
468
&& hdr->
IsToDs
())
469
{
470
// this is an AP-to-AP frame
471
// we ignore for now.
472
NotifyRxDrop
(packet);
473
}
474
else
475
{
476
// we can ignore these frames since
477
// they are not targeted at the AP
478
NotifyRxDrop
(packet);
479
}
480
return
;
481
}
482
else
if
(hdr->
IsMgt
())
483
{
484
if
(hdr->
IsProbeReq
())
485
{
486
NS_ASSERT
(hdr->
GetAddr1
().
IsBroadcast
());
487
SendProbeResp
(from);
488
return
;
489
}
490
else
if
(hdr->
GetAddr1
() ==
GetAddress
())
491
{
492
if
(hdr->
IsAssocReq
())
493
{
494
// first, verify that the the station's supported
495
// rate set is compatible with our Basic Rate set
496
MgtAssocRequestHeader
assocReq;
497
packet->
RemoveHeader
(assocReq);
498
SupportedRates
rates = assocReq.
GetSupportedRates
();
499
bool
problem =
false
;
500
for
(uint32_t i = 0; i <
m_stationManager
->
GetNBasicModes
(); i++)
501
{
502
WifiMode
mode =
m_stationManager
->
GetBasicMode
(i);
503
if
(!rates.
IsSupportedRate
(mode.
GetDataRate
()))
504
{
505
problem =
true
;
506
break
;
507
}
508
}
509
if
(problem)
510
{
511
// one of the Basic Rate set mode is not
512
// supported by the station. So, we return an assoc
513
// response with an error status.
514
SendAssocResp
(hdr->
GetAddr2
(),
false
);
515
}
516
else
517
{
518
// station supports all rates in Basic Rate Set.
519
// record all its supported modes in its associated WifiRemoteStation
520
for
(uint32_t j = 0; j <
m_phy
->
GetNModes
(); j++)
521
{
522
WifiMode
mode =
m_phy
->
GetMode
(j);
523
if
(rates.
IsSupportedRate
(mode.
GetDataRate
()))
524
{
525
m_stationManager
->
AddSupportedMode
(from, mode);
526
}
527
}
528
m_stationManager
->
RecordWaitAssocTxOk
(from);
529
// send assoc response with success status.
530
SendAssocResp
(hdr->
GetAddr2
(),
true
);
531
}
532
return
;
533
}
534
else
if
(hdr->
IsDisassociation
())
535
{
536
m_stationManager
->
RecordDisassociated
(from);
537
return
;
538
}
539
}
540
}
541
542
// Invoke the receive handler of our parent class to deal with any
543
// other frames. Specifically, this will handle Block Ack-related
544
// Management Action frames.
545
RegularWifiMac::Receive
(packet, hdr);
546
}
547
548
void
549
ApWifiMac::DeaggregateAmsduAndForward
(
Ptr<Packet>
aggregatedPacket,
550
const
WifiMacHeader
*hdr)
551
{
552
NS_LOG_FUNCTION
(
this
<< aggregatedPacket << hdr);
553
MsduAggregator::DeaggregatedMsdus
packets =
554
MsduAggregator::Deaggregate
(aggregatedPacket);
555
556
for
(
MsduAggregator::DeaggregatedMsdusCI
i = packets.begin ();
557
i != packets.end (); ++i)
558
{
559
if
((*i).second.GetDestinationAddr () ==
GetAddress
())
560
{
561
ForwardUp
((*i).first, (*i).second.GetSourceAddr (),
562
(*i).second.GetDestinationAddr ());
563
}
564
else
565
{
566
Mac48Address
from = (*i).second.GetSourceAddr ();
567
Mac48Address
to = (*i).second.GetDestinationAddr ();
568
NS_LOG_DEBUG
(
"forwarding QoS frame from="
<< from <<
", to="
<< to);
569
ForwardDown
((*i).first, from, to, hdr->
GetQosTid
());
570
}
571
}
572
}
573
574
void
575
ApWifiMac::DoInitialize
(
void
)
576
{
577
NS_LOG_FUNCTION
(
this
);
578
m_beaconDca
->
Initialize
();
579
m_beaconEvent
.
Cancel
();
580
if
(
m_enableBeaconGeneration
)
581
{
582
m_beaconEvent
=
Simulator::ScheduleNow
(&
ApWifiMac::SendOneBeacon
,
this
);
583
}
584
RegularWifiMac::DoInitialize
();
585
}
586
587
}
// namespace ns3
src
wifi
model
ap-wifi-mac.cc
Generated on Tue May 14 2013 11:08:35 for ns-3 by
1.8.1.2