diff options
author | Annika Wickert <aw@awlnx.space> | 2020-10-02 21:43:05 +0200 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-02-24 17:57:29 +0100 |
commit | c0267a592a2d44c89874249573d53a456ea3756b (patch) | |
tree | b51b3dbcd12d626a441297a4db5fb672a98f7922 /src/network/netdev | |
parent | resolved: don't discard mDNS queries with bad flags (diff) | |
download | systemd-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.c | 204 | ||||
-rw-r--r-- | src/network/netdev/batadv.h | 47 | ||||
-rw-r--r-- | src/network/netdev/netdev-gperf.gperf | 11 | ||||
-rw-r--r-- | src/network/netdev/netdev.c | 7 | ||||
-rw-r--r-- | src/network/netdev/netdev.h | 2 |
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, |