diff --git a/examples/wireless/examples-to-run.py b/examples/wireless/examples-to-run.py index 00e61973c..14a28a7d8 100755 --- a/examples/wireless/examples-to-run.py +++ b/examples/wireless/examples-to-run.py @@ -180,7 +180,7 @@ cpp_examples = [ "True", ), ( - "wifi-eht-network --simulationTime=0.2 --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=4 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=50 --maxExpectedThroughput=415", + "wifi-eht-network --simulationTime=0.2 --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=7 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=70 --maxExpectedThroughput=550", "True", "True", ), diff --git a/src/wifi/model/txop.cc b/src/wifi/model/txop.cc index db3415950..a9c0e9631 100644 --- a/src/wifi/model/txop.cc +++ b/src/wifi/model/txop.cc @@ -29,10 +29,12 @@ #include "ns3/attribute-container.h" #include "ns3/log.h" #include "ns3/pointer.h" -#include "ns3/random-variable-stream.h" #include "ns3/simulator.h" #include "ns3/socket.h" +#include +#include + #undef NS_LOG_APPEND_CONTEXT #define NS_LOG_APPEND_CONTEXT WIFI_TXOP_NS_LOG_APPEND_CONTEXT @@ -137,7 +139,7 @@ Txop::Txop(Ptr queue) : m_queue(queue) { NS_LOG_FUNCTION(this); - m_rng = CreateObject(); + m_rng = m_shuffleLinkIdsGen.GetRv(); } Txop::~Txop() @@ -529,9 +531,22 @@ void Txop::Queue(Ptr mpdu) { NS_LOG_FUNCTION(this << *mpdu); - const auto linkIds = m_mac->GetMacQueueScheduler()->GetLinkIds(m_queue->GetAc(), mpdu); + auto linkIds = m_mac->GetMacQueueScheduler()->GetLinkIds(m_queue->GetAc(), mpdu); std::map hasFramesToTransmit; + // ignore the links for which a channel access request event is already running + for (auto it = linkIds.begin(); it != linkIds.end();) + { + if (const auto& event = GetLink(*it).accessRequest.event; event.IsRunning()) + { + it = linkIds.erase(it); + } + else + { + ++it; + } + } + // save the status of the AC queues before enqueuing the MPDU (required to determine if // backoff is needed) for (const auto linkId : linkIds) @@ -539,20 +554,31 @@ Txop::Queue(Ptr mpdu) hasFramesToTransmit[linkId] = HasFramesToTransmit(linkId); } m_queue->Enqueue(mpdu); - for (const auto linkId : linkIds) + + // shuffle link IDs not to request channel access on links always in the same order + std::vector shuffledLinkIds(linkIds.cbegin(), linkIds.cend()); + std::shuffle(shuffledLinkIds.begin(), shuffledLinkIds.end(), m_shuffleLinkIdsGen); + + if (!linkIds.empty() && g_log.IsEnabled(ns3::LOG_DEBUG)) + { + std::stringstream ss; + std::copy(shuffledLinkIds.cbegin(), + shuffledLinkIds.cend(), + std::ostream_iterator(ss, " ")); + NS_LOG_DEBUG("Request channel access on link IDs: " << ss.str()); + } + + for (const auto linkId : shuffledLinkIds) { // schedule a call to StartAccessIfNeeded() to request channel access after that all the // packets of a burst have been enqueued, instead of requesting channel access right after // the first packet. The call to StartAccessIfNeeded() is scheduled only after the first // packet - if (auto& event = GetLink(linkId).accessRequest.event; !event.IsRunning()) - { - event = Simulator::ScheduleNow(&Txop::StartAccessAfterEvent, - this, - linkId, - hasFramesToTransmit.at(linkId), - CHECK_MEDIUM_BUSY); - } + GetLink(linkId).accessRequest.event = Simulator::ScheduleNow(&Txop::StartAccessAfterEvent, + this, + linkId, + hasFramesToTransmit.at(linkId), + CHECK_MEDIUM_BUSY); } } diff --git a/src/wifi/model/txop.h b/src/wifi/model/txop.h index 11140f5e9..ba80a9ee8 100644 --- a/src/wifi/model/txop.h +++ b/src/wifi/model/txop.h @@ -25,6 +25,7 @@ #include "ns3/nstime.h" #include "ns3/object.h" #include "ns3/traced-value.h" +#include "ns3/uniform-random-bit-generator.h" #include #include @@ -555,11 +556,12 @@ class Txop : public Object */ const std::map>& GetLinks() const; - DroppedMpdu m_droppedMpduCallback; //!< the dropped MPDU callback - Ptr m_queue; //!< the wifi MAC queue - Ptr m_txMiddle; //!< the MacTxMiddle - Ptr m_mac; //!< the wifi MAC - Ptr m_rng; //!< the random stream + DroppedMpdu m_droppedMpduCallback; //!< the dropped MPDU callback + Ptr m_queue; //!< the wifi MAC queue + Ptr m_txMiddle; //!< the MacTxMiddle + Ptr m_mac; //!< the wifi MAC + Ptr m_rng; //!< the random stream + UniformRandomBitGenerator m_shuffleLinkIdsGen; //!< random number generator to shuffle link IDs /// TracedCallback for backoff trace value typedef typedef TracedCallback BackoffValueTracedCallback;