A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
regular-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) 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 
44 {
45  NS_LOG_FUNCTION (this);
46  m_rxMiddle = new MacRxMiddle ();
48 
49  m_txMiddle = new MacTxMiddle ();
50 
51  m_low = CreateObject<MacLow> ();
53 
54  m_dcfManager = new DcfManager ();
56 
57  m_dca = CreateObject<DcaTxop> ();
58  m_dca->SetLow (m_low);
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.
70 }
71 
73 {
74  NS_LOG_FUNCTION (this);
75 }
76 
77 void
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
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
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 
135 {
136  return m_stationManager;
137 }
138 
139 void
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
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 
171 {
172  return m_dca;
173 }
174 
177 {
178  return m_edca.find (AC_VO)->second;
179 }
180 
183 {
184  return m_edca.find (AC_VI)->second;
185 }
186 
189 {
190  return m_edca.find (AC_BE)->second;
191 }
192 
195 {
196  return m_edca.find (AC_BK)->second;
197 }
198 
199 void
201 {
202  NS_LOG_FUNCTION (this << phy);
203  m_phy = phy;
205  m_low->SetPhy (phy);
206 }
207 
210 {
211  return m_phy;
212 }
213 
214 void
216 {
217  NS_LOG_FUNCTION (this);
218  m_forwardUp = upCallback;
219 }
220 
221 void
223 {
224  NS_LOG_FUNCTION (this);
225  m_linkUp = linkUp;
226 }
227 
228 void
230 {
231  NS_LOG_FUNCTION (this);
232  m_linkDown = linkDown;
233 }
234 
235 void
237 {
238  NS_LOG_FUNCTION (this);
239  m_qosSupported = enable;
240 }
241 
242 bool
244 {
245  return m_qosSupported;
246 }
247 
248 void
250 {
251  NS_LOG_FUNCTION (this << slotTime);
252  m_dcfManager->SetSlot (slotTime);
253  m_low->SetSlotTime (slotTime);
254 }
255 
256 Time
258 {
259  return m_low->GetSlotTime ();
260 }
261 
262 void
264 {
265  NS_LOG_FUNCTION (this << sifs);
266  m_dcfManager->SetSifs (sifs);
267  m_low->SetSifs (sifs);
268 }
269 
270 Time
272 {
273  return m_low->GetSifs ();
274 }
275 
276 void
278 {
279  NS_LOG_FUNCTION (this << eifsNoDifs);
280  m_dcfManager->SetEifsNoDifs (eifsNoDifs);
281 }
282 
283 Time
285 {
286  return m_dcfManager->GetEifsNoDifs ();
287 }
288 
289 void
291 {
292  NS_LOG_FUNCTION (this << pifs);
293  m_low->SetPifs (pifs);
294 }
295 
296 Time
298 {
299  return m_low->GetPifs ();
300 }
301 
302 void
304 {
305  NS_LOG_FUNCTION (this << ackTimeout);
306  m_low->SetAckTimeout (ackTimeout);
307 }
308 
309 Time
311 {
312  return m_low->GetAckTimeout ();
313 }
314 
315 void
317 {
318  NS_LOG_FUNCTION (this << ctsTimeout);
319  m_low->SetCtsTimeout (ctsTimeout);
320 }
321 
322 Time
324 {
325  return m_low->GetCtsTimeout ();
326 }
327 
328 void
330 {
331  NS_LOG_FUNCTION (this << blockAckTimeout);
332  m_low->SetBasicBlockAckTimeout (blockAckTimeout);
333 }
334 
335 Time
337 {
338  return m_low->GetBasicBlockAckTimeout ();
339 }
340 
341 void
343 {
344  NS_LOG_FUNCTION (this << blockAckTimeout);
345  m_low->SetCompressedBlockAckTimeout (blockAckTimeout);
346 }
347 
348 Time
350 {
352 }
353 
354 void
356 {
357  NS_LOG_FUNCTION (this << address);
358  m_low->SetAddress (address);
359 }
360 
363 {
364  return m_low->GetAddress ();
365 }
366 
367 void
369 {
370  NS_LOG_FUNCTION (this << ssid);
371  m_ssid = ssid;
372 }
373 
374 Ssid
376 {
377  return m_ssid;
378 }
379 
380 void
382 {
383  NS_LOG_FUNCTION (this << bssid);
384  m_low->SetBssid (bssid);
385 }
386 
389 {
390  return m_low->GetBssid ();
391 }
392 
393 void
395 {
396  m_low->SetPromisc ();
397 }
398 
399 void
401  Mac48Address to, Mac48Address from)
402 {
403  // We expect RegularWifiMac subclasses which do support forwarding (e.g.,
404  // AP) to override this method. Therefore, we throw a fatal error if
405  // someone tries to invoke this method on a class which has not done
406  // this.
407  NS_FATAL_ERROR ("This MAC entity (" << this << ", " << GetAddress ()
408  << ") does not support Enqueue() with from address");
409 }
410 
411 bool
413 {
414  return false;
415 }
416 
417 void
419 {
420  NS_LOG_FUNCTION (this << packet << from);
421  m_forwardUp (packet, from, to);
422 }
423 
424 void
426 {
427  NS_LOG_FUNCTION (this << packet << hdr);
428 
429  Mac48Address to = hdr->GetAddr1 ();
430  Mac48Address from = hdr->GetAddr2 ();
431 
432  // We don't know how to deal with any frame that is not addressed to
433  // us (and odds are there is nothing sensible we could do anyway),
434  // so we ignore such frames.
435  //
436  // The derived class may also do some such filtering, but it doesn't
437  // hurt to have it here too as a backstop.
438  if (to != GetAddress ())
439  {
440  return;
441  }
442 
443  if (hdr->IsMgt () && hdr->IsAction ())
444  {
445  // There is currently only any reason for Management Action
446  // frames to be flying about if we are a QoS STA.
448 
449  WifiActionHeader actionHdr;
450  packet->RemoveHeader (actionHdr);
451 
452  switch (actionHdr.GetCategory ())
453  {
455 
456  switch (actionHdr.GetAction ().blockAck)
457  {
459  {
460  MgtAddBaRequestHeader reqHdr;
461  packet->RemoveHeader (reqHdr);
462 
463  // We've received an ADDBA Request. Our policy here is
464  // to automatically accept it, so we get the ADDBA
465  // Response on it's way immediately.
466  SendAddBaResponse (&reqHdr, from);
467  // This frame is now completely dealt with, so we're done.
468  return;
469  }
470 
472  {
473  MgtAddBaResponseHeader respHdr;
474  packet->RemoveHeader (respHdr);
475 
476  // We've received an ADDBA Response. We assume that it
477  // indicates success after an ADDBA Request we have
478  // sent (we could, in principle, check this, but it
479  // seems a waste given the level of the current model)
480  // and act by locally establishing the agreement on
481  // the appropriate queue.
482  AcIndex ac = QosUtilsMapTidToAc (respHdr.GetTid ());
483  m_edca[ac]->GotAddBaResponse (&respHdr, from);
484  // This frame is now completely dealt with, so we're done.
485  return;
486  }
487 
489  {
490  MgtDelBaHeader delBaHdr;
491  packet->RemoveHeader (delBaHdr);
492 
493  if (delBaHdr.IsByOriginator ())
494  {
495  // This DELBA frame was sent by the originator, so
496  // this means that an ingoing established
497  // agreement exists in MacLow and we need to
498  // destroy it.
499  m_low->DestroyBlockAckAgreement (from, delBaHdr.GetTid ());
500  }
501  else
502  {
503  // We must have been the originator. We need to
504  // tell the correct queue that the agreement has
505  // been torn down
506  AcIndex ac = QosUtilsMapTidToAc (delBaHdr.GetTid ());
507  m_edca[ac]->GotDelBaFrame (&delBaHdr, from);
508  }
509  // This frame is now completely dealt with, so we're done.
510  return;
511  }
512 
513  default:
514  NS_FATAL_ERROR ("Unsupported Action field in Block Ack Action frame");
515  }
516 
517  default:
518  NS_FATAL_ERROR ("Unsupported Action frame received");
519  }
520  }
521  NS_FATAL_ERROR ("Don't know how to handle frame (type=" << hdr->GetType ());
522 }
523 
524 void
526  const WifiMacHeader *hdr)
527 {
529  MsduAggregator::Deaggregate (aggregatedPacket);
530 
531  for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin ();
532  i != packets.end (); ++i)
533  {
534  ForwardUp ((*i).first, (*i).second.GetSourceAddr (),
535  (*i).second.GetDestinationAddr ());
536  }
537 }
538 
539 void
541  Mac48Address originator)
542 {
543  NS_LOG_FUNCTION (this);
544  WifiMacHeader hdr;
545  hdr.SetAction ();
546  hdr.SetAddr1 (originator);
547  hdr.SetAddr2 (GetAddress ());
548  hdr.SetAddr3 (GetAddress ());
549  hdr.SetDsNotFrom ();
550  hdr.SetDsNotTo ();
551 
552  MgtAddBaResponseHeader respHdr;
553  StatusCode code;
554  code.SetSuccess ();
555  respHdr.SetStatusCode (code);
556  //Here a control about queues type?
557  respHdr.SetAmsduSupport (reqHdr->IsAmsduSupported ());
558 
559  if (reqHdr->IsImmediateBlockAck ())
560  {
561  respHdr.SetImmediateBlockAck ();
562  }
563  else
564  {
565  respHdr.SetDelayedBlockAck ();
566  }
567  respHdr.SetTid (reqHdr->GetTid ());
568  // For now there's not no control about limit of reception. We
569  // assume that receiver has no limit on reception. However we assume
570  // that a receiver sets a bufferSize in order to satisfy next
571  // equation: (bufferSize + 1) % 16 = 0 So if a recipient is able to
572  // buffer a packet, it should be also able to buffer all possible
573  // packet's fragments. See section 7.3.1.14 in IEEE802.11e for more
574  // details.
575  respHdr.SetBufferSize (1023);
576  respHdr.SetTimeout (reqHdr->GetTimeout ());
577 
578  WifiActionHeader actionHdr;
581  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
582 
583  Ptr<Packet> packet = Create<Packet> ();
584  packet->AddHeader (respHdr);
585  packet->AddHeader (actionHdr);
586 
587  // We need to notify our MacLow object as it will have to buffer all
588  // correctly received packets for this Block Ack session
589  m_low->CreateBlockAckAgreement (&respHdr, originator,
590  reqHdr->GetStartingSequence ());
591 
592  // It is unclear which queue this frame should go into. For now we
593  // bung it into the queue corresponding to the TID for which we are
594  // establishing an agreement, and push it to the head.
595  m_edca[QosUtilsMapTidToAc (reqHdr->GetTid ())]->PushFront (packet, hdr);
596 }
597 
598 TypeId
600 {
601  static TypeId tid = TypeId ("ns3::RegularWifiMac")
602  .SetParent<WifiMac> ()
603  .AddAttribute ("QosSupported",
604  "This Boolean attribute is set to enable 802.11e/WMM-style QoS support at this STA",
605  BooleanValue (false),
606  MakeBooleanAccessor (&RegularWifiMac::SetQosSupported,
608  MakeBooleanChecker ())
609  .AddAttribute ("DcaTxop", "The DcaTxop object",
610  PointerValue (),
611  MakePointerAccessor (&RegularWifiMac::GetDcaTxop),
612  MakePointerChecker<DcaTxop> ())
613  .AddAttribute ("VO_EdcaTxopN",
614  "Queue that manages packets belonging to AC_VO access class",
615  PointerValue (),
616  MakePointerAccessor (&RegularWifiMac::GetVOQueue),
617  MakePointerChecker<EdcaTxopN> ())
618  .AddAttribute ("VI_EdcaTxopN",
619  "Queue that manages packets belonging to AC_VI access class",
620  PointerValue (),
621  MakePointerAccessor (&RegularWifiMac::GetVIQueue),
622  MakePointerChecker<EdcaTxopN> ())
623  .AddAttribute ("BE_EdcaTxopN",
624  "Queue that manages packets belonging to AC_BE access class",
625  PointerValue (),
626  MakePointerAccessor (&RegularWifiMac::GetBEQueue),
627  MakePointerChecker<EdcaTxopN> ())
628  .AddAttribute ("BK_EdcaTxopN",
629  "Queue that manages packets belonging to AC_BK access class",
630  PointerValue (),
631  MakePointerAccessor (&RegularWifiMac::GetBKQueue),
632  MakePointerChecker<EdcaTxopN> ())
633  .AddTraceSource ( "TxOkHeader",
634  "The header of successfully transmitted packet",
636  .AddTraceSource ("TxErrHeader",
637  "The header of unsuccessfully transmitted packet",
639  ;
640 
641  return tid;
642 }
643 
644 void
646 {
647  uint32_t cwmin;
648  uint32_t cwmax;
649 
650  switch (standard)
651  {
654  cwmin = 15;
655  cwmax = 511;
656  break;
657 
663  cwmin = 15;
664  cwmax = 1023;
665  break;
666 
668  cwmin = 31;
669  cwmax = 1023;
670  break;
671 
672  default:
673  NS_FATAL_ERROR ("Unsupported WifiPhyStandard in RegularWifiMac::FinishConfigureStandard ()");
674  }
675 
676  // The special value of AC_BE_NQOS which exists in the Access
677  // Category enumeration allows us to configure plain old DCF.
678  ConfigureDcf (m_dca, cwmin, cwmax, AC_BE_NQOS);
679 
680  // Now we configure the EDCA functions
681  for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i)
682  {
683  // Special configuration for 802.11p CCH
684  if (standard == WIFI_PHY_STANDARD_80211p_CCH)
685  {
686  ConfigureCCHDcf (i->second, cwmin, cwmax, i->first);
687  }
688  else
689  {
690  ConfigureDcf (i->second, cwmin, cwmax, i->first);
691  }
692  }
693 }
694 
695 void
697 {
698  NS_LOG_FUNCTION (this << hdr);
699  m_txOkCallback (hdr);
700 }
701 
702 void
704 {
705  NS_LOG_FUNCTION (this << hdr);
706  m_txErrCallback (hdr);
707 }
708 
709 } // namespace ns3