A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-mpdu.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005, 2009 INRIA
3 * Copyright (c) 2009 MIRKO BANCHI
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 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 * Mirko Banchi <mk.banchi@gmail.com>
20 * Stefano Avallone <stavallo@unina.it>
21 */
22
23#include "wifi-mpdu.h"
24
25#include "msdu-aggregator.h"
26#include "wifi-mac-trailer.h"
27#include "wifi-utils.h"
28
29#include "ns3/log.h"
30#include "ns3/packet.h"
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("WifiMpdu");
36
38 : m_header(header)
39{
40 auto& original = std::get<OriginalInfo>(m_instanceInfo);
41 original.m_packet = p;
42 original.m_timestamp = stamp;
43
44 if (header.IsQosData() && header.IsQosAmsdu())
45 {
46 original.m_msduList = MsduAggregator::Deaggregate(p->Copy());
47 }
48}
49
51{
52 // Aliases can be queued (i.e., the original copy is queued) when destroyed
53 NS_ASSERT(std::holds_alternative<Ptr<WifiMpdu>>(m_instanceInfo) || !IsQueued());
54}
55
56bool
58{
59 return std::holds_alternative<OriginalInfo>(m_instanceInfo);
60}
61
64{
65 if (std::holds_alternative<OriginalInfo>(m_instanceInfo))
66 {
67 return this;
68 }
69 return std::get<ALIAS>(m_instanceInfo);
70}
71
73WifiMpdu::CreateAlias(uint8_t linkId) const
74{
75 NS_LOG_FUNCTION(this << +linkId);
76 NS_ABORT_MSG_IF(!std::holds_alternative<OriginalInfo>(m_instanceInfo),
77 "This method can only be called on the original version of the MPDU");
79 "This method can only be called if the MPDU is stored in a MAC queue");
80
81 auto alias = Ptr<WifiMpdu>(new WifiMpdu, false);
82
83 alias->m_header = m_header; // copy the MAC header
84 alias->m_instanceInfo = Ptr(const_cast<WifiMpdu*>(this));
85 NS_ASSERT(alias->m_instanceInfo.index() == ALIAS);
86
87 return alias;
88}
89
92{
93 if (auto original = std::get_if<ORIGINAL>(&m_instanceInfo))
94 {
95 return *original;
96 }
97 auto& origInstanceInfo = std::get<Ptr<WifiMpdu>>(m_instanceInfo)->m_instanceInfo;
98 return std::get<OriginalInfo>(origInstanceInfo);
99}
100
103{
104 if (auto original = std::get_if<ORIGINAL>(&m_instanceInfo))
105 {
106 return *original;
107 }
108 const auto& origInstanceInfo = std::get<Ptr<WifiMpdu>>(m_instanceInfo)->m_instanceInfo;
109 return std::get<OriginalInfo>(origInstanceInfo);
110}
111
114{
115 return GetOriginalInfo().m_packet;
116}
117
118Time
120{
121 if (auto original = std::get_if<ORIGINAL>(&m_instanceInfo))
122 {
123 return original->m_timestamp;
124 }
125 const auto& origInstanceInfo = std::get<Ptr<WifiMpdu>>(m_instanceInfo)->m_instanceInfo;
126 return std::get<OriginalInfo>(origInstanceInfo).m_timestamp;
127}
128
129const WifiMacHeader&
131{
132 return m_header;
133}
134
137{
138 return m_header;
139}
140
143{
144 return m_header.GetAddr1();
145}
146
149{
150 return GetPacket()->GetSize();
151}
152
155{
157}
158
159bool
161{
163}
164
167{
168 Ptr<Packet> mpdu = GetPacket()->Copy();
169 mpdu->AddHeader(m_header);
170 AddWifiMacTrailer(mpdu);
171 return mpdu;
172}
173
174void
176{
177 if (msdu)
178 {
179 NS_LOG_FUNCTION(this << *msdu);
180 }
181 else
182 {
183 NS_LOG_FUNCTION(this);
184 }
185 NS_ABORT_MSG_IF(msdu && (!msdu->GetHeader().IsQosData() || msdu->GetHeader().IsQosAmsdu()),
186 "Only QoS data frames that do not contain an A-MSDU can be aggregated");
187 NS_ABORT_MSG_IF(!std::holds_alternative<OriginalInfo>(m_instanceInfo),
188 "This method can only be called on the original version of the MPDU");
189
190 auto& original = std::get<OriginalInfo>(m_instanceInfo);
191
192 if (original.m_msduList.empty())
193 {
194 // An MSDU is going to be aggregated to this MPDU, hence this has to be an A-MSDU now
195 Ptr<const WifiMpdu> firstMsdu = Create<const WifiMpdu>(*this);
196 original.m_packet = Create<Packet>();
197 DoAggregate(firstMsdu);
198
200 // Set Address3 according to Table 9-26 of 802.11-2016
201 if (m_header.IsToDs() && !m_header.IsFromDs())
202 {
203 // from STA to AP: BSSID is in Address1
205 }
206 else if (!m_header.IsToDs() && m_header.IsFromDs())
207 {
208 // from AP to STA: BSSID is in Address2
210 }
211 // in the WDS case (ToDS = FromDS = 1), both Address 3 and Address 4 need
212 // to be set to the BSSID, but neither Address 1 nor Address 2 contain the
213 // BSSID. Hence, it is left up to the caller to set these Address fields.
214 }
215 if (msdu)
216 {
217 DoAggregate(msdu);
218 }
219}
220
221void
223{
224 NS_LOG_FUNCTION(this << *msdu);
225
226 // build the A-MSDU Subframe header
228 /*
229 * (See Table 9-26 of 802.11-2016)
230 *
231 * ToDS | FromDS | DA | SA
232 * 0 | 0 | Addr1 | Addr2
233 * 0 | 1 | Addr1 | Addr3
234 * 1 | 0 | Addr3 | Addr2
235 * 1 | 1 | Addr3 | Addr4
236 */
237 hdr.SetDestinationAddr(msdu->GetHeader().IsToDs() ? msdu->GetHeader().GetAddr3()
238 : msdu->GetHeader().GetAddr1());
239 hdr.SetSourceAddr(!msdu->GetHeader().IsFromDs()
240 ? msdu->GetHeader().GetAddr2()
241 : (!msdu->GetHeader().IsToDs() ? msdu->GetHeader().GetAddr3()
242 : msdu->GetHeader().GetAddr4()));
243 hdr.SetLength(static_cast<uint16_t>(msdu->GetPacket()->GetSize()));
244
245 auto& original = std::get<OriginalInfo>(m_instanceInfo);
246
247 original.m_msduList.emplace_back(msdu->GetPacket(), hdr);
248
249 // build the A-MSDU
250 NS_ASSERT(original.m_packet);
251 Ptr<Packet> amsdu = original.m_packet->Copy();
252
253 // pad the previous A-MSDU subframe if the A-MSDU is not empty
254 if (original.m_packet->GetSize() > 0)
255 {
256 uint8_t padding = MsduAggregator::CalculatePadding(original.m_packet->GetSize());
257
258 if (padding)
259 {
260 amsdu->AddAtEnd(Create<Packet>(padding));
261 }
262 }
263
264 // add A-MSDU subframe header and MSDU
265 Ptr<Packet> amsduSubframe = msdu->GetPacket()->Copy();
266 amsduSubframe->AddHeader(hdr);
267 amsdu->AddAtEnd(amsduSubframe);
268 original.m_packet = amsdu;
269}
270
271bool
273{
274 return GetOriginalInfo().m_queueIt.has_value();
275}
276
277void
278WifiMpdu::SetQueueIt(std::optional<Iterator> queueIt, WmqIteratorTag tag)
279{
280 NS_ABORT_MSG_IF(!std::holds_alternative<OriginalInfo>(m_instanceInfo),
281 "This method can only be called on the original version of the MPDU");
282
283 auto& original = std::get<OriginalInfo>(m_instanceInfo);
284 original.m_queueIt = queueIt;
285}
286
289{
290 return GetQueueIt();
291}
292
295{
297 return GetOriginalInfo().m_queueIt.value();
298}
299
302{
303 return GetQueueIt()->ac;
304}
305
306Time
308{
309 return GetQueueIt()->expiryTime;
310}
311
312void
313WifiMpdu::SetInFlight(uint8_t linkId) const
314{
315 GetQueueIt()->inflights[linkId] = Ptr(const_cast<WifiMpdu*>(this));
316}
317
318void
319WifiMpdu::ResetInFlight(uint8_t linkId) const
320{
321 GetQueueIt()->inflights.erase(linkId);
322}
323
324std::set<uint8_t>
326{
327 if (!IsQueued())
328 {
329 return {};
330 }
331 std::set<uint8_t> linkIds;
332 for (const auto& [linkId, mpdu] : GetQueueIt()->inflights)
333 {
334 linkIds.insert(linkId);
335 }
336 return linkIds;
337}
338
339bool
341{
342 return IsQueued() && !GetQueueIt()->inflights.empty();
343}
344
345void
347{
348 NS_LOG_FUNCTION(this << seqNo);
349
351 // if this is an alias, set the sequence number on the original copy, too
352 if (auto originalPtr = std::get_if<ALIAS>(&m_instanceInfo))
353 {
354 (*originalPtr)->m_header.SetSequenceNumber(seqNo);
355 }
357}
358
359bool
361{
363}
364
365void
367{
369}
370
373{
374 return GetOriginalInfo().m_msduList.cbegin();
375}
376
379{
380 return GetOriginalInfo().m_msduList.cend();
381}
382
383void
384WifiMpdu::Print(std::ostream& os) const
385{
386 os << m_header.GetTypeString() << ", payloadSize=" << GetPacketSize()
387 << ", to=" << m_header.GetAddr1() << ", seqN=" << m_header.GetSequenceNumber()
388 << ", duration/ID=" << m_header.GetDuration();
389 if (m_header.IsQosData())
390 {
391 os << ", tid=" << +m_header.GetQosTid();
392 if (m_header.IsQosNoAck())
393 {
394 os << ", ack=NoAck";
395 }
396 else if (m_header.IsQosAck())
397 {
398 os << ", ack=NormalAck";
399 }
400 else if (m_header.IsQosBlockAck())
401 {
402 os << ", ack=BlockAck";
403 }
404 }
405 os << ", queued=" << IsQueued();
406 if (IsQueued())
407 {
408 os << ", residualLifetime=" << (GetExpiryTime() - Simulator::Now()).As(Time::US)
409 << ", inflight=" << IsInFlight();
410 }
411 os << ", packet=" << GetPacket();
412}
413
414std::ostream&
415operator<<(std::ostream& os, const WifiMpdu& item)
416{
417 item.Print(os);
418 return os;
419}
420
421} // namespace ns3
Headers for A-MSDU subframes.
void SetSourceAddr(Mac48Address to)
Set source address function.
void SetDestinationAddr(Mac48Address to)
Set destination address function.
void SetLength(uint16_t length)
Set length function.
an EUI-48 address
Definition: mac48-address.h:46
static WifiMpdu::DeaggregatedMsdus Deaggregate(Ptr< Packet > aggregatedPacket)
static uint8_t CalculatePadding(uint16_t amsduSize)
Calculate how much padding must be added to the end of an A-MSDU of the given size if a new MSDU is a...
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
@ US
microsecond
Definition: nstime.h:118
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
bool IsQosAmsdu() const
Check if the A-MSDU present bit is set in the QoS control field.
void SetQosAmsdu()
Set that A-MSDU is present.
uint32_t GetSerializedSize() const override
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
uint16_t GetSequenceNumber() const
Return the sequence number of the header.
bool IsMoreFragments() const
Return if the More Fragment bit is set.
Time GetDuration() const
Return the duration from the Duration/ID field (Time object).
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
virtual const char * GetTypeString() const
Return a string corresponds to the header type.
bool IsQosAck() const
Return if the QoS Ack policy is Normal Ack.
bool IsQosNoAck() const
Return if the QoS Ack policy is No Ack.
bool IsQosBlockAck() const
Return if the QoS Ack policy is Block Ack.
uint8_t GetFragmentNumber() const
Return the fragment number of the header.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
WifiMpdu stores a (const) packet along with a MAC header.
Definition: wifi-mpdu.h:62
bool IsOriginal() const
Definition: wifi-mpdu.cc:57
InstanceInfo m_instanceInfo
information associated with the instance type
Definition: wifi-mpdu.h:307
Time GetTimestamp() const
Definition: wifi-mpdu.cc:119
bool HasSeqNoAssigned() const
Definition: wifi-mpdu.cc:360
Time GetExpiryTime() const
Definition: wifi-mpdu.cc:307
bool IsInFlight() const
Definition: wifi-mpdu.cc:340
static constexpr std::size_t ALIAS
index of an alias in the InstanceInfo variant
Definition: wifi-mpdu.h:310
void ResetInFlight(uint8_t linkId) const
Mark this MPDU as not being in flight on the given link.
Definition: wifi-mpdu.cc:319
WifiMacHeader m_header
Information stored by both the original copy and the aliases.
Definition: wifi-mpdu.h:281
void SetInFlight(uint8_t linkId) const
Mark this MPDU as being in flight on the given link.
Definition: wifi-mpdu.cc:313
Iterator GetQueueIt() const
Definition: wifi-mpdu.cc:294
std::list< std::pair< Ptr< constPacket >, AmsduSubframeHeader > >::const_iterator DeaggregatedMsdusCI
DeaggregatedMsdusCI typedef.
Definition: wifi-mpdu.h:145
const WifiMacHeader & GetHeader() const
Get the header stored in this item.
Definition: wifi-mpdu.cc:130
void Aggregate(Ptr< const WifiMpdu > msdu)
Aggregate the MSDU contained in the given MPDU to this MPDU (thus constituting an A-MSDU).
Definition: wifi-mpdu.cc:175
OriginalInfo & GetOriginalInfo()
Definition: wifi-mpdu.cc:91
virtual ~WifiMpdu()
Definition: wifi-mpdu.cc:50
uint32_t GetSize() const
Return the size of the packet stored by this item, including header size and trailer size.
Definition: wifi-mpdu.cc:154
Ptr< Packet > GetProtocolDataUnit() const
Get the MAC protocol data unit (MPDU) corresponding to this item (i.e.
Definition: wifi-mpdu.cc:166
void DoAggregate(Ptr< const WifiMpdu > msdu)
Aggregate the MSDU contained in the given MPDU to this MPDU (thus constituting an A-MSDU).
Definition: wifi-mpdu.cc:222
void UnassignSeqNo()
Record that a sequence number is no (longer) assigned to this MPDU.
Definition: wifi-mpdu.cc:366
virtual void Print(std::ostream &os) const
Print the item contents.
Definition: wifi-mpdu.cc:384
WifiMpdu()=default
Private default constructor (used to construct aliases).
Ptr< const Packet > GetPacket() const
Get the packet stored in this item.
Definition: wifi-mpdu.cc:113
DeaggregatedMsdusCI end() const
Get a constant iterator indicating past-the-last MSDU in the list of aggregated MSDUs.
Definition: wifi-mpdu.cc:378
DeaggregatedMsdusCI begin() const
Get a constant iterator pointing to the first MSDU in the list of aggregated MSDUs.
Definition: wifi-mpdu.cc:372
uint32_t GetPacketSize() const
Return the size in bytes of the packet or control header or management header stored by this item.
Definition: wifi-mpdu.cc:148
AcIndex GetQueueAc() const
Get the AC of the queue this item is stored into.
Definition: wifi-mpdu.cc:301
std::list< WifiMacQueueElem >::iterator Iterator
Const iterator typedef.
Definition: wifi-mpdu.h:161
Mac48Address GetDestinationAddress() const
Return the destination address present in the header.
Definition: wifi-mpdu.cc:142
bool IsQueued() const
Return true if this item is stored in some queue, false otherwise.
Definition: wifi-mpdu.cc:272
void SetQueueIt(std::optional< Iterator > queueIt, WmqIteratorTag tag)
Set the queue iterator stored by this object.
Definition: wifi-mpdu.cc:278
bool IsFragment() const
Return true if this item contains an MSDU fragment, false otherwise.
Definition: wifi-mpdu.cc:160
std::set< uint8_t > GetInFlightLinkIds() const
Definition: wifi-mpdu.cc:325
Ptr< const WifiMpdu > GetOriginal() const
Definition: wifi-mpdu.cc:63
void AssignSeqNo(uint16_t seqNo)
Set the sequence number of this MPDU (and of the original copy, if this is an alias) to the given val...
Definition: wifi-mpdu.cc:346
Ptr< WifiMpdu > CreateAlias(uint8_t linkId) const
Create an alias for this MPDU (which must be an original copy) for transmission on the link with the ...
Definition: wifi-mpdu.cc:73
Tag used to allow (only) WifiMacQueue to access the queue iterator stored by a WifiMpdu.
Definition: wifi-mpdu.h:48
#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_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#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 ",...
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:73
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
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:125
Information stored by the original copy only.
Definition: wifi-mpdu.h:287
bool m_seqNoAssigned
whether a sequence number has been assigned
Definition: wifi-mpdu.h:292
DeaggregatedMsdus m_msduList
list of aggregated MSDUs included in this MPDU
Definition: wifi-mpdu.h:290
Ptr< const Packet > m_packet
MSDU or A-MSDU contained in this queue item.
Definition: wifi-mpdu.h:288
std::optional< Iterator > m_queueIt
Queue iterator pointing to this MPDU, if queued.
Definition: wifi-mpdu.h:291