A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-mac-queue-container.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "ctrl-headers.h"
12#include "wifi-mpdu.h"
13
14#include "ns3/mac48-address.h"
15#include "ns3/simulator.h"
16
17#include <vector>
18
19namespace ns3
20{
21
22void
24{
25 m_queues.clear();
26 m_expiredQueue.clear();
27 m_nBytesPerQueue.clear();
28}
29
32{
33 WifiContainerQueueId queueId = GetQueueId(item);
34
35 NS_ABORT_MSG_UNLESS(pos == m_queues[queueId].cend() || GetQueueId(pos->mpdu) == queueId,
36 "pos iterator does not point to the correct container queue");
37 NS_ABORT_MSG_IF(!item->IsOriginal(), "Only the original copy of an MPDU can be inserted");
38
39 auto [it, ret] = m_nBytesPerQueue.insert({queueId, 0});
40 it->second += item->GetSize();
41
42 return m_queues[queueId].emplace(pos, item);
43}
44
47{
48 if (pos->expired)
49 {
50 return m_expiredQueue.erase(pos);
51 }
52
53 WifiContainerQueueId queueId = GetQueueId(pos->mpdu);
54 auto it = m_nBytesPerQueue.find(queueId);
55 NS_ASSERT(it != m_nBytesPerQueue.end());
56 NS_ASSERT(it->second >= pos->mpdu->GetSize());
57 it->second -= pos->mpdu->GetSize();
58
59 return m_queues[queueId].erase(pos);
60}
61
64{
65 return it->mpdu;
66}
67
70{
71 const WifiMacHeader& hdr = mpdu->GetHeader();
72
74 Mac48Address address;
75 if (hdr.GetAddr1().IsBroadcast())
76 {
77 addrType = WIFI_BROADCAST;
78 address = hdr.GetAddr2();
79 }
80 else if (hdr.GetAddr1().IsGroup())
81 {
82 addrType = WIFI_GROUPCAST;
83 address = hdr.IsQosAmsdu() ? mpdu->begin()->second.GetDestinationAddr() : hdr.GetAddr1();
84 }
85 else
86 {
87 addrType = WIFI_UNICAST;
88 address = hdr.GetAddr1();
89 }
90
91 if (hdr.IsCtl())
92 {
93 return {WIFI_CTL_QUEUE, addrType, address, std::nullopt};
94 }
95 if (hdr.IsMgt())
96 {
97 return {WIFI_MGT_QUEUE, addrType, address, std::nullopt};
98 }
99 if (hdr.IsQosData())
100 {
101 return {WIFI_QOSDATA_QUEUE, addrType, address, hdr.GetQosTid()};
102 }
103 return {WIFI_DATA_QUEUE, addrType, address, std::nullopt};
104}
105
108{
109 return m_queues[queueId];
110}
111
114{
115 if (auto it = m_queues.find(queueId); it == m_queues.end() || it->second.empty())
116 {
117 return 0;
118 }
119 return m_nBytesPerQueue.at(queueId);
120}
121
122std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
127
128std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
130{
131 std::optional<std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>> ret;
132 auto firstExpiredIt = queue.begin();
133 auto lastExpiredIt = firstExpiredIt;
134 Time now = Simulator::Now();
135
136 do
137 {
138 // advance firstExpiredIt and lastExpiredIt to skip all inflight MPDUs
139 for (firstExpiredIt = lastExpiredIt;
140 firstExpiredIt != queue.end() && !firstExpiredIt->inflights.empty();
141 ++firstExpiredIt, ++lastExpiredIt)
142 {
143 }
144
145 if (!ret)
146 {
147 // we get here in the first iteration only
148 ret = std::make_pair(firstExpiredIt, lastExpiredIt);
149 }
150
151 // advance lastExpiredIt as we encounter MPDUs with expired lifetime that are not inflight
152 while (lastExpiredIt != queue.end() && lastExpiredIt->expiryTime <= now &&
153 lastExpiredIt->inflights.empty())
154 {
155 lastExpiredIt->expired = true;
156 // this MPDU is no longer queued
157 lastExpiredIt->ac = AC_UNDEF;
158 lastExpiredIt->deleter(lastExpiredIt->mpdu);
159
160 WifiContainerQueueId queueId = GetQueueId(lastExpiredIt->mpdu);
161 auto it = m_nBytesPerQueue.find(queueId);
162 NS_ASSERT(it != m_nBytesPerQueue.end());
163 NS_ASSERT(it->second >= lastExpiredIt->mpdu->GetSize());
164 it->second -= lastExpiredIt->mpdu->GetSize();
165
166 ++lastExpiredIt;
167 }
168
169 if (lastExpiredIt == firstExpiredIt)
170 {
171 break;
172 }
173
174 // transfer non-inflight MPDUs with expired lifetime to the tail of m_expiredQueue
175 m_expiredQueue.splice(m_expiredQueue.end(), queue, firstExpiredIt, lastExpiredIt);
176 ret->second = m_expiredQueue.end();
177
178 } while (true);
179
180 return *ret;
181}
182
183std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
185{
186 std::optional<WifiMacQueueContainer::iterator> firstExpiredIt;
187
188 for (auto& queue : m_queues)
189 {
190 auto [firstIt, lastIt] = DoExtractExpiredMpdus(queue.second);
191
192 if (firstIt != lastIt && !firstExpiredIt)
193 {
194 // this is the first queue with MPDUs with expired lifetime
195 firstExpiredIt = firstIt;
196 }
197 }
198 return std::make_pair(firstExpiredIt ? *firstExpiredIt : m_expiredQueue.end(),
199 m_expiredQueue.end());
200}
201
202std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
204{
205 return {m_expiredQueue.begin(), m_expiredQueue.end()};
206}
207
208} // namespace ns3
209
210/****************************************************
211 * Global Functions (outside namespace ns3)
212 ***************************************************/
213
214std::size_t
215std::hash<ns3::WifiContainerQueueId>::operator()(ns3::WifiContainerQueueId queueId) const
216{
217 auto [type, addrType, address, tid] = queueId;
218 const std::size_t size = tid.has_value() ? 8 : 7;
219
220 std::vector<uint8_t> buffer(size);
221 buffer[0] = type;
222 address.CopyTo(&buffer[1]);
223 if (tid.has_value())
224 {
225 buffer[7] = *tid;
226 }
227
228 std::string s(buffer.begin(), buffer.end());
229 return std::hash<std::string>{}(s);
230}
an EUI-48 address
bool IsGroup() const
bool IsBroadcast() const
Smart pointer class similar to boost::intrusive_ptr.
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
bool IsQosAmsdu() const
Check if IsQosData() is true and the A-MSDU present bit is set in the QoS control field.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
bool IsMgt() const
Return true if the Type is Management.
bool IsCtl() const
Return true if the Type is Control.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
const ContainerQueue & GetQueue(const WifiContainerQueueId &queueId) const
Get a const reference to the container queue identified by the given QueueId.
void clear()
Erase all elements from the container.
static WifiContainerQueueId GetQueueId(Ptr< const WifiMpdu > mpdu)
Return the QueueId identifying the container queue in which the given MPDU is (or is to be) enqueued.
ContainerQueue::iterator iterator
iterator over elements in a container queue
std::unordered_map< WifiContainerQueueId, uint32_t > m_nBytesPerQueue
size in bytes of the container queues
uint32_t GetNBytes(const WifiContainerQueueId &queueId) const
Get the total size of the MPDUs stored in the queue identified by the given QueueId.
Ptr< WifiMpdu > GetItem(const const_iterator it) const
Return the WifiMpdu included in the element pointed to by the given iterator.
std::pair< iterator, iterator > ExtractAllExpiredMpdus() const
Transfer non-inflight MPDUs with expired lifetime in all the container queues to the container queue ...
iterator insert(const_iterator pos, Ptr< WifiMpdu > item)
Insert the given item at the specified location in the container.
std::unordered_map< WifiContainerQueueId, ContainerQueue > m_queues
the container queues
std::list< WifiMacQueueElem > ContainerQueue
Type of a queue held by the container.
iterator erase(const_iterator pos)
Erase the specified elements from the container.
std::pair< iterator, iterator > GetAllExpiredMpdus() const
Get the range [first, last) of iterators pointing to all the MPDUs queued in the container queue stor...
ContainerQueue::const_iterator const_iterator
const iterator over elements in a container queue
ContainerQueue m_expiredQueue
queue storing MPDUs with expired lifetime
std::pair< iterator, iterator > ExtractExpiredMpdus(const WifiContainerQueueId &queueId) const
Transfer non-inflight MPDUs with expired lifetime in the container queue identified by the given Queu...
std::pair< iterator, iterator > DoExtractExpiredMpdus(ContainerQueue &queue) const
Transfer non-inflight MPDUs with expired lifetime in the given container queue to the container queue...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
@ AC_UNDEF
Total number of ACs.
Definition qos-utils.h:76
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
WifiReceiverAddressType
enumeration of frame directions