Index: src/wifi/model/mac-low.cc |
=================================================================== |
--- a/src/wifi/model/mac-low.cc |
+++ b/src/wifi/model/mac-low.cc |
@@ -18,6 +18,7 @@ |
* |
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
* Author: Mirko Banchi <mk.banchi@gmail.com> |
+ * Author: Ghada Badawy <gbadawy@gmail.com> |
*/ |
#include "ns3/assert.h" |
@@ -34,6 +35,9 @@ |
#include "qos-utils.h" |
#include "edca-txop-n.h" |
#include "snr-tag.h" |
+#include "yans-wifi-phy.h" |
+#include "ampdu-tag.h" |
+#include "wifi-mac-queue.h" |
NS_LOG_COMPONENT_DEFINE ("MacLow"); |
@@ -51,7 +55,7 @@ |
} |
void |
MacLowTransmissionListener::GotBlockAck (const CtrlBAckResponseHeader *blockAck, |
- Mac48Address source) |
+ Mac48Address source, WifiMode mode) |
{ |
} |
void |
@@ -72,6 +76,52 @@ |
{ |
} |
+void MacLowBlockAckEventListener::SetAmpdu (bool ampdu) |
+{ |
+} |
+ |
+void MacLowBlockAckEventListener::CompleteTransfer(Mac48Address address, uint8_t tid) |
+{ |
+} |
+void |
+MacLowBlockAckEventListener::CompleteMpduTx (Ptr<const Packet> packet, WifiMacHeader hdr, Time tstamp) |
+{ |
+} |
+ |
+uint16_t |
+MacLowBlockAckEventListener::GetNextSequenceNumberfor (WifiMacHeader *hdr) |
+{ |
+ return 0; |
+} |
+ |
+uint16_t |
+MacLowBlockAckEventListener::PeekNextSequenceNumberfor (WifiMacHeader *hdr) |
+{ |
+ return 0; |
+} |
+ |
+Ptr<const Packet> |
+MacLowBlockAckEventListener::PeekNextPacketInBaQueue (WifiMacHeader &Hdr) |
+{ |
+ return 0; |
+} |
+ |
+void |
+MacLowBlockAckEventListener::RemoveFromBaQueue (Ptr<const Packet> packet) |
+{ |
+} |
+ |
+uint32_t |
+MacLowBlockAckEventListener::GetNOutstandingPackets (Mac48Address recipient, uint8_t tid) |
+{ |
+ return 0; |
+} |
+ |
+uint32_t |
+MacLowBlockAckEventListener::GetNRetryNeededPackets (Mac48Address recipient, uint8_t tid) const |
+{ |
+ return 0; |
+} |
MacLowTransmissionParameters::MacLowTransmissionParameters () |
: m_nextSize (0), |
m_waitAck (ACK_NONE), |
@@ -261,10 +311,13 @@ |
virtual void NotifyRxStart (Time duration) |
{ |
} |
- virtual void NotifyRxEndOk (void) |
+ virtual void NotifyRxEnd (void) |
{ |
} |
- virtual void NotifyRxEndError (void) |
+ virtual void NotifyRxEndOk (void) |
+ { |
+ } |
+ virtual void NotifyRxEndError (void) |
{ |
} |
virtual void NotifyTxStart (Time duration) |
@@ -294,6 +347,8 @@ |
m_sendDataEvent (), |
m_waitSifsEvent (), |
m_endTxNoAckEvent (), |
+ m_waitRifsEvent(), |
+ m_mpduAggregator (0), |
m_currentPacket (0), |
m_listener (0) |
{ |
@@ -301,6 +356,9 @@ |
m_lastNavDuration = Seconds (0); |
m_lastNavStart = Seconds (0); |
m_promisc = false; |
+ m_sentMpdus=0; |
+ m_aggregateQueue = CreateObject<WifiMacQueue> (); |
+ m_random = CreateObject<UniformRandomVariable> (); |
} |
MacLow::~MacLow () |
@@ -314,7 +372,13 @@ |
m_phyMacLowListener = new PhyMacLowListener (this); |
phy->RegisterListener (m_phyMacLowListener); |
} |
- |
+int64_t |
+MacLow::AssignStreams (int64_t stream) |
+{ |
+ NS_LOG_FUNCTION (this << stream); |
+ m_random->SetStream (stream); |
+ return 1; |
+} |
void |
MacLow::DoDispose (void) |
@@ -336,6 +400,9 @@ |
m_stationManager = 0; |
delete m_phyMacLowListener; |
m_phyMacLowListener = 0; |
+ m_mpduAggregator = 0; |
+ m_sentMpdus = 0; |
+ m_aggregateQueue = 0; |
} |
void |
@@ -414,7 +481,7 @@ |
MacLow::SetPhy (Ptr<WifiPhy> phy) |
{ |
m_phy = phy; |
- m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::ReceiveOk, this)); |
+ m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::DeaggregateAmpduAndReceive, this)); |
m_phy->SetReceiveErrorCallback (MakeCallback (&MacLow::ReceiveError, this)); |
SetupPhyMacLowListener (phy); |
} |
@@ -551,7 +618,24 @@ |
m_dcfListeners.push_back (listener); |
} |
- |
+bool |
+MacLow::IsAmpdu(Ptr<const Packet> packet, const WifiMacHeader hdr) |
+{ |
+ uint32_t size, actualSize; |
+ WifiMacTrailer fcs; |
+ Ptr<Packet> p; |
+ p = packet->Copy(); |
+ size= packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize (); |
+ p = AggregateToAmpdu (packet, hdr); |
+ actualSize = p->GetSize(); |
+ if (actualSize > size) |
+ { |
+ m_currentPacket = p; |
+ return true; |
+ } |
+ else |
+ return false; |
+} |
void |
MacLow::StartTransmission (Ptr<const Packet> packet, |
const WifiMacHeader* hdr, |
@@ -581,9 +665,15 @@ |
//NS_ASSERT (m_phy->IsStateIdle ()); |
- NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, &m_currentHdr) << |
+ m_ampdu=IsAmpdu(m_currentPacket,m_currentHdr); |
+ |
+ NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, m_currentHdr) << |
", to=" << m_currentHdr.GetAddr1 () << ", listener=" << m_listener); |
+ if (m_ampdu) |
+ m_txParams.EnableCompressedBlockAck (); |
+ |
+ |
if (m_txParams.MustSendRts ()) |
{ |
SendRtsForPacket (); |
@@ -640,7 +730,7 @@ |
} |
void |
-MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble) |
+MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble, bool ampduSubframe) |
{ |
NS_LOG_FUNCTION (this << packet << rxSnr << txMode << preamble); |
/* A packet is received from the PHY. |
@@ -662,23 +752,30 @@ |
* idle. If the NAV at the STA receiving the RTS indicates the medium is not idle, |
* that STA shall not respond to the RTS frame. |
*/ |
- if (isPrevNavZero |
- && hdr.GetAddr1 () == m_self) |
+ if (ampduSubframe) |
{ |
- NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS"); |
- NS_ASSERT (m_sendCtsEvent.IsExpired ()); |
- m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr, |
- rxSnr, txMode); |
- m_sendCtsEvent = Simulator::Schedule (GetSifs (), |
- &MacLow::SendCtsAfterRts, this, |
- hdr.GetAddr2 (), |
- hdr.GetDuration (), |
- txMode, |
- rxSnr); |
+ NS_FATAL_ERROR ("Received RTS as part of an A-MPDU"); |
} |
else |
{ |
- NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS"); |
+ if (isPrevNavZero |
+ && hdr.GetAddr1 () == m_self) |
+ { |
+ NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS"); |
+ NS_ASSERT (m_sendCtsEvent.IsExpired ()); |
+ m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr, |
+ rxSnr, txMode); |
+ m_sendCtsEvent = Simulator::Schedule (GetSifs (), |
+ &MacLow::SendCtsAfterRts, this, |
+ hdr.GetAddr2 (), |
+ hdr.GetDuration (), |
+ txMode, |
+ rxSnr); |
+ } |
+ else |
+ { |
+ NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS"); |
+ } |
} |
} |
else if (hdr.IsCts () |
@@ -686,23 +783,30 @@ |
&& m_ctsTimeoutEvent.IsRunning () |
&& m_currentPacket != 0) |
{ |
- NS_LOG_DEBUG ("receive cts from=" << m_currentHdr.GetAddr1 ()); |
- SnrTag tag; |
- packet->RemovePacketTag (tag); |
- m_stationManager->ReportRxOk (m_currentHdr.GetAddr1 (), &m_currentHdr, |
- rxSnr, txMode); |
- m_stationManager->ReportRtsOk (m_currentHdr.GetAddr1 (), &m_currentHdr, |
- rxSnr, txMode, tag.Get ()); |
+ if (ampduSubframe) |
+ { |
+ NS_FATAL_ERROR ("Received CTS as part of an A-MPDU"); |
+ } |
+ else |
+ { |
+ NS_LOG_DEBUG ("receive cts from=" << m_currentHdr.GetAddr1 ()); |
+ SnrTag tag; |
+ packet->RemovePacketTag (tag); |
+ m_stationManager->ReportRxOk (m_currentHdr.GetAddr1 (), &m_currentHdr, |
+ rxSnr, txMode); |
+ m_stationManager->ReportRtsOk (m_currentHdr.GetAddr1 (), &m_currentHdr, |
+ rxSnr, txMode, tag.Get ()); |
- m_ctsTimeoutEvent.Cancel (); |
- NotifyCtsTimeoutResetNow (); |
- m_listener->GotCts (rxSnr, txMode); |
- NS_ASSERT (m_sendDataEvent.IsExpired ()); |
- m_sendDataEvent = Simulator::Schedule (GetSifs (), |
- &MacLow::SendDataAfterCts, this, |
- hdr.GetAddr1 (), |
- hdr.GetDuration (), |
- txMode); |
+ m_ctsTimeoutEvent.Cancel (); |
+ NotifyCtsTimeoutResetNow (); |
+ m_listener->GotCts (rxSnr, txMode); |
+ NS_ASSERT (m_sendDataEvent.IsExpired ()); |
+ m_sendDataEvent = Simulator::Schedule (GetSifs (), |
+ &MacLow::SendDataAfterCts, this, |
+ hdr.GetAddr1 (), |
+ hdr.GetDuration (), |
+ txMode); |
+ } |
} |
else if (hdr.IsAck () |
&& hdr.GetAddr1 () == m_self |
@@ -751,7 +855,9 @@ |
CtrlBAckResponseHeader blockAck; |
packet->RemoveHeader (blockAck); |
m_blockAckTimeoutEvent.Cancel (); |
- m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 ()); |
+ NotifyAckTimeoutResetNow (); |
+ m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (),txMode); |
+ m_sentMpdus=0; |
} |
else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self) |
{ |
@@ -805,14 +911,14 @@ |
m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr, |
rxSnr, txMode); |
- if (hdr.IsQosData () && StoreMpduIfNeeded (packet, hdr)) |
+ if (hdr.IsQosData () && ReceiveMpdu (packet, hdr)) |
{ |
/* From section 9.10.4 in IEEE802.11: |
Upon the receipt of a QoS data frame from the originator for which |
the Block Ack agreement exists, the recipient shall buffer the MSDU |
regardless of the value of the Ack Policy subfield within the |
QoS Control field of the QoS data frame. */ |
- if (hdr.IsQosAck ()) |
+ if (hdr.IsQosAck () && !ampduSubframe) |
{ |
AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ())); |
RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequence (), |
@@ -850,31 +956,52 @@ |
} |
else if (hdr.IsQosData () && hdr.IsQosNoAck ()) |
{ |
- NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ()); |
+ if (ampduSubframe) |
+ { |
+ NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ()); |
+ } |
+ else |
+ { |
+ NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ()); |
+ } |
} |
else if (hdr.IsData () || hdr.IsMgt ()) |
{ |
- NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ()); |
- NS_ASSERT (m_sendAckEvent.IsExpired ()); |
- m_sendAckEvent = Simulator::Schedule (GetSifs (), |
- &MacLow::SendAckAfterData, this, |
- hdr.GetAddr2 (), |
- hdr.GetDuration (), |
- txMode, |
- rxSnr); |
+ if (hdr.IsMgt() && ampduSubframe) |
+ { |
+ NS_FATAL_ERROR ("Received management packet as part of an A-MPDU"); |
+ } |
+ else |
+ { |
+ NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ()); |
+ NS_ASSERT (m_sendAckEvent.IsExpired ()); |
+ m_sendAckEvent = Simulator::Schedule (GetSifs (), |
+ &MacLow::SendAckAfterData, this, |
+ hdr.GetAddr2 (), |
+ hdr.GetDuration (), |
+ txMode, |
+ rxSnr); |
+ } |
} |
goto rxPacket; |
} |
else if (hdr.GetAddr1 ().IsGroup ()) |
{ |
- if (hdr.IsData () || hdr.IsMgt ()) |
+ if (ampduSubframe) |
{ |
- NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ()); |
- goto rxPacket; |
+ NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU"); |
} |
else |
{ |
- // DROP |
+ if (hdr.IsData () || hdr.IsMgt ()) |
+ { |
+ NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ()); |
+ goto rxPacket; |
+ } |
+ else |
+ { |
+ // DROP |
+ } |
} |
} |
else if (m_promisc) |
@@ -897,6 +1024,27 @@ |
return; |
} |
+uint8_t |
+MacLow::GetTid(Ptr<const Packet> packet, const WifiMacHeader hdr) const |
+{ |
+ uint8_t tid; |
+ if (hdr.IsQosData()) |
+ tid= hdr.GetQosTid (); |
+ else if (hdr.IsBlockAckReq()) |
+ { |
+ CtrlBAckRequestHeader baReqHdr; |
+ packet->PeekHeader (baReqHdr); |
+ tid=baReqHdr.GetTidInfo(); |
+ } |
+ else if (hdr.IsBlockAck()) |
+ { |
+ CtrlBAckResponseHeader baRespHdr; |
+ packet->PeekHeader (baRespHdr); |
+ tid=baRespHdr.GetTidInfo(); |
+ } |
+ return tid; |
+} |
+ |
uint32_t |
MacLow::GetAckSize (void) const |
{ |
@@ -946,7 +1094,7 @@ |
preamble= WIFI_PREAMBLE_HT_MF; |
else |
preamble=WIFI_PREAMBLE_LONG; |
- return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble); |
+ return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble,0,0); |
} |
Time |
MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const |
@@ -964,7 +1112,7 @@ |
preamble= WIFI_PREAMBLE_HT_MF; |
else |
preamble=WIFI_PREAMBLE_LONG; |
- return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble); |
+ return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble,0,0); |
} |
Time |
MacLow::GetCtsDuration (Mac48Address to, WifiTxVector rtsTxVector) const |
@@ -981,7 +1129,7 @@ |
preamble= WIFI_PREAMBLE_HT_MF; |
else |
preamble=WIFI_PREAMBLE_LONG; |
- return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble); |
+ return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble,0,0); |
} |
uint32_t |
MacLow::GetCtsSize (void) const |
@@ -991,10 +1139,15 @@ |
return cts.GetSize () + 4; |
} |
uint32_t |
-MacLow::GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const |
+MacLow::GetSize (Ptr<const Packet> packet, const WifiMacHeader hdr) const |
{ |
+uint32_t size; |
WifiMacTrailer fcs; |
- return packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize (); |
+ if (m_ampdu) |
+ size = packet->GetSize (); |
+ else |
+ size= packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize (); |
+ return size; |
} |
WifiTxVector |
@@ -1064,7 +1217,7 @@ |
preamble=WIFI_PREAMBLE_LONG; |
if (params.MustSendRts ()) |
{ |
- txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble); |
+ txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble,0,0); |
txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector); |
txTime += Time (GetSifs () * 2); |
} |
@@ -1075,8 +1228,8 @@ |
preamble= WIFI_PREAMBLE_HT_MF; |
else |
preamble=WIFI_PREAMBLE_LONG; |
- uint32_t dataSize = GetSize (packet, hdr); |
- txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble); |
+ uint32_t dataSize = GetSize (packet, *hdr); |
+ txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble,0,0); |
if (params.MustWaitAck ()) |
{ |
txTime += GetSifs (); |
@@ -1103,7 +1256,7 @@ |
else |
preamble=WIFI_PREAMBLE_LONG; |
txTime += GetSifs (); |
- txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble); |
+ txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble,0,0); |
} |
return txTime; |
} |
@@ -1141,7 +1294,7 @@ |
cts.SetType (WIFI_MAC_CTL_CTS); |
WifiTxVector txVector=GetRtsTxVector (packet, &hdr); |
Time navCounterResetCtsMissedDelay = |
- m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble) + |
+ m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble,0,0) + |
Time (2 * GetSifs ()) + Time (2 * GetSlotTime ()); |
m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay, |
&MacLow::NavCounterResetCtsMissed, this, |
@@ -1230,10 +1383,63 @@ |
", mode=" << txVector.GetMode() << |
", duration=" << hdr->GetDuration () << |
", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec); |
- m_phy->SendPacket (packet, txVector.GetMode(), preamble, txVector); |
+ if (!m_ampdu) |
+ { |
+ m_phy->SendPacket (packet, txVector.GetMode(), preamble, txVector,0); |
+ } |
+ else |
+ { |
+ Ptr<Packet> newPacket; |
+ Ptr <const Packet> dequeuedPacket; |
+ WifiMacHeader newHdr; |
+ WifiMacTrailer fcs; |
+ uint32_t queueSize = m_aggregateQueue->GetSize (); |
+ bool last = false; |
+ uint8_t packetType; |
+ //Add packet tag |
+ AmpduTag ampdutag; |
+ ampdutag.SetAmpdu (true); |
+ Time delay=Seconds(0); |
+ for (;queueSize > 0; queueSize--) |
+ { |
+ dequeuedPacket = m_aggregateQueue->Dequeue(&newHdr); |
+ newPacket = dequeuedPacket->Copy(); |
+ newHdr.SetDuration (hdr->GetDuration ()); |
+ newPacket->AddHeader (newHdr); |
+ newPacket->AddTrailer (fcs); |
+ if (queueSize==1) |
+ { |
+ last=true; |
+ packetType=2; |
+ } |
+ m_mpduAggregator->AddHeaderAndPad (newPacket,last); |
+ |
+ ampdutag.SetNoOfMpdus(queueSize); |
+ newPacket->AddPacketTag(ampdutag); |
+ if (delay ==Seconds(0)) |
+ { |
+ NS_LOG_DEBUG("Sending MPDU as part of A-MPDU"); |
+ packetType=1; |
+ m_phy->SendPacket (newPacket, txVector.GetMode(), preamble, txVector,packetType); |
+ |
+ } |
+ else |
+ { |
+ m_mpduTxEnd=Simulator::Schedule (delay, &MacLow::SendPacket, this,newPacket, txVector.GetMode(), preamble, txVector,packetType); |
+ } |
+ delay=delay+m_phy->CalculateTxDuration (GetSize (newPacket,newHdr), txVector, preamble,packetType,1); |
+ preamble= WIFI_PREAMBLE_NONE; |
+ } |
+ } |
} |
void |
+MacLow::SendPacket(Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, WifiTxVector txVector, uint8_t packetType) |
+{ |
+ NS_LOG_DEBUG("Sending MPDU as part of A-MPDU"); |
+ m_phy->SendPacket (packet, txMode, preamble, txVector,packetType); |
+} |
+void |
MacLow::CtsTimeout (void) |
{ |
NS_LOG_FUNCTION (this); |
@@ -1242,6 +1448,15 @@ |
/// we should restart a new cts timeout now until the expected |
/// end of rx if there was a rx start before now. |
m_stationManager->ReportRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); |
+ uint32_t queueSize = m_aggregateQueue->GetSize (); |
+ //since transmission will be retried clear mac-low |
+ if (queueSize >= 1) |
+ { |
+ //remove any packets that we added to the aggregate queue |
+ NS_LOG_DEBUG("Flush aggregate queue"); |
+ m_aggregateQueue->Flush(); |
+ } |
+ m_sentMpdus = m_sentMpdus - queueSize; |
m_currentPacket = 0; |
MacLowTransmissionListener *listener = m_listener; |
m_listener = 0; |
@@ -1255,7 +1470,8 @@ |
/// \todo should check that there was no rx start before now. |
/// we should restart a new ack timeout now until the expected |
/// end of rx if there was a rx start before now. |
- m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); |
+ if (m_currentHdr.IsData() || m_currentHdr.IsQosData()) //only report data failures because some nmanagement frames require an Ack as AddBa, AssocReq,... |
+ m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); |
MacLowTransmissionListener *listener = m_listener; |
m_listener = 0; |
listener->MissedAck (); |
@@ -1342,14 +1558,14 @@ |
duration += GetSifs (); |
duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector); |
duration += GetSifs (); |
- duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), |
- dataTxVector, preamble); |
+ duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, m_currentHdr), |
+ dataTxVector, preamble,0,0); |
duration += GetSifs (); |
duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); |
} |
rts.SetDuration (duration); |
- Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble); |
+ Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble,0,0); |
Time timerDelay = txDuration + GetCtsTimeout (); |
NS_ASSERT (m_ctsTimeoutEvent.IsExpired ()); |
@@ -1377,7 +1593,7 @@ |
else |
preamble=WIFI_PREAMBLE_LONG; |
- Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble); |
+ Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, m_currentHdr), dataTxVector, preamble,0,0); |
if (m_txParams.MustWaitNormalAck ()) |
{ |
Time timerDelay = txDuration + GetAckTimeout (); |
@@ -1478,7 +1694,7 @@ |
{ |
duration += GetSifs (); |
duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), |
- dataTxVector, preamble); |
+ dataTxVector, preamble,0,0); |
if (m_txParams.MustWaitAck ()) |
{ |
duration += GetSifs (); |
@@ -1488,9 +1704,13 @@ |
} |
m_currentHdr.SetDuration (duration); |
- m_currentPacket->AddHeader (m_currentHdr); |
- WifiMacTrailer fcs; |
- m_currentPacket->AddTrailer (fcs); |
+ if (!m_ampdu) |
+ { |
+ m_currentPacket->AddHeader (m_currentHdr); |
+ WifiMacTrailer fcs; |
+ m_currentPacket->AddTrailer (fcs); |
+ } |
+ |
ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector,preamble); |
m_currentPacket = 0; |
@@ -1537,8 +1757,8 @@ |
{ |
WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr); |
duration += GetSifs (); |
- duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket,&m_currentHdr), |
- dataTxVector, preamble); |
+ duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket,m_currentHdr), |
+ dataTxVector, preamble,0,0); |
if (m_txParams.MustWaitBasicBlockAck ()) |
{ |
@@ -1559,7 +1779,7 @@ |
{ |
duration += GetSifs (); |
duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), |
- dataTxVector, preamble); |
+ dataTxVector, preamble,0,0); |
if (m_txParams.MustWaitCompressedBlockAck ()) |
{ |
duration += GetSifs (); |
@@ -1582,7 +1802,7 @@ |
ForwardDown (packet, &cts, ctsTxVector,preamble); |
- Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble); |
+ Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble,0,0); |
txDuration += GetSifs (); |
NS_ASSERT (m_sendDataEvent.IsExpired ()); |
@@ -1650,10 +1870,41 @@ |
StartDataTxTimers (dataTxVector); |
Time newDuration = Seconds (0); |
- newDuration += GetSifs (); |
- newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); |
- Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), |
- dataTxVector, preamble); |
+ |
+ if (m_txParams.MustWaitBasicBlockAck ()) |
+ { |
+ newDuration += GetSifs (); |
+ newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, BASIC_BLOCK_ACK); |
+ } |
+ else if (m_txParams.MustWaitCompressedBlockAck ()) |
+ { |
+ newDuration += GetSifs (); |
+ newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, COMPRESSED_BLOCK_ACK); |
+ } |
+ else if (m_txParams.MustWaitAck ()) |
+ { |
+ newDuration += GetSifs (); |
+ newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); |
+ } |
+ if (m_txParams.HasNextPacket ()) |
+ { |
+ newDuration += GetSifs (); |
+ newDuration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), |
+ dataTxVector, preamble,0,0); |
+ if (m_txParams.MustWaitCompressedBlockAck ()) |
+ { |
+ newDuration += GetSifs (); |
+ newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, COMPRESSED_BLOCK_ACK); |
+ } |
+ else if (m_txParams.MustWaitAck ()) |
+ { |
+ newDuration += GetSifs (); |
+ newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); |
+ } |
+ } |
+ |
+ Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, m_currentHdr), |
+ dataTxVector, preamble,0,0); |
duration -= txDuration; |
duration -= GetSifs (); |
@@ -1661,9 +1912,13 @@ |
NS_ASSERT (duration >= MicroSeconds (0)); |
m_currentHdr.SetDuration (duration); |
- m_currentPacket->AddHeader (m_currentHdr); |
- WifiMacTrailer fcs; |
- m_currentPacket->AddTrailer (fcs); |
+ if (!m_ampdu) |
+ { |
+ m_currentPacket->AddHeader (m_currentHdr); |
+ WifiMacTrailer fcs; |
+ m_currentPacket->AddTrailer (fcs); |
+ } |
+ |
ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector,preamble); |
m_currentPacket = 0; |
@@ -1732,6 +1987,49 @@ |
} |
bool |
+MacLow::IsInWindow (uint16_t seq, uint16_t winstart, uint16_t winsize) |
+{ |
+ return ((seq - winstart+ 4096) % 4096) < winsize; |
+} |
+ |
+bool |
+MacLow::ReceiveMpdu (Ptr<Packet> packet, WifiMacHeader hdr) |
+{ |
+ if (m_stationManager->HasHtSupported()) |
+ { |
+ Mac48Address originator =hdr.GetAddr2 (); |
+ uint8_t tid = hdr.GetQosTid (); |
+ uint16_t seqNumber = hdr.GetSequenceNumber (); |
+ AgreementsI it = m_bAckAgreements.find (std::make_pair (originator,tid)); |
+ if (it != m_bAckAgreements.end ()) |
+ { |
+ //Implement HT immediate Block Ack support for HT Delayed BlockAck is not added yet |
+ if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence(), seqNumber)) |
+ { |
+ StoreMpduIfNeeded(packet,hdr); |
+ if (!IsInWindow(hdr.GetSequenceNumber (),(*it).second.first.GetStartingSequence(), (*it).second.first.GetBufferSize())) |
+ { |
+ uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd()+ 4096) % 4096; |
+ if (delta > 1) |
+ { |
+ (*it).second.first.SetWinEnd (seqNumber); |
+ (*it).second.first.SetStartingSequence(((*it).second.first.GetWinEnd()-(*it).second.first.GetBufferSize() +1)%4096); |
+ RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequence(), originator, tid); |
+ } |
+ } |
+ RxCompleteBufferedPacketsUntilFirstLost (originator, tid);//forwards up packets starting from winstart and set winstart to last +1 |
+ (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1)%4096); |
+ } |
+ return true; |
+ } |
+ return false; |
+ } |
+ else |
+ return StoreMpduIfNeeded (packet,hdr); |
+} |
+ |
+ |
+bool |
MacLow::StoreMpduIfNeeded (Ptr<Packet> packet, WifiMacHeader hdr) |
{ |
AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ())); |
@@ -1768,6 +2066,8 @@ |
{ |
uint8_t tid = respHdr->GetTid (); |
BlockAckAgreement agreement (originator, tid); |
+ //if the STA is an HT STA then the Immediate Block Ack is HT-Immediate BlockAck since |
+ // no mixed networks is supported as off yet (i.e no backward compatibility) |
if (respHdr->IsImmediateBlockAck ()) |
{ |
agreement.SetImmediateBlockAck (); |
@@ -1780,6 +2080,7 @@ |
agreement.SetBufferSize (respHdr->GetBufferSize () + 1); |
agreement.SetTimeout (respHdr->GetTimeout ()); |
agreement.SetStartingSequence (startingSeq); |
+ agreement.SetWinEnd ((agreement.GetStartingSequence()+ agreement.GetBufferSize()-1)%4096); |
std::list<BufferedPacket> buffer (0); |
AgreementKey key (originator, respHdr->GetTid ()); |
@@ -1841,9 +2142,11 @@ |
{ |
while (last != i) |
{ |
+ NS_LOG_DEBUG ("forward up packet with seq " << (*i).second.GetSequenceNumber ()); |
m_rxCallback ((*last).first, &(*last).second); |
last++; |
} |
+ NS_LOG_DEBUG ("forward up packet with seq " << (*i).second.GetSequenceNumber ()); |
m_rxCallback ((*last).first, &(*last).second); |
last++; |
/* go to next packet */ |
@@ -1897,9 +2200,11 @@ |
{ |
while (lastComplete != i) |
{ |
+ NS_LOG_DEBUG ("forward up packet with seq " << (*i).second.GetSequenceNumber ()); |
m_rxCallback ((*lastComplete).first, &(*lastComplete).second); |
lastComplete++; |
} |
+ NS_LOG_DEBUG ("forward up packet with seq " << (*i).second.GetSequenceNumber ()); |
m_rxCallback ((*lastComplete).first, &(*lastComplete).second); |
lastComplete++; |
} |
@@ -1981,6 +2286,28 @@ |
ForwardDown (packet, &hdr, blockAckTxVector,preamble); |
m_currentPacket = 0; |
} |
+void |
+MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, |
+ Time duration, WifiMode blockAckReqTxMode) |
+{ |
+ NS_LOG_FUNCTION (this); |
+ CtrlBAckResponseHeader blockAck; |
+ uint16_t seqNumber; |
+ BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid)); |
+ NS_ASSERT (i != m_bAckCaches.end ()); |
+ seqNumber = (*i).second.GetWinStart (); |
+ |
+ bool immediate = true; |
+ AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid)); |
+ blockAck.SetStartingSequence (seqNumber); |
+ blockAck.SetTidInfo (tid); |
+ immediate = (*it).second.first.IsImmediateBlockAck (); |
+ blockAck.SetType (COMPRESSED_BLOCK_ACK); |
+ NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber); |
+ (*i).second.FillBlockAckBitmap (&blockAck); |
+ |
+ SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode); |
+} |
void |
MacLow::SendBlockAckAfterBlockAckRequest (const CtrlBAckRequestHeader reqHdr, Mac48Address originator, |
@@ -2011,11 +2338,25 @@ |
NS_ASSERT (i != m_bAckCaches.end ()); |
(*i).second.FillBlockAckBitmap (&blockAck); |
- /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac |
- * See 9.10.3 in IEEE8022.11e standard. |
- */ |
- RxCompleteBufferedPacketsWithSmallerSequence (reqHdr.GetStartingSequence (), originator, tid); |
- RxCompleteBufferedPacketsUntilFirstLost (originator, tid); |
+ if (!m_stationManager->HasHtSupported()) |
+ { |
+ /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac |
+ * See 9.10.3 in IEEE8022.11e standard. |
+ */ |
+ RxCompleteBufferedPacketsWithSmallerSequence (reqHdr.GetStartingSequence (), originator, tid); |
+ RxCompleteBufferedPacketsUntilFirstLost (originator, tid); |
+ } |
+ else |
+ { |
+ if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence(), reqHdr.GetStartingSequence ())) |
+ { |
+ (*it).second.first.SetStartingSequence(reqHdr.GetStartingSequence ()); |
+ (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1)%4096); |
+ RxCompleteBufferedPacketsWithSmallerSequence (reqHdr.GetStartingSequence (), originator, tid); |
+ RxCompleteBufferedPacketsUntilFirstLost (originator, tid);//forwards up packets starting from winstart and set winstart to last +1 |
+ (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1)%4096); |
+ } |
+ } |
} |
else |
{ |
@@ -2040,9 +2381,7 @@ |
Time timeout = MicroSeconds (1024 * agreement.GetTimeout ()); |
AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ()); |
- //std::map<AcIndex, MacLowTransmissionListener*>::iterator it = m_edcaListeners.find (ac); |
- //NS_ASSERT (it != m_edcaListeners.end ()); |
- |
+ |
agreement.m_inactivityEvent = Simulator::Schedule (timeout, |
&MacLowBlockAckEventListener::BlockAckInactivityTimeout, |
m_edcaListeners[ac], |
@@ -2057,4 +2396,298 @@ |
m_edcaListeners.insert (std::make_pair (ac, listener)); |
} |
+//mpdu aggregation happens here |
+ |
+Ptr<MpduAggregator> |
+MacLow::GetMpduAggregator (void) const |
+{ |
+ return m_mpduAggregator; |
+} |
+ |
+ |
+void |
+MacLow::SetMpduAggregator (Ptr<MpduAggregator> aggr) |
+{ |
+ m_mpduAggregator = aggr; |
+} |
+ |
+ |
+void |
+MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiMode txMode, WifiPreamble preamble) |
+{ |
+ AmpduTag ampdu; |
+ bool normalAck=false; |
+ bool ampduSubframe=false; |
+ uint16_t startingSeqNumber=5000; |
+ if (aggregatedPacket->RemovePacketTag(ampdu)) |
+ { |
+ ampduSubframe=true; |
+ MpduAggregator::DeaggregatedMpdus packets = MpduAggregator::Deaggregate (aggregatedPacket); |
+ MpduAggregator::DeaggregatedMpdusCI n = packets.begin (); |
+ |
+ WifiMacHeader firsthdr; |
+ (*n).first->PeekHeader(firsthdr); |
+ NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ()); |
+ NotifyNav ((*n).first,firsthdr, txMode, preamble); |
+ if (firsthdr.GetAddr1 () == m_self) |
+ { |
+ if (firsthdr.IsAck() || firsthdr.IsBlockAck() || firsthdr.IsBlockAckReq()) |
+ { |
+ ReceiveOk ((*n).first,rxSnr, txMode, preamble, ampduSubframe); |
+ } |
+ else if (firsthdr.IsData () || firsthdr.IsQosData()) |
+ { |
+ startingSeqNumber=firsthdr.GetSequenceNumber(); |
+ NS_LOG_DEBUG ("Deaagregate packet with sequence=" << startingSeqNumber); |
+ ReceiveOk ((*n).first,rxSnr, txMode, preamble, ampduSubframe); |
+ if (firsthdr.IsQosAck()) |
+ { |
+ NS_LOG_DEBUG ("Normal Ack"); |
+ normalAck=true; |
+ } |
+ } |
+ else |
+ NS_FATAL_ERROR ("Received A-MPDU with invalid MPDU type"); |
+ } |
+ |
+ if (normalAck && ampdu.GetNoOfMpdus() ==1) |
+ { |
+ //send block Ack |
+ if (firsthdr.IsBlockAckReq()) |
+ { |
+ NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack"); |
+ } |
+ uint8_t tid = firsthdr.GetQosTid (); |
+ AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid)); |
+ 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); |
+ NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ()); |
+ m_sendAckEvent = Simulator::Schedule (GetSifs (), |
+ &MacLow::SendBlockAckAfterAmpdu, this, |
+ firsthdr.GetQosTid(), |
+ firsthdr.GetAddr2 (), |
+ firsthdr.GetDuration (), |
+ txMode); |
+ } |
+ else |
+ { |
+ NS_LOG_DEBUG ("There's not a valid agreement for this block ack request."); |
+ } |
+ }// normal Ack |
+ }// !self |
+ else |
+ { |
+ |
+ ReceiveOk (aggregatedPacket,rxSnr, txMode, preamble, ampduSubframe); |
+ |
+ } |
+} |
+ |
+bool |
+MacLow::StopAggregation(Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint16_t size) const |
+{ |
+ if (peekedPacket == 0) |
+ return true; |
+ if (!m_mpduAggregator->CanBeAggregated (peekedPacket->GetSize()+peekedHdr.GetSize()+WIFI_MAC_FCS_LENGTH, aggregatedPacket, size)) |
+ return true; |
+ //since m_sendMpdus is not reset except when we get an ack or blockack this line doesn't allow more than x MPDUs to be transmitted |
+ if ((m_sentMpdus*(peekedPacket->GetSize()+peekedHdr.GetSize()+WIFI_MAC_FCS_LENGTH +6)) + size >= m_mpduAggregator->GetAmpduSize()) |
+ return true; |
+ return false; |
+} |
+ |
+ |
+Ptr<Packet> |
+MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr) |
+{ |
+ bool isAmpdu=false; |
+ Ptr<Packet> newPacket; |
+ WifiMacHeader peekedHdr; |
+ newPacket=packet->Copy(); |
+ peekedHdr=hdr; |
+ //missing hdr.IsAck() sincewe have no means of knowing the Tid of the Ack yet |
+ if (hdr.IsQosData()|| hdr.IsBlockAck()|| hdr.IsBlockAckReq()) |
+ { |
+ |
+ Time tstamp; |
+ uint8_t tid; |
+ tid=GetTid(packet,hdr); |
+ Ptr<WifiMacQueue> queue; |
+ AcIndex ac = QosUtilsMapTidToAc (tid); |
+ //since a blockack agreement always preceeds mpdu aggregation there should alway exist blockAck listener |
+ std::map<AcIndex, MacLowBlockAckEventListener*>::const_iterator listenerIt = m_edcaListeners.find(ac); |
+ NS_ASSERT (listenerIt != m_edcaListeners.end ()); |
+ queue = listenerIt->second->GetQueue(); |
+ |
+ if (!hdr.GetAddr1 ().IsBroadcast () && m_mpduAggregator!= 0) |
+ { |
+ //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager) |
+ if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1(), tid)) |
+ { |
+ |
+ /* here is performed mpdu aggregation */ |
+ /* MSDU aggregation happened in edca if the user asked for it so m_cuurentPacket may contains a normal packet or a A-MSDU*/ |
+ Ptr<Packet> currentAggregatedPacket = Create<Packet> (); |
+ peekedHdr=hdr; |
+ //get new ampdu duration |
+ Time duration = peekedHdr.GetDuration(); |
+ uint16_t startingSequenceNumber=0; //max sequence number id 4095 and it repeats, makes sure number of unacknowledged is < 64 |
+ uint16_t currentSequenceNumber=0; |
+ uint8_t qosPolicy=0; |
+ uint16_t blockAckSize=0; |
+ bool aggregated = false; |
+ int i=0; |
+ Ptr<Packet> aggPacket= newPacket->Copy(); |
+ |
+ if (!hdr.IsBlockAckReq()) |
+ { |
+ if (!hdr.IsBlockAck()) |
+ { |
+ startingSequenceNumber=peekedHdr.GetSequenceNumber(); |
+ peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); |
+ } |
+ newPacket->AddHeader (peekedHdr); |
+ WifiMacTrailer fcs; |
+ newPacket->AddTrailer (fcs); |
+ |
+ aggregated=m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket); |
+ if (aggregated) |
+ { |
+ NS_LOG_DEBUG ("Adding packet with Sequnce number " << peekedHdr.GetSequenceNumber()<<" to A-MPDU"); |
+ i++; |
+ m_sentMpdus++; |
+ m_aggregateQueue->Enqueue (aggPacket,peekedHdr); |
+ } |
+ } |
+ else if (hdr.IsBlockAckReq()) |
+ { |
+ blockAckSize=packet->GetSize()+hdr.GetSize()+WIFI_MAC_FCS_LENGTH; |
+ qosPolicy=3; //if the last subrame is block ack req then set ack policy of all frames to blockack |
+ CtrlBAckRequestHeader blockAckReq; |
+ packet->PeekHeader (blockAckReq); |
+ startingSequenceNumber = blockAckReq.GetStartingSequence (); |
+ } |
+ aggregated = false; |
+ bool retry = false; |
+ //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs |
+ Ptr<const Packet> peekedPacket= listenerIt->second->PeekNextPacketInBaQueue(peekedHdr); |
+ if (peekedPacket==0) |
+ { |
+ peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid, |
+ WifiMacHeader::ADDR1, |
+ hdr.GetAddr1 (),&tstamp); |
+ currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr); |
+ } |
+ else |
+ { |
+ retry = true; |
+ currentSequenceNumber = peekedHdr.GetSequenceNumber(); |
+ } |
+ while (currentSequenceNumber < (startingSequenceNumber + 63) && listenerIt->second->GetNOutstandingPackets(hdr.GetAddr1(), tid) < 63 &&!StopAggregation (peekedPacket,peekedHdr,currentAggregatedPacket, blockAckSize)) |
+ { |
+ //for now always send AMPDU with normal ACK |
+ if (retry==false) |
+ { |
+ currentSequenceNumber = listenerIt->second->GetNextSequenceNumberfor (&peekedHdr); |
+ peekedHdr.SetSequenceNumber (currentSequenceNumber); |
+ peekedHdr.SetFragmentNumber (0); |
+ peekedHdr.SetNoMoreFragments (); |
+ peekedHdr.SetNoRetry (); |
+ } |
+ if (qosPolicy==0) |
+ peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); |
+ else |
+ peekedHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK); |
+ newPacket=peekedPacket->Copy(); |
+ Ptr<Packet> aggPacket= newPacket->Copy(); |
+ |
+ newPacket->AddHeader (peekedHdr); |
+ WifiMacTrailer fcs; |
+ newPacket->AddTrailer (fcs); |
+ aggregated=m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket); |
+ if (aggregated) |
+ { |
+ m_aggregateQueue->Enqueue (aggPacket,peekedHdr); |
+ if (i==1 && hdr.IsQosData()) |
+ listenerIt->second->CompleteMpduTx(packet,hdr,tstamp); |
+ NS_LOG_DEBUG ("Adding packet with Sequnce number " << peekedHdr.GetSequenceNumber()<<" to A-MPDU"); |
+ i++; |
+ isAmpdu=true; |
+ m_sentMpdus++; |
+ listenerIt->second->CompleteMpduTx(peekedPacket,peekedHdr,tstamp); |
+ if (retry) |
+ listenerIt->second->RemoveFromBaQueue(peekedPacket); |
+ else |
+ queue->Remove (peekedPacket); |
+ newPacket=0; |
+ }//aggregated |
+ else |
+ break; |
+ if (retry==true) |
+ { |
+ peekedPacket= listenerIt->second->PeekNextPacketInBaQueue(peekedHdr); |
+ |
+ if (peekedPacket == 0) |
+ { |
+ //I reached the first packet that I added to this A-MPDU |
+ retry=false; |
+ peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid, |
+ WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp); |
+ } |
+ else |
+ currentSequenceNumber = peekedHdr.GetSequenceNumber(); |
+ } |
+ else |
+ { |
+ peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid, |
+ WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp); |
+ } |
+ |
+ }//while |
+ if (isAmpdu) |
+ { |
+ if (hdr.IsBlockAckReq()) |
+ { |
+ newPacket=packet->Copy(); |
+ peekedHdr=hdr; |
+ Ptr<Packet> aggPacket= newPacket->Copy(); |
+ m_aggregateQueue->Enqueue (aggPacket,peekedHdr); |
+ newPacket->AddHeader (peekedHdr); |
+ WifiMacTrailer fcs; |
+ newPacket->AddTrailer (fcs); |
+ m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket); |
+ } |
+ if (qosPolicy==0) |
+ { |
+ listenerIt->second->CompleteTransfer(hdr.GetAddr1 (),tid); |
+ } |
+ //Add packet tag |
+ AmpduTag ampdutag; |
+ ampdutag.SetAmpdu (true); |
+ ampdutag.SetNoOfMpdus(i); |
+ newPacket = currentAggregatedPacket; |
+ newPacket->AddPacketTag(ampdutag); |
+ currentAggregatedPacket = 0; |
+ NS_LOG_DEBUG ("tx unicast A-MPDU"); |
+ listenerIt->second->SetAmpdu(true); |
+ } |
+ else |
+ { |
+ uint32_t queueSize = m_aggregateQueue->GetSize (); |
+ NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more |
+ if (queueSize >= 1) |
+ { |
+ //remove any packets that we added to the aggregate queue |
+ NS_LOG_DEBUG("Flush aggregate queue"); |
+ m_aggregateQueue->Flush(); |
+ } |
+ } |
+ }//if block ack |
+ }//if aggregate |
+ }//if appropoaite header |
+ return newPacket; |
+} |
} // namespace ns3 |