1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "supported-rates.h"
23 
24 namespace ns3 {
25 
26 NS_LOG_COMPONENT_DEFINE ("SupportedRates");
27 
28 #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
29 #define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
30 #define BSS_MEMBERSHIP_SELECTOR_HE_PHY 125
31 
SupportedRates()32 SupportedRates::SupportedRates ()
33   : extended (this),
34     m_nRates (0)
35 {
36   NS_LOG_FUNCTION (this);
37 }
38 
SupportedRates(const SupportedRates & rates)39 SupportedRates::SupportedRates (const SupportedRates &rates)
40 {
41   NS_LOG_FUNCTION (this);
42   m_nRates = rates.m_nRates;
43   memcpy (m_rates, rates.m_rates, MAX_SUPPORTED_RATES);
44   //reset the back pointer to this object
45   extended.SetSupportedRates (this);
46 }
47 
48 SupportedRates&
operator =(const SupportedRates & rates)49 SupportedRates::operator= (const SupportedRates& rates)
50 {
51   this->m_nRates = rates.m_nRates;
52   memcpy (this->m_rates, rates.m_rates, MAX_SUPPORTED_RATES);
53   //reset the back pointer to this object
54   this->extended.SetSupportedRates (this);
55   return (*this);
56 }
57 
58 void
AddSupportedRate(uint64_t bs)59 SupportedRates::AddSupportedRate (uint64_t bs)
60 {
61   NS_LOG_FUNCTION (this << bs);
62   NS_ASSERT_MSG (IsBssMembershipSelectorRate (bs) == false, "Invalid rate");
63   NS_ASSERT (m_nRates < MAX_SUPPORTED_RATES);
64   if (IsSupportedRate (bs))
65     {
66       return;
67     }
68   m_rates[m_nRates] = static_cast<uint8_t> (bs / 500000);
69   m_nRates++;
70   NS_LOG_DEBUG ("add rate=" << bs << ", n rates=" << +m_nRates);
71 }
72 
73 void
SetBasicRate(uint64_t bs)74 SupportedRates::SetBasicRate (uint64_t bs)
75 {
76   NS_LOG_FUNCTION (this << bs);
77   NS_ASSERT_MSG (IsBssMembershipSelectorRate (bs) == false, "Invalid rate");
78   uint8_t rate = static_cast<uint8_t> (bs / 500000);
79   for (uint8_t i = 0; i < m_nRates; i++)
80     {
81       if ((rate | 0x80) == m_rates[i])
82         {
83           return;
84         }
85       if (rate == m_rates[i])
86         {
87           NS_LOG_DEBUG ("set basic rate=" << bs << ", n rates=" << +m_nRates);
88           m_rates[i] |= 0x80;
89           return;
90         }
91     }
92   AddSupportedRate (bs);
93   SetBasicRate (bs);
94 }
95 
96 void
AddBssMembershipSelectorRate(uint64_t bs)97 SupportedRates::AddBssMembershipSelectorRate (uint64_t bs)
98 {
99   NS_LOG_FUNCTION (this << bs);
100   NS_ASSERT_MSG (bs == BSS_MEMBERSHIP_SELECTOR_HT_PHY ||
101  	         bs == BSS_MEMBERSHIP_SELECTOR_VHT_PHY ||
102  	         bs == BSS_MEMBERSHIP_SELECTOR_HE_PHY,
103                  "Value " << bs << " not a BSS Membership Selector");
104   uint8_t rate = static_cast<uint8_t> (bs / 500000);
105   for (uint8_t i = 0; i < m_nRates; i++)
106     {
107       if (rate == m_rates[i])
108         {
109           return;
110         }
111     }
112   m_rates[m_nRates] = rate;
113   NS_LOG_DEBUG ("add BSS membership selector rate " << bs << " as rate " << +rate);
114   m_nRates++;
115 }
116 
117 bool
IsBasicRate(uint64_t bs) const118 SupportedRates::IsBasicRate (uint64_t bs) const
119 {
120   NS_LOG_FUNCTION (this << bs);
121   uint8_t rate = static_cast<uint8_t> (bs / 500000) | 0x80;
122   for (uint8_t i = 0; i < m_nRates; i++)
123     {
124       if (rate == m_rates[i])
125         {
126           return true;
127         }
128     }
129   return false;
130 }
131 
132 bool
IsSupportedRate(uint64_t bs) const133 SupportedRates::IsSupportedRate (uint64_t bs) const
134 {
135   NS_LOG_FUNCTION (this << bs);
136   uint8_t rate = static_cast<uint8_t> (bs / 500000);
137   for (uint8_t i = 0; i < m_nRates; i++)
138     {
139       if (rate == m_rates[i]
140           || (rate | 0x80) == m_rates[i])
141         {
142           return true;
143         }
144     }
145   return false;
146 }
147 
148 bool
IsBssMembershipSelectorRate(uint64_t bs) const149 SupportedRates::IsBssMembershipSelectorRate (uint64_t bs) const
150 {
151   NS_LOG_FUNCTION (this << bs);
152   if ((bs & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY
153       || (bs & 0x7f) == BSS_MEMBERSHIP_SELECTOR_VHT_PHY
154       || (bs & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
155     {
156       return true;
157     }
158   return false;
159 }
160 
161 uint8_t
GetNRates(void) const162 SupportedRates::GetNRates (void) const
163 {
164   return m_nRates;
165 }
166 
167 uint32_t
GetRate(uint8_t i) const168 SupportedRates::GetRate (uint8_t i) const
169 {
170   return (m_rates[i] & 0x7f) * 500000;
171 }
172 
173 WifiInformationElementId
ElementId() const174 SupportedRates::ElementId () const
175 {
176   return IE_SUPPORTED_RATES;
177 }
178 
179 uint8_t
GetInformationFieldSize() const180 SupportedRates::GetInformationFieldSize () const
181 {
182   //The Supported Rates Information Element contains only the first 8
183   //supported rates - the remainder appear in the Extended Supported
184   //Rates Information Element.
185   return m_nRates > 8 ? 8 : m_nRates;
186 }
187 
188 void
SerializeInformationField(Buffer::Iterator start) const189 SupportedRates::SerializeInformationField (Buffer::Iterator start) const
190 {
191   //The Supported Rates Information Element contains only the first 8
192   //supported rates - the remainder appear in the Extended Supported
193   //Rates Information Element.
194   start.Write (m_rates, m_nRates > 8 ? 8 : m_nRates);
195 }
196 
197 uint8_t
DeserializeInformationField(Buffer::Iterator start,uint8_t length)198 SupportedRates::DeserializeInformationField (Buffer::Iterator start,
199                                              uint8_t length)
200 {
201   NS_ASSERT (length <= 8);
202   m_nRates = length;
203   start.Read (m_rates, m_nRates);
204   return m_nRates;
205 }
206 
ExtendedSupportedRatesIE()207 ExtendedSupportedRatesIE::ExtendedSupportedRatesIE ()
208 {
209 }
210 
ExtendedSupportedRatesIE(SupportedRates * sr)211 ExtendedSupportedRatesIE::ExtendedSupportedRatesIE (SupportedRates *sr)
212 {
213   m_supportedRates = sr;
214 }
215 
216 WifiInformationElementId
ElementId() const217 ExtendedSupportedRatesIE::ElementId () const
218 {
219   return IE_EXTENDED_SUPPORTED_RATES;
220 }
221 
222 void
SetSupportedRates(SupportedRates * sr)223 ExtendedSupportedRatesIE::SetSupportedRates (SupportedRates *sr)
224 {
225   m_supportedRates = sr;
226 }
227 
228 uint8_t
GetInformationFieldSize() const229 ExtendedSupportedRatesIE::GetInformationFieldSize () const
230 {
231   //If there are 8 or fewer rates then we don't need an Extended
232   //Supported Rates IE and so could return zero here, but we're
233   //overriding the GetSerializedSize() method, so if this function is
234   //invoked in that case then it indicates a programming error. Hence
235   //we have an assertion on that condition.
236   NS_ASSERT (m_supportedRates->m_nRates > 8);
237 
238   //The number of rates we have beyond the initial 8 is the size of
239   //the information field.
240   return (m_supportedRates->m_nRates - 8);
241 }
242 
243 void
SerializeInformationField(Buffer::Iterator start) const244 ExtendedSupportedRatesIE::SerializeInformationField (Buffer::Iterator start) const
245 {
246   //If there are 8 or fewer rates then there should be no Extended
247   //Supported Rates Information Element at all so being here would
248   //seemingly indicate a programming error.
249   //
250   //Our overridden version of the Serialize() method should ensure
251   //that this routine is never invoked in that case (by ensuring that
252   //WifiInformationElement::Serialize() is not invoked).
253   NS_ASSERT (m_supportedRates->m_nRates > 8);
254   start.Write (m_supportedRates->m_rates + 8, m_supportedRates->m_nRates - 8);
255 }
256 
257 Buffer::Iterator
Serialize(Buffer::Iterator start) const258 ExtendedSupportedRatesIE::Serialize (Buffer::Iterator start) const
259 {
260   //If there are 8 or fewer rates then we don't need an Extended
261   //Supported Rates IE, so we don't serialise anything.
262   if (m_supportedRates->m_nRates <= 8)
263     {
264       return start;
265     }
266 
267   //If there are more than 8 rates then we serialise as per normal.
268   return WifiInformationElement::Serialize (start);
269 }
270 
271 uint16_t
GetSerializedSize() const272 ExtendedSupportedRatesIE::GetSerializedSize () const
273 {
274   //If there are 8 or fewer rates then we don't need an Extended
275   //Supported Rates IE, so it's serialised length will be zero.
276   if (m_supportedRates->m_nRates <= 8)
277     {
278       return 0;
279     }
280 
281   //Otherwise, the size of it will be the number of supported rates
282   //beyond 8, plus 2 for the Element ID and Length.
283   return WifiInformationElement::GetSerializedSize ();
284 }
285 
286 uint8_t
DeserializeInformationField(Buffer::Iterator start,uint8_t length)287 ExtendedSupportedRatesIE::DeserializeInformationField (Buffer::Iterator start,
288                                                        uint8_t length)
289 {
290   NS_ASSERT (length > 0);
291   NS_ASSERT (m_supportedRates->m_nRates + length <= SupportedRates::MAX_SUPPORTED_RATES);
292   start.Read (m_supportedRates->m_rates + m_supportedRates->m_nRates, length);
293   m_supportedRates->m_nRates += length;
294   return length;
295 }
296 
operator <<(std::ostream & os,const SupportedRates & rates)297 std::ostream &operator << (std::ostream &os, const SupportedRates &rates)
298 {
299   os << "[";
300   for (uint8_t i = 0; i < rates.GetNRates (); i++)
301     {
302       uint32_t rate = rates.GetRate (i);
303       if (rates.IsBasicRate (rate))
304         {
305           os << "*";
306         }
307       os << rate / 1000000 << "mbs";
308       if (i < rates.GetNRates () - 1)
309         {
310           os << " ";
311         }
312     }
313   os << "]";
314   return os;
315 }
316 
317 } //namespace ns3
318