]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: Add bridge port priority setting (#5545)
authorDimitri John Ledkov <xnox@ubuntu.com>
Tue, 11 Apr 2017 21:17:31 +0000 (22:17 +0100)
committerMartin Pitt <martinpitt@users.noreply.github.com>
Tue, 11 Apr 2017 21:17:31 +0000 (23:17 +0200)
Allow setting bridge port priority in the Bridge section of the network file,
similar to e.g. port path cost setting.

Set the default to an invalid value of 128, and only set the port priority when
it's not 128. Unlike e.g. path cost, zero is a valid priority value.

Add a networkd-test.py to check that bridge port priority is correctly set.

Incidently, fix bridge port cost type and document valid ranges.

man/systemd.network.xml
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/networkd-test.py

index 61bed263e51f72088942d8792371cf2fa7eb1792..971dee338fa097346cb4c1739870e696be13acfa 100644 (file)
             <para>Sets the "cost" of sending packets of this interface.
             Each port in a bridge may have a different speed and the cost
             is used to decide which link to use. Faster interfaces
-            should have lower costs.</para>
+            should have lower costs. It is an interger value between 1 and
+            65535.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>Priority=</varname></term>
+          <listitem>
+            <para>Sets the "priority" of sending packets on this interface.
+            Each port in a bridge may have a different priority which is used
+            to decide which link to use. Lower value means higher priority.
+            It is an interger value between 0 to 63. Networkd does not set any
+            default, meaning the kernel default value of 32 is used.</para>
           </listitem>
         </varlistentry>
       </variablelist>
index 0c1229336b87c8d4b8db7e106ef504e2d68f0af1..1797f144b68cfef4953a86fdf4353fb541afef83 100644 (file)
@@ -1325,6 +1325,11 @@ static int link_set_bridge(Link *link) {
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
         }
+        if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
+                r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
+        }
 
         r = sd_netlink_message_close_container(req);
         if (r < 0)
index e6190fbe576409ff5b59018889ae38d7ad5e60e0..010b38248a2d32466d03346f68ca1af911c1153c 100644 (file)
@@ -33,6 +33,8 @@
 #include "list.h"
 #include "set.h"
 
