From 99f68ef02d1e136457c2b0fd1a375050ff965af3 Mon Sep 17 00:00:00 2001 From: Tobias Jungel Date: Fri, 2 Nov 2018 02:31:20 +0100 Subject: [PATCH] networkd: add missing bonding options (#10542) Add support for bonding options system prio, port key and actor system mac. These options exist in the linux kernel since 4.2 (torvalds/linux@171a42c38c6e1) Details: https://www.kernel.org/doc/Documentation/networking/bonding.txt --- man/systemd.netdev.xml | 21 +++++ meson.build | 2 +- src/basic/missing.h | 7 +- src/libsystemd/sd-netlink/netlink-types.c | 3 + src/network/netdev/bond.c | 130 ++++++++++++++++++++++++++++ src/network/netdev/bond.h | 7 ++ src/network/netdev/netdev-gperf.gperf | 3 + test/test-network/conf/25-bond.netdev | 5 ++ test/test-network/systemd-networkd-tests.py | 19 ++-- 9 files changed, 186 insertions(+), 11 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 971d81a..7b702e8 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -1269,6 +1269,27 @@ + AdActorSysPrio= + + Specifies the 802.3ad system priority. Ranges [1-65535]. + + + + + AdUserPortKey= + + Specifies the 802.3ad user defined portion of the port key. Ranges [0-1023]. + + + + + AdActorSystem= + + Specifies the 802.3ad system mac address. This can not be either NULL or Multicast. + + + + FailOverMACPolicy= Specifies whether the active-backup mode should set all slaves to diff --git a/meson.build b/meson.build index fcbb22b..76add43 100644 --- a/meson.build +++ b/meson.build @@ -455,7 +455,7 @@ foreach decl : [['IFLA_INET6_ADDR_GEN_MODE', 'linux/if_link.h'], ['IFLA_MACVLAN_FLAGS', 'linux/if_link.h'], ['IFLA_IPVLAN_FLAGS', 'linux/if_link.h'], ['IFLA_PHYS_PORT_ID', 'linux/if_link.h'], - ['IFLA_BOND_AD_INFO', 'linux/if_link.h'], + ['IFLA_BOND_AD_ACTOR_SYSTEM', 'linux/if_link.h'], ['IFLA_VLAN_PROTOCOL', 'linux/if_link.h'], ['IFLA_VXLAN_REMCSUM_NOPARTIAL', 'linux/if_link.h'], ['IFLA_VXLAN_GPE', 'linux/if_link.h'], diff --git a/src/basic/missing.h b/src/basic/missing.h index 648a2b9..d671202 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -752,7 +752,7 @@ struct input_mask { #define IFLA_MAX (__IFLA_MAX - 1) #endif -#if !HAVE_IFLA_BOND_AD_INFO +#if !HAVE_IFLA_BOND_AD_ACTOR_SYSTEM #define IFLA_BOND_UNSPEC 0 #define IFLA_BOND_MODE 1 #define IFLA_BOND_ACTIVE_SLAVE 2 @@ -777,7 +777,10 @@ struct input_mask { #define IFLA_BOND_AD_LACP_RATE 21 #define IFLA_BOND_AD_SELECT 22 #define IFLA_BOND_AD_INFO 23 -#define __IFLA_BOND_MAX 24 +#define IFLA_BOND_AD_ACTOR_SYS_PRIO 24 +#define IFLA_BOND_AD_USER_PORT_KEY 25 +#define IFLA_BOND_AD_ACTOR_SYSTEM 26 +#define __IFLA_BOND_MAX 27 #define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) #endif diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 3365906..4e42ab1 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -224,6 +224,9 @@ static const NLType rtnl_link_info_data_bond_types[] = { [IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED }, + [IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BOND_AD_USER_PORT_KEY] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NETLINK_TYPE_ETHER_ADDR }, }; static const NLType rtnl_link_info_data_iptun_types[] = { diff --git a/src/network/netdev/bond.c b/src/network/netdev/bond.c index 5840a96..43019c3 100644 --- a/src/network/netdev/bond.c +++ b/src/network/netdev/bond.c @@ -7,6 +7,7 @@ #include "alloc-util.h" #include "conf-parser.h" +#include "ether-addr-util.h" #include "extract-word.h" #include "missing.h" #include "netdev/bond.h" @@ -284,6 +285,24 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m"); } + if (b->ad_actor_sys_prio != 0) { + r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_ACTOR_SYS_PRIO, b->ad_actor_sys_prio); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYS_PRIO attribute: %m"); + } + + if (b->ad_user_port_key != 0) { + r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_USER_PORT_KEY, b->ad_user_port_key); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_USER_PORT_KEY attribute: %m"); + } + + if (b->ad_actor_system) { + r = sd_netlink_message_append_ether_addr(m, IFLA_BOND_AD_ACTOR_SYSTEM, b->ad_actor_system); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYSTEM attribute: %m"); + } + r = sd_netlink_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m"); @@ -371,6 +390,115 @@ int config_parse_arp_ip_target_address(const char *unit, return 0; } +int config_parse_ad_actor_sys_prio(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) { + Bond *b = userdata; + uint16_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse actor system priority '%s', ignoring: %m", rvalue); + return 0; + } + + if (v == 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse actor system priority '%s'. Range is [1,65535], ignoring: %m", rvalue); + return 0; + } + + b->ad_actor_sys_prio = v; + + return 0; +} + +int config_parse_ad_user_port_key(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) { + Bond *b = userdata; + uint16_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse user port key '%s', ignoring: %m", rvalue); + return 0; + } + + if (v > 1023) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse user port key '%s'. Range is [0,1023], ignoring: %m", rvalue); + return 0; + } + + b->ad_user_port_key = v; + + return 0; +} + +int config_parse_ad_actor_system(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) { + Bond *b = userdata; + _cleanup_free_ struct ether_addr *n = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + n = new0(struct ether_addr, 1); + if (!n) + return log_oom(); + + r = ether_addr_from_string(rvalue, n); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address %s. Ignoring assignment: %m", rvalue); + return 0; + } + + if (ether_addr_is_null(n) || (n->ether_addr_octet[0] & 0x01)) { + log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address %s, can not be null or multicast. Ignoring assignment: %m", rvalue); + return 0; + } + + free_and_replace(b->ad_actor_system, n); + + return 0; +} + static void bond_done(NetDev *netdev) { ArpIpTarget *t = NULL, *n = NULL; Bond *b; @@ -381,6 +509,8 @@ static void bond_done(NetDev *netdev) { assert(b); + free(b->ad_actor_system); + LIST_FOREACH_SAFE(arp_ip_target, t, n, b->arp_ip_targets) free(t); diff --git a/src/network/netdev/bond.h b/src/network/netdev/bond.h index be03d72..ce6e8ca 100644 --- a/src/network/netdev/bond.h +++ b/src/network/netdev/bond.h @@ -106,6 +106,10 @@ typedef struct Bond { unsigned num_grat_arp; unsigned min_links; + uint16_t ad_actor_sys_prio; + uint16_t ad_user_port_key; + struct ether_addr *ad_actor_system; + usec_t miimon; usec_t updelay; usec_t downdelay; @@ -152,3 +156,6 @@ int config_parse_bond_arp_validate(const char *unit, const char *filename, unsig int config_parse_bond_arp_all_targets(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); int config_parse_bond_primary_reselect(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); int config_parse_arp_ip_target_address(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); +int config_parse_ad_actor_sys_prio(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); +int config_parse_ad_user_port_key(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); +int config_parse_ad_actor_system(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); diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 96c8fb1..f754f23 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -141,6 +141,9 @@ Bond.UpDelaySec, config_parse_sec, 0, Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay) Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval) Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval) +Bond.AdActorSysPrio, config_parse_ad_actor_sys_prio, 0, offsetof(Bond, ad_actor_sys_prio) +Bond.AdUserPortKey, config_parse_ad_user_port_key, 0, offsetof(Bond, ad_user_port_key) +Bond.AdActorSystem, config_parse_ad_actor_system, 0, offsetof(Bond, ad_actor_system) Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time) Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age) Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time) diff --git a/test/test-network/conf/25-bond.netdev b/test/test-network/conf/25-bond.netdev index 1059910..61c54c4 100644 --- a/test/test-network/conf/25-bond.netdev +++ b/test/test-network/conf/25-bond.netdev @@ -11,3 +11,8 @@ UpDelaySec=2s DownDelaySec=2s ResendIGMP=4 MinLinks=1 +AdActorSysPrio=1218 +AdUserPortKey=811 +AdActorSystem=00:11:22:33:44:55 +# feed the sanitizer +AdActorSystem=00:11:22:33:44:55 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index fc347c6..a0db6ee 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -173,14 +173,17 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertTrue(self.link_exits('bond99')) - self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode')) - self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy')) - self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon')) - self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate')) - self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay')) - self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay')) - self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp')) - self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links')) + self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode')) + self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy')) + self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon')) + self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate')) + self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay')) + self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay')) + self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp')) + self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links')) + self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio')) + self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key')) + self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system')) def test_vlan(self): self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network') -- 2.7.4