summaryrefslogtreecommitdiffstats
path: root/src/network/netdev
diff options
context:
space:
mode:
authorAnnika Wickert <aw@awlnx.space>2020-10-02 21:43:05 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-02-24 17:57:29 +0100
commitc0267a592a2d44c89874249573d53a456ea3756b (patch)
treeb51b3dbcd12d626a441297a4db5fb672a98f7922 /src/network/netdev
parentresolved: don't discard mDNS queries with bad flags (diff)
downloadsystemd-c0267a592a2d44c89874249573d53a456ea3756b.tar.xz
systemd-c0267a592a2d44c89874249573d53a456ea3756b.zip
network: Implement B.A.T.M.A.N. Advanced interface type
Diffstat (limited to 'src/network/netdev')
-rw-r--r--src/network/netdev/batadv.c204
-rw-r--r--src/network/netdev/batadv.h47
-rw-r--r--src/network/netdev/netdev-gperf.gperf11
-rw-r--r--src/network/netdev/netdev.c7
-rw-r--r--src/network/netdev/netdev.h2
5 files changed, 269 insertions, 2 deletions
diff --git a/src/network/netdev/batadv.c b/src/network/netdev/batadv.c
new file mode 100644
index 0000000000..86cd1f19b3
--- /dev/null
+++ b/src/network/netdev/batadv.c
@@ -0,0 +1,204 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <inttypes.h>
+#include <linux/genetlink.h>
+
+#include "batadv.h"
+#include "fileio.h"
+#include "netlink-util.h"
+#include "network-internal.h"
+#include "networkd-manager.h"
+#include "parse-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
+#include "string-util.h"
+
+static void batadv_init(NetDev *n) {
+ BatmanAdvanced *b;
+
+ b = BATADV(n);
+
+ /* Set defaults */
+ b->aggregation = true;
+ b->gateway_bandwidth_down = 10000;
+ b->gateway_bandwidth_up = 2000;
+ b->bridge_loop_avoidance = true;
+ b->distributed_arp_table = true;
+ b->fragmentation = true;
+ b->hop_penalty = 15;
+ b->originator_interval = 1000;
+ b->routing_algorithm = BATADV_ROUTING_ALGORITHM_BATMAN_V;
+}
+
+static const char* const batadv_gateway_mode_table[_BATADV_GATEWAY_MODE_MAX] = {
+ [BATADV_GATEWAY_MODE_OFF] = "off",
+ [BATADV_GATEWAY_MODE_CLIENT] = "client",
+ [BATADV_GATEWAY_MODE_SERVER] = "server",
+};
+
+static const char* const batadv_routing_algorithm_table[_BATADV_ROUTING_ALGORITHM_MAX] = {
+ [BATADV_ROUTING_ALGORITHM_BATMAN_V] = "batman-v",
+ [BATADV_ROUTING_ALGORITHM_BATMAN_IV] = "batman-iv",
+};
+
+static const char* const batadv_routing_algorithm_kernel_table[_BATADV_ROUTING_ALGORITHM_MAX] = {
+ [BATADV_ROUTING_ALGORITHM_BATMAN_V] = "BATMAN_V",
+ [BATADV_ROUTING_ALGORITHM_BATMAN_IV] = "BATMAN_IV",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(batadv_gateway_mode, BatadvGatewayModes);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_batadv_gateway_mode, batadv_gateway_mode, BatadvGatewayModes,
+ "Failed to parse GatewayMode=");
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(batadv_routing_algorithm, BatadvRoutingAlgorithm);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_batadv_routing_algorithm, batadv_routing_algorithm, BatadvRoutingAlgorithm,
+ "Failed to parse RoutingAlgorithm=");
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(batadv_routing_algorithm_kernel, BatadvRoutingAlgorithm);
+
+int config_parse_badadv_bandwidth (
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint64_t k;
+ uint32_t *bandwidth = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = parse_size(rvalue, 1000, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse '%s=', ignoring assignment: %s",
+ lvalue, rvalue);
+ return 0;
+ }
+
+ if (k/1000/100 > UINT32_MAX) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "The value of '%s=', is outside of 0...429496729500000 range: %s",
+ lvalue, rvalue);
+ }
+
+ *bandwidth = k/1000/100;
+
+ return 0;
+}
+
+/* callback for batman netdev's parameter set */
+static int netdev_batman_set_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
+ int r;
+
+ assert(netdev);
+ assert(m);
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0) {
+ log_netdev_warning_errno(netdev, r, "BATADV parameters could not be set: %m");
+ return 1;
+ }
+
+ log_netdev_debug(netdev, "BATADV parameters set success");
+
+ return 1;
+}
+
+static int netdev_batadv_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ BatmanAdvanced *b;
+ int r;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
+
+ assert(netdev);
+
+ b = BATADV(netdev);
+ assert(b);
+
+ r = sd_genl_message_new(netdev->manager->genl, SD_GENL_BATADV, BATADV_CMD_SET_MESH, &message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_MESH_IFINDEX, netdev->ifindex);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set ifindex: %m");
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_GW_MODE, b->gateway_mode);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set gateway_mode: %m");
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_AGGREGATED_OGMS_ENABLED, b->aggregation);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set aggregation: %m");
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED, b->bridge_loop_avoidance);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set bridge_loop_avoidance: %m");
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED, b->distributed_arp_table);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set distributed_arp_table: %m");
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_FRAGMENTATION_ENABLED, b->fragmentation);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set fragmentation: %m");
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_HOP_PENALTY, b->hop_penalty);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set hop_penalty: %m");
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_ORIG_INTERVAL, DIV_ROUND_UP(b->originator_interval, USEC_PER_MSEC));
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set orig_interval: %m");
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_GW_BANDWIDTH_DOWN, b->gateway_bandwidth_down);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set gateway_bandwidth_down: %m");
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_GW_BANDWIDTH_UP, b->gateway_bandwidth_up);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Failed to set gateway_bandwidth_up: %m");
+
+ r = netlink_call_async(netdev->manager->genl, NULL, message, netdev_batman_set_handler,
+ netdev_destroy_callback, netdev);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not send batman device message: %m");
+
+ netdev_ref(netdev);
+
+ return r;
+}
+
+static int netdev_batadv_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ BatmanAdvanced *b;
+ int r;
+
+ assert(netdev);
+ assert(m);
+
+ b = BATADV(netdev);
+ assert(b);
+
+ r = sd_netlink_message_append_string(m, IFLA_BATADV_ALGO_NAME, batadv_routing_algorithm_kernel_to_string(b->routing_algorithm));
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BATADV_ALGO_NAME attribute: %m");
+
+ return r;
+}
+
+const NetDevVTable batadv_vtable = {
+ .object_size = sizeof(BatmanAdvanced),
+ .init = batadv_init,
+ .sections = NETDEV_COMMON_SECTIONS "BatmanAdvanced\0",
+ .fill_message_create = netdev_batadv_fill_message_create,
+ .post_create = netdev_batadv_post_create,
+ .create_type = NETDEV_CREATE_MASTER,
+};
diff --git a/src/network/netdev/batadv.h b/src/network/netdev/batadv.h
new file mode 100644
index 0000000000..f1f9b46885
--- /dev/null
+++ b/src/network/netdev/batadv.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#pragma once
+
+#include <linux/batman_adv.h>
+
+#include "conf-parser.h"
+#include "netdev.h"
+
+#define BATADV_GENL_NAME "batadv"
+
+typedef enum BatadvGatewayModes {
+ BATADV_GATEWAY_MODE_OFF = BATADV_GW_MODE_OFF,
+ BATADV_GATEWAY_MODE_CLIENT = BATADV_GW_MODE_CLIENT,
+ BATADV_GATEWAY_MODE_SERVER = BATADV_GW_MODE_SERVER,
+ _BATADV_GATEWAY_MODE_MAX,
+ _BATADV_GATEWAY_MODE_INVALID = -EINVAL,
+} BatadvGatewayModes;
+
+typedef enum BatadvRoutingAlgorithm {
+ BATADV_ROUTING_ALGORITHM_BATMAN_V,
+ BATADV_ROUTING_ALGORITHM_BATMAN_IV,
+ _BATADV_ROUTING_ALGORITHM_MAX,
+ _BATADV_ROUTING_ALGORITHM_INVALID = -EINVAL,
+} BatadvRoutingAlgorithm;
+
+typedef struct Batadv {
+ NetDev meta;
+
+ BatadvGatewayModes gateway_mode;
+ uint32_t gateway_bandwidth_down;
+ uint32_t gateway_bandwidth_up;
+ uint8_t hop_penalty;
+ BatadvRoutingAlgorithm routing_algorithm;
+ usec_t originator_interval;
+ bool aggregation;
+ bool bridge_loop_avoidance;
+ bool distributed_arp_table;
+ bool fragmentation;
+} BatmanAdvanced;
+
+DEFINE_NETDEV_CAST(BATADV, BatmanAdvanced);
+extern const NetDevVTable batadv_vtable;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_batadv_gateway_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_batadv_routing_algorithm);
+CONFIG_PARSER_PROTOTYPE(config_parse_badadv_bandwidth);
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index fd02c6689b..8abe044890 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -5,6 +5,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#endif
#include <stddef.h>
#include "bareudp.h"
+#include "batadv.h"
#include "bond.h"
#include "bridge.h"
#include "conf-parser.h"
@@ -235,3 +236,13 @@ WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_f
WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0
Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id)
Xfrm.Independent, config_parse_bool, 0, offsetof(Xfrm, independent)
+BatmanAdvanced.Aggregation, config_parse_bool, 0, offsetof(BatmanAdvanced, aggregation)
+BatmanAdvanced.BridgeLoopAvoidance, config_parse_bool, 0, offsetof(BatmanAdvanced, bridge_loop_avoidance)
+BatmanAdvanced.DistributedArpTable, config_parse_bool, 0, offsetof(BatmanAdvanced, distributed_arp_table)
+BatmanAdvanced.Fragmentation, config_parse_bool, 0, offsetof(BatmanAdvanced, fragmentation)
+BatmanAdvanced.GatewayMode, config_parse_batadv_gateway_mode, 0, offsetof(BatmanAdvanced, gateway_mode)
+BatmanAdvanced.GatewayBandwithDown, config_parse_badadv_bandwidth, 0, offsetof(BatmanAdvanced, gateway_bandwidth_down)
+BatmanAdvanced.GatewayBandwithUp, config_parse_badadv_bandwidth, 0, offsetof(BatmanAdvanced, gateway_bandwidth_up)
+BatmanAdvanced.HopPenalty, config_parse_uint8, 0, offsetof(BatmanAdvanced, hop_penalty)
+BatmanAdvanced.OriginatorIntervalSec, config_parse_sec, 0, offsetof(BatmanAdvanced, originator_interval)
+BatmanAdvanced.RoutingAlgorithm, config_parse_batadv_routing_algorithm, 0, offsetof(BatmanAdvanced, routing_algorithm)
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 36d6c5168a..fb03534869 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -6,6 +6,7 @@
#include "alloc-util.h"
#include "bareudp.h"
+#include "batadv.h"
#include "bond.h"
#include "bridge.h"
#include "conf-files.h"
@@ -43,6 +44,7 @@
#include "xfrm.h"
const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
+ [NETDEV_KIND_BATADV] = &batadv_vtable,
[NETDEV_KIND_BRIDGE] = &bridge_vtable,
[NETDEV_KIND_BOND] = &bond_vtable,
[NETDEV_KIND_VLAN] = &vlan_vtable,
@@ -82,6 +84,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_BAREUDP] = "bareudp",
+ [NETDEV_KIND_BATADV] = "batadv",
[NETDEV_KIND_BRIDGE] = "bridge",
[NETDEV_KIND_BOND] = "bond",
[NETDEV_KIND_VLAN] = "vlan",
@@ -262,7 +265,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, link_netlink_message
assert(netdev->state == NETDEV_STATE_READY);
assert(netdev->manager);
assert(netdev->manager->rtnl);
- assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF));
+ assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF, NETDEV_KIND_BATADV));
assert(link);
assert(callback);
@@ -353,7 +356,7 @@ static int netdev_enslave(NetDev *netdev, Link *link, link_netlink_message_handl
assert(netdev);
assert(netdev->manager);
assert(netdev->manager->rtnl);
- assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF));
+ assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF, NETDEV_KIND_BATADV));
if (netdev->state == NETDEV_STATE_READY) {
r = netdev_enslave_ready(netdev, link, callback);
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index c13542ae80..6d149da2e9 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -12,6 +12,7 @@
/* This is the list of known sections. We need to ignore them in the initial parsing phase. */
#define NETDEV_OTHER_SECTIONS \
"-BareUDP\0" \
+ "-BatmanAdvanced\0" \
"-Bond\0" \
"-Bridge\0" \
"-FooOverUDP\0" \
@@ -83,6 +84,7 @@ typedef enum NetDevKind {
NETDEV_KIND_XFRM,
NETDEV_KIND_IFB,
NETDEV_KIND_BAREUDP,
+ NETDEV_KIND_BATADV,
_NETDEV_KIND_MAX,
_NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
_NETDEV_KIND_INVALID = -EINVAL,