A Discrete-Event Network Simulator
API
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 #include "ns3/simulator.h"
32 
33 namespace ns3
34 {
35 
36 NS_LOG_COMPONENT_DEFINE("WifiMpdu");
37 
39  : m_header(header)
40 {
41  auto& original = std::get<OriginalInfo>(m_instanceInfo);
42  original.m_packet = p;
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 
56 bool
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 
73 WifiMpdu::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 
118 const WifiMacHeader&
120 {
121  return m_header;
122 }
123 
126 {
127  return m_header;
128 }
129 
132 {
133  return m_header.GetAddr1();
134 }
135 
136 uint32_t
138 {
139  return GetPacket()->GetSize();
140 }
141 
142 uint32_t
144 {
146 }
147 
148 bool
150 {
152 }
153 
156 {
157  Ptr<Packet> mpdu = GetPacket()->Copy();
158  mpdu->AddHeader(m_header);
159  AddWifiMacTrailer(mpdu);
160  return mpdu;
161 }
162 
163 void
165 {
166  NS_ASSERT(msdu);
167  NS_LOG_FUNCTION(this << *msdu);
168  NS_ABORT_MSG_IF(!msdu->GetHeader().IsQosData() || msdu->GetHeader().IsQosAmsdu(),
169  "Only QoS data frames that do not contain an A-MSDU can be aggregated");
170  NS_ABORT_MSG_IF(!std::holds_alternative<OriginalInfo>(m_instanceInfo),
171  "This method can only be called on the original version of the MPDU");
172 
173  auto& original = std::get<OriginalInfo>(m_instanceInfo);
174 
175  if (original.m_msduList.empty())
176  {
177  // An MSDU is going to be aggregated to this MPDU, hence this has to be an A-MSDU now
178  Ptr<const WifiMpdu> firstMsdu = Create<const WifiMpdu>(*this);
179  original.m_packet = Create<Packet>();
180  DoAggregate(firstMsdu);
181 
183  // Set Address3 according to Table 9-26 of 802.11-2016
184  if (m_header.IsToDs() && !m_header.IsFromDs())
185  {
186  // from STA to AP: BSSID is in Address1
188  }
189  else if (!m_header.IsToDs() && m_header.IsFromDs())
190  {
191  // from AP to STA: BSSID is in Address2
193  }
194  // in the WDS case (ToDS = FromDS = 1), both Address 3 and Address 4 need
195  // to be set to the BSSID, but neither Address 1 nor Address 2 contain the
196  // BSSID. Hence, it is left up to the caller to set these Address fields.
197  }
198  DoAggregate(msdu);
199 }
200 
201 void
203 {
204  NS_LOG_FUNCTION(this << *msdu);
205 
206  // build the A-MSDU Subframe header
208  /*
209  * (See Table 9-26 of 802.11-2016)
210  *
211  * ToDS | FromDS | DA | SA
212  * 0 | 0 | Addr1 | Addr2
213  * 0 | 1 | Addr1 | Addr3
214  * 1 | 0 | Addr3 | Addr2
215  * 1 | 1 | Addr3 | Addr4
216  */
217  hdr.SetDestinationAddr(msdu->GetHeader().IsToDs() ? msdu->GetHeader().GetAddr3()
218  : msdu->GetHeader().GetAddr1());
219  hdr.SetSourceAddr(!msdu->GetHeader().IsFromDs()
220  ? msdu->GetHeader().GetAddr2()
221  : (!msdu->GetHeader().IsToDs() ? msdu->GetHeader().GetAddr3()
222  : msdu->GetHeader().GetAddr4()));
223  hdr.SetLength(static_cast<uint16_t>(msdu->GetPacket()->GetSize()));
224 
225  auto& original = std::get<OriginalInfo>(m_instanceInfo);
226 
227  original.m_msduList.emplace_back(msdu->GetPacket(), hdr);
228 
229  // build the A-MSDU
230  NS_ASSERT(original.m_packet);
231  Ptr<Packet> amsdu = original.m_packet->Copy();
232 
233  // pad the previous A-MSDU subframe if the A-MSDU is not empty
234  if (original.m_packet->GetSize() > 0)
235  {
236  uint8_t padding = MsduAggregator::CalculatePadding(original.m_packet->GetSize());
237 
238  if (padding)
239  {
240  amsdu->AddAtEnd(Create<Packet>(padding));
241  }
242  }
243 
244  // add A-MSDU subframe header and MSDU
245  Ptr<Packet> amsduSubframe = msdu->GetPacket()->Copy();
246  amsduSubframe->AddHeader(hdr);
247  amsdu->AddAtEnd(amsduSubframe);
248  original.m_packet = amsdu;
249 }
250 
251 bool
253 {
254  return GetOriginalInfo().m_queueIt.has_value();
255 }
256 
257 void
258 WifiMpdu::SetQueueIt(std::optional<Iterator> queueIt, WmqIteratorTag tag)
259 {
260  NS_ABORT_MSG_IF(!std::holds_alternative<OriginalInfo>(m_instanceInfo),
261  "This method can only be called on the original version of the MPDU");
262 
263  auto& original = std::get<OriginalInfo>(m_instanceInfo);
264  original.m_queueIt = queueIt;
265 }
266 
269 {
270  return GetQueueIt();
271 }
272 
275 {
276  NS_ASSERT(IsQueued());
277  return GetOriginalInfo().m_queueIt.value();
278 }
279 
280 AcIndex
282 {
283  return GetQueueIt()->ac;
284 }
285 
286 Time
288 {
289  return GetQueueIt()->expiryTime;
290 }
291 
292 void
293 WifiMpdu::SetInFlight(uint8_t linkId) const
294 {
295  GetQueueIt()->inflights[linkId] = Ptr(const_cast<WifiMpdu*>(this));
296 }
297 
298 void
299 WifiMpdu::ResetInFlight(uint8_t linkId) const
300 {
301  GetQueueIt()->inflights.erase(linkId);
302 }
303 
304 std::set<uint8_t>
306 {
307  if (!IsQueued())
308  {
309  return {};
310  }
311  std::set<uint8_t> linkIds;
312  for (const auto& [linkId, mpdu] : GetQueueIt()->inflights)
313  {
314  linkIds.insert(linkId);
315  }
316  return linkIds;
317 }
318 
319 bool
321 {
322  return IsQueued() && !GetQueueIt()->inflights.empty();
323 }
324 
325 void
326 WifiMpdu::AssignSeqNo(uint16_t seqNo)
327 {
328  NS_LOG_FUNCTION(this << seqNo);
329 
331  // if this is an alias, set the sequence number on the original copy, too
332  if (auto originalPtr = std::get_if<ALIAS>(&m_instanceInfo))
333  {
334  (*originalPtr)->m_header.SetSequenceNumber(seqNo);
335  }
337 }
338 
339 bool
341 {
343 }
344 
345 void
347 {
349 }
350 
353 {
354  return GetOriginalInfo().m_msduList.cbegin();
355 }
356 
359 {
360  return GetOriginalInfo().m_msduList.cend();
361 }
362 
363 void
364 WifiMpdu::Print(std::ostream& os) const
365 {
366  os << m_header.GetTypeString() << ", payloadSize=" << GetPacketSize()
367  << ", to=" << m_header.GetAddr1() << ", seqN=" << m_header.GetSequenceNumber()
368  << ", duration/ID=" << m_header.GetDuration();
369  if (m_header.IsQosData())
370  {
371  os << ", tid=" << +m_header.GetQosTid();
372  if (m_header.IsQosNoAck())
373  {
374  os << ", ack=NoAck";
375  }
376  else if (m_header.IsQosAck())
377  {
378  os << ", ack=NormalAck";
379  }
380  else if (m_header.IsQosBlockAck())
381  {
382  os << ", ack=BlockAck";
383  }
384  }
385  os << ", queued=" << IsQueued();
386  if (IsQueued())
387  {
388  os << ", residualLifetime=" << (GetExpiryTime() - Simulator::Now()).As(Time::US)
389  << ", inflight=" << IsInFlight();
390  }
391  os << ", packet=" << GetPacket();
392 }
393 
394 std::ostream&
395 operator<<(std::ostream& os, const WifiMpdu& item)
396 {
397  item.Print(os);
398  return os;
399 }
400 
401 } // 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...
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
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.
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:61
bool IsOriginal() const
Definition: wifi-mpdu.cc:57
InstanceInfo m_instanceInfo
information associated with the instance type
Definition: wifi-mpdu.h:298
bool HasSeqNoAssigned() const
Definition: wifi-mpdu.cc:340
Time GetExpiryTime() const
Definition: wifi-mpdu.cc:287
bool IsInFlight() const
Definition: wifi-mpdu.cc:320
static constexpr std::size_t ALIAS
index of an alias in the InstanceInfo variant
Definition: wifi-mpdu.h:301
void ResetInFlight(uint8_t linkId) const
Mark this MPDU as not being in flight on the given link.
Definition: wifi-mpdu.cc:299
WifiMacHeader m_header
Information stored by both the original copy and the aliases.
Definition: wifi-mpdu.h:273
void SetInFlight(uint8_t linkId) const
Mark this MPDU as being in flight on the given link.
Definition: wifi-mpdu.cc:293
Iterator GetQueueIt() const
Definition: wifi-mpdu.cc:274
const WifiMacHeader & GetHeader() const
Get the header stored in this item.
Definition: wifi-mpdu.cc:119
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:164
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:143
Ptr< Packet > GetProtocolDataUnit() const
Get the MAC protocol data unit (MPDU) corresponding to this item (i.e.
Definition: wifi-mpdu.cc:155
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:202
void UnassignSeqNo()
Record that a sequence number is no (longer) assigned to this MPDU.
Definition: wifi-mpdu.cc:346
virtual void Print(std::ostream &os) const
Print the item contents.
Definition: wifi-mpdu.cc:364
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
std::list< std::pair< Ptr< const Packet >, AmsduSubframeHeader > >::const_iterator DeaggregatedMsdusCI
DeaggregatedMsdusCI typedef.
Definition: wifi-mpdu.h:141
DeaggregatedMsdusCI end() const
Get a constant iterator indicating past-the-last MSDU in the list of aggregated MSDUs.
Definition: wifi-mpdu.cc:358
DeaggregatedMsdusCI begin() const
Get a constant iterator pointing to the first MSDU in the list of aggregated MSDUs.
Definition: wifi-mpdu.cc:352
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:137
AcIndex GetQueueAc() const
Get the AC of the queue this item is stored into.
Definition: wifi-mpdu.cc:281
std::list< WifiMacQueueElem >::iterator Iterator
Const iterator typedef.
Definition: wifi-mpdu.h:157
Mac48Address GetDestinationAddress() const
Return the destination address present in the header.
Definition: wifi-mpdu.cc:131
bool IsQueued() const
Return true if this item is stored in some queue, false otherwise.
Definition: wifi-mpdu.cc:252
void SetQueueIt(std::optional< Iterator > queueIt, WmqIteratorTag tag)
Set the queue iterator stored by this object.
Definition: wifi-mpdu.cc:258
bool IsFragment() const
Return true if this item contains an MSDU fragment, false otherwise.
Definition: wifi-mpdu.cc:149
std::set< uint8_t > GetInFlightLinkIds() const
Definition: wifi-mpdu.cc:305
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:326
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:47
#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:72
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.
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:125
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
Information stored by the original copy only.
Definition: wifi-mpdu.h:279
bool m_seqNoAssigned
whether a sequence number has been assigned
Definition: wifi-mpdu.h:283
DeaggregatedMsdus m_msduList
list of aggregated MSDUs included in this MPDU
Definition: wifi-mpdu.h:281
Ptr< const Packet > m_packet
MSDU or A-MSDU contained in this queue item.
Definition: wifi-mpdu.h:280
std::optional< Iterator > m_queueIt
Queue iterator pointing to this MPDU, if queued.
Definition: wifi-mpdu.h:282