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