1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
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: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #ifndef WIFI_ACKNOWLEDGMENT_H
22 #define WIFI_ACKNOWLEDGMENT_H
23 
24 #include "ns3/nstime.h"
25 #include "wifi-tx-vector.h"
26 #include "block-ack-type.h"
27 #include "wifi-mac-header.h"
28 #include "ctrl-headers.h"
29 #include <map>
30 #include <memory>
31 
32 
33 namespace ns3 {
34 
35 class Mac48Address;
36 
37 /**
38  * \ingroup wifi
39  *
40  * WifiAcknowledgment is an abstract base struct. Each derived struct defines an acknowledgment
41  * method and stores the information needed to perform acknowledgment according to
42  * that method.
43  */
44 struct WifiAcknowledgment
45 {
46   /**
47    * \enum Method
48    * \brief Available acknowledgment methods
49    */
50   enum Method
51     {
52       NONE = 0,
53       NORMAL_ACK,
54       BLOCK_ACK,
55       BAR_BLOCK_ACK,
56       DL_MU_BAR_BA_SEQUENCE,
57       DL_MU_TF_MU_BAR,
58       DL_MU_AGGREGATE_TF,
59       UL_MU_MULTI_STA_BA,
60       ACK_AFTER_TB_PPDU
61     };
62 
63   /**
64    * Constructor.
65    * \param m the acknowledgment method for this object
66    */
67   WifiAcknowledgment (Method m);
68   virtual ~WifiAcknowledgment ();
69 
70   /**
71    * Clone this object.
72    * \return a pointer to the cloned object
73    */
74   virtual std::unique_ptr<WifiAcknowledgment> Copy (void) const = 0;
75 
76   /**
77    * Get the QoS Ack policy to use for the MPDUs addressed to the given receiver
78    * and belonging to the given TID.
79    *
80    * \param receiver the MAC address of the receiver
81    * \param tid the TID
82    * \return the QoS Ack policy to use
83    */
84   WifiMacHeader::QosAckPolicy GetQosAckPolicy (Mac48Address receiver, uint8_t tid) const;
85 
86   /**
87    * Set the QoS Ack policy to use for the MPDUs addressed to the given receiver
88    * and belonging to the given TID. If the pair (receiver, TID) already exists,
89    * it is overwritten with the given QoS Ack policy.
90    *
91    * \param receiver the MAC address of the receiver
92    * \param tid the TID
93    * \param ackPolicy the QoS Ack policy to use
94    */
95   void SetQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy);
96 
97   /**
98    * \brief Print the object contents.
99    * \param os output stream in which the data should be printed.
100    */
101   virtual void Print (std::ostream &os) const = 0;
102 
103   const Method method;       //!< acknowledgment method
104   Time acknowledgmentTime;   //!< time required by the acknowledgment method
105 
106 private:
107   /**
108    * Check whether the given QoS Ack policy can be used for the MPDUs addressed
109    * to the given receiver and belonging to the given TID.
110    *
111    * \param receiver the MAC address of the receiver
112    * \param tid the TID
113    * \param ackPolicy the QoS Ack policy to use
114    * \return true if the given QoS Ack policy can be used, false otherwise
115    */
116   virtual bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid,
117                                   WifiMacHeader::QosAckPolicy ackPolicy) const = 0;
118 
119   /// Qos Ack Policy to set for MPDUs addressed to a given receiver and having a given TID
120   std::map<std::pair<Mac48Address, uint8_t>, WifiMacHeader::QosAckPolicy> m_ackPolicy;
121 };
122 
123 
124 /**
125  * \ingroup wifi
126  *
127  * WifiNoAck specifies that no acknowledgment is required.
128  */
129 struct WifiNoAck : public WifiAcknowledgment
130 {
131   WifiNoAck ();
132 
133   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
134   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
135   void Print (std::ostream &os) const override;
136 };
137 
138 
139 /**
140  * \ingroup wifi
141  *
142  * WifiNormalAck specifies that acknowledgment via Normal Ack is required.
143  */
144 struct WifiNormalAck : public WifiAcknowledgment
145 {
146   WifiNormalAck ();
147 
148   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
149   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
150   void Print (std::ostream &os) const override;
151 
152   WifiTxVector ackTxVector;       //!< Ack TXVECTOR
153 };
154 
155 
156 /**
157  * \ingroup wifi
158  *
159  * WifiBlockAck specifies that acknowledgment via Block Ack is required.
160  */
161 struct WifiBlockAck : public WifiAcknowledgment
162 {
163   WifiBlockAck ();
164 
165   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
166   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
167   void Print (std::ostream &os) const override;
168 
169   WifiTxVector blockAckTxVector;       //!< BlockAck TXVECTOR
170   BlockAckType baType;                 //!< BlockAck type
171 };
172 
173 
174 /**
175  * \ingroup wifi
176  *
177  * WifiBarBlockAck specifies that a BlockAckReq is sent to solicit a Block Ack response.
178  */
179 struct WifiBarBlockAck : public WifiAcknowledgment
180 {
181   WifiBarBlockAck ();
182 
183   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
184   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
185   void Print (std::ostream &os) const override;
186 
187   WifiTxVector blockAckReqTxVector;    //!< BlockAckReq TXVECTOR
188   WifiTxVector blockAckTxVector;       //!< BlockAck TXVECTOR
189   BlockAckReqType barType;             //!< BlockAckReq type
190   BlockAckType baType;                 //!< BlockAck type
191 };
192 
193 
194 /**
195  * \ingroup wifi
196  *
197  * WifiDlMuBarBaSequence specifies that a DL MU PPDU is acknowledged through a
198  * sequence of BlockAckReq and BlockAck frames. Only one station may be allowed
199  * to reply a SIFS after the DL MU PPDU by sending either a Normal Ack or a BlockAck.
200  */
201 struct WifiDlMuBarBaSequence : public WifiAcknowledgment
202 {
203   WifiDlMuBarBaSequence ();
204 
205   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
206   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
207   void Print (std::ostream &os) const override;
208 
209   /// information related to an Ack frame sent by a station
210   struct AckInfo
211   {
212     WifiTxVector ackTxVector;          //!< TXVECTOR for the Ack frame
213   };
214   /// information related to a BlockAck frame sent by a station
215   struct BlockAckInfo
216   {
217     WifiTxVector blockAckTxVector;     //!< TXVECTOR for the BlockAck frame
218     BlockAckType baType;               //!< BlockAck type
219   };
220   /// information related to a BlockAckReq frame sent to a station
221   struct BlockAckReqInfo
222   {
223     WifiTxVector blockAckReqTxVector;  //!< TXVECTOR for the BlockAckReq frame
224     BlockAckReqType barType;           //!< BlockAckReq type
225     WifiTxVector blockAckTxVector;     //!< TXVECTOR for the BlockAck frame
226     BlockAckType baType;               //!< BlockAck type
227   };
228 
229   /// Set of stations replying with an Ack frame (no more than one)
230   std::map<Mac48Address, AckInfo> stationsReplyingWithNormalAck;
231   /// Set of stations replying with a BlockAck frame (no more than one)
232   std::map<Mac48Address, BlockAckInfo> stationsReplyingWithBlockAck;
233   /// Set of stations receiving a BlockAckReq frame and replying with a BlockAck frame
234   std::map<Mac48Address, BlockAckReqInfo> stationsSendBlockAckReqTo;
235 };
236 
237 
238 /**
239  * \ingroup wifi
240  *
241  * WifiDlMuTfMuBar specifies that a DL MU PPDU is followed after a SIFS duration
242  * by a MU-BAR Trigger Frame (sent as single user frame) soliciting BlockAck
243  * frames sent as HE TB PPDUs.
244  */
245 struct WifiDlMuTfMuBar : public WifiAcknowledgment
246 {
247   WifiDlMuTfMuBar ();
248 
249   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
250   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
251   void Print (std::ostream &os) const override;
252 
253   /// information related to a BlockAck frame sent by a station
254   struct BlockAckInfo
255   {
256     CtrlBAckRequestHeader barHeader;   //!< BlockAckReq header
257     WifiTxVector blockAckTxVector;     //!< TXVECTOR for the BlockAck frame
258     BlockAckType baType;               //!< BlockAck type
259   };
260 
261   /// Set of stations replying with a BlockAck frame
262   std::map<Mac48Address, BlockAckInfo> stationsReplyingWithBlockAck;
263   std::list<BlockAckReqType> barTypes; //!< BAR types
264   uint16_t ulLength;                   //!< the UL Length field of the MU-BAR Trigger Frame
265   WifiTxVector muBarTxVector;          //!< TXVECTOR used to transmit the MU-BAR Trigger Frame
266 };
267 
268 
269 /**
270  * \ingroup wifi
271  *
272  * WifiDlMuAggregateTf specifies that a DL MU PPDU made of PSDUs including each
273  * a MU-BAR Trigger Frame is acknowledged through BlockAck frames sent as
274  * HE TB PPDUs.
275  */
276 struct WifiDlMuAggregateTf : public WifiAcknowledgment
277 {
278   WifiDlMuAggregateTf ();
279 
280   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
281   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
282   void Print (std::ostream &os) const override;
283 
284   /// information related to a BlockAck frame sent by a station
285   struct BlockAckInfo
286   {
287     uint32_t muBarSize;                //!< size in bytes of a MU-BAR Trigger Frame
288     CtrlBAckRequestHeader barHeader;   //!< BlockAckReq header
289     WifiTxVector blockAckTxVector;     //!< TXVECTOR for the BlockAck frame
290     BlockAckType baType;               //!< BlockAck type
291   };
292 
293   /// Set of stations replying with a BlockAck frame
294   std::map<Mac48Address, BlockAckInfo> stationsReplyingWithBlockAck;
295   uint16_t ulLength;                   //!< the UL Length field of the MU-BAR Trigger Frames
296 };
297 
298 
299 /**
300  * \ingroup wifi
301  *
302  * WifiUlMuMultiStaBa specifies that a Basic Trigger Frame is being sent to
303  * solicit TB PPDUs that will be acknowledged through a multi-STA BlockAck frame.
304  */
305 struct WifiUlMuMultiStaBa : public WifiAcknowledgment
306 {
307   WifiUlMuMultiStaBa ();
308 
309   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
310   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
311   void Print (std::ostream &os) const override;
312 
313   /// Map (originator, tid) pairs to the their index in baType
314   std::map<std::pair<Mac48Address, uint8_t>, std::size_t> stationsReceivingMultiStaBa;
315   BlockAckType baType;                 //!< BlockAck type
316   WifiTxVector tbPpduTxVector;         //!< TXVECTOR for a TB PPDU
317   WifiTxVector multiStaBaTxVector;     //!< TXVECTOR for the Multi-STA BlockAck
318 };
319 
320 
321 /**
322  * \ingroup wifi
323  *
324  * WifiAckAfterTbPpdu is used when a station prepares a TB PPDU to send in
325  * response to a Basic Trigger Frame. The acknowledgment time must be
326  * zero because the time taken by the actual acknowledgment is not included
327  * in the duration indicated by the Trigger Frame. The QoS ack policy instead
328  * must be Normal Ack/Implicit Block Ack Request.
329  */
330 struct WifiAckAfterTbPpdu : public WifiAcknowledgment
331 {
332   WifiAckAfterTbPpdu ();
333 
334   std::unique_ptr<WifiAcknowledgment> Copy (void) const override;
335   bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override;
336   void Print (std::ostream &os) const override;
337 };
338 
339 
340 /**
341  * \brief Stream insertion operator.
342  *
343  * \param os the output stream
344  * \param acknowledgment the acknowledgment method
345  * \returns a reference to the stream
346  */
347 std::ostream& operator<< (std::ostream& os, const WifiAcknowledgment* acknowledgment);
348 
349 } //namespace ns3
350 
351 #endif /* WIFI_ACKNOWLEDGMENT_H */
352