]> git.ipfire.org Git - thirdparty/iw.git/blame - bitrate.c
update nl80211.h
[thirdparty/iw.git] / bitrate.c
CommitLineData
942b5cd8
JB
1#include <errno.h>
2
3#include "nl80211.h"
4#include "iw.h"
5
6
118976b2
JD
7static int parse_vht_chunk(const char *arg, __u8 *nss, __u16 *mcs)
8{
9 int count, i;
10 unsigned int inss, mcs_start, mcs_end, tab[10];
11
12 *nss = 0; *mcs = 0;
13
14 if (strchr(arg, '-')) {
15 /* Format: NSS:MCS_START-MCS_END */
16 count = sscanf(arg, "%u:%u-%u", &inss, &mcs_start, &mcs_end);
17
18 if (count != 3)
19 return 0;
20
21 if (inss < 1 || inss > NL80211_VHT_NSS_MAX)
22 return 0;
23
24 if (mcs_start > mcs_end)
25 return 0;
26
27 if (mcs_start > 9 || mcs_end > 9)
28 return 0;
29
30 *nss = inss;
31 for (i = mcs_start; i <= mcs_end; i++)
32 *mcs |= 1 << i;
33
34 } else {
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]);
39
40 if (count < 2)
41 return 0;
42
43 if (inss < 1 || inss > NL80211_VHT_NSS_MAX)
44 return 0;
45
46 *nss = inss;
47 for (i = 0; i < count - 1; i++) {
48 if (tab[i] > 9)
49 return 0;
50 *mcs |= 1 << tab[i];
51 }
52 }
53
54 return 1;
55}
56
57static int setup_vht(struct nl80211_txrate_vht *txrate_vht,
58 int argc, char **argv)
59{
60 __u8 nss;
61 __u16 mcs;
62 int i;
63
64 memset(txrate_vht, 0, sizeof(*txrate_vht));
65
66 for (i = 0; i < argc; i++) {
67 if(!parse_vht_chunk(argv[i], &nss, &mcs))
68 return 0;
69
70 nss--;
71 txrate_vht->mcs[nss] |= mcs;
72 }
73
74 return 1;
75}
76
77#define VHT_ARGC_MAX 100
78
942b5cd8
JB
79static int handle_bitrates(struct nl80211_state *state,
80 struct nl_cb *cb,
81 struct nl_msg *msg,
05514f95
JB
82 int argc, char **argv,
83 enum id_input id)
942b5cd8
JB
84{
85 struct nlattr *nl_rates, *nl_band;
86 int i;
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;
91 int *n_legacy = NULL;
118976b2
JD
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 = {};
942b5cd8
JB
98 uint8_t *mcs = NULL;
99 int *n_mcs = NULL;
118976b2
JD
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
942b5cd8
JB
105 enum {
106 S_NONE,
107 S_LEGACY,
118976b2
JD
108 S_HT,
109 S_VHT,
942b5cd8
JB
110 } parser_state = S_NONE;
111
112 for (i = 0; i < argc; i++) {
113 char *end;
bd0f464b 114 double tmpd;
942b5cd8 115 long tmpl;
942b5cd8
JB
116
117 if (strcmp(argv[i], "legacy-2.4") == 0) {
118 if (have_legacy_24)
119 return 1;
120 parser_state = S_LEGACY;
121 legacy = legacy_24;
122 n_legacy = &n_legacy_24;
123 have_legacy_24 = true;
124 } else if (strcmp(argv[i], "legacy-5") == 0) {
125 if (have_legacy_5)
126 return 1;
127 parser_state = S_LEGACY;
128 legacy = legacy_5;
129 n_legacy = &n_legacy_5;
130 have_legacy_5 = true;
131 }
118976b2
JD
132 else if (strcmp(argv[i], "ht-mcs-2.4") == 0) {
133 if (have_ht_mcs_24)
134 return 1;
135 parser_state = S_HT;
136 mcs = ht_mcs_24;
137 n_mcs = &n_ht_mcs_24;
138 have_ht_mcs_24 = true;
139 } else if (strcmp(argv[i], "ht-mcs-5") == 0) {
140 if (have_ht_mcs_5)
141 return 1;
142 parser_state = S_HT;
143 mcs = ht_mcs_5;
144 n_mcs = &n_ht_mcs_5;
145 have_ht_mcs_5 = true;
146 } else if (strcmp(argv[i], "vht-mcs-2.4") == 0) {
147 if (have_vht_mcs_24)
942b5cd8 148 return 1;
118976b2
JD
149 parser_state = S_VHT;
150 vht_argv = vht_argv_24;
151 vht_argc = &vht_argc_24;
152 have_vht_mcs_24 = true;
153 } else if (strcmp(argv[i], "vht-mcs-5") == 0) {
154 if (have_vht_mcs_5)
942b5cd8 155 return 1;
118976b2
JD
156 parser_state = S_VHT;
157 vht_argv = vht_argv_5;
158 vht_argc = &vht_argc_5;
159 have_vht_mcs_5 = true;
942b5cd8 160 }
942b5cd8
JB
161 else switch (parser_state) {
162 case S_LEGACY:
bd0f464b 163 tmpd = strtod(argv[i], &end);
942b5cd8
JB
164 if (*end != '\0')
165 return 1;
bd0f464b 166 if (tmpd < 1 || tmpd > 255 * 2)
942b5cd8 167 return 1;
bd0f464b 168 legacy[(*n_legacy)++] = tmpd * 2;
942b5cd8 169 break;
118976b2 170 case S_HT:
942b5cd8
JB
171 tmpl = strtol(argv[i], &end, 0);
172 if (*end != '\0')
173 return 1;
174 if (tmpl < 0 || tmpl > 255)
175 return 1;
176 mcs[(*n_mcs)++] = tmpl;
177 break;
118976b2
JD
178 case S_VHT:
179 if (*vht_argc >= VHT_ARGC_MAX)
180 return 1;
181 vht_argv[(*vht_argc)++] = argv[i];
182 break;
942b5cd8
JB
183 default:
184 return 1;
185 }
186 }
187
118976b2
JD
188 if (have_vht_mcs_24)
189 if(!setup_vht(&txrate_vht_24, vht_argc_24, vht_argv_24))
190 return -EINVAL;
191
192 if (have_vht_mcs_5)
193 if(!setup_vht(&txrate_vht_5, vht_argc_5, vht_argv_5))
194 return -EINVAL;
195
942b5cd8
JB
196 nl_rates = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
197 if (!nl_rates)
198 goto nla_put_failure;
199
118976b2 200 if (have_legacy_24 || have_ht_mcs_24 || have_vht_mcs_24) {
942b5cd8
JB
201 nl_band = nla_nest_start(msg, NL80211_BAND_2GHZ);
202 if (!nl_band)
203 goto nla_put_failure;
204 if (have_legacy_24)
205 nla_put(msg, NL80211_TXRATE_LEGACY, n_legacy_24, legacy_24);
118976b2
JD
206 if (have_ht_mcs_24)
207 nla_put(msg, NL80211_TXRATE_HT, n_ht_mcs_24, ht_mcs_24);
208 if (have_vht_mcs_24)
209 nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht_24), &txrate_vht_24);
942b5cd8
JB
210 nla_nest_end(msg, nl_band);
211 }
212
118976b2 213 if (have_legacy_5 || have_ht_mcs_5 || have_vht_mcs_5) {
942b5cd8
JB
214 nl_band = nla_nest_start(msg, NL80211_BAND_5GHZ);
215 if (!nl_band)
216 goto nla_put_failure;
217 if (have_legacy_5)
218 nla_put(msg, NL80211_TXRATE_LEGACY, n_legacy_5, legacy_5);
118976b2
JD
219 if (have_ht_mcs_5)
220 nla_put(msg, NL80211_TXRATE_HT, n_ht_mcs_5, ht_mcs_5);
221 if (have_vht_mcs_5)
222 nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht_5), &txrate_vht_5);
942b5cd8
JB
223 nla_nest_end(msg, nl_band);
224 }
225
226 nla_nest_end(msg, nl_rates);
227
228 return 0;
229 nla_put_failure:
230 return -ENOBUFS;
231}
232
233#define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]"
118976b2 234#define DESCR DESCR_LEGACY " [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*]"
942b5cd8 235
118976b2 236COMMAND(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>*]",
135e65d6 237 NL80211_CMD_SET_TX_BITRATE_MASK, 0, CIB_NETDEV, handle_bitrates,
dce7b720
SM
238 "Sets up the specified rate masks.\n"
239 "Not passing any arguments would clear the existing mask (if any).");