1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018
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 HE_RU_H
22 #define HE_RU_H
23 
24 #include <map>
25 #include <vector>
26 #include <cstdint>
27 #include <ostream>
28 
29 namespace ns3 {
30 
31 
32 /**
33  * This class stores the subcarrier groups of all the available HE RUs.
34  */
35 class HeRu
36 {
37 public:
38   /**
39    * The different HE Resource Unit (RU) types.
40    */
41   enum RuType
42   {
43     RU_26_TONE = 0,
44     RU_52_TONE,
45     RU_106_TONE,
46     RU_242_TONE,
47     RU_484_TONE,
48     RU_996_TONE,
49     RU_2x996_TONE
50   };
51 
52   /// (lowest index, highest index) pair defining a subcarrier range
53   typedef std::pair<int16_t, int16_t> SubcarrierRange;
54 
55   /// a vector of subcarrier ranges defining a subcarrier group
56   typedef std::vector<SubcarrierRange> SubcarrierGroup;
57 
58 
59   /**
60    * RU Specification. Stores the information carried by the RU Allocation subfield
61    * of the User Info field of Trigger frames (see 9.3.1.22.1 of 802.11ax D8.0).
62    * Note that primary80MHz must be true if ruType is RU_2x996_TONE.
63    * Internally, this class also stores the RU PHY index (ranging from 1 to the number
64    * of RUs of the given type in a channel of the considered width), so that this class
65    * contains all the information needed to locate the RU in a 160 MHz channel.
66    */
67   class RuSpec
68   {
69   public:
70     /**
71      * Default constructor
72      */
73     RuSpec ();
74     /**
75      * Constructor
76      *
77      * \param ruType the RU type
78      * \param index the RU index (starting at 1)
79      * \param primary80MHz whether the RU is allocated in the primary 80MHz channel
80      */
81     RuSpec (RuType ruType, std::size_t index, bool primary80MHz);
82 
83     /**
84      * Get the RU type
85      *
86      * \return the RU type
87      */
88     RuType GetRuType (void) const;
89     /**
90      * Get the RU index
91      *
92      * \return the RU index
93      */
94     std::size_t GetIndex (void) const;
95     /**
96      * Get the primary 80 MHz flag
97      *
98      * \return true if the RU is in the primary 80 MHz channel and false otherwise
99      */
100     bool GetPrimary80MHz (void) const;
101     /**
102      * Set the RU PHY index
103      *
104      * \param bw the width of the channel of which the RU is part (in MHz)
105      * \param p20Index the index of the primary20 channel
106      */
107     void SetPhyIndex (uint16_t bw, uint8_t p20Index);
108     /**
109      * Return true if the RU PHY index has been set, false otherwise
110      *
111      * \return true if the RU PHY index has been set, false otherwise
112      */
113     bool IsPhyIndexSet (void) const;
114     /**
115      * Get the RU PHY index
116      *
117      * \return the RU PHY index
118      */
119     std::size_t GetPhyIndex (void) const;
120 
121   private:
122     RuType m_ruType;         //!< RU type
123     std::size_t m_index;     /**< RU index (starting at 1) as defined by Tables 27-7
124                                   to 27-9 of 802.11ax D8.0 */
125     bool m_primary80MHz;     //!< true if the RU is allocated in the primary 80MHz channel
126     std::size_t m_phyIndex;  /**< the RU PHY index, which is used to indicate whether an
127                                   RU is located in the lower half or the higher half of
128                                   a 160MHz channel. For channel widths less than 160MHz,
129                                   the RU PHY index equals the RU index */
130   };
131 
132 
133   /**
134    * Get the number of distinct RUs of the given type (number of tones)
135    * available in a HE PPDU of the given bandwidth.
136    *
137    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
138    * \param ruType the RU type (number of tones)
139    * \return the number of distinct RUs available
140    */
141   static std::size_t GetNRus (uint16_t bw, RuType ruType);
142 
143   /**
144    * Get the set of distinct RUs of the given type (number of tones)
145    * available in a HE PPDU of the given bandwidth.
146    *
147    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
148    * \param ruType the RU type (number of tones)
149    * \return the set of distinct RUs available
150    */
151   static std::vector<HeRu::RuSpec> GetRusOfType (uint16_t bw, HeRu::RuType ruType);
152 
153   /**
154    * Get the set of 26-tone RUs that can be additionally allocated if the given
155    * bandwidth is split in RUs of the given type.
156    *
157    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
158    * \param ruType the RU type (number of tones)
159    * \return the set of 26-tone RUs that can be additionally allocated
160    */
161   static std::vector<HeRu::RuSpec> GetCentral26TonesRus (uint16_t bw, HeRu::RuType ruType);
162 
163   /**
164    * Get the subcarrier group of the RU having the given PHY index among all the
165    * RUs of the given type (number of tones) available in a HE PPDU of the
166    * given bandwidth. A subcarrier group is defined as one or more pairs
167    * indicating the lowest frequency index and the highest frequency index.
168    * Note that for channel width of 160 MHz the returned range is relative to
169    * the 160 MHz channel (i.e. -1012 to 1012). The PHY index parameter is used to
170    * distinguish between lower and higher 80 MHz subchannels.
171    *
172    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
173    * \param ruType the RU type (number of tones)
174    * \param phyIndex the PHY index (starting at 1) of the RU
175    * \return the subcarrier range of the specified RU
176    */
177   static SubcarrierGroup GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t phyIndex);
178 
179   /**
180    * Check whether the given RU overlaps with the given set of RUs.
181    * Note that for channel width of 160 MHz the returned range is relative to
182    * the 160 MHz channel (i.e. -1012 to 1012).
183    *
184    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
185    * \param ru the given RU allocation
186    * \param v the given set of RUs
187    * \return true if the given RU overlaps with the given set of RUs.
188    */
189   static bool DoesOverlap (uint16_t bw, RuSpec ru, const std::vector<RuSpec> &v);
190 
191   /**
192    * Check whether the given RU overlaps with the given tone ranges.
193    * Note that for channel width of 160 MHz the returned range is relative to
194    * the 160 MHz channel (i.e. -1012 to 1012).
195    *
196    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
197    * \param ru the given RU allocation
198    * \param toneRanges the given set of tone ranges
199    * \return true if the given RU overlaps with the given set of tone ranges.
200    */
201   static bool DoesOverlap (uint16_t bw, RuSpec ru, const SubcarrierGroup &toneRanges);
202 
203   /**
204    * Find the RU allocation of the given RU type overlapping the given
205    * reference RU allocation.
206    * Note that an assert is generated if the RU allocation is not found.
207    *
208    * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160)
209    * \param referenceRu the reference RU allocation
210    * \param searchedRuType the searched RU type
211    * \return the searched RU allocation.
212    */
213   static RuSpec FindOverlappingRu (uint16_t bw, RuSpec referenceRu, RuType searchedRuType);
214 
215   /**
216    * Get the approximate bandwidth occupied by a RU.
217    *
218    * \param ruType the RU type
219    * \return the approximate bandwidth (in MHz) occupied by the RU
220    */
221   static uint16_t GetBandwidth (RuType ruType);
222 
223   /**
224    * Get the RU corresponding to the approximate bandwidth.
225    *
226    * \param bandwidth the approximate bandwidth (in MHz) occupied by the RU
227    * \return the RU type
228    */
229   static RuType GetRuType (uint16_t bandwidth);
230 
231   /**
232    * Given the channel bandwidth and the number of stations candidate for being
233    * assigned an RU, maximize the number of candidate stations that can be assigned
234    * an RU subject to the constraint that all the stations must be assigned an RU
235    * of the same size (in terms of number of tones).
236    *
237    * \param bandwidth the channel bandwidth in MHz
238    * \param nStations the number of candidate stations. On return, it is set to
239    *                  the number of stations that are assigned an RU
240    * \param[out] nCentral26TonesRus the number of additional 26-tone RUs that can be
241    *                                allocated if the returned RU size is greater than 26 tones
242    * \return the RU type
243    */
244   static RuType GetEqualSizedRusForStations (uint16_t bandwidth, std::size_t& nStations,
245                                              std::size_t& nCentral26TonesRus);
246 
247   /// (bandwidth, number of tones) pair
248   typedef std::pair<uint8_t, RuType> BwTonesPair;
249 
250   /// map (bandwidth, number of tones) pairs to the group of subcarrier ranges
251   typedef std::map<BwTonesPair, std::vector<SubcarrierGroup> > SubcarrierGroups;
252 
253   /// Subcarrier groups for all RUs (with indices being applicable to primary 80 MHz channel)
254   static const SubcarrierGroups  m_heRuSubcarrierGroups;
255 };
256 
257 /**
258  * \brief Stream insertion operator.
259  *
260  * \param os the stream
261  * \param ruType the RU type
262  * \returns a reference to the stream
263  */
264 std::ostream& operator<< (std::ostream& os, const HeRu::RuType &ruType);
265 
266 /**
267  * \brief Stream insertion operator.
268  *
269  * \param os the stream
270  * \param ru the RU
271  * \returns a reference to the stream
272  */
273 std::ostream& operator<< (std::ostream& os, const HeRu::RuSpec &ru);
274 
275 } //namespace ns3
276 
277 #endif /* HE_RU_H */
278