A Discrete-Event Network Simulator
API
mpdu-aggregator.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013
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  * Author: Ghada Badawy <gbadawy@gmail.com>
19  * Stefano Avallone <stavallo@unina.it>
20  */
21 
22 #include "ns3/log.h"
23 #include "ns3/packet.h"
24 #include "mpdu-aggregator.h"
25 #include "ampdu-subframe-header.h"
26 #include "wifi-phy.h"
27 #include "wifi-tx-vector.h"
29 #include "wifi-mac-queue-item.h"
30 #include "wifi-mac-queue.h"
31 #include "msdu-aggregator.h"
32 #include "wifi-net-device.h"
33 #include "ns3/ht-capabilities.h"
34 #include "ns3/vht-capabilities.h"
35 #include "ns3/he-capabilities.h"
36 #include "regular-wifi-mac.h"
37 #include "ctrl-headers.h"
38 #include "wifi-mac-trailer.h"
39 #include "wifi-tx-parameters.h"
40 
41 NS_LOG_COMPONENT_DEFINE ("MpduAggregator");
42 
43 namespace ns3 {
44 
45 NS_OBJECT_ENSURE_REGISTERED (MpduAggregator);
46 
47 TypeId
49 {
50  static TypeId tid = TypeId ("ns3::MpduAggregator")
51  .SetParent<Object> ()
52  .SetGroupName ("Wifi")
53  .AddConstructor<MpduAggregator> ()
54  ;
55  return tid;
56 }
57 
59 {
60 }
61 
63 {
64 }
65 
66 void
68 {
69  m_mac = 0;
71 }
72 
73 void
75 {
76  NS_LOG_FUNCTION (this << mac);
77  m_mac = mac;
78 }
79 
80 void
82 {
83  NS_LOG_FUNCTION (mpdu << ampdu << isSingle);
84  NS_ASSERT (ampdu);
85  // if isSingle is true, then ampdu must be empty
86  NS_ASSERT (!isSingle || ampdu->GetSize () == 0);
87 
88  // pad the previous A-MPDU subframe if the A-MPDU is not empty
89  if (ampdu->GetSize () > 0)
90  {
91  uint8_t padding = CalculatePadding (ampdu->GetSize ());
92 
93  if (padding)
94  {
95  Ptr<Packet> pad = Create<Packet> (padding);
96  ampdu->AddAtEnd (pad);
97  }
98  }
99 
100  // add MPDU header and trailer
101  Ptr<Packet> tmp = mpdu->GetPacket ()->Copy ();
102  tmp->AddHeader (mpdu->GetHeader ());
103  AddWifiMacTrailer (tmp);
104 
105  // add A-MPDU subframe header and MPDU to the A-MPDU
106  AmpduSubframeHeader hdr = GetAmpduSubframeHeader (static_cast<uint16_t> (tmp->GetSize ()), isSingle);
107 
108  tmp->AddHeader (hdr);
109  ampdu->AddAtEnd (tmp);
110 }
111 
112 uint32_t
113 MpduAggregator::GetSizeIfAggregated (uint32_t mpduSize, uint32_t ampduSize)
114 {
115  NS_LOG_FUNCTION (mpduSize << ampduSize);
116 
117  return ampduSize + CalculatePadding (ampduSize) + 4 + mpduSize;
118 }
119 
120 uint32_t
122  WifiModulationClass modulation) const
123 {
124  NS_LOG_FUNCTION (this << recipient << +tid << modulation);
125 
126  AcIndex ac = QosUtilsMapTidToAc (tid);
127 
128  // Find the A-MPDU max size configured on this device
129  UintegerValue size;
130 
131  switch (ac)
132  {
133  case AC_BE:
134  m_mac->GetAttribute ("BE_MaxAmpduSize", size);
135  break;
136  case AC_BK:
137  m_mac->GetAttribute ("BK_MaxAmpduSize", size);
138  break;
139  case AC_VI:
140  m_mac->GetAttribute ("VI_MaxAmpduSize", size);
141  break;
142  case AC_VO:
143  m_mac->GetAttribute ("VO_MaxAmpduSize", size);
144  break;
145  default:
146  NS_ABORT_MSG ("Unknown AC " << ac);
147  return 0;
148  }
149 
150  uint32_t maxAmpduSize = size.Get ();
151 
152  if (maxAmpduSize == 0)
153  {
154  NS_LOG_DEBUG ("A-MPDU Aggregation is disabled on this station for AC " << ac);
155  return 0;
156  }
157 
158  Ptr<WifiRemoteStationManager> stationManager = m_mac->GetWifiRemoteStationManager ();
159  NS_ASSERT (stationManager);
160 
161  // Retrieve the Capabilities elements advertised by the recipient
162  Ptr<const HeCapabilities> heCapabilities = stationManager->GetStationHeCapabilities (recipient);
163  Ptr<const VhtCapabilities> vhtCapabilities = stationManager->GetStationVhtCapabilities (recipient);
164  Ptr<const HtCapabilities> htCapabilities = stationManager->GetStationHtCapabilities (recipient);
165 
166  // Determine the constraint imposed by the recipient based on the PPDU
167  // format used to transmit the A-MPDU
168  if (modulation == WIFI_MOD_CLASS_HE)
169  {
170  NS_ABORT_MSG_IF (!heCapabilities, "HE Capabilities element not received");
171 
172  maxAmpduSize = std::min (maxAmpduSize, heCapabilities->GetMaxAmpduLength ());
173  }
174  else if (modulation == WIFI_MOD_CLASS_VHT)
175  {
176  NS_ABORT_MSG_IF (!vhtCapabilities, "VHT Capabilities element not received");
177 
178  maxAmpduSize = std::min (maxAmpduSize, vhtCapabilities->GetMaxAmpduLength ());
179  }
180  else if (modulation == WIFI_MOD_CLASS_HT)
181  {
182  NS_ABORT_MSG_IF (!htCapabilities, "HT Capabilities element not received");
183 
184  maxAmpduSize = std::min (maxAmpduSize, htCapabilities->GetMaxAmpduLength ());
185  }
186  else // non-HT PPDU
187  {
188  NS_LOG_DEBUG ("A-MPDU aggregation is not available for non-HT PHYs");
189 
190  maxAmpduSize = 0;
191  }
192 
193  return maxAmpduSize;
194 }
195 
196 uint8_t
198 {
199  return (4 - (ampduSize % 4 )) % 4;
200 }
201 
203 MpduAggregator::GetAmpduSubframeHeader (uint16_t mpduSize, bool isSingle)
204 {
206  hdr.SetLength (mpduSize);
207  if (isSingle)
208  {
209  hdr.SetEof (1);
210  }
211  return hdr;
212 }
213 
214 std::vector<Ptr<WifiMacQueueItem>>
216  Time availableTime, WifiMacQueueItem::QueueIteratorPair queueIt) const
217 {
218  NS_LOG_FUNCTION (this << *mpdu << &txParams << availableTime);
219 
220  std::vector<Ptr<WifiMacQueueItem>> mpduList;
221 
222  Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
223  NS_ASSERT (mpdu->GetHeader ().IsQosData () && !recipient.IsBroadcast ());
224  uint8_t tid = mpdu->GetHeader ().GetQosTid ();
225 
226  Ptr<QosTxop> qosTxop = m_mac->GetQosTxop (tid);
227  NS_ASSERT (qosTxop != 0);
228 
229  //Have to make sure that the block ack agreement is established and A-MPDU is enabled
230  if (qosTxop->GetBaAgreementEstablished (recipient, tid)
231  && GetMaxAmpduSize (recipient, tid, txParams.m_txVector.GetModulationClass ()) > 0)
232  {
233  /* here is performed MPDU aggregation */
234  Ptr<WifiMacQueueItem> nextMpdu = mpdu;
235 
236  while (nextMpdu != 0)
237  {
238  // if we are here, nextMpdu can be aggregated to the A-MPDU.
239  NS_LOG_DEBUG ("Adding packet with sequence number " << nextMpdu->GetHeader ().GetSequenceNumber ()
240  << " to A-MPDU, packet size = " << nextMpdu->GetSize ()
241  << ", A-MPDU size = " << txParams.GetSize (recipient));
242 
243  mpduList.push_back (nextMpdu);
244 
245  // If allowed by the BA agreement, get the next MPDU
246  nextMpdu = 0;
247 
248  Ptr<const WifiMacQueueItem> peekedMpdu;
249  peekedMpdu = qosTxop->PeekNextMpdu (queueIt, tid, recipient);
250  if (peekedMpdu != 0)
251  {
252  // PeekNextMpdu() does not return an MPDU that is beyond the transmit window
253  NS_ASSERT (IsInWindow (peekedMpdu->GetHeader ().GetSequenceNumber (),
254  qosTxop->GetBaStartingSequence (recipient, tid),
255  qosTxop->GetBaBufferSize (recipient, tid)));
256 
257  // get the next MPDU to aggregate, provided that the constraints on size
258  // and duration limit are met. Note that the returned MPDU differs from
259  // the peeked MPDU if A-MSDU aggregation is enabled.
260  NS_LOG_DEBUG ("Trying to aggregate another MPDU");
261  nextMpdu = qosTxop->GetNextMpdu (peekedMpdu, txParams, availableTime, false, queueIt);
262  }
263  }
264 
265  if (mpduList.size () == 1)
266  {
267  // return an empty vector if it was not possible to aggregate at least two MPDUs
268  mpduList.clear ();
269  }
270  }
271 
272  return mpduList;
273 }
274 
275 } //namespace ns3
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802...
Aggregator used to construct A-MPDUs.
Ptr< const WifiMacQueueItem > PeekNextMpdu(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast())
Peek the next frame to transmit to the given receiver and of the given TID from the block ack manager...
Definition: qos-txop.cc:277
bool IsBroadcast(void) const
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::vector< Ptr< WifiMacQueueItem > > GetNextAmpdu(Ptr< WifiMacQueueItem > mpdu, WifiTxParameters &txParams, Time availableTime, WifiMacQueueItem::QueueIteratorPair queueIt) const
Attempt to aggregate other MPDUs to the given MPDU, while meeting the following constraints: ...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:231
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:70
#define min(a, b)
Definition: 80211b.c:42
uint32_t GetSize(void) const
Return the size of the packet stored by this item, including header size and trailer size...
WifiModulationClass GetModulationClass(void) const
Get the modulation class specified by this TXVECTOR.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
Information needed to remove an MSDU from the queue.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
void SetWifiMac(const Ptr< RegularWifiMac > mac)
Set the MAC layer to use.
Ptr< RegularWifiMac > m_mac
the MAC of this station
uint16_t GetBaStartingSequence(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:173
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
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...
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
const WifiMacHeader & GetHeader(void) const
Get the header stored in this item.
Video.
Definition: qos-utils.h:77
Hold an unsigned integer type.
Definition: uinteger.h:44
mac
Definition: third.py:99
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:126
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
Headers for A-MPDU subframes.
Best Effort.
Definition: qos-utils.h:73
Ptr< const HeCapabilities > GetStationHeCapabilities(Mac48Address from)
Return the HE capabilities sent by the remote station.
Ptr< const HtCapabilities > GetStationHtCapabilities(Mac48Address from)
Return the HT capabilities sent by the remote station.
static void Aggregate(Ptr< const WifiMacQueueItem > mpdu, Ptr< Packet > ampdu, bool isSingle)
Aggregate an MPDU to an A-MPDU.
void SetEof(bool eof)
Set the EOF field.
uint64_t Get(void) const
Definition: uinteger.cc:35
void SetLength(uint16_t length)
Set the length field.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
static uint8_t CalculatePadding(uint32_t ampduSize)
Background.
Definition: qos-utils.h:75
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:225
an EUI-48 address
Definition: mac48-address.h:43
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
Voice.
Definition: qos-utils.h:79
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint32_t GetMaxAmpduSize(Mac48Address recipient, uint8_t tid, WifiModulationClass modulation) const
Determine the maximum size for an A-MPDU of the given TID that can be sent to the given receiver when...
bool GetBaAgreementEstablished(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:161
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
static TypeId GetTypeId(void)
Get the type ID.
Ptr< const VhtCapabilities > GetStationVhtCapabilities(Mac48Address from)
Return the VHT capabilities sent by the remote station.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism...
uint16_t GetBaBufferSize(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:167
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data...
A base class which provides memory management and object aggregation.
Definition: object.h:87
Ptr< WifiMacQueueItem > GetNextMpdu(Ptr< const WifiMacQueueItem > peekedItem, WifiTxParameters &txParams, Time availableTime, bool initialFrame, WifiMacQueueItem::QueueIteratorPair &queueIt)
Prepare the frame to transmit starting from the MPDU that has been previously peeked by calling PeekN...
Definition: qos-txop.cc:359
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...
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void DoDispose() override
Destructor implementation.