7 static int parse_vht_chunk(const char *arg
, __u8
*nss
, __u16
*mcs
)
10 unsigned int inss
, mcs_start
, mcs_end
, tab
[10];
14 if (strchr(arg
, '-')) {
15 /* Format: NSS:MCS_START-MCS_END */
16 count
= sscanf(arg
, "%u:%u-%u", &inss
, &mcs_start
, &mcs_end
);
21 if (inss
< 1 || inss
> NL80211_VHT_NSS_MAX
)
24 if (mcs_start
> mcs_end
)
27 if (mcs_start
> 9 || mcs_end
> 9)
31 for (i
= mcs_start
; i
<= mcs_end
; i
++)
35 /* Format: NSS:MCSx,MCSy,... */
36 count
= sscanf(arg
, "%u:%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", &inss
,
37 &tab
[0], &tab
[1], &tab
[2], &tab
[3], &tab
[4], &tab
[5],
38 &tab
[6], &tab
[7], &tab
[8], &tab
[9]);
43 if (inss
< 1 || inss
> NL80211_VHT_NSS_MAX
)
47 for (i
= 0; i
< count
- 1; i
++) {
57 static int setup_vht(struct nl80211_txrate_vht
*txrate_vht
,
58 int argc
, char **argv
)
64 memset(txrate_vht
, 0, sizeof(*txrate_vht
));
66 for (i
= 0; i
< argc
; i
++) {
67 if(!parse_vht_chunk(argv
[i
], &nss
, &mcs
))
71 txrate_vht
->mcs
[nss
] |= mcs
;
77 #define VHT_ARGC_MAX 100
79 static int handle_bitrates(struct nl80211_state
*state
,
82 int argc
, char **argv
,
85 struct nlattr
*nl_rates
, *nl_band
;
87 bool have_legacy_24
= false, have_legacy_5
= false;
88 uint8_t legacy_24
[32], legacy_5
[32];
89 int n_legacy_24
= 0, n_legacy_5
= 0;
90 uint8_t *legacy
= NULL
;
92 bool have_ht_mcs_24
= false, have_ht_mcs_5
= false;
93 bool have_vht_mcs_24
= false, have_vht_mcs_5
= false;
94 uint8_t ht_mcs_24
[77], ht_mcs_5
[77];
95 int n_ht_mcs_24
= 0, n_ht_mcs_5
= 0;
96 struct nl80211_txrate_vht txrate_vht_24
= {};
97 struct nl80211_txrate_vht txrate_vht_5
= {};
100 char *vht_argv_5
[VHT_ARGC_MAX
] = {}; char *vht_argv_24
[VHT_ARGC_MAX
] = {};
101 char **vht_argv
= NULL
;
102 int vht_argc_5
= 0; int vht_argc_24
= 0;
103 int *vht_argc
= NULL
;
104 int sgi_24
= 0, sgi_5
= 0, lgi_24
= 0, lgi_5
= 0;
112 } parser_state
= S_NONE
;
114 for (i
= 0; i
< argc
; i
++) {
119 if (strcmp(argv
[i
], "legacy-2.4") == 0) {
122 parser_state
= S_LEGACY
;
124 n_legacy
= &n_legacy_24
;
125 have_legacy_24
= true;
126 } else if (strcmp(argv
[i
], "legacy-5") == 0) {
129 parser_state
= S_LEGACY
;
131 n_legacy
= &n_legacy_5
;
132 have_legacy_5
= true;
134 else if (strcmp(argv
[i
], "ht-mcs-2.4") == 0) {
139 n_mcs
= &n_ht_mcs_24
;
140 have_ht_mcs_24
= true;
141 } else if (strcmp(argv
[i
], "ht-mcs-5") == 0) {
147 have_ht_mcs_5
= true;
148 } else if (strcmp(argv
[i
], "vht-mcs-2.4") == 0) {
151 parser_state
= S_VHT
;
152 vht_argv
= vht_argv_24
;
153 vht_argc
= &vht_argc_24
;
154 have_vht_mcs_24
= true;
155 } else if (strcmp(argv
[i
], "vht-mcs-5") == 0) {
158 parser_state
= S_VHT
;
159 vht_argv
= vht_argv_5
;
160 vht_argc
= &vht_argc_5
;
161 have_vht_mcs_5
= true;
162 } else if (strcmp(argv
[i
], "sgi-2.4") == 0) {
165 } else if (strcmp(argv
[i
], "sgi-5") == 0) {
168 } else if (strcmp(argv
[i
], "lgi-2.4") == 0) {
171 } else if (strcmp(argv
[i
], "lgi-5") == 0) {
174 } else switch (parser_state
) {
176 tmpd
= strtod(argv
[i
], &end
);
179 if (tmpd
< 1 || tmpd
> 255 * 2)
181 legacy
[(*n_legacy
)++] = tmpd
* 2;
184 tmpl
= strtol(argv
[i
], &end
, 0);
187 if (tmpl
< 0 || tmpl
> 255)
189 mcs
[(*n_mcs
)++] = tmpl
;
192 if (*vht_argc
>= VHT_ARGC_MAX
)
194 vht_argv
[(*vht_argc
)++] = argv
[i
];
204 if(!setup_vht(&txrate_vht_24
, vht_argc_24
, vht_argv_24
))
208 if(!setup_vht(&txrate_vht_5
, vht_argc_5
, vht_argv_5
))
214 if (sgi_24
&& lgi_24
)
217 nl_rates
= nla_nest_start(msg
, NL80211_ATTR_TX_RATES
);
219 goto nla_put_failure
;
221 if (have_legacy_24
|| have_ht_mcs_24
|| have_vht_mcs_24
|| sgi_24
|| lgi_24
) {
222 nl_band
= nla_nest_start(msg
, NL80211_BAND_2GHZ
);
224 goto nla_put_failure
;
226 nla_put(msg
, NL80211_TXRATE_LEGACY
, n_legacy_24
, legacy_24
);
228 nla_put(msg
, NL80211_TXRATE_HT
, n_ht_mcs_24
, ht_mcs_24
);
230 nla_put(msg
, NL80211_TXRATE_VHT
, sizeof(txrate_vht_24
), &txrate_vht_24
);
232 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_SGI
);
234 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_LGI
);
235 nla_nest_end(msg
, nl_band
);
238 if (have_legacy_5
|| have_ht_mcs_5
|| have_vht_mcs_5
|| sgi_5
|| lgi_5
) {
239 nl_band
= nla_nest_start(msg
, NL80211_BAND_5GHZ
);
241 goto nla_put_failure
;
243 nla_put(msg
, NL80211_TXRATE_LEGACY
, n_legacy_5
, legacy_5
);
245 nla_put(msg
, NL80211_TXRATE_HT
, n_ht_mcs_5
, ht_mcs_5
);
247 nla_put(msg
, NL80211_TXRATE_VHT
, sizeof(txrate_vht_5
), &txrate_vht_5
);
249 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_SGI
);
251 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_LGI
);
252 nla_nest_end(msg
, nl_band
);
255 nla_nest_end(msg
, nl_rates
);
262 #define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]"
263 #define DESCR DESCR_LEGACY " [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]"
265 COMMAND(set
, bitrates
, "[legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]",
266 NL80211_CMD_SET_TX_BITRATE_MASK
, 0, CIB_NETDEV
, handle_bitrates
,
267 "Sets up the specified rate masks.\n"
268 "Not passing any arguments would clear the existing mask (if any).");