A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "mpdu-aggregator.h"
12#include "msdu-aggregator.h"
13#include "wifi-acknowledgment.h"
14#include "wifi-mac-trailer.h"
15#include "wifi-mpdu.h"
16#include "wifi-protection.h"
17
18#include "ns3/log.h"
19#include "ns3/packet.h"
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("WifiTxParameters");
25
29
31{
32 m_txVector = txParams.m_txVector;
33 m_protection = (txParams.m_protection ? txParams.m_protection->Copy() : nullptr);
34 m_acknowledgment = (txParams.m_acknowledgment ? txParams.m_acknowledgment->Copy() : nullptr);
35 m_txDuration = txParams.m_txDuration;
36 m_info = txParams.m_info;
37}
38
41{
42 // check for self-assignment
43 if (&txParams == this)
44 {
45 return *this;
46 }
47
48 m_txVector = txParams.m_txVector;
49 m_protection = (txParams.m_protection ? txParams.m_protection->Copy() : nullptr);
50 m_acknowledgment = (txParams.m_acknowledgment ? txParams.m_acknowledgment->Copy() : nullptr);
51 m_txDuration = txParams.m_txDuration;
52 m_info = txParams.m_info;
53
54 return *this;
55}
56
57void
59{
60 NS_LOG_FUNCTION(this);
61
62 // Reset the current info
63 m_info.clear();
65 m_protection.reset(nullptr);
66 m_acknowledgment.reset(nullptr);
67 m_txDuration.reset();
68}
69
72{
73 auto infoIt = m_info.find(receiver);
74
75 if (infoIt == m_info.end())
76 {
77 return nullptr;
78 }
79 return &infoIt->second;
80}
81
84{
85 return m_info;
86}
87
88void
90{
91 NS_LOG_FUNCTION(this << *mpdu);
92
93 const WifiMacHeader& hdr = mpdu->GetHeader();
94
95 auto infoIt = m_info.find(hdr.GetAddr1());
96
97 if (infoIt == m_info.end())
98 {
99 // this is an MPDU starting a new PSDU
100 std::map<uint8_t, std::set<uint16_t>> seqNumbers;
101 if (hdr.IsQosData())
102 {
103 seqNumbers[hdr.GetQosTid()] = {hdr.GetSequenceNumber()};
104 }
105
106 // Insert the info about the given frame
107 const auto [it, inserted] =
108 m_info.emplace(hdr.GetAddr1(), PsduInfo{hdr, mpdu->GetPacketSize(), 0, seqNumbers});
109 NS_ASSERT(inserted);
110
111 // store information to undo the addition of this MPDU
112 m_lastInfoIt = it;
113 m_undoInfo = PsduInfo{WifiMacHeader{}, 0, 0, {}};
114 return;
115 }
116
117 // a PSDU for the receiver of the given MPDU is already being built
118 NS_ASSERT_MSG((hdr.IsQosData() && !hdr.HasData()) || infoIt->second.amsduSize > 0,
119 "An MPDU can only be aggregated to an existing (A-)MPDU");
120
121 // store information to undo the addition of this MPDU
122 m_lastInfoIt = infoIt;
123 m_undoInfo =
124 PsduInfo{infoIt->second.header, infoIt->second.amsduSize, infoIt->second.ampduSize, {}};
125 if (hdr.IsQosData())
126 {
128 {hdr.GetQosTid(), {hdr.GetSequenceNumber()}}}; // seq number to remove
129 }
130
131 // The (A-)MSDU being built is included in an A-MPDU subframe
132 infoIt->second.ampduSize = MpduAggregator::GetSizeIfAggregated(
133 infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH,
134 infoIt->second.ampduSize);
135 infoIt->second.header = hdr;
136 infoIt->second.amsduSize = mpdu->GetPacketSize();
137
138 if (hdr.IsQosData())
139 {
140 const auto [it, inserted] =
141 infoIt->second.seqNumbers.emplace(hdr.GetQosTid(),
142 std::set<uint16_t>{hdr.GetSequenceNumber()});
143
144 if (!inserted)
145 {
146 // insertion did not happen because an entry with the same TID already exists
147 it->second.insert(hdr.GetSequenceNumber());
148 }
149 }
150}
151
152void
154{
155 NS_LOG_FUNCTION(this);
156 NS_ASSERT(m_lastInfoIt.has_value());
157
158 if (m_undoInfo.amsduSize == 0 && m_undoInfo.ampduSize == 0)
159 {
160 // the last MPDU was the first one being added for its receiver
161 m_info.erase(*m_lastInfoIt);
162 m_lastInfoIt.reset();
163 return;
164 }
165
166 auto& lastInfo = (*m_lastInfoIt)->second;
167 lastInfo.header = m_undoInfo.header;
168 lastInfo.amsduSize = m_undoInfo.amsduSize;
169 lastInfo.ampduSize = m_undoInfo.ampduSize;
170 // if the MPDU to remove is not a QoS data frame or it is the first QoS data frame added for
171 // a given receiver, no sequence number information is stored
172 if (!m_undoInfo.seqNumbers.empty())
173 {
174 NS_ASSERT(m_undoInfo.seqNumbers.size() == 1);
175 const auto tid = m_undoInfo.seqNumbers.cbegin()->first;
176 auto& seqNoSet = m_undoInfo.seqNumbers.cbegin()->second;
177 NS_ASSERT(seqNoSet.size() == 1);
178 NS_ASSERT(lastInfo.seqNumbers.contains(tid));
179 lastInfo.seqNumbers.at(tid).erase(*seqNoSet.cbegin());
180 }
181 m_lastInfoIt.reset();
182}
183
184bool
186{
187 auto infoIt = m_info.find(receiver);
188 NS_ASSERT_MSG(infoIt != m_info.cend(), "No frame added for receiver " << receiver);
189 NS_ASSERT_MSG(m_lastInfoIt == infoIt, "Last MPDU not addressed to " << receiver);
190 return (m_undoInfo.amsduSize == 0 && m_undoInfo.ampduSize == 0);
191}
192
195{
196 NS_LOG_FUNCTION(this << *mpdu);
197
198 auto infoIt = m_info.find(mpdu->GetHeader().GetAddr1());
199
200 if (infoIt == m_info.end())
201 {
202 // this is an MPDU starting a new PSDU
204 {
205 // All MPDUs are sent with the A-MPDU structure
206 return MpduAggregator::GetSizeIfAggregated(mpdu->GetSize(), 0);
207 }
208 return mpdu->GetSize();
209 }
210
211 // aggregate the (A-)MSDU being built to the existing A-MPDU (if any)
213 infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH,
214 infoIt->second.ampduSize);
215 // aggregate the new MPDU to the A-MPDU
216 return MpduAggregator::GetSizeIfAggregated(mpdu->GetSize(), ampduSize);
217}
218
219void
221{
222 NS_LOG_FUNCTION(this << *msdu);
223
224 auto infoIt = m_info.find(msdu->GetHeader().GetAddr1());
225 NS_ASSERT_MSG(infoIt != m_info.end(),
226 "There must be already an MPDU addressed to the same receiver");
227
228 // store information to undo the addition of this MSDU
229 m_lastInfoIt = infoIt;
230 m_undoInfo =
231 PsduInfo{infoIt->second.header, infoIt->second.amsduSize, infoIt->second.ampduSize, {}};
232
233 infoIt->second.amsduSize = GetSizeIfAggregateMsdu(msdu);
234 infoIt->second.header.SetQosAmsdu();
235}
236
239{
240 NS_LOG_FUNCTION(this << *msdu);
241
242 NS_ASSERT_MSG(msdu->GetHeader().IsQosData(),
243 "Can only aggregate a QoS data frame to an A-MSDU");
244
245 auto infoIt = m_info.find(msdu->GetHeader().GetAddr1());
246 NS_ASSERT_MSG(infoIt != m_info.end(),
247 "There must be already an MPDU addressed to the same receiver");
248
249 NS_ASSERT_MSG(infoIt->second.amsduSize > 0,
250 "The amsduSize should be set to the size of the previous MSDU(s)");
251 NS_ASSERT_MSG(infoIt->second.header.IsQosData(),
252 "The MPDU being built for this receiver must be a QoS data frame");
253 NS_ASSERT_MSG(infoIt->second.header.GetQosTid() == msdu->GetHeader().GetQosTid(),
254 "The MPDU being built must belong to the same TID as the MSDU to aggregate");
255 NS_ASSERT_MSG(infoIt->second.seqNumbers.contains(msdu->GetHeader().GetQosTid()),
256 "At least one MPDU with the same TID must have been added previously");
257
258 // all checks passed
259 uint32_t currAmsduSize = infoIt->second.amsduSize;
260
261 if (!infoIt->second.header.IsQosAmsdu())
262 {
263 // consider the A-MSDU subframe for the first MSDU
264 currAmsduSize = MsduAggregator::GetSizeIfAggregated(currAmsduSize, 0);
265 }
266
267 return MsduAggregator::GetSizeIfAggregated(msdu->GetPacket()->GetSize(), currAmsduSize);
268}
269
272{
273 auto infoIt = m_info.find(receiver);
274
275 if (infoIt == m_info.end())
276 {
277 return 0;
278 }
279
280 uint32_t newMpduSize =
281 infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH;
282
283 if (infoIt->second.ampduSize > 0 || m_txVector.GetModulationClass() >= WIFI_MOD_CLASS_VHT)
284 {
285 return MpduAggregator::GetSizeIfAggregated(newMpduSize, infoIt->second.ampduSize);
286 }
287
288 return newMpduSize;
289}
290
291void
292WifiTxParameters::Print(std::ostream& os) const
293{
294 os << "TXVECTOR=" << m_txVector;
295 if (m_protection)
296 {
297 os << ", Protection=" << m_protection.get();
298 }
300 {
301 os << ", Acknowledgment=" << m_acknowledgment.get();
302 }
303 os << ", PSDUs:";
304 for (const auto& info : m_info)
305 {
306 os << " [To=" << info.second.header.GetAddr1() << ", A-MSDU size=" << info.second.amsduSize
307 << ", A-MPDU size=" << info.second.ampduSize << "]";
308 }
309}
310
311std::ostream&
312operator<<(std::ostream& os, const WifiTxParameters* txParams)
313{
314 txParams->Print(os);
315 return os;
316}
317
318} // namespace ns3
an EUI-48 address
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.
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.
std::optional< Time > m_txDuration
TX duration of the frame.
const PsduInfoMap & GetPsduInfoMap() const
Get a const reference to the map containing information about PSDUs.
PsduInfo m_undoInfo
information needed to undo the addition of an MPDU
std::unique_ptr< WifiProtection > m_protection
protection method
WifiTxParameters & operator=(const WifiTxParameters &txParams)
Copy assignment operator.
uint32_t GetSizeIfAggregateMsdu(Ptr< const WifiMpdu > msdu) const
Get the size in bytes of the frame in case the given MSDU is aggregated.
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,...
void UndoAddMpdu()
Undo the addition of the last MPDU added by calling AddMpdu().
bool LastAddedIsFirstMpdu(Mac48Address receiver) const
Check if the last added MPDU is the first MPDU for the given receiver.
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.
std::optional< PsduInfoMap::iterator > m_lastInfoIt
iterator pointing to the entry in the m_info map that was created/modified by the last added MPDU
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(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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:148
information about the frame being prepared for a specific receiver
std::map< uint8_t, std::set< uint16_t > > seqNumbers
set of the sequence numbers of the MPDUs added for each TID
uint32_t ampduSize
the size in bytes of the A-MPDU if multiple MPDUs have been added, and zero otherwise
WifiMacHeader header
MAC header of the last MPDU added.
uint32_t amsduSize
the size in bytes of the MSDU or A-MSDU included in the last MPDU added