From f1a69d5accfd566c5af0210115f4b4a9743425ee Mon Sep 17 00:00:00 2001 From: Jian Zhang Date: Fri, 2 Dec 2022 20:08:38 +0800 Subject: [PATCH 1/2] network: Fix set bond device MAC address failed Issue: When device is in bond mode and booting up, there is a probability of set bond MAC address failed due to `Device or resource busy` error. In systemd-networkd, set MAC address steps are: 1. Try to set MAC address to device. 2. If failed with `Device or resource busy`, then `Down` the device. 3. Try to set MAC address to device again. Currently, Even down the bond device, the bond device is still return `Device or resource busy` error. So the MAC address set failed. The root cause is that this not enough to down the bond device. We need to down all the slaves of the bond device. About this descprition, we could use those commands to check: ```shell We have two network devices: eth0, bond1, eth0 is slave of bond1. They are all up. 1. Down bond1, and set MAC address to bond1. ~# ip link set bond1 down ~# ip link set bond1 address 00:11:22:33:44:55 ip: SIOCSIFHWADDR: Device or resource busy 2. Down eth0, and set MAC address to bond1. ~# ip link set eth0 down ~# ip link set bond1 address 00:11:22:33:44:55 Set okay. ``` Fix: When setting the mac for the second time, if the device kind is bond, then we need to down the slave devices of bond device. Tested: Verified in a long time test( reboot cycles ). Fixes: #25627 Signed-off-by: Jian Zhang --- src/network/networkd-setlink.c | 23 +++++++++++++++++++++++ src/network/networkd-setlink.h | 1 + 2 files changed, 24 insertions(+) diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index b6aaa1e9db..541c4b8a72 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -502,6 +502,14 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { r = link_down_now(link); if (r < 0) return r; + + /* If the kind of the link is "bond", we need + * set the slave link down as well. */ + if (streq_ptr(link->kind, "bond")) { + r = link_down_slave_links(link); + if (r < 0) + return r; + } } break; @@ -1226,6 +1234,21 @@ int link_down_now(Link *link) { return 0; } +int link_down_slave_links(Link *link) { + Link *slave; + int r; + + assert(link); + + SET_FOREACH(slave, link->slaves) { + r = link_down_now(slave); + if (r < 0) + return r; + } + + return 0; +} + static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 7e5ba32ef1..841e5eeb9c 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -25,4 +25,5 @@ int link_request_to_activate(Link *link); int link_request_to_bring_up_or_down(Link *link, bool up); int link_down_now(Link *link); +int link_down_slave_links(Link *link); int link_remove(Link *link); From 23b6bf274fc1a46d8778bfc979d3c803d61a1f5c Mon Sep 17 00:00:00 2001 From: Jian Zhang Date: Mon, 5 Dec 2022 18:38:00 +0800 Subject: [PATCH 2/2] test-network: add test for bond mac address config Signed-off-by: Jian Zhang --- test/test-network/conf/23-bond199.network | 3 +++ test/test-network/systemd-networkd-tests.py | 1 + 2 files changed, 4 insertions(+) diff --git a/test/test-network/conf/23-bond199.network b/test/test-network/conf/23-bond199.network index 9f4879ff24..6a1f9a1bc7 100644 --- a/test/test-network/conf/23-bond199.network +++ b/test/test-network/conf/23-bond199.network @@ -4,3 +4,6 @@ Name=bond199 [Network] IPv6AcceptRA=no + +[Link] +MACAddress=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 e4e92d5a37..398ece8297 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3881,6 +3881,7 @@ class NetworkdBondTests(unittest.TestCase, Utilities): output = check_output('ip -d link show bond199') print(output) self.assertRegex(output, 'primary dummy98') + self.assertIn('link/ether 00:11:22:33:44:55', output) def test_bond_operstate(self): copy_network_unit('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',