|
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 "supported-rates.h" |
|
22 #include "ns3/assert.h" |
|
23 #include "ns3/log.h" |
|
24 |
|
25 NS_LOG_COMPONENT_DEFINE ("SupportedRates"); |
|
26 |
|
27 namespace ns3 { |
|
28 |
|
29 SupportedRates::SupportedRates () |
|
30 : extended (this), m_nRates (0) |
|
31 {} |
|
32 |
|
33 void |
|
34 SupportedRates::AddSupportedRate (uint32_t bs) |
|
35 { |
|
36 NS_ASSERT (m_nRates < MAX_SUPPORTED_RATES); |
|
37 if (IsSupportedRate (bs)) |
|
38 { |
|
39 return; |
|
40 } |
|
41 m_rates[m_nRates] = bs/500000; |
|
42 m_nRates++; |
|
43 NS_LOG_DEBUG ("add rate="<<bs<<", n rates="<<(uint32_t)m_nRates); |
|
44 } |
|
45 void |
|
46 SupportedRates::SetBasicRate (uint32_t bs) |
|
47 { |
|
48 uint8_t rate = bs / 500000; |
|
49 for (uint8_t i = 0; i < m_nRates; i++) |
|
50 { |
|
51 if ((rate | 0x80) == m_rates[i]) |
|
52 { |
|
53 return; |
|
54 } |
|
55 if (rate == m_rates[i]) |
|
56 { |
|
57 NS_LOG_DEBUG ("set basic rate="<<bs<<", n rates="<<(uint32_t)m_nRates); |
|
58 m_rates[i] |= 0x80; |
|
59 return; |
|
60 } |
|
61 } |
|
62 AddSupportedRate (bs); |
|
63 SetBasicRate (bs); |
|
64 } |
|
65 bool |
|
66 SupportedRates::IsBasicRate (uint32_t bs) const |
|
67 { |
|
68 uint8_t rate = (bs / 500000) | 0x80; |
|
69 for (uint8_t i = 0; i < m_nRates; i++) |
|
70 { |
|
71 if (rate == m_rates[i]) |
|
72 { |
|
73 return true; |
|
74 } |
|
75 } |
|
76 return false; |
|
77 } |
|
78 bool |
|
79 SupportedRates::IsSupportedRate (uint32_t bs) const |
|
80 { |
|
81 uint8_t rate = bs / 500000; |
|
82 for (uint8_t i = 0; i < m_nRates; i++) |
|
83 { |
|
84 if (rate == m_rates[i] || |
|
85 (rate|0x80) == m_rates[i]) |
|
86 { |
|
87 return true; |
|
88 } |
|
89 } |
|
90 return false; |
|
91 } |
|
92 uint8_t |
|
93 SupportedRates::GetNRates (void) const |
|
94 { |
|
95 return m_nRates; |
|
96 } |
|
97 uint32_t |
|
98 SupportedRates::GetRate (uint8_t i) const |
|
99 { |
|
100 return (m_rates[i]&0x7f) * 500000; |
|
101 } |
|
102 |
|
103 WifiInformationElementId |
|
104 SupportedRates::ElementId () const |
|
105 { |
|
106 return IE_SUPPORTED_RATES; |
|
107 } |
|
108 uint8_t |
|
109 SupportedRates::GetInformationFieldSize () const |
|
110 { |
|
111 // The Supported Rates Information Element contains only the first 8 |
|
112 // supported rates - the remainder appear in the Extended Supported |
|
113 // Rates Information Element. |
|
114 return m_nRates > 8 ? 8 : m_nRates; |
|
115 } |
|
116 void |
|
117 SupportedRates::SerializeInformationField (Buffer::Iterator start) const |
|
118 { |
|
119 // The Supported Rates Information Element contains only the first 8 |
|
120 // supported rates - the remainder appear in the Extended Supported |
|
121 // Rates Information Element. |
|
122 start.Write (m_rates, m_nRates > 8 ? 8 : m_nRates); |
|
123 } |
|
124 uint8_t |
|
125 SupportedRates::DeserializeInformationField (Buffer::Iterator start, |
|
126 uint8_t length) |
|
127 { |
|
128 NS_ASSERT (length <= 8); |
|
129 m_nRates = length; |
|
130 start.Read (m_rates, m_nRates); |
|
131 return m_nRates; |
|
132 } |
|
133 |
|
134 ExtendedSupportedRatesIE::ExtendedSupportedRatesIE () |
|
135 {} |
|
136 |
|
137 ExtendedSupportedRatesIE::ExtendedSupportedRatesIE (SupportedRates *sr) |
|
138 { |
|
139 m_supportedRates = sr; |
|
140 } |
|
141 |
|
142 WifiInformationElementId |
|
143 ExtendedSupportedRatesIE::ElementId () const |
|
144 { |
|
145 return IE_EXTENDED_SUPPORTED_RATES; |
|
146 } |
|
147 |
|
148 uint8_t |
|
149 ExtendedSupportedRatesIE::GetInformationFieldSize () const |
|
150 { |
|
151 // If there are 8 or fewer rates then we don't need an Extended |
|
152 // Supported Rates IE and so could return zero here, but we're |
|
153 // overriding the GetSerializedSize() method, so if this function is |
|
154 // invoked in that case then it indicates a programming error. Hence |
|
155 // we have an assertion on that condition. |
|
156 NS_ASSERT(m_supportedRates->m_nRates > 8); |
|
157 |
|
158 // The number of rates we have beyond the initial 8 is the size of |
|
159 // the information field. |
|
160 return (m_supportedRates->m_nRates - 8); |
|
161 } |
|
162 |
|
163 void |
|
164 ExtendedSupportedRatesIE::SerializeInformationField (Buffer::Iterator start) const |
|
165 { |
|
166 // If there are 8 or fewer rates then there should be no Extended |
|
167 // Supported Rates Information Element at all so being here would |
|
168 // seemingly indicate a programming error. |
|
169 // |
|
170 // Our overridden version of the Serialize() method should ensure |
|
171 // that this routine is never invoked in that case (by ensuring that |
|
172 // WifiInformationElement::Serialize() is not invoked). |
|
173 NS_ASSERT(m_supportedRates->m_nRates > 8); |
|
174 start.Write (m_supportedRates->m_rates + 8, m_supportedRates->m_nRates - 8); |
|
175 } |
|
176 |
|
177 Buffer::Iterator |
|
178 ExtendedSupportedRatesIE::Serialize (Buffer::Iterator start) const |
|
179 { |
|
180 // If there are 8 or fewer rates then we don't need an Extended |
|
181 // Supported Rates IE, so we don't serialise anything. |
|
182 if (m_supportedRates->m_nRates <= 8) |
|
183 { |
|
184 return start; |
|
185 } |
|
186 |
|
187 // If there are more than 8 rates then we serialise as per normal. |
|
188 return WifiInformationElement::Serialize (start); |
|
189 } |
|
190 |
|
191 uint16_t |
|
192 ExtendedSupportedRatesIE::GetSerializedSize () const |
|
193 { |
|
194 // If there are 8 or fewer rates then we don't need an Extended |
|
195 // Supported Rates IE, so it's serialised length will be zero. |
|
196 if (m_supportedRates->m_nRates <= 8) |
|
197 { |
|
198 return 0; |
|
199 } |
|
200 |
|
201 // Otherwise, the size of it will be the number of supported rates |
|
202 // beyond 8, plus 2 for the Element ID and Length. |
|
203 return WifiInformationElement::GetSerializedSize (); |
|
204 } |
|
205 |
|
206 uint8_t |
|
207 ExtendedSupportedRatesIE::DeserializeInformationField (Buffer::Iterator start, |
|
208 uint8_t length) |
|
209 { |
|
210 NS_ASSERT (length > 0); |
|
211 NS_ASSERT (m_supportedRates->m_nRates + length <= MAX_SUPPORTED_RATES); |
|
212 start.Read (m_supportedRates->m_rates + m_supportedRates->m_nRates, length); |
|
213 m_supportedRates->m_nRates += length; |
|
214 return length; |
|
215 } |
|
216 |
|
217 std::ostream &operator << (std::ostream &os, const SupportedRates &rates) |
|
218 { |
|
219 os << "["; |
|
220 for (uint8_t i = 0; i < rates.GetNRates (); i++) |
|
221 { |
|
222 uint32_t rate = rates.GetRate (i); |
|
223 if (rates.IsBasicRate (rate)) |
|
224 { |
|
225 os << "*"; |
|
226 } |
|
227 os << rate / 1000000 << "mbs"; |
|
228 if (i < rates.GetNRates () - 1) |
|
229 { |
|
230 os << " "; |
|
231 } |
|
232 } |
|
233 os << "]"; |
|
234 return os; |
|
235 } |
|
236 |
|
237 } // namespace ns3 |