1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006,2007 INRIA
4  * Copyright (c) 2020 Orange Labs
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  *          Rediet <getachew.redieteab@orange.com>
21  */
22 
23 #ifndef WIFI_PHY_COMMON_H
24 #define WIFI_PHY_COMMON_H
25 
26 #include <ostream>
27 #include "ns3/fatal-error.h"
28 #include "ns3/ptr.h"
29 
30 /**
31  * \file
32  * \ingroup wifi
33  * Declaration of the following enums:
34  * - ns3::WifiPreamble
35  * - ns3::WifiModulationClass
36  * - ns3::WifiPpduField
37  * - ns3::WifiPpduType
38  * - ns3::WifiPhyRxfailureReason
39  */
40 
41 namespace ns3 {
42 
43 class WifiNetDevice;
44 class WifiMode;
45 class Time;
46 
47 /**
48  * These constants define the various convolutional coding rates
49  * used for the OFDM transmission modes in the IEEE 802.11
50  * standard. DSSS (for example) rates which do not have an explicit
51  * coding stage in their generation should have this parameter set to
52  * WIFI_CODE_RATE_UNDEFINED.
53  * \note This typedef and constants could be converted to an enum or scoped
54  * enum if pybindgen is upgraded to support Callback<WifiCodeRate>
55  */
56 typedef uint16_t WifiCodeRate;
57 const uint16_t WIFI_CODE_RATE_UNDEFINED = 0; //!< undefined coding rate
58 const uint16_t WIFI_CODE_RATE_1_2 = 1;       //!< 1/2 coding rate
59 const uint16_t WIFI_CODE_RATE_2_3 = 2;       //!< 2/3 coding rate
60 const uint16_t WIFI_CODE_RATE_3_4 = 3;       //!< 3/4 coding rate
61 const uint16_t WIFI_CODE_RATE_5_6 = 4;       //!< 5/6 coding rate
62 
63 /**
64  * \ingroup wifi
65  * The type of preamble to be used by an IEEE 802.11 transmission
66  */
67 enum WifiPreamble
68 {
69   WIFI_PREAMBLE_LONG,
70   WIFI_PREAMBLE_SHORT,
71   WIFI_PREAMBLE_HT_MF,
72   WIFI_PREAMBLE_VHT_SU,
73   WIFI_PREAMBLE_VHT_MU,
74   WIFI_PREAMBLE_HE_SU,
75   WIFI_PREAMBLE_HE_ER_SU,
76   WIFI_PREAMBLE_HE_MU,
77   WIFI_PREAMBLE_HE_TB
78 };
79 
80 /**
81  * \brief Stream insertion operator.
82  *
83  * \param os the stream
84  * \param preamble the preamble
85  * \returns a reference to the stream
86  */
87 inline std::ostream& operator<< (std::ostream &os, const WifiPreamble &preamble)
88 {
89   switch (preamble)
90     {
91       case WIFI_PREAMBLE_LONG:
92         return (os << "LONG");
93       case WIFI_PREAMBLE_SHORT:
94         return (os << "SHORT");
95       case WIFI_PREAMBLE_HT_MF:
96         return (os << "HT_MF");
97       case WIFI_PREAMBLE_VHT_SU:
98         return (os << "VHT_SU");
99       case WIFI_PREAMBLE_VHT_MU:
100         return (os << "VHT_MU");
101       case WIFI_PREAMBLE_HE_SU:
102         return (os << "HE_SU");
103       case WIFI_PREAMBLE_HE_ER_SU:
104         return (os << "HE_ER_SU");
105       case WIFI_PREAMBLE_HE_MU:
106         return (os << "HE_MU");
107       case WIFI_PREAMBLE_HE_TB:
108         return (os << "HE_TB");
109       default:
110         NS_FATAL_ERROR ("Invalid preamble");
111         return (os << "INVALID");
112     }
113 }
114 
115 /**
116  * \ingroup wifi
117  * This enumeration defines the modulation classes per
118  * (Table 10-6 "Modulation classes"; IEEE 802.11-2016, with
119  * updated in 802.11ax/D6.0 as Table 10-9).
120  */
121 enum WifiModulationClass
122 {
123   /** Modulation class unknown or unspecified. A WifiMode with this
124   WifiModulationClass has not been properly initialized. */
125   WIFI_MOD_CLASS_UNKNOWN = 0,
126   WIFI_MOD_CLASS_DSSS,     //!< DSSS (Clause 15)
127   WIFI_MOD_CLASS_HR_DSSS,  //!< HR/DSSS (Clause 16)
128   WIFI_MOD_CLASS_ERP_OFDM, //!< ERP-OFDM (18.4)
129   WIFI_MOD_CLASS_OFDM,     //!< OFDM (Clause 17)
130   WIFI_MOD_CLASS_HT,       //!< HT (Clause 19)
131   WIFI_MOD_CLASS_VHT,      //!< VHT (Clause 22)
132   WIFI_MOD_CLASS_HE        //!< HE (Clause 27)
133 };
134 
135 /**
136  * \brief Stream insertion operator.
137  *
138  * \param os the stream
139  * \param modulation the WifiModulationClass
140  * \returns a reference to the stream
141  */
142 inline std::ostream& operator<< (std::ostream &os, const WifiModulationClass &modulation)
143 {
144   switch (modulation)
145     {
146       case WIFI_MOD_CLASS_DSSS:
147         return (os << "DSSS");
148       case WIFI_MOD_CLASS_HR_DSSS:
149         return (os << "HR/DSSS");
150       case WIFI_MOD_CLASS_ERP_OFDM:
151         return (os << "ERP-OFDM");
152       case WIFI_MOD_CLASS_OFDM:
153         return (os << "OFDM");
154       case WIFI_MOD_CLASS_HT:
155         return (os << "HT");
156       case WIFI_MOD_CLASS_VHT:
157         return (os << "VHT");
158       case WIFI_MOD_CLASS_HE:
159         return (os << "HE");
160       default:
161         NS_FATAL_ERROR ("Unknown modulation");
162         return (os << "unknown");
163     }
164 }
165 
166 /**
167  * \ingroup wifi
168  * The type of PPDU field (grouped for convenience)
169  */
170 enum WifiPpduField
171 {
172   /**
173    * SYNC + SFD fields for DSSS or ERP,
174    * shortSYNC + shortSFD fields for HR/DSSS or ERP,
175    * HT-GF-STF + HT-GF-LTF1 fields for HT-GF,
176    * L-STF + L-LTF fields otherwise.
177    */
178   WIFI_PPDU_FIELD_PREAMBLE = 0,
179   /**
180    * PHY header field for DSSS or ERP,
181    * short PHY header field for HR/DSSS or ERP,
182    * field not present for HT-GF,
183    * L-SIG field or L-SIG + RL-SIG fields otherwise.
184    */
185   WIFI_PPDU_FIELD_NON_HT_HEADER,
186   WIFI_PPDU_FIELD_HT_SIG,   //!< HT-SIG field
187   WIFI_PPDU_FIELD_TRAINING, //!< STF + LTF fields (excluding those in preamble for HT-GF)
188   WIFI_PPDU_FIELD_SIG_A,    //!< SIG-A field
189   WIFI_PPDU_FIELD_SIG_B,    //!< SIG-B field
190   WIFI_PPDU_FIELD_DATA      //!< data field
191 };
192 
193 /**
194  * \brief Stream insertion operator.
195  *
196  * \param os the stream
197  * \param field the PPDU field
198  * \returns a reference to the stream
199  */
200 inline std::ostream& operator<< (std::ostream &os, const WifiPpduField &field)
201 {
202   switch (field)
203     {
204       case WIFI_PPDU_FIELD_PREAMBLE:
205         return (os << "preamble");
206       case WIFI_PPDU_FIELD_NON_HT_HEADER:
207         return (os << "non-HT header");
208       case WIFI_PPDU_FIELD_HT_SIG:
209         return (os << "HT-SIG");
210       case WIFI_PPDU_FIELD_TRAINING:
211         return (os << "training");
212       case WIFI_PPDU_FIELD_SIG_A:
213         return (os << "SIG-A");
214       case WIFI_PPDU_FIELD_SIG_B:
215         return (os << "SIG-B");
216       case WIFI_PPDU_FIELD_DATA:
217         return (os << "data");
218       default:
219         NS_FATAL_ERROR ("Unknown field");
220         return (os << "unknown");
221     }
222 }
223 
224 /**
225  * \ingroup wifi
226  * The type of PPDU (SU, DL MU, or UL MU)
227  */
228 enum WifiPpduType
229 {
230   WIFI_PPDU_TYPE_SU = 0,
231   WIFI_PPDU_TYPE_DL_MU,
232   WIFI_PPDU_TYPE_UL_MU
233 };
234 
235 /**
236  * \brief Stream insertion operator.
237  *
238  * \param os the stream
239  * \param type the PPDU type
240  * \returns a reference to the stream
241  */
242 inline std::ostream& operator<< (std::ostream &os, const WifiPpduType &type)
243 {
244   switch (type)
245     {
246       case WIFI_PPDU_TYPE_SU:
247         return (os << "SU");
248       case WIFI_PPDU_TYPE_DL_MU:
249         return (os << "DL MU");
250       case WIFI_PPDU_TYPE_UL_MU:
251         return (os << "UL MU");
252       default:
253         NS_FATAL_ERROR ("Unknown type");
254         return (os << "unknown");
255     }
256 }
257 
258 /**
259  * \ingroup wifi
260  * Enumeration of the possible reception failure reasons.
261  */
262 enum WifiPhyRxfailureReason
263 {
264   UNKNOWN = 0,
265   UNSUPPORTED_SETTINGS,
266   CHANNEL_SWITCHING,
267   RXING,
268   TXING,
269   SLEEPING,
270   BUSY_DECODING_PREAMBLE,
271   PREAMBLE_DETECT_FAILURE,
272   RECEPTION_ABORTED_BY_TX,
273   L_SIG_FAILURE,
274   HT_SIG_FAILURE,
275   SIG_A_FAILURE,
276   SIG_B_FAILURE,
277   PREAMBLE_DETECTION_PACKET_SWITCH,
278   FRAME_CAPTURE_PACKET_SWITCH,
279   OBSS_PD_CCA_RESET,
280   HE_TB_PPDU_TOO_LATE,
281   FILTERED
282 };
283 
284 /**
285  * \brief Stream insertion operator.
286  *
287  * \param os the stream
288  * \param reason the failure reason
289  * \returns a reference to the stream
290  */
291 inline std::ostream& operator<< (std::ostream &os, const WifiPhyRxfailureReason &reason)
292 {
293   switch (reason)
294     {
295       case UNSUPPORTED_SETTINGS:
296         return (os << "UNSUPPORTED_SETTINGS");
297       case CHANNEL_SWITCHING:
298         return (os << "CHANNEL_SWITCHING");
299       case RXING:
300         return (os << "RXING");
301       case TXING:
302         return (os << "TXING");
303       case SLEEPING:
304         return (os << "SLEEPING");
305       case BUSY_DECODING_PREAMBLE:
306         return (os << "BUSY_DECODING_PREAMBLE");
307       case PREAMBLE_DETECT_FAILURE:
308         return (os << "PREAMBLE_DETECT_FAILURE");
309       case RECEPTION_ABORTED_BY_TX:
310         return (os << "RECEPTION_ABORTED_BY_TX");
311       case L_SIG_FAILURE:
312         return (os << "L_SIG_FAILURE");
313       case HT_SIG_FAILURE:
314         return (os << "HT_SIG_FAILURE");
315       case SIG_A_FAILURE:
316         return (os << "SIG_A_FAILURE");
317       case SIG_B_FAILURE:
318         return (os << "SIG_B_FAILURE");
319       case PREAMBLE_DETECTION_PACKET_SWITCH:
320         return (os << "PREAMBLE_DETECTION_PACKET_SWITCH");
321       case FRAME_CAPTURE_PACKET_SWITCH:
322         return (os << "FRAME_CAPTURE_PACKET_SWITCH");
323       case OBSS_PD_CCA_RESET:
324         return (os << "OBSS_PD_CCA_RESET");
325       case HE_TB_PPDU_TOO_LATE:
326         return (os << "HE_TB_PPDU_TOO_LATE");
327       case FILTERED:
328         return (os << "FILTERED");
329       case UNKNOWN:
330       default:
331         NS_FATAL_ERROR ("Unknown reason");
332         return (os << "UNKNOWN");
333     }
334 }
335 
336 /**
337  * Convert the guard interval to nanoseconds based on the WifiMode.
338  *
339  * \param mode the WifiMode
340  * \param device pointer to the WifiNetDevice object
341  *
342  * \return the guard interval duration in nanoseconds
343  */
344 uint16_t ConvertGuardIntervalToNanoSeconds (WifiMode mode, const Ptr<WifiNetDevice> device);
345 
346 /**
347  * Convert the guard interval to nanoseconds based on the WifiMode.
348  *
349  * \param mode the WifiMode
350  * \param htShortGuardInterval whether HT/VHT short guard interval is enabled
351  * \param heGuardInterval the HE guard interval duration
352  *
353  * \return the guard interval duration in nanoseconds
354  */
355 uint16_t ConvertGuardIntervalToNanoSeconds (WifiMode mode, bool htShortGuardInterval, Time heGuardInterval);
356 
357 /**
358  * Return the preamble to be used for the transmission.
359  *
360  * \param modulation the modulation selected for the transmission
361  * \param useShortPreamble whether short preamble should be used
362  *
363  * \return the preamble to be used for the transmission
364  */
365 WifiPreamble GetPreambleForTransmission (WifiModulationClass modulation, bool useShortPreamble);
366 
367 /**
368  * Return the channel width that corresponds to the selected mode (instead of
369  * letting the PHY's default channel width). This is especially useful when using
370  * non-HT modes with HT/VHT/HE capable stations (with default width above 20 MHz).
371  *
372  * \param mode selected WifiMode
373  * \param maxSupportedChannelWidth maximum channel width supported by the PHY layer
374  * \return channel width adapted to the selected mode
375  */
376 uint16_t GetChannelWidthForTransmission (WifiMode mode, uint16_t maxSupportedChannelWidth);
377 
378 /**
379  * Return whether the modulation class of the selected mode for the
380  * control answer frame is allowed.
381  *
382  * \param modClassReq modulation class of the request frame
383  * \param modClassAnswer modulation class of the answer frame
384  *
385  * \return true if the modulation class of the selected mode for the
386  * control answer frame is allowed, false otherwise
387  */
388 bool IsAllowedControlAnswerModulationClass (WifiModulationClass modClassReq, WifiModulationClass modClassAnswer);
389 
390 /**
391  * Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for
392  * the PHY layers defining the aPPDUMaxTime characteristic (HT, VHT and HE).
393  * Return zero otherwise.
394  *
395  * \param preamble the preamble type
396  *
397  * \return the maximum PPDU duration, if defined, and zero otherwise
398  */
399 Time GetPpduMaxTime (WifiPreamble preamble);
400 
401 /**
402  * Return true if a preamble corresponds to a multi-user transmission.
403  *
404  * \param preamble the preamble
405  * \return true if the provided preamble corresponds to a multi-user transmission
406  */
407 bool IsMu (WifiPreamble preamble);
408 
409 /**
410  * Return true if a preamble corresponds to a downlink multi-user transmission.
411  *
412  * \param preamble the preamble
413  * \return true if the provided preamble corresponds to a downlink multi-user transmission
414  */
415 bool IsDlMu (WifiPreamble preamble);
416 
417 /**
418  * Return true if a preamble corresponds to a uplink multi-user transmission.
419  *
420  * \param preamble the preamble
421  * \return true if the provided preamble corresponds to a uplink multi-user transmission
422  */
423 bool IsUlMu (WifiPreamble preamble);
424 
425 } //namespace ns3
426 
427 #endif /* WIFI_PHY_COMMON_H */
428