]>
Commit | Line | Data |
---|---|---|
942b5cd8 JB |
1 | #include <errno.h> |
2 | ||
3 | #include "nl80211.h" | |
4 | #include "iw.h" | |
5 | ||
6 | ||
3071b521 | 7 | static int parse_rate_chunk(const char *arg, __u8 *nss, __u16 *mcs, unsigned int mode) |
118976b2 | 8 | { |
0ee571d5 | 9 | unsigned int count, i; |
3071b521 MH |
10 | unsigned int inss, mcs_start, mcs_end, tab[12]; |
11 | unsigned int max_mcs = 0, max_nss = 0; | |
118976b2 JD |
12 | |
13 | *nss = 0; *mcs = 0; | |
14 | ||
3071b521 MH |
15 | if (mode == NL80211_TXRATE_HE) { |
16 | max_mcs = 11; | |
17 | max_nss = NL80211_HE_NSS_MAX; | |
18 | } else { | |
19 | max_mcs = 9; | |
20 | max_nss = NL80211_VHT_NSS_MAX; | |
21 | } | |
22 | ||
118976b2 JD |
23 | if (strchr(arg, '-')) { |
24 | /* Format: NSS:MCS_START-MCS_END */ | |
25 | count = sscanf(arg, "%u:%u-%u", &inss, &mcs_start, &mcs_end); | |
26 | ||
27 | if (count != 3) | |
28 | return 0; | |
29 | ||
3071b521 | 30 | if (inss < 1 || inss > max_nss) |
118976b2 JD |
31 | return 0; |
32 | ||
33 | if (mcs_start > mcs_end) | |
34 | return 0; | |
35 | ||
3071b521 | 36 | if (mcs_start > max_mcs || mcs_end > max_mcs) |
118976b2 JD |
37 | return 0; |
38 | ||
39 | *nss = inss; | |
40 | for (i = mcs_start; i <= mcs_end; i++) | |
41 | *mcs |= 1 << i; | |
42 | ||
43 | } else { | |
44 | /* Format: NSS:MCSx,MCSy,... */ | |
3071b521 MH |
45 | if (mode == NL80211_TXRATE_HE) { |
46 | count = sscanf(arg, "%u:%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", | |
47 | &inss, &tab[0], &tab[1], &tab[2], &tab[3], | |
48 | &tab[4], &tab[5], &tab[6], &tab[7], &tab[8], | |
49 | &tab[9], &tab[10], &tab[11]); | |
50 | } else { | |
51 | count = sscanf(arg, "%u:%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", &inss, | |
52 | &tab[0], &tab[1], &tab[2], &tab[3], &tab[4], | |
53 | &tab[5], &tab[6], &tab[7], &tab[8], &tab[9]); | |
54 | } | |
118976b2 JD |
55 | |
56 | if (count < 2) | |
57 | return 0; | |
58 | ||
3071b521 | 59 | if (inss < 1 || inss > max_nss) |
118976b2 JD |
60 | return 0; |
61 | ||
62 | *nss = inss; | |
63 | for (i = 0; i < count - 1; i++) { | |
3071b521 | 64 | if (tab[i] > max_mcs) |
118976b2 JD |
65 | return 0; |
66 | *mcs |= 1 << tab[i]; | |
67 | } | |
68 | } | |
69 | ||
70 | return 1; | |
71 | } | |
72 | ||
3071b521 MH |
73 | static int parse_vht_chunk(const char *arg, __u8 *nss, __u16 *mcs) |
74 | { | |
75 | return parse_rate_chunk(arg, nss, mcs, NL80211_TXRATE_VHT); | |
76 | } | |
77 | ||
78 | static int parse_he_chunk(const char *arg, __u8 *nss, __u16 *mcs) | |
79 | { | |
80 | return parse_rate_chunk(arg, nss, mcs, NL80211_TXRATE_HE); | |
81 | } | |
82 | ||
118976b2 JD |
83 | static int setup_vht(struct nl80211_txrate_vht *txrate_vht, |
84 | int argc, char **argv) | |
85 | { | |
86 | __u8 nss; | |
87 | __u16 mcs; | |
88 | int i; | |
89 | ||
90 | memset(txrate_vht, 0, sizeof(*txrate_vht)); | |
91 | ||
92 | for (i = 0; i < argc; i++) { | |
88f9e988 | 93 | if (!parse_vht_chunk(argv[i], &nss, &mcs)) |
118976b2 JD |
94 | return 0; |
95 | ||
96 | nss--; | |
97 | txrate_vht->mcs[nss] |= mcs; | |
98 | } | |
99 | ||
100 | return 1; | |
101 | } | |
102 | ||
3071b521 MH |
103 | static int setup_he(struct nl80211_txrate_he *txrate_he, |
104 | int argc, char **argv) | |
105 | { | |
106 | __u8 nss; | |
107 | __u16 mcs; | |
108 | int i; | |
109 | ||
110 | memset(txrate_he, 0, sizeof(*txrate_he)); | |
111 | ||
112 | for (i = 0; i < argc; i++) { | |
113 | if (!parse_he_chunk(argv[i], &nss, &mcs)) | |
114 | return 0; | |
115 | ||
116 | nss--; | |
117 | txrate_he->mcs[nss] |= mcs; | |
118 | } | |
119 | ||
120 | return 1; | |
121 | } | |
122 | ||
123 | #define HE_GI_STR_MAX 16 | |
124 | #define HE_GI_08_STR "0.8" | |
125 | #define HE_GI_16_STR "1.6" | |
126 | #define HE_GI_32_STR "3.2" | |
127 | int parse_he_gi(char *he_gi) | |
128 | { | |
129 | if (he_gi == NULL) | |
130 | return 0; | |
131 | ||
132 | if (!strncmp(he_gi, HE_GI_08_STR, sizeof(HE_GI_08_STR))) | |
133 | return NL80211_RATE_INFO_HE_GI_0_8; | |
134 | if (!strncmp(he_gi, HE_GI_16_STR, sizeof(HE_GI_16_STR))) | |
135 | return NL80211_RATE_INFO_HE_GI_1_6; | |
136 | if (!strncmp(he_gi, HE_GI_32_STR, sizeof(HE_GI_32_STR))) | |
137 | return NL80211_RATE_INFO_HE_GI_3_2; | |
138 | ||
139 | return -1; | |
140 | } | |
141 | ||
118976b2 JD |
142 | #define VHT_ARGC_MAX 100 |
143 | ||
4d2749a6 TC |
144 | int set_bitrates(struct nl_msg *msg, |
145 | int argc, char **argv, | |
146 | enum nl80211_attrs attr) | |
942b5cd8 JB |
147 | { |
148 | struct nlattr *nl_rates, *nl_band; | |
4d2749a6 | 149 | int i, ret = 0; |
942b5cd8 JB |
150 | bool have_legacy_24 = false, have_legacy_5 = false; |
151 | uint8_t legacy_24[32], legacy_5[32]; | |
152 | int n_legacy_24 = 0, n_legacy_5 = 0; | |
153 | uint8_t *legacy = NULL; | |
154 | int *n_legacy = NULL; | |
118976b2 JD |
155 | bool have_ht_mcs_24 = false, have_ht_mcs_5 = false; |
156 | bool have_vht_mcs_24 = false, have_vht_mcs_5 = false; | |
3071b521 | 157 | bool have_he_mcs_24 = false, have_he_mcs_5 = false; |
562404c1 | 158 | bool have_he_mcs_6 = false; |
118976b2 JD |
159 | uint8_t ht_mcs_24[77], ht_mcs_5[77]; |
160 | int n_ht_mcs_24 = 0, n_ht_mcs_5 = 0; | |
161 | struct nl80211_txrate_vht txrate_vht_24 = {}; | |
162 | struct nl80211_txrate_vht txrate_vht_5 = {}; | |
3071b521 MH |
163 | struct nl80211_txrate_he txrate_he_24 = {}; |
164 | struct nl80211_txrate_he txrate_he_5 = {}; | |
562404c1 | 165 | struct nl80211_txrate_he txrate_he_6 = {}; |
942b5cd8 JB |
166 | uint8_t *mcs = NULL; |
167 | int *n_mcs = NULL; | |
118976b2 | 168 | char *vht_argv_5[VHT_ARGC_MAX] = {}; char *vht_argv_24[VHT_ARGC_MAX] = {}; |
3071b521 | 169 | char *he_argv_5[VHT_ARGC_MAX] = {}; char *he_argv_24[VHT_ARGC_MAX] = {}; |
562404c1 | 170 | char *he_argv_6[VHT_ARGC_MAX] = {}; |
3071b521 | 171 | char **vht_argv = NULL, **he_argv = NULL; |
118976b2 | 172 | int vht_argc_5 = 0; int vht_argc_24 = 0; |
3071b521 | 173 | int he_argc_5 = 0; int he_argc_24 = 0; |
562404c1 | 174 | int he_argc_6 = 0; |
3071b521 | 175 | int *vht_argc = NULL, *he_argc = NULL; |
eaa16697 | 176 | int sgi_24 = 0, sgi_5 = 0, lgi_24 = 0, lgi_5 = 0; |
3071b521 | 177 | int has_he_gi_24 = 0, has_he_gi_5 = 0, has_he_ltf_24 = 0, has_he_ltf_5 = 0; |
562404c1 | 178 | int has_he_gi_6 = 0, has_he_ltf_6 = 0; |
3071b521 MH |
179 | int he_gi = 0, he_ltf = 0; |
180 | char *he_gi_argv = NULL; | |
118976b2 | 181 | |
942b5cd8 JB |
182 | enum { |
183 | S_NONE, | |
184 | S_LEGACY, | |
118976b2 JD |
185 | S_HT, |
186 | S_VHT, | |
3071b521 | 187 | S_HE, |
eaa16697 | 188 | S_GI, |
3071b521 MH |
189 | S_HE_GI, |
190 | S_HE_LTF, | |
942b5cd8 JB |
191 | } parser_state = S_NONE; |
192 | ||
193 | for (i = 0; i < argc; i++) { | |
194 | char *end; | |
bd0f464b | 195 | double tmpd; |
942b5cd8 | 196 | long tmpl; |
942b5cd8 JB |
197 | |
198 | if (strcmp(argv[i], "legacy-2.4") == 0) { | |
199 | if (have_legacy_24) | |
200 | return 1; | |
201 | parser_state = S_LEGACY; | |
202 | legacy = legacy_24; | |
203 | n_legacy = &n_legacy_24; | |
204 | have_legacy_24 = true; | |
205 | } else if (strcmp(argv[i], "legacy-5") == 0) { | |
206 | if (have_legacy_5) | |
207 | return 1; | |
208 | parser_state = S_LEGACY; | |
209 | legacy = legacy_5; | |
210 | n_legacy = &n_legacy_5; | |
211 | have_legacy_5 = true; | |
212 | } | |
118976b2 JD |
213 | else if (strcmp(argv[i], "ht-mcs-2.4") == 0) { |
214 | if (have_ht_mcs_24) | |
215 | return 1; | |
216 | parser_state = S_HT; | |
217 | mcs = ht_mcs_24; | |
218 | n_mcs = &n_ht_mcs_24; | |
219 | have_ht_mcs_24 = true; | |
220 | } else if (strcmp(argv[i], "ht-mcs-5") == 0) { | |
221 | if (have_ht_mcs_5) | |
222 | return 1; | |
223 | parser_state = S_HT; | |
224 | mcs = ht_mcs_5; | |
225 | n_mcs = &n_ht_mcs_5; | |
226 | have_ht_mcs_5 = true; | |
227 | } else if (strcmp(argv[i], "vht-mcs-2.4") == 0) { | |
228 | if (have_vht_mcs_24) | |
942b5cd8 | 229 | return 1; |
118976b2 JD |
230 | parser_state = S_VHT; |
231 | vht_argv = vht_argv_24; | |
232 | vht_argc = &vht_argc_24; | |
233 | have_vht_mcs_24 = true; | |
234 | } else if (strcmp(argv[i], "vht-mcs-5") == 0) { | |
235 | if (have_vht_mcs_5) | |
942b5cd8 | 236 | return 1; |
118976b2 JD |
237 | parser_state = S_VHT; |
238 | vht_argv = vht_argv_5; | |
239 | vht_argc = &vht_argc_5; | |
240 | have_vht_mcs_5 = true; | |
3071b521 MH |
241 | } else if (strcmp(argv[i], "he-mcs-2.4") == 0) { |
242 | if (have_he_mcs_24) | |
243 | return 1; | |
244 | parser_state = S_HE; | |
245 | he_argv = he_argv_24; | |
246 | he_argc = &he_argc_24; | |
247 | have_he_mcs_24 = true; | |
248 | } else if (strcmp(argv[i], "he-mcs-5") == 0) { | |
249 | if (have_he_mcs_5) | |
250 | return 1; | |
251 | parser_state = S_HE; | |
252 | he_argv = he_argv_5; | |
253 | he_argc = &he_argc_5; | |
254 | have_he_mcs_5 = true; | |
562404c1 RM |
255 | } else if (strcmp(argv[i], "he-mcs-6") == 0) { |
256 | if (have_he_mcs_6) | |
257 | return 1; | |
258 | parser_state = S_HE; | |
259 | he_argv = he_argv_6; | |
260 | he_argc = &he_argc_6; | |
261 | have_he_mcs_6 = true; | |
eaa16697 JD |
262 | } else if (strcmp(argv[i], "sgi-2.4") == 0) { |
263 | sgi_24 = 1; | |
264 | parser_state = S_GI; | |
265 | } else if (strcmp(argv[i], "sgi-5") == 0) { | |
266 | sgi_5 = 1; | |
267 | parser_state = S_GI; | |
268 | } else if (strcmp(argv[i], "lgi-2.4") == 0) { | |
269 | lgi_24 = 1; | |
270 | parser_state = S_GI; | |
271 | } else if (strcmp(argv[i], "lgi-5") == 0) { | |
272 | lgi_5 = 1; | |
273 | parser_state = S_GI; | |
3071b521 MH |
274 | } else if (strcmp(argv[i], "he-gi-2.4") == 0) { |
275 | has_he_gi_24 = 1; | |
276 | parser_state = S_HE_GI; | |
277 | } else if (strcmp(argv[i], "he-gi-5") == 0) { | |
278 | has_he_gi_5 = 1; | |
279 | parser_state = S_HE_GI; | |
562404c1 RM |
280 | } else if (strcmp(argv[i], "he-gi-6") == 0) { |
281 | has_he_gi_6 = 1; | |
282 | parser_state = S_HE_GI; | |
3071b521 MH |
283 | } else if (strcmp(argv[i], "he-ltf-2.4") == 0) { |
284 | has_he_ltf_24 = 1; | |
285 | parser_state = S_HE_LTF; | |
286 | } else if (strcmp(argv[i], "he-ltf-5") == 0) { | |
287 | has_he_ltf_5 = 1; | |
288 | parser_state = S_HE_LTF; | |
562404c1 RM |
289 | } else if (strcmp(argv[i], "he-ltf-6") == 0) { |
290 | has_he_ltf_6 = 1; | |
291 | parser_state = S_HE_LTF; | |
eaa16697 | 292 | } else switch (parser_state) { |
942b5cd8 | 293 | case S_LEGACY: |
bd0f464b | 294 | tmpd = strtod(argv[i], &end); |
942b5cd8 JB |
295 | if (*end != '\0') |
296 | return 1; | |
bd0f464b | 297 | if (tmpd < 1 || tmpd > 255 * 2) |
942b5cd8 | 298 | return 1; |
bd0f464b | 299 | legacy[(*n_legacy)++] = tmpd * 2; |
942b5cd8 | 300 | break; |
118976b2 | 301 | case S_HT: |
942b5cd8 JB |
302 | tmpl = strtol(argv[i], &end, 0); |
303 | if (*end != '\0') | |
304 | return 1; | |
305 | if (tmpl < 0 || tmpl > 255) | |
306 | return 1; | |
307 | mcs[(*n_mcs)++] = tmpl; | |
308 | break; | |
118976b2 JD |
309 | case S_VHT: |
310 | if (*vht_argc >= VHT_ARGC_MAX) | |
311 | return 1; | |
312 | vht_argv[(*vht_argc)++] = argv[i]; | |
313 | break; | |
3071b521 MH |
314 | case S_HE: |
315 | if (*he_argc >= VHT_ARGC_MAX) | |
316 | return 1; | |
317 | he_argv[(*he_argc)++] = argv[i]; | |
318 | break; | |
eaa16697 JD |
319 | case S_GI: |
320 | break; | |
3071b521 MH |
321 | case S_HE_GI: |
322 | he_gi_argv = argv[i]; | |
323 | break; | |
324 | case S_HE_LTF: | |
325 | he_ltf = strtol(argv[i], &end, 0); | |
326 | if (*end != '\0') | |
327 | return 1; | |
328 | if (he_ltf < 0 || he_ltf > 4) | |
329 | return 1; | |
330 | he_ltf = he_ltf >> 1; | |
331 | break; | |
942b5cd8 | 332 | default: |
4d2749a6 TC |
333 | if (attr != NL80211_ATTR_TX_RATES) |
334 | goto next; | |
942b5cd8 JB |
335 | return 1; |
336 | } | |
337 | } | |
338 | ||
4d2749a6 TC |
339 | next: |
340 | if (attr != NL80211_ATTR_TX_RATES) | |
341 | ret = i; | |
342 | ||
118976b2 | 343 | if (have_vht_mcs_24) |
88f9e988 | 344 | if (!setup_vht(&txrate_vht_24, vht_argc_24, vht_argv_24)) |
118976b2 JD |
345 | return -EINVAL; |
346 | ||
347 | if (have_vht_mcs_5) | |
88f9e988 | 348 | if (!setup_vht(&txrate_vht_5, vht_argc_5, vht_argv_5)) |
118976b2 JD |
349 | return -EINVAL; |
350 | ||
3071b521 MH |
351 | if (have_he_mcs_24) |
352 | if (!setup_he(&txrate_he_24, he_argc_24, he_argv_24)) | |
353 | return -EINVAL; | |
354 | ||
355 | if (have_he_mcs_5) | |
356 | if (!setup_he(&txrate_he_5, he_argc_5, he_argv_5)) | |
357 | return -EINVAL; | |
358 | ||
562404c1 RM |
359 | if (have_he_mcs_6) |
360 | if (!setup_he(&txrate_he_6, he_argc_6, he_argv_6)) | |
361 | return -EINVAL; | |
362 | ||
eaa16697 JD |
363 | if (sgi_5 && lgi_5) |
364 | return 1; | |
365 | ||
366 | if (sgi_24 && lgi_24) | |
367 | return 1; | |
368 | ||
3071b521 MH |
369 | if (he_gi_argv) { |
370 | he_gi = parse_he_gi(he_gi_argv); | |
371 | if (he_gi < 0) | |
372 | return 1; | |
373 | } | |
374 | ||
4d2749a6 | 375 | nl_rates = nla_nest_start(msg, attr); |
942b5cd8 JB |
376 | if (!nl_rates) |
377 | goto nla_put_failure; | |
378 | ||
3071b521 MH |
379 | if (have_legacy_24 || have_ht_mcs_24 || have_vht_mcs_24 || have_he_mcs_24 || |
380 | sgi_24 || lgi_24 || has_he_gi_24 || has_he_ltf_24) { | |
942b5cd8 JB |
381 | nl_band = nla_nest_start(msg, NL80211_BAND_2GHZ); |
382 | if (!nl_band) | |
383 | goto nla_put_failure; | |
384 | if (have_legacy_24) | |
385 | nla_put(msg, NL80211_TXRATE_LEGACY, n_legacy_24, legacy_24); | |
118976b2 JD |
386 | if (have_ht_mcs_24) |
387 | nla_put(msg, NL80211_TXRATE_HT, n_ht_mcs_24, ht_mcs_24); | |
388 | if (have_vht_mcs_24) | |
389 | nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht_24), &txrate_vht_24); | |
3071b521 MH |
390 | if (have_he_mcs_24) |
391 | nla_put(msg, NL80211_TXRATE_HE, sizeof(txrate_he_24), | |
392 | &txrate_he_24); | |
eaa16697 JD |
393 | if (sgi_24) |
394 | nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_SGI); | |
395 | if (lgi_24) | |
396 | nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_LGI); | |
3071b521 MH |
397 | if (has_he_gi_24) |
398 | nla_put_u8(msg, NL80211_TXRATE_HE_GI, he_gi); | |
399 | if (has_he_ltf_24) | |
400 | nla_put_u8(msg, NL80211_TXRATE_HE_LTF, he_ltf); | |
942b5cd8 JB |
401 | nla_nest_end(msg, nl_band); |
402 | } | |
403 | ||
3071b521 MH |
404 | if (have_legacy_5 || have_ht_mcs_5 || have_vht_mcs_5 || have_he_mcs_5 || |
405 | sgi_5 || lgi_5 || has_he_gi_5 || has_he_ltf_5) { | |
942b5cd8 JB |
406 | nl_band = nla_nest_start(msg, NL80211_BAND_5GHZ); |
407 | if (!nl_band) | |
408 | goto nla_put_failure; | |
409 | if (have_legacy_5) | |
410 | nla_put(msg, NL80211_TXRATE_LEGACY, n_legacy_5, legacy_5); | |
118976b2 JD |
411 | if (have_ht_mcs_5) |
412 | nla_put(msg, NL80211_TXRATE_HT, n_ht_mcs_5, ht_mcs_5); | |
413 | if (have_vht_mcs_5) | |
414 | nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht_5), &txrate_vht_5); | |
3071b521 MH |
415 | if (have_he_mcs_5) |
416 | nla_put(msg, NL80211_TXRATE_HE, sizeof(txrate_he_5), | |
417 | &txrate_he_5); | |
eaa16697 JD |
418 | if (sgi_5) |
419 | nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_SGI); | |
420 | if (lgi_5) | |
421 | nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_LGI); | |
3071b521 MH |
422 | if (has_he_gi_5) |
423 | nla_put_u8(msg, NL80211_TXRATE_HE_GI, he_gi); | |
424 | if (has_he_ltf_5) | |
425 | nla_put_u8(msg, NL80211_TXRATE_HE_LTF, he_ltf); | |
942b5cd8 JB |
426 | nla_nest_end(msg, nl_band); |
427 | } | |
428 | ||
562404c1 RM |
429 | if (have_he_mcs_6 || has_he_gi_6 || has_he_ltf_6) { |
430 | nl_band = nla_nest_start(msg, NL80211_BAND_6GHZ); | |
431 | if (!nl_band) | |
432 | goto nla_put_failure; | |
433 | if (have_he_mcs_6) | |
434 | nla_put(msg, NL80211_TXRATE_HE, sizeof(txrate_he_6), | |
435 | &txrate_he_6); | |
436 | if (has_he_gi_6) | |
437 | nla_put_u8(msg, NL80211_TXRATE_HE_GI, he_gi); | |
438 | if (has_he_ltf_6) | |
439 | nla_put_u8(msg, NL80211_TXRATE_HE_LTF, he_ltf); | |
440 | nla_nest_end(msg, nl_band); | |
441 | } | |
442 | ||
942b5cd8 JB |
443 | nla_nest_end(msg, nl_rates); |
444 | ||
4d2749a6 | 445 | return ret; |
942b5cd8 JB |
446 | nla_put_failure: |
447 | return -ENOBUFS; | |
448 | } | |
449 | ||
4d2749a6 TC |
450 | static int handle_bitrates(struct nl80211_state *state, |
451 | struct nl_msg *msg, | |
452 | int argc, char **argv, | |
453 | enum id_input id) | |
454 | { | |
455 | return set_bitrates(msg, argc, argv, NL80211_ATTR_TX_RATES); | |
456 | } | |
457 | ||
942b5cd8 | 458 | #define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]" |
562404c1 | 459 | #define DESCR DESCR_LEGACY " [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> [he-mcs-<2.4|5|6> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]" |
942b5cd8 | 460 | |
562404c1 | 461 | COMMAND(set, bitrates, "[legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> [he-mcs-<2.4|5|6> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5] [he-gi-<2.4|5|6> <0.8|1.6|3.2>] [he-ltf-<2.4|5|6> <1|2|4>]", |
135e65d6 | 462 | NL80211_CMD_SET_TX_BITRATE_MASK, 0, CIB_NETDEV, handle_bitrates, |
dce7b720 SM |
463 | "Sets up the specified rate masks.\n" |
464 | "Not passing any arguments would clear the existing mask (if any)."); |