summaryrefslogtreecommitdiffstats
path: root/src/network/netdev/batadv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/netdev/batadv.c')
-rw-r--r--src/network/netdev/batadv.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/network/netdev/batadv.c b/src/network/netdev/batadv.c
new file mode 100644
index 0000000..26da023
--- /dev/null
+++ b/src/network/netdev/batadv.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <inttypes.h>
+#include <netinet/in.h>
+#include <linux/genetlink.h>
+#include <linux/if_arp.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 = 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_message(NetDev *netdev, sd_netlink_message *message) {
+ BatmanAdvanced *b = BATADV(netdev);
+ int r;
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_MESH_IFINDEX, netdev->ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_GW_MODE, b->gateway_mode);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_AGGREGATED_OGMS_ENABLED, b->aggregation);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED, b->bridge_loop_avoidance);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED, b->distributed_arp_table);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_FRAGMENTATION_ENABLED, b->fragmentation);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u8(message, BATADV_ATTR_HOP_PENALTY, b->hop_penalty);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_ORIG_INTERVAL, DIV_ROUND_UP(b->originator_interval, USEC_PER_MSEC));
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_GW_BANDWIDTH_DOWN, b->gateway_bandwidth_down);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u32(message, BATADV_ATTR_GW_BANDWIDTH_UP, b->gateway_bandwidth_up);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int netdev_batadv_post_create(NetDev *netdev, Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
+ int r;
+
+ assert(netdev);
+
+ r = sd_genl_message_new(netdev->manager->genl, BATADV_NL_NAME, BATADV_CMD_SET_MESH, &message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not allocate netlink message: %m");
+
+ r = netdev_batadv_post_create_message(netdev, message);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not create netlink message: %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 netlink message: %m");
+
+ netdev_ref(netdev);
+
+ return r;
+}
+
+static int netdev_batadv_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ assert(m);
+
+ BatmanAdvanced *b = BATADV(netdev);
+ int r;
+
+ r = sd_netlink_message_append_string(m, IFLA_BATADV_ALGO_NAME, batadv_routing_algorithm_kernel_to_string(b->routing_algorithm));
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+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_INDEPENDENT,
+ .iftype = ARPHRD_ETHER,
+ .generate_mac = true,
+};