Adds support for the new 'noflood_mark' setting in batman-adv.
Signed-off-by: Linus Lüssing linus.luessing@c0d3.blue --- Changelog v3: * changed command from a noflood tri-state option to a value/mask one similar to the isolation mark * noflood.c -> noflood_mark.c
Changelog v2: * added noflood.c --- Makefile | 1 + README.rst | 15 ++++++ batman_adv.h | 12 +++++ man/batctl.8 | 23 ++++++++ noflood_mark.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 192 insertions(+) create mode 100644 noflood_mark.c
diff --git a/Makefile b/Makefile index b7bd545..18f874c 100755 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ $(eval $(call add_command,multicast_mode,y)) $(eval $(call add_command,nc_nodes,y)) $(eval $(call add_command,neighbors,y)) $(eval $(call add_command,network_coding,y)) +$(eval $(call add_command,noflood_mark,y)) $(eval $(call add_command,orig_interval,y)) $(eval $(call add_command,originators,y)) $(eval $(call add_command,ping,y)) diff --git a/README.rst b/README.rst index bc54412..c025c30 100644 --- a/README.rst +++ b/README.rst @@ -549,6 +549,21 @@ Usage:: * Example 4: ``batctl mark 0x0f``
+batctl noflood_mark +======================= + +display or modify noflood_mark setting + +Usage:: + + batctl noflood_mark|nf $value[/0x$mask] + +* Example 1: ``batctl nf 0x00000001/0xffffffff`` +* Example 2: ``batctl nf 0x00040000/0xffff0000`` +* Example 3: ``batctl nf 16`` +* Example 4: ``batctl nf 0x0f`` + + batctl translocal =================
diff --git a/batman_adv.h b/batman_adv.h index 67f4636..6fabb7a 100644 --- a/batman_adv.h +++ b/batman_adv.h @@ -480,6 +480,18 @@ enum batadv_nl_attrs { */ BATADV_ATTR_MULTICAST_FANOUT,
+ /** + * @BATADV_ATTR_NOFLOOD_MARK: the noflood mark which allows to tag + * frames which should never be broadcast flooded through the mesh. + */ + BATADV_ATTR_NOFLOOD_MARK, + + /** + * @BATADV_ATTR_NOFLOOD_MASK: the noflood (bit)mask which allows to tag + * frames which should never be broadcast flooded through the mesh. + */ + BATADV_ATTR_NOFLOOD_MASK, + /* add attributes above here, update the policy in netlink.c */
/** diff --git a/man/batctl.8 b/man/batctl.8 index 0b43031..4173137 100644 --- a/man/batctl.8 +++ b/man/batctl.8 @@ -116,6 +116,29 @@ If no parameter is given the current multicast fanout setting is displayed. Othe the multicast fanout. The multicast fanout defines the maximum number of packet copies that may be generated for a multicast-to-unicast conversion. Once this limit is exceeded distribution will fall back to broadcast. .br +.IP "\fBnoflood_mark\fP|\fBnf\fP" +If no parameter is given the current noflood mark value is displayed. +Otherwise the parameter is used to set or unset the noflood mark. The +noflood mark allows to prevent broadcast flooding of a frame which +was previously tagged via netfilter for instance. batman-adv will +then only forward a frame into the mesh if destined to a limited +number of destination nodes and drop the frame otherwise. +.br +The input is supposed to be of the form $value/$mask, where $value can be any +32bit long integer (expressed in decimal or hex base) and $mask is a generic +bitmask (expressed in hex base) that selects the bits to take into consideration +from $value. It is also possible to enter the input using only $value and in +this case the full bitmask is used by default. + +.br +.br +Example 1: 0x00000001/0xffffffff +.br +Example 2: 0x00040000/0xffff0000 +.br +Example 3: 16 or 0x0F +.br +.br .IP "\fBloglevel\fP|\fBll\fP [\fBlevel\fP[ \fBlevel\fP[ \fBlevel\fP]] \fB...\fP]" If no parameter is given the current log level settings are displayed otherwise the parameter(s) is/are used to set the log level. Level 'none' disables all verbose logging. Level 'batman' enables messages related to routing / flooding / broadcasting. diff --git a/noflood_mark.c b/noflood_mark.c new file mode 100644 index 0000000..e89205c --- /dev/null +++ b/noflood_mark.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2009-2019 B.A.T.M.A.N. contributors: + * + * Antonio Quartulli a@unstable.cc + * Linus Lüssing linus.luessing@c0d3.blue + * + * License-Filename: LICENSES/preferred/GPL-2.0 + */ + +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#include "main.h" +#include "sys.h" + +static struct noflood_mark_data { + uint32_t noflood_mark; + uint32_t noflood_mask; +} noflood_mark; + +static int parse_noflood_mark(struct state *state, int argc, char *argv[]) +{ + struct settings_data *settings = state->cmd->arg; + struct noflood_mark_data *data = settings->data; + char *mask_ptr; + char buff[256]; + uint32_t mark; + uint32_t mask; + char *endptr; + + if (argc != 2) { + fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n"); + return -EINVAL; + } + + strncpy(buff, argv[1], sizeof(buff)); + buff[sizeof(buff) - 1] = '\0'; + + /* parse the mask if it has been specified, otherwise assume the mask is + * the biggest possible + */ + mask = 0xFFFFFFFF; + mask_ptr = strchr(buff, '/'); + if (mask_ptr) { + *mask_ptr = '\0'; + mask_ptr++; + + /* the mask must be entered in hex base as it is going to be a + * bitmask and not a prefix length + */ + mask = strtoul(mask_ptr, &endptr, 16); + if (!endptr || *endptr != '\0') + goto inval_format; + } + + /* the mark can be entered in any base */ + mark = strtoul(buff, &endptr, 0); + if (!endptr || *endptr != '\0') + goto inval_format; + + data->noflood_mask = mask; + /* erase bits not covered by the mask */ + data->noflood_mark = mark & mask; + + return 0; + +inval_format: + fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n"); + fprintf(stderr, "The following formats for mark(/mask) are allowed:\n"); + fprintf(stderr, " * 0x12345678\n"); + fprintf(stderr, " * 0x12345678/0xabcdef09\n"); + return -EINVAL; +} + +static int print_noflood_mark(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int *result = arg; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } + + if (!attrs[BATADV_ATTR_NOFLOOD_MARK] || + !attrs[BATADV_ATTR_NOFLOOD_MASK]) + return NL_OK; + + printf("0x%08x/0x%08x\n", + nla_get_u32(attrs[BATADV_ATTR_NOFLOOD_MARK]), + nla_get_u32(attrs[BATADV_ATTR_NOFLOOD_MASK])); + + *result = 0; + return NL_STOP; +} + +static int get_noflood_mark(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_noflood_mark); +} + +static int set_attrs_noflood_mark(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct noflood_mark_data *data = settings->data; + + nla_put_u32(msg, BATADV_ATTR_NOFLOOD_MARK, data->noflood_mark); + nla_put_u32(msg, BATADV_ATTR_NOFLOOD_MASK, data->noflood_mask); + + return 0; +} + +static int set_noflood_mark(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_noflood_mark, NULL); +} + +static struct settings_data batctl_settings_noflood_mark = { + .sysfs_name = NULL, + .data = &noflood_mark, + .parse = parse_noflood_mark, + .netlink_get = get_noflood_mark, + .netlink_set = set_noflood_mark, +}; + +COMMAND_NAMED(SUBCOMMAND, noflood_mark, "nf", handle_sys_setting, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_noflood_mark, + "[mark] \tdisplay or modify noflood_mark setting");
b.a.t.m.a.n@lists.open-mesh.org