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/he-capabilities.h"
37#include "ns3/ht-capabilities.h"
38#include "ns3/ht-frame-exchange-manager.h"
39#include "ns3/log.h"
40#include "ns3/packet.h"
41#include "ns3/vht-capabilities.h"
42
43NS_LOG_COMPONENT_DEFINE("MpduAggregator");
44
45namespace ns3
46{
47
48NS_OBJECT_ENSURE_REGISTERED(MpduAggregator);
49
50TypeId
52{
53 static TypeId tid = TypeId("ns3::MpduAggregator")
55 .SetGroupName("Wifi")
56 .AddConstructor<MpduAggregator>();
57 return tid;
58}
59
60void
62{
63 m_mac = nullptr;
64 m_htFem = nullptr;
66}
67
68void
70{
71 NS_LOG_FUNCTION(this << mac);
72 m_mac = mac;
73 m_htFem = DynamicCast<HtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
74}
75
76void
78{
79 NS_LOG_FUNCTION(this << +linkId);
80 m_linkId = linkId;
81 if (m_mac)
82 {
83 m_htFem = DynamicCast<HtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
84 }
85}
86
87void
89{
90 NS_LOG_FUNCTION(mpdu << ampdu << isSingle);
91 NS_ASSERT(ampdu);
92 // if isSingle is true, then ampdu must be empty
93 NS_ASSERT(!isSingle || ampdu->GetSize() == 0);
94
95 // pad the previous A-MPDU subframe if the A-MPDU is not empty
96 if (ampdu->GetSize() > 0)
97 {
98 uint8_t padding = CalculatePadding(ampdu->GetSize());
99
100 if (padding)
101 {
102 Ptr<Packet> pad = Create<Packet>(padding);
103 ampdu->AddAtEnd(pad);
104 }
105 }
106
107 // add MPDU header and trailer
108 Ptr<Packet> tmp = mpdu->GetPacket()->Copy();
109 tmp->AddHeader(mpdu->GetHeader());
111
112 // add A-MPDU subframe header and MPDU to the A-MPDU
114 GetAmpduSubframeHeader(static_cast<uint16_t>(tmp->GetSize()), isSingle);
115
116 tmp->AddHeader(hdr);
117 ampdu->AddAtEnd(tmp);
118}
119
122{
123 NS_LOG_FUNCTION(mpduSize << ampduSize);
124
125 return ampduSize + CalculatePadding(ampduSize) + 4 + mpduSize;
126}
127
130 uint8_t tid,
131 WifiModulationClass modulation) const
132{
133 NS_LOG_FUNCTION(this << recipient << +tid << modulation);
134
135 AcIndex ac = QosUtilsMapTidToAc(tid);
136
137 // Find the A-MPDU max size configured on this device
138 uint32_t maxAmpduSize = m_mac->GetMaxAmpduSize(ac);
139
140 if (maxAmpduSize == 0)
141 {
142 NS_LOG_DEBUG("A-MPDU Aggregation is disabled on this station for AC " << ac);
143 return 0;
144 }
145
147 NS_ASSERT(stationManager);
148
149 // Retrieve the Capabilities elements advertised by the recipient
150 Ptr<const HeCapabilities> heCapabilities = stationManager->GetStationHeCapabilities(recipient);
151 Ptr<const VhtCapabilities> vhtCapabilities =
152 stationManager->GetStationVhtCapabilities(recipient);
153 Ptr<const HtCapabilities> htCapabilities = stationManager->GetStationHtCapabilities(recipient);
154
155 // Determine the constraint imposed by the recipient based on the PPDU
156 // format used to transmit the A-MPDU
157 if (modulation >= WIFI_MOD_CLASS_HE)
158 {
159 NS_ABORT_MSG_IF(!heCapabilities, "HE Capabilities element not received");
160
161 maxAmpduSize = std::min(maxAmpduSize, heCapabilities->GetMaxAmpduLength());
162 }
163 else if (modulation == WIFI_MOD_CLASS_VHT)
164 {
165 NS_ABORT_MSG_IF(!vhtCapabilities, "VHT Capabilities element not received");
166
167 maxAmpduSize = std::min(maxAmpduSize, vhtCapabilities->GetMaxAmpduLength());
168 }
169 else if (modulation == WIFI_MOD_CLASS_HT)
170 {
171 NS_ABORT_MSG_IF(!htCapabilities, "HT Capabilities element not received");
172
173 maxAmpduSize = std::min(maxAmpduSize, htCapabilities->GetMaxAmpduLength());
174 }
175 else // non-HT PPDU
176 {
177 NS_LOG_DEBUG("A-MPDU aggregation is not available for non-HT PHYs");
178
179 maxAmpduSize = 0;
180 }
181
182 return maxAmpduSize;
183}
184
185uint8_t
187{
188 return (4 - (ampduSize % 4)) % 4;
189}
190
192MpduAggregator::GetAmpduSubframeHeader(uint16_t mpduSize, bool isSingle)
193{
195 hdr.SetLength(mpduSize);
196 if (isSingle)
197 {
198 hdr.SetEof(1);
199 }
200 return hdr;
201}
202
203std::vector<Ptr<WifiMpdu>>
205 WifiTxParameters& txParams,
206 Time availableTime) const
207{
208 NS_LOG_FUNCTION(this << *mpdu << &txParams << availableTime);
209
210 std::vector<Ptr<WifiMpdu>> mpduList;
211
212 Mac48Address recipient = mpdu->GetHeader().GetAddr1();
213 NS_ASSERT(mpdu->GetHeader().IsQosData() && !recipient.IsBroadcast());
214 uint8_t tid = mpdu->GetHeader().GetQosTid();
215 auto origRecipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
216
217 Ptr<QosTxop> qosTxop = m_mac->GetQosTxop(tid);
218 NS_ASSERT(qosTxop);
219
220 // Have to make sure that the block ack agreement is established and A-MPDU is enabled
221 if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid) &&
222 GetMaxAmpduSize(recipient, tid, txParams.m_txVector.GetModulationClass()) > 0)
223 {
224 /* here is performed MPDU aggregation */
225 Ptr<WifiMpdu> nextMpdu = mpdu;
226
227 while (nextMpdu)
228 {
229 // if we are here, nextMpdu can be aggregated to the A-MPDU.
230 NS_LOG_DEBUG("Adding packet with sequence number "
231 << nextMpdu->GetHeader().GetSequenceNumber()
232 << " to A-MPDU, packet size = " << nextMpdu->GetSize()
233 << ", A-MPDU size = " << txParams.GetSize(recipient));
234
235 mpduList.push_back(nextMpdu);
236
237 // If allowed by the BA agreement, get the next MPDU
238 auto peekedMpdu =
239 qosTxop->PeekNextMpdu(m_linkId, tid, origRecipient, nextMpdu->GetOriginal());
240 nextMpdu = nullptr;
241
242 if (peekedMpdu)
243 {
244 // PeekNextMpdu() does not return an MPDU that is beyond the transmit window
245 NS_ASSERT(IsInWindow(peekedMpdu->GetHeader().GetSequenceNumber(),
246 qosTxop->GetBaStartingSequence(origRecipient, tid),
247 qosTxop->GetBaBufferSize(origRecipient, tid)));
248
249 peekedMpdu = m_htFem->CreateAliasIfNeeded(peekedMpdu);
250 // get the next MPDU to aggregate, provided that the constraints on size
251 // and duration limit are met. Note that the returned MPDU differs from
252 // the peeked MPDU if A-MSDU aggregation is enabled.
253 NS_LOG_DEBUG("Trying to aggregate another MPDU");
254 nextMpdu =
255 qosTxop->GetNextMpdu(m_linkId, peekedMpdu, txParams, availableTime, false);
256 }
257 }
258
259 if (mpduList.size() == 1)
260 {
261 // return an empty vector if it was not possible to aggregate at least two MPDUs
262 mpduList.clear();
263 }
264 }
265
266 return mpduList;
267}
268
269} // 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:353
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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:936
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:1942
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:910
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Definition: wifi-mac.cc:1405
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:497
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:72
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ 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