src/wifi/model/regular-wifi-mac.cc
changeset 6852 8f1a53d3f6ca
parent 6848 1f453ad50ef3
child 7014 937151f978b3
equal deleted inserted replaced
6851:7fdad61b88f1 6852:8f1a53d3f6ca
       
     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