add support to block ack tear down in MacLow
This commit is contained in:
@@ -102,6 +102,22 @@ private:
|
||||
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 @@ EdcaTxopN::EdcaTxopN ()
|
||||
{
|
||||
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 @@ EdcaTxopN::DoDispose (void)
|
||||
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 @@ EdcaTxopN::GotAck (double snr, WifiMode txMode)
|
||||
{
|
||||
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 @@ EdcaTxopN::GetFragmentPacket (WifiMacHeader *hdr)
|
||||
return fragment;
|
||||
}
|
||||
|
||||
void
|
||||
EdcaTxopN::SetAccessClass (enum AccessClass ac)
|
||||
{
|
||||
m_ac = ac;
|
||||
}
|
||||
|
||||
Mac48Address
|
||||
EdcaTxopN::MapSrcAddressForAggregation (const WifiMacHeader &hdr)
|
||||
{
|
||||
@@ -913,6 +959,7 @@ EdcaTxopN::CompleteConfig (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_baManager->SetTxMiddle (m_txMiddle);
|
||||
m_low->RegisterBlockAckListenerForAc (m_ac, m_blockAckListener);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -992,4 +1039,38 @@ EdcaTxopN::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
|
||||
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
|
||||
|
||||
@@ -136,13 +136,14 @@ public:
|
||||
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 @@ private:
|
||||
*/
|
||||
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 @@ private:
|
||||
Ptr<MacLow> m_low;
|
||||
MacTxMiddle *m_txMiddle;
|
||||
TransmissionListener *m_transmissionListener;
|
||||
BlockAckEventListener *m_blockAckListener;
|
||||
RandomStream *m_rng;
|
||||
Ptr<WifiRemoteStationManager> m_stationManager;
|
||||
uint8_t m_fragmentNumber;
|
||||
|
||||
@@ -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 ()
|
||||
MacLowDcfListener::~MacLowDcfListener ()
|
||||
{}
|
||||
|
||||
MacLowBlockAckEventListener::MacLowBlockAckEventListener ()
|
||||
{}
|
||||
MacLowBlockAckEventListener::~MacLowBlockAckEventListener ()
|
||||
{}
|
||||
|
||||
MacLowTransmissionParameters::MacLowTransmissionParameters ()
|
||||
: m_nextSize (0),
|
||||
m_waitAck (ACK_NONE),
|
||||
@@ -745,6 +751,8 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamb
|
||||
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 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamb
|
||||
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 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamb
|
||||
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 @@ void
|
||||
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 @@ MacLow::CreateBlockAckAgreement (const MgtAddBaResponseHeader *respHdr, Mac48Add
|
||||
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 @@ MacLow::SendBlockAckAfterBlockAckRequest (const CtrlBAckRequestHeader reqHdr, Ma
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
@@ -147,6 +149,25 @@ public:
|
||||
virtual void CtsTimeoutReset () = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \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.
|
||||
*
|
||||
@@ -451,6 +472,14 @@ public:
|
||||
* 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 @@ private:
|
||||
*/
|
||||
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 @@ private:
|
||||
typedef std::map<AgreementKey, AgreementValue>::iterator AgreementsI;
|
||||
|
||||
Agreements m_bAckAgreements;
|
||||
|
||||
typedef std::map<AccessClass, MacLowBlockAckEventListener*> QueueListeners;
|
||||
QueueListeners m_edcaListeners;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -403,8 +403,9 @@ QadhocWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
|
||||
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 @@ QadhocWifiMac::SetQueue (enum AccessClass ac)
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -723,7 +723,9 @@ QapWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
|
||||
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 @@ QapWifiMac::SetQueue (enum AccessClass ac)
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -723,7 +723,9 @@ QstaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
|
||||
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 @@ QstaWifiMac::SetQueue (enum AccessClass ac)
|
||||
edca->SetManager (m_dcfManager);
|
||||
edca->SetTypeOfStation (STA);
|
||||
edca->SetTxMiddle (m_txMiddle);
|
||||
edca->SetAccessClass (ac);
|
||||
edca->CompleteConfig ();
|
||||
m_queues.insert (std::make_pair(ac, edca));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user