Blob Blame History Raw
From 03c3c716f67874c5b97fd53155e91ceeeb49ed79 Mon Sep 17 00:00:00 2001
From: Marius Tomaschewski <mt@suse.de>
Date: Mon, 30 Jan 2023 18:48:31 +0100
Subject: [PATCH] bond: workaround 6.1 enslave regression (boo#1206674)
References: boo#1206674, https://github.com/openSUSE/wicked/pull/952
Upstream: yes

The kernel bonding accepts only enslave of interfaces in DOWN state
and the bonding driver sets the slave UP itself after enslave, once
it also inherited MTU, MAC address, ... to the slave as needed.

All kernels between (at least) 4.12 up to 6.0 accepted to enslave
using a single `ip link set down master bond0 dev eth0` rtnetlink
message, which ensured that the (eth0) interface to enslave were
set down if needed and wasn't rejected to enslave.

Since kernel 6.1 (commit a4abfa627c3865c37e036bccb681619a50d3d93c)
the enslave processing changed and the `down` flag in the enslave
message is applied after enslave, causing that the UP flag added
by enslave is removed again, the slave remains inactive and is not
used by the bond, which remains in a no-carrier state.

Changed to not pass the DOWN flag any more, but enslave only.

diff --git a/src/ifconfig.c b/src/ifconfig.c
index a3db731f..d873a6b0 100644
--- a/src/ifconfig.c
+++ b/src/ifconfig.c
@@ -127,7 +127,7 @@ static int	__ni_rtnl_link_unenslave(const ni_netdev_t *);
 static int	__ni_rtnl_link_delete(const ni_netdev_t *);
 
 static int	__ni_rtnl_link_add_port_up(const ni_netdev_t *, const char *, unsigned int);
-static int	__ni_rtnl_link_add_slave_down(const ni_netdev_t *, const char *, unsigned int);
+static int	__ni_rtnl_link_bond_enslave(const ni_netdev_t *, const char *, unsigned int);
 
 static int	__ni_rtnl_send_deladdr(ni_netdev_t *, const ni_address_t *);
 static int	__ni_rtnl_send_newaddr(ni_netdev_t *, const ni_address_t *, int);
@@ -207,7 +207,7 @@ ni_system_interface_enslave(ni_netconfig_t *nc, ni_netdev_t *master, ni_netdev_t
 		if (dev->link.masterdev.index)
 			return 0;
 
-		ret = __ni_rtnl_link_add_slave_down(dev, master->name,
+		ret = __ni_rtnl_link_bond_enslave(dev, master->name,
 						master->link.ifindex);
 		if (ret == 0) {
 			ni_netdev_ref_set(&dev->link.masterdev,
@@ -4021,10 +4021,10 @@ failed:
 }
 
 /*
- * Bring down an interface and enslave (bond slave) to master
+ * Enslave into a bond master
  */
 int
-__ni_rtnl_link_add_slave_down(const ni_netdev_t *slave, const char *mname, unsigned int mindex)
+__ni_rtnl_link_bond_enslave(const ni_netdev_t *slave, const char *mname, unsigned int mindex)
 {
 	struct ifinfomsg ifi;
 	struct nl_msg *msg;
@@ -4035,7 +4035,6 @@ __ni_rtnl_link_add_slave_down(const ni_netdev_t *slave, const char *mname, unsig
 	memset(&ifi, 0, sizeof(ifi));
 	ifi.ifi_family = AF_UNSPEC;
 	ifi.ifi_index = slave->link.ifindex;
-	ifi.ifi_change = IFF_UP;
 
 	msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST);
 	if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
-- 
2.35.3