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
,
81 int argc
, char **argv
,
84 struct nlattr
*nl_rates
, *nl_band
;
86 bool have_legacy_24
= false, have_legacy_5
= false;
87 uint8_t legacy_24
[32], legacy_5
[32];
88 int n_legacy_24
= 0, n_legacy_5
= 0;
89 uint8_t *legacy
= NULL
;
91 bool have_ht_mcs_24
= false, have_ht_mcs_5
= false;
92 bool have_vht_mcs_24
= false, have_vht_mcs_5
= false;
93 uint8_t ht_mcs_24
[77], ht_mcs_5
[77];
94 int n_ht_mcs_24
= 0, n_ht_mcs_5
= 0;
95 struct nl80211_txrate_vht txrate_vht_24
= {};
96 struct nl80211_txrate_vht txrate_vht_5
= {};
99 char *vht_argv_5
[VHT_ARGC_MAX
] = {}; char *vht_argv_24
[VHT_ARGC_MAX
] = {};
100 char **vht_argv
= NULL
;
101 int vht_argc_5
= 0; int vht_argc_24
= 0;
102 int *vht_argc
= NULL
;
103 int sgi_24
= 0, sgi_5
= 0, lgi_24
= 0, lgi_5
= 0;
111 } parser_state
= S_NONE
;
113 for (i
= 0; i
< argc
; i
++) {
118 if (strcmp(argv
[i
], "legacy-2.4") == 0) {
121 parser_state
= S_LEGACY
;
123 n_legacy
= &n_legacy_24
;
124 have_legacy_24
= true;
125 } else if (strcmp(argv
[i
], "legacy-5") == 0) {
128 parser_state
= S_LEGACY
;
130 n_legacy
= &n_legacy_5
;
131 have_legacy_5
= true;
133 else if (strcmp(argv
[i
], "ht-mcs-2.4") == 0) {
138 n_mcs
= &n_ht_mcs_24
;
139 have_ht_mcs_24
= true;
140 } else if (strcmp(argv
[i
], "ht-mcs-5") == 0) {
146 have_ht_mcs_5
= true;
147 } else if (strcmp(argv
[i
], "vht-mcs-2.4") == 0) {
150 parser_state
= S_VHT
;
151 vht_argv
= vht_argv_24
;
152 vht_argc
= &vht_argc_24
;
153 have_vht_mcs_24
= true;
154 } else if (strcmp(argv
[i
], "vht-mcs-5") == 0) {
157 parser_state
= S_VHT
;
158 vht_argv
= vht_argv_5
;
159 vht_argc
= &vht_argc_5
;
160 have_vht_mcs_5
= true;
161 } else if (strcmp(argv
[i
], "sgi-2.4") == 0) {
164 } else if (strcmp(argv
[i
], "sgi-5") == 0) {
167 } else if (strcmp(argv
[i
], "lgi-2.4") == 0) {
170 } else if (strcmp(argv
[i
], "lgi-5") == 0) {
173 } else switch (parser_state
) {
175 tmpd
= strtod(argv
[i
], &end
);
178 if (tmpd
< 1 || tmpd
> 255 * 2)
180 legacy
[(*n_legacy
)++] = tmpd
* 2;
183 tmpl
= strtol(argv
[i
], &end
, 0);
186 if (tmpl
< 0 || tmpl
> 255)
188 mcs
[(*n_mcs
)++] = tmpl
;
191 if (*vht_argc
>= VHT_ARGC_MAX
)
193 vht_argv
[(*vht_argc
)++] = argv
[i
];
203 if(!setup_vht(&txrate_vht_24
, vht_argc_24
, vht_argv_24
))
207 if(!setup_vht(&txrate_vht_5
, vht_argc_5
, vht_argv_5
))
213 if (sgi_24
&& lgi_24
)
216 nl_rates
= nla_nest_start(msg
, NL80211_ATTR_TX_RATES
);
218 goto nla_put_failure
;
220 if (have_legacy_24
|| have_ht_mcs_24
|| have_vht_mcs_24
|| sgi_24
|| lgi_24
) {
221 nl_band
= nla_nest_start(msg
, NL80211_BAND_2GHZ
);
223 goto nla_put_failure
;
225 nla_put(msg
, NL80211_TXRATE_LEGACY
, n_legacy_24
, legacy_24
);
227 nla_put(msg
, NL80211_TXRATE_HT
, n_ht_mcs_24
, ht_mcs_24
);
229 nla_put(msg
, NL80211_TXRATE_VHT
, sizeof(txrate_vht_24
), &txrate_vht_24
);
231 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_SGI
);
233 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_LGI
);
234 nla_nest_end(msg
, nl_band
);
237 if (have_legacy_5
|| have_ht_mcs_5
|| have_vht_mcs_5
|| sgi_5
|| lgi_5
) {
238 nl_band
= nla_nest_start(msg
, NL80211_BAND_5GHZ
);
240 goto nla_put_failure
;
242 nla_put(msg
, NL80211_TXRATE_LEGACY
, n_legacy_5
, legacy_5
);
244 nla_put(msg
, NL80211_TXRATE_HT
, n_ht_mcs_5
, ht_mcs_5
);
246 nla_put(msg
, NL80211_TXRATE_VHT
, sizeof(txrate_vht_5
), &txrate_vht_5
);
248 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_SGI
);
250 nla_put_u8(msg
, NL80211_TXRATE_GI
, NL80211_TXRATE_FORCE_LGI
);
251 nla_nest_end(msg
, nl_band
);
254 nla_nest_end(msg
, nl_rates
);
261 #define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]"
262 #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]"
264 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]",
265 NL80211_CMD_SET_TX_BITRATE_MASK
, 0, CIB_NETDEV
, handle_bitrates
,
266 "Sets up the specified rate masks.\n"
267 "Not passing any arguments would clear the existing mask (if any).");