A Discrete-Event Network Simulator
API
mu-edca-parameter-set.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2021 Universita' degli Studi di Napoli Federico II
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #include "mu-edca-parameter-set.h"
22 #include <cmath>
23 #include <algorithm>
24 
25 namespace ns3 {
26 
28  : m_qosInfo (0),
29  m_records {{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}
30 {
31 }
32 
34 MuEdcaParameterSet::ElementId () const
35 {
36  return IE_EXTENSION;
37 }
38 
40 MuEdcaParameterSet::ElementIdExt () const
41 {
43 }
44 
45 bool
46 MuEdcaParameterSet::IsPresent (void) const
47 {
48  auto timerNotNull = [](const ParameterRecord &r) { return r.muEdcaTimer != 0; };
49 
50  bool isPresent = std::all_of (m_records.begin (), m_records.end (), timerNotNull);
51  if (isPresent)
52  {
53  return true;
54  }
55  NS_ABORT_MSG_IF (std::any_of (m_records.begin (), m_records.end (), timerNotNull),
56  "MU EDCA Timers must be either all zero or all non-zero.");
57  return false;
58 }
59 
60 void
61 MuEdcaParameterSet::SetQosInfo (uint8_t qosInfo)
62 {
63  m_qosInfo = qosInfo;
64 }
65 
66 void
67 MuEdcaParameterSet::SetMuAifsn (uint8_t aci, uint8_t aifsn)
68 {
69  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
70  NS_ABORT_MSG_IF (aifsn == 1 || aifsn > 15, "Invalid AIFSN value: " << +aifsn);
71 
72  m_records[aci].aifsnField |= (aifsn & 0x0f);
73  m_records[aci].aifsnField |= (aci & 0x03) << 5;
74 }
75 
76 void
77 MuEdcaParameterSet::SetMuCwMin (uint8_t aci, uint16_t cwMin)
78 {
79  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
80  NS_ABORT_MSG_IF (cwMin > 32767, "CWmin exceeds the maximum value");
81 
82  auto eCwMin = std::log2 (cwMin + 1);
83  NS_ABORT_MSG_IF (std::trunc (eCwMin) != eCwMin, "CWmin is not a power of 2 minus 1");
84 
85  m_records[aci].cwMinMax |= (static_cast<uint8_t> (eCwMin) & 0x0f);
86 }
87 
88 void
89 MuEdcaParameterSet::SetMuCwMax (uint8_t aci, uint16_t cwMax)
90 {
91  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
92  NS_ABORT_MSG_IF (cwMax > 32767, "CWmin exceeds the maximum value");
93 
94  auto eCwMax = std::log2 (cwMax + 1);
95  NS_ABORT_MSG_IF (std::trunc (eCwMax) != eCwMax, "CWmax is not a power of 2 minus 1");
96 
97  m_records[aci].cwMinMax |= (static_cast<uint8_t> (eCwMax) & 0x0f) << 4;
98 }
99 
100 void
101 MuEdcaParameterSet::SetMuEdcaTimer (uint8_t aci, Time timer)
102 {
103  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
104  NS_ABORT_MSG_IF (timer.IsStrictlyPositive () && timer < MicroSeconds (8192),
105  "Timer value is below 8.192 ms");
106  NS_ABORT_MSG_IF (timer > MicroSeconds (2088960), "Timer value is above 2088.96 ms");
107 
108  double value = timer.GetMicroSeconds () / 8192.;
109  NS_ABORT_MSG_IF (std::trunc (value) != value, "Timer value is not a multiple of 8 TUs (8192 us)");
110 
111  m_records[aci].muEdcaTimer = static_cast<uint8_t> (value);
112 }
113 
114 uint8_t
115 MuEdcaParameterSet::GetQosInfo (void) const
116 {
117  return m_qosInfo;
118 }
119 
120 uint8_t
121 MuEdcaParameterSet::GetMuAifsn (uint8_t aci) const
122 {
123  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
124  return (m_records[aci].aifsnField & 0x0f);
125 }
126 
127 uint16_t
128 MuEdcaParameterSet::GetMuCwMin (uint8_t aci) const
129 {
130  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
131  uint8_t eCwMin = (m_records[aci].cwMinMax & 0x0f);
132  return static_cast<uint16_t> (std::exp2 (eCwMin) - 1);
133 }
134 
135 uint16_t
136 MuEdcaParameterSet::GetMuCwMax (uint8_t aci) const
137 {
138  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
139  uint8_t eCwMax = ((m_records[aci].cwMinMax >> 4) & 0x0f);
140  return static_cast<uint16_t> (std::exp2 (eCwMax) - 1);
141 }
142 
143 Time
144 MuEdcaParameterSet::GetMuEdcaTimer (uint8_t aci) const
145 {
146  NS_ABORT_MSG_IF (aci > 3, "Invalid AC Index value: " << +aci);
147  return MicroSeconds (m_records[aci].muEdcaTimer * 8192);
148 }
149 
150 uint8_t
151 MuEdcaParameterSet::GetInformationFieldSize () const
152 {
153  NS_ASSERT (IsPresent ());
154  // ElementIdExt (1) + QoS Info (1) + MU Parameter Records (4 * 3)
155  return 14;
156 }
157 
159 MuEdcaParameterSet::Serialize (Buffer::Iterator i) const
160 {
161  if (!IsPresent ())
162  {
163  return i;
164  }
165  return WifiInformationElement::Serialize (i);
166 }
167 
168 uint16_t
169 MuEdcaParameterSet::GetSerializedSize () const
170 {
171  if (!IsPresent ())
172  {
173  return 0;
174  }
175  return WifiInformationElement::GetSerializedSize ();
176 }
177 
178 void
179 MuEdcaParameterSet::SerializeInformationField (Buffer::Iterator start) const
180 {
181  if (IsPresent ())
182  {
183  start.WriteU8 (GetQosInfo ());
184  for (const auto& record : m_records)
185  {
186  start.WriteU8 (record.aifsnField);
187  start.WriteU8 (record.cwMinMax);
188  start.WriteU8 (record.muEdcaTimer);
189  }
190  }
191 }
192 
193 uint8_t
194 MuEdcaParameterSet::DeserializeInformationField (Buffer::Iterator start, uint8_t length)
195 {
197  m_qosInfo = i.ReadU8 ();
198  for (auto& record : m_records)
199  {
200  record.aifsnField = i.ReadU8 ();
201  record.cwMinMax = i.ReadU8 ();
202  record.muEdcaTimer = i.ReadU8 ();
203  }
204  return 13;
205 }
206 
207 } //namespace ns3
iterator in a Buffer instance
Definition: buffer.h:99
uint8_t ReadU8(void)
Definition: buffer.h:1021
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:387
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:332
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t WifiInformationElementId
This type is used to represent an Information Element ID.
def start()
Definition: core.py:1853
#define IE_EXTENSION
#define IE_EXT_MU_EDCA_PARAMETER_SET