A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
mpdu-aggregator.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Ghada Badawy <gbadawy@gmail.com>
18 * Stefano Avallone <stavallo@unina.it>
19 */
20
21#include "mpdu-aggregator.h"
22
24#include "ctrl-headers.h"
25#include "msdu-aggregator.h"
26#include "qos-txop.h"
27#include "wifi-mac-trailer.h"
28#include "wifi-mac.h"
29#include "wifi-mpdu.h"
30#include "wifi-net-device.h"
31#include "wifi-phy.h"
33#include "wifi-tx-parameters.h"
34#include "wifi-tx-vector.h"
35
36#include "ns3/eht-capabilities.h"
37#include "ns3/he-capabilities.h"
38#include "ns3/ht-capabilities.h"
39#include "ns3/ht-frame-exchange-manager.h"
40#include "ns3/log.h"
41#include "ns3/packet.h"
42#include "ns3/vht-capabilities.h"
43
44NS_LOG_COMPONENT_DEFINE("MpduAggregator");
45
46namespace ns3
47{
48
49NS_OBJECT_ENSURE_REGISTERED(MpduAggregator);
50
51TypeId
53{
54 static TypeId tid = TypeId("ns3::MpduAggregator")
56 .SetGroupName("Wifi")
57 .AddConstructor<MpduAggregator>();
58 return tid;
59}
60
61void
63{
64 m_mac = nullptr;
65 m_htFem = nullptr;
67}
68
69void
71{
72 NS_LOG_FUNCTION(this << mac);
73 m_mac = mac;
74 m_htFem = DynamicCast<HtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
75}
76
77void
79{
80 NS_LOG_FUNCTION(this << +linkId);
81 m_linkId = linkId;
82 if (m_mac)
83 {
84 m_htFem = DynamicCast<HtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
85 }
86}
87
88void
90{
91 NS_LOG_FUNCTION(mpdu << ampdu << isSingle);
92 NS_ASSERT(ampdu);
93 // if isSingle is true, then ampdu must be empty
94 NS_ASSERT(!isSingle || ampdu->GetSize() == 0);
95
96 // pad the previous A-MPDU subframe if the A-MPDU is not empty
97 if (ampdu->GetSize() > 0)
98 {
99 uint8_t padding = CalculatePadding(ampdu->GetSize());
100
101 if (padding)
102 {
103 Ptr<Packet> pad = Create<Packet>(padding);
104 ampdu->AddAtEnd(pad);
105 }
106 }
107
108 // add MPDU header and trailer
109 Ptr<Packet> tmp = mpdu->GetPacket()->Copy();
110 tmp->AddHeader(mpdu->GetHeader());
112
113 // add A-MPDU subframe header and MPDU to the A-MPDU
115 GetAmpduSubframeHeader(static_cast<uint16_t>(tmp->GetSize()), isSingle);
116
117 tmp->AddHeader(hdr);
118 ampdu->AddAtEnd(tmp);
119}
120
123{
124 NS_LOG_FUNCTION(mpduSize << ampduSize);
125
126 return ampduSize + CalculatePadding(ampduSize) + 4 + mpduSize;
127}
128
131 uint8_t tid,
132 WifiModulationClass modulation) const
133{
134 NS_LOG_FUNCTION(this << recipient << +tid << modulation);
135
136 AcIndex ac = QosUtilsMapTidToAc(tid);
137
138 // Find the A-MPDU max size configured on this device
139 uint32_t maxAmpduSize = m_mac->GetMaxAmpduSize(ac);
140
141 if (maxAmpduSize == 0)
142 {
143 NS_LOG_DEBUG("A-MPDU Aggregation is disabled on this station for AC " << ac);
144 return 0;
145 }
146
148 NS_ASSERT(stationManager);
149
150 // Retrieve the Capabilities elements advertised by the recipient
151 auto ehtCapabilities = stationManager->GetStationEhtCapabilities(recipient);
152 auto heCapabilities = stationManager->GetStationHeCapabilities(recipient);
153 auto vhtCapabilities = stationManager->GetStationVhtCapabilities(recipient);
154 auto htCapabilities = stationManager->GetStationHtCapabilities(recipient);
155
156 // Determine the constraint imposed by the recipient based on the PPDU
157 // format used to transmit the A-MPDU
158 if (modulation >= WIFI_MOD_CLASS_EHT)
159 {
160 NS_ABORT_MSG_IF(!ehtCapabilities, "EHT Capabilities element not received");
161
162 maxAmpduSize = std::min(maxAmpduSize, ehtCapabilities->GetMaxAmpduLength());
163 }
164 else if (modulation >= WIFI_MOD_CLASS_HE)
165 {
166 NS_ABORT_MSG_IF(!heCapabilities, "HE Capabilities element not received");
167
168 maxAmpduSize = std::min(maxAmpduSize, heCapabilities->GetMaxAmpduLength());
169 }
170 else if (modulation == WIFI_MOD_CLASS_VHT)
171 {
172 NS_ABORT_MSG_IF(!vhtCapabilities, "VHT Capabilities element not received");
173
174 maxAmpduSize = std::min(maxAmpduSize, vhtCapabilities->GetMaxAmpduLength());
175 }
176 else if (modulation == WIFI_MOD_CLASS_HT)
177 {
178 NS_ABORT_MSG_IF(!htCapabilities, "HT Capabilities element not received");
179
180 maxAmpduSize = std::min(maxAmpduSize, htCapabilities->GetMaxAmpduLength());
181 }
182 else // non-HT PPDU
183 {
184 NS_LOG_DEBUG("A-MPDU aggregation is not available for non-HT PHYs");
185
186 maxAmpduSize = 0;
187 }
188
189 return maxAmpduSize;
190}
191
192uint8_t
194{
195 return (4 - (ampduSize % 4)) % 4;
196}
197
199MpduAggregator::GetAmpduSubframeHeader(uint16_t mpduSize, bool isSingle)
200{
202 hdr.SetLength(mpduSize);
203 if (isSingle)
204 {
205 hdr.SetEof(true);
206 }
207 return hdr;
208}
209
210std::vector<Ptr<WifiMpdu>>
212 WifiTxParameters& txParams,
213 Time availableTime) const
214{
215 NS_LOG_FUNCTION(this << *mpdu << &txParams << availableTime);
216
217 std::vector<Ptr<WifiMpdu>> mpduList;
218
219 Mac48Address recipient = mpdu->GetHeader().GetAddr1();
220 NS_ASSERT(mpdu->GetHeader().IsQosData() && !recipient.IsBroadcast());
221 uint8_t tid = mpdu->GetHeader().GetQosTid();
222 auto origRecipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
223
224 Ptr<QosTxop> qosTxop = m_mac->GetQosTxop(tid);
225 NS_ASSERT(qosTxop);
226
227 // Have to make sure that the block ack agreement is established and A-MPDU is enabled
228 if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid) &&
229 GetMaxAmpduSize(recipient, tid, txParams.m_txVector.GetModulationClass()) > 0)
230 {
231 /* here is performed MPDU aggregation */
232 Ptr<WifiMpdu> nextMpdu = mpdu;
233
234 while (nextMpdu)
235 {
236 // if we are here, nextMpdu can be aggregated to the A-MPDU.
237 NS_LOG_DEBUG("Adding packet with sequence number "
238 << nextMpdu->GetHeader().GetSequenceNumber()
239 << " to A-MPDU, packet size = " << nextMpdu->GetSize()
240 << ", A-MPDU size = " << txParams.GetSize(recipient));
241
242 mpduList.push_back(nextMpdu);
243
244 // If allowed by the BA agreement, get the next MPDU
245 auto peekedMpdu =
246 qosTxop->PeekNextMpdu(m_linkId, tid, origRecipient, nextMpdu->GetOriginal());
247 nextMpdu = nullptr;
248
249 if (peekedMpdu)
250 {
251 // PeekNextMpdu() does not return an MPDU that is beyond the transmit window
252 NS_ASSERT(IsInWindow(peekedMpdu->GetHeader().GetSequenceNumber(),
253 qosTxop->GetBaStartingSequence(origRecipient, tid),
254 qosTxop->GetBaBufferSize(origRecipient, tid)));
255
256 peekedMpdu = m_htFem->CreateAliasIfNeeded(peekedMpdu);
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 =
262 qosTxop->GetNextMpdu(m_linkId, peekedMpdu, txParams, availableTime, false);
263 }
264 }
265
266 if (mpduList.size() == 1)
267 {
268 // return an empty vector if it was not possible to aggregate at least two MPDUs
269 mpduList.clear();
270 }
271 }
272
273 return mpduList;
274}
275
276} // namespace ns3
Headers for A-MPDU subframes.
void SetEof(bool eof)
Set the EOF field.
void SetLength(uint16_t length)
Set the length field.
an EUI-48 address
Definition: mac48-address.h:46
bool IsBroadcast() const
Aggregator used to construct A-MPDUs.
static uint8_t CalculatePadding(uint32_t ampduSize)
void DoDispose() override
Destructor implementation.
static void Aggregate(Ptr< const WifiMpdu > mpdu, Ptr< Packet > ampdu, bool isSingle)
Aggregate an MPDU to an A-MPDU.
Ptr< WifiMac > m_mac
the MAC of this station
Ptr< HtFrameExchangeManager > m_htFem
the HT Frame Exchange Manager of this station
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...
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 TypeId GetTypeId()
Get the type ID.
void SetWifiMac(const Ptr< WifiMac > mac)
Set the MAC layer to use.
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...
std::vector< Ptr< WifiMpdu > > GetNextAmpdu(Ptr< WifiMpdu > mpdu, WifiTxParameters &txParams, Time availableTime) const
Attempt to aggregate other MPDUs to the given MPDU, while meeting the following constraints:
void SetLinkId(uint8_t linkId)
Set the ID of the link this MPDU aggregator is associated with.
uint8_t m_linkId
ID of the link this object is connected to.
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:864
uint32_t GetMaxAmpduSize(AcIndex ac) const
Return the maximum A-MPDU size of the given Access Category.
Definition: wifi-mac.cc:2251
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:906
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Definition: wifi-mac.cc:1679
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:499
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:134
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:73
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:125
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:119