wifi: Update backoff before checking for immediate access
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -242,6 +242,56 @@ ChannelAccessManager::IsBusy (void) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelAccessManager::NeedBackoffUponAccess (Ptr<Txop> txop)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << txop);
|
||||
|
||||
// the Txop might have a stale value of remaining backoff slots
|
||||
UpdateBackoff ();
|
||||
|
||||
/*
|
||||
* From section 10.3.4.2 "Basic access" of IEEE 802.11-2016:
|
||||
*
|
||||
* A STA may transmit an MPDU when it is operating under the DCF access
|
||||
* method, either in the absence of a PC, or in the CP of the PCF access
|
||||
* method, when the STA determines that the medium is idle when a frame is
|
||||
* queued for transmission, and remains idle for a period of a DIFS, or an
|
||||
* EIFS (10.3.2.3.7) from the end of the immediately preceding medium-busy
|
||||
* event, whichever is the greater, and the backoff timer is zero. Otherwise
|
||||
* the random backoff procedure described in 10.3.4.3 shall be followed.
|
||||
*
|
||||
* From section 10.22.2.2 "EDCA backoff procedure" of IEEE 802.11-2016:
|
||||
*
|
||||
* The backoff procedure shall be invoked by an EDCAF when any of the following
|
||||
* events occurs:
|
||||
* a) An MA-UNITDATA.request primitive is received that causes a frame with that AC
|
||||
* to be queued for transmission such that one of the transmit queues associated
|
||||
* with that AC has now become non-empty and any other transmit queues
|
||||
* associated with that AC are empty; the medium is busy on the primary channel
|
||||
*/
|
||||
if (!txop->HasFramesToTransmit () && !txop->GetLow ()->IsCfPeriod () && txop->GetBackoffSlots () == 0)
|
||||
{
|
||||
if (!IsBusy ())
|
||||
{
|
||||
// medium idle. If this is a DCF, use immediate access (we can transmit
|
||||
// in a DIFS if the medium remains idle). If this is an EDCAF, update
|
||||
// the backoff start time kept by the EDCAF to the current time in order
|
||||
// to correctly align the backoff start time at the next slot boundary
|
||||
// (performed by the next call to ChannelAccessManager::RequestAccess())
|
||||
Time delay = (txop->IsQosTxop () ? Seconds (0)
|
||||
: m_sifs + txop->GetAifsn () * m_slot);
|
||||
txop->UpdateBackoffSlotsNow (0, Simulator::Now () + delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
// medium busy, backoff is neeeded
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ChannelAccessManager::RequestAccess (Ptr<Txop> state, bool isCfPeriod)
|
||||
{
|
||||
|
||||
@@ -112,6 +112,15 @@ public:
|
||||
*/
|
||||
void Add (Ptr<Txop> dcf);
|
||||
|
||||
/**
|
||||
* Determine if a new backoff needs to be generated when a packet is queued
|
||||
* for transmission.
|
||||
*
|
||||
* \param txop the Txop requesting to generate a backoff
|
||||
* \return true if backoff needs to be generated, false otherwise
|
||||
*/
|
||||
bool NeedBackoffUponAccess (Ptr<Txop> txop);
|
||||
|
||||
/**
|
||||
* \param state a Txop
|
||||
* \param isCfPeriod flag whether it is called during the CF period
|
||||
|
||||
@@ -312,50 +312,6 @@ Txop::HasFramesToTransmit (void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
Txop::GenerateBackoffUponAccessIfNeeded (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
/*
|
||||
* From section 10.3.4.2 "Basic access" of IEEE 802.11-2016:
|
||||
*
|
||||
* A STA may transmit an MPDU when it is operating under the DCF access
|
||||
* method, either in the absence of a PC, or in the CP of the PCF access
|
||||
* method, when the STA determines that the medium is idle when a frame is
|
||||
* queued for transmission, and remains idle for a period of a DIFS, or an
|
||||
* EIFS (10.3.2.3.7) from the end of the immediately preceding medium-busy
|
||||
* event, whichever is the greater, and the backoff timer is zero. Otherwise
|
||||
* the random backoff procedure described in 10.3.4.3 shall be followed.
|
||||
*
|
||||
* From section 10.22.2.2 "EDCA backoff procedure" of IEEE 802.11-2016:
|
||||
*
|
||||
* The backoff procedure shall be invoked by an EDCAF when any of the following
|
||||
* events occurs:
|
||||
* a) An MA-UNITDATA.request primitive is received that causes a frame with that AC
|
||||
* to be queued for transmission such that one of the transmit queues associated
|
||||
* with that AC has now become non-empty and any other transmit queues
|
||||
* associated with that AC are empty; the medium is busy on the primary channel
|
||||
*/
|
||||
if (!HasFramesToTransmit () && !m_low->IsCfPeriod () && m_backoffSlots == 0)
|
||||
{
|
||||
if (!m_channelAccessManager->IsBusy ())
|
||||
{
|
||||
// medium idle. If this is a DCF, use immediate access (we can transmit
|
||||
// in a DIFS if the medium remains idle). If this is an EDCAF, update
|
||||
// the backoff start time kept by the EDCAF to the current time in order
|
||||
// to correctly align the backoff start time at the next slot boundary
|
||||
// (performed by the next call to ChannelAccessManager::RequestAccess())
|
||||
Time delay = (IsQosTxop () ? Seconds (0) : m_low->GetSifs () + GetAifsn () * m_low->GetSlotTime ());
|
||||
UpdateBackoffSlotsNow (0, Simulator::Now () + delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
// medium busy, generate backoff
|
||||
GenerateBackoff ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Txop::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
{
|
||||
@@ -365,7 +321,10 @@ Txop::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
SocketPriorityTag priorityTag;
|
||||
packetCopy->RemovePacketTag (priorityTag);
|
||||
m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packetCopy);
|
||||
GenerateBackoffUponAccessIfNeeded ();
|
||||
if (m_channelAccessManager->NeedBackoffUponAccess (this))
|
||||
{
|
||||
GenerateBackoff ();
|
||||
}
|
||||
m_queue->Enqueue (Create<WifiMacQueueItem> (packetCopy, hdr));
|
||||
StartAccessIfNeeded ();
|
||||
}
|
||||
|
||||
@@ -376,10 +376,6 @@ protected:
|
||||
* \return true if the DCF has frames to transmit.
|
||||
*/
|
||||
virtual bool HasFramesToTransmit (void);
|
||||
/**
|
||||
* Generate a new backoff, if needed, when a packet is queued for transmission.
|
||||
*/
|
||||
virtual void GenerateBackoffUponAccessIfNeeded (void);
|
||||
/**
|
||||
* Generate a new backoff now.
|
||||
*/
|
||||
|
||||
@@ -679,7 +679,10 @@ void
|
||||
ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
|
||||
Ptr<TxopTest<TxopType>> state)
|
||||
{
|
||||
state->GenerateBackoffUponAccessIfNeeded ();
|
||||
if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
|
||||
{
|
||||
state->GenerateBackoff ();
|
||||
}
|
||||
state->QueueTx (txTime, expectedGrantTime);
|
||||
m_ChannelAccessManager->RequestAccess (state);
|
||||
}
|
||||
|
||||
@@ -460,7 +460,6 @@ DcfImmediateAccessBroadcastTestCase::NotifyPhyTxBegin (Ptr<const Packet> p, doub
|
||||
{
|
||||
if (m_numSentPackets == 0)
|
||||
{
|
||||
NS_ASSERT_MSG (Simulator::Now () == Time (Seconds (1)), "Packet 0 not transmitted at 1 second");
|
||||
m_numSentPackets++;
|
||||
m_firstTransmissionTime = Simulator::Now ();
|
||||
}
|
||||
@@ -536,13 +535,17 @@ DcfImmediateAccessBroadcastTestCase::DoRun (void)
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
// First packet is transmitted a DIFS after the packet is queued. A DIFS
|
||||
// is 2 slots (2 * 9 = 18 us) plus a SIFS (16 us), i.e., 34 us
|
||||
Time expectedFirstTransmissionTime = Seconds (1.0) + MicroSeconds (34);
|
||||
|
||||
//First packet has 1408 us of transmit time. Slot time is 9 us.
|
||||
//Backoff is 1 slots. SIFS is 16 us. DIFS is 2 slots = 18 us.
|
||||
//Should send next packet at 1408 us + (1 * 9 us) + 16 us + (2 * 9) us
|
||||
//1451 us after the first one.
|
||||
uint32_t expectedWait1 = 1408 + (1 * 9) + 16 + (2 * 9);
|
||||
Time expectedSecondTransmissionTime = MicroSeconds (expectedWait1) + MilliSeconds (1000);
|
||||
NS_TEST_ASSERT_MSG_EQ (m_firstTransmissionTime, MilliSeconds (1000), "The first transmission time not correct!");
|
||||
Time expectedSecondTransmissionTime = expectedFirstTransmissionTime + MicroSeconds (expectedWait1);
|
||||
NS_TEST_ASSERT_MSG_EQ (m_firstTransmissionTime, expectedFirstTransmissionTime, "The first transmission time not correct!");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_secondTransmissionTime, expectedSecondTransmissionTime, "The second transmission time not correct!");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user