+#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
+
 typedef enum LinkState {
         LINK_STATE_PENDING,
         LINK_STATE_ENSLAVING,
index 68052ba54439840b2bac6dc3a8b20db51d160653..9658978651467a2bb8b3782194d9bb059cc2cf03 100644 (file)
@@ -119,12 +119,13 @@ DHCPServer.EmitTimezone,                config_parse_bool,
 DHCPServer.Timezone,                    config_parse_timezone,                          0,                             offsetof(Network, dhcp_server_timezone)
 DHCPServer.PoolOffset,                  config_parse_uint32,                            0,                             offsetof(Network, dhcp_server_pool_offset)
 DHCPServer.PoolSize,                    config_parse_uint32,                            0,                             offsetof(Network, dhcp_server_pool_size)
-Bridge.Cost,                            config_parse_unsigned,                          0,                             offsetof(Network, cost)
+Bridge.Cost,                            config_parse_uint32,                            0,                             offsetof(Network, cost)
 Bridge.UseBPDU,                         config_parse_bool,                              0,                             offsetof(Network, use_bpdu)
 Bridge.HairPin,                         config_parse_bool,                              0,                             offsetof(Network, hairpin)
 Bridge.FastLeave,                       config_parse_bool,                              0,                             offsetof(Network, fast_leave)
 Bridge.AllowPortToBeRoot,               config_parse_bool,                              0,                             offsetof(Network, allow_port_to_be_root)
 Bridge.UnicastFlood,                    config_parse_bool,                              0,                             offsetof(Network, unicast_flood)
+Bridge.Priority,                        config_parse_uint16,                            0,                             offsetof(Network, priority)
 BridgeFDB.MACAddress,                   config_parse_fdb_hwaddr,                        0,                             0
 BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,                       0,                             0
 BridgeVLAN.PVID,                        config_parse_brvlan_pvid,                       0,                             0
index fac42d8478fc6e7b9fcabcb8405061e4d14f248a..dd29b4ca480188100c18a3b5a6f7dffc36a0633a 100644 (file)
@@ -165,6 +165,7 @@ static int network_load_one(Manager *manager, const char *filename) {
         network->use_bpdu = true;
         network->allow_port_to_be_root = true;
         network->unicast_flood = true;
+        network->priority = LINK_BRIDGE_PORT_PRIORITY_INVALID;
 
         network->lldp_mode = LLDP_MODE_ROUTERS_ONLY;
 
index 4ce066a76463b16091eba7786b27cec7884bb5fa..d6f418d521f621219b6ff306e974133961395f7b 100644 (file)
@@ -163,7 +163,8 @@ struct Network {
         bool fast_leave;
         bool allow_port_to_be_root;
         bool unicast_flood;
-        unsigned cost;
+        uint32_t cost;
+        uint16_t priority;
 
         bool use_br_vlan;
         uint16_t pvid;
index e0dddeb05389bc8cc734b3a9309c595bb3f81384..eee8b65ec01050a8cebcac618228e54398033d41 100755 (executable)
@@ -96,10 +96,20 @@ class NetworkdTestingUtilities:
         dropin_path = os.path.join(dropin_dir, "%s.conf" % dropin_name)
 
         os.makedirs(dropin_dir, exist_ok=True)
+        self.addCleanup(os.rmdir, dropin_dir)
         with open(dropin_path, 'w') as dropin:
             dropin.write(contents)
         self.addCleanup(os.remove, dropin_path)
 
+    def read_attr(self, link, attribute):
+        """Read a link attributed from the sysfs."""
+        # Note we we don't want to check if interface `link' is managed, we
+        # want to evaluate link variable and pass the value of the link to
+        # assert_link_states e.g. eth0=managed.
+        self.assert_link_states(**{link:'managed'})
+        with open(os.path.join('/sys/class/net', link, attribute)) as f:
+            return f.readline().strip()
+
     def assert_link_states(self, **kwargs):
         """Match networkctl link states to the given ones.
 
@@ -140,6 +150,74 @@ class NetworkdTestingUtilities:
             self.fail("Missing links in status output: %s" % interfaces)
 
 
+class BridgeTest(NetworkdTestingUtilities, unittest.TestCase):
+    """Provide common methods for testing networkd against servers."""
+
+    def setUp(self):
+        self.write_network('port1.netdev', '''\
+[NetDev]
+Name=port1
+Kind=dummy
+MACAddress=12:34:56:78:9a:bc''')
+        self.write_network('port2.netdev', '''\
+[NetDev]
+Name=port2
+Kind=dummy
+MACAddress=12:34:56:78:9a:bd''')
+        self.write_network('mybridge.netdev', '''\
+[NetDev]
+Name=mybridge
+Kind=bridge''')
+        self.write_network('port1.network', '''\
+[Match]
+Name=port1
+[Network]
+Bridge=mybridge''')
+        self.write_network('port2.network', '''\
+[Match]
+Name=port2
+[Network]
+Bridge=mybridge''')
+        self.write_network('mybridge.network', '''\
+[Match]
+Name=mybridge
+[Network]
+DNS=192.168.250.1
+Address=192.168.250.33/24
+Gateway=192.168.250.1''')
+        subprocess.check_call(['systemctl', 'start', 'systemd-networkd'])
+
+    def tearDown(self):
+        subprocess.check_call(['systemctl', 'stop', 'systemd-networkd'])
+        subprocess.check_call(['ip', 'link', 'del', 'mybridge'])
+        subprocess.check_call(['ip', 'link', 'del', 'port1'])
+        subprocess.check_call(['ip', 'link', 'del', 'port2'])
+
+    def test_bridge_init(self):
+        self.assert_link_states(
+            port1='managed',
+            port2='managed',
+            mybridge='managed')
+
+    def test_bridge_port_priority(self):
+        self.assertEqual(self.read_attr('port1', 'brport/priority'), '32')
+        self.write_network_dropin('port1.network', 'priority', '''\
+[Bridge]
+Priority=28
+''')
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
+        self.assertEqual(self.read_attr('port1', 'brport/priority'), '28')
+
+    def test_bridge_port_priority_set_zero(self):
+        """It should be possible to set the bridge port priority to 0"""
+        self.assertEqual(self.read_attr('port2', 'brport/priority'), '32')
+        self.write_network_dropin('port2.network', 'priority', '''\
+[Bridge]
+Priority=0
+''')
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
+        self.assertEqual(self.read_attr('port2', 'brport/priority'), '0')
+
 class ClientTestBase(NetworkdTestingUtilities):
     """Provide common methods for testing networkd against servers."""