wifi: Txop holds per-link contention window information
This commit is contained in:
committed by
Stefano Avallone
parent
18eb7e47a0
commit
262918d22c
@@ -343,30 +343,35 @@ OcbWifiMac::ConfigureEdca (uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, enum
|
||||
{
|
||||
case AC_VO:
|
||||
dcf = WifiMac::GetVOQueue ();
|
||||
dcf->SetWifiMac (this);
|
||||
dcf->SetMinCw ((cwmin + 1) / 4 - 1);
|
||||
dcf->SetMaxCw ((cwmin + 1) / 2 - 1);
|
||||
dcf->SetAifsn (aifsn);
|
||||
break;
|
||||
case AC_VI:
|
||||
dcf = WifiMac::GetVIQueue ();
|
||||
dcf->SetWifiMac (this);
|
||||
dcf->SetMinCw ((cwmin + 1) / 2 - 1);
|
||||
dcf->SetMaxCw (cwmin);
|
||||
dcf->SetAifsn (aifsn);
|
||||
break;
|
||||
case AC_BE:
|
||||
dcf = WifiMac::GetBEQueue ();
|
||||
dcf->SetWifiMac (this);
|
||||
dcf->SetMinCw (cwmin);
|
||||
dcf->SetMaxCw (cwmax);
|
||||
dcf->SetAifsn (aifsn);
|
||||
break;
|
||||
case AC_BK:
|
||||
dcf = WifiMac::GetBKQueue ();
|
||||
dcf->SetWifiMac (this);
|
||||
dcf->SetMinCw (cwmin);
|
||||
dcf->SetMaxCw (cwmax);
|
||||
dcf->SetAifsn (aifsn);
|
||||
break;
|
||||
case AC_BE_NQOS:
|
||||
dcf = WifiMac::GetTxop ();
|
||||
dcf->SetWifiMac (this);
|
||||
dcf->SetMinCw (cwmin);
|
||||
dcf->SetMaxCw (cwmax);
|
||||
dcf->SetAifsn (aifsn);
|
||||
@@ -379,7 +384,6 @@ OcbWifiMac::ConfigureEdca (uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, enum
|
||||
break;
|
||||
}
|
||||
|
||||
dcf->SetWifiMac (this);
|
||||
GetLink (SINGLE_LINK_OP_ID).channelAccessManager-> Add (dcf);
|
||||
}
|
||||
|
||||
|
||||
@@ -600,12 +600,12 @@ TracePacketReception (std::string context, Ptr<const Packet> p, uint16_t channel
|
||||
}
|
||||
|
||||
void
|
||||
CwTrace (std::string context, uint32_t oldVal, uint32_t newVal)
|
||||
CwTrace (std::string context, uint32_t cw, uint8_t /* linkId */)
|
||||
{
|
||||
NS_LOG_INFO ("CW time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " val=" << newVal);
|
||||
NS_LOG_INFO ("CW time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " val=" << cw);
|
||||
if (tracing)
|
||||
{
|
||||
cwTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << newVal << std::endl;
|
||||
cwTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << cw << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,9 +106,6 @@ ApWifiMac::ApWifiMac ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_beaconTxop = CreateObject<Txop> (CreateObject<WifiMacQueue> (AC_BEACON));
|
||||
m_beaconTxop->SetAifsn (1);
|
||||
m_beaconTxop->SetMinCw (0);
|
||||
m_beaconTxop->SetMaxCw (0);
|
||||
m_beaconTxop->SetTxMiddle (m_txMiddle);
|
||||
|
||||
//Let the lower layers know that we are acting as an AP.
|
||||
@@ -148,6 +145,9 @@ ApWifiMac::ConfigureStandard (WifiStandard standard)
|
||||
NS_LOG_FUNCTION (this << standard);
|
||||
WifiMac::ConfigureStandard (standard);
|
||||
m_beaconTxop->SetWifiMac (this);
|
||||
m_beaconTxop->SetAifsns (std::vector<uint8_t> (GetNLinks (), 1));
|
||||
m_beaconTxop->SetMinCws (std::vector<uint32_t> (GetNLinks (), 0));
|
||||
m_beaconTxop->SetMaxCws (std::vector<uint32_t> (GetNLinks (), 0));
|
||||
for (uint8_t linkId = 0; linkId < GetNLinks (); linkId++)
|
||||
{
|
||||
GetLink (linkId).channelAccessManager->Add (m_beaconTxop);
|
||||
@@ -482,33 +482,33 @@ ApWifiMac::GetEdcaParameterSet (void) const
|
||||
edca = GetQosTxop (AC_BE);
|
||||
txopLimit = edca->GetTxopLimit ();
|
||||
edcaParameters.SetBeAci (0);
|
||||
edcaParameters.SetBeCWmin (edca->GetMinCw ());
|
||||
edcaParameters.SetBeCWmax (edca->GetMaxCw ());
|
||||
edcaParameters.SetBeAifsn (edca->GetAifsn ());
|
||||
edcaParameters.SetBeCWmin (edca->GetMinCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetBeCWmax (edca->GetMaxCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetBeAifsn (edca->GetAifsn (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetBeTxopLimit (static_cast<uint16_t> (txopLimit.GetMicroSeconds () / 32));
|
||||
|
||||
edca = GetQosTxop (AC_BK);
|
||||
txopLimit = edca->GetTxopLimit ();
|
||||
edcaParameters.SetBkAci (1);
|
||||
edcaParameters.SetBkCWmin (edca->GetMinCw ());
|
||||
edcaParameters.SetBkCWmax (edca->GetMaxCw ());
|
||||
edcaParameters.SetBkAifsn (edca->GetAifsn ());
|
||||
edcaParameters.SetBkCWmin (edca->GetMinCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetBkCWmax (edca->GetMaxCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetBkAifsn (edca->GetAifsn (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetBkTxopLimit (static_cast<uint16_t> (txopLimit.GetMicroSeconds () / 32));
|
||||
|
||||
edca = GetQosTxop (AC_VI);
|
||||
txopLimit = edca->GetTxopLimit ();
|
||||
edcaParameters.SetViAci (2);
|
||||
edcaParameters.SetViCWmin (edca->GetMinCw ());
|
||||
edcaParameters.SetViCWmax (edca->GetMaxCw ());
|
||||
edcaParameters.SetViAifsn (edca->GetAifsn ());
|
||||
edcaParameters.SetViCWmin (edca->GetMinCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetViCWmax (edca->GetMaxCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetViAifsn (edca->GetAifsn (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetViTxopLimit (static_cast<uint16_t> (txopLimit.GetMicroSeconds () / 32));
|
||||
|
||||
edca = GetQosTxop (AC_VO);
|
||||
txopLimit = edca->GetTxopLimit ();
|
||||
edcaParameters.SetVoAci (3);
|
||||
edcaParameters.SetVoCWmin (edca->GetMinCw ());
|
||||
edcaParameters.SetVoCWmax (edca->GetMaxCw ());
|
||||
edcaParameters.SetVoAifsn (edca->GetAifsn ());
|
||||
edcaParameters.SetVoCWmin (edca->GetMinCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetVoCWmax (edca->GetMaxCw (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetVoAifsn (edca->GetAifsn (SINGLE_LINK_OP_ID));
|
||||
edcaParameters.SetVoTxopLimit (static_cast<uint16_t> (txopLimit.GetMicroSeconds () / 32));
|
||||
|
||||
edcaParameters.SetQosInfo (0);
|
||||
|
||||
@@ -302,7 +302,7 @@ ChannelAccessManager::NeedBackoffUponAccess (Ptr<Txop> txop)
|
||||
// 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)
|
||||
: GetSifs () + txop->GetAifsn () * GetSlot ());
|
||||
: GetSifs () + txop->GetAifsn (m_linkId) * GetSlot ());
|
||||
txop->UpdateBackoffSlotsNow (0, Simulator::Now () + delay, m_linkId);
|
||||
}
|
||||
else
|
||||
@@ -330,7 +330,7 @@ ChannelAccessManager::RequestAccess (Ptr<Txop> txop)
|
||||
/*
|
||||
* EDCAF operations shall be performed at slot boundaries (Sec. 10.22.2.4 of 802.11-2016)
|
||||
*/
|
||||
Time accessGrantStart = GetAccessGrantStart () + (txop->GetAifsn () * GetSlot ());
|
||||
Time accessGrantStart = GetAccessGrantStart () + (txop->GetAifsn (m_linkId) * GetSlot ());
|
||||
|
||||
if (txop->IsQosTxop () && txop->GetBackoffStart (m_linkId) > accessGrantStart)
|
||||
{
|
||||
@@ -358,7 +358,7 @@ ChannelAccessManager::DoGrantDcfAccess (void)
|
||||
{
|
||||
Ptr<Txop> txop = *i;
|
||||
if (txop->GetAccessStatus () == Txop::REQUESTED
|
||||
&& (!txop->IsQosTxop () || !StaticCast<QosTxop> (txop)->EdcaDisabled ())
|
||||
&& (!txop->IsQosTxop () || !StaticCast<QosTxop> (txop)->EdcaDisabled (m_linkId))
|
||||
&& GetBackoffEndFor (txop) <= Simulator::Now () )
|
||||
{
|
||||
/**
|
||||
@@ -478,7 +478,7 @@ ChannelAccessManager::GetBackoffStartFor (Ptr<Txop> txop)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << txop);
|
||||
Time mostRecentEvent = std::max ({txop->GetBackoffStart (m_linkId),
|
||||
GetAccessGrantStart () + (txop->GetAifsn () * GetSlot ())});
|
||||
GetAccessGrantStart () + (txop->GetAifsn (m_linkId) * GetSlot ())});
|
||||
NS_LOG_DEBUG ("Backoff start: " << mostRecentEvent.As (Time::US));
|
||||
|
||||
return mostRecentEvent;
|
||||
@@ -728,7 +728,7 @@ ChannelAccessManager::NotifySwitchingStartNow (Time duration)
|
||||
txop->UpdateBackoffSlotsNow (remainingSlots, now, m_linkId);
|
||||
NS_ASSERT (txop->GetBackoffSlots (m_linkId) == 0);
|
||||
}
|
||||
txop->ResetCw ();
|
||||
txop->ResetCw (m_linkId);
|
||||
txop->m_access = Txop::NOT_REQUESTED;
|
||||
}
|
||||
|
||||
@@ -785,7 +785,7 @@ ChannelAccessManager::NotifyWakeupNow (void)
|
||||
txop->UpdateBackoffSlotsNow (remainingSlots, Simulator::Now (), m_linkId);
|
||||
NS_ASSERT (txop->GetBackoffSlots (m_linkId) == 0);
|
||||
}
|
||||
txop->ResetCw ();
|
||||
txop->ResetCw (m_linkId);
|
||||
txop->m_access = Txop::NOT_REQUESTED;
|
||||
txop->NotifyWakeUp ();
|
||||
}
|
||||
@@ -804,7 +804,7 @@ ChannelAccessManager::NotifyOnNow (void)
|
||||
txop->UpdateBackoffSlotsNow (remainingSlots, Simulator::Now (), m_linkId);
|
||||
NS_ASSERT (txop->GetBackoffSlots (m_linkId) == 0);
|
||||
}
|
||||
txop->ResetCw ();
|
||||
txop->ResetCw (m_linkId);
|
||||
txop->m_access = Txop::NOT_REQUESTED;
|
||||
txop->NotifyOn ();
|
||||
}
|
||||
|
||||
@@ -797,14 +797,14 @@ FrameExchangeManager::NormalAckTimeout (Ptr<WifiMacQueueItem> mpdu, const WifiTx
|
||||
// Dequeue the MPDU if it is stored in a queue
|
||||
DequeueMpdu (mpdu);
|
||||
m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
|
||||
m_dcf->ResetCw ();
|
||||
m_dcf->ResetCw (m_linkId);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Missed Ack, retransmit MPDU");
|
||||
mpdu->GetHeader ().SetRetry ();
|
||||
RetransmitMpduAfterMissedAck (mpdu);
|
||||
m_dcf->UpdateFailedCw ();
|
||||
m_dcf->UpdateFailedCw (m_linkId);
|
||||
}
|
||||
|
||||
m_mpdu = 0;
|
||||
@@ -843,12 +843,12 @@ FrameExchangeManager::DoCtsTimeout (Ptr<WifiPsdu> psdu)
|
||||
DequeueMpdu (mpdu);
|
||||
NotifyPacketDiscarded (mpdu);
|
||||
}
|
||||
m_dcf->ResetCw ();
|
||||
m_dcf->ResetCw (m_linkId);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Missed CTS, retransmit MPDU(s)");
|
||||
m_dcf->UpdateFailedCw ();
|
||||
m_dcf->UpdateFailedCw (m_linkId);
|
||||
}
|
||||
// Make the sequence numbers of the MPDUs available again if the MPDUs have never
|
||||
// been transmitted, both in case the MPDUs have been discarded and in case the
|
||||
@@ -907,12 +907,12 @@ FrameExchangeManager::NotifyInternalCollision (Ptr<Txop> txop)
|
||||
m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
|
||||
DequeueMpdu (mpdu);
|
||||
NotifyPacketDiscarded (mpdu);
|
||||
txop->ResetCw ();
|
||||
txop->ResetCw (m_linkId);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Update CW");
|
||||
txop->UpdateFailedCw ();
|
||||
txop->UpdateFailedCw (m_linkId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,7 +1186,7 @@ FrameExchangeManager::ReceivedNormalAck (Ptr<WifiMacQueueItem> mpdu, const WifiT
|
||||
|
||||
// The CW shall be reset to aCWmin after every successful attempt to transmit
|
||||
// a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
|
||||
m_dcf->ResetCw ();
|
||||
m_dcf->ResetCw (m_linkId);
|
||||
|
||||
if (mpdu->GetHeader ().IsMoreFragments ())
|
||||
{
|
||||
|
||||
@@ -904,13 +904,13 @@ HeFrameExchangeManager::TbPpduTimeout (WifiPsduMap* psduMap,
|
||||
if (staMissedTbPpduFrom->size () == nSolicitedStations)
|
||||
{
|
||||
// no station replied, the transmission failed
|
||||
m_edca->UpdateFailedCw ();
|
||||
m_edca->UpdateFailedCw (m_linkId);
|
||||
|
||||
TransmissionFailed ();
|
||||
}
|
||||
else if (!m_multiStaBaEvent.IsRunning ())
|
||||
{
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
TransmissionSucceeded ();
|
||||
}
|
||||
|
||||
@@ -966,11 +966,11 @@ HeFrameExchangeManager::BlockAcksInTbPpduTimeout (WifiPsduMap* psduMap,
|
||||
|
||||
if (resetCw)
|
||||
{
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edca->UpdateFailedCw ();
|
||||
m_edca->UpdateFailedCw (m_linkId);
|
||||
}
|
||||
|
||||
if (staMissedBlockAckFrom->size () == nSolicitedStations)
|
||||
@@ -1238,7 +1238,7 @@ HeFrameExchangeManager::SendMultiStaBlockAck (const WifiTxParameters& txParams)
|
||||
|
||||
// continue with the TXOP if time remains
|
||||
m_psduMap.clear ();
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
m_muSnrTag.Reset ();
|
||||
Simulator::Schedule (txDuration, &HeFrameExchangeManager::TransmissionSucceeded, this);
|
||||
}
|
||||
@@ -1528,7 +1528,7 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rx
|
||||
// all of the stations that replied with a TB PPDU sent QoS Null frames.
|
||||
NS_LOG_DEBUG ("Continue the TXOP");
|
||||
m_psduMap.clear ();
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
TransmissionSucceeded ();
|
||||
}
|
||||
}
|
||||
@@ -1567,7 +1567,7 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rx
|
||||
|
||||
NS_ASSERT (m_edca != 0);
|
||||
m_psduMap.clear ();
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
TransmissionSucceeded ();
|
||||
}
|
||||
|
||||
@@ -1653,7 +1653,7 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rx
|
||||
m_channelAccessManager->NotifyAckTimeoutResetNow ();
|
||||
m_triggerFrame = nullptr; // this is strictly needed for DL_MU_TF_MU_BAR only
|
||||
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
m_psduMap.clear ();
|
||||
TransmissionSucceeded ();
|
||||
}
|
||||
@@ -1731,7 +1731,7 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rx
|
||||
// transmitted in response to a Basic Trigger Frame and at least one
|
||||
// MPDU was acknowledged. Therefore, it needs to update the access
|
||||
// parameters if it received an MU EDCA Parameter Set element.
|
||||
m_mac->GetQosTxop (tid)->StartMuEdcaTimerNow ();
|
||||
m_mac->GetQosTxop (tid)->StartMuEdcaTimerNow (m_linkId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1900,7 +1900,7 @@ HeFrameExchangeManager::EndReceiveAmpdu (Ptr<const WifiPsdu> psdu, const RxSigna
|
||||
// all of the stations that replied with a TB PPDU sent QoS Null frames.
|
||||
NS_LOG_DEBUG ("Continue the TXOP");
|
||||
m_psduMap.clear ();
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
TransmissionSucceeded ();
|
||||
}
|
||||
}
|
||||
@@ -1941,7 +1941,7 @@ HeFrameExchangeManager::EndReceiveAmpdu (Ptr<const WifiPsdu> psdu, const RxSigna
|
||||
|
||||
NS_ASSERT (m_edca != 0);
|
||||
m_psduMap.clear ();
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
TransmissionSucceeded ();
|
||||
}
|
||||
|
||||
|
||||
@@ -1114,11 +1114,11 @@ HtFrameExchangeManager::BlockAckTimeout (Ptr<WifiPsdu> psdu, const WifiTxVector&
|
||||
|
||||
if (resetCw)
|
||||
{
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edca->UpdateFailedCw ();
|
||||
m_edca->UpdateFailedCw (m_linkId);
|
||||
}
|
||||
|
||||
m_psdu = 0;
|
||||
@@ -1324,7 +1324,7 @@ HtFrameExchangeManager::ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rx
|
||||
m_channelAccessManager->NotifyAckTimeoutResetNow ();
|
||||
|
||||
// Reset the CW
|
||||
m_edca->ResetCw ();
|
||||
m_edca->ResetCw (m_linkId);
|
||||
|
||||
m_psdu = 0;
|
||||
TransmissionSucceeded ();
|
||||
|
||||
@@ -94,12 +94,7 @@ QosTxop::QosTxop (AcIndex ac)
|
||||
: Txop (CreateObject<WifiMacQueue> (ac)),
|
||||
m_ac (ac),
|
||||
m_startTxop (Seconds (0)),
|
||||
m_txopDuration (Seconds (0)),
|
||||
m_muCwMin (0),
|
||||
m_muCwMax (0),
|
||||
m_muAifsn (0),
|
||||
m_muEdcaTimer (Seconds (0)),
|
||||
m_muEdcaTimerStartTime (Seconds (0))
|
||||
m_txopDuration (Seconds (0))
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_qosBlockedDestinations = Create<QosBlockedDestinations> ();
|
||||
@@ -128,6 +123,18 @@ QosTxop::DoDispose (void)
|
||||
Txop::DoDispose ();
|
||||
}
|
||||
|
||||
std::unique_ptr<Txop::LinkEntity>
|
||||
QosTxop::CreateLinkEntity (void) const
|
||||
{
|
||||
return std::make_unique<QosLinkEntity> ();
|
||||
}
|
||||
|
||||
QosTxop::QosLinkEntity&
|
||||
QosTxop::GetLink (uint8_t linkId) const
|
||||
{
|
||||
return static_cast<QosLinkEntity&> (Txop::GetLink (linkId));
|
||||
}
|
||||
|
||||
uint8_t
|
||||
QosTxop::GetQosQueueSize (uint8_t tid, Mac48Address receiver) const
|
||||
{
|
||||
@@ -147,88 +154,90 @@ QosTxop::SetDroppedMpduCallback (DroppedMpdu callback)
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::SetMuCwMin (uint16_t cwMin)
|
||||
QosTxop::SetMuCwMin (uint16_t cwMin, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << cwMin);
|
||||
m_muCwMin = cwMin;
|
||||
NS_LOG_FUNCTION (this << cwMin << +linkId);
|
||||
GetLink (linkId).muCwMin = cwMin;
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::SetMuCwMax (uint16_t cwMax)
|
||||
QosTxop::SetMuCwMax (uint16_t cwMax, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << cwMax);
|
||||
m_muCwMax = cwMax;
|
||||
NS_LOG_FUNCTION (this << cwMax << +linkId);
|
||||
GetLink (linkId).muCwMax = cwMax;
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::SetMuAifsn (uint8_t aifsn)
|
||||
QosTxop::SetMuAifsn (uint8_t aifsn, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +aifsn);
|
||||
m_muAifsn = aifsn;
|
||||
NS_LOG_FUNCTION (this << +aifsn << +linkId);
|
||||
GetLink (linkId).muAifsn = aifsn;
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::SetMuEdcaTimer (Time timer)
|
||||
QosTxop::SetMuEdcaTimer (Time timer, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << timer);
|
||||
m_muEdcaTimer = timer;
|
||||
NS_LOG_FUNCTION (this << timer << +linkId);
|
||||
GetLink (linkId).muEdcaTimer = timer;
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::StartMuEdcaTimerNow (void)
|
||||
QosTxop::StartMuEdcaTimerNow (uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_muEdcaTimerStartTime = Simulator::Now ();
|
||||
if (EdcaDisabled ())
|
||||
NS_LOG_FUNCTION (this << +linkId);
|
||||
auto& link = GetLink (linkId);
|
||||
link.muEdcaTimerStartTime = Simulator::Now ();
|
||||
if (EdcaDisabled (linkId))
|
||||
{
|
||||
NS_LOG_DEBUG ("Disable EDCA for " << m_muEdcaTimer.As (Time::MS));
|
||||
m_mac->GetChannelAccessManager (SINGLE_LINK_OP_ID)->DisableEdcaFor (this, m_muEdcaTimer);
|
||||
NS_LOG_DEBUG ("Disable EDCA for " << link.muEdcaTimer.As (Time::MS));
|
||||
m_mac->GetChannelAccessManager (linkId)->DisableEdcaFor (this, link.muEdcaTimer);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
QosTxop::MuEdcaTimerRunning (void) const
|
||||
QosTxop::MuEdcaTimerRunning (uint8_t linkId) const
|
||||
{
|
||||
return (m_muEdcaTimerStartTime.IsStrictlyPositive () && m_muEdcaTimer.IsStrictlyPositive ()
|
||||
&& m_muEdcaTimerStartTime + m_muEdcaTimer > Simulator::Now ());
|
||||
auto& link = GetLink (linkId);
|
||||
return (link.muEdcaTimerStartTime.IsStrictlyPositive () && link.muEdcaTimer.IsStrictlyPositive ()
|
||||
&& link.muEdcaTimerStartTime + link.muEdcaTimer > Simulator::Now ());
|
||||
}
|
||||
|
||||
bool
|
||||
QosTxop::EdcaDisabled (void) const
|
||||
QosTxop::EdcaDisabled (uint8_t linkId) const
|
||||
{
|
||||
return (MuEdcaTimerRunning () && m_muAifsn == 0);
|
||||
return (MuEdcaTimerRunning (linkId) && GetLink (linkId).muAifsn == 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QosTxop::GetMinCw (void) const
|
||||
QosTxop::GetMinCw (uint8_t linkId) const
|
||||
{
|
||||
if (!MuEdcaTimerRunning ())
|
||||
if (!MuEdcaTimerRunning (linkId))
|
||||
{
|
||||
return m_cwMin;
|
||||
return GetLink (linkId).cwMin;
|
||||
}
|
||||
NS_ASSERT (!EdcaDisabled ());
|
||||
return m_muCwMin;
|
||||
NS_ASSERT (!EdcaDisabled (linkId));
|
||||
return GetLink (linkId).muCwMin;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QosTxop::GetMaxCw (void) const
|
||||
QosTxop::GetMaxCw (uint8_t linkId) const
|
||||
{
|
||||
if (!MuEdcaTimerRunning ())
|
||||
if (!MuEdcaTimerRunning (linkId))
|
||||
{
|
||||
return m_cwMax;
|
||||
return GetLink (linkId).cwMax;
|
||||
}
|
||||
NS_ASSERT (!EdcaDisabled ());
|
||||
return m_muCwMax;
|
||||
NS_ASSERT (!EdcaDisabled (linkId));
|
||||
return GetLink (linkId).muCwMax;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
QosTxop::GetAifsn (void) const
|
||||
QosTxop::GetAifsn (uint8_t linkId) const
|
||||
{
|
||||
if (!MuEdcaTimerRunning ())
|
||||
if (!MuEdcaTimerRunning (linkId))
|
||||
{
|
||||
return m_aifsn;
|
||||
return GetLink (linkId).aifsn;
|
||||
}
|
||||
return m_muAifsn;
|
||||
return GetLink (linkId).muAifsn;
|
||||
}
|
||||
|
||||
Ptr<BlockAckManager>
|
||||
|
||||
@@ -366,80 +366,118 @@ public:
|
||||
|
||||
/**
|
||||
* Set the minimum contention window size to use while the MU EDCA Timer
|
||||
* is running.
|
||||
* is running for the given link.
|
||||
*
|
||||
* \param cwMin the minimum contention window size.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetMuCwMin (uint16_t cwMin);
|
||||
void SetMuCwMin (uint16_t cwMin, uint8_t linkId);
|
||||
/**
|
||||
* Set the maximum contention window size to use while the MU EDCA Timer
|
||||
* is running.
|
||||
* is running for the given link.
|
||||
*
|
||||
* \param cwMax the maximum contention window size.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetMuCwMax (uint16_t cwMax);
|
||||
void SetMuCwMax (uint16_t cwMax, uint8_t linkId);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS while the MU EDCA Timer
|
||||
* is running.
|
||||
* is running for the given link.
|
||||
*
|
||||
* \param aifsn the number of slots that make up an AIFS.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetMuAifsn (uint8_t aifsn);
|
||||
void SetMuAifsn (uint8_t aifsn, uint8_t linkId);
|
||||
/**
|
||||
* Set the MU EDCA Timer.
|
||||
* Set the MU EDCA Timer for the given link.
|
||||
*
|
||||
* \param timer the timer duration.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetMuEdcaTimer (Time timer);
|
||||
void SetMuEdcaTimer (Time timer, uint8_t linkId);
|
||||
/**
|
||||
* Start the MU EDCA Timer.
|
||||
*/
|
||||
void StartMuEdcaTimerNow (void);
|
||||
/**
|
||||
* Return true if the MU EDCA Timer is running, false otherwise.
|
||||
* Start the MU EDCA Timer for the given link.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void StartMuEdcaTimerNow (uint8_t linkId);
|
||||
/**
|
||||
* Return true if the MU EDCA Timer is running for the given link, false otherwise.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return whether the MU EDCA Timer is running
|
||||
*/
|
||||
bool MuEdcaTimerRunning (void) const;
|
||||
bool MuEdcaTimerRunning (uint8_t linkId) const;
|
||||
/**
|
||||
* Return true if the EDCA is disabled (the MU EDCA Timer is running and the
|
||||
* MU AIFSN is zero), false otherwise.
|
||||
* MU AIFSN is zero) for the given link, false otherwise.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return whether the EDCA is disabled
|
||||
*/
|
||||
bool EdcaDisabled (void) const;
|
||||
bool EdcaDisabled (uint8_t linkId) const;
|
||||
/**
|
||||
* Return the minimum contention window size from the EDCA Parameter Set
|
||||
* or the MU EDCA Parameter Set, depending on whether the MU EDCA Timer is
|
||||
* running or not.
|
||||
*
|
||||
* \return the currently used minimum contention window size.
|
||||
*/
|
||||
uint32_t GetMinCw (void) const override;
|
||||
/**
|
||||
* Return the maximum contention window size from the EDCA Parameter Set
|
||||
* or the MU EDCA Parameter Set, depending on whether the MU EDCA Timer is
|
||||
* running or not.
|
||||
*
|
||||
* \return the currently used maximum contention window size.
|
||||
*/
|
||||
uint32_t GetMaxCw (void) const override;
|
||||
/**
|
||||
* Return the number of slots that make up an AIFS according to the
|
||||
* For the given link, return the minimum contention window size from the
|
||||
* EDCA Parameter Set or the MU EDCA Parameter Set, depending on whether the
|
||||
* MU EDCA Timer is running or not.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the currently used minimum contention window size.
|
||||
*/
|
||||
uint32_t GetMinCw (uint8_t linkId) const override;
|
||||
/**
|
||||
* For the given link, return the maximum contention window size from the
|
||||
* EDCA Parameter Set or the MU EDCA Parameter Set, depending on whether the
|
||||
* MU EDCA Timer is running or not.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the currently used maximum contention window size.
|
||||
*/
|
||||
uint32_t GetMaxCw (uint8_t linkId) const override;
|
||||
/**
|
||||
* For the given link, return the number of slots that make up an AIFS according
|
||||
* to the EDCA Parameter Set or the MU EDCA Parameter Set, depending on whether
|
||||
* the MU EDCA Timer is running or not.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the number of slots that currently make up an AIFS.
|
||||
*/
|
||||
uint8_t GetAifsn (void) const override;
|
||||
uint8_t GetAifsn (uint8_t linkId) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Structure holding information specific to a single link. Here, the meaning of
|
||||
* "link" is that of the 11be amendment which introduced multi-link devices. For
|
||||
* previous amendments, only one link can be created.
|
||||
*/
|
||||
struct QosLinkEntity : public Txop::LinkEntity
|
||||
{
|
||||
/// Destructor (a virtual method is needed to make this struct polymorphic)
|
||||
virtual ~QosLinkEntity () = default;
|
||||
|
||||
uint32_t muCwMin {0}; //!< the MU CW minimum
|
||||
uint32_t muCwMax {0}; //!< the MU CW maximum
|
||||
uint8_t muAifsn {0}; //!< the MU AIFSN
|
||||
Time muEdcaTimer {0}; //!< the MU EDCA Timer
|
||||
Time muEdcaTimerStartTime {0}; //!< last start time of the MU EDCA Timer
|
||||
};
|
||||
|
||||
void DoDispose (void) override;
|
||||
|
||||
/**
|
||||
* Get a reference to the link associated with the given ID.
|
||||
*
|
||||
* \param linkId the given link ID
|
||||
* \return a reference to the link associated with the given ID
|
||||
*/
|
||||
QosLinkEntity& GetLink (uint8_t linkId) const;
|
||||
|
||||
private:
|
||||
/// allow AggregationCapableTransmissionListener class access
|
||||
friend class AggregationCapableTransmissionListener;
|
||||
|
||||
std::unique_ptr<LinkEntity> CreateLinkEntity (void) const override;
|
||||
|
||||
/**
|
||||
* Check if the given MPDU is to be considered old according to the current
|
||||
* starting sequence number of the transmit window, provided that a block ack
|
||||
@@ -463,12 +501,6 @@ private:
|
||||
Time m_failedAddBaTimeout; //!< timeout after failed BA agreement
|
||||
bool m_useExplicitBarAfterMissedBlockAck; //!< flag whether explicit BlockAckRequest should be sent upon missed BlockAck Response
|
||||
|
||||
uint32_t m_muCwMin; //!< the MU CW minimum
|
||||
uint32_t m_muCwMax; //!< the MU CW maximum
|
||||
uint8_t m_muAifsn; //!< the MU AIFSN
|
||||
Time m_muEdcaTimer; //!< the MU EDCA Timer
|
||||
Time m_muEdcaTimerStartTime; //!< last start time of the MU EDCA Timer
|
||||
|
||||
TracedCallback<Time, Time> m_txopTrace; //!< TXOP trace callback
|
||||
};
|
||||
|
||||
|
||||
@@ -1181,9 +1181,9 @@ void
|
||||
StaWifiMac::SetEdcaParameters (AcIndex ac, uint32_t cwMin, uint32_t cwMax, uint8_t aifsn, Time txopLimit)
|
||||
{
|
||||
Ptr<QosTxop> edca = GetQosTxop (ac);
|
||||
edca->SetMinCw (cwMin);
|
||||
edca->SetMaxCw (cwMax);
|
||||
edca->SetAifsn (aifsn);
|
||||
edca->SetMinCw (cwMin, SINGLE_LINK_OP_ID);
|
||||
edca->SetMaxCw (cwMax, SINGLE_LINK_OP_ID);
|
||||
edca->SetAifsn (aifsn, SINGLE_LINK_OP_ID);
|
||||
edca->SetTxopLimit (txopLimit);
|
||||
}
|
||||
|
||||
@@ -1191,10 +1191,10 @@ void
|
||||
StaWifiMac::SetMuEdcaParameters (AcIndex ac, uint16_t cwMin, uint16_t cwMax, uint8_t aifsn, Time muEdcaTimer)
|
||||
{
|
||||
Ptr<QosTxop> edca = GetQosTxop (ac);
|
||||
edca->SetMuCwMin (cwMin);
|
||||
edca->SetMuCwMax (cwMax);
|
||||
edca->SetMuAifsn (aifsn);
|
||||
edca->SetMuEdcaTimer (muEdcaTimer);
|
||||
edca->SetMuCwMin (cwMin, SINGLE_LINK_OP_ID);
|
||||
edca->SetMuCwMax (cwMax, SINGLE_LINK_OP_ID);
|
||||
edca->SetMuAifsn (aifsn, SINGLE_LINK_OP_ID);
|
||||
edca->SetMuEdcaTimer (muEdcaTimer, SINGLE_LINK_OP_ID);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -46,20 +46,27 @@ Txop::GetTypeId (void)
|
||||
.SetParent<ns3::Object> ()
|
||||
.SetGroupName ("Wifi")
|
||||
.AddConstructor<Txop> ()
|
||||
.AddAttribute ("MinCw", "The minimum value of the contention window.",
|
||||
.AddAttribute ("MinCw",
|
||||
"The minimum value of the contention window (just for the first link, "
|
||||
"in case of 11be multi-link devices).",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
UintegerValue (15),
|
||||
MakeUintegerAccessor (&Txop::SetMinCw,
|
||||
&Txop::GetMinCw),
|
||||
MakeUintegerAccessor ((void (Txop::*) (uint32_t)) &Txop::SetMinCw,
|
||||
(uint32_t (Txop::*) (void) const) &Txop::GetMinCw),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("MaxCw", "The maximum value of the contention window.",
|
||||
.AddAttribute ("MaxCw", "The maximum value of the contention window (just for the first link, "
|
||||
"in case of 11be multi-link devices).",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
UintegerValue (1023),
|
||||
MakeUintegerAccessor (&Txop::SetMaxCw,
|
||||
&Txop::GetMaxCw),
|
||||
MakeUintegerAccessor ((void (Txop::*) (uint32_t)) &Txop::SetMaxCw,
|
||||
(uint32_t (Txop::*) (void) const) &Txop::GetMaxCw),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("Aifsn", "The AIFSN: the default value conforms to non-QOS.",
|
||||
.AddAttribute ("Aifsn", "The AIFSN: the default value conforms to non-QOS (just for the first link, "
|
||||
"in case of 11be multi-link devices).",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
UintegerValue (2),
|
||||
MakeUintegerAccessor (&Txop::SetAifsn,
|
||||
&Txop::GetAifsn),
|
||||
MakeUintegerAccessor ((void (Txop::*) (uint8_t)) &Txop::SetAifsn,
|
||||
(uint8_t (Txop::*) (void) const) &Txop::GetAifsn),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
.AddAttribute ("TxopLimit", "The TXOP limit: the default value conforms to non-QoS.",
|
||||
TimeValue (MilliSeconds (0)),
|
||||
@@ -77,7 +84,7 @@ Txop::GetTypeId (void)
|
||||
.AddTraceSource ("CwTrace",
|
||||
"Trace source for contention window values",
|
||||
MakeTraceSourceAccessor (&Txop::m_cwTrace),
|
||||
"ns3::TracedValueCallback::Uint32")
|
||||
"ns3::Txop::CwValueTracedCallback")
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@@ -89,9 +96,6 @@ Txop::Txop ()
|
||||
|
||||
Txop::Txop (Ptr<WifiMacQueue> queue)
|
||||
: m_queue (queue),
|
||||
m_cwMin (0),
|
||||
m_cwMax (0),
|
||||
m_cw (0),
|
||||
m_access (NOT_REQUESTED)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
@@ -175,50 +179,86 @@ Txop::GetWifiMacQueue () const
|
||||
void
|
||||
Txop::SetMinCw (uint32_t minCw)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << minCw);
|
||||
bool changed = (m_cwMin != minCw);
|
||||
m_cwMin = minCw;
|
||||
SetMinCw (minCw, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMinCws (std::vector<uint32_t> minCws)
|
||||
{
|
||||
NS_ABORT_IF (minCws.size () != m_links.size ());
|
||||
for (uint8_t linkId = 0; linkId < minCws.size (); linkId++)
|
||||
{
|
||||
SetMinCw (minCws[linkId], linkId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMinCw (uint32_t minCw, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << minCw << +linkId);
|
||||
auto& link = GetLink (linkId);
|
||||
bool changed = (link.cwMin != minCw);
|
||||
link.cwMin = minCw;
|
||||
if (changed == true)
|
||||
{
|
||||
ResetCw ();
|
||||
ResetCw (linkId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMaxCw (uint32_t maxCw)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << maxCw);
|
||||
bool changed = (m_cwMax != maxCw);
|
||||
m_cwMax = maxCw;
|
||||
SetMaxCw (maxCw, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMaxCws (std::vector<uint32_t> maxCws)
|
||||
{
|
||||
NS_ABORT_IF (maxCws.size () != m_links.size ());
|
||||
for (uint8_t linkId = 0; linkId < maxCws.size (); linkId++)
|
||||
{
|
||||
SetMaxCw (maxCws[linkId], linkId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMaxCw (uint32_t maxCw, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << maxCw << +linkId);
|
||||
auto& link = GetLink (linkId);
|
||||
bool changed = (link.cwMax != maxCw);
|
||||
link.cwMax = maxCw;
|
||||
if (changed == true)
|
||||
{
|
||||
ResetCw ();
|
||||
ResetCw (linkId);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Txop::GetCw (void) const
|
||||
Txop::GetCw (uint8_t linkId) const
|
||||
{
|
||||
return m_cw;
|
||||
return GetLink (linkId).cw;
|
||||
}
|
||||
|
||||
void
|
||||
Txop::ResetCw (void)
|
||||
Txop::ResetCw (uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_cw = GetMinCw ();
|
||||
m_cwTrace = m_cw;
|
||||
auto& link = GetLink (linkId);
|
||||
link.cw = GetMinCw (linkId);
|
||||
m_cwTrace (link.cw, linkId);
|
||||
}
|
||||
|
||||
void
|
||||
Txop::UpdateFailedCw (void)
|
||||
Txop::UpdateFailedCw (uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
auto& link = GetLink (linkId);
|
||||
//see 802.11-2012, section 9.19.2.5
|
||||
m_cw = std::min ( 2 * (m_cw + 1) - 1, GetMaxCw ());
|
||||
link.cw = std::min ( 2 * (link.cw + 1) - 1, GetMaxCw (linkId));
|
||||
// if the MU EDCA timer is running, CW cannot be less than MU CW min
|
||||
m_cw = std::max (m_cw, GetMinCw ());
|
||||
m_cwTrace = m_cw;
|
||||
link.cw = std::max (link.cw, GetMinCw (linkId));
|
||||
m_cwTrace (link.cw, linkId);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -265,8 +305,24 @@ Txop::StartBackoffNow (uint32_t nSlots, uint8_t linkId)
|
||||
void
|
||||
Txop::SetAifsn (uint8_t aifsn)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +aifsn);
|
||||
m_aifsn = aifsn;
|
||||
SetAifsn (aifsn, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetAifsns (std::vector<uint8_t> aifsns)
|
||||
{
|
||||
NS_ABORT_IF (aifsns.size () != m_links.size ());
|
||||
for (uint8_t linkId = 0; linkId < aifsns.size (); linkId++)
|
||||
{
|
||||
SetAifsn (aifsns[linkId], linkId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetAifsn (uint8_t aifsn, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +aifsn << +linkId);
|
||||
GetLink (linkId).aifsn = aifsn;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -280,19 +336,70 @@ Txop::SetTxopLimit (Time txopLimit)
|
||||
uint32_t
|
||||
Txop::GetMinCw (void) const
|
||||
{
|
||||
return m_cwMin;
|
||||
return GetMinCw (0);
|
||||
}
|
||||
|
||||
std::vector<uint32_t>
|
||||
Txop::GetMinCws (void) const
|
||||
{
|
||||
std::vector<uint32_t> ret;
|
||||
for (uint8_t linkId = 0; linkId < m_links.size (); linkId++)
|
||||
{
|
||||
ret.push_back (GetMinCw (linkId));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Txop::GetMinCw (uint8_t linkId) const
|
||||
{
|
||||
return GetLink (linkId).cwMin;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Txop::GetMaxCw (void) const
|
||||
{
|
||||
return m_cwMax;
|
||||
return GetMaxCw (0);
|
||||
}
|
||||
|
||||
std::vector<uint32_t>
|
||||
Txop::GetMaxCws (void) const
|
||||
{
|
||||
std::vector<uint32_t> ret;
|
||||
for (uint8_t linkId = 0; linkId < m_links.size (); linkId++)
|
||||
{
|
||||
ret.push_back (GetMaxCw (linkId));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Txop::GetMaxCw (uint8_t linkId) const
|
||||
{
|
||||
return GetLink (linkId).cwMax;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Txop::GetAifsn (void) const
|
||||
{
|
||||
return m_aifsn;
|
||||
return GetAifsn (0);
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
Txop::GetAifsns (void) const
|
||||
{
|
||||
std::vector<uint8_t> ret;
|
||||
for (uint8_t linkId = 0; linkId < m_links.size (); linkId++)
|
||||
{
|
||||
ret.push_back (GetAifsn (linkId));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Txop::GetAifsn (uint8_t linkId) const
|
||||
{
|
||||
return GetLink (linkId).aifsn;
|
||||
}
|
||||
|
||||
Time
|
||||
@@ -346,9 +453,9 @@ void
|
||||
Txop::DoInitialize ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
ResetCw ();
|
||||
for (uint8_t linkId = 0; linkId < m_links.size (); linkId++)
|
||||
{
|
||||
ResetCw (linkId);
|
||||
GenerateBackoff (linkId);
|
||||
}
|
||||
}
|
||||
@@ -398,7 +505,7 @@ void
|
||||
Txop::GenerateBackoff (uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +linkId);
|
||||
uint32_t backoff = m_rng->GetInteger (0, GetCw ());
|
||||
uint32_t backoff = m_rng->GetInteger (0, GetCw (linkId));
|
||||
m_backoffTrace (backoff, linkId);
|
||||
StartBackoffNow (backoff, linkId);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ns3/traced-value.h"
|
||||
#include "wifi-mac-header.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -130,23 +131,71 @@ public:
|
||||
Ptr<WifiMacQueue > GetWifiMacQueue () const;
|
||||
|
||||
/**
|
||||
* Set the minimum contention window size.
|
||||
* Set the minimum contention window size. For 11be multi-link devices,
|
||||
* set the minimum contention window size on the first link.
|
||||
*
|
||||
* \param minCw the minimum contention window size.
|
||||
*/
|
||||
void SetMinCw (uint32_t minCw);
|
||||
/**
|
||||
* Set the maximum contention window size.
|
||||
* Set the minimum contention window size for each link.
|
||||
* Note that the size of <i>minCws</i> must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param minCws the minimum contention window size values.
|
||||
*/
|
||||
void SetMinCws (std::vector<uint32_t> minCws);
|
||||
/**
|
||||
* Set the minimum contention window size for the given link.
|
||||
*
|
||||
* \param minCw the minimum contention window size.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetMinCw (uint32_t minCw, uint8_t linkId);
|
||||
/**
|
||||
* Set the maximum contention window size. For 11be multi-link devices,
|
||||
* set the maximum contention window size on the first link.
|
||||
*
|
||||
* \param maxCw the maximum contention window size.
|
||||
*/
|
||||
void SetMaxCw (uint32_t maxCw);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS.
|
||||
* Set the maximum contention window size for each link.
|
||||
* Note that the size of <i>maxCws</i> must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param maxCws the maximum contention window size values.
|
||||
*/
|
||||
void SetMaxCws (std::vector<uint32_t> maxCws);
|
||||
/**
|
||||
* Set the maximum contention window size for the given link.
|
||||
*
|
||||
* \param maxCw the maximum contention window size.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetMaxCw (uint32_t maxCw, uint8_t linkId);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS. For 11be multi-link devices,
|
||||
* set the number of slots that make up an AIFS on the first link.
|
||||
*
|
||||
* \param aifsn the number of slots that make up an AIFS.
|
||||
*/
|
||||
void SetAifsn (uint8_t aifsn);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS for each link.
|
||||
* Note that the size of <i>aifsns</i> must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param aifsns the number of slots that make up an AIFS for each link.
|
||||
*/
|
||||
void SetAifsns (std::vector<uint8_t> aifsns);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS for the given link.
|
||||
*
|
||||
* \param aifsn the number of slots that make up an AIFS.
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetAifsn (uint8_t aifsn, uint8_t linkId);
|
||||
/**
|
||||
* Set the TXOP limit.
|
||||
*
|
||||
@@ -155,23 +204,65 @@ public:
|
||||
*/
|
||||
void SetTxopLimit (Time txopLimit);
|
||||
/**
|
||||
* Return the minimum contention window size.
|
||||
* Return the minimum contention window size. For 11be multi-link devices,
|
||||
* return the minimum contention window size on the first link.
|
||||
*
|
||||
* \return the minimum contention window size.
|
||||
*/
|
||||
virtual uint32_t GetMinCw (void) const;
|
||||
uint32_t GetMinCw (void) const;
|
||||
/**
|
||||
* Return the maximum contention window size.
|
||||
* Return the minimum contention window size for each link.
|
||||
*
|
||||
* \return the minimum contention window size values.
|
||||
*/
|
||||
std::vector<uint32_t> GetMinCws (void) const;
|
||||
/**
|
||||
* Return the minimum contention window size for the given link.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the minimum contention window size.
|
||||
*/
|
||||
virtual uint32_t GetMinCw (uint8_t linkId) const;
|
||||
/**
|
||||
* Return the maximum contention window size. For 11be multi-link devices,
|
||||
* return the maximum contention window size on the first link.
|
||||
*
|
||||
* \return the maximum contention window size.
|
||||
*/
|
||||
virtual uint32_t GetMaxCw (void) const;
|
||||
uint32_t GetMaxCw (void) const;
|
||||
/**
|
||||
* Return the number of slots that make up an AIFS.
|
||||
* Return the maximum contention window size for each link.
|
||||
*
|
||||
* \return the maximum contention window size values.
|
||||
*/
|
||||
std::vector<uint32_t> GetMaxCws (void) const;
|
||||
/**
|
||||
* Return the maximum contention window size for the given link.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the maximum contention window size.
|
||||
*/
|
||||
virtual uint32_t GetMaxCw (uint8_t linkId) const;
|
||||
/**
|
||||
* Return the number of slots that make up an AIFS. For 11be multi-link devices,
|
||||
* return the number of slots that make up an AIFS on the first link.
|
||||
*
|
||||
* \return the number of slots that make up an AIFS.
|
||||
*/
|
||||
virtual uint8_t GetAifsn (void) const;
|
||||
uint8_t GetAifsn (void) const;
|
||||
/**
|
||||
* Return the number of slots that make up an AIFS for each link.
|
||||
*
|
||||
* \return the number of slots that make up an AIFS for each link.
|
||||
*/
|
||||
std::vector<uint8_t> GetAifsns (void) const;
|
||||
/**
|
||||
* Return the number of slots that make up an AIFS for the given link.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the number of slots that make up an AIFS.
|
||||
*/
|
||||
virtual uint8_t GetAifsn (uint8_t linkId) const;
|
||||
/**
|
||||
* Return the TXOP limit.
|
||||
*
|
||||
@@ -179,18 +270,22 @@ public:
|
||||
*/
|
||||
Time GetTxopLimit (void) const;
|
||||
/**
|
||||
* Update the value of the CW variable to take into account
|
||||
* Update the value of the CW variable for the given link to take into account
|
||||
* a transmission success or a transmission abort (stop transmission
|
||||
* of a packet after the maximum number of retransmissions has been
|
||||
* reached). By default, this resets the CW variable to minCW.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void ResetCw (void);
|
||||
void ResetCw (uint8_t linkId);
|
||||
/**
|
||||
* Update the value of the CW variable to take into account
|
||||
* Update the value of the CW variable for the given link to take into account
|
||||
* a transmission failure. By default, this triggers a doubling
|
||||
* of CW (capped by maxCW).
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void UpdateFailedCw (void);
|
||||
void UpdateFailedCw (uint8_t linkId);
|
||||
|
||||
/**
|
||||
* When sleep operation occurs, if there is a pending packet transmission,
|
||||
@@ -294,10 +389,13 @@ protected:
|
||||
void RequestAccess (void);
|
||||
|
||||
/**
|
||||
* \returns the current value of the CW variable. The initial value is
|
||||
* minCW.
|
||||
* Get the current value of the CW variable for the given link. The initial
|
||||
* value is minCw.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the current value of the CW variable for the given link
|
||||
*/
|
||||
uint32_t GetCw (void) const;
|
||||
uint32_t GetCw (uint8_t linkId) const;
|
||||
/**
|
||||
* Return the current number of backoff slots on the given link.
|
||||
*
|
||||
@@ -337,6 +435,10 @@ protected:
|
||||
track of the time at which a backoff was
|
||||
started or the time at which the backoff
|
||||
counter was last updated */
|
||||
uint32_t cw {0}; //!< the current contention window
|
||||
uint32_t cwMin {0}; //!< the minimum contention window
|
||||
uint32_t cwMax {0}; //!< the maximum contention window
|
||||
uint8_t aifsn {0}; //!< the AIFSN
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -359,19 +461,17 @@ protected:
|
||||
Ptr<WifiMac> m_mac; //!< the wifi MAC
|
||||
Ptr<UniformRandomVariable> m_rng; //!< the random stream
|
||||
|
||||
uint32_t m_cwMin; //!< the minimum contention window
|
||||
uint32_t m_cwMax; //!< the maximum contention window
|
||||
uint32_t m_cw; //!< the current contention window
|
||||
ChannelAccessStatus m_access; //!< channel access status
|
||||
|
||||
uint8_t m_aifsn; //!< the AIFSN
|
||||
Time m_txopLimit; //!< the TXOP limit time
|
||||
|
||||
/// TracedCallback for backoff trace value typedef
|
||||
typedef TracedCallback<uint32_t /* value */, uint8_t /* linkId */> BackoffValueTracedCallback;
|
||||
/// TracedCallback for CW trace value typedef
|
||||
typedef TracedCallback<uint32_t /* value */, uint8_t /* linkId */> CwValueTracedCallback;
|
||||
|
||||
BackoffValueTracedCallback m_backoffTrace; //!< backoff trace value
|
||||
TracedValue<uint32_t> m_cwTrace; //!< CW trace value
|
||||
CwValueTracedCallback m_cwTrace; //!< CW trace value
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -600,9 +600,9 @@ WifiMac::ConfigureDcf (Ptr<Txop> dcf, uint32_t cwmin, uint32_t cwmax, bool isDss
|
||||
switch (ac)
|
||||
{
|
||||
case AC_VO:
|
||||
dcf->SetMinCw ((cwmin + 1) / 4 - 1);
|
||||
dcf->SetMaxCw ((cwmin + 1) / 2 - 1);
|
||||
dcf->SetAifsn (2);
|
||||
dcf->SetMinCw ((cwmin + 1) / 4 - 1, SINGLE_LINK_OP_ID);
|
||||
dcf->SetMaxCw ((cwmin + 1) / 2 - 1, SINGLE_LINK_OP_ID);
|
||||
dcf->SetAifsn (2, SINGLE_LINK_OP_ID);
|
||||
if (isDsss)
|
||||
{
|
||||
dcf->SetTxopLimit (MicroSeconds (3264));
|
||||
@@ -613,9 +613,9 @@ WifiMac::ConfigureDcf (Ptr<Txop> dcf, uint32_t cwmin, uint32_t cwmax, bool isDss
|
||||
}
|
||||
break;
|
||||
case AC_VI:
|
||||
dcf->SetMinCw ((cwmin + 1) / 2 - 1);
|
||||
dcf->SetMaxCw (cwmin);
|
||||
dcf->SetAifsn (2);
|
||||
dcf->SetMinCw ((cwmin + 1) / 2 - 1, SINGLE_LINK_OP_ID);
|
||||
dcf->SetMaxCw (cwmin, SINGLE_LINK_OP_ID);
|
||||
dcf->SetAifsn (2, SINGLE_LINK_OP_ID);
|
||||
if (isDsss)
|
||||
{
|
||||
dcf->SetTxopLimit (MicroSeconds (6016));
|
||||
@@ -626,21 +626,21 @@ WifiMac::ConfigureDcf (Ptr<Txop> dcf, uint32_t cwmin, uint32_t cwmax, bool isDss
|
||||
}
|
||||
break;
|
||||
case AC_BE:
|
||||
dcf->SetMinCw (cwmin);
|
||||
dcf->SetMaxCw (cwmax);
|
||||
dcf->SetAifsn (3);
|
||||
dcf->SetMinCw (cwmin, SINGLE_LINK_OP_ID);
|
||||
dcf->SetMaxCw (cwmax, SINGLE_LINK_OP_ID);
|
||||
dcf->SetAifsn (3, SINGLE_LINK_OP_ID);
|
||||
dcf->SetTxopLimit (MicroSeconds (0));
|
||||
break;
|
||||
case AC_BK:
|
||||
dcf->SetMinCw (cwmin);
|
||||
dcf->SetMaxCw (cwmax);
|
||||
dcf->SetAifsn (7);
|
||||
dcf->SetMinCw (cwmin, SINGLE_LINK_OP_ID);
|
||||
dcf->SetMaxCw (cwmax, SINGLE_LINK_OP_ID);
|
||||
dcf->SetAifsn (7, SINGLE_LINK_OP_ID);
|
||||
dcf->SetTxopLimit (MicroSeconds (0));
|
||||
break;
|
||||
case AC_BE_NQOS:
|
||||
dcf->SetMinCw (cwmin);
|
||||
dcf->SetMaxCw (cwmax);
|
||||
dcf->SetAifsn (2);
|
||||
dcf->SetMinCw (cwmin, SINGLE_LINK_OP_ID);
|
||||
dcf->SetMaxCw (cwmax, SINGLE_LINK_OP_ID);
|
||||
dcf->SetAifsn (2, SINGLE_LINK_OP_ID);
|
||||
dcf->SetTxopLimit (MicroSeconds (0));
|
||||
break;
|
||||
case AC_BEACON:
|
||||
|
||||
@@ -592,13 +592,13 @@ void
|
||||
ChannelAccessManagerTest<TxopType>::AddTxop (uint32_t aifsn)
|
||||
{
|
||||
Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
|
||||
txop->SetAifsn (aifsn);
|
||||
m_txop.push_back (txop);
|
||||
m_ChannelAccessManager->Add (txop);
|
||||
// the following causes the creation of a link for the txop object
|
||||
auto mac = CreateObject<AdhocWifiMac> ();
|
||||
mac->SetWifiPhys ({nullptr});
|
||||
txop->SetWifiMac (mac);
|
||||
txop->SetAifsn (aifsn);
|
||||
}
|
||||
|
||||
template <typename TxopType>
|
||||
|
||||
@@ -361,10 +361,9 @@ public:
|
||||
/**
|
||||
* Function to trace CW value used by the given station after the MU exchange
|
||||
* \param staIndex the index of the given station
|
||||
* \param oldCw the previous Contention Window value
|
||||
* \param cw the current Contention Window value
|
||||
*/
|
||||
void TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw);
|
||||
void TraceCw (uint32_t staIndex, uint32_t cw, uint8_t /* linkId */);
|
||||
/**
|
||||
* Callback invoked when FrameExchangeManager passes PSDUs to the PHY
|
||||
* \param context the context
|
||||
@@ -444,7 +443,7 @@ OfdmaAckSequenceTest::L7Receive (std::string context, Ptr<const Packet> p, const
|
||||
}
|
||||
|
||||
void
|
||||
OfdmaAckSequenceTest::TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw)
|
||||
OfdmaAckSequenceTest::TraceCw (uint32_t staIndex, uint32_t cw, uint8_t /* linkId */)
|
||||
{
|
||||
if (m_cwValues.at (staIndex) == 2)
|
||||
{
|
||||
@@ -1268,7 +1267,7 @@ OfdmaAckSequenceTest::DoRun (void)
|
||||
Simulator::Run ();
|
||||
|
||||
CheckResults (dev->GetMac ()->GetWifiPhy ()->GetSifs (), dev->GetMac ()->GetWifiPhy ()->GetSlot (),
|
||||
apBeQosTxop->GetAifsn ());
|
||||
apBeQosTxop->Txop::GetAifsn ());
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
@@ -224,8 +224,8 @@ WifiTxopTest::DoRun (void)
|
||||
PointerValue ptr;
|
||||
dev->GetMac ()->GetAttribute ("BE_Txop", ptr);
|
||||
ptr.Get<QosTxop> ()->SetTxopLimit (m_txopLimit);
|
||||
m_aifsn = ptr.Get<QosTxop> ()->GetAifsn ();
|
||||
m_cwMin = ptr.Get<QosTxop> ()->GetMinCw ();
|
||||
m_aifsn = ptr.Get<QosTxop> ()->Txop::GetAifsn ();
|
||||
m_cwMin = ptr.Get<QosTxop> ()->Txop::GetMinCw ();
|
||||
|
||||
PacketSocketHelper packetSocket;
|
||||
packetSocket.Install (wifiApNode);
|
||||
|
||||
Reference in New Issue
Block a user