wifi: Allow to continue a TXOP after a BSRP Trigger Frame
This commit is contained in:
@@ -54,10 +54,17 @@ IsTrigger(const WifiConstPsduMap& psduMap)
|
||||
TypeId
|
||||
HeFrameExchangeManager::GetTypeId()
|
||||
{
|
||||
static TypeId tid = TypeId("ns3::HeFrameExchangeManager")
|
||||
.SetParent<VhtFrameExchangeManager>()
|
||||
.AddConstructor<HeFrameExchangeManager>()
|
||||
.SetGroupName("Wifi");
|
||||
static TypeId tid =
|
||||
TypeId("ns3::HeFrameExchangeManager")
|
||||
.SetParent<VhtFrameExchangeManager>()
|
||||
.AddConstructor<HeFrameExchangeManager>()
|
||||
.SetGroupName("Wifi")
|
||||
.AddAttribute("ContinueTxopAfterBsrp",
|
||||
"Whether to continue a TXOP a SIFS after the reception of responses "
|
||||
"to a BSRP Trigger Frame when TXOP limit is zero.",
|
||||
BooleanValue(false),
|
||||
MakeBooleanAccessor(&HeFrameExchangeManager::m_continueTxopAfterBsrpTf),
|
||||
MakeBooleanChecker());
|
||||
return tid;
|
||||
}
|
||||
|
||||
@@ -508,7 +515,25 @@ HeFrameExchangeManager::TransmissionSucceeded()
|
||||
m_sentFrameTo.erase(address);
|
||||
}
|
||||
|
||||
VhtFrameExchangeManager::TransmissionSucceeded();
|
||||
if (m_continueTxopAfterBsrpTf && m_edca && m_edca->GetTxopLimit(m_linkId).IsZero() &&
|
||||
m_txTimer.IsRunning() && m_txTimer.GetReason() == WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF)
|
||||
{
|
||||
NS_LOG_DEBUG("Schedule another transmission in a SIFS after successful BSRP TF");
|
||||
bool (HeFrameExchangeManager::*fp)(Ptr<QosTxop>, Time) =
|
||||
&HeFrameExchangeManager::StartTransmission;
|
||||
|
||||
// TXOP limit is null, hence the txopDuration parameter is unused
|
||||
Simulator::Schedule(m_phy->GetSifs(), fp, this, m_edca, Seconds(0));
|
||||
if (m_protectedIfResponded)
|
||||
{
|
||||
m_protectedStas.merge(m_sentFrameTo);
|
||||
}
|
||||
m_sentFrameTo.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
VhtFrameExchangeManager::TransmissionSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -795,6 +820,15 @@ HeFrameExchangeManager::SendPsduMap()
|
||||
|
||||
// Set Duration/ID
|
||||
Time durationId = GetPsduDurationId(txDuration, m_txParams);
|
||||
|
||||
if (m_continueTxopAfterBsrpTf && m_edca && m_edca->GetTxopLimit(m_linkId).IsZero() &&
|
||||
timerType == WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF)
|
||||
{
|
||||
// add the duration of the following frame exchange to extend the NAV beyond the
|
||||
// responses to the BSRP TF
|
||||
durationId += m_muScheduler->GetExtraTimeForBsrpTfDurationId(m_linkId);
|
||||
}
|
||||
|
||||
for (auto& psdu : m_psduMap)
|
||||
{
|
||||
psdu.second->SetDuration(durationId);
|
||||
@@ -2310,21 +2344,7 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG("Received a QoS Null frame in a TB PPDU from " << sender);
|
||||
|
||||
// remove the sender from the set of stations that are expected to send a TB PPDU
|
||||
m_txTimer.GotResponseFrom(sender);
|
||||
|
||||
if (m_txTimer.GetStasExpectedToRespond().empty())
|
||||
{
|
||||
// we do not expect any other response
|
||||
m_txTimer.Cancel();
|
||||
m_channelAccessManager->NotifyAckTimeoutResetNow();
|
||||
|
||||
NS_ASSERT(m_edca);
|
||||
m_psduMap.clear();
|
||||
m_edca->ResetCw(m_linkId);
|
||||
TransmissionSucceeded();
|
||||
}
|
||||
ReceivedQosNullAfterBsrpTf(sender);
|
||||
|
||||
// the received TB PPDU has been processed
|
||||
return;
|
||||
@@ -2770,21 +2790,7 @@ HeFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG("Received QoS Null frames in a TB PPDU from " << sender);
|
||||
|
||||
// remove the sender from the set of stations that are expected to send a TB PPDU
|
||||
m_txTimer.GotResponseFrom(sender);
|
||||
|
||||
if (m_txTimer.GetStasExpectedToRespond().empty())
|
||||
{
|
||||
// we do not expect any other response
|
||||
m_txTimer.Cancel();
|
||||
m_channelAccessManager->NotifyAckTimeoutResetNow();
|
||||
|
||||
NS_ASSERT(m_edca);
|
||||
m_psduMap.clear();
|
||||
m_edca->ResetCw(m_linkId);
|
||||
TransmissionSucceeded();
|
||||
}
|
||||
ReceivedQosNullAfterBsrpTf(sender);
|
||||
|
||||
// the received TB PPDU has been processed
|
||||
return;
|
||||
@@ -2811,4 +2817,30 @@ HeFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
|
||||
VhtFrameExchangeManager::EndReceiveAmpdu(psdu, rxSignalInfo, txVector, perMpduStatus);
|
||||
}
|
||||
|
||||
void
|
||||
HeFrameExchangeManager::ReceivedQosNullAfterBsrpTf(Mac48Address sender)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << sender);
|
||||
|
||||
NS_ASSERT(m_txTimer.IsRunning() &&
|
||||
m_txTimer.GetReason() == WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF);
|
||||
|
||||
// remove the sender from the set of stations that are expected to send a TB PPDU
|
||||
m_txTimer.GotResponseFrom(sender);
|
||||
|
||||
if (m_txTimer.GetStasExpectedToRespond().empty())
|
||||
{
|
||||
// we do not expect any other response
|
||||
m_channelAccessManager->NotifyAckTimeoutResetNow();
|
||||
|
||||
NS_ASSERT(m_edca);
|
||||
m_psduMap.clear();
|
||||
m_edca->ResetCw(m_linkId);
|
||||
TransmissionSucceeded();
|
||||
// we reset the TX timer after calling TransmissionSucceeded, so that the latter can
|
||||
// check whether the reason for the last timer is WAIT_QOS_NULL_AFTER_BSRP_TF
|
||||
m_txTimer.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -341,6 +341,14 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
|
||||
*/
|
||||
void SendQosNullFramesInTbPpdu(const CtrlTriggerHeader& trigger, const WifiMacHeader& hdr);
|
||||
|
||||
/**
|
||||
* Perform the actions required when receiving QoS Null frame(s) from the given sender after
|
||||
* a BSRP Trigger Frame.
|
||||
*
|
||||
* \param sender the MAC address of the given sender
|
||||
*/
|
||||
void ReceivedQosNullAfterBsrpTf(Mac48Address sender);
|
||||
|
||||
Ptr<ApWifiMac> m_apMac; //!< MAC pointer (null if not an AP)
|
||||
Ptr<StaWifiMac> m_staMac; //!< MAC pointer (null if not a STA)
|
||||
WifiTxVector m_trigVector; //!< the TRIGVECTOR
|
||||
@@ -381,6 +389,8 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
|
||||
EventId m_multiStaBaEvent; //!< Sending a Multi-STA BlockAck event
|
||||
MuSnrTag m_muSnrTag; //!< Tag to attach to Multi-STA BlockAck frames
|
||||
bool m_triggerFrameInAmpdu; //!< True if the received A-MPDU contains an MU-BAR
|
||||
bool m_continueTxopAfterBsrpTf; //!< whether to continue a TXOP a SIFS after the reception of
|
||||
//!< responses to a BSRP TF when TXOP limit is zero
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -64,7 +64,19 @@ MultiUserScheduler::GetTypeId()
|
||||
"channel access.",
|
||||
BooleanValue(true),
|
||||
MakeBooleanAccessor(&MultiUserScheduler::m_restartTimerUponAccess),
|
||||
MakeBooleanChecker());
|
||||
MakeBooleanChecker())
|
||||
.AddAttribute("DefaultTbPpduDuration",
|
||||
"Default duration of TB PPDUs solicited via a Basic Trigger Frame. "
|
||||
"This value is used to compute the Duration/ID field of BSRP Trigger "
|
||||
"Frames sent when the TXOP Limit is zero and the FrameExchangeManager "
|
||||
"continues the TXOP a SIFS after receiving response to the BSRP TF. "
|
||||
"This value shall also be used by subclasses when they have no other "
|
||||
"information available to determine the TX duration of solicited PPDUs. "
|
||||
"The default value roughly corresponds to half the maximum PPDU TX "
|
||||
"duration.",
|
||||
TimeValue(MilliSeconds(2)),
|
||||
MakeTimeAccessor(&MultiUserScheduler::m_defaultTbPpduDuration),
|
||||
MakeTimeChecker());
|
||||
return tid;
|
||||
}
|
||||
|
||||
@@ -186,6 +198,12 @@ MultiUserScheduler::GetHeFem(uint8_t linkId) const
|
||||
return StaticCast<HeFrameExchangeManager>(m_apMac->GetFrameExchangeManager(linkId));
|
||||
}
|
||||
|
||||
Time
|
||||
MultiUserScheduler::GetExtraTimeForBsrpTfDurationId(uint8_t linkId) const
|
||||
{
|
||||
return m_defaultTbPpduDuration;
|
||||
}
|
||||
|
||||
void
|
||||
MultiUserScheduler::AccessReqTimeout(uint8_t linkId)
|
||||
{
|
||||
|
||||
@@ -111,6 +111,23 @@ class MultiUserScheduler : public Object
|
||||
*/
|
||||
UlMuInfo& GetUlMuInfo(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* When the TXOP limit is zero and the TXOP continues a SIFS after receiving a response to a
|
||||
* BSRP TF, the Duration/ID field of the BSRP TF should be extended to reserve the medium
|
||||
* for the frame exchange following the BSRP TF. This method is intended to return the estimated
|
||||
* duration of the frame exchange following the BSRP TF (including the SIFS after the responses
|
||||
* to the BSRP TF). Specifically, the base class method simply returns the default duration of
|
||||
* TB PPDUs solicited via a Basic Trigger Frame. Subclasses can override this method to return
|
||||
* a more accurate estimate of the time required by the following frame exchange.
|
||||
*
|
||||
* This method should only be called when the MU scheduler has determined that a BSRP TF has
|
||||
* to be sent on the given link.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the estimated duration of the frame exchange following the BSRP TF
|
||||
*/
|
||||
virtual Time GetExtraTimeForBsrpTfDurationId(uint8_t linkId) const;
|
||||
|
||||
/**
|
||||
* Set the duration of the interval between two consecutive requests for channel
|
||||
* access made by the MultiUserScheduler.
|
||||
@@ -177,12 +194,13 @@ class MultiUserScheduler : public Object
|
||||
void NotifyNewAggregate() override;
|
||||
void DoInitialize() override;
|
||||
|
||||
Ptr<ApWifiMac> m_apMac; //!< the AP wifi MAC
|
||||
Ptr<QosTxop> m_edca; //!< the AC that gained channel access
|
||||
Time m_availableTime; //!< the time available for frame exchange
|
||||
bool m_initialFrame; //!< true if a TXOP is being started
|
||||
MHz_u m_allowedWidth; //!< the allowed width for the current transmission
|
||||
uint8_t m_linkId; //!< the ID of the link over which channel access has been granted
|
||||
Ptr<ApWifiMac> m_apMac; //!< the AP wifi MAC
|
||||
Ptr<QosTxop> m_edca; //!< the AC that gained channel access
|
||||
Time m_availableTime; //!< the time available for frame exchange
|
||||
bool m_initialFrame; //!< true if a TXOP is being started
|
||||
MHz_u m_allowedWidth; //!< the allowed width for the current transmission
|
||||
uint8_t m_linkId; //!< the ID of the link over which channel access has been granted
|
||||
Time m_defaultTbPpduDuration; //!< the default duration of TB PPDUs solicited by Basic TFs
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -383,6 +383,9 @@ RrMultiUserScheduler::TrySendingBsrpTf()
|
||||
qosNullTxDuration = Max(qosNullTxDuration, duration);
|
||||
}
|
||||
|
||||
NS_ASSERT(m_txParams.m_txDuration.has_value());
|
||||
m_triggerTxDuration = m_txParams.m_txDuration.value();
|
||||
|
||||
if (m_availableTime != Time::Min())
|
||||
{
|
||||
// TryAddMpdu only considers the time to transmit the Trigger Frame
|
||||
@@ -390,7 +393,6 @@ RrMultiUserScheduler::TrySendingBsrpTf()
|
||||
NS_ASSERT(m_txParams.m_acknowledgment &&
|
||||
m_txParams.m_acknowledgment->acknowledgmentTime.has_value() &&
|
||||
m_txParams.m_acknowledgment->acknowledgmentTime->IsZero());
|
||||
NS_ASSERT(m_txParams.m_txDuration.has_value());
|
||||
|
||||
if (*m_txParams.m_protection->protectionTime + *m_txParams.m_txDuration // BSRP TF tx time
|
||||
+ m_apMac->GetWifiPhy(m_linkId)->GetSifs() + qosNullTxDuration >
|
||||
@@ -503,13 +505,15 @@ RrMultiUserScheduler::TrySendingBasicTf()
|
||||
return NO_TX;
|
||||
}
|
||||
|
||||
NS_ASSERT(m_txParams.m_txDuration.has_value());
|
||||
m_triggerTxDuration = m_txParams.m_txDuration.value();
|
||||
|
||||
if (m_availableTime != Time::Min())
|
||||
{
|
||||
// TryAddMpdu only considers the time to transmit the Trigger Frame
|
||||
NS_ASSERT(m_txParams.m_protection && m_txParams.m_protection->protectionTime.has_value());
|
||||
NS_ASSERT(m_txParams.m_acknowledgment &&
|
||||
m_txParams.m_acknowledgment->acknowledgmentTime.has_value());
|
||||
NS_ASSERT(m_txParams.m_txDuration.has_value());
|
||||
|
||||
maxDuration = Min(maxDuration,
|
||||
m_availableTime - *m_txParams.m_protection->protectionTime -
|
||||
@@ -582,6 +586,49 @@ RrMultiUserScheduler::TrySendingBasicTf()
|
||||
return UL_MU_TX;
|
||||
}
|
||||
|
||||
Time
|
||||
RrMultiUserScheduler::GetExtraTimeForBsrpTfDurationId(uint8_t linkId) const
|
||||
{
|
||||
auto phy = m_apMac->GetWifiPhy(linkId);
|
||||
BlockAckType baType(BlockAckType::MULTI_STA);
|
||||
uint16_t aid{0};
|
||||
Mac48Address staAddress;
|
||||
|
||||
// we assume that a Basic Trigger Frame is sent after a BSRP Trigger Frame. In order to
|
||||
// compute the TX duration of the Multi-STA BlockAck, we need to find the bitmap length
|
||||
// for each STA solicited by the Trigger Frame
|
||||
for (const auto& userInfo : m_trigger)
|
||||
{
|
||||
aid = userInfo.GetAid12();
|
||||
auto it = m_apMac->GetStaList(linkId).find(aid);
|
||||
NS_ASSERT(it != m_apMac->GetStaList(linkId).cend());
|
||||
staAddress = it->second;
|
||||
|
||||
// find a TID for which a BA agreement exists with the given originator
|
||||
uint8_t tid = 0;
|
||||
while (tid < 8 && !m_apMac->GetBaAgreementEstablishedAsRecipient(staAddress, tid))
|
||||
{
|
||||
++tid;
|
||||
}
|
||||
NS_ASSERT_MSG(tid < 8, "No Block Ack agreement established with originator " << staAddress);
|
||||
|
||||
baType.m_bitmapLen.push_back(
|
||||
m_apMac->GetBaTypeAsRecipient(staAddress, tid).m_bitmapLen.at(0));
|
||||
}
|
||||
|
||||
NS_ASSERT_MSG(aid != 0, "No User Info field in the Trigger Frame");
|
||||
|
||||
auto multiStaBaTxVector =
|
||||
GetWifiRemoteStationManager(linkId)->GetBlockAckTxVector(staAddress,
|
||||
m_trigger.GetHeTbTxVector(aid));
|
||||
|
||||
auto multiStaBaDuration = WifiPhy::CalculateTxDuration(GetBlockAckSize(baType),
|
||||
multiStaBaTxVector,
|
||||
phy->GetPhyBand());
|
||||
|
||||
return m_triggerTxDuration + m_defaultTbPpduDuration + multiStaBaDuration + 3 * phy->GetSifs();
|
||||
}
|
||||
|
||||
void
|
||||
RrMultiUserScheduler::NotifyStationAssociated(uint16_t aid, Mac48Address address)
|
||||
{
|
||||
|
||||
@@ -42,6 +42,8 @@ class RrMultiUserScheduler : public MultiUserScheduler
|
||||
RrMultiUserScheduler();
|
||||
~RrMultiUserScheduler() override;
|
||||
|
||||
Time GetExtraTimeForBsrpTfDurationId(uint8_t linkId) const override;
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
void DoInitialize() override;
|
||||
@@ -173,6 +175,7 @@ class RrMultiUserScheduler : public MultiUserScheduler
|
||||
Time m_maxCredits; //!< Max amount of credits a station can have
|
||||
CtrlTriggerHeader m_trigger; //!< Trigger Frame to send
|
||||
WifiMacHeader m_triggerMacHdr; //!< MAC header for Trigger Frame
|
||||
Time m_triggerTxDuration{0}; //!< Trigger Frame TX duration
|
||||
WifiTxParameters m_txParams; //!< TX parameters
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user