src/devices/wifi/qap-wifi-mac.cc
changeset 6068 a2127017ecb4
parent 6065 0f012e7d9128
parent 5965 4e64e751be07
child 6080 41ee42654550
--- a/src/devices/wifi/qap-wifi-mac.cc	Thu Feb 25 13:51:59 2010 +0100
+++ b/src/devices/wifi/qap-wifi-mac.cc	Thu Feb 25 14:17:21 2010 +0100
@@ -199,6 +199,18 @@
 }
 
 void 
+QapWifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetBasicBlockAckTimeout (blockAckTimeout);
+}
+
+void
+QapWifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetCompressedBlockAckTimeout (blockAckTimeout);
+}
+
+void 
 QapWifiMac::SetCtsTimeout (Time ctsTimeout)
 {
   m_low->SetCtsTimeout (ctsTimeout);
@@ -235,6 +247,18 @@
 }
 
 Time 
+QapWifiMac::GetBasicBlockAckTimeout () const
+{
+  return m_low->GetBasicBlockAckTimeout ();
+}
+
+Time 
+QapWifiMac::GetCompressedBlockAckTimeout () const
+{
+  return m_low->GetCompressedBlockAckTimeout ();
+}
+
+Time 
 QapWifiMac::GetCtsTimeout (void) const
 {
   return m_low->GetCtsTimeout ();
@@ -670,7 +694,44 @@
           else if (hdr->IsReassocReq ()) 
             {
               /* we don't support reassoc frames for now */
-            } 
+            }
+          else if (hdr->IsAction ())
+            {
+              WifiActionHeader actionHdr;
+              packet->RemoveHeader (actionHdr);
+              if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK &&
+                  actionHdr.GetAction().blockAck == WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST)
+                {
+                  MgtAddBaRequestHeader reqHdr;
+                  packet->RemoveHeader (reqHdr);
+                  SendAddBaResponse (&reqHdr, hdr->GetAddr2 ());
+                }
+              else if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK &&
+                       actionHdr.GetAction().blockAck == WifiActionHeader::BLOCK_ACK_ADDBA_RESPONSE)
+                {
+                  MgtAddBaResponseHeader respHdr;
+                  packet->RemoveHeader (respHdr);
+                  m_queues[QosUtilsMapTidToAc (respHdr.GetTid ())]->GotAddBaResponse (&respHdr, hdr->GetAddr2 ());
+                }
+              else if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK &&
+                       actionHdr.GetAction().blockAck == WifiActionHeader::BLOCK_ACK_DELBA)
+                {
+                  MgtDelBaHeader delBaHdr;
+                  packet->RemoveHeader (delBaHdr);
+                  if (delBaHdr.IsByOriginator ())
+                    {
+                      /* Delba frame was sent by originator, this means that an ingoing established
+                      agreement exists in MacLow */
+                      m_low->DestroyBlockAckAgreement (hdr->GetAddr2 (), delBaHdr.GetTid ());
+                    }
+                  else
+                    {
+                      /* We must notify correct queue tear down of agreement */
+                      AccessClass ac = QosUtilsMapTidToAc (delBaHdr.GetTid ());
+                      m_queues[ac]->GotDelBaFrame (&delBaHdr, hdr->GetAddr2 ());
+                    }
+                }
+            }
           else if (hdr->IsAuthentication () ||
                    hdr->IsDeauthentication ()) 
                  {
@@ -741,6 +802,8 @@
   edca->SetTxMiddle (m_txMiddle);
   edca->SetTxOkCallback (MakeCallback (&QapWifiMac::TxOk, this));
   edca->SetTxFailedCallback (MakeCallback (&QapWifiMac::TxFailed, this));
+  edca->SetAccessClass (ac);
+  edca->CompleteConfig ();
   m_queues.insert (std::make_pair(ac, edca));
 }
 
@@ -796,4 +859,59 @@
   WifiMac::DoStart ();
 }
 
+void
+QapWifiMac::SendAddBaResponse (const MgtAddBaRequestHeader *reqHdr, Mac48Address originator)
+{
+  NS_LOG_FUNCTION (this);
+  WifiMacHeader hdr;
+  hdr.SetAction ();
+  hdr.SetAddr1 (originator);
+  hdr.SetAddr2 (m_low->GetAddress ());
+  hdr.SetAddr3 (m_low->GetAddress ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+
+  MgtAddBaResponseHeader respHdr;
+  StatusCode code;
+  code.SetSuccess ();
+  respHdr.SetStatusCode (code);
+  //Here a control about queues type?
+  respHdr.SetAmsduSupport (reqHdr->IsAmsduSupported ());
+  
+  if (reqHdr->IsImmediateBlockAck ())
+    {
+      respHdr.SetImmediateBlockAck ();
+    }
+  else
+    {
+      respHdr.SetDelayedBlockAck ();
+    }
+  respHdr.SetTid (reqHdr->GetTid ());
+  /* For now there's not no control about limit of reception.
+     We assume that receiver has no limit on reception.
+     However we assume that a receiver sets a bufferSize in order to satisfy
+     next equation:
+     (bufferSize + 1) % 16 = 0
+     So if a recipient is able to buffer a packet, it should be also able to buffer
+     all possible packet's fragments.
+     See section 7.3.1.14 in IEEE802.11e for more details. */
+  respHdr.SetBufferSize (1023);
+  respHdr.SetTimeout (reqHdr->GetTimeout ());
+
+  WifiActionHeader actionHdr;
+  WifiActionHeader::ActionValue action;
+  action.blockAck = WifiActionHeader::BLOCK_ACK_ADDBA_RESPONSE;
+  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
+
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (respHdr);
+  packet->AddHeader (actionHdr);
+  
+  /* ns3::MacLow have to buffer all correctly received packet for this block ack session */
+  m_low->CreateBlockAckAgreement (&respHdr, originator, reqHdr->GetStartingSequence ());
+
+  //Better a management queue? 
+  m_queues[QosUtilsMapTidToAc (reqHdr->GetTid ())]->PushFront (packet, hdr);
+}
+
 }  //namespace ns3