A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-psdu.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 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
9#include "wifi-psdu.h"
10
12#include "mpdu-aggregator.h"
13#include "wifi-mac-trailer.h"
14#include "wifi-utils.h"
15
16#include "ns3/log.h"
17#include "ns3/packet.h"
18
19namespace ns3
20{
21
22NS_LOG_COMPONENT_DEFINE("WifiPsdu");
23
25 : m_isSingle(false)
26{
27 m_mpduList.push_back(Create<WifiMpdu>(p, header));
28 m_size = header.GetSerializedSize() + p->GetSize() + WIFI_MAC_FCS_LENGTH;
29}
30
32 : m_isSingle(isSingle)
33{
34 m_mpduList.push_back(mpdu);
35 m_size = mpdu->GetSize();
36
37 if (isSingle)
38 {
39 m_size += 4; // A-MPDU Subframe header size
40 }
41}
42
43WifiPsdu::WifiPsdu(Ptr<const WifiMpdu> mpdu, bool isSingle)
44 : WifiPsdu(Create<WifiMpdu>(*mpdu), isSingle)
45{
46}
47
48WifiPsdu::WifiPsdu(std::vector<Ptr<WifiMpdu>> mpduList)
49 : m_isSingle(mpduList.size() == 1),
50 m_mpduList(mpduList)
51{
52 NS_ABORT_MSG_IF(mpduList.empty(), "Cannot initialize a WifiPsdu with an empty MPDU list");
53
54 m_size = 0;
55 for (auto& mpdu : m_mpduList)
56 {
58 }
59}
60
64
65bool
67{
68 return m_isSingle;
69}
70
71bool
73{
74 return (m_mpduList.size() > 1 || m_isSingle);
75}
76
79{
80 Ptr<Packet> packet = Create<Packet>();
81 if (m_mpduList.size() == 1 && !m_isSingle)
82 {
83 packet = m_mpduList.at(0)->GetPacket()->Copy();
84 packet->AddHeader(m_mpduList.at(0)->GetHeader());
85 AddWifiMacTrailer(packet);
86 }
87 else if (m_isSingle)
88 {
89 MpduAggregator::Aggregate(m_mpduList.at(0), packet, true);
90 }
91 else
92 {
93 for (auto& mpdu : m_mpduList)
94 {
95 MpduAggregator::Aggregate(mpdu, packet, false);
96 }
97 }
98 return packet;
99}
100
103{
104 Mac48Address ra = m_mpduList.at(0)->GetHeader().GetAddr1();
105 // check that the other MPDUs have the same RA
106 for (std::size_t i = 1; i < m_mpduList.size(); i++)
107 {
108 if (m_mpduList.at(i)->GetHeader().GetAddr1() != ra)
109 {
110 NS_ABORT_MSG("MPDUs in an A-MPDU must have the same receiver address");
111 }
112 }
113 return ra;
114}
115
118{
119 Mac48Address ta = m_mpduList.at(0)->GetHeader().GetAddr2();
120 // check that the other MPDUs have the same TA
121 for (std::size_t i = 1; i < m_mpduList.size(); i++)
122 {
123 if (m_mpduList.at(i)->GetHeader().GetAddr2() != ta)
124 {
125 NS_ABORT_MSG("MPDUs in an A-MPDU must have the same transmitter address");
126 }
127 }
128 return ta;
129}
130
131bool
133{
134 return m_mpduList.at(0)->GetHeader().HasNav();
135}
136
137Time
139{
140 Time duration = m_mpduList.at(0)->GetHeader().GetDuration();
141 // check that the other MPDUs have the same Duration/ID
142 for (std::size_t i = 1; i < m_mpduList.size(); i++)
143 {
144 if (m_mpduList.at(i)->GetHeader().GetDuration() != duration)
145 {
146 NS_ABORT_MSG("MPDUs in an A-AMPDU must have the same Duration/ID");
147 }
148 }
149 return duration;
150}
151
152void
154{
155 NS_LOG_FUNCTION(this << duration);
156 for (auto& mpdu : m_mpduList)
157 {
158 mpdu->GetHeader().SetDuration(duration);
159 }
160}
161
162void
164{
165 NS_LOG_FUNCTION(this);
166 for (auto& mpdu : m_mpduList)
167 {
168 mpdu->IncrementRetryCount();
169 }
170}
171
172std::set<uint8_t>
174{
175 std::set<uint8_t> s;
176 for (auto& mpdu : m_mpduList)
177 {
178 if (mpdu->GetHeader().IsQosData())
179 {
180 s.insert(mpdu->GetHeader().GetQosTid());
181 }
182 }
183 return s;
184}
185
188{
189 NS_LOG_FUNCTION(this << +tid);
191 auto it = m_mpduList.begin();
192 bool found = false;
193
194 // find the first QoS Data frame with the given TID
195 do
196 {
197 if ((*it)->GetHeader().IsQosData() && (*it)->GetHeader().GetQosTid() == tid)
198 {
199 policy = (*it)->GetHeader().GetQosAckPolicy();
200 found = true;
201 }
202 it++;
203 } while (!found && it != m_mpduList.end());
204
205 NS_ABORT_MSG_IF(!found, "No QoS Data frame in the PSDU");
206
207 // check that the other QoS Data frames with the given TID have the same ack policy
208 while (it != m_mpduList.end())
209 {
210 if ((*it)->GetHeader().IsQosData() && (*it)->GetHeader().GetQosTid() == tid &&
211 (*it)->GetHeader().GetQosAckPolicy() != policy)
212 {
213 NS_ABORT_MSG("QoS Data frames with the same TID must have the same QoS Ack Policy");
214 }
215 it++;
216 }
217 return policy;
218}
219
220void
222{
223 NS_LOG_FUNCTION(this << +tid << policy);
224 for (auto& mpdu : m_mpduList)
225 {
226 if (mpdu->GetHeader().IsQosData() && mpdu->GetHeader().GetQosTid() == tid)
227 {
228 mpdu->GetHeader().SetQosAckPolicy(policy);
229 }
230 }
231}
232
233uint16_t
234WifiPsdu::GetMaxDistFromStartingSeq(uint16_t startingSeq) const
235{
236 NS_LOG_FUNCTION(this << startingSeq);
237
238 uint16_t maxDistFromStartingSeq = 0;
239 bool foundFirst = false;
240
241 for (auto& mpdu : m_mpduList)
242 {
243 uint16_t currSeqNum = mpdu->GetHeader().GetSequenceNumber();
244
245 if (mpdu->GetHeader().IsQosData() && !QosUtilsIsOldPacket(startingSeq, currSeqNum))
246 {
247 uint16_t currDistToStartingSeq =
248 (currSeqNum - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE;
249
250 if (!foundFirst || currDistToStartingSeq > maxDistFromStartingSeq)
251 {
252 foundFirst = true;
253 maxDistFromStartingSeq = currDistToStartingSeq;
254 }
255 }
256 }
257
258 if (!foundFirst)
259 {
260 NS_LOG_DEBUG("All QoS Data frames in this PSDU are old frames");
261 return SEQNO_SPACE_SIZE;
262 }
263 NS_LOG_DEBUG("Returning " << maxDistFromStartingSeq);
264 return maxDistFromStartingSeq;
265}
266
269{
270 return m_size;
271}
272
273const WifiMacHeader&
274WifiPsdu::GetHeader(std::size_t i) const
275{
276 return m_mpduList.at(i)->GetHeader();
277}
278
281{
282 return m_mpduList.at(i)->GetHeader();
283}
284
286WifiPsdu::GetPayload(std::size_t i) const
287{
288 return m_mpduList.at(i)->GetPacket();
289}
290
292WifiPsdu::GetAmpduSubframe(std::size_t i) const
293{
294 NS_ASSERT(i < m_mpduList.size());
295 Ptr<Packet> subframe = m_mpduList.at(i)->GetProtocolDataUnit();
296 subframe->AddHeader(
297 MpduAggregator::GetAmpduSubframeHeader(static_cast<uint16_t>(subframe->GetSize()),
298 m_isSingle));
299 size_t padding = GetAmpduSubframeSize(i) - subframe->GetSize();
300 if (padding > 0)
301 {
302 Ptr<Packet> pad = Create<Packet>(padding);
303 subframe->AddAtEnd(pad);
304 }
305 return subframe;
306}
307
308std::size_t
310{
311 NS_ASSERT(i < m_mpduList.size());
312 size_t subframeSize = 4; // A-MPDU Subframe header size
313 subframeSize += m_mpduList.at(i)->GetSize();
314 if (i != m_mpduList.size() - 1) // add padding if not last
315 {
316 subframeSize += MpduAggregator::CalculatePadding(subframeSize);
317 }
318 return subframeSize;
319}
320
321std::size_t
323{
324 return m_mpduList.size();
325}
326
327std::vector<Ptr<WifiMpdu>>::const_iterator
329{
330 return m_mpduList.begin();
331}
332
333std::vector<Ptr<WifiMpdu>>::iterator
335{
336 return m_mpduList.begin();
337}
338
339std::vector<Ptr<WifiMpdu>>::const_iterator
341{
342 return m_mpduList.end();
343}
344
345std::vector<Ptr<WifiMpdu>>::iterator
347{
348 return m_mpduList.end();
349}
350
351void
352WifiPsdu::Print(std::ostream& os) const
353{
354 os << "size=" << m_size;
355 if (IsAggregate())
356 {
357 os << ", A-MPDU of " << GetNMpdus() << " MPDUs";
358 for (const auto& mpdu : m_mpduList)
359 {
360 os << " (" << *mpdu << ")";
361 }
362 }
363 else
364 {
365 os << ", " << ((m_isSingle) ? "S-MPDU" : "normal MPDU") << " (" << *(m_mpduList.at(0))
366 << ")";
367 }
368}
369
370std::ostream&
371operator<<(std::ostream& os, const WifiPsdu& psdu)
372{
373 psdu.Print(os);
374 return os;
375}
376
377std::ostream&
378operator<<(std::ostream& os, const WifiPsduMap& psduMap)
379{
380 for (const auto& [staId, psdu] : psduMap)
381 {
382 if (staId != SU_STA_ID)
383 {
384 os << "[PSDU for STA_ID=" << staId << ", ";
385 }
386 psdu->Print(os);
387 if (staId != SU_STA_ID)
388 {
389 os << "]";
390 }
391 }
392 return os;
393}
394
395std::ostream&
396operator<<(std::ostream& os, const WifiConstPsduMap& psduMap)
397{
398 for (const auto& [staId, psdu] : psduMap)
399 {
400 if (staId != SU_STA_ID)
401 {
402 os << "[PSDU for STA_ID=" << staId << ", ";
403 }
404 psdu->Print(os);
405 if (staId != SU_STA_ID)
406 {
407 os << "]";
408 }
409 }
410 return os;
411}
412
413} // namespace ns3
an EUI-48 address
static uint8_t CalculatePadding(uint32_t ampduSize)
static void Aggregate(Ptr< const WifiMpdu > mpdu, Ptr< Packet > ampdu, bool isSingle)
Aggregate an MPDU to an A-MPDU.
static AmpduSubframeHeader GetAmpduSubframeHeader(uint16_t mpduSize, bool isSingle)
Get the A-MPDU subframe header corresponding to the MPDU size and whether the MPDU is a single MPDU.
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...
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Implements the IEEE 802.11 MAC header.
uint32_t GetSerializedSize() const override
QosAckPolicy
Ack policy for QoS frames.
WifiMpdu stores a (const) packet along with a MAC header.
Definition wifi-mpdu.h:51
WifiPsdu stores an MPDU, S-MPDU or A-MPDU, by keeping header(s) and payload(s) separate for each cons...
Definition wifi-psdu.h:33
std::set< uint8_t > GetTids() const
Get the set of TIDs of the QoS Data frames included in the PSDU.
Definition wifi-psdu.cc:173
void SetAckPolicyForTid(uint8_t tid, WifiMacHeader::QosAckPolicy policy)
Set the QoS Ack Policy of the QoS Data frames included in the PSDU that have the given TID to the giv...
Definition wifi-psdu.cc:221
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition wifi-psdu.cc:274
void Print(std::ostream &os) const
Print the PSDU contents.
Definition wifi-psdu.cc:352
Time GetDuration() const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Definition wifi-psdu.cc:138
Ptr< const Packet > GetPacket() const
Get the PSDU as a single packet.
Definition wifi-psdu.cc:78
Ptr< Packet > GetAmpduSubframe(std::size_t i) const
Get a copy of the i-th A-MPDU subframe (includes subframe header, MPDU, and possibly padding)
Definition wifi-psdu.cc:292
std::vector< Ptr< WifiMpdu > >::const_iterator end() const
Return a const iterator to past-the-last MPDU.
Definition wifi-psdu.cc:340
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Definition wifi-psdu.cc:328
WifiPsdu(Ptr< const Packet > p, const WifiMacHeader &header)
Create a PSDU storing an MPDU.
Definition wifi-psdu.cc:24
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition wifi-psdu.cc:117
bool HasNav() const
Definition wifi-psdu.cc:132
uint32_t m_size
the size of the PSDU in bytes
Definition wifi-psdu.h:251
virtual ~WifiPsdu()
Definition wifi-psdu.cc:61
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition wifi-psdu.cc:268
Ptr< const Packet > GetPayload(std::size_t i) const
Get the payload of the i-th MPDU.
Definition wifi-psdu.cc:286
std::size_t GetAmpduSubframeSize(std::size_t i) const
Return the size of the i-th A-MPDU subframe.
Definition wifi-psdu.cc:309
bool m_isSingle
true for an S-MPDU
Definition wifi-psdu.h:249
Mac48Address GetAddr1() const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition wifi-psdu.cc:102
bool IsAggregate() const
Return true if the PSDU is an S-MPDU or A-MPDU.
Definition wifi-psdu.cc:72
bool IsSingle() const
Return true if the PSDU is an S-MPDU.
Definition wifi-psdu.cc:66
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition wifi-psdu.cc:153
void IncrementRetryCount()
Increment the frame retry count for all the MPDUs.
Definition wifi-psdu.cc:163
std::vector< Ptr< WifiMpdu > > m_mpduList
list of constituent MPDUs
Definition wifi-psdu.h:250
uint16_t GetMaxDistFromStartingSeq(uint16_t startingSeq) const
Get the maximum distance between the sequence number of any QoS Data frame included in this PSDU that...
Definition wifi-psdu.cc:234
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition wifi-psdu.cc:322
WifiMacHeader::QosAckPolicy GetAckPolicyForTid(uint8_t tid) const
Get the QoS Ack Policy of the QoS Data frames included in the PSDU that have the given TID.
Definition wifi-psdu.cc:187
#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_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet.
Definition qos-utils.cc:156
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
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
Definition wifi-mac.h:78
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition wifi-utils.h:273
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24