add support to block ack tear down in MacLow

This commit is contained in:
Mirko Banchi
2010-02-03 20:34:53 +01:00
parent 091f5a7cc7
commit 5925c92f74
7 changed files with 197 additions and 8 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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));
}