summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2017-04-11 22:17:31 +0100
committerMartin Pitt <martinpitt@users.noreply.github.com>2017-04-11 23:17:31 +0200
commitb56be2966a8a8bcc2432e37370bad5381498a819 (patch)
tree79083431600346ae3c1910f142b60d1948d40f7a
parentc618423a5aacb0378985f6d49d31be65866ab79a (diff)
downloadsystemd-b56be2966a8a8bcc2432e37370bad5381498a819.tar.gz
networkd: Add bridge port priority setting (#5545)
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.
-rw-r--r--man/systemd.network.xml13
-rw-r--r--src/network/networkd-link.c5
-rw-r--r--src/network/networkd-link.h2
-rw-r--r--src/network/networkd-network-gperf.gperf3
-rw-r--r--src/network/networkd-network.c1
-rw-r--r--src/network/networkd-network.h3
-rwxr-xr-xtest/networkd-test.py78
7 files changed, 102 insertions, 3 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 61bed263e5..971dee338f 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1257,7 +1257,18 @@
<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>
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0c1229336b..1797f144b6 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -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)
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index e6190fbe57..010b38248a 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -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,
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 68052ba544..9658978651 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -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
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index fac42d8478..dd29b4ca48 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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;
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 4ce066a764..d6f418d521 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -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;
diff --git a/test/networkd-test.py b/test/networkd-test.py
index e0dddeb053..eee8b65ec0 100755
--- a/test/networkd-test.py
+++ b/test/networkd-test.py
@@ -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."""