networkd: add missing bonding options (#10542)
authorTobias Jungel <Tobias.Jungel@gmail.com>
Fri, 2 Nov 2018 01:31:20 +0000 (02:31 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 2 Nov 2018 01:31:20 +0000 (10:31 +0900)
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
meson.build
src/basic/missing.h
src/libsystemd/sd-netlink/netlink-types.c
src/network/netdev/bond.c
src/network/netdev/bond.h
src/network/netdev/netdev-gperf.gperf
test/test-network/conf/25-bond.netdev
test/test-network/systemd-networkd-tests.py

index 971d81a..7b702e8 100644 (file)
       </varlistentry>
 
       <varlistentry>
+        <term><varname>AdActorSysPrio=</varname></term>
+        <listitem>
+          <para>Specifies the 802.3ad system priority. Ranges [1-65535].</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>AdUserPortKey=</varname></term>
+        <listitem>
+          <para>Specifies the 802.3ad user defined portion of the port key. Ranges [0-1023].</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>AdActorSystem=</varname></term>
+        <listitem>
+          <para>Specifies the 802.3ad system mac address. This can not be either NULL or Multicast.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><varname>FailOverMACPolicy=</varname></term>
         <listitem>
           <para>Specifies whether the active-backup mode should set all slaves to
index fcbb22b..76add43 100644 (file)
@@ -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'],
index 648a2b9..d671202 100644 (file)
@@ -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
index 3365906..4e42ab1 100644 (file)
@@ -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[] = {
index 5840a96..43019c3 100644 (file)
@@ -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);
 
index be03d72..ce6e8ca 100644 (file)
@@ -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);
index 96c8fb1..f754f23 100644 (file)
@@ -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)
index 1059910..61c54c4 100644 (file)
@@ -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
index fc347c6..a0db6ee 100755 (executable)
@@ -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')