From 95c5dca23c2fa6326cdc59736f48f20e40ed3561 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 5 Jun 2023 14:51:41 +0000 Subject: [PATCH] ports: Add the most basic supports for bonding Signed-off-by: Michael Tremer --- Makefile.am | 2 + src/networkd/port-bonding.c | 142 ++++++++++++++++++++++++++++++++++++ src/networkd/port-bonding.h | 37 ++++++++++ src/networkd/port.c | 7 ++ src/networkd/port.h | 10 ++- 5 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 src/networkd/port-bonding.c create mode 100644 src/networkd/port-bonding.h diff --git a/Makefile.am b/Makefile.am index 273302b3..ad42f49c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -330,6 +330,8 @@ dist_networkd_SOURCES = \ src/networkd/ports.h \ src/networkd/port.c \ src/networkd/port.h \ + src/networkd/port-bonding.c \ + src/networkd/port-bonding.h \ src/networkd/port-bus.c \ src/networkd/port-bus.h \ src/networkd/port-dummy.c \ diff --git a/src/networkd/port-bonding.c b/src/networkd/port-bonding.c new file mode 100644 index 00000000..6bddc430 --- /dev/null +++ b/src/networkd/port-bonding.c @@ -0,0 +1,142 @@ +/*############################################################################# +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2023 IPFire Network Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include + +#include "config.h" +#include "daemon.h" +#include "logging.h" +#include "port.h" +#include "port-bonding.h" +#include "string.h" + +const struct nw_port_bonding_mode { + const int mode; + const char* string; +} nw_port_bonding_modes[] = { + { BOND_MODE_ROUNDROBIN, "round-robin" }, + { BOND_MODE_ACTIVEBACKUP, "active-backup" }, + { BOND_MODE_XOR, "xor" }, + { BOND_MODE_BROADCAST, "broadcast" }, + { BOND_MODE_8023AD, "802.3ad" }, + { BOND_MODE_TLB, "tlb" }, + { BOND_MODE_ALB, "alb" }, + { -1, NULL }, +}; + +static int nw_port_bonding_mode_from_string(const char* string) { + const struct nw_port_bonding_mode* m = NULL; + + for (m = nw_port_bonding_modes; m->string; m++) { + if (strcmp(m->string, string) == 0) + return m->mode; + } + + return -1; +} + +static const char* nw_port_bonding_mode_to_string(const int mode) { + const struct nw_port_bonding_mode* m = NULL; + + for (m = nw_port_bonding_modes; m->string; m++) { + if (m->mode == mode) + return m->string; + } + + return NULL; +} + +static int nw_port_bonding_config_read(nw_port* port) { + int r; + + // Mode + const char* mode = nw_config_get(port->config, "BONDING_MODE"); + if (mode) { + r = nw_port_bonding_set_mode(port, mode); + if (r) + return r; + } + + return 0; +} + +static int nw_port_bonding_config_write(nw_port* port) { + int r; + + // Mode + r = nw_config_set(port->config, "BONDING_MODE", + nw_port_bonding_mode_to_string(port->bonding.mode)); + if (r) + return r; + + return 0; +} + +static int nw_port_bonding_create_link(nw_port* port, sd_netlink_message* m) { + int r; + + // Set mode + r = sd_netlink_message_append_u8(m, IFLA_BOND_MODE, port->bonding.mode); + if (r < 0) + return r; + + return 0; +} + +const nw_port_info_t nw_port_info_bonding = { + .kind = "bond", + + // Operations + .ops = { + // Configuration + .config_read = nw_port_bonding_config_read, + .config_write = nw_port_bonding_config_write, + + // Link + .create_link = nw_port_bonding_create_link, + }, +}; + +const char* nw_port_bonding_get_mode(nw_port* port) { + return nw_port_bonding_mode_to_string(port->bonding.mode); +} + +int nw_port_bonding_set_mode(nw_port* port, const char* mode) { + const int m = nw_port_bonding_mode_from_string(mode); + + switch (m) { + case BOND_MODE_ROUNDROBIN: + case BOND_MODE_ACTIVEBACKUP: + case BOND_MODE_XOR: + case BOND_MODE_BROADCAST: + case BOND_MODE_8023AD: + case BOND_MODE_TLB: + case BOND_MODE_ALB: + port->bonding.mode = m; + break; + + default: + ERROR("%s: Unsupported bonding mode '%s'\n", port->name, mode); + errno = ENOTSUP; + return 1; + } + + return 0; +} diff --git a/src/networkd/port-bonding.h b/src/networkd/port-bonding.h new file mode 100644 index 00000000..5cd2c433 --- /dev/null +++ b/src/networkd/port-bonding.h @@ -0,0 +1,37 @@ +/*############################################################################# +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2023 IPFire Network Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#ifndef NETWORKD_PORT_BONDING_H +#define NETWORKD_PORT_BONDING_H + +#include + +#include "port.h" + +struct nw_port_bonding { + int mode; +}; + +extern const nw_port_info_t nw_port_info_bonding; + +const char* nw_port_bonding_get_mode(nw_port* port); +int nw_port_bonding_set_mode(nw_port* port, const char* mode); + +#endif /* NETWORKD_PORT_BONDING_H */ diff --git a/src/networkd/port.c b/src/networkd/port.c index d5ffe42c..b44cc882 100644 --- a/src/networkd/port.c +++ b/src/networkd/port.c @@ -30,6 +30,7 @@ #include "link.h" #include "logging.h" #include "port.h" +#include "port-bonding.h" #include "port-dummy.h" #include "port-vlan.h" #include "stats-collector.h" @@ -39,6 +40,7 @@ static const struct nw_port_type_map { nw_port_type_t type; const char* name; } nw_port_type_map[] = { + { NW_PORT_BONDING, "bonding" }, { NW_PORT_DUMMY, "dummy" }, { NW_PORT_VLAN, "vlan" }, { NW_PORT_UNKNOWN, NULL }, @@ -210,6 +212,10 @@ int nw_port_create(nw_port** port, nw_daemon* daemon, nw_port_type_t type, const // Set operations switch (p->type) { + case NW_PORT_BONDING: + p->info = &nw_port_info_bonding; + break; + case NW_PORT_DUMMY: p->info = &nw_port_info_dummy; break; @@ -337,6 +343,7 @@ int __nw_port_drop_port(nw_daemon* daemon, nw_port* port, void* data) { } break; + case NW_PORT_BONDING: case NW_PORT_DUMMY: case NW_PORT_UNKNOWN: break; diff --git a/src/networkd/port.h b/src/networkd/port.h index 8bc4db8a..f8beed3b 100644 --- a/src/networkd/port.h +++ b/src/networkd/port.h @@ -31,6 +31,7 @@ typedef enum nw_port_type { NW_PORT_UNKNOWN = 0, + NW_PORT_BONDING, NW_PORT_DUMMY, NW_PORT_VLAN, } nw_port_type_t; @@ -41,12 +42,14 @@ typedef enum nw_port_type { #define NW_VLAN_ID_MAX 4096 typedef struct nw_port nw_port; +typedef struct nw_port_info nw_port_info_t; #include "address.h" #include "config.h" #include "daemon.h" +#include "port-bonding.h" -typedef struct nw_port_info { +struct nw_port_info { // IFLA_INFO_KIND/IFLA_INFO_DATA const char* kind; @@ -62,7 +65,7 @@ typedef struct nw_port_info { int (*create_link)(nw_port* port, sd_netlink_message* message); int (*destroy_link)(nw_port* port); } ops; -} nw_port_info_t; +}; #define NW_PORT_INFO(port) (port->info) #define NW_PORT_OPS(port) (&NW_PORT_INFO(port)->ops) @@ -86,6 +89,9 @@ struct nw_port { // Type Operations const nw_port_info_t* info; + // Bonding Settings + struct nw_port_bonding bonding; + // VLAN settings struct nw_port_vlan { nw_port* parent; -- 2.39.2