A Discrete-Event Network Simulator
API
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/log.h"
39#include "ns3/packet.h"
40#include "ns3/vht-capabilities.h"
41
42NS_LOG_COMPONENT_DEFINE("MpduAggregator");
43
44namespace ns3
45{
46
47NS_OBJECT_ENSURE_REGISTERED(MpduAggregator);
48
49TypeId
51{
52 static TypeId tid = TypeId("ns3::MpduAggregator")
54 .SetGroupName("Wifi")
55 .AddConstructor<MpduAggregator>();
56 return tid;
57}
58
60{
61}
62
64{
65}
66
67void
69{
70 m_mac = nullptr;
72}
73
74void
76{
77 NS_LOG_FUNCTION(this << mac);
78 m_mac = mac;
79}
80
81void
83{
84 NS_LOG_FUNCTION(mpdu << ampdu << isSingle);
85 NS_ASSERT(ampdu);
86 // if isSingle is true, then ampdu must be empty
87 NS_ASSERT(!isSingle || ampdu->GetSize() == 0);
88
89 // pad the previous A-MPDU subframe if the A-MPDU is not empty
90 if (ampdu->GetSize() > 0)
91 {
92 uint8_t padding = CalculatePadding(ampdu->GetSize());
93
94 if (padding)
95 {
96 Ptr<Packet> pad = Create<Packet>(padding);
97 ampdu->AddAtEnd(pad);
98 }
99 }
100
101 // add MPDU header and trailer
102 Ptr<Packet> tmp = mpdu->GetPacket()->Copy();
103 tmp->AddHeader(mpdu->GetHeader());
105
106 // add A-MPDU subframe header and MPDU to the A-MPDU
108 GetAmpduSubframeHeader(static_cast<uint16_t>(tmp->GetSize()), isSingle);
109
110 tmp->AddHeader(hdr);
111 ampdu->AddAtEnd(tmp);
112}
113
116{
117 NS_LOG_FUNCTION(mpduSize << ampduSize);
118
119 return ampduSize + CalculatePadding(ampduSize) + 4 + mpduSize;
120}
121
124 uint8_t tid,
125 WifiModulationClass modulation) const
126{
127 NS_LOG_FUNCTION(this << recipient << +tid << modulation);
128
129 AcIndex ac = QosUtilsMapTidToAc(tid);
130
131 // Find the A-MPDU max size configured on this device
132 uint32_t maxAmpduSize = m_mac->GetMaxAmpduSize(ac);
133
134 if (maxAmpduSize == 0)
135 {
136 NS_LOG_DEBUG("A-MPDU Aggregation is disabled on this station for AC " << ac);
137 return 0;
138 }
139
140 Ptr<WifiRemoteStationManager> stationManager = m_mac->GetWifiRemoteStationManager();
141 NS_ASSERT(stationManager);
142
143 // Retrieve the Capabilities elements advertised by the recipient
144 Ptr<const HeCapabilities> heCapabilities = stationManager->GetStationHeCapabilities(recipient);
145 Ptr<const VhtCapabilities> vhtCapabilities =
146 stationManager->GetStationVhtCapabilities(recipient);
147 Ptr<const HtCapabilities> htCapabilities = stationManager->GetStationHtCapabilities(recipient);
148
149 // Determine the constraint imposed by the recipient based on the PPDU
150 // format used to transmit the A-MPDU
151 if (modulation >= WIFI_MOD_CLASS_HE)
152 {
153 NS_ABORT_MSG_IF(!heCapabilities, "HE Capabilities element not received");
154
155 maxAmpduSize = std::min(maxAmpduSize, heCapabilities->GetMaxAmpduLength());
156 }
157 else if (modulation == WIFI_MOD_CLASS_VHT)
158 {
159 NS_ABORT_MSG_IF(!vhtCapabilities, "VHT Capabilities element not received");
160
161 maxAmpduSize = std::min(maxAmpduSize, vhtCapabilities->GetMaxAmpduLength());
162 }
163 else if (modulation == WIFI_MOD_CLASS_HT)
164 {
165 NS_ABORT_MSG_IF(!htCapabilities, "HT Capabilities element not received");
166
167 maxAmpduSize = std::min(maxAmpduSize, htCapabilities->GetMaxAmpduLength());
168 }
169 else // non-HT PPDU
170 {
171 NS_LOG_DEBUG("A-MPDU aggregation is not available for non-HT PHYs");
172
173 maxAmpduSize = 0;
174 }
175
176 return maxAmpduSize;
177}
178
179uint8_t
181{
182 return (4 - (ampduSize % 4)) % 4;
183}
184
186MpduAggregator::GetAmpduSubframeHeader(uint16_t mpduSize, bool isSingle)
187{
189 hdr.SetLength(mpduSize);
190 if (isSingle)
191 {
192 hdr.SetEof(1);
193 }
194 return hdr;
195}
196
197std::vector<Ptr<WifiMpdu>>
199 WifiTxParameters& txParams,
200 Time availableTime) const
201{
202 NS_LOG_FUNCTION(this << *mpdu << &txParams << availableTime);
203
204 std::vector<Ptr<WifiMpdu>> mpduList;
205
206 Mac48Address recipient = mpdu->GetHeader().GetAddr1();
207 NS_ASSERT(mpdu->GetHeader().IsQosData() && !recipient.IsBroadcast());
208 uint8_t tid = mpdu->GetHeader().GetQosTid();
209
210 Ptr<QosTxop> qosTxop = m_mac->GetQosTxop(tid);
211 NS_ASSERT(qosTxop);
212
213 // Have to make sure that the block ack agreement is established and A-MPDU is enabled
214 if (qosTxop->GetBaAgreementEstablished(recipient, tid) &&
215 GetMaxAmpduSize(recipient, tid, txParams.m_txVector.GetModulationClass()) > 0)
216 {
217 /* here is performed MPDU aggregation */
218 Ptr<WifiMpdu> nextMpdu = mpdu;
219
220 while (nextMpdu)
221 {
222 // if we are here, nextMpdu can be aggregated to the A-MPDU.
223 NS_LOG_DEBUG("Adding packet with sequence number "
224 << nextMpdu->GetHeader().GetSequenceNumber()
225 << " to A-MPDU, packet size = " << nextMpdu->GetSize()
226 << ", A-MPDU size = " << txParams.GetSize(recipient));
227
228 mpduList.push_back(nextMpdu);
229
230 // If allowed by the BA agreement, get the next MPDU
231 auto peekedMpdu = qosTxop->PeekNextMpdu(SINGLE_LINK_OP_ID, tid, recipient, nextMpdu);
232 nextMpdu = nullptr;
233
234 if (peekedMpdu)
235 {
236 // PeekNextMpdu() does not return an MPDU that is beyond the transmit window
237 NS_ASSERT(IsInWindow(peekedMpdu->GetHeader().GetSequenceNumber(),
238 qosTxop->GetBaStartingSequence(recipient, tid),
239 qosTxop->GetBaBufferSize(recipient, tid)));
240
241 // get the next MPDU to aggregate, provided that the constraints on size
242 // and duration limit are met. Note that the returned MPDU differs from
243 // the peeked MPDU if A-MSDU aggregation is enabled.
244 NS_LOG_DEBUG("Trying to aggregate another MPDU");
245 nextMpdu = qosTxop->GetNextMpdu(SINGLE_LINK_OP_ID,
246 peekedMpdu,
247 txParams,
248 availableTime,
249 false);
250 }
251 }
252
253 if (mpduList.size() == 1)
254 {
255 // return an empty vector if it was not possible to aggregate at least two MPDUs
256 mpduList.clear();
257 }
258 }
259
260 return mpduList;
261}
262
263} // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
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)
~MpduAggregator() override
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
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:
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
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
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
uint16_t GetBaBufferSize(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:269
bool GetBaAgreementEstablished(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:261
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< WifiMpdu > item=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
Definition: qos-txop.cc:368
Ptr< WifiMpdu > GetNextMpdu(uint8_t linkId, Ptr< WifiMpdu > peekedItem, WifiTxParameters &txParams, Time availableTime, bool initialFrame)
Prepare the frame to transmit on the given link starting from the MPDU that has been previously peeke...
Definition: qos-txop.cc:454
uint16_t GetBaStartingSequence(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:275
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Ptr< const HtCapabilities > GetStationHtCapabilities(Mac48Address from)
Return the HT capabilities sent by the remote station.
Ptr< const HeCapabilities > GetStationHeCapabilities(Mac48Address from)
Return the HE capabilities sent by the remote station.
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,...
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:45
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:132
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:74
@ 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.
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition: wifi-utils.h:140
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
mac
Definition: third.py:85