|
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2013 |
|
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: Ghada Badawy <gbadawy@rim.com> |
|
19 */ |
|
20 |
|
21 #include "ht-capabilities.h" |
|
22 #include "ns3/assert.h" |
|
23 #include "ns3/log.h" |
|
24 |
|
25 |
|
26 NS_LOG_COMPONENT_DEFINE ("HtCapabilities"); |
|
27 |
|
28 namespace ns3 { |
|
29 |
|
30 |
|
31 HtCapabilities::HtCapabilities () |
|
32 : m_ldpc(0), |
|
33 m_supportedChannelWidth(0), |
|
34 m_smPowerSave(0), |
|
35 m_greenField(0), |
|
36 m_shortGuardInterval20(0), |
|
37 m_shortGuardInterval40(0), |
|
38 m_txStbc(0), |
|
39 m_rxStbc(0), |
|
40 m_htDelayedBlockAck(0), |
|
41 m_maxAmsduLength(0), |
|
42 m_dssMode40(0), |
|
43 m_reserved(0), |
|
44 m_fortyMhzIntolerant(0), |
|
45 m_lsigProtectionSupport(0), |
|
46 m_maxAmpduLength(0), |
|
47 m_minMpduStartSpace(0), |
|
48 m_ampduReserved(0), |
|
49 m_reservedMcsSet1(0), |
|
50 m_rxHighestSupportedDataRate(0), |
|
51 m_reservedMcsSet2(0), |
|
52 m_txMcsSetDefined(0), |
|
53 m_txRxMcsSetUnequal(0), |
|
54 m_txMaxNSpatialStreams(0), |
|
55 m_txUnequalModulation(0), |
|
56 m_reservedMcsSet3(7), |
|
57 m_htSupported(0) |
|
58 { |
|
59 for (uint32_t k=0; k < MAX_SUPPORTED_MCS ;k++) |
|
60 { |
|
61 m_rxMcsBitmask[k]=0; |
|
62 } |
|
63 } |
|
64 |
|
65 |
|
66 WifiInformationElementId |
|
67 HtCapabilities::ElementId () const |
|
68 { |
|
69 return IE_HT_CAPABILITIES; |
|
70 } |
|
71 |
|
72 void |
|
73 HtCapabilities::SetHtSupported(uint8_t htsupported) |
|
74 { |
|
75 m_htSupported = htsupported; |
|
76 } |
|
77 void |
|
78 HtCapabilities::SetLdpc (uint8_t ldpc) |
|
79 { |
|
80 m_ldpc=ldpc; |
|
81 } |
|
82 |
|
83 void |
|
84 HtCapabilities::SetSupportedChannelWidth (uint8_t supportedchannelwidth) |
|
85 { |
|
86 m_supportedChannelWidth=supportedchannelwidth; |
|
87 } |
|
88 |
|
89 void |
|
90 HtCapabilities::SetGreenfield (uint8_t greenfield) |
|
91 { |
|
92 m_greenField=greenfield; |
|
93 } |
|
94 |
|
95 void |
|
96 HtCapabilities::SetShortGuardInterval20 (uint8_t shortguardinterval) |
|
97 { |
|
98 m_shortGuardInterval20=shortguardinterval; |
|
99 } |
|
100 void |
|
101 HtCapabilities::SetRxMcsBitmask(uint8_t index) |
|
102 { |
|
103 m_rxMcsBitmask[index]=1; |
|
104 } |
|
105 |
|
106 uint8_t* |
|
107 HtCapabilities::GetRxMcsBitmask() |
|
108 { |
|
109 uint8_t* p; |
|
110 p= m_rxMcsBitmask; |
|
111 return p; |
|
112 } |
|
113 |
|
114 bool |
|
115 HtCapabilities::IsSupportedMcs (uint8_t mcs) |
|
116 { |
|
117 if (m_rxMcsBitmask[mcs] == 1) |
|
118 { |
|
119 return true; |
|
120 } |
|
121 return false; |
|
122 |
|
123 } |
|
124 uint8_t |
|
125 HtCapabilities::GetLdpc (void) const |
|
126 { |
|
127 return m_ldpc; |
|
128 } |
|
129 |
|
130 uint8_t |
|
131 HtCapabilities::GetSupportedChannelWidth (void) const |
|
132 { |
|
133 return m_supportedChannelWidth; |
|
134 } |
|
135 |
|
136 uint8_t |
|
137 HtCapabilities::GetGreenfield (void) const |
|
138 { |
|
139 return m_greenField; |
|
140 } |
|
141 uint8_t |
|
142 HtCapabilities::GetShortGuardInterval20(void) const |
|
143 { |
|
144 return m_shortGuardInterval20; |
|
145 } |
|
146 |
|
147 uint8_t |
|
148 HtCapabilities::GetInformationFieldSize () const |
|
149 { |
|
150 // we should not be here if ht is not supported |
|
151 NS_ASSERT (m_htSupported > 0); |
|
152 return 19; |
|
153 } |
|
154 Buffer::Iterator |
|
155 HtCapabilities::Serialize (Buffer::Iterator i) const |
|
156 { |
|
157 if (m_htSupported< 1) |
|
158 { |
|
159 return i; |
|
160 } |
|
161 return WifiInformationElement::Serialize (i); |
|
162 } |
|
163 uint16_t |
|
164 HtCapabilities::GetSerializedSize () const |
|
165 { |
|
166 if (m_htSupported < 1) |
|
167 { |
|
168 return 0; |
|
169 } |
|
170 return WifiInformationElement::GetSerializedSize (); |
|
171 } |
|
172 |
|
173 uint16_t |
|
174 HtCapabilities::GetHtCapabilitiesInfo (void) const |
|
175 { |
|
176 uint16_t val = 0; |
|
177 val |= m_ldpc; |
|
178 val |= (m_supportedChannelWidth << 1)& (0x1 << 1); |
|
179 val |= (m_smPowerSave << 2)& (0x3 << 2) ; |
|
180 val |= (m_greenField << 4)& (0x1 << 4) ; |
|
181 val |= (m_shortGuardInterval20 << 5)& (0x1 << 5); |
|
182 val |= (m_shortGuardInterval40 << 6)& (0x1 << 6); |
|
183 val |= (m_txStbc << 7)& (0x1 << 7); |
|
184 val |= (m_rxStbc << 8)& (0x3 << 8); |
|
185 val |= (m_htDelayedBlockAck << 10)& (0x1 << 10); |
|
186 val |= (m_maxAmsduLength << 11)& (0x1 << 11); |
|
187 val |= (m_dssMode40 << 12)& (0x1 << 12); |
|
188 val |= (m_reserved<< 13)& (0x1 << 13); |
|
189 val |= (m_fortyMhzIntolerant << 14)& (0x1 << 14); |
|
190 val |= (m_lsigProtectionSupport << 15)& (0x1 << 15); |
|
191 return val; |
|
192 } |
|
193 |
|
194 void |
|
195 HtCapabilities::SetHtCapabilitiesInfo(uint16_t ctrl) |
|
196 { |
|
197 m_ldpc = ctrl & 0x01; |
|
198 m_supportedChannelWidth = (ctrl >> 1) & 0x01; |
|
199 m_smPowerSave = (ctrl >> 2) & 0x03; |
|
200 m_greenField = (ctrl >> 4) & 0x01; |
|
201 m_shortGuardInterval20 = (ctrl >> 5) & 0x01; |
|
202 m_shortGuardInterval40 = (ctrl >> 6) & 0x01; |
|
203 m_txStbc = (ctrl >> 7) & 0x01; |
|
204 m_rxStbc = (ctrl >> 8) & 0x03; |
|
205 m_htDelayedBlockAck = (ctrl >> 10) & 0x01; |
|
206 m_maxAmsduLength = (ctrl >> 11) & 0x01; |
|
207 m_dssMode40= (ctrl >> 12) & 0x01; |
|
208 m_reserved= (ctrl >> 13) & 0x01; |
|
209 m_fortyMhzIntolerant= (ctrl >> 14) & 0x01; |
|
210 m_lsigProtectionSupport= (ctrl >> 15) & 0x01; |
|
211 } |
|
212 uint8_t |
|
213 HtCapabilities::GetAmpduParameters (void) const |
|
214 { |
|
215 uint8_t val = 0; |
|
216 val |= m_maxAmpduLength & 0x3; |
|
217 val |= ( m_minMpduStartSpace << 2)& (0x7 << 2); |
|
218 val |= (m_ampduReserved << 5)& (0x7 << 5) ; |
|
219 return val; |
|
220 } |
|
221 |
|
222 void |
|
223 HtCapabilities::SetAmpduParameters (uint8_t ctrl) |
|
224 { |
|
225 m_maxAmpduLength = ctrl & 0x03; |
|
226 m_minMpduStartSpace = (ctrl >> 2) & 0x07; |
|
227 m_ampduReserved =(ctrl >> 5) & 0x07; |
|
228 } |
|
229 |
|
230 void |
|
231 HtCapabilities::SetSupportedMcsSet (uint64_t ctrl2, uint64_t ctrl1) |
|
232 { |
|
233 for(uint64_t i=0 ; i < 77;i++) |
|
234 { |
|
235 if (i < 64) |
|
236 { |
|
237 m_rxMcsBitmask[i]=(ctrl1 >> i) & 0x01; |
|
238 } |
|
239 else |
|
240 { |
|
241 m_rxMcsBitmask[i]=( ctrl2 >> (i-64))& 0x01 ; |
|
242 } |
|
243 } |
|
244 m_reservedMcsSet1 = (ctrl2 >> 12) & 0x07; |
|
245 m_rxHighestSupportedDataRate = (ctrl2 >> 15) & 0x03ff; |
|
246 m_reservedMcsSet2 = (ctrl2 >> 25) & 0x3f; |
|
247 m_txMcsSetDefined = (ctrl2 >> 31) & 0x01; |
|
248 m_txRxMcsSetUnequal = (ctrl2 >> 32) & 0x01; |
|
249 m_txMaxNSpatialStreams = (ctrl2 >> 33) & 0x03; |
|
250 m_txUnequalModulation = (ctrl2 >> 35) & 0x01; |
|
251 m_reservedMcsSet3 = (ctrl2 >> 36) & 0x07ffffff; |
|
252 } |
|
253 uint64_t |
|
254 HtCapabilities::GetSupportedMcsSet1 (void) const |
|
255 { |
|
256 uint64_t val=0; |
|
257 for(uint64_t i=63 ; i >0 ;i--) |
|
258 { |
|
259 val = (val << 1) | (m_rxMcsBitmask[i] & 0x01); |
|
260 } |
|
261 val = (val << 1) | (m_rxMcsBitmask[0] & 0x01); |
|
262 return val; |
|
263 } |
|
264 uint64_t |
|
265 HtCapabilities::GetSupportedMcsSet2 (void) const |
|
266 { |
|
267 uint64_t val=0; |
|
268 val = val | (m_reservedMcsSet3 & 0x07ffffff); |
|
269 val = (val << 1) | (m_txUnequalModulation & 0x01); |
|
270 val = (val << 2) | (m_txMaxNSpatialStreams & 0x03); |
|
271 val = (val << 1) | (m_txRxMcsSetUnequal & 0x01); |
|
272 val = (val << 1) | (m_txMcsSetDefined & 0x01); |
|
273 val = (val << 6) | (m_reservedMcsSet2 & 0x3f); |
|
274 val = (val << 10) |(m_rxHighestSupportedDataRate & 0x3ff); |
|
275 val = (val << 3) |(m_reservedMcsSet1 & 0x07); |
|
276 |
|
277 for (uint64_t i=12; i>0;i--) |
|
278 { |
|
279 val = (val << 1)|( m_rxMcsBitmask[i+64] & 0x01); |
|
280 } |
|
281 return val; |
|
282 } |
|
283 |
|
284 void |
|
285 HtCapabilities::SerializeInformationField (Buffer::Iterator start) const |
|
286 { |
|
287 if (m_htSupported == 1) |
|
288 { |
|
289 // write the corresponding value for each bit |
|
290 start. WriteHtolsbU16 (GetHtCapabilitiesInfo()); |
|
291 start. WriteU8 (GetAmpduParameters()); |
|
292 start. WriteHtolsbU64 (GetSupportedMcsSet2()); |
|
293 start. WriteHtolsbU64 (GetSupportedMcsSet1()); |
|
294 } |
|
295 } |
|
296 |
|
297 uint8_t |
|
298 HtCapabilities::DeserializeInformationField (Buffer::Iterator start, |
|
299 uint8_t length) |
|
300 { |
|
301 Buffer::Iterator i = start; |
|
302 uint16_t htinfo = i.ReadLsbtohU16 (); |
|
303 uint8_t ampduparam = i.ReadU8 (); |
|
304 uint64_t mcsset1=i.ReadLsbtohU64 (); |
|
305 uint64_t mcsset2 = i.ReadLsbtohU64 (); |
|
306 SetHtCapabilitiesInfo(htinfo); |
|
307 SetAmpduParameters(ampduparam); |
|
308 SetSupportedMcsSet(mcsset1,mcsset2); |
|
309 return length; |
|
310 } |
|
311 |
|
312 ATTRIBUTE_HELPER_CPP (HtCapabilities); |
|
313 |
|
314 std::ostream & |
|
315 operator << (std::ostream &os, const HtCapabilities &htcapabilities) |
|
316 { |
|
317 os << htcapabilities.GetLdpc () << "|" << htcapabilities.GetSupportedChannelWidth () |
|
318 << "|" << htcapabilities.GetGreenfield () |
|
319 << "|" << htcapabilities.GetShortGuardInterval20 (); |
|
320 |
|
321 return os; |
|
322 } |
|
323 |
|
324 std::istream &operator >> (std::istream &is,HtCapabilities &htcapabilities) |
|
325 { |
|
326 bool c1, c2, c3,c4; |
|
327 is >> c1 >> c2 >> c3 >>c4; |
|
328 htcapabilities.SetLdpc (c1); |
|
329 htcapabilities.SetSupportedChannelWidth (c2); |
|
330 htcapabilities.SetGreenfield (c3); |
|
331 htcapabilities.SetShortGuardInterval20 (c4); |
|
332 |
|
333 return is; |
|
334 } |
|
335 |
|
336 } // namespace ns3 |