wifi: (fixes #1909) Implement timeouts according to the standard
This commit is contained in:
@@ -36,6 +36,7 @@ Bugs fixed
|
||||
- Bug 2636 - Add to doxygen a list of all registered TypeIds
|
||||
- Bug 2928 - BlockAckManager::NeedBarRetransmission returns "true" infinitely
|
||||
- Bug 2985 - PhyTxEnd tracecallback not implemented
|
||||
- Bug 1909, Issue #41 - wifi: Implementation of ACK timeout
|
||||
- Issue #22 - wifi: Station long retry counter is incremented twice if BlockAck was not received
|
||||
- Issue #40 - IdealWifiManager not working if stations are moving
|
||||
- Issue #84 - Wi-Fi removing wrong header due to copy-paste error
|
||||
|
||||
@@ -48,8 +48,8 @@ cpp_examples = [
|
||||
("wifi-he-network --simulationTime=0.3 --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=745", "True", "True"),
|
||||
("wifi-he-network --simulationTime=0.25 --frequency=2.4 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=238", "True", "True"),
|
||||
("wifi-he-network --simulationTime=0.3 --frequency=2.4 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=223", "True", "True"),
|
||||
("wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=0 --nMpdus=32 --minExpectedThroughput=50 --maxExpectedThroughput=51", "True", "True"),
|
||||
("wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=1 --nMpdus=32 --minExpectedThroughput=57 --maxExpectedThroughput=58", "True", "True"),
|
||||
("wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=0 --nMpdus=32 --minExpectedThroughput=59 --maxExpectedThroughput=60", "True", "True"),
|
||||
("wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=1 --nMpdus=32 --minExpectedThroughput=55 --maxExpectedThroughput=56", "True", "True"),
|
||||
("wifi-mixed-network --simulationTime=1", "True", "True"),
|
||||
("wifi-aggregation --simulationTime=1 --verifyResults=1", "True", "True"),
|
||||
("wifi-txop-aggregation --simulationTime=1 --verifyResults=1", "True", "True"),
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -47,6 +47,11 @@
|
||||
#undef NS_LOG_APPEND_CONTEXT
|
||||
#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
|
||||
|
||||
// Time (in nanoseconds) to be added to the PSDU duration to yield the duration
|
||||
// of the timer that is started when the PHY indicates the start of the reception
|
||||
// of a frame and we are waiting for a response.
|
||||
#define PSDU_DURATION_SAFEGUARD 400
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("MacLow");
|
||||
@@ -248,6 +253,7 @@ void
|
||||
MacLow::SetPhy (const Ptr<WifiPhy> phy)
|
||||
{
|
||||
m_phy = phy;
|
||||
m_phy->TraceConnectWithoutContext ("PhyRxPayloadBegin", MakeCallback (&MacLow::RxStartIndication, this));
|
||||
m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::DeaggregateAmpduAndReceive, this));
|
||||
m_phy->SetReceiveErrorCallback (MakeCallback (&MacLow::ReceiveError, this));
|
||||
SetupPhyMacLowListener (phy);
|
||||
@@ -262,6 +268,7 @@ MacLow::GetPhy (void) const
|
||||
void
|
||||
MacLow::ResetPhy (void)
|
||||
{
|
||||
m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin", MakeCallback (&MacLow::RxStartIndication, this));
|
||||
m_phy->SetReceiveOkCallback (MakeNullCallback<void, Ptr<WifiPsdu>, double, WifiTxVector, std::vector<bool>> ());
|
||||
m_phy->SetReceiveErrorCallback (MakeNullCallback<void, Ptr<WifiPsdu>> ());
|
||||
RemovePhyMacLowListener (m_phy);
|
||||
@@ -715,6 +722,48 @@ MacLow::IsWithinSizeAndTimeLimits (uint32_t mpduSize, Mac48Address receiver, uin
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MacLow::RxStartIndication (WifiTxVector txVector, Time psduDuration)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_DEBUG ("PSDU reception started for " << psduDuration.ToDouble (Time::US)
|
||||
<< " us (txVector: " << txVector << ")");
|
||||
NS_ASSERT (psduDuration.IsStrictlyPositive ());
|
||||
|
||||
if (m_normalAckTimeoutEvent.IsRunning ())
|
||||
{
|
||||
// we are waiting for a Normal Ack and something arrived
|
||||
NS_LOG_DEBUG ("Rescheduling Normal Ack timeout");
|
||||
m_normalAckTimeoutEvent.Cancel ();
|
||||
NotifyAckTimeoutResetNow ();
|
||||
m_normalAckTimeoutEvent = Simulator::Schedule (psduDuration + NanoSeconds (PSDU_DURATION_SAFEGUARD),
|
||||
&MacLow::NormalAckTimeout, this);
|
||||
}
|
||||
else if (m_blockAckTimeoutEvent.IsRunning ())
|
||||
{
|
||||
// we are waiting for a BlockAck and something arrived
|
||||
NS_LOG_DEBUG ("Rescheduling Block Ack timeout");
|
||||
m_blockAckTimeoutEvent.Cancel ();
|
||||
NotifyAckTimeoutResetNow ();
|
||||
m_blockAckTimeoutEvent = Simulator::Schedule (psduDuration + NanoSeconds (PSDU_DURATION_SAFEGUARD),
|
||||
&MacLow::BlockAckTimeout, this);
|
||||
}
|
||||
else if (m_ctsTimeoutEvent.IsRunning ())
|
||||
{
|
||||
// we are waiting for a CTS and something arrived
|
||||
NS_LOG_DEBUG ("Rescheduling CTS timeout");
|
||||
m_ctsTimeoutEvent.Cancel ();
|
||||
NotifyCtsTimeoutResetNow ();
|
||||
m_ctsTimeoutEvent = Simulator::Schedule (psduDuration + NanoSeconds (PSDU_DURATION_SAFEGUARD),
|
||||
&MacLow::CtsTimeout, this);
|
||||
}
|
||||
else if (m_navCounterResetCtsMissed.IsRunning ())
|
||||
{
|
||||
NS_LOG_DEBUG ("Cannot reset NAV");
|
||||
m_navCounterResetCtsMissed.Cancel ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacLow::ReceiveError (Ptr<WifiPsdu> psdu)
|
||||
{
|
||||
@@ -874,18 +923,11 @@ MacLow::ReceiveOk (Ptr<WifiMacQueueItem> mpdu, double rxSnr, WifiTxVector txVect
|
||||
rxSnr, txVector.GetMode (), tag.Get (),
|
||||
m_currentPacket->GetSize ());
|
||||
}
|
||||
bool gotAck = false;
|
||||
if (m_txParams.MustWaitNormalAck ()
|
||||
&& m_normalAckTimeoutEvent.IsRunning ())
|
||||
{
|
||||
m_normalAckTimeoutEvent.Cancel ();
|
||||
NotifyAckTimeoutResetNow ();
|
||||
gotAck = true;
|
||||
}
|
||||
if (gotAck)
|
||||
{
|
||||
m_currentTxop->GotAck ();
|
||||
}
|
||||
// cancel the Normal Ack timer
|
||||
m_normalAckTimeoutEvent.Cancel ();
|
||||
NotifyAckTimeoutResetNow ();
|
||||
m_currentTxop->GotAck ();
|
||||
|
||||
if (m_txParams.HasNextPacket ())
|
||||
{
|
||||
if (m_stationManager->GetRifsPermitted ())
|
||||
@@ -1565,20 +1607,21 @@ MacLow::NotifyNav (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
/**
|
||||
* A STA that used information from an RTS frame as the most recent basis to update its NAV setting
|
||||
* is permitted to reset its NAV if no PHY-RXSTART.indication is detected from the PHY during a
|
||||
* period with a duration of (2 * aSIFSTime) + (CTS_Time) + (2 * aSlotTime) starting at the
|
||||
* PHY-RXEND.indication corresponding to the detection of the RTS frame. The “CTS_Time” shall
|
||||
* be calculated using the length of the CTS frame and the data rate at which the RTS frame
|
||||
* used for the most recent NAV update was received.
|
||||
* period with a duration of (2 * aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 * aSlotTime)
|
||||
* starting at the PHY-RXEND.indication corresponding to the detection of the RTS frame. The
|
||||
* “CTS_Time” shall be calculated using the length of the CTS frame and the data rate at which
|
||||
* the RTS frame used for the most recent NAV update was received.
|
||||
*/
|
||||
WifiMacHeader cts;
|
||||
cts.SetType (WIFI_MAC_CTL_CTS);
|
||||
WifiTxVector txVector = GetRtsTxVector (Create<const WifiMacQueueItem> (packet, hdr));
|
||||
Time navCounterResetCtsMissedDelay =
|
||||
m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, m_phy->GetFrequency ()) +
|
||||
Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
|
||||
Time (2 * GetSifs ()) + Time (2 * GetSlotTime ()) +
|
||||
m_phy->CalculatePhyPreambleAndHeaderDuration (txVector);
|
||||
m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
|
||||
&MacLow::NavCounterResetCtsMissed, this,
|
||||
Simulator::Now ());
|
||||
&MacLow::DoNavResetNow, this,
|
||||
Seconds (0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1818,8 +1861,11 @@ MacLow::SendRtsForPacket (void)
|
||||
rts.SetDuration (duration);
|
||||
|
||||
Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
|
||||
Time timerDelay = txDuration + GetCtsTimeout ();
|
||||
|
||||
// After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
|
||||
// a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
|
||||
// aRxPHYStartDelay equals the time to transmit the PHY header.
|
||||
Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
|
||||
+ m_phy->CalculatePhyPreambleAndHeaderDuration (rtsTxVector);
|
||||
NS_ASSERT (m_ctsTimeoutEvent.IsExpired ());
|
||||
NotifyCtsTimeoutStartNow (timerDelay);
|
||||
m_ctsTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::CtsTimeout, this);
|
||||
@@ -1833,23 +1879,26 @@ MacLow::StartDataTxTimers (WifiTxVector dataTxVector)
|
||||
Time txDuration = m_phy->CalculateTxDuration (m_currentPacket->GetSize (), dataTxVector, m_phy->GetFrequency ());
|
||||
if (m_txParams.MustWaitNormalAck () && !IsCfPeriod ())
|
||||
{
|
||||
Time timerDelay = txDuration + GetAckTimeout ();
|
||||
// the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
|
||||
// at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
|
||||
// aRxPHYStartDelay equals the time to transmit the PHY header.
|
||||
WifiTxVector ackTxVector = GetAckTxVector (m_currentPacket->GetAddr1 (),
|
||||
dataTxVector.GetMode ());
|
||||
Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
|
||||
+ m_phy->CalculatePhyPreambleAndHeaderDuration (ackTxVector);
|
||||
NS_ASSERT (m_normalAckTimeoutEvent.IsExpired ());
|
||||
NotifyAckTimeoutStartNow (timerDelay);
|
||||
m_normalAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::NormalAckTimeout, this);
|
||||
}
|
||||
else if (m_txParams.MustWaitBlockAck () && m_txParams.GetBlockAckType () == BlockAckType::BASIC_BLOCK_ACK)
|
||||
else if (m_txParams.MustWaitBlockAck ())
|
||||
{
|
||||
Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
|
||||
NS_ASSERT (m_blockAckTimeoutEvent.IsExpired ());
|
||||
NotifyAckTimeoutStartNow (timerDelay);
|
||||
m_blockAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::BlockAckTimeout, this);
|
||||
}
|
||||
else if (m_txParams.MustWaitBlockAck () &&
|
||||
(m_txParams.GetBlockAckType () == BlockAckType::COMPRESSED_BLOCK_ACK
|
||||
|| m_txParams.GetBlockAckType () == BlockAckType::EXTENDED_COMPRESSED_BLOCK_ACK))
|
||||
{
|
||||
Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
|
||||
// the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
|
||||
// at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
|
||||
// aRxPHYStartDelay equals the time to transmit the PHY header.
|
||||
WifiTxVector blockAckTxVector = GetBlockAckTxVector (m_currentPacket->GetAddr1 (),
|
||||
dataTxVector.GetMode ());
|
||||
Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
|
||||
+ m_phy->CalculatePhyPreambleAndHeaderDuration (blockAckTxVector);
|
||||
NS_ASSERT (m_blockAckTimeoutEvent.IsExpired ());
|
||||
NotifyAckTimeoutStartNow (timerDelay);
|
||||
m_blockAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::BlockAckTimeout, this);
|
||||
|
||||
@@ -367,6 +367,19 @@ public:
|
||||
MacLowTransmissionParameters parameters,
|
||||
Ptr<Txop> txop);
|
||||
|
||||
/**
|
||||
* \param txVector the TXVECTOR decoded from PHY header.
|
||||
* \param psduDuration the duration of the PSDU that is about to be received.
|
||||
*
|
||||
* This method is typically invoked by the lower PHY layer to notify
|
||||
* the MAC layer that the reception of a PSDU is starting.
|
||||
* This is equivalent to the PHY-RXSTART primitive.
|
||||
* If the reception is correct for at least one MPDU of the PSDU
|
||||
* the DeaggregateAmpduAndReceive will be called after \p psduDuration.
|
||||
* Otherwise, ReceiveError will be called after the same duration.
|
||||
*/
|
||||
void RxStartIndication (WifiTxVector txVector, Time psduDuration);
|
||||
|
||||
/**
|
||||
* \param mpdu MPDU received
|
||||
* \param rxSnr snr of MPDU received in linear scale
|
||||
|
||||
@@ -2143,7 +2143,7 @@ Bug2470TestCase::DoRun (void)
|
||||
// Block ADDBA request 3 times (== maximum number of MAC frame transmissions in the ADDBA response timeout interval)
|
||||
blackList.push_back (4);
|
||||
blackList.push_back (5);
|
||||
blackList.push_back (8);
|
||||
blackList.push_back (6);
|
||||
apPem->SetList (blackList);
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user