|
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2008 INRIA |
|
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 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
|
19 */ |
|
20 #include "regular-wifi-mac.h" |
|
21 |
|
22 #include "ns3/log.h" |
|
23 #include "ns3/boolean.h" |
|
24 #include "ns3/pointer.h" |
|
25 #include "ns3/uinteger.h" |
|
26 #include "ns3/trace-source-accessor.h" |
|
27 |
|
28 #include "mac-rx-middle.h" |
|
29 #include "mac-tx-middle.h" |
|
30 #include "mac-low.h" |
|
31 #include "dcf.h" |
|
32 #include "dcf-manager.h" |
|
33 #include "wifi-phy.h" |
|
34 |
|
35 #include "msdu-aggregator.h" |
|
36 |
|
37 NS_LOG_COMPONENT_DEFINE ("RegularWifiMac"); |
|
38 |
|
39 namespace ns3 { |
|
40 |
|
41 NS_OBJECT_ENSURE_REGISTERED (RegularWifiMac); |
|
42 |
|
43 RegularWifiMac::RegularWifiMac () |
|
44 { |
|
45 NS_LOG_FUNCTION (this); |
|
46 m_rxMiddle = new MacRxMiddle (); |
|
47 m_rxMiddle->SetForwardCallback (MakeCallback (&RegularWifiMac::Receive, this)); |
|
48 |
|
49 m_txMiddle = new MacTxMiddle (); |
|
50 |
|
51 m_low = CreateObject<MacLow> (); |
|
52 m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle)); |
|
53 |
|
54 m_dcfManager = new DcfManager (); |
|
55 m_dcfManager->SetupLowListener (m_low); |
|
56 |
|
57 m_dca = CreateObject<DcaTxop> (); |
|
58 m_dca->SetLow (m_low); |
|
59 m_dca->SetManager (m_dcfManager); |
|
60 m_dca->SetTxOkCallback (MakeCallback (&RegularWifiMac::TxOk, this)); |
|
61 m_dca->SetTxFailedCallback (MakeCallback (&RegularWifiMac::TxFailed, this)); |
|
62 |
|
63 // Construct the EDCAFs. The ordering is important - highest |
|
64 // priority (see Table 9-1 in IEEE 802.11-2007) must be created |
|
65 // first. |
|
66 SetupEdcaQueue (AC_VO); |
|
67 SetupEdcaQueue (AC_VI); |
|
68 SetupEdcaQueue (AC_BE); |
|
69 SetupEdcaQueue (AC_BK); |
|
70 } |
|
71 |
|
72 RegularWifiMac::~RegularWifiMac () |
|
73 { |
|
74 NS_LOG_FUNCTION (this); |
|
75 } |
|
76 |
|
77 void |
|
78 RegularWifiMac::DoStart () |
|
79 { |
|
80 NS_LOG_FUNCTION (this); |
|
81 |
|
82 m_dca->Start (); |
|
83 |
|
84 for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i) |
|
85 { |
|
86 i->second->Start (); |
|
87 } |
|
88 } |
|
89 |
|
90 void |
|
91 RegularWifiMac::DoDispose () |
|
92 { |
|
93 NS_LOG_FUNCTION (this); |
|
94 delete m_rxMiddle; |
|
95 m_rxMiddle = NULL; |
|
96 |
|
97 delete m_txMiddle; |
|
98 m_txMiddle = NULL; |
|
99 |
|
100 delete m_dcfManager; |
|
101 m_dcfManager = NULL; |
|
102 |
|
103 m_low->Dispose (); |
|
104 m_low = NULL; |
|
105 |
|
106 m_phy = NULL; |
|
107 m_stationManager = NULL; |
|
108 |
|
109 m_dca->Dispose (); |
|
110 m_dca = NULL; |
|
111 |
|
112 for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i) |
|
113 { |
|
114 i->second = NULL; |
|
115 } |
|
116 } |
|
117 |
|
118 void |
|
119 RegularWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager) |
|
120 { |
|
121 NS_LOG_FUNCTION (this << stationManager); |
|
122 m_stationManager = stationManager; |
|
123 m_low->SetWifiRemoteStationManager (stationManager); |
|
124 |
|
125 m_dca->SetWifiRemoteStationManager (stationManager); |
|
126 |
|
127 for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i) |
|
128 { |
|
129 i->second->SetWifiRemoteStationManager (stationManager); |
|
130 } |
|
131 } |
|
132 |
|
133 Ptr<WifiRemoteStationManager> |
|
134 RegularWifiMac::GetWifiRemoteStationManager () const |
|
135 { |
|
136 return m_stationManager; |
|
137 } |
|
138 |
|
139 void |
|
140 RegularWifiMac::SetupEdcaQueue (enum AcIndex ac) |
|
141 { |
|
142 NS_LOG_FUNCTION (this << ac); |
|
143 |
|
144 // Our caller shouldn't be attempting to setup a queue that is |
|
145 // already configured. |
|
146 NS_ASSERT (m_edca.find (ac) == m_edca.end ()); |
|
147 |
|
148 Ptr<EdcaTxopN> edca = CreateObject<EdcaTxopN> (); |
|
149 edca->SetLow (m_low); |
|
150 edca->SetManager (m_dcfManager); |
|
151 edca->SetTxMiddle (m_txMiddle); |
|
152 edca->SetTxOkCallback (MakeCallback (&RegularWifiMac::TxOk, this)); |
|
153 edca->SetTxFailedCallback (MakeCallback (&RegularWifiMac::TxFailed, this)); |
|
154 edca->SetAccessCategory (ac); |
|
155 edca->CompleteConfig (); |
|
156 m_edca.insert (std::make_pair(ac, edca)); |
|
157 } |
|
158 |
|
159 void |
|
160 RegularWifiMac::SetTypeOfStation (TypeOfStation type) |
|
161 { |
|
162 NS_LOG_FUNCTION (this << type); |
|
163 for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i) |
|
164 { |
|
165 i->second->SetTypeOfStation (type); |
|
166 } |
|
167 } |
|
168 |
|
169 Ptr<DcaTxop> |
|
170 RegularWifiMac::GetDcaTxop () const |
|
171 { |
|
172 return m_dca; |
|
173 } |
|
174 |
|
175 Ptr<EdcaTxopN> |
|
176 RegularWifiMac::GetVOQueue () const |
|
177 { |
|
178 return m_edca.find (AC_VO)->second; |
|
179 } |
|
180 |
|
181 Ptr<EdcaTxopN> |
|
182 RegularWifiMac::GetVIQueue () const |
|
183 { |
|
184 return m_edca.find (AC_VI)->second; |
|
185 } |
|
186 |
|
187 Ptr<EdcaTxopN> |
|
188 RegularWifiMac::GetBEQueue () const |
|
189 { |
|
190 return m_edca.find (AC_BE)->second; |
|
191 } |
|
192 |
|
193 Ptr<EdcaTxopN> |
|
194 RegularWifiMac::GetBKQueue () const |
|
195 { |
|
196 return m_edca.find (AC_BK)->second; |
|
197 } |
|
198 |
|
199 void |
|
200 RegularWifiMac::SetWifiPhy (Ptr<WifiPhy> phy) |
|
201 { |
|
202 NS_LOG_FUNCTION (this << phy); |
|
203 m_phy = phy; |
|
204 m_dcfManager->SetupPhyListener (phy); |
|
205 m_low->SetPhy (phy); |
|
206 } |
|
207 |
|
208 Ptr<WifiPhy> |
|
209 RegularWifiMac::GetWifiPhy () const |
|
210 { |
|
211 return m_phy; |
|
212 } |
|
213 |
|
214 void |
|
215 RegularWifiMac::SetForwardUpCallback (ForwardUpCallback upCallback) |
|
216 { |
|
217 NS_LOG_FUNCTION (this); |
|
218 m_forwardUp = upCallback; |
|
219 } |
|
220 |
|
221 void |
|
222 RegularWifiMac::SetLinkUpCallback (Callback<void> linkUp) |
|
223 { |
|
224 NS_LOG_FUNCTION (this); |
|
225 m_linkUp = linkUp; |
|
226 } |
|
227 |
|
228 void |
|
229 RegularWifiMac::SetLinkDownCallback (Callback<void> linkDown) |
|
230 { |
|
231 NS_LOG_FUNCTION (this); |
|
232 m_linkDown = linkDown; |
|
233 } |
|
234 |
|
235 void |
|
236 RegularWifiMac::SetQosSupported (bool enable) |
|
237 { |
|
238 NS_LOG_FUNCTION (this); |
|
239 m_qosSupported = enable; |
|
240 } |
|
241 |
|
242 bool |
|
243 RegularWifiMac::GetQosSupported () const |
|
244 { |
|
245 return m_qosSupported; |
|
246 } |
|
247 |
|
248 void |
|
249 RegularWifiMac::SetSlot (Time slotTime) |
|
250 { |
|
251 NS_LOG_FUNCTION (this << slotTime); |
|
252 m_dcfManager->SetSlot (slotTime); |
|
253 m_low->SetSlotTime (slotTime); |
|
254 } |
|
255 |
|
256 Time |
|
257 RegularWifiMac::GetSlot (void) const |
|
258 { |
|
259 return m_low->GetSlotTime (); |
|
260 } |
|
261 |
|
262 void |
|
263 RegularWifiMac::SetSifs (Time sifs) |
|
264 { |
|
265 NS_LOG_FUNCTION (this << sifs); |
|
266 m_dcfManager->SetSifs (sifs); |
|
267 m_low->SetSifs (sifs); |
|
268 } |
|
269 |
|
270 Time |
|
271 RegularWifiMac::GetSifs (void) const |
|
272 { |
|
273 return m_low->GetSifs (); |
|
274 } |
|
275 |
|
276 void |
|
277 RegularWifiMac::SetEifsNoDifs (Time eifsNoDifs) |
|
278 { |
|
279 NS_LOG_FUNCTION (this << eifsNoDifs); |
|
280 m_dcfManager->SetEifsNoDifs (eifsNoDifs); |
|
281 } |
|
282 |
|
283 Time |
|
284 RegularWifiMac::GetEifsNoDifs (void) const |
|
285 { |
|
286 return m_dcfManager->GetEifsNoDifs (); |
|
287 } |
|
288 |
|
289 void |
|
290 RegularWifiMac::SetPifs (Time pifs) |
|
291 { |
|
292 NS_LOG_FUNCTION (this << pifs); |
|
293 m_low->SetPifs (pifs); |
|
294 } |
|
295 |
|
296 Time |
|
297 RegularWifiMac::GetPifs (void) const |
|
298 { |
|
299 return m_low->GetPifs (); |
|
300 } |
|
301 |
|
302 void |
|
303 RegularWifiMac::SetAckTimeout (Time ackTimeout) |
|
304 { |
|
305 NS_LOG_FUNCTION (this << ackTimeout); |
|
306 m_low->SetAckTimeout (ackTimeout); |
|
307 } |
|
308 |
|
309 Time |
|
310 RegularWifiMac::GetAckTimeout (void) const |
|
311 { |
|
312 return m_low->GetAckTimeout (); |
|
313 } |
|
314 |
|
315 void |
|
316 RegularWifiMac::SetCtsTimeout (Time ctsTimeout) |
|
317 { |
|
318 NS_LOG_FUNCTION (this << ctsTimeout); |
|
319 m_low->SetCtsTimeout (ctsTimeout); |
|
320 } |
|
321 |
|
322 Time |
|
323 RegularWifiMac::GetCtsTimeout (void) const |
|
324 { |
|
325 return m_low->GetCtsTimeout (); |
|
326 } |
|
327 |
|
328 void |
|
329 RegularWifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout) |
|
330 { |
|
331 NS_LOG_FUNCTION (this << blockAckTimeout); |
|
332 m_low->SetBasicBlockAckTimeout (blockAckTimeout); |
|
333 } |
|
334 |
|
335 Time |
|
336 RegularWifiMac::GetBasicBlockAckTimeout (void) const |
|
337 { |
|
338 return m_low->GetBasicBlockAckTimeout (); |
|
339 } |
|
340 |
|
341 void |
|
342 RegularWifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout) |
|
343 { |
|
344 NS_LOG_FUNCTION (this << blockAckTimeout); |
|
345 m_low->SetCompressedBlockAckTimeout (blockAckTimeout); |
|
346 } |
|
347 |
|
348 Time |
|
349 RegularWifiMac::GetCompressedBlockAckTimeout (void) const |
|
350 { |
|
351 return m_low->GetCompressedBlockAckTimeout (); |
|
352 } |
|
353 |
|
354 void |
|
355 RegularWifiMac::SetAddress (Mac48Address address) |
|
356 { |
|
357 NS_LOG_FUNCTION (this << address); |
|
358 m_low->SetAddress (address); |
|
359 } |
|
360 |
|
361 Mac48Address |
|
362 RegularWifiMac::GetAddress (void) const |
|
363 { |
|
364 return m_low->GetAddress (); |
|
365 } |
|
366 |
|
367 void |
|
368 RegularWifiMac::SetSsid (Ssid ssid) |
|
369 { |
|
370 NS_LOG_FUNCTION (this << ssid); |
|
371 m_ssid = ssid; |
|
372 } |
|
373 |
|
374 Ssid |
|
375 RegularWifiMac::GetSsid (void) const |
|
376 { |
|
377 return m_ssid; |
|
378 } |
|
379 |
|
380 void |
|
381 RegularWifiMac::SetBssid (Mac48Address bssid) |
|
382 { |
|
383 NS_LOG_FUNCTION (this << bssid); |
|
384 m_low->SetBssid (bssid); |
|
385 } |
|
386 |
|
387 Mac48Address |
|
388 RegularWifiMac::GetBssid (void) const |
|
389 { |
|
390 return m_low->GetBssid (); |
|
391 } |
|
392 |
|
393 void |
|
394 RegularWifiMac::Enqueue (Ptr<const Packet> packet, |
|
395 Mac48Address to, Mac48Address from) |
|
396 { |
|
397 // We expect RegularWifiMac subclasses which do support forwarding (e.g., |
|
398 // AP) to override this method. Therefore, we throw a fatal error if |
|
399 // someone tries to invoke this method on a class which has not done |
|
400 // this. |
|
401 NS_FATAL_ERROR ("This MAC entity (" << this << ", " << GetAddress () |
|
402 << ") does not support Enqueue() with from address"); |
|
403 } |
|
404 |
|
405 bool |
|
406 RegularWifiMac::SupportsSendFrom (void) const |
|
407 { |
|
408 return false; |
|
409 } |
|
410 |
|
411 void |
|
412 RegularWifiMac::ForwardUp (Ptr<Packet> packet, Mac48Address from, Mac48Address to) |
|
413 { |
|
414 NS_LOG_FUNCTION (this << packet << from); |
|
415 m_forwardUp (packet, from, to); |
|
416 } |
|
417 |
|
418 void |
|
419 RegularWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr) |
|
420 { |
|
421 NS_LOG_FUNCTION (this << packet << hdr); |
|
422 |
|
423 Mac48Address to = hdr->GetAddr1 (); |
|
424 Mac48Address from = hdr->GetAddr2 (); |
|
425 |
|
426 if (hdr->IsMgt () && hdr->IsAction () && to == GetAddress ()) |
|
427 { |
|
428 // There is currently only any reason for Management Action |
|
429 // frames to be flying about if we are a QoS STA. |
|
430 NS_ASSERT (m_qosSupported); |
|
431 |
|
432 WifiActionHeader actionHdr; |
|
433 packet->RemoveHeader (actionHdr); |
|
434 |
|
435 switch (actionHdr.GetCategory ()) |
|
436 { |
|
437 case WifiActionHeader::BLOCK_ACK: |
|
438 |
|
439 switch (actionHdr.GetAction().blockAck) |
|
440 { |
|
441 case WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST: |
|
442 { |
|
443 MgtAddBaRequestHeader reqHdr; |
|
444 packet->RemoveHeader (reqHdr); |
|
445 |
|
446 // We've received an ADDBA Request. Our policy here is |
|
447 // to automatically accept it, so we get the ADDBA |
|
448 // Response on it's way immediately. |
|
449 SendAddBaResponse (&reqHdr, from); |
|
450 // This frame is now completely dealt with, so we're done. |
|
451 return; |
|
452 } |
|
453 |
|
454 case WifiActionHeader::BLOCK_ACK_ADDBA_RESPONSE: |
|
455 { |
|
456 MgtAddBaResponseHeader respHdr; |
|
457 packet->RemoveHeader (respHdr); |
|
458 |
|
459 // We've received an ADDBA Response. We assume that it |
|
460 // indicates success after an ADDBA Request we have |
|
461 // sent (we could, in principle, check this, but it |
|
462 // seems a waste given the level of the current model) |
|
463 // and act by locally establishing the agreement on |
|
464 // the appropriate queue. |
|
465 AcIndex ac = QosUtilsMapTidToAc (respHdr.GetTid ()); |
|
466 m_edca[ac]->GotAddBaResponse (&respHdr, from); |
|
467 // This frame is now completely dealt with, so we're done. |
|
468 return; |
|
469 } |
|
470 |
|
471 case WifiActionHeader::BLOCK_ACK_DELBA: |
|
472 { |
|
473 MgtDelBaHeader delBaHdr; |
|
474 packet->RemoveHeader (delBaHdr); |
|
475 |
|
476 if (delBaHdr.IsByOriginator ()) |
|
477 { |
|
478 // This DELBA frame was sent by the originator, so |
|
479 // this means that an ingoing established |
|
480 // agreement exists in MacLow and we need to |
|
481 // destroy it. |
|
482 m_low->DestroyBlockAckAgreement (from, delBaHdr.GetTid ()); |
|
483 } |
|
484 else |
|
485 { |
|
486 // We must have been the originator. We need to |
|
487 // tell the correct queue that the agreement has |
|
488 // been torn down |
|
489 AcIndex ac = QosUtilsMapTidToAc (delBaHdr.GetTid ()); |
|
490 m_edca[ac]->GotDelBaFrame (&delBaHdr, from); |
|
491 } |
|
492 // This frame is now completely dealt with, so we're done. |
|
493 return; |
|
494 } |
|
495 |
|
496 default: |
|
497 NS_FATAL_ERROR ("Unsupported Action field in Block Ack Action frame"); |
|
498 } |
|
499 |
|
500 default: |
|
501 NS_FATAL_ERROR ("Unsupported Action frame received"); |
|
502 } |
|
503 } |
|
504 NS_FATAL_ERROR ("Don't know how to handle frame (type=" << hdr->GetType ()); |
|
505 } |
|
506 |
|
507 void |
|
508 RegularWifiMac::DeaggregateAmsduAndForward (Ptr<Packet> aggregatedPacket, |
|
509 const WifiMacHeader *hdr) |
|
510 { |
|
511 MsduAggregator::DeaggregatedMsdus packets = |
|
512 MsduAggregator::Deaggregate (aggregatedPacket); |
|
513 |
|
514 for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin (); |
|
515 i != packets.end (); ++i) |
|
516 { |
|
517 ForwardUp ((*i).first, (*i).second.GetSourceAddr (), |
|
518 (*i).second.GetDestinationAddr ()); |
|
519 } |
|
520 } |
|
521 |
|
522 void |
|
523 RegularWifiMac::SendAddBaResponse (const MgtAddBaRequestHeader *reqHdr, |
|
524 Mac48Address originator) |
|
525 { |
|
526 NS_LOG_FUNCTION (this); |
|
527 WifiMacHeader hdr; |
|
528 hdr.SetAction (); |
|
529 hdr.SetAddr1 (originator); |
|
530 hdr.SetAddr2 (GetAddress ()); |
|
531 hdr.SetAddr3 (GetAddress ()); |
|
532 hdr.SetDsNotFrom (); |
|
533 hdr.SetDsNotTo (); |
|
534 |
|
535 MgtAddBaResponseHeader respHdr; |
|
536 StatusCode code; |
|
537 code.SetSuccess (); |
|
538 respHdr.SetStatusCode (code); |
|
539 //Here a control about queues type? |
|
540 respHdr.SetAmsduSupport (reqHdr->IsAmsduSupported ()); |
|
541 |
|
542 if (reqHdr->IsImmediateBlockAck ()) |
|
543 { |
|
544 respHdr.SetImmediateBlockAck (); |
|
545 } |
|
546 else |
|
547 { |
|
548 respHdr.SetDelayedBlockAck (); |
|
549 } |
|
550 respHdr.SetTid (reqHdr->GetTid ()); |
|
551 // For now there's not no control about limit of reception. We |
|
552 // assume that receiver has no limit on reception. However we assume |
|
553 // that a receiver sets a bufferSize in order to satisfy next |
|
554 // equation: (bufferSize + 1) % 16 = 0 So if a recipient is able to |
|
555 // buffer a packet, it should be also able to buffer all possible |
|
556 // packet's fragments. See section 7.3.1.14 in IEEE802.11e for more |
|
557 // details. |
|
558 respHdr.SetBufferSize (1023); |
|
559 respHdr.SetTimeout (reqHdr->GetTimeout ()); |
|
560 |
|
561 WifiActionHeader actionHdr; |
|
562 WifiActionHeader::ActionValue action; |
|
563 action.blockAck = WifiActionHeader::BLOCK_ACK_ADDBA_RESPONSE; |
|
564 actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action); |
|
565 |
|
566 Ptr<Packet> packet = Create<Packet> (); |
|
567 packet->AddHeader (respHdr); |
|
568 packet->AddHeader (actionHdr); |
|
569 |
|
570 // We need to notify our MacLow object as it will have to buffer all |
|
571 // correctly received packets for this Block Ack session |
|
572 m_low->CreateBlockAckAgreement (&respHdr, originator, |
|
573 reqHdr->GetStartingSequence ()); |
|
574 |
|
575 // It is unclear which queue this frame should go into. For now we |
|
576 // bung it into the queue corresponding to the TID for which we are |
|
577 // establishing an agreement, and push it to the head. |
|
578 m_edca[QosUtilsMapTidToAc (reqHdr->GetTid ())]->PushFront (packet, hdr); |
|
579 } |
|
580 |
|
581 TypeId |
|
582 RegularWifiMac::GetTypeId (void) |
|
583 { |
|
584 static TypeId tid = TypeId ("ns3::RegularWifiMac") |
|
585 .SetParent<WifiMac> () |
|
586 .AddAttribute ("QosSupported", |
|
587 "This Boolean attribute is set to enable 802.11e/WMM-style QoS support at this STA", |
|
588 BooleanValue (false), |
|
589 MakeBooleanAccessor (&RegularWifiMac::SetQosSupported, |
|
590 &RegularWifiMac::GetQosSupported), |
|
591 MakeBooleanChecker ()) |
|
592 .AddAttribute ("DcaTxop", "The DcaTxop object", |
|
593 PointerValue (), |
|
594 MakePointerAccessor (&RegularWifiMac::GetDcaTxop), |
|
595 MakePointerChecker<DcaTxop> ()) |
|
596 .AddAttribute ("VO_EdcaTxopN", |
|
597 "Queue that manages packets belonging to AC_VO access class", |
|
598 PointerValue (), |
|
599 MakePointerAccessor(&RegularWifiMac::GetVOQueue), |
|
600 MakePointerChecker<EdcaTxopN> ()) |
|
601 .AddAttribute ("VI_EdcaTxopN", |
|
602 "Queue that manages packets belonging to AC_VI access class", |
|
603 PointerValue (), |
|
604 MakePointerAccessor(&RegularWifiMac::GetVIQueue), |
|
605 MakePointerChecker<EdcaTxopN> ()) |
|
606 .AddAttribute ("BE_EdcaTxopN", |
|
607 "Queue that manages packets belonging to AC_BE access class", |
|
608 PointerValue (), |
|
609 MakePointerAccessor(&RegularWifiMac::GetBEQueue), |
|
610 MakePointerChecker<EdcaTxopN> ()) |
|
611 .AddAttribute ("BK_EdcaTxopN", |
|
612 "Queue that manages packets belonging to AC_BK access class", |
|
613 PointerValue (), |
|
614 MakePointerAccessor(&RegularWifiMac::GetBKQueue), |
|
615 MakePointerChecker<EdcaTxopN> ()) |
|
616 .AddTraceSource ( "TxOkHeader", |
|
617 "The header of successfully transmitted packet", |
|
618 MakeTraceSourceAccessor (&RegularWifiMac::m_txOkCallback)) |
|
619 .AddTraceSource ("TxErrHeader", |
|
620 "The header of unsuccessfully transmitted packet", |
|
621 MakeTraceSourceAccessor (&RegularWifiMac::m_txErrCallback)) |
|
622 ; |
|
623 |
|
624 return tid; |
|
625 } |
|
626 |
|
627 void |
|
628 RegularWifiMac::FinishConfigureStandard (enum WifiPhyStandard standard) |
|
629 { |
|
630 uint32_t cwmin; |
|
631 uint32_t cwmax; |
|
632 |
|
633 switch (standard) |
|
634 { |
|
635 case WIFI_PHY_STANDARD_80211p_CCH: |
|
636 case WIFI_PHY_STANDARD_80211p_SCH: |
|
637 cwmin = 15; |
|
638 cwmax = 511; |
|
639 break; |
|
640 |
|
641 case WIFI_PHY_STANDARD_holland: |
|
642 case WIFI_PHY_STANDARD_80211a: |
|
643 case WIFI_PHY_STANDARD_80211g: |
|
644 case WIFI_PHY_STANDARD_80211_10Mhz: |
|
645 case WIFI_PHY_STANDARD_80211_5Mhz: |
|
646 cwmin = 15; |
|
647 cwmax = 1023; |
|
648 break; |
|
649 |
|
650 case WIFI_PHY_STANDARD_80211b: |
|
651 cwmin = 31; |
|
652 cwmax = 1023; |
|
653 break; |
|
654 |
|
655 default: |
|
656 NS_FATAL_ERROR ("Unsupported WifiPhyStandard in RegularWifiMac::FinishConfigureStandard ()"); |
|
657 } |
|
658 |
|
659 // The special value of AC_BE_NQOS which exists in the Access |
|
660 // Category enumeration allows us to configure plain old DCF. |
|
661 ConfigureDcf (m_dca, cwmin, cwmax, AC_BE_NQOS); |
|
662 |
|
663 // Now we configure the EDCA functions |
|
664 for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i) |
|
665 { |
|
666 // Special configuration for 802.11p CCH |
|
667 if (standard == WIFI_PHY_STANDARD_80211p_CCH) |
|
668 { |
|
669 ConfigureCCHDcf (i->second, cwmin, cwmax, i->first); |
|
670 } |
|
671 else |
|
672 { |
|
673 ConfigureDcf (i->second, cwmin, cwmax, i->first); |
|
674 } |
|
675 } |
|
676 } |
|
677 |
|
678 void |
|
679 RegularWifiMac::TxOk (const WifiMacHeader &hdr) |
|
680 { |
|
681 NS_LOG_FUNCTION (this << hdr); |
|
682 m_txOkCallback (hdr); |
|
683 } |
|
684 |
|
685 void |
|
686 RegularWifiMac::TxFailed (const WifiMacHeader &hdr) |
|
687 { |
|
688 NS_LOG_FUNCTION (this << hdr); |
|
689 m_txErrCallback (hdr); |
|
690 } |
|
691 |
|
692 } // namespace ns3 |