--- a/src/wifi/model/mac-low.cc Wed Jan 28 06:34:11 2015 -0800
+++ b/src/wifi/model/mac-low.cc Wed Jan 28 10:11:32 2015 -0800
@@ -34,6 +34,10 @@
#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"
+#include "mpdu-aggregator.h"
#undef NS_LOG_APPEND_CONTEXT
#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
@@ -50,8 +54,7 @@
{
}
void
-MacLowTransmissionListener::GotBlockAck (const CtrlBAckResponseHeader *blockAck,
- Mac48Address source)
+MacLowTransmissionListener::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source, WifiMode mode)
{
}
void
@@ -72,6 +75,46 @@
{
}
+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 &header, Mac48Address recipient, uint8_t tid, Time *timestamp)
+{
+ return 0;
+}
+void
+MacLowBlockAckEventListener::RemoveFromBaQueue (uint8_t tid, Mac48Address recipient, uint16_t seqnumber)
+{
+}
+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),
@@ -304,15 +347,20 @@
m_sendDataEvent (),
m_waitSifsEvent (),
m_endTxNoAckEvent (),
+ m_mpduAggregator (0),
m_currentPacket (0),
m_listener (0),
m_phyMacLowListener (0),
- m_ctsToSelfSupported (false)
+ m_ctsToSelfSupported (false),
+ m_receivedAtLeastOneMpdu (false)
{
NS_LOG_FUNCTION (this);
m_lastNavDuration = Seconds (0);
m_lastNavStart = Seconds (0);
m_promisc = false;
+ m_ampdu = false;
+ m_sentMpdus = 0;
+ m_aggregateQueue = CreateObject<WifiMacQueue> ();
}
MacLow::~MacLow ()
@@ -361,6 +409,10 @@
delete m_phyMacLowListener;
m_phyMacLowListener = 0;
}
+ m_mpduAggregator = 0;
+ m_sentMpdus = 0;
+ m_aggregateQueue = 0;
+ m_ampdu = false;
}
void
@@ -439,7 +491,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);
}
@@ -594,6 +646,22 @@
m_dcfListeners.push_back (listener);
}
+bool
+MacLow::IsAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
+{
+ uint32_t size, actualSize;
+ WifiMacTrailer fcs;
+ size = packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize ();
+ Ptr<Packet> 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,
@@ -616,7 +684,6 @@
* QapScheduler has taken access to the channel from
* one of the Edca of the QAP.
*/
- m_currentPacket = packet->Copy ();
m_currentHdr = *hdr;
CancelAllEvents ();
m_listener = listener;
@@ -624,9 +691,26 @@
//NS_ASSERT (m_phy->IsStateIdle ());
+ if(m_aggregateQueue->GetSize () == 0)
+ {
+ m_currentPacket = packet->Copy ();
+ m_ampdu = IsAmpdu (m_currentPacket, m_currentHdr);
+ }
+ else
+ {
+ /*m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
+ *In that case, we transmit the same A-MPDU as previously.
+ */
+ m_sentMpdus = m_aggregateQueue->GetSize ();
+ m_ampdu = true;
+ }
+
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 ();
@@ -657,7 +741,33 @@
{
NS_LOG_FUNCTION (this << packet << rxSnr);
NS_LOG_DEBUG ("rx failed ");
- if (m_txParams.MustWaitFastAck ())
+ AmpduTag ampdu;
+ Ptr<Packet> pkt = packet->Copy();
+ bool isInAmpdu = pkt->RemovePacketTag(ampdu);
+
+ if(isInAmpdu && m_receivedAtLeastOneMpdu && (ampdu.GetNoOfMpdus() == 1))
+ {
+ MpduAggregator::DeaggregatedMpdus packets = MpduAggregator::Deaggregate (pkt);
+ MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
+ WifiMacHeader hdr;
+ (*n).first->PeekHeader(hdr);
+ if(hdr.IsQosData())
+ {
+ NS_LOG_DEBUG ("last a-mpdu subframe detected/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
+ m_sendAckEvent = Simulator::Schedule (GetSifs (),
+ &MacLow::SendBlockAckAfterAmpdu, this,
+ hdr.GetQosTid(),
+ hdr.GetAddr2 (),
+ hdr.GetDuration (),
+ m_currentMode);
+ }
+ else if (hdr.IsBlockAckReq())
+ {
+ NS_LOG_DEBUG("last a-mpdu subframe is BAR");
+ }
+ m_receivedAtLeastOneMpdu = false;
+ }
+ else if (m_txParams.MustWaitFastAck ())
{
NS_ASSERT (m_fastAckFailedTimeoutEvent.IsExpired ());
m_fastAckFailedTimeoutEvent = Simulator::Schedule (GetSifs (),
@@ -698,7 +808,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.
@@ -720,23 +830,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 ()
@@ -744,6 +861,10 @@
&& m_ctsTimeoutEvent.IsRunning ()
&& m_currentPacket != 0)
{
+ if (ampduSubframe)
+ {
+ NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
+ }
NS_LOG_DEBUG ("receive cts from=" << m_currentHdr.GetAddr1 ());
SnrTag tag;
packet->RemovePacketTag (tag);
@@ -776,6 +897,7 @@
rxSnr, txMode);
m_stationManager->ReportDataOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
rxSnr, txMode, tag.Get ());
+
bool gotAck = false;
if (m_txParams.MustWaitNormalAck ()
&& m_normalAckTimeoutEvent.IsRunning ())
@@ -809,7 +931,10 @@
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;
+ m_ampdu = false;
}
else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
{
@@ -843,6 +968,7 @@
{
NS_FATAL_ERROR ("Delayed block ack not supported.");
}
+ m_receivedAtLeastOneMpdu = false;
}
else
{
@@ -857,22 +983,24 @@
else if (hdr.IsCtl ())
{
NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
+ m_receivedAtLeastOneMpdu = false;
}
else if (hdr.GetAddr1 () == m_self)
{
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 IEEE 802.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 ())
+ QoS Control field of the QoS data frame. */;
+ if (hdr.IsQosAck () && !ampduSubframe)
{
+ NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
+
RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequence (),
hdr.GetAddr2 (), hdr.GetQosTid ());
RxCompleteBufferedPacketsUntilFirstLost (hdr.GetAddr2 (), hdr.GetQosTid ());
@@ -883,6 +1011,7 @@
hdr.GetDuration (),
txMode,
rxSnr);
+ m_receivedAtLeastOneMpdu = false;
}
else if (hdr.IsQosBlockAck ())
{
@@ -908,31 +1037,53 @@
}
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 ());
+ m_receivedAtLeastOneMpdu = false;
+ goto rxPacket;
+ }
+ else
+ {
+ // DROP
+ }
}
}
else if (m_promisc)
@@ -955,6 +1106,27 @@
return;
}
+uint8_t
+MacLow::GetTid (Ptr<const Packet> packet, const WifiMacHeader hdr) const
+{
+ uint8_t tid = 0;
+ 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
{
@@ -1004,7 +1176,7 @@
preamble= WIFI_PREAMBLE_HT_MF;
else
preamble=WIFI_PREAMBLE_LONG;
- return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency());
+ return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency(), 0, 0);
}
Time
MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const
@@ -1022,7 +1194,7 @@
preamble= WIFI_PREAMBLE_HT_MF;
else
preamble=WIFI_PREAMBLE_LONG;
- return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble, m_phy->GetFrequency());
+ return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble, m_phy->GetFrequency(), 0, 0);
}
Time
MacLow::GetCtsDuration (Mac48Address to, WifiTxVector rtsTxVector) const
@@ -1039,7 +1211,7 @@
preamble= WIFI_PREAMBLE_HT_MF;
else
preamble=WIFI_PREAMBLE_LONG;
- return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency());
+ return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
}
uint32_t
MacLow::GetCtsSize (void) const
@@ -1051,8 +1223,13 @@
uint32_t
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
@@ -1127,7 +1304,7 @@
{
preamble = WIFI_PREAMBLE_LONG;
}
- txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency());
+ txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector);
txTime += Time (GetSifs () * 2);
}
@@ -1140,7 +1317,7 @@
else
preamble=WIFI_PREAMBLE_LONG;
uint32_t dataSize = GetSize (packet, hdr);
- txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency());
+ txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
if (params.MustWaitAck ())
{
txTime += GetSifs ();
@@ -1167,7 +1344,7 @@
else
preamble=WIFI_PREAMBLE_LONG;
txTime += GetSifs ();
- txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency());
+ txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
}
return txTime;
}
@@ -1205,7 +1382,7 @@
cts.SetType (WIFI_MAC_CTL_CTS);
WifiTxVector txVector=GetRtsTxVector (packet, &hdr);
Time navCounterResetCtsMissedDelay =
- m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble, m_phy->GetFrequency()) +
+ m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble, m_phy->GetFrequency(), 0, 0) +
Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
&MacLow::NavCounterResetCtsMissed, this,
@@ -1294,7 +1471,61 @@
", mode=" << txVector.GetMode() <<
", duration=" << hdr->GetDuration () <<
", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
- m_phy->SendPacket (packet, txVector, preamble);
+ if (!m_ampdu || hdr->IsRts ())
+ {
+ m_phy->SendPacket (packet, txVector, preamble, 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 = 0;
+ //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, preamble, packetType);
+ }
+ else
+ {
+ Simulator::Schedule (delay, &MacLow::SendPacket, this, newPacket, txVector, preamble, packetType);
+ }
+ if(queueSize > 1)
+ delay = delay + m_phy->CalculateTxDuration (GetSize (newPacket, &newHdr), txVector, preamble, m_phy->GetFrequency(), packetType, 0);
+ preamble = WIFI_PREAMBLE_NONE;
+ }
+ }
+}
+
+void
+MacLow::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType)
+{
+ NS_LOG_DEBUG("Sending MPDU as part of A-MPDU");
+ m_phy->SendPacket (packet, txVector, preamble, packetType);
}
void
@@ -1306,9 +1537,14 @@
/// 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);
- m_currentPacket = 0;
+ if(m_sentMpdus == 0)
+ {
+ m_currentPacket = 0;
+ }
MacLowTransmissionListener *listener = m_listener;
m_listener = 0;
+ m_sentMpdus = 0;
+ m_ampdu = false;
listener->MissedCts ();
}
void
@@ -1322,6 +1558,8 @@
m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
MacLowTransmissionListener *listener = m_listener;
m_listener = 0;
+ m_sentMpdus = 0;
+ m_ampdu = false;
listener->MissedAck ();
}
void
@@ -1350,6 +1588,8 @@
m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
MacLowTransmissionListener *listener = m_listener;
m_listener = 0;
+ m_sentMpdus = 0;
+ m_ampdu = false;
listener->MissedBlockAck ();
}
void
@@ -1407,13 +1647,36 @@
duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
duration += GetSifs ();
duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr),
- dataTxVector, preamble, m_phy->GetFrequency());
+ dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
duration += GetSifs ();
- duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
+ if (m_txParams.MustWaitBasicBlockAck ())
+ {
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
+ }
+ else if (m_txParams.MustWaitCompressedBlockAck ())
+ {
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
+ }
+ else if (m_txParams.MustWaitAck ())
+ {
+ duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
+ }
+ if (m_txParams.HasNextPacket ())
+ {
+ duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (),
+ dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
+ if (m_txParams.MustWaitAck ())
+ {
+ duration += GetSifs ();
+ duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
+ }
+ }
}
rts.SetDuration (duration);
- Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency());
+ Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
Time timerDelay = txDuration + GetCtsTimeout ();
NS_ASSERT (m_ctsTimeoutEvent.IsExpired ());
@@ -1441,7 +1704,7 @@
else
preamble=WIFI_PREAMBLE_LONG;
- Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency());
+ Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
if (m_txParams.MustWaitNormalAck ())
{
Time timerDelay = txDuration + GetAckTimeout ();
@@ -1528,12 +1791,14 @@
if (m_txParams.MustWaitBasicBlockAck ())
{
duration += GetSifs ();
- duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, BASIC_BLOCK_ACK);
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
}
else if (m_txParams.MustWaitCompressedBlockAck ())
{
duration += GetSifs ();
- duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, COMPRESSED_BLOCK_ACK);
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
}
else if (m_txParams.MustWaitAck ())
{
@@ -1544,7 +1809,7 @@
{
duration += GetSifs ();
duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (),
- dataTxVector, preamble, m_phy->GetFrequency());
+ dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
if (m_txParams.MustWaitAck ())
{
duration += GetSifs ();
@@ -1554,9 +1819,12 @@
}
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;
@@ -1604,17 +1872,19 @@
WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr);
duration += GetSifs ();
duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket,&m_currentHdr),
- dataTxVector, preamble, m_phy->GetFrequency());
+ dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
if (m_txParams.MustWaitBasicBlockAck ())
{
duration += GetSifs ();
- duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, BASIC_BLOCK_ACK);
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
}
else if (m_txParams.MustWaitCompressedBlockAck ())
{
duration += GetSifs ();
- duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, COMPRESSED_BLOCK_ACK);
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
}
else if (m_txParams.MustWaitAck ())
{
@@ -1625,11 +1895,12 @@
{
duration += GetSifs ();
duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (),
- dataTxVector, preamble, m_phy->GetFrequency());
+ dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
if (m_txParams.MustWaitCompressedBlockAck ())
{
duration += GetSifs ();
- duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), dataTxVector, COMPRESSED_BLOCK_ACK);
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
}
else if (m_txParams.MustWaitAck ())
{
@@ -1648,7 +1919,7 @@
ForwardDown (packet, &cts, ctsTxVector,preamble);
- Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency());
+ Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
txDuration += GetSifs ();
NS_ASSERT (m_sendDataEvent.IsExpired ());
@@ -1716,10 +1987,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, m_phy->GetFrequency());
+ if (m_txParams.MustWaitBasicBlockAck ())
+ {
+ newDuration += GetSifs ();
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
+ }
+ else if (m_txParams.MustWaitCompressedBlockAck ())
+ {
+ newDuration += GetSifs ();
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, 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, m_phy->GetFrequency(), 0, 0);
+ if (m_txParams.MustWaitCompressedBlockAck ())
+ {
+ newDuration += GetSifs ();
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+ newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, 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, m_phy->GetFrequency(), 0, 0);
duration -= txDuration;
duration -= GetSifs ();
@@ -1727,9 +2029,12 @@
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;
@@ -1798,6 +2103,53 @@
}
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 = 0;
+ if (hdr.IsQosData ())
+ 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 Block Ack 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);
+ int16_t winEnd = (*it).second.first.GetWinEnd ();
+ int16_t bufferSize = (*it).second.first.GetBufferSize ();
+ uint16_t sum = ((uint16_t)(std::abs(winEnd - bufferSize + 1))) % 4096;
+ (*it).second.first.SetStartingSequence (sum);
+ 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 ()));
@@ -1822,7 +2174,6 @@
BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
NS_ASSERT (j != m_bAckCaches.end ());
(*j).second.UpdateWithMpdu (&hdr);
-
return true;
}
return false;
@@ -1894,8 +2245,10 @@
{
uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
uint16_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
- uint16_t guard = (*it).second.second.begin ()->second.GetSequenceControl () & 0xfff0;
BufferedPacketI last = (*it).second.second.begin ();
+ uint16_t guard;
+ if (last != (*it).second.second.end ())
+ guard = (*it).second.second.begin ()->second.GetSequenceControl () & 0xfff0;
BufferedPacketI i = (*it).second.second.begin ();
for (; i != (*it).second.second.end ()
@@ -1977,7 +2330,6 @@
(*it).second.second.erase ((*it).second.second.begin (), lastComplete);
}
}
-
void
MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
Time duration, WifiMode blockAckReqTxMode)
@@ -1994,11 +2346,7 @@
hdr.SetNoRetry ();
hdr.SetNoMoreFragments ();
- WifiTxVector blockAckTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
- WifiTxVector blockAckReqTxVector;
- blockAckReqTxVector.SetMode(blockAckReqTxMode);
- blockAckReqTxVector.SetNss(1);
- blockAckReqTxVector.SetStbc(false);
+ WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
m_currentPacket = packet;
m_currentHdr = hdr;
@@ -2029,7 +2377,7 @@
if (!immediate)
{
- StartDataTxTimers (blockAckTxVector);
+ StartDataTxTimers (blockAckReqTxVector);
}
NS_ASSERT (duration >= MicroSeconds (0));
@@ -2039,14 +2387,35 @@
packet->AddHeader (hdr);
WifiMacTrailer fcs;
packet->AddTrailer (fcs);
- WifiPreamble preamble;
- if (blockAckTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
+ WifiPreamble preamble;
+ if (blockAckReqTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
preamble= WIFI_PREAMBLE_HT_MF;
else
preamble=WIFI_PREAMBLE_LONG;
- ForwardDown (packet, &hdr, blockAckTxVector,preamble);
+ ForwardDown (packet, &hdr, blockAckReqTxVector, 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 = 0;
+ 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,
@@ -2054,7 +2423,7 @@
{
NS_LOG_FUNCTION (this);
CtrlBAckResponseHeader blockAck;
- uint8_t tid;
+ uint8_t tid = 0;
bool immediate = false;
if (!reqHdr.IsMultiTid ())
{
@@ -2076,12 +2445,27 @@
BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
NS_ASSERT (i != m_bAckCaches.end ());
(*i).second.FillBlockAckBitmap (&blockAck);
+ NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
- /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
- * See 9.10.3 in IEEE 802.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 IEEE 802.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);
+ (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1) % 4096);
+ }
+ }
}
else
{
@@ -2104,7 +2488,6 @@
NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
agreement.m_inactivityEvent.Cancel ();
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 ());
@@ -2123,4 +2506,311 @@
m_edcaListeners.insert (std::make_pair (ac, listener));
}
+void
+MacLow::SetMpduAggregator (Ptr<MpduAggregator> aggregator)
+{
+ m_mpduAggregator = aggregator;
+}
+
+void
+MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiMode txMode, WifiPreamble preamble)
+{
+ m_currentMode = txMode;
+ AmpduTag ampdu;
+ bool normalAck = false;
+ bool ampduSubframe = false;
+ 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)
+ {
+ m_receivedAtLeastOneMpdu = true;
+ if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
+ ReceiveOk ((*n).first, rxSnr, txMode, preamble, ampduSubframe);
+ else if (firsthdr.IsData () || firsthdr.IsQosData ())
+ {
+ NS_LOG_DEBUG ("Deaagregate packet with sequence=" << firsthdr.GetSequenceNumber ());
+ 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 first 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 IEEE 802.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.");
+ }
+ m_receivedAtLeastOneMpdu = false;
+ }
+ }
+ else
+ {
+ ReceiveOk (aggregatedPacket,rxSnr, txMode, preamble, ampduSubframe);
+ }
+}
+
+bool
+MacLow::StopAggregation(Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint16_t size) const
+{
+ WifiPreamble preamble;
+ WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr);
+ if (m_phy->GetGreenfield () && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
+ preamble = WIFI_PREAMBLE_HT_GF;
+ else
+ preamble = WIFI_PREAMBLE_HT_MF;
+
+ if (peekedPacket == 0)
+ return true;
+
+ //An HT STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime (10 milliseconds)
+ if(m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () +WIFI_MAC_FCS_LENGTH,dataTxVector, preamble, m_phy->GetFrequency(), 0, 0) > MilliSeconds(10))
+ return true;
+
+ if (!m_mpduAggregator->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, size))
+ return true;
+
+ return false;
+}
+
+Ptr<Packet>
+MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
+{
+ NS_ASSERT (m_aggregateQueue->GetSize () == 0);
+ bool isAmpdu = false;
+ Ptr<Packet> newPacket;
+ WifiMacHeader peekedHdr;
+ newPacket = packet->Copy();
+ //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
+ if (hdr.IsQosData() || hdr.IsBlockAck()|| hdr.IsBlockAckReq())
+ {
+ Time tstamp;
+ uint8_t tid = GetTid (packet, hdr);
+ Ptr<WifiMacQueue> queue;
+ AcIndex ac = QosUtilsMapTidToAc (tid);
+ //since a blockack agreement always preceeds mpdu aggregation there should always 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_currentPacket may contains a normal packet or a A-MSDU*/
+ Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
+ peekedHdr = hdr;
+ uint16_t startingSequenceNumber = 0;
+ 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);
+ }
+ currentSequenceNumber = peekedHdr.GetSequenceNumber();
+ newPacket->AddHeader (peekedHdr);
+ WifiMacTrailer fcs;
+ newPacket->AddTrailer (fcs);
+
+ aggregated=m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket);
+
+ if (aggregated)
+ {
+ NS_LOG_DEBUG ("Adding packet with Sequence 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, peekedHdr.GetAddr1 (), tid, &tstamp);
+ 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 (IsInWindow (currentSequenceNumber, startingSequenceNumber, 64) && !StopAggregation (peekedPacket, peekedHdr, currentAggregatedPacket, blockAckSize))
+//&& listenerIt->second->GetNOutstandingPackets (hdr.GetAddr1(), tid) < 63
+ {
+ //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 Sequence number " << peekedHdr.GetSequenceNumber()<<" to A-MPDU");
+ i++;
+ isAmpdu = true;
+ m_sentMpdus++;
+ listenerIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
+ if (retry)
+ listenerIt->second->RemoveFromBaQueue(tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
+ else
+ queue->Remove (peekedPacket);
+ newPacket = 0;
+ }
+ else
+ break;
+ if (retry == true)
+ {
+ peekedPacket = listenerIt->second->PeekNextPacketInBaQueue(peekedHdr, hdr.GetAddr1(), tid, &tstamp);
+ 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);
+ if (peekedPacket != 0)
+ {
+ //find what will the sequence number be so that we don't send more than 64 packets apart
+ currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
+ }
+ }
+ else
+ currentSequenceNumber = peekedHdr.GetSequenceNumber();
+ }
+ else
+ {
+ peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
+ WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
+ if (peekedPacket != 0)
+ {
+ //find what will the sequence number be so that we don't send more than 64 packets apart
+ currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
+ }
+ }
+ }
+ 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
+ FlushAggregateQueue ();
+ }
+ }
+ }
+ }
+ }
+ return newPacket;
+}
+
+void
+MacLow::FlushAggregateQueue (void)
+{
+ NS_LOG_DEBUG("Flush aggregate queue");
+ m_aggregateQueue->Flush ();
+}
+
} // namespace ns3