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 * 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
32namespace ns3
33{
34
35NS_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
68void
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);
78 m_txDuration.reset();
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
99void
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 const auto [it, inserted] =
119 m_info.emplace(hdr.GetAddr1(), PsduInfo{hdr, mpdu->GetPacketSize(), 0, seqNumbers});
120 NS_ASSERT(inserted);
121
122 // store information to undo the addition of this MPDU
123 m_lastInfoIt = it;
124 m_undoInfo = PsduInfo{WifiMacHeader{}, 0, 0, {}};
125 return;
126 }
127
128 // a PSDU for the receiver of the given MPDU is already being built
129 NS_ASSERT_MSG((hdr.IsQosData() && !hdr.HasData()) || infoIt->second.amsduSize > 0,
130 "An MPDU can only be aggregated to an existing (A-)MPDU");
131
132 // store information to undo the addition of this MPDU
133 m_lastInfoIt = infoIt;
134 m_undoInfo =
135 PsduInfo{infoIt->second.header, infoIt->second.amsduSize, infoIt->second.ampduSize, {}};
136 if (hdr.IsQosData())
137 {
139 {hdr.GetQosTid(), {hdr.GetSequenceNumber()}}}; // seq number to remove
140 }
141
142 // The (A-)MSDU being built is included in an A-MPDU subframe
143 infoIt->second.ampduSize = MpduAggregator::GetSizeIfAggregated(
144 infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH,
145 infoIt->second.ampduSize);
146 infoIt->second.header = hdr;
147 infoIt->second.amsduSize = mpdu->GetPacketSize();
148
149 if (hdr.IsQosData())
150 {
151 const auto [it, inserted] =
152 infoIt->second.seqNumbers.emplace(hdr.GetQosTid(),
153 std::set<uint16_t>{hdr.GetSequenceNumber()});
154
155 if (!inserted)
156 {
157 // insertion did not happen because an entry with the same TID already exists
158 it->second.insert(hdr.GetSequenceNumber());
159 }
160 }
161}
162
163void
165{
166 NS_LOG_FUNCTION(this);
167 NS_ASSERT(m_lastInfoIt.has_value());
168
169 if (m_undoInfo.amsduSize == 0 && m_undoInfo.ampduSize == 0)
170 {
171 // the last MPDU was the first one being added for its receiver
172 m_info.erase(*m_lastInfoIt);
173 m_lastInfoIt.reset();
174 return;
175 }
176
177 auto& lastInfo = (*m_lastInfoIt)->second;
178 lastInfo.header = m_undoInfo.header;
179 lastInfo.amsduSize = m_undoInfo.amsduSize;
180 lastInfo.ampduSize = m_undoInfo.ampduSize;
181 // if the MPDU to remove is not a QoS data frame or it is the first QoS data frame added for
182 // a given receiver, no sequence number information is stored
183 if (!m_undoInfo.seqNumbers.empty())
184 {
185 NS_ASSERT(m_undoInfo.seqNumbers.size() == 1);
186 const auto tid = m_undoInfo.seqNumbers.cbegin()->first;
187 auto& seqNoSet = m_undoInfo.seqNumbers.cbegin()->second;
188 NS_ASSERT(seqNoSet.size() == 1);
189 NS_ASSERT(lastInfo.seqNumbers.contains(tid));
190 lastInfo.seqNumbers.at(tid).erase(*seqNoSet.cbegin());
191 }
192 m_lastInfoIt.reset();
193}
194
195bool
197{
198 auto infoIt = m_info.find(receiver);
199 NS_ASSERT_MSG(infoIt != m_info.cend(), "No frame added for receiver " << receiver);
200 NS_ASSERT_MSG(m_lastInfoIt == infoIt, "Last MPDU not addressed to " << receiver);
201 return (m_undoInfo.amsduSize == 0 && m_undoInfo.ampduSize == 0);
202}
203
206{
207 NS_LOG_FUNCTION(this << *mpdu);
208
209 auto infoIt = m_info.find(mpdu->GetHeader().GetAddr1());
210
211 if (infoIt == m_info.end())
212 {
213 // this is an MPDU starting a new PSDU
215 {
216 // All MPDUs are sent with the A-MPDU structure
217 return MpduAggregator::GetSizeIfAggregated(mpdu->GetSize(), 0);
218 }
219 return mpdu->GetSize();
220 }
221
222 // aggregate the (A-)MSDU being built to the existing A-MPDU (if any)
224 infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH,
225 infoIt->second.ampduSize);
226 // aggregate the new MPDU to the A-MPDU
227 return MpduAggregator::GetSizeIfAggregated(mpdu->GetSize(), ampduSize);
228}
229
230void
232{
233 NS_LOG_FUNCTION(this << *msdu);
234
235 auto infoIt = m_info.find(msdu->GetHeader().GetAddr1());
236 NS_ASSERT_MSG(infoIt != m_info.end(),
237 "There must be already an MPDU addressed to the same receiver");
238
239 // store information to undo the addition of this MSDU
240 m_lastInfoIt = infoIt;
241 m_undoInfo =
242 PsduInfo{infoIt->second.header, infoIt->second.amsduSize, infoIt->second.ampduSize, {}};
243
244 infoIt->second.amsduSize = GetSizeIfAggregateMsdu(msdu);
245 infoIt->second.header.SetQosAmsdu();
246}
247
250{
251 NS_LOG_FUNCTION(this << *msdu);
252
253 NS_ASSERT_MSG(msdu->GetHeader().IsQosData(),
254 "Can only aggregate a QoS data frame to an A-MSDU");
255
256 auto infoIt = m_info.find(msdu->GetHeader().GetAddr1());
257 NS_ASSERT_MSG(infoIt != m_info.end(),
258 "There must be already an MPDU addressed to the same receiver");
259
260 NS_ASSERT_MSG(infoIt->second.amsduSize > 0,
261 "The amsduSize should be set to the size of the previous MSDU(s)");
262 NS_ASSERT_MSG(infoIt->second.header.IsQosData(),
263 "The MPDU being built for this receiver must be a QoS data frame");
264 NS_ASSERT_MSG(infoIt->second.header.GetQosTid() == msdu->GetHeader().GetQosTid(),
265 "The MPDU being built must belong to the same TID as the MSDU to aggregate");
266 NS_ASSERT_MSG(infoIt->second.seqNumbers.contains(msdu->GetHeader().GetQosTid()),
267 "At least one MPDU with the same TID must have been added previously");
268
269 // all checks passed
270 uint32_t currAmsduSize = infoIt->second.amsduSize;
271
272 if (!infoIt->second.header.IsQosAmsdu())
273 {
274 // consider the A-MSDU subframe for the first MSDU
275 currAmsduSize = MsduAggregator::GetSizeIfAggregated(currAmsduSize, 0);
276 }
277
278 return MsduAggregator::GetSizeIfAggregated(msdu->GetPacket()->GetSize(), currAmsduSize);
279}
280
283{
284 NS_LOG_FUNCTION(this << receiver);
285
286 auto infoIt = m_info.find(receiver);
287
288 if (infoIt == m_info.end())
289 {
290 return 0;
291 }
292
293 uint32_t newMpduSize =
294 infoIt->second.header.GetSize() + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH;
295
296 if (infoIt->second.ampduSize > 0 || m_txVector.GetModulationClass() >= WIFI_MOD_CLASS_VHT)
297 {
298 return MpduAggregator::GetSizeIfAggregated(newMpduSize, infoIt->second.ampduSize);
299 }
300
301 return newMpduSize;
302}
303
304void
305WifiTxParameters::Print(std::ostream& os) const
306{
307 os << "TXVECTOR=" << m_txVector;
308 if (m_protection)
309 {
310 os << ", Protection=" << m_protection.get();
311 }
313 {
314 os << ", Acknowledgment=" << m_acknowledgment.get();
315 }
316 os << ", PSDUs:";
317 for (const auto& info : m_info)
318 {
319 os << " [To=" << info.second.header.GetAddr1() << ", A-MSDU size=" << info.second.amsduSize
320 << ", A-MPDU size=" << info.second.ampduSize << "]";
321 }
322}
323
324std::ostream&
325operator<<(std::ostream& os, const WifiTxParameters* txParams)
326{
327 txParams->Print(os);
328 return os;
329}
330
331} // 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
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:66
#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
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