e63c3dd2c2d0c805a4d37ef4ca21fb7f66ed2550
[feed/routing.git] / batctl / patches / 0001-batctl-Make-vlan-setting-explicit.patch
1 From: Sven Eckelmann <sven@narfation.org>
2 Date: Thu, 13 Jun 2019 21:12:14 +0200
3 Subject: batctl: Make vlan setting explicit
4
5 The requirement to have a VLAN master device on top of the batadv mesh
6 interface is artificially limiting the capabilities of batctl. Not all
7 master devices in linux which register a VLAN are from type "vlan" and are
8 only registering a single VLAN.
9
10 For example VLAN aware bridges can create multiple VLANs. These require
11 that the VLAN is identified using the VID and not the vlan device.
12
13 Signed-off-by: Sven Eckelmann <sven@narfation.org>
14
15 Forwarded: https://patchwork.open-mesh.org/patch/17947/
16
17 diff --git a/ap_isolation.c b/ap_isolation.c
18 index 71dcd00eac845d488c4969b17e1339f181c6c913..7c34649225dcc9cc557cc5bb4cbfa2343f8c0763 100644
19 --- a/ap_isolation.c
20 +++ b/ap_isolation.c
21 @@ -81,3 +81,8 @@ COMMAND_NAMED(SUBCOMMAND, ap_isolation, "ap", handle_sys_setting,
22 COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
23 &batctl_settings_ap_isolation,
24 "[0|1] \tdisplay or modify ap_isolation setting");
25 +
26 +COMMAND_NAMED(SUBCOMMAND_VID, ap_isolation, "ap", handle_sys_setting,
27 + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
28 + &batctl_settings_ap_isolation,
29 + "[0|1] \tdisplay or modify ap_isolation setting for vlan device or id");
30 diff --git a/main.c b/main.c
31 index 278683c6080e3ff4a9f3225931d0c5eb44f89595..6ca13ac0ec4c82ee969be04737a339fd702b52bd 100644
32 --- a/main.c
33 +++ b/main.c
34 @@ -28,48 +28,75 @@ extern const struct command *__stop___command[];
35
36 static void print_usage(void)
37 {
38 - enum command_type type[] = {
39 - SUBCOMMAND,
40 - DEBUGTABLE,
41 + struct {
42 + const char *label;
43 + uint32_t types;
44 + } type[] = {
45 + {
46 + .label = "commands:\n",
47 + .types = BIT(SUBCOMMAND) |
48 + BIT(SUBCOMMAND_VID),
49 + },
50 + {
51 + .label = "debug tables: \tdisplay the corresponding debug table\n",
52 + .types = BIT(DEBUGTABLE),
53 + },
54 + };
55 + const char *default_prefixes[] = {
56 + "",
57 + NULL,
58 + };
59 + const char *vlan_prefixes[] = {
60 + "vlan <vdev> ",
61 + "vid <vid> ",
62 + NULL,
63 };
64 const struct command **p;
65 - char buf[32];
66 + const char **prefixes;
67 + const char **prefix;
68 + char buf[64];
69 size_t i;
70
71 fprintf(stderr, "Usage: batctl [options] command|debug table [parameters]\n");
72 fprintf(stderr, "options:\n");
73 - fprintf(stderr, " \t-m mesh interface or VLAN created on top of a mesh interface (default 'bat0')\n");
74 + fprintf(stderr, " \t-m mesh interface (default 'bat0')\n");
75 fprintf(stderr, " \t-h print this help (or 'batctl <command|debug table> -h' for the parameter help)\n");
76 fprintf(stderr, " \t-v print version\n");
77
78 for (i = 0; i < sizeof(type) / sizeof(*type); i++) {
79 fprintf(stderr, "\n");
80
81 - switch (type[i]) {
82 - case SUBCOMMAND:
83 - fprintf(stderr, "commands:\n");
84 - break;
85 - case DEBUGTABLE:
86 - fprintf(stderr, "debug tables: \tdisplay the corresponding debug table\n");
87 - break;
88 - }
89 + fprintf(stderr, "%s", type[i].label);
90
91 for (p = __start___command; p < __stop___command; p++) {
92 const struct command *cmd = *p;
93
94 - if (cmd->type != type[i])
95 + if (!(BIT(cmd->type) & type[i].types))
96 continue;
97
98 if (!cmd->usage)
99 continue;
100
101 - if (strcmp(cmd->name, cmd->abbr) == 0)
102 - snprintf(buf, sizeof(buf), "%s", cmd->name);
103 - else
104 - snprintf(buf, sizeof(buf), "%s|%s", cmd->name,
105 - cmd->abbr);
106 + switch (cmd->type) {
107 + case SUBCOMMAND_VID:
108 + prefixes = vlan_prefixes;
109 + break;
110 + default:
111 + prefixes = default_prefixes;
112 + break;
113 + }
114
115 - fprintf(stderr, " \t%-27s%s\n", buf, cmd->usage);
116 + for (prefix = &prefixes[0]; *prefix; prefix++) {
117 + if (strcmp(cmd->name, cmd->abbr) == 0)
118 + snprintf(buf, sizeof(buf), "%s%s",
119 + *prefix, cmd->name);
120 + else
121 + snprintf(buf, sizeof(buf), "%s%s|%s",
122 + *prefix, cmd->name, cmd->abbr);
123 +
124 + fprintf(stderr, " \t%-35s%s\n", buf,
125 + cmd->usage);
126 + }
127 }
128 }
129 }
130 @@ -93,13 +120,19 @@ static void version(void)
131 exit(EXIT_SUCCESS);
132 }
133
134 -static const struct command *find_command(const char *name)
135 +static const struct command *find_command(struct state *state, const char *name)
136 {
137 const struct command **p;
138
139 for (p = __start___command; p < __stop___command; p++) {
140 const struct command *cmd = *p;
141
142 + if (state->vid >= 0 && cmd->type != SUBCOMMAND_VID)
143 + continue;
144 +
145 + if (state->vid < 0 && cmd->type == SUBCOMMAND_VID)
146 + continue;
147 +
148 if (strcmp(cmd->name, name) == 0)
149 return cmd;
150
151 @@ -110,6 +143,51 @@ static const struct command *find_command(const char *name)
152 return NULL;
153 }
154
155 +static int parse_dev_args(struct state *state, int argc, char *argv[])
156 +{
157 + unsigned long vid;
158 + char *endptr;
159 +
160 + /* not enough arguments to parse */
161 + if (argc < 2) {
162 + translate_mesh_iface(state);
163 + return 0;
164 + }
165 +
166 + if (strcmp(argv[0], "vid") == 0) {
167 + if (argv[1] == '\0') {
168 + fprintf(stderr, "Error - unparsable vid\n");
169 + return -EINVAL;
170 + }
171 +
172 + vid = strtoul(argv[1], &endptr, 0);
173 + if (!endptr || *endptr != '\0') {
174 + fprintf(stderr, "Error - unparsable vid\n");
175 + return -EINVAL;
176 + }
177 +
178 + if (vid > 4095) {
179 + fprintf(stderr, "Error - too large vid (max 4095)\n");
180 + return -ERANGE;
181 + }
182 +
183 + /* get mesh interface and overwrite vid afterwards */
184 + translate_mesh_iface(state);
185 + state->vid = vid;
186 +
187 + return 2;
188 + } else if (strcmp(argv[0], "vlan") == 0) {
189 + state->arg_iface = argv[1];
190 + translate_mesh_iface(state);
191 +
192 + return 2;
193 + } else {
194 + /* parse vlan as part of -m parameter */
195 + translate_mesh_iface(state);
196 + return 0;
197 + }
198 +}
199 +
200 int main(int argc, char **argv)
201 {
202 const struct command *cmd;
203 @@ -117,6 +195,7 @@ int main(int argc, char **argv)
204 .arg_iface = mesh_dfl_iface,
205 .cmd = NULL,
206 };
207 + int dev_arguments;
208 int opt;
209 int ret;
210
211 @@ -152,7 +231,15 @@ int main(int argc, char **argv)
212 argc -= optind;
213 optind = 0;
214
215 - cmd = find_command(argv[0]);
216 + /* parse arguments to identify vlan, ... */
217 + dev_arguments = parse_dev_args(&state, argc, argv);
218 + if (dev_arguments < 0)
219 + goto err;
220 +
221 + argv += dev_arguments;
222 + argc -= dev_arguments;
223 +
224 + cmd = find_command(&state, argv[0]);
225 if (!cmd) {
226 fprintf(stderr,
227 "Error - no valid command or debug table specified: %s\n",
228 @@ -162,8 +249,6 @@ int main(int argc, char **argv)
229
230 state.cmd = cmd;
231
232 - translate_mesh_iface(&state);
233 -
234 if (cmd->flags & COMMAND_FLAG_MESH_IFACE &&
235 check_mesh_iface(&state) < 0) {
236 fprintf(stderr,
237 diff --git a/main.h b/main.h
238 index 1a4701513c49ad8974b9c9189619f5dde622acd4..1d952610aefb8367bd52e24bea8c04c3d70b94ea 100644
239 --- a/main.h
240 +++ b/main.h
241 @@ -58,6 +58,7 @@ enum command_flags {
242
243 enum command_type {
244 SUBCOMMAND,
245 + SUBCOMMAND_VID,
246 DEBUGTABLE,
247 };
248
249 @@ -84,7 +85,7 @@ struct command {
250 };
251
252 #define COMMAND_NAMED(_type, _name, _abbr, _handler, _flags, _arg, _usage) \
253 - static const struct command command_ ## _name = { \
254 + static const struct command command_ ## _name ## _ ## _type = { \
255 .type = (_type), \
256 .name = (#_name), \
257 .abbr = _abbr, \
258 @@ -93,8 +94,8 @@ struct command {
259 .arg = (_arg), \
260 .usage = (_usage), \
261 }; \
262 - static const struct command *__command_ ## _name \
263 - __attribute__((__used__)) __attribute__ ((__section__ ("__command"))) = &command_ ## _name
264 + static const struct command *__command_ ## _name ## _ ## _type \
265 + __attribute__((__used__)) __attribute__ ((__section__ ("__command"))) = &command_ ## _name ## _ ## _type
266
267 #define COMMAND(_type, _handler, _abbr, _flags, _arg, _usage) \
268 COMMAND_NAMED(_type, _handler, _abbr, _handler, _flags, _arg, _usage)
269 diff --git a/man/batctl.8 b/man/batctl.8
270 index 0b430313075b5a7a4c796eba0867954e10061002..acb4288c4e6f59b322d20631ef8e3aee6f2215e5 100644
271 --- a/man/batctl.8
272 +++ b/man/batctl.8
273 @@ -68,7 +68,7 @@ free all attached interfaces and remove batman-adv interface.
274 If no parameter is given the current originator interval setting is displayed otherwise the parameter is used to set the
275 originator interval. The interval is in units of milliseconds.
276 .br
277 -.IP "\fBap_isolation\fP|\fBap\fP [\fB0\fP|\fB1\fP]"
278 +.IP "[\fBvlan <vdev>\fP|\fBvid <vid>\fP] \fBap_isolation\fP|\fBap\fP [\fB0\fP|\fB1\fP]"
279 If no parameter is given the current ap isolation setting is displayed. Otherwise the parameter is used to enable or
280 disable ap isolation. This command can be used in conjunction with "\-m" option to target per VLAN configurations.
281 .br
282 diff --git a/sys.c b/sys.c
283 index 39123db87d391b8898b7454eba7708515bfb3c78..f19719cfad61f36f2a5c1078305de83eb5be142a 100644
284 --- a/sys.c
285 +++ b/sys.c
286 @@ -141,9 +141,35 @@ int sys_simple_print_boolean(struct nl_msg *msg, void *arg,
287
288 static void settings_usage(struct state *state)
289 {
290 - fprintf(stderr, "Usage: batctl [options] %s|%s [parameters] %s\n",
291 - state->cmd->name, state->cmd->abbr,
292 - state->cmd->usage ? state->cmd->usage : "");
293 + const char *default_prefixes[] = {
294 + "",
295 + NULL,
296 + };
297 + const char *vlan_prefixes[] = {
298 + "vlan <vdev> ",
299 + "vid <vid> ",
300 + NULL,
301 + };
302 + const char *linestart = "Usage:";
303 + const char **prefixes;
304 + const char **prefix;
305 +
306 + switch (state->cmd->type) {
307 + case SUBCOMMAND_VID:
308 + prefixes = vlan_prefixes;
309 + break;
310 + default:
311 + prefixes = default_prefixes;
312 + break;
313 + }
314 +
315 + for (prefix = &prefixes[0]; *prefix; prefix++) {
316 + fprintf(stderr, "%s batctl [options] %s%s|%s [parameters] %s\n",
317 + linestart, *prefix, state->cmd->name, state->cmd->abbr,
318 + state->cmd->usage ? state->cmd->usage : "");
319 +
320 + linestart = " ";
321 + }
322
323 fprintf(stderr, "parameters:\n");
324 fprintf(stderr, " \t -h print this help\n");