1 From: Sven Eckelmann <sven@narfation.org>
2 Date: Thu, 13 Jun 2019 21:12:14 +0200
3 Subject: batctl: Make vlan setting explicit
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.
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.
13 Signed-off-by: Sven Eckelmann <sven@narfation.org>
15 Forwarded: https://patchwork.open-mesh.org/patch/17947/
17 diff --git a/ap_isolation.c b/ap_isolation.c
18 index 71dcd00eac845d488c4969b17e1339f181c6c913..7c34649225dcc9cc557cc5bb4cbfa2343f8c0763 100644
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");
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
34 @@ -28,48 +28,75 @@ extern const struct command *__stop___command[];
36 static void print_usage(void)
38 - enum command_type type[] = {
46 + .label = "commands:\n",
47 + .types = BIT(SUBCOMMAND) |
48 + BIT(SUBCOMMAND_VID),
51 + .label = "debug tables: \tdisplay the corresponding debug table\n",
52 + .types = BIT(DEBUGTABLE),
55 + const char *default_prefixes[] = {
59 + const char *vlan_prefixes[] = {
64 const struct command **p;
66 + const char **prefixes;
67 + const char **prefix;
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");
78 for (i = 0; i < sizeof(type) / sizeof(*type); i++) {
79 fprintf(stderr, "\n");
83 - fprintf(stderr, "commands:\n");
86 - fprintf(stderr, "debug tables: \tdisplay the corresponding debug table\n");
89 + fprintf(stderr, "%s", type[i].label);
91 for (p = __start___command; p < __stop___command; p++) {
92 const struct command *cmd = *p;
94 - if (cmd->type != type[i])
95 + if (!(BIT(cmd->type) & type[i].types))
101 - if (strcmp(cmd->name, cmd->abbr) == 0)
102 - snprintf(buf, sizeof(buf), "%s", cmd->name);
104 - snprintf(buf, sizeof(buf), "%s|%s", cmd->name,
106 + switch (cmd->type) {
107 + case SUBCOMMAND_VID:
108 + prefixes = vlan_prefixes;
111 + prefixes = default_prefixes;
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);
121 + snprintf(buf, sizeof(buf), "%s%s|%s",
122 + *prefix, cmd->name, cmd->abbr);
124 + fprintf(stderr, " \t%-35s%s\n", buf,
130 @@ -93,13 +120,19 @@ static void version(void)
134 -static const struct command *find_command(const char *name)
135 +static const struct command *find_command(struct state *state, const char *name)
137 const struct command **p;
139 for (p = __start___command; p < __stop___command; p++) {
140 const struct command *cmd = *p;
142 + if (state->vid >= 0 && cmd->type != SUBCOMMAND_VID)
145 + if (state->vid < 0 && cmd->type == SUBCOMMAND_VID)
148 if (strcmp(cmd->name, name) == 0)
151 @@ -110,6 +143,51 @@ static const struct command *find_command(const char *name)
155 +static int parse_dev_args(struct state *state, int argc, char *argv[])
160 + /* not enough arguments to parse */
162 + translate_mesh_iface(state);
166 + if (strcmp(argv[0], "vid") == 0) {
167 + if (argv[1] == '\0') {
168 + fprintf(stderr, "Error - unparsable vid\n");
172 + vid = strtoul(argv[1], &endptr, 0);
173 + if (!endptr || *endptr != '\0') {
174 + fprintf(stderr, "Error - unparsable vid\n");
179 + fprintf(stderr, "Error - too large vid (max 4095)\n");
183 + /* get mesh interface and overwrite vid afterwards */
184 + translate_mesh_iface(state);
188 + } else if (strcmp(argv[0], "vlan") == 0) {
189 + state->arg_iface = argv[1];
190 + translate_mesh_iface(state);
194 + /* parse vlan as part of -m parameter */
195 + translate_mesh_iface(state);
200 int main(int argc, char **argv)
202 const struct command *cmd;
203 @@ -117,6 +195,7 @@ int main(int argc, char **argv)
204 .arg_iface = mesh_dfl_iface,
211 @@ -152,7 +231,15 @@ int main(int argc, char **argv)
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)
221 + argv += dev_arguments;
222 + argc -= dev_arguments;
224 + cmd = find_command(&state, argv[0]);
227 "Error - no valid command or debug table specified: %s\n",
228 @@ -162,8 +249,6 @@ int main(int argc, char **argv)
232 - translate_mesh_iface(&state);
234 if (cmd->flags & COMMAND_FLAG_MESH_IFACE &&
235 check_mesh_iface(&state) < 0) {
237 diff --git a/main.h b/main.h
238 index 1a4701513c49ad8974b9c9189619f5dde622acd4..1d952610aefb8367bd52e24bea8c04c3d70b94ea 100644
241 @@ -58,6 +58,7 @@ enum command_flags {
249 @@ -84,7 +85,7 @@ struct command {
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 = { \
258 @@ -93,8 +94,8 @@ struct command {
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
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
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.
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.
282 diff --git a/sys.c b/sys.c
283 index 39123db87d391b8898b7454eba7708515bfb3c78..f19719cfad61f36f2a5c1078305de83eb5be142a 100644
286 @@ -141,9 +141,35 @@ int sys_simple_print_boolean(struct nl_msg *msg, void *arg,
288 static void settings_usage(struct state *state)
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[] = {
297 + const char *vlan_prefixes[] = {
302 + const char *linestart = "Usage:";
303 + const char **prefixes;
304 + const char **prefix;
306 + switch (state->cmd->type) {
307 + case SUBCOMMAND_VID:
308 + prefixes = vlan_prefixes;
311 + prefixes = default_prefixes;
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 : "");
323 fprintf(stderr, "parameters:\n");
324 fprintf(stderr, " \t -h print this help\n");