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 "mac-low.h"
30 #include "wifi-mac-queue-item.h"
31 #include "wifi-mac-queue.h"
32 #include "msdu-aggregator.h"
33 #include "wifi-net-device.h"
34 #include "ht-capabilities.h"
35 #include "vht-capabilities.h"
36 #include "he-capabilities.h"
37 #include "wifi-mac.h"
38 #include "ctrl-headers.h"
39 #include "wifi-mac-trailer.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_edca = edcaQueues;
70 }
71 
72 void
74 {
75  NS_LOG_FUNCTION (mpdu << ampdu << isSingle);
76  NS_ASSERT (ampdu);
77  // if isSingle is true, then ampdu must be empty
78  NS_ASSERT (!isSingle || ampdu->GetSize () == 0);
79 
80  // pad the previous A-MPDU subframe if the A-MPDU is not empty
81  if (ampdu->GetSize () > 0)
82  {
83  uint8_t padding = CalculatePadding (ampdu->GetSize ());
84 
85  if (padding)
86  {
87  Ptr<Packet> pad = Create<Packet> (padding);
88  ampdu->AddAtEnd (pad);
89  }
90  }
91 
92  // add MPDU header and trailer
93  Ptr<Packet> tmp = mpdu->GetPacket ()->Copy ();
94  tmp->AddHeader (mpdu->GetHeader ());
95  AddWifiMacTrailer (tmp);
96 
97  // add A-MPDU subframe header and MPDU to the A-MPDU
98  AmpduSubframeHeader hdr = GetAmpduSubframeHeader (static_cast<uint16_t> (tmp->GetSize ()), isSingle);
99 
100  tmp->AddHeader (hdr);
101  ampdu->AddAtEnd (tmp);
102 }
103 
104 uint32_t
105 MpduAggregator::GetSizeIfAggregated (uint32_t mpduSize, uint32_t ampduSize)
106 {
107  NS_LOG_FUNCTION (mpduSize << ampduSize);
108 
109  return ampduSize + CalculatePadding (ampduSize) + 4 + mpduSize;
110 }
111 
112 uint32_t
114  WifiModulationClass modulation) const
115 {
116  NS_LOG_FUNCTION (this << recipient << +tid << modulation);
117 
118  AcIndex ac = QosUtilsMapTidToAc (tid);
119  Ptr<QosTxop> qosTxop = m_edca.find (ac)->second;
120  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (qosTxop->GetLow ()->GetPhy ()->GetDevice ());
121  NS_ASSERT (device);
122  Ptr<WifiRemoteStationManager> stationManager = device->GetRemoteStationManager ();
123  NS_ASSERT (stationManager);
124 
125  // Find the A-MPDU max size configured on this device
126  UintegerValue size;
127 
128  switch (ac)
129  {
130  case AC_BE:
131  device->GetMac ()->GetAttribute ("BE_MaxAmpduSize", size);
132  break;
133  case AC_BK:
134  device->GetMac ()->GetAttribute ("BK_MaxAmpduSize", size);
135  break;
136  case AC_VI:
137  device->GetMac ()->GetAttribute ("VI_MaxAmpduSize", size);
138  break;
139  case AC_VO:
140  device->GetMac ()->GetAttribute ("VO_MaxAmpduSize", size);
141  break;
142  default:
143  NS_ABORT_MSG ("Unknown AC " << ac);
144  return 0;
145  }
146 
147  uint32_t maxAmpduSize = size.Get ();
148 
149  if (maxAmpduSize == 0)
150  {
151  NS_LOG_DEBUG ("A-MPDU Aggregation is disabled on this station for AC " << ac);
152  return 0;
153  }
154 
155  // Retrieve the Capabilities elements advertised by the recipient
156  Ptr<const HeCapabilities> heCapabilities = stationManager->GetStationHeCapabilities (recipient);
157  Ptr<const VhtCapabilities> vhtCapabilities = stationManager->GetStationVhtCapabilities (recipient);
158  Ptr<const HtCapabilities> htCapabilities = stationManager->GetStationHtCapabilities (recipient);
159 
160  // Determine the constraint imposed by the recipient based on the PPDU
161  // format used to transmit the A-MPDU
162  if (modulation == WIFI_MOD_CLASS_HE)
163  {
164  NS_ABORT_MSG_IF (!heCapabilities, "HE Capabilities element not received");
165 
166  maxAmpduSize = std::min (maxAmpduSize, heCapabilities->GetMaxAmpduLength ());
167  }
168  else if (modulation == WIFI_MOD_CLASS_VHT)
169  {
170  NS_ABORT_MSG_IF (!vhtCapabilities, "VHT Capabilities element not received");
171 
172  maxAmpduSize = std::min (maxAmpduSize, vhtCapabilities->GetMaxAmpduLength ());
173  }
174  else if (modulation == WIFI_MOD_CLASS_HT)
175  {
176  NS_ABORT_MSG_IF (!htCapabilities, "HT Capabilities element not received");
177 
178  maxAmpduSize = std::min (maxAmpduSize, htCapabilities->GetMaxAmpduLength ());
179  }
180  else // non-HT PPDU
181  {
182  NS_LOG_DEBUG ("A-MPDU aggregation is not available for non-HT PHYs");
183 
184  maxAmpduSize = 0;
185  }
186 
187  return maxAmpduSize;
188 }
189 
190 uint8_t
192 {
193  return (4 - (ampduSize % 4 )) % 4;
194 }
195 
197 MpduAggregator::GetAmpduSubframeHeader (uint16_t mpduSize, bool isSingle)
198 {
200  hdr.SetLength (mpduSize);
201  if (isSingle)
202  {
203  hdr.SetEof (1);
204  }
205  return hdr;
206 }
207 
208 std::vector<Ptr<WifiMacQueueItem>>
210  Time ppduDurationLimit) const
211 {
212  NS_LOG_FUNCTION (this << *mpdu << ppduDurationLimit);
213  std::vector<Ptr<WifiMacQueueItem>> mpduList;
214  Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
215 
216  NS_ASSERT (mpdu->GetHeader ().IsQosData () && !recipient.IsGroup ());
217 
218  uint8_t tid = GetTid (mpdu->GetPacket (), mpdu->GetHeader ());
219  auto edcaIt = m_edca.find (QosUtilsMapTidToAc (tid));
220  NS_ASSERT (edcaIt != m_edca.end ());
221 
222  WifiModulationClass modulation = txVector.GetMode ().GetModulationClass ();
223  uint32_t maxAmpduSize = GetMaxAmpduSize (recipient, tid, modulation);
224 
225  if (maxAmpduSize == 0)
226  {
227  NS_LOG_DEBUG ("A-MPDU aggregation disabled");
228  return mpduList;
229  }
230 
231  //Have to make sure that the block ack agreement is established before sending an A-MPDU
232  if (edcaIt->second->GetBaAgreementEstablished (recipient, tid))
233  {
234  /* here is performed MPDU aggregation */
235  uint16_t startingSequenceNumber = edcaIt->second->GetBaStartingSequence (recipient, tid);
236  Ptr<WifiMacQueueItem> nextMpdu;
237  uint16_t maxMpdus = edcaIt->second->GetBaBufferSize (recipient, tid);
238  uint32_t currentAmpduSize = 0;
239 
240  // check if the received MPDU meets the size and duration constraints
241  if (edcaIt->second->GetLow ()->IsWithinSizeAndTimeLimits (mpdu, txVector, 0, ppduDurationLimit))
242  {
243  // MPDU can be aggregated
244  nextMpdu = Copy (mpdu);
245  }
246 
247  while (nextMpdu != 0)
248  {
249  /* if we are here, nextMpdu can be aggregated to the A-MPDU.
250  * nextMpdu may be any of the following:
251  * (a) an A-MSDU (with all the constituent MSDUs dequeued from
252  * the EDCA queue)
253  * (b) an MSDU dequeued from the EDCA queue
254  * (c) a retransmitted MSDU or A-MSDU dequeued from the BA Manager queue
255  * (d) an MPDU that was aggregated in an A-MPDU which was not
256  * transmitted (e.g., because the RTS/CTS exchange failed)
257  */
258 
259  currentAmpduSize = GetSizeIfAggregated (nextMpdu->GetSize (), currentAmpduSize);
260 
261  NS_LOG_DEBUG ("Adding packet with sequence number " << nextMpdu->GetHeader ().GetSequenceNumber ()
262  << " to A-MPDU, packet size = " << nextMpdu->GetSize ()
263  << ", A-MPDU size = " << currentAmpduSize);
264 
265  // Always use the Normal Ack policy (Implicit Block Ack), for now
266  nextMpdu->GetHeader ().SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
267 
268  mpduList.push_back (nextMpdu);
269 
270  // If allowed by the BA agreement, get the next MPDU
271  nextMpdu = 0;
272 
273  Ptr<const WifiMacQueueItem> peekedMpdu;
274  peekedMpdu = edcaIt->second->PeekNextFrame (tid, recipient);
275  if (peekedMpdu != 0)
276  {
277  uint16_t currentSequenceNumber = peekedMpdu->GetHeader ().GetSequenceNumber ();
278 
279  if (IsInWindow (currentSequenceNumber, startingSequenceNumber, maxMpdus))
280  {
281  // dequeue the frame if constraints on size and duration limit are met.
282  // Note that the dequeued MPDU differs from the peeked MPDU if A-MSDU
283  // aggregation is performed during the dequeue
284  NS_LOG_DEBUG ("Trying to aggregate another MPDU");
285  nextMpdu = edcaIt->second->DequeuePeekedFrame (peekedMpdu, txVector, true,
286  currentAmpduSize, ppduDurationLimit);
287  }
288  }
289  }
290  if (mpduList.size () == 1)
291  {
292  // return an empty vector if it was not possible to aggregate at least two MPDUs
293  mpduList.clear ();
294  }
295  }
296  return mpduList;
297 }
298 
299 } //namespace ns3
Aggregator used to construct A-MPDUs.
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 "...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#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:219
#define min(a, b)
Definition: 80211b.c:42
#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
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
Video.
Definition: qos-utils.h:45
Voice.
Definition: qos-utils.h:47
Best Effort.
Definition: qos-utils.h:41
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...
Background.
Definition: qos-utils.h:43
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
Ptr< WifiRemoteStationManager > GetRemoteStationManager(void) const
Hold an unsigned integer type.
Definition: uinteger.h:44
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:32
WifiMode GetMode(void) const
Headers for A-MPDU subframes.
HT PHY (Clause 20)
Definition: wifi-mode.h:58
Ptr< const HeCapabilities > GetStationHeCapabilities(Mac48Address from)
Return the HE capabilities sent by the remote station.
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:463
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.
Ptr< MacLow > GetLow(void) const
Return the MacLow associated with this Txop.
Definition: txop.cc:366
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static uint8_t CalculatePadding(uint32_t ampduSize)
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:213
an EUI-48 address
Definition: mac48-address.h:43
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
Extraction operator for TypeId.
Definition: qos-utils.cc:99
bool IsGroup(void) const
std::vector< Ptr< WifiMacQueueItem > > GetNextAmpdu(Ptr< const WifiMacQueueItem > mpdu, WifiTxVector txVector, Time ppduDurationLimit=Time::Min()) const
Attempt to aggregate other MPDUs to the given MPDU, while meeting the following constraints: ...
Ptr< WifiMac > GetMac(void) const
WifiModulationClass
This enumeration defines the modulation classes per (Table 9-4 "Modulation classes"; IEEE 802...
Definition: wifi-mode.h:36
#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...
#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.
std::map< AcIndex, Ptr< QosTxop > > EdcaQueues
EDCA queues typedef.
A base class which provides memory management and object aggregation.
Definition: object.h:87
EdcaQueues m_edca
the map of EDCA queues
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
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:38
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:536
HE PHY (Clause 26)
Definition: wifi-mode.h:62
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void SetEdcaQueues(EdcaQueues edcaQueues)
Set the map of EDCA queues.