wifi: FCFS queue scheduler prioritizes control frames

This commit is contained in:
Stefano Avallone
2022-11-23 12:23:04 +01:00
committed by Stefano Avallone
parent 45f726abd7
commit 4bf26a41aa
2 changed files with 90 additions and 36 deletions

View File

@@ -29,6 +29,38 @@ namespace ns3
NS_LOG_COMPONENT_DEFINE("FcfsWifiQueueScheduler");
bool
operator==(const FcfsPrio& lhs, const FcfsPrio& rhs)
{
return lhs.priority == rhs.priority && lhs.type == rhs.type;
}
bool
operator<(const FcfsPrio& lhs, const FcfsPrio& rhs)
{
// Control queues have the highest priority
if (lhs.type == WIFI_CTL_QUEUE && rhs.type != WIFI_CTL_QUEUE)
{
return true;
}
if (lhs.type != WIFI_CTL_QUEUE && rhs.type == WIFI_CTL_QUEUE)
{
return false;
}
// Management queues have the second highest priority
if (lhs.type == WIFI_MGT_QUEUE && rhs.type != WIFI_MGT_QUEUE)
{
return true;
}
if (lhs.type != WIFI_MGT_QUEUE && rhs.type == WIFI_MGT_QUEUE)
{
return false;
}
// we get here if both priority values refer to container queues of the same type,
// hence we can compare the time values.
return lhs.priority < rhs.priority;
}
NS_OBJECT_ENSURE_REGISTERED(FcfsWifiQueueScheduler);
TypeId
@@ -65,23 +97,31 @@ FcfsWifiQueueScheduler::HasToDropBeforeEnqueuePriv(AcIndex ac, Ptr<WifiMpdu> mpd
return nullptr;
}
// Management frames should be prioritized
if (m_dropPolicy == DROP_OLDEST || mpdu->GetHeader().IsMgt())
// Control and management frames should be prioritized
if (m_dropPolicy == DROP_OLDEST || mpdu->GetHeader().IsCtl() || mpdu->GetHeader().IsMgt())
{
auto sortedQueuesIt = GetSortedQueues(ac).begin();
while (sortedQueuesIt != GetSortedQueues(ac).end() &&
std::get<WifiContainerQueueType>(sortedQueuesIt->second.get().first) ==
WIFI_MGT_QUEUE)
for (const auto& [priority, queueInfo] : GetSortedQueues(ac))
{
sortedQueuesIt++;
}
if (std::get<WifiContainerQueueType>(queueInfo.get().first) == WIFI_MGT_QUEUE ||
std::get<WifiContainerQueueType>(queueInfo.get().first) == WIFI_CTL_QUEUE)
{
// do not drop control or management frames
continue;
}
if (sortedQueuesIt != GetSortedQueues(ac).end())
{
return queue->PeekByQueueId(sortedQueuesIt->second.get().first);
// do not drop frames that are inflight or to be retransmitted
Ptr<WifiMpdu> item;
while ((item = queue->PeekByQueueId(queueInfo.get().first, item)))
{
if (!item->IsInFlight() && !item->GetHeader().IsRetry())
{
NS_LOG_DEBUG("Dropping " << *item);
return item;
}
}
}
}
NS_LOG_DEBUG("Dropping received MPDU: " << *mpdu);
return mpdu;
}
@@ -100,10 +140,7 @@ FcfsWifiQueueScheduler::DoNotifyEnqueue(AcIndex ac, Ptr<WifiMpdu> mpdu)
return;
}
auto priority =
(mpdu->GetHeader().IsMgt() ? Seconds(0) // Highest priority for management frames
: mpdu->GetExpiryTime());
SetPriority(ac, queueId, priority);
SetPriority(ac, queueId, {mpdu->GetExpiryTime(), std::get<WifiContainerQueueType>(queueId)});
}
void
@@ -120,15 +157,11 @@ FcfsWifiQueueScheduler::DoNotifyDequeue(AcIndex ac, const std::list<Ptr<WifiMpdu
for (const auto& queueId : queueIds)
{
if (std::get<WifiContainerQueueType>(queueId) == WIFI_MGT_QUEUE)
if (auto item = GetWifiMacQueue(ac)->PeekByQueueId(queueId))
{
// the priority of management queues does not change
continue;
}
if (auto item = GetWifiMacQueue(ac)->PeekByQueueId(queueId); item != nullptr)
{
SetPriority(ac, queueId, item->GetExpiryTime());
SetPriority(ac,
queueId,
{item->GetExpiryTime(), std::get<WifiContainerQueueType>(queueId)});
}
}
}
@@ -147,15 +180,11 @@ FcfsWifiQueueScheduler::DoNotifyRemove(AcIndex ac, const std::list<Ptr<WifiMpdu>
for (const auto& queueId : queueIds)
{
if (std::get<0>(queueId) == WIFI_MGT_QUEUE)
if (auto item = GetWifiMacQueue(ac)->PeekByQueueId(queueId))
{
// the priority of management queues does not change
continue;
}
if (auto item = GetWifiMacQueue(ac)->PeekByQueueId(queueId); item != nullptr)
{
SetPriority(ac, queueId, item->GetExpiryTime());
SetPriority(ac,
queueId,
{item->GetExpiryTime(), std::get<WifiContainerQueueType>(queueId)});
}
}
}

View File

@@ -32,11 +32,36 @@ class WifiMpdu;
/**
* \ingroup wifi
*
* FcfsWifiQueueScheduler is a wifi queue scheduler that serves data frames in a
* first come first serve fashion. Management frames have higher priority than data
* frames, hence the former will be served before the latter.
* Definition of priority for container queues.
*/
class FcfsWifiQueueScheduler : public WifiMacQueueSchedulerImpl<Time>
struct FcfsPrio
{
Time priority; ///< time priority
WifiContainerQueueType type; ///< type of container queue
};
/**
* \param lhs the left hand side priority
* \param rhs the right hand side priority
* \return whether the left hand side priority is equal to the right hand side priority
*/
bool operator==(const FcfsPrio& lhs, const FcfsPrio& rhs);
/**
* \param lhs the left hand side priority
* \param rhs the right hand side priority
* \return whether the left hand side priority is less than the right hand side priority
*/
bool operator<(const FcfsPrio& lhs, const FcfsPrio& rhs);
/**
* \ingroup wifi
*
* FcfsWifiQueueScheduler is a wifi queue scheduler that serves data frames in a
* first come first serve fashion. Control frames have the highest priority.
* Management frames have the second highest priority. Hence, data frames are
* served after control and management frames.
*/
class FcfsWifiQueueScheduler : public WifiMacQueueSchedulerImpl<FcfsPrio>
{
public:
/**