--- a/src/devices/wifi/edca-txop-n.cc Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/edca-txop-n.cc Wed Feb 03 20:34:53 2010 +0100
@@ -102,6 +102,22 @@
EdcaTxopN *m_txop;
};
+class EdcaTxopN::BlockAckEventListener : public MacLowBlockAckEventListener
+{
+public:
+ BlockAckEventListener (EdcaTxopN *txop)
+ : MacLowBlockAckEventListener (),
+ m_txop (txop) {}
+ virtual ~BlockAckEventListener () {}
+
+ virtual void BlockAckInactivityTimeout (Mac48Address address, uint8_t tid) {
+ m_txop->SendDelbaFrame (address, tid, false);
+ }
+
+private:
+ EdcaTxopN *m_txop;
+};
+
NS_OBJECT_ENSURE_REGISTERED (EdcaTxopN);
TypeId
@@ -128,6 +144,7 @@
{
NS_LOG_FUNCTION (this);
m_transmissionListener = new EdcaTxopN::TransmissionListener (this);
+ m_blockAckListener = new EdcaTxopN::BlockAckEventListener (this);
m_dcf = new EdcaTxopN::Dcf (this);
m_queue = CreateObject<WifiMacQueue> ();
m_rng = new RealRandomStream ();
@@ -157,11 +174,13 @@
delete m_rng;
delete m_qosBlockedDestinations;
delete m_baManager;
+ delete m_blockAckListener;
m_transmissionListener = 0;
m_dcf = 0;
m_rng = 0;
m_qosBlockedDestinations = 0;
m_baManager = 0;
+ m_blockAckListener = 0;
m_txMiddle = 0;
m_aggregator = 0;
}
@@ -527,6 +546,27 @@
{
m_txOkCallback (m_currentHdr);
}
+
+ if (m_currentHdr.IsAction ())
+ {
+ WifiActionHeader actionHdr;
+ Ptr<Packet> p = m_currentPacket->Copy ();
+ p->RemoveHeader (actionHdr);
+ if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK &&
+ actionHdr.GetAction ().blockAck == WifiActionHeader::BLOCK_ACK_DELBA)
+ {
+ MgtDelBaHeader delBa;
+ p->PeekHeader (delBa);
+ if (delBa.IsByOriginator ())
+ {
+ m_baManager->TearDownBlockAck (m_currentHdr.GetAddr1 (), delBa.GetTid ());
+ }
+ else
+ {
+ m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
+ }
+ }
+ }
m_currentPacket = 0;
m_dcf->ResetCw ();
@@ -730,6 +770,12 @@
return fragment;
}
+void
+EdcaTxopN::SetAccessClass (enum AccessClass ac)
+{
+ m_ac = ac;
+}
+
Mac48Address
EdcaTxopN::MapSrcAddressForAggregation (const WifiMacHeader &hdr)
{
@@ -913,6 +959,7 @@
{
NS_LOG_FUNCTION (this);
m_baManager->SetTxMiddle (m_txMiddle);
+ m_low->RegisterBlockAckListenerForAc (m_ac, m_blockAckListener);
}
void
@@ -992,4 +1039,38 @@
m_transmissionListener);
}
+void
+EdcaTxopN::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
+{
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetAddr1 (addr);
+ hdr.SetAddr2 (m_low->GetAddress ());
+ hdr.SetAddr3 (m_low->GetAddress ());
+ hdr.SetDsNotTo ();
+ hdr.SetDsNotFrom ();
+
+ MgtDelBaHeader delbaHdr;
+ delbaHdr.SetTid (tid);
+ if (byOriginator)
+ {
+ delbaHdr.SetByOriginator ();
+ }
+ else
+ {
+ delbaHdr.SetByRecipient ();
+ }
+
+ WifiActionHeader actionHdr;
+ WifiActionHeader::ActionValue action;
+ action.blockAck = WifiActionHeader::BLOCK_ACK_DELBA;
+ actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
+
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (delbaHdr);
+ packet->AddHeader (actionHdr);
+
+ PushFront (packet, hdr);
+}
+
} //namespace ns3
--- a/src/devices/wifi/edca-txop-n.h Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/edca-txop-n.h Wed Feb 03 20:34:53 2010 +0100
@@ -136,13 +136,14 @@
void NextFragment (void);
Ptr<Packet> GetFragmentPacket (WifiMacHeader *hdr);
+ void SetAccessClass (enum AccessClass ac);
void Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr);
void SetMsduAggregator (Ptr<MsduAggregator> aggr);
void PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr);
void CompleteConfig (void);
void SetBlockAckThreshold (uint8_t threshold);
uint8_t GetBlockAckThreshold (void) const;
-
+ void SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator);
private:
/**
@@ -181,9 +182,10 @@
*/
void VerifyBlockAck (void);
-
+ AccessClass m_ac;
class Dcf;
class TransmissionListener;
+ class BlockAckEventListener;
friend class Dcf;
friend class TransmissionListener;
Dcf *m_dcf;
@@ -194,6 +196,7 @@
Ptr<MacLow> m_low;
MacTxMiddle *m_txMiddle;
TransmissionListener *m_transmissionListener;
+ BlockAckEventListener *m_blockAckListener;
RandomStream *m_rng;
Ptr<WifiRemoteStationManager> m_stationManager;
uint8_t m_fragmentNumber;
--- a/src/devices/wifi/mac-low.cc Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/mac-low.cc Wed Feb 03 20:34:53 2010 +0100
@@ -31,6 +31,7 @@
#include "wifi-phy.h"
#include "wifi-mac-trailer.h"
#include "qos-utils.h"
+#include "edca-txop-n.h"
NS_LOG_COMPONENT_DEFINE ("MacLow");
@@ -125,6 +126,11 @@
MacLowDcfListener::~MacLowDcfListener ()
{}
+MacLowBlockAckEventListener::MacLowBlockAckEventListener ()
+{}
+MacLowBlockAckEventListener::~MacLowBlockAckEventListener ()
+{}
+
MacLowTransmissionParameters::MacLowTransmissionParameters ()
: m_nextSize (0),
m_waitAck (ACK_NONE),
@@ -745,6 +751,8 @@
if (it != m_bAckAgreements.end ())
{
NS_ASSERT (m_sendAckEvent.IsExpired ());
+ /* See section 11.5.3 in IEEE802.11 for mean of this timer */
+ ResetBlockAckInactivityTimerIfNeeded (it->second.first);
if ((*it).second.first.IsImmediateBlockAck ())
{
NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from="<< hdr.GetAddr2 ());
@@ -800,6 +808,12 @@
txMode,
rxSnr);
}
+ else if (hdr.IsQosBlockAck ())
+ {
+ AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
+ /* See section 11.5.3 in IEEE802.11 for mean of this timer */
+ ResetBlockAckInactivityTimerIfNeeded (it->second.first);
+ }
return;
}
else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
@@ -810,7 +824,10 @@
From section 11.5.3 in IEEE802.11e:
When a recipient does not have an active Block ack for a TID, but receives
data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
- them [...]. */
+ them and shall send a DELBA frame using the normal access
+ mechanisms. */
+ AccessClass ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
+ m_edcaListeners[ac]->BlockAckInactivityTimeout (hdr.GetAddr2 (), hdr.GetQosTid ());
return;
}
else if (hdr.IsQosData () && hdr.IsQosNoAck ())
@@ -1504,7 +1521,8 @@
MacLow::CreateBlockAckAgreement (const MgtAddBaResponseHeader *respHdr, Mac48Address originator,
uint16_t startingSeq)
{
- BlockAckAgreement agreement (originator, respHdr->GetTid ());
+ uint8_t tid = respHdr->GetTid ();
+ BlockAckAgreement agreement (originator, tid);
if (respHdr->IsImmediateBlockAck ())
{
agreement.SetImmediateBlockAck ();
@@ -1522,6 +1540,19 @@
AgreementKey key (originator, respHdr->GetTid ());
AgreementValue value (agreement, buffer);
m_bAckAgreements.insert (std::make_pair (key, value));
+
+ if (respHdr->GetTimeout () != 0)
+ {
+ AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
+ Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
+
+ AccessClass ac = QosUtilsMapTidToAc (agreement.GetTid ());
+
+ it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
+ &MacLowBlockAckEventListener::BlockAckInactivityTimeout,
+ m_edcaListeners[ac],
+ originator, tid);
+ }
}
void
@@ -1798,4 +1829,31 @@
SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode);
}
+void
+MacLow::ResetBlockAckInactivityTimerIfNeeded (BlockAckAgreement &agreement)
+{
+ if (agreement.GetTimeout () != 0)
+ {
+ NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
+ agreement.m_inactivityEvent.Cancel ();
+ Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
+
+ AccessClass ac = QosUtilsMapTidToAc (agreement.GetTid ());
+ //std::map<AccessClass, MacLowTransmissionListener*>::iterator it = m_edcaListeners.find (ac);
+ //NS_ASSERT (it != m_edcaListeners.end ());
+
+ agreement.m_inactivityEvent = Simulator::Schedule (timeout,
+ &MacLowBlockAckEventListener::BlockAckInactivityTimeout,
+ m_edcaListeners[ac],
+ agreement.GetPeer (),
+ agreement.GetTid ());
+ }
+}
+
+void
+MacLow::RegisterBlockAckListenerForAc (enum AccessClass ac, MacLowBlockAckEventListener *listener)
+{
+ m_edcaListeners.insert (std::make_pair (ac, listener));
+}
+
} // namespace ns3
--- a/src/devices/wifi/mac-low.h Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/mac-low.h Wed Feb 03 20:34:53 2010 +0100
@@ -39,11 +39,13 @@
#include "ns3/event-id.h"
#include "ns3/packet.h"
#include "ns3/nstime.h"
+#include "qos-utils.h"
namespace ns3 {
class WifiPhy;
class WifiMac;
+class EdcaTxopN;
/**
* \brief listen to events coming from ns3::MacLow.
@@ -148,6 +150,25 @@
};
/**
+ * \brief listen for block ack events.
+ */
+class MacLowBlockAckEventListener {
+public:
+ MacLowBlockAckEventListener ();
+ virtual ~MacLowBlockAckEventListener ();
+ /**
+ * Typically is called in order to notify EdcaTxopN that a block ack inactivity
+ * timeout occurs for the block ack agreement identified by the pair <i>originator</i>, <i>tid</i>.
+ *
+ * Rx station maintains an inactivity timer for each block ack
+ * agreement. Timer is reset when a frame with ack policy block ack
+ * or a block ack request are received. When this timer reaches zero
+ * this method is called and a delba frame is scheduled for transmission.
+ */
+ virtual void BlockAckInactivityTimeout (Mac48Address originator, uint8_t tid) = 0;
+};
+
+/**
* \brief control how a packet is transmitted.
*
* The ns3::MacLow::StartTransmission method expects
@@ -451,6 +472,14 @@
* invoked when a DELBA frame is received from <i>originator</i>.
*/
void DestroyBlockAckAgreement (Mac48Address originator, uint8_t tid);
+ /**
+ * \param ac Access class managed by the queue.
+ * \param listener The listener for the queue.
+ *
+ * The lifetime of the registered listener is typically equal to the lifetime of the queue
+ * associated to this AC.
+ */
+ void RegisterBlockAckListenerForAc (enum AccessClass ac, MacLowBlockAckEventListener *listener);
private:
void CancelAllEvents (void);
uint32_t GetAckSize (void) const;
@@ -540,6 +569,13 @@
*/
void SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
Time duration, WifiMode blockAckReqTxMode);
+ /*
+ * Every time that a block ack request or a packet with ack policy equals to <i>block ack</i>
+ * are received, if a relative block ack agreement exists and the value of inactivity timeout
+ * is not 0, the timer is reset.
+ * see section 11.5.3 in IEEE802.11e for more details.
+ */
+ void ResetBlockAckInactivityTimerIfNeeded (BlockAckAgreement &agreement);
void SetupPhyMacLowListener (Ptr<WifiPhy> phy);
@@ -595,6 +631,9 @@
typedef std::map<AgreementKey, AgreementValue>::iterator AgreementsI;
Agreements m_bAckAgreements;
+
+ typedef std::map<AccessClass, MacLowBlockAckEventListener*> QueueListeners;
+ QueueListeners m_edcaListeners;
};
} // namespace ns3
--- a/src/devices/wifi/qadhoc-wifi-mac.cc Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/qadhoc-wifi-mac.cc Wed Feb 03 20:34:53 2010 +0100
@@ -403,8 +403,9 @@
packet->RemoveHeader (delBaHdr);
if (delBaHdr.IsByOriginator ())
{
- /* Block ack agreement tear down */
- }
+ /* 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 */
@@ -458,6 +459,7 @@
edca->SetManager (m_dcfManager);
edca->SetTypeOfStation (ADHOC_STA);
edca->SetTxMiddle (m_txMiddle);
+ edca->SetAccessClass (ac);
edca->CompleteConfig ();
m_queues.insert (std::make_pair(ac, edca));
}
--- a/src/devices/wifi/qap-wifi-mac.cc Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/qap-wifi-mac.cc Wed Feb 03 20:34:53 2010 +0100
@@ -723,7 +723,9 @@
packet->RemoveHeader (delBaHdr);
if (delBaHdr.IsByOriginator ())
{
- /* Block ack agreement tear down */
+ /* Delba frame was sent by originator, this means that an ingoing established
+ agreement exists in MacLow */
+ m_low->DestroyBlockAckAgreement (hdr->GetAddr2 (), delBaHdr.GetTid ());
}
else
{
@@ -801,6 +803,7 @@
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));
}
--- a/src/devices/wifi/qsta-wifi-mac.cc Wed Feb 03 20:34:53 2010 +0100
+++ b/src/devices/wifi/qsta-wifi-mac.cc Wed Feb 03 20:34:53 2010 +0100
@@ -723,7 +723,9 @@
packet->RemoveHeader (delBaHdr);
if (delBaHdr.IsByOriginator ())
{
- /* Block ack agreement tear down */
+ /* Delba frame was sent by originator, this means that an ingoing established
+ agreement exists in MacLow */
+ m_low->DestroyBlockAckAgreement (hdr->GetAddr2 (), delBaHdr.GetTid ());
}
else
{
@@ -788,6 +790,7 @@
edca->SetManager (m_dcfManager);
edca->SetTypeOfStation (STA);
edca->SetTxMiddle (m_txMiddle);
+ edca->SetAccessClass (ac);
edca->CompleteConfig ();
m_queues.insert (std::make_pair(ac, edca));
}