A Discrete-Event Network Simulator
API
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  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Stefano Avallone <stavallo@unina.it>
18  */
19 
21 
22 #include "ctrl-headers.h"
23 #include "wifi-mpdu.h"
24 
25 #include "ns3/mac48-address.h"
26 #include "ns3/simulator.h"
27 
28 namespace ns3
29 {
30 
31 void
33 {
34  m_queues.clear();
35  m_expiredQueue.clear();
36  m_nBytesPerQueue.clear();
37 }
38 
41 {
42  WifiContainerQueueId queueId = GetQueueId(item);
43 
44  NS_ABORT_MSG_UNLESS(pos == m_queues[queueId].cend() || GetQueueId(pos->mpdu) == queueId,
45  "pos iterator does not point to the correct container queue");
46  NS_ABORT_MSG_IF(!item->IsOriginal(), "Only the original copy of an MPDU can be inserted");
47 
48  auto [it, ret] = m_nBytesPerQueue.insert({queueId, 0});
49  it->second += item->GetSize();
50 
51  return m_queues[queueId].emplace(pos, item);
52 }
53 
56 {
57  if (pos->expired)
58  {
59  return m_expiredQueue.erase(pos);
60  }
61 
62  WifiContainerQueueId queueId = GetQueueId(pos->mpdu);
63  auto it = m_nBytesPerQueue.find(queueId);
64  NS_ASSERT(it != m_nBytesPerQueue.end());
65  NS_ASSERT(it->second >= pos->mpdu->GetSize());
66  it->second -= pos->mpdu->GetSize();
67 
68  return m_queues[queueId].erase(pos);
69 }
70 
73 {
74  return it->mpdu;
75 }
76 
79 {
80  const WifiMacHeader& hdr = mpdu->GetHeader();
81 
82  if (hdr.IsCtl())
83  {
84  return {WIFI_CTL_QUEUE, hdr.GetAddr2(), std::nullopt};
85  }
86  if (hdr.IsMgt())
87  {
88  return {WIFI_MGT_QUEUE, hdr.GetAddr2(), std::nullopt};
89  }
90  if (hdr.IsQosData())
91  {
92  if (hdr.GetAddr1().IsGroup())
93  {
94  return {WIFI_QOSDATA_BROADCAST_QUEUE, hdr.GetAddr2(), hdr.GetQosTid()};
95  }
96  return {WIFI_QOSDATA_UNICAST_QUEUE, hdr.GetAddr1(), hdr.GetQosTid()};
97  }
98  return {WIFI_DATA_QUEUE, hdr.GetAddr1(), std::nullopt};
99 }
100 
103 {
104  return m_queues[queueId];
105 }
106 
107 uint32_t
109 {
110  if (auto it = m_queues.find(queueId); it == m_queues.end() || it->second.empty())
111  {
112  return 0;
113  }
114  return m_nBytesPerQueue.at(queueId);
115 }
116 
117 std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
119 {
120  return DoExtractExpiredMpdus(m_queues[queueId]);
121 }
122 
123 std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
125 {
126  std::optional<std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>> ret;
127  iterator firstExpiredIt = queue.begin();
128  iterator lastExpiredIt = firstExpiredIt;
129  Time now = Simulator::Now();
130 
131  do
132  {
133  // advance firstExpiredIt and lastExpiredIt to skip all inflight MPDUs
134  for (firstExpiredIt = lastExpiredIt;
135  firstExpiredIt != queue.end() && !firstExpiredIt->inflights.empty();
136  ++firstExpiredIt, ++lastExpiredIt)
137  {
138  }
139 
140  if (!ret)
141  {
142  // we get here in the first iteration only
143  ret = std::make_pair(firstExpiredIt, lastExpiredIt);
144  }
145 
146  // advance lastExpiredIt as we encounter MPDUs with expired lifetime that are not inflight
147  while (lastExpiredIt != queue.end() && lastExpiredIt->expiryTime <= now &&
148  lastExpiredIt->inflights.empty())
149  {
150  lastExpiredIt->expired = true;
151  // this MPDU is no longer queued
152  lastExpiredIt->ac = AC_UNDEF;
153  lastExpiredIt->deleter(lastExpiredIt->mpdu);
154 
155  WifiContainerQueueId queueId = GetQueueId(lastExpiredIt->mpdu);
156  auto it = m_nBytesPerQueue.find(queueId);
157  NS_ASSERT(it != m_nBytesPerQueue.end());
158  NS_ASSERT(it->second >= lastExpiredIt->mpdu->GetSize());
159  it->second -= lastExpiredIt->mpdu->GetSize();
160 
161  ++lastExpiredIt;
162  }
163 
164  if (lastExpiredIt != firstExpiredIt)
165  {
166  // transfer non-inflight MPDUs with expired lifetime to the tail of m_expiredQueue
167  m_expiredQueue.splice(m_expiredQueue.end(), queue, firstExpiredIt, lastExpiredIt);
168  ret->second = m_expiredQueue.end();
169  }
170 
171  } while (lastExpiredIt != firstExpiredIt);
172 
173  return *ret;
174 }
175 
176 std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
178 {
179  std::optional<WifiMacQueueContainer::iterator> firstExpiredIt;
180 
181  for (auto& queue : m_queues)
182  {
183  auto [firstIt, lastIt] = DoExtractExpiredMpdus(queue.second);
184 
185  if (firstIt != lastIt && !firstExpiredIt)
186  {
187  // this is the first queue with MPDUs with expired lifetime
188  firstExpiredIt = firstIt;
189  }
190  }
191  return std::make_pair(firstExpiredIt ? *firstExpiredIt : m_expiredQueue.end(),
192  m_expiredQueue.end());
193 }
194 
195 std::pair<WifiMacQueueContainer::iterator, WifiMacQueueContainer::iterator>
197 {
198  return {m_expiredQueue.begin(), m_expiredQueue.end()};
199 }
200 
201 } // namespace ns3
202 
203 /****************************************************
204  * Global Functions (outside namespace ns3)
205  ***************************************************/
206 
207 std::size_t
209 {
210  auto [type, address, tid] = queueId;
211  const std::size_t size = tid.has_value() ? 8 : 7;
212 
213  uint8_t buffer[size];
214  buffer[0] = type;
215  address.CopyTo(buffer + 1);
216  if (tid.has_value())
217  {
218  buffer[7] = *tid;
219  }
220 
221  std::string s(buffer, buffer + size);
222  return std::hash<std::string>{}(s);
223 }
bool IsGroup() const
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
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:66
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
@ AC_UNDEF
Total number of ACs.
Definition: qos-utils.h:86
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ WIFI_QOSDATA_UNICAST_QUEUE
@ WIFI_QOSDATA_BROADCAST_QUEUE
std::tuple< WifiContainerQueueType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, Address, TID) identifying a container queue.
std::size_t operator()(ns3::WifiContainerQueueId queueId) const
The functor.