diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 1e65fa45b0..853e1b6c1b 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -40,7 +40,7 @@ NM_SETTING_BOND_OPTION_RESEND_IGMP, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, \ NM_SETTING_BOND_OPTION_USE_CARRIER, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, \ NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, \ - NM_SETTING_BOND_OPTION_ARP_MISSED_MAX + NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, NM_SETTING_BOND_OPTION_LACP_ACTIVE #define OPTIONS_REAPPLY_SUBSET \ NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_UPDELAY, \ @@ -52,7 +52,8 @@ NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, \ NM_SETTING_BOND_OPTION_RESEND_IGMP, NM_SETTING_BOND_OPTION_USE_CARRIER, \ NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, \ - NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX + NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, \ + NM_SETTING_BOND_OPTION_LACP_ACTIVE #define OPTIONS_REAPPLY_FULL \ OPTIONS_REAPPLY_SUBSET, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, \ @@ -439,6 +440,9 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p .num_grat_arp = _v_u8(s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP), .all_ports_active = _v_u8(s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE), .arp_missed_max = _v_u8(s_bond, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX), + .lacp_active = _v_fcn(_nm_setting_bond_lacp_active_from_string, + s_bond, + NM_SETTING_BOND_OPTION_LACP_ACTIVE), .lacp_rate = _v_fcn(_nm_setting_bond_lacp_rate_from_string, s_bond, NM_SETTING_BOND_OPTION_LACP_RATE), @@ -465,6 +469,7 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p props->resend_igmp_has = props->resend_igmp != 1; props->lp_interval_has = props->lp_interval != 1; props->tlb_dynamic_lb_has = NM_IN_SET(props->mode, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB); + props->lacp_active_has = NM_IN_SET(props->mode, NM_BOND_MODE_8023AD); } static void diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.c b/src/libnm-core-aux-intern/nm-libnm-core-utils.c index c4bfd2bd73..5ccb5e400e 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.c +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.c @@ -86,6 +86,20 @@ NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"follow", NM_BOND_FAIL_OVER_MAC_FOLLOW}, {"none", NM_BOND_FAIL_OVER_MAC_NONE}, ); +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + _nm_setting_bond_lacp_active_from_string, + NMBondLacpActive, + { + G_STATIC_ASSERT_EXPR(_NM_BOND_LACP_ACTIVE_NUM <= 2); + + if (name && name[0] < '0' + _NM_BOND_LACP_ACTIVE_NUM && name[0] >= '0' && name[1] == '\0') { + return name[0] - '0'; + } + }, + { return NM_BOND_LACP_ACTIVE_ON; }, + {"off", NM_BOND_LACP_ACTIVE_OFF}, + {"on", NM_BOND_LACP_ACTIVE_ON}, ); + NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( _nm_setting_bond_lacp_rate_from_string, NMBondLacpRate, diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.h b/src/libnm-core-aux-intern/nm-libnm-core-utils.h index 18af1e1a1c..79ddfbbcc7 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.h +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.h @@ -95,6 +95,18 @@ typedef enum { NMBondFailOverMac _nm_setting_bond_fail_over_mac_from_string(const char *str); +typedef enum { + NM_BOND_LACP_ACTIVE_UNKNOWN = -1, + + /* The numeric values correspond to kernel's numbering. */ + NM_BOND_LACP_ACTIVE_OFF = 0, + NM_BOND_LACP_ACTIVE_ON = 1, + + _NM_BOND_LACP_ACTIVE_NUM, +} NMBondLacpActive; + +NMBondLacpActive _nm_setting_bond_lacp_active_from_string(const char *str); + typedef enum { NM_BOND_LACP_RATE_UNKNOWN = -1, diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c index cc65598fab..5367f5230c 100644 --- a/src/libnm-core-impl/nm-setting-bond.c +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -93,6 +93,7 @@ static const char *const valid_options_lst[] = { NM_SETTING_BOND_OPTION_LP_INTERVAL, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, + NM_SETTING_BOND_OPTION_LACP_ACTIVE, NULL, }; @@ -155,8 +156,9 @@ static char const *const _option_default_strv_arp_validate[] = NM_MAKE_STRV("none", "active", "backup", "all", "filter", "filter_active", "filter_backup"); static char const *const _option_default_strv_fail_over_mac[] = NM_MAKE_STRV("none", "active", "follow"); -static char const *const _option_default_strv_lacp_rate[] = NM_MAKE_STRV("slow", "fast"); -static char const *const _option_default_strv_mode[] = NM_MAKE_STRV("balance-rr", +static char const *const _option_default_strv_lacp_rate[] = NM_MAKE_STRV("slow", "fast"); +static char const *const _option_default_strv_lacp_active[] = NM_MAKE_STRV("off", "on"); +static char const *const _option_default_strv_mode[] = NM_MAKE_STRV("balance-rr", "active-backup", "balance-xor", "broadcast", @@ -202,6 +204,8 @@ static NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE( {NM_SETTING_BOND_OPTION_DOWNDELAY, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, {NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_fail_over_mac}}, + {NM_SETTING_BOND_OPTION_LACP_ACTIVE, + {"on", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_lacp_active}}, {NM_SETTING_BOND_OPTION_LACP_RATE, {"slow", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_lacp_rate}}, {NM_SETTING_BOND_OPTION_LP_INTERVAL, {"1", NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT}}, @@ -855,6 +859,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) const char *mode_str; const char *arp_ip_target = NULL; const char *lacp_rate; + const char *lacp_active; const char *primary; const char *s; NMBondMode bond_mode; @@ -1085,6 +1090,18 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + lacp_active = _bond_get_option(self, NM_SETTING_BOND_OPTION_LACP_ACTIVE); + if (lacp_active && bond_mode != NM_BOND_MODE_8023AD) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is only valid with mode '%s'"), + NM_SETTING_BOND_OPTION_LACP_RATE, + "802.3ad"); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + if (_bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP) && _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA) && num_grat_arp != num_unsol_na) { diff --git a/src/libnm-core-public/nm-setting-bond.h b/src/libnm-core-public/nm-setting-bond.h index 16e11f0151..1e653abcfa 100644 --- a/src/libnm-core-public/nm-setting-bond.h +++ b/src/libnm-core-public/nm-setting-bond.h @@ -59,6 +59,7 @@ G_BEGIN_DECLS #define NM_SETTING_BOND_OPTION_LP_INTERVAL "lp_interval" #define NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY "peer_notif_delay" #define NM_SETTING_BOND_OPTION_ARP_MISSED_MAX "arp_missed_max" +#define NM_SETTING_BOND_OPTION_LACP_ACTIVE "lacp_active" typedef struct _NMSettingBondClass NMSettingBondClass; diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 2b26494663..9c9987bbba 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -180,6 +180,7 @@ G_STATIC_ASSERT(RTA_MAX == (__RTA_MAX - 1)); /*****************************************************************************/ #define IFLA_BOND_PEER_NOTIF_DELAY 28 +#define IFLA_BOND_AD_LACP_ACTIVE 29 #define IFLA_BOND_MISSED_MAX 30 #undef IFLA_BOND_MAX @@ -1608,6 +1609,7 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) [IFLA_BOND_TLB_DYNAMIC_LB] = {.type = NLA_U8}, [IFLA_BOND_PEER_NOTIF_DELAY] = {.type = NLA_U32}, [IFLA_BOND_MISSED_MAX] = {.type = NLA_U8}, + [IFLA_BOND_AD_LACP_ACTIVE] = {.type = NLA_U8}, }; NMPlatformLnkBond *props; struct nlattr *tb[G_N_ELEMENTS(policy)]; @@ -1692,6 +1694,10 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) props->packets_per_port = nla_get_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]); if (tb[IFLA_BOND_AD_LACP_RATE]) props->lacp_rate = nla_get_u8(tb[IFLA_BOND_AD_LACP_RATE]); + if (tb[IFLA_BOND_AD_LACP_ACTIVE]) { + props->lacp_active = nla_get_u8(tb[IFLA_BOND_AD_LACP_ACTIVE]); + props->lacp_active_has = TRUE; + } if (tb[IFLA_BOND_AD_SELECT]) props->ad_select = nla_get_u8(tb[IFLA_BOND_AD_SELECT]); if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) @@ -4747,6 +4753,8 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo NLA_PUT_U8(msg, IFLA_BOND_FAIL_OVER_MAC, props->fail_over_mac); if (props->lacp_rate) NLA_PUT_U8(msg, IFLA_BOND_AD_LACP_RATE, props->lacp_rate); + if (props->lacp_active_has) + NLA_PUT_U8(msg, IFLA_BOND_AD_LACP_ACTIVE, props->lacp_active); if (props->num_grat_arp) NLA_PUT_U8(msg, IFLA_BOND_NUM_PEER_NOTIF, props->num_grat_arp); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 8692453efa..7f0e444805 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -6187,6 +6187,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le char sbuf_miimon[30]; char sbuf_updelay[30]; char sbuf_downdelay[30]; + char sbuf_lacp_active[30]; char sbuf_peer_notif_delay[60]; char sbuf_resend_igmp[30]; char sbuf_lp_interval[30]; @@ -6223,6 +6224,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le " all_ports_active %u" " arp_missed_max %u" " lacp_rate %u" + "%s" /* lacp_active */ " ad_select %u" " use_carrier %d" "%s" /* tlb_dynamic_lb */, @@ -6274,6 +6276,12 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le lnk->all_ports_active, lnk->arp_missed_max, lnk->lacp_rate, + lnk->lacp_active_has || lnk->lacp_active != 0 + ? nm_sprintf_buf(sbuf_lacp_active, + " lacp_active%s %u", + !lnk->lacp_active_has ? "?" : "", + lnk->lacp_active) + : "", lnk->ad_select, (int) lnk->use_carrier, lnk->tlb_dynamic_lb_has ? nm_sprintf_buf(sbuf_tlb_dynamic_lb, @@ -8043,12 +8051,14 @@ nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h) obj->arp_ip_targets_num, obj->fail_over_mac, obj->lacp_rate, + obj->lacp_active, obj->num_grat_arp, obj->mode, obj->primary_reselect, obj->xmit_hash_policy, NM_HASH_COMBINE_BOOLS(guint16, obj->downdelay_has, + obj->lacp_active_has, obj->lp_interval_has, obj->miimon_has, obj->peer_notif_delay_has, @@ -8090,11 +8100,13 @@ nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) NM_CMP_FIELD(a, b, arp_missed_max); NM_CMP_FIELD(a, b, fail_over_mac); NM_CMP_FIELD(a, b, lacp_rate); + NM_CMP_FIELD(a, b, lacp_active); NM_CMP_FIELD(a, b, num_grat_arp); NM_CMP_FIELD(a, b, mode); NM_CMP_FIELD(a, b, primary_reselect); NM_CMP_FIELD(a, b, xmit_hash_policy); NM_CMP_FIELD_BOOL(a, b, downdelay_has); + NM_CMP_FIELD_BOOL(a, b, lacp_active_has); NM_CMP_FIELD_BOOL(a, b, lp_interval_has); NM_CMP_FIELD_BOOL(a, b, miimon_has); NM_CMP_FIELD_BOOL(a, b, peer_notif_delay_has); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index f4202f25ab..61173a6cc2 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -785,12 +785,14 @@ typedef struct { guint8 arp_missed_max; guint8 arp_ip_targets_num; guint8 fail_over_mac; + guint8 lacp_active; guint8 lacp_rate; guint8 num_grat_arp; guint8 mode; guint8 primary_reselect; guint8 xmit_hash_policy; bool downdelay_has : 1; + bool lacp_active_has : 1; bool lp_interval_has : 1; bool miimon_has : 1; bool peer_notif_delay_has : 1;