A Discrete-Event Network Simulator
API
wifi-tx-parameters.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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 
20 #include "wifi-tx-parameters.h"
21 
22 #include "mpdu-aggregator.h"
23 #include "msdu-aggregator.h"
24 #include "wifi-acknowledgment.h"
25 #include "wifi-mac-trailer.h"
26 #include "wifi-mpdu.h"
27 #include "wifi-protection.h"
28 
29 #include "ns3/log.h"
30 #include "ns3/packet.h"
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("WifiTxParameters");
36 
38 {
39 }
40 
42 {
43  m_txVector = txParams.m_txVector;
44  m_protection = (txParams.m_protection ? txParams.m_protection->Copy() : nullptr);
45  m_acknowledgment = (txParams.m_acknowledgment ? txParams.m_acknowledgment->Copy() : nullptr);
46  m_txDuration = txParams.m_txDuration;
47  m_info = txParams.m_info;
48 }
49 
52 {
53  // check for self-assignment
54  if (&txParams == this)
55  {
56  return *this;
57  }
58 
59  m_txVector = txParams.m_txVector;
60  m_protection = (txParams.m_protection ? txParams.m_protection->Copy() : nullptr);
61  m_acknowledgment = (txParams.m_acknowledgment ? txParams.m_acknowledgment->Copy() : nullptr);
62  m_txDuration = txParams.m_txDuration;
63  m_info = txParams.m_info;
64 
65  return *this;
66 }
67 
68 void
70 {
71  NS_LOG_FUNCTION(this);
72 
73  // Reset the current info
74  m_info.clear();
76  m_protection.reset(nullptr);
77  m_acknowledgment.reset(nullptr);
79 }
80 
83 {
84  auto infoIt = m_info.find(receiver);
85 
86  if (infoIt == m_info.end())
87  {
88  return nullptr;
89  }
90  return &infoIt->second;
91 }
92 
95 {
96  return m_info;
97 }
98 
99 void
101 {
102  NS_LOG_FUNCTION(this << *mpdu);
103 
104  const WifiMacHeader& hdr = mpdu->GetHeader();
105 
106  auto infoIt = m_info.find(hdr.GetAddr1());
107 
108  if (infoIt == m_info.end())
109  {
110  // this is an MPDU starting a new PSDU
111  std::map<uint8_t, std::set<uint16_t>> seqNumbers;
112  if (hdr.IsQosData())
113  {
114  seqNumbers[hdr.GetQosTid()] = {hdr.GetSequenceNumber()};
115  }
116 
117  // Insert the info about the given frame
118  m_info.emplace(hdr.GetAddr1(), PsduInfo{hdr, mpdu->GetPacketSize(), 0, seqNumbers});
119  return;
120  }
121 
122  // a PSDU for the receiver of the given MPDU is already being built
123  NS_ASSERT_MSG((hdr.IsQosData() && !hdr.HasData()) || infoIt->second.amsduSize > 0,
124  "An MPDU can only be aggregated to an existing (A-)MPDU");
125 
126  // The (A-)MSDU being built is included in an A-MPDU subframe
127  infoIt->second.ampduSize = MpduAggregator::GetSizeIfAggregated(
128  infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH,
129  infoIt->second.ampduSize);
130  infoIt->second.header = hdr;
131  infoIt->second.amsduSize = mpdu->GetPacketSize();
132 
133  if (hdr.IsQosData())
134  {
135  auto ret = infoIt->second.seqNumbers.emplace(hdr.GetQosTid(),
136  std::set<uint16_t>{hdr.GetSequenceNumber()});
137 
138  if (!ret.second)
139  {
140  // insertion did not happen because an entry with the same TID already exists
141  ret.first->second.insert(hdr.GetSequenceNumber());
142  }
143  }
144 }
145 
146 uint32_t
148 {
149  NS_LOG_FUNCTION(this << *mpdu);
150 
151  auto infoIt = m_info.find(mpdu->GetHeader().GetAddr1());
152 
153  if (infoIt == m_info.end())
154  {
155  // this is an MPDU starting a new PSDU
157  {
158  // All MPDUs are sent with the A-MPDU structure
159  return MpduAggregator::GetSizeIfAggregated(mpdu->GetSize(), 0);
160  }
161  return mpdu->GetSize();
162  }
163 
164  // aggregate the (A-)MSDU being built to the existing A-MPDU (if any)
165  uint32_t ampduSize = MpduAggregator::GetSizeIfAggregated(
166  infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH,
167  infoIt->second.ampduSize);
168  // aggregate the new MPDU to the A-MPDU
169  return MpduAggregator::GetSizeIfAggregated(mpdu->GetSize(), ampduSize);
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION(this << *msdu);
176 
177  auto infoIt = m_info.find(msdu->GetHeader().GetAddr1());
178  NS_ASSERT_MSG(infoIt != m_info.end(),
179  "There must be already an MPDU addressed to the same receiver");
180 
181  infoIt->second.amsduSize = GetSizeIfAggregateMsdu(msdu).first;
182  infoIt->second.header.SetQosAmsdu();
183 }
184 
185 std::pair<uint32_t, uint32_t>
187 {
188  NS_LOG_FUNCTION(this << *msdu);
189 
190  NS_ASSERT_MSG(msdu->GetHeader().IsQosData(),
191  "Can only aggregate a QoS data frame to an A-MSDU");
192 
193  auto infoIt = m_info.find(msdu->GetHeader().GetAddr1());
194  NS_ASSERT_MSG(infoIt != m_info.end(),
195  "There must be already an MPDU addressed to the same receiver");
196 
197  NS_ASSERT_MSG(infoIt->second.amsduSize > 0,
198  "The amsduSize should be set to the size of the previous MSDU(s)");
199  NS_ASSERT_MSG(infoIt->second.header.IsQosData(),
200  "The MPDU being built for this receiver must be a QoS data frame");
201  NS_ASSERT_MSG(infoIt->second.header.GetQosTid() == msdu->GetHeader().GetQosTid(),
202  "The MPDU being built must belong to the same TID as the MSDU to aggregate");
203  NS_ASSERT_MSG(infoIt->second.seqNumbers.find(msdu->GetHeader().GetQosTid()) !=
204  infoIt->second.seqNumbers.end(),
205  "At least one MPDU with the same TID must have been added previously");
206 
207  // all checks passed
208  uint32_t currAmsduSize = infoIt->second.amsduSize;
209 
210  if (!infoIt->second.header.IsQosAmsdu())
211  {
212  // consider the A-MSDU subframe for the first MSDU
213  currAmsduSize = MsduAggregator::GetSizeIfAggregated(currAmsduSize, 0);
214  }
215 
216  uint32_t newAmsduSize =
217  MsduAggregator::GetSizeIfAggregated(msdu->GetPacket()->GetSize(), currAmsduSize);
218  uint32_t newMpduSize = infoIt->second.header.GetSize() + newAmsduSize + WIFI_MAC_FCS_LENGTH;
219 
220  if (infoIt->second.ampduSize > 0 || m_txVector.GetModulationClass() >= WIFI_MOD_CLASS_VHT)
221  {
222  return {newAmsduSize,
223  MpduAggregator::GetSizeIfAggregated(newMpduSize, infoIt->second.ampduSize)};
224  }
225 
226  return {newAmsduSize, newMpduSize};
227 }
228 
229 uint32_t
231 {
232  NS_LOG_FUNCTION(this << receiver);
233 
234  auto infoIt = m_info.find(receiver);
235 
236  if (infoIt == m_info.end())
237  {
238  return 0;
239  }
240 
241  uint32_t newMpduSize =
242  infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH;
243 
244  if (infoIt->second.ampduSize > 0 || m_txVector.GetModulationClass() >= WIFI_MOD_CLASS_VHT)
245  {
246  return MpduAggregator::GetSizeIfAggregated(newMpduSize, infoIt->second.ampduSize);
247  }
248 
249  return newMpduSize;
250 }
251 
252 void
253 WifiTxParameters::Print(std::ostream& os) const
254 {
255  os << "TXVECTOR=" << m_txVector;
256  if (m_protection)
257  {
258  os << ", Protection=" << m_protection.get();
259  }
260  if (m_acknowledgment)
261  {
262  os << ", Acknowledgment=" << m_acknowledgment.get();
263  }
264  os << ", PSDUs:";
265  for (const auto& info : m_info)
266  {
267  os << " [To=" << info.second.header.GetAddr1() << ", A-MSDU size=" << info.second.amsduSize
268  << ", A-MPDU size=" << info.second.ampduSize << "]";
269  }
270 }
271 
272 std::ostream&
273 operator<<(std::ostream& os, const WifiTxParameters* txParams)
274 {
275  txParams->Print(os);
276  return os;
277 }
278 
279 } // namespace ns3
an EUI-48 address
Definition: mac48-address.h:46
static uint32_t GetSizeIfAggregated(uint32_t mpduSize, uint32_t ampduSize)
Compute the size of the A-MPDU resulting from the aggregation of an MPDU of size mpduSize and an A-MP...
static uint16_t GetSizeIfAggregated(uint16_t msduSize, uint16_t amsduSize)
Compute the size of the A-MSDU resulting from the aggregation of an MSDU of size msduSize and an A-MS...
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:287
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.
uint16_t GetSequenceNumber() const
Return the sequence number of the header.
bool HasData() const
Return true if the header type is DATA and is not DATA_NULL.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
uint32_t GetSizeIfAddMpdu(Ptr< const WifiMpdu > mpdu) const
Get the size in bytes of the frame in case the given MPDU is added.
const PsduInfoMap & GetPsduInfoMap() const
Get a const reference to the map containing information about PSDUs.
std::pair< uint32_t, uint32_t > GetSizeIfAggregateMsdu(Ptr< const WifiMpdu > msdu) const
Get the size in bytes of the frame in case the given MSDU is aggregated.
std::unique_ptr< WifiProtection > m_protection
protection method
WifiTxParameters & operator=(const WifiTxParameters &txParams)
Copy assignment operator.
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
const PsduInfo * GetPsduInfo(Mac48Address receiver) const
Get a pointer to the information about the PSDU addressed to the given receiver, if present,...
Time m_txDuration
TX duration of the frame.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
PsduInfoMap m_info
information about the frame being prepared.
void AggregateMsdu(Ptr< const WifiMpdu > msdu)
Record that an MSDU is being aggregated to the last MPDU added to the frame that hase the same receiv...
void Print(std::ostream &os) const
Print the object contents.
void AddMpdu(Ptr< const WifiMpdu > mpdu)
Record that an MPDU is being added to the current frame.
void Clear()
Reset the TX parameters.
std::map< Mac48Address, PsduInfo > PsduInfoMap
Map containing information about the PSDUs addressed to every receiver.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
information about the frame being prepared for a specific receiver