A Discrete-Event Network Simulator
API
tid-to-link-mapping-element.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022
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: Sharan Naribole <sharan.naribole@gmail.com>
18  */
19 
21 
22 #include "ns3/assert.h"
23 #include "ns3/simulator.h"
24 
25 namespace ns3
26 {
27 
29 static constexpr uint64_t BIT_63_TO_26_MASK = 0xfffffffffc000000;
30 
31 uint16_t
33 {
34  // IEEE 802.11be D3.1 Figure 9-1002ap
36  "Presence bitmap not expected if default mapping is set");
38  if (!presenceBitmap.has_value())
39  {
40  return size;
41  }
43 }
44 
45 void
47 {
48  auto val = static_cast<uint8_t>(direction) | ((defaultMapping ? 1 : 0) << 2) |
49  ((mappingSwitchTimePresent ? 1 : 0) << 3) |
50  ((expectedDurationPresent ? 1 : 0) << 4) | ((linkMappingSize == 1 ? 1 : 0) << 5);
51 
52  start.WriteU8(val);
53  NS_ASSERT_MSG(!defaultMapping || !presenceBitmap.has_value(),
54  "Presence bitmap not expected if default mapping is set");
55  if (presenceBitmap.has_value())
56  {
57  start.WriteU8(presenceBitmap.value());
58  }
59 }
60 
61 uint16_t
63 {
64  auto i = start;
65  uint8_t count = 0;
66  auto val = i.ReadU8();
67  count++;
68 
69  direction = static_cast<WifiDirection>(val & 0x03);
70  defaultMapping = (((val >> 2) & 0x01) == 1);
71  mappingSwitchTimePresent = (((val >> 3) & 0x01) == 1);
72  expectedDurationPresent = (((val >> 4) & 0x01) == 1);
73  linkMappingSize = (((val >> 5) & 0x01) == 1 ? 1 : 2);
74  if (defaultMapping)
75  {
76  presenceBitmap.reset();
77  return count;
78  }
79  presenceBitmap = i.ReadU8();
80  return ++count;
81 }
82 
85 {
86  return IE_EXTENSION;
87 }
88 
91 {
93 }
94 
95 void
97 {
98  // The 2 octet Mapping Switch Time field has units of TUs and is set to the time at which
99  // the new mapping is established using as a time-base the value of the TSF corresponding
100  // to the BSS identified by the BSSID of the frame containing the TID-To-Link Mapping
101  // element: i.e., bits 10 to 25 of the TSF. (Sec. 9.4.2.314 of 802.11be D3.1)
102  NS_ABORT_IF(mappingSwitchTime < Simulator::Now());
103  auto switchTimeUsec = static_cast<uint64_t>(mappingSwitchTime.GetMicroSeconds());
104  // set the Mapping Switch Time field to bits 10 to 25 of the given time
105  m_mappingSwitchTime = (switchTimeUsec & ~BIT_63_TO_26_MASK) >> 10;
107 }
108 
109 std::optional<Time>
111 {
113  {
114  return std::nullopt;
115  }
116 
117  auto nowUsec = static_cast<uint64_t>(Simulator::Now().GetMicroSeconds());
118  uint64_t switchTimeUsec = (*m_mappingSwitchTime << 10) + (nowUsec & BIT_63_TO_26_MASK);
119  if (switchTimeUsec < nowUsec)
120  {
121  // The switch time derived from the value in the corresponding field may be less than the
122  // current time in case the bits 10 to 25 of TSF have been reset since the transmission
123  // of the frame carrying this field. In such a case we have to increase bits 63 to 26 by 1
124  switchTimeUsec += (1 << 26);
125  }
126  return MicroSeconds(switchTimeUsec);
127 }
128 
129 void
131 {
132  auto durationTu = static_cast<uint64_t>(expectedDuration.GetMicroSeconds()) >> 10;
133  m_expectedDuration = (durationTu & 0x0000000000ffffff); // Expected Duration size is 3 bytes
135 }
136 
137 std::optional<Time>
139 {
141  {
142  return std::nullopt;
143  }
144 
145  return MicroSeconds(*m_expectedDuration << 10);
146 }
147 
148 void
149 TidToLinkMapping::SetLinkMappingOfTid(uint8_t tid, std::set<uint8_t> linkIds)
150 {
151  NS_ABORT_MSG_IF(tid > 7, "Invalid tid: " << +tid);
153  "Per-TID link mapping not expected if default mapping is set");
154 
155  // derive link mapping for the given TID
156  uint16_t linkMapping = 0;
157 
158  for (const auto& linkId : linkIds)
159  {
160  linkMapping |= (1 << linkId);
161  if (linkId > 7)
162  {
164  }
165  }
166 
167  m_linkMapping[tid] = linkMapping;
168  m_control.presenceBitmap = m_control.presenceBitmap.value_or(0) | (1 << tid);
169 }
170 
171 std::set<uint8_t>
173 {
174  auto it = m_linkMapping.find(tid);
175 
176  if (it == m_linkMapping.cend())
177  {
178  return {};
179  }
180 
181  std::set<uint8_t> linkIds;
182  for (uint8_t linkId = 0; linkId < 15; linkId++)
183  {
184  if (((it->second >> linkId) & 0x0001) == 1)
185  {
186  linkIds.insert(linkId);
187  }
188  }
189  NS_ABORT_MSG_IF(linkIds.empty(), "TID " << +tid << " cannot be mapped to an empty link set");
190 
191  return linkIds;
192 }
193 
194 uint16_t
196 {
197  // IEEE 802.11be D3.1 9.4.2.314 TID-To-Link Mapping element
198  uint16_t ret = WIFI_IE_ELEMENT_ID_EXT_SIZE; // Element ID Extension
199  ret += m_control.GetSubfieldSize();
201  {
202  ret += 2; // Mapping Switch Time
203  }
205  {
206  ret += 3; // Expected Duration
207  }
208 
210  "Per-TID link mapping not expected if default mapping is set");
211  ret += m_control.linkMappingSize * (m_linkMapping.size());
212  return ret;
213 }
214 
215 void
217 {
218  // IEEE 802.11be D3.1 9.4.2.314 TID-To-Link Mapping element
221  {
222  start.WriteHtolsbU16(*m_mappingSwitchTime);
223  }
225  {
226  start.WriteU8((*m_expectedDuration >> 0) & 0xff);
227  start.WriteU8((*m_expectedDuration >> 8) & 0xff);
228  start.WriteU8((*m_expectedDuration >> 16) & 0xff);
229  }
230 
232  "Per-TID link mapping not expected if default mapping is set");
233 
234  for (const auto& [tid, linkMapping] : m_linkMapping)
235  {
236  if (m_control.linkMappingSize == 1)
237  {
238  start.WriteU8(linkMapping);
239  }
240  else
241  {
242  start.WriteHtolsbU16(linkMapping);
243  }
244  }
245 }
246 
247 uint16_t
249 {
250  auto i = start;
251  uint16_t count = 0;
252  auto nCtrlOctets = m_control.Deserialize(i);
253  NS_ASSERT_MSG(nCtrlOctets <= length, "Tid-to-Link Mapping deserialize error");
254  i.Next(nCtrlOctets);
255  count += nCtrlOctets;
257  {
258  m_mappingSwitchTime = i.ReadLsbtohU16();
259  count += 2;
260  }
262  {
263  uint8_t byte0 = i.ReadU8();
264  uint8_t byte1 = i.ReadU8();
265  uint8_t byte2 = i.ReadU8();
266  m_expectedDuration = byte2;
267  m_expectedDuration.value() <<= 8;
268  m_expectedDuration.value() |= byte1;
269  m_expectedDuration.value() <<= 8;
270  m_expectedDuration.value() |= byte0;
271  count += 3;
272  }
273  m_linkMapping.clear();
274  if (m_control.presenceBitmap.has_value())
275  {
277  "Default mapping should not be set when presence bitmap is present");
278  const auto presenceBitmap = m_control.presenceBitmap.value();
279  for (uint8_t tid = 0; tid < 8; tid++)
280  {
281  if (((presenceBitmap >> tid) & 0x01) == 1)
282  {
283  if (m_control.linkMappingSize == 1)
284  {
285  m_linkMapping[tid] = i.ReadU8();
286  count++;
287  }
288  else
289  {
290  m_linkMapping[tid] = i.ReadLsbtohU16();
291  count += 2;
292  }
293  }
294  }
295  }
296 
297  NS_ABORT_MSG_IF(count != length,
298  "TID-to-Link Mapping Length (" << +length
299  << ") differs "
300  "from actual number of bytes read ("
301  << +count << ")");
302  return count;
303 }
304 
305 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:413
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr uint16_t WIFI_TID_TO_LINK_MAPPING_CONTROL_BASIC_SIZE_B
size in bytes of the TID-To-Link Control field with default link mapping
static constexpr uint64_t BIT_63_TO_26_MASK
Bitmask with all bits from 63 to 26 set to 1, all the others set to 0.
constexpr uint8_t WIFI_IE_ELEMENT_ID_EXT_SIZE
Size in bytes of the Element ID Extension field (IEEE 802.11-2020 9.4.2.1 General)
WifiDirection
Wifi direction.
Definition: wifi-utils.h:43
constexpr uint16_t WIFI_LINK_MAPPING_PRESENCE_IND_SIZE_B
size in bytes of the Link Mapping Presence Indicator field (IEEE 802.11be D2.0 9.4....
uint8_t WifiInformationElementId
This type is used to represent an Information Element ID.
#define IE_EXTENSION
#define IE_EXT_TID_TO_LINK_MAPPING_ELEMENT