From bfc474a8241a0139618eff06719c80127b863720 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Fri, 2 Sep 2022 17:17:54 +0200 Subject: [PATCH] bond: fix primary bond option when the link is not present Bond option netlink support requires primary property to be a ifindex instead of the interface name. This is a workaround for supporting specifying a primary that does not exist yet. ``` nmcli con add type bond ifname mybond0 bond.options "mode=active-backup,primary=veth1" Connection 'bond-mybond0' (38100ef9-11e2-4003-aff9-cb2d152ce34f) successfully added. cat /sys/class/net/mybond0/bonding/primary ip link add veth1 type veth peer veth1p ip link set veth1 up ip link set veth1p up nmcli con add type ethernet ifname veth1 master mybond0 Connection 'bond-slave-veth1' (24c8f7c4-5a50-4634-aec1-9df0da6d597a) successfully added. nmcli c up bond-slave-veth1 Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3) nmcli c NAME UUID TYPE DEVICE bond-mybond0 38100ef9-11e2-4003-aff9-cb2d152ce34f bond mybond0 bond-slave-veth1 24c8f7c4-5a50-4634-aec1-9df0da6d597a ethernet veth1 cat /sys/class/net/mybond0/bonding/primary veth1 ``` Fixes: e064eb9 ('bond: use netlink to set bond options') --- src/core/devices/nm-device-bond.c | 82 ++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 558f8f7598..447785c510 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -58,8 +58,13 @@ /*****************************************************************************/ +typedef struct { + bool missing_primary; +} NMDeviceBondPrivate; + struct _NMDeviceBond { - NMDevice parent; + NMDevice parent; + NMDeviceBondPrivate _priv; }; struct _NMDeviceBondClass { @@ -68,6 +73,9 @@ struct _NMDeviceBondClass { G_DEFINE_TYPE(NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE) +#define NM_DEVICE_BOND_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDeviceBond, NM_IS_DEVICE_BOND, NMDevice) + /*****************************************************************************/ static NMDeviceCapabilities @@ -465,15 +473,25 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p props->tlb_dynamic_lb_has = NM_IN_SET(props->mode, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB); } +static gboolean +_check_primary_missing(NMPlatformLnkBond *props, NMSettingBond *s_bond) +{ + /* checks if the ifindex is 0 but the primary option string is set */ + return !_setting_bond_primary_opt_as_ifindex(s_bond) + && nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_PRIMARY); +} + static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - NMConnection *connection; - NMSettingBond *s_bond; - NMPlatformLnkBond props; - int r; - int ifindex = nm_device_get_ifindex(device); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMDeviceBond *self = NM_DEVICE_BOND(device); + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE(self); + NMConnection *connection; + NMSettingBond *s_bond; + NMPlatformLnkBond props; + int r; + int ifindex = nm_device_get_ifindex(device); connection = nm_device_get_applied_connection(device); g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); @@ -482,6 +500,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) g_return_val_if_fail(s_bond, NM_ACT_STAGE_RETURN_FAILURE); _platform_lnk_bond_init_from_setting(s_bond, &props); + priv->missing_primary = _check_primary_missing(&props, s_bond); /* Interface must be down to set bond options */ nm_device_take_down(device, TRUE); @@ -529,11 +548,45 @@ attach_port(NMDevice *device, NMDeviceAttachPortCallback callback, gpointer user_data) { - NMDeviceBond *self = NM_DEVICE_BOND(device); - NMSettingBondPort *s_port; + NMDeviceBond *self = NM_DEVICE_BOND(device); + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE(self); + NMSettingBondPort *s_port; nm_device_master_check_slave_physical_port(device, port, LOGD_BOND); + if (priv->missing_primary) { + NMSettingBond *s_bond; + NMConnection *conn_bond; + + conn_bond = nm_device_get_applied_connection(device); + if (conn_bond) { + s_bond = nm_connection_get_setting_bond(conn_bond); + if (s_bond) { + /* mode is a mandatory property */ + int r; + int ifindex; + NMPlatformLnkBond props = { + .mode = _nm_setting_bond_mode_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE)), + }; + + ifindex = _setting_bond_primary_opt_as_ifindex(s_bond); + if (ifindex) { + props.primary = ifindex; + r = nm_platform_link_bond_change(nm_device_get_platform(device), + nm_device_get_ip_ifindex(device), + &props); + if (r < 0) + _LOGW(LOGD_BOND, + "setting bond opts when attaching port %s: failed", + nm_device_get_ip_iface(port)); + else + priv->missing_primary = FALSE; + } + } + } + } + if (configure) { gboolean success; @@ -631,10 +684,12 @@ create_and_realize(NMDevice *device, const NMPlatformLink **out_plink, GError **error) { - const char *iface = nm_device_get_iface(device); - NMSettingBond *s_bond; - NMPlatformLnkBond props; - int r; + const char *iface = nm_device_get_iface(device); + NMDeviceBond *self = NM_DEVICE_BOND(device); + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE(self); + NMSettingBond *s_bond; + NMPlatformLnkBond props; + int r; g_assert(iface); @@ -642,6 +697,7 @@ create_and_realize(NMDevice *device, nm_assert(s_bond); _platform_lnk_bond_init_from_setting(s_bond, &props); + priv->missing_primary = _check_primary_missing(&props, s_bond); r = nm_platform_link_bond_add(nm_device_get_platform(device), iface, &props, out_plink); if (r < 0) {