From 8dd18d91b2c74f43ca2467245f78815bc4df5249 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Mon, 6 Mar 2023 11:34:48 +0100 Subject: [PATCH 1/5] platform: compare arp_ip_targets_num before arp_ip_target values We must first check whether a->arp_ip_targets_num and b->arp_ip_targets_num are identical. Otherwise, this accesses potentially uninitialized values. Fixes: f900f7bc2c52 ('platform: add netlink support for bond link') --- src/libnm-platform/nm-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 06c1f4a74..42b90a83f 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -8062,6 +8062,7 @@ int nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) { NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, arp_ip_targets_num); NM_CMP_FIELD_MEMCMP_LEN(a, b, arp_ip_target, @@ -8083,7 +8084,6 @@ nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) NM_CMP_FIELD_MEMCMP(a, b, ad_actor_system); NM_CMP_FIELD(a, b, ad_select); NM_CMP_FIELD(a, b, all_ports_active); - NM_CMP_FIELD(a, b, arp_ip_targets_num); NM_CMP_FIELD(a, b, fail_over_mac); NM_CMP_FIELD(a, b, lacp_rate); NM_CMP_FIELD(a, b, num_grat_arp); From ddd2fd46b022f87589ae4b1cde61f93576231e9d Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Wed, 1 Mar 2023 15:12:35 +0000 Subject: [PATCH 2/5] bonding: add support to arp_missed_max option The new arp_missed_max option valid range is 0-255 where value 0 means not set. Please notice that this option is not compatible with 802.3AD, balance-tlb and balance-alb modes. --- src/core/devices/nm-device-bond.c | 6 ++++-- src/libnm-core-impl/nm-setting-bond.c | 17 +++++++++++++++++ src/libnm-core-impl/tests/test-setting.c | 1 + src/libnm-core-public/nm-setting-bond.h | 1 + src/libnm-platform/nm-linux-platform.c | 6 ++++++ src/libnm-platform/nm-platform.c | 4 ++++ src/libnm-platform/nm-platform.h | 1 + 7 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 0b0697e3c..1e65fa45b 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -39,7 +39,8 @@ NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, \ 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_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, \ + NM_SETTING_BOND_OPTION_ARP_MISSED_MAX #define OPTIONS_REAPPLY_SUBSET \ NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_UPDELAY, \ @@ -51,7 +52,7 @@ 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_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX #define OPTIONS_REAPPLY_FULL \ OPTIONS_REAPPLY_SUBSET, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, \ @@ -437,6 +438,7 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY), .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_rate = _v_fcn(_nm_setting_bond_lacp_rate_from_string, s_bond, NM_SETTING_BOND_OPTION_LACP_RATE), diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c index 54030e0b4..cc65598fa 100644 --- a/src/libnm-core-impl/nm-setting-bond.c +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -92,6 +92,7 @@ static const char *const valid_options_lst[] = { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, NM_SETTING_BOND_OPTION_LP_INTERVAL, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, + NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, NULL, }; @@ -194,6 +195,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE( {"any", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_arp_all_targets}}, {NM_SETTING_BOND_OPTION_ARP_INTERVAL, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, {NM_SETTING_BOND_OPTION_ARP_IP_TARGET, {"", NM_BOND_OPTION_TYPE_IP}}, + {NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, {"0", NM_BOND_OPTION_TYPE_INT, 0, 255}}, {NM_SETTING_BOND_OPTION_ARP_VALIDATE, {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_arp_validate}}, {NM_SETTING_BOND_OPTION_BALANCE_SLB, {"0", NM_BOND_OPTION_TYPE_INT, 0, 1}}, @@ -846,6 +848,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(setting); int miimon; int arp_interval; + int arp_missed_max; int num_grat_arp; int num_unsol_na; int peer_notif_delay; @@ -876,6 +879,8 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) miimon = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_MIIMON)); arp_interval = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_ARP_INTERVAL)); + arp_missed_max = + _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX)); num_grat_arp = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP)); num_unsol_na = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)); peer_notif_delay = @@ -886,6 +891,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) * arp_interval conflicts [ alb, tlb ] * arp_interval needs arp_ip_target * arp_validate does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ] + * arp_missed_max does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ] * downdelay needs miimon * updelay needs miimon * peer_notif_delay needs miimon enabled @@ -929,6 +935,17 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } + if (arp_missed_max > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s=%s' is incompatible with '%s > 0'"), + NM_SETTING_BOND_OPTION_MODE, + mode_str, + NM_SETTING_BOND_OPTION_ARP_MISSED_MAX); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } } primary = _bond_get_option(self, NM_SETTING_BOND_OPTION_PRIMARY); diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index 46e681812..b30758ffa 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -5259,6 +5259,7 @@ test_bond_meta(void) _A(_nm_setting_bond_opt_value_as_u16, set, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, 0, EINVAL); _A(_nm_setting_bond_opt_value_as_u16, set, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, 0, EINVAL); _A(_nm_setting_bond_opt_value_as_u8, set, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, 1, 0); + _A(_nm_setting_bond_opt_value_as_u8, set, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, 0, 0); _A(_nm_setting_bond_opt_value_as_u8, set, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, 0, 0); _A(_nm_setting_bond_opt_value_as_intbool, set, NM_SETTING_BOND_OPTION_USE_CARRIER, 1, 0); _A(_nm_setting_bond_opt_value_as_intbool, diff --git a/src/libnm-core-public/nm-setting-bond.h b/src/libnm-core-public/nm-setting-bond.h index 10d703bca..16e11f015 100644 --- a/src/libnm-core-public/nm-setting-bond.h +++ b/src/libnm-core-public/nm-setting-bond.h @@ -58,6 +58,7 @@ G_BEGIN_DECLS #define NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB "tlb_dynamic_lb" #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" typedef struct _NMSettingBondClass NMSettingBondClass; diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 94e92a9be..2b2649466 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_MISSED_MAX 30 #undef IFLA_BOND_MAX @@ -1606,6 +1607,7 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) [IFLA_BOND_AD_ACTOR_SYSTEM] = {.minlen = sizeof(NMEtherAddr)}, [IFLA_BOND_TLB_DYNAMIC_LB] = {.type = NLA_U8}, [IFLA_BOND_PEER_NOTIF_DELAY] = {.type = NLA_U32}, + [IFLA_BOND_MISSED_MAX] = {.type = NLA_U8}, }; NMPlatformLnkBond *props; struct nlattr *tb[G_N_ELEMENTS(policy)]; @@ -1680,6 +1682,8 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) props->num_grat_arp = nla_get_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]); if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE]) props->all_ports_active = nla_get_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]); + if (tb[IFLA_BOND_MISSED_MAX]) + props->arp_missed_max = nla_get_u8(tb[IFLA_BOND_MISSED_MAX]); if (tb[IFLA_BOND_MIN_LINKS]) props->min_links = nla_get_u32(tb[IFLA_BOND_MIN_LINKS]); if (tb[IFLA_BOND_LP_INTERVAL]) @@ -4734,6 +4738,8 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo &props->ad_actor_system); if (props->ad_select) NLA_PUT_U8(msg, IFLA_BOND_AD_SELECT, props->ad_select); + if (props->arp_missed_max) + NLA_PUT_U8(msg, IFLA_BOND_MISSED_MAX, props->arp_missed_max); NLA_PUT_U8(msg, IFLA_BOND_ALL_SLAVES_ACTIVE, props->all_ports_active); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 42b90a83f..8692453ef 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -6221,6 +6221,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le " xmit_hash_policy %u" " num_gray_arp %u" " all_ports_active %u" + " arp_missed_max %u" " lacp_rate %u" " ad_select %u" " use_carrier %d" @@ -6271,6 +6272,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le lnk->xmit_hash_policy, lnk->num_grat_arp, lnk->all_ports_active, + lnk->arp_missed_max, lnk->lacp_rate, lnk->ad_select, (int) lnk->use_carrier, @@ -8037,6 +8039,7 @@ nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h) obj->ad_actor_system, obj->ad_select, obj->all_ports_active, + obj->arp_missed_max, obj->arp_ip_targets_num, obj->fail_over_mac, obj->lacp_rate, @@ -8084,6 +8087,7 @@ nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) NM_CMP_FIELD_MEMCMP(a, b, ad_actor_system); NM_CMP_FIELD(a, b, ad_select); NM_CMP_FIELD(a, b, all_ports_active); + 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, num_grat_arp); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index d816513cd..f4202f25a 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -782,6 +782,7 @@ typedef struct { NMEtherAddr ad_actor_system; guint8 ad_select; guint8 all_ports_active; + guint8 arp_missed_max; guint8 arp_ip_targets_num; guint8 fail_over_mac; guint8 lacp_rate; From 6cde20fecc4e25e085532c1b47a6c2a26a418bfd Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Thu, 2 Mar 2023 11:43:25 +0100 Subject: [PATCH 3/5] bonding: add support to lacp_active option The valid values for this option are 0 (off) and 1 (on). By default the value is 1 (on). Please notice that this option is only compatible with 802.3AD mode. --- src/core/devices/nm-device-bond.c | 9 ++++++-- .../nm-libnm-core-utils.c | 14 +++++++++++++ .../nm-libnm-core-utils.h | 12 +++++++++++ src/libnm-core-impl/nm-setting-bond.c | 21 +++++++++++++++++-- src/libnm-core-public/nm-setting-bond.h | 1 + src/libnm-platform/nm-linux-platform.c | 8 +++++++ src/libnm-platform/nm-platform.c | 12 +++++++++++ src/libnm-platform/nm-platform.h | 2 ++ 8 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 1e65fa45b..853e1b6c1 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 c4bfd2bd7..5ccb5e400 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 18af1e1a1..79ddfbbcc 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 cc65598fa..5367f5230 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 16e11f015..1e653abcf 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 2b2649466..9c9987bbb 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 8692453ef..7f0e44480 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 f4202f25a..61173a6cc 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; From 426658b422ad4fb75e419ad1339d78b8a12cc540 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Thu, 2 Mar 2023 14:45:23 +0100 Subject: [PATCH 4/5] netlink: introduce nla_get_in6_addr() helper --- src/libnm-platform/nm-netlink.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libnm-platform/nm-netlink.h b/src/libnm-platform/nm-netlink.h index 117525f94..6fed8189b 100644 --- a/src/libnm-platform/nm-netlink.h +++ b/src/libnm-platform/nm-netlink.h @@ -290,6 +290,17 @@ size_t nla_memcpy(void *dst, const struct nlattr *nla, size_t dstsize); } \ G_STMT_END +static inline struct in6_addr +nla_get_in6_addr(const struct nlattr *nla) +{ + struct in6_addr in6; + + nm_assert(nla_len(nla) >= sizeof(struct in6_addr)); + + nla_memcpy(&in6, nla, sizeof(in6)); + return in6; +} + int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data); static inline int From c6487c240c433bbba6b891da81741adec6c2ae9a Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Thu, 2 Mar 2023 15:07:07 +0100 Subject: [PATCH 5/5] bonding: add support to ns_ip6_target option This is the IPv6 equivalent of arp_ip_target option. It requires arp_interval set and allow the user to specify up to 16 IPv6 addresses as targets. By default, the list is empty. --- src/core/devices/nm-device-bond.c | 36 ++++++++- .../nm-libnm-core-utils.c | 3 +- .../nm-libnm-core-utils.h | 2 +- src/libnm-core-impl/nm-setting-bond.c | 37 +++++++-- src/libnm-core-intern/nm-core-internal.h | 1 + src/libnm-core-public/nm-setting-bond.h | 1 + src/libnm-platform/nm-linux-platform.c | 26 +++++++ src/libnm-platform/nm-platform.c | 16 ++++ src/libnm-platform/nm-platform.h | 76 ++++++++++--------- src/libnmc-setting/nm-meta-setting-desc.c | 7 +- src/nmtui/nmt-page-bond.c | 2 +- 11 files changed, 157 insertions(+), 50 deletions(-) diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 853e1b6c1..cb3233192 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -57,7 +57,7 @@ #define OPTIONS_REAPPLY_FULL \ OPTIONS_REAPPLY_SUBSET, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, \ - NM_SETTING_BOND_OPTION_ARP_IP_TARGET + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_NS_IP6_TARGET /*****************************************************************************/ @@ -270,7 +270,7 @@ set_arp_targets(NMDevice *device, const char *cur_arp_ip_target, const char *new cur_strv = nm_strsplit_set_full(cur_arp_ip_target, NM_ASCII_SPACES, NM_STRSPLIT_SET_FLAGS_STRSTRIP); - new_strv = nm_utils_bond_option_arp_ip_targets_split(new_arp_ip_target); + new_strv = nm_utils_bond_option_ip_split(new_arp_ip_target); cur_len = NM_PTRARRAY_LEN(cur_strv); new_len = NM_PTRARRAY_LEN(new_strv); @@ -367,7 +367,7 @@ _bond_arp_ip_target_to_platform(const char *value, in_addr_t out[static NM_BOND_ int i; int added = 0; - ip = nm_utils_bond_option_arp_ip_targets_split(value); + ip = nm_utils_bond_option_ip_split(value); if (!ip) return added; @@ -383,6 +383,31 @@ _bond_arp_ip_target_to_platform(const char *value, in_addr_t out[static NM_BOND_ return added; } +static guint8 +_bond_ns_ip6_target_to_platform(const char *value, + struct in6_addr out[static NM_BOND_MAX_ARP_TARGETS]) +{ + gs_free const char **ip = NULL; + struct in6_addr in6_a; + int i; + int added = 0; + + ip = nm_utils_bond_option_ip_split(value); + + if (!ip) + return added; + + for (i = 0; ip[i]; i++) { + if (added > NM_BOND_MAX_ARP_TARGETS - 1) + break; + if (!nm_inet_parse_bin(AF_INET6, ip[i], NULL, &in6_a)) + nm_assert_not_reached(); /* verify() already validated the IP addresses */ + + out[added++] = in6_a; + } + return added; +} + static int _setting_bond_primary_opt_as_ifindex(NMSettingBond *s_bond) { @@ -462,6 +487,11 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p props->arp_ip_targets_num = _bond_arp_ip_target_to_platform(opt_value, props->arp_ip_target); + opt_value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_NS_IP6_TARGET); + if (opt_value != NULL) + props->ns_ip6_targets_num = + _bond_ns_ip6_target_to_platform(opt_value, props->ns_ip6_target); + props->miimon_has = !props->arp_interval && !props->arp_validate; props->updelay_has = props->miimon_has && props->miimon; props->downdelay_has = props->miimon_has && props->miimon; 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 5ccb5e400..e7530c83b 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.c +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.c @@ -13,7 +13,7 @@ /*****************************************************************************/ const char ** -nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target) +nm_utils_bond_option_ip_split(const char *arp_ip_target) { return nm_strsplit_set_full(arp_ip_target, ",", NM_STRSPLIT_SET_FLAGS_STRSTRIP); } @@ -36,6 +36,7 @@ _nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond) nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_NS_IP6_TARGET); } /*****************************************************************************/ 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 79ddfbbcc..589291e5a 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.h +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.h @@ -52,7 +52,7 @@ NM_AUTO_DEFINE_FCN0(NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_ /****************************************************************************/ -const char **nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target); +const char **nm_utils_bond_option_ip_split(const char *arp_ip_target); void _nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond); void _nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond); diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c index 5367f5230..a09129afb 100644 --- a/src/libnm-core-impl/nm-setting-bond.c +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -94,6 +94,7 @@ static const char *const valid_options_lst[] = { NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, NM_SETTING_BOND_OPTION_LACP_ACTIVE, + NM_SETTING_BOND_OPTION_NS_IP6_TARGET, NULL, }; @@ -135,6 +136,7 @@ _nm_assert_bond_meta(const OptionMeta *option_meta) })); return TRUE; case NM_BOND_OPTION_TYPE_IP: + case NM_BOND_OPTION_TYPE_IP6: nm_assert(option_meta->val); /* fall-through */ case NM_BOND_OPTION_TYPE_IFNAME: @@ -213,6 +215,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE( {NM_SETTING_BOND_OPTION_MIN_LINKS, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, {NM_SETTING_BOND_OPTION_MODE, {"balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_mode}}, + {NM_SETTING_BOND_OPTION_NS_IP6_TARGET, {"", NM_BOND_OPTION_TYPE_IP6}}, {NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, {NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, {NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, {"1", NM_BOND_OPTION_TYPE_INT, 0, 65535}}, @@ -510,12 +513,12 @@ validate_list(const char *name, const char *value, const OptionMeta *option_meta } static gboolean -validate_ip(const char *name, const char *value, GError **error) +validate_ip(int addr_family, const char *name, const char *value, GError **error) { gs_free const char **addrs = NULL; gsize i; - addrs = nm_utils_bond_option_arp_ip_targets_split(value); + addrs = nm_utils_bond_option_ip_split(value); if (!addrs) { g_set_error(error, NM_CONNECTION_ERROR, @@ -524,13 +527,18 @@ validate_ip(const char *name, const char *value, GError **error) name); return FALSE; } + + /* An empty list is invalid. */ + nm_assert(addrs[0]); + for (i = 0; addrs[i]; i++) { - if (!nm_inet_parse_bin(AF_INET, addrs[i], NULL, NULL)) { + if (!nm_inet_parse_bin(addr_family, addrs[i], NULL, NULL)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IPv4 address for '%s' option"), + _("'%s' is not a valid %s address for '%s' option"), addrs[i], + addr_family == AF_INET ? "IPv4" : "IPv6", name); return FALSE; } @@ -580,7 +588,10 @@ _nm_setting_bond_validate_option(const char *name, const char *value, GError **e goto handle_error; case NM_BOND_OPTION_TYPE_IP: nm_assert(nm_streq0(name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)); - return validate_ip(name, value, error); + return validate_ip(AF_INET, name, value, error); + case NM_BOND_OPTION_TYPE_IP6: + nm_assert(nm_streq0(name, NM_SETTING_BOND_OPTION_NS_IP6_TARGET)); + return validate_ip(AF_INET6, name, value, error); case NM_BOND_OPTION_TYPE_MAC: success = nm_utils_hwaddr_valid(value, ETH_ALEN); goto handle_error; @@ -858,6 +869,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) int peer_notif_delay; const char *mode_str; const char *arp_ip_target = NULL; + const char *ns_ip6_target; const char *lacp_rate; const char *lacp_active; const char *primary; @@ -1078,6 +1090,21 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } } + /* ns_ip6_target can only be used with arp_interval, and must + * contain a comma-separated list of IPv6 addresses. + */ + ns_ip6_target = _bond_get_option(self, NM_SETTING_BOND_OPTION_NS_IP6_TARGET); + if (ns_ip6_target && arp_interval == 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be set"), + NM_SETTING_BOND_OPTION_NS_IP6_TARGET, + NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + lacp_rate = _bond_get_option(self, NM_SETTING_BOND_OPTION_LACP_RATE); if (lacp_rate && bond_mode != NM_BOND_MODE_8023AD && !NM_IN_STRSET(lacp_rate, "0", "slow")) { g_set_error(error, diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index 3a5601232..5e1cd3582 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -471,6 +471,7 @@ typedef enum { NM_BOND_OPTION_TYPE_INT, NM_BOND_OPTION_TYPE_BOTH, NM_BOND_OPTION_TYPE_IP, + NM_BOND_OPTION_TYPE_IP6, NM_BOND_OPTION_TYPE_MAC, NM_BOND_OPTION_TYPE_IFNAME, } NMBondOptionType; diff --git a/src/libnm-core-public/nm-setting-bond.h b/src/libnm-core-public/nm-setting-bond.h index 1e653abcf..7cead175c 100644 --- a/src/libnm-core-public/nm-setting-bond.h +++ b/src/libnm-core-public/nm-setting-bond.h @@ -60,6 +60,7 @@ G_BEGIN_DECLS #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" +#define NM_SETTING_BOND_OPTION_NS_IP6_TARGET "ns_ip6_target" typedef struct _NMSettingBondClass NMSettingBondClass; diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 9c9987bbb..c75fb3bf8 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -182,6 +182,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 +#define IFLA_BOND_NS_IP6_TARGET 31 #undef IFLA_BOND_MAX @@ -1610,6 +1611,7 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) [IFLA_BOND_PEER_NOTIF_DELAY] = {.type = NLA_U32}, [IFLA_BOND_MISSED_MAX] = {.type = NLA_U8}, [IFLA_BOND_AD_LACP_ACTIVE] = {.type = NLA_U8}, + [IFLA_BOND_NS_IP6_TARGET] = {.type = NLA_NESTED}, }; NMPlatformLnkBond *props; struct nlattr *tb[G_N_ELEMENTS(policy)]; @@ -1664,6 +1666,19 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) props->arp_ip_target[props->arp_ip_targets_num++] = nla_get_u32(attr); } } + if (tb[IFLA_BOND_NS_IP6_TARGET]) { + struct nlattr *attr; + int rem; + + nla_for_each_nested (attr, tb[IFLA_BOND_NS_IP6_TARGET], rem) { + if (props->ns_ip6_targets_num > NM_BOND_MAX_ARP_TARGETS - 1) + break; + if (nla_len(attr) < sizeof(struct in6_addr)) + break; + + props->ns_ip6_target[props->ns_ip6_targets_num++] = nla_get_in6_addr(attr); + } + } if (tb[IFLA_BOND_ARP_VALIDATE]) props->arp_validate = nla_get_u32(tb[IFLA_BOND_ARP_VALIDATE]); if (tb[IFLA_BOND_ARP_ALL_TARGETS]) @@ -4709,6 +4724,17 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo nla_nest_end(msg, targets); } + if (props->ns_ip6_targets_num > 0) { + targets = nla_nest_start(msg, IFLA_BOND_NS_IP6_TARGET); + if (!targets) + goto nla_put_failure; + + for (i = 0; i < props->ns_ip6_targets_num; i++) + NLA_PUT(msg, i, sizeof(struct in6_addr), &props->ns_ip6_target[i]); + + nla_nest_end(msg, targets); + } + if (props->arp_all_targets) NLA_PUT_U32(msg, IFLA_BOND_ARP_ALL_TARGETS, props->arp_all_targets); if (props->arp_interval) diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 7f0e44480..eddbaba37 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -6299,6 +6299,15 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le nm_strbuf_append_str(&buf, &len, nm_inet4_ntop(lnk->arp_ip_target[i], target)); } } + if (lnk->ns_ip6_targets_num > 0) { + nm_strbuf_append_str(&buf, &len, " ns_ip6_target"); + for (i = 0; i < lnk->ns_ip6_targets_num; i++) { + char target[INET6_ADDRSTRLEN]; + + nm_strbuf_append_c(&buf, &len, ' '); + nm_strbuf_append_str(&buf, &len, nm_inet6_ntop(&lnk->ns_ip6_target[i], target)); + } + } return buf; } @@ -8052,6 +8061,7 @@ nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h) obj->fail_over_mac, obj->lacp_rate, obj->lacp_active, + obj->ns_ip6_targets_num, obj->num_grat_arp, obj->mode, obj->primary_reselect, @@ -8069,6 +8079,7 @@ nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h) obj->use_carrier)); nm_hash_update(h, obj->arp_ip_target, obj->arp_ip_targets_num * sizeof(obj->arp_ip_target[0])); + nm_hash_update(h, obj->ns_ip6_target, obj->ns_ip6_targets_num * sizeof(obj->ns_ip6_target[0])); } int @@ -8076,6 +8087,11 @@ nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) { NM_CMP_SELF(a, b); NM_CMP_FIELD(a, b, arp_ip_targets_num); + NM_CMP_FIELD(a, b, ns_ip6_targets_num); + NM_CMP_FIELD_MEMCMP_LEN(a, + b, + ns_ip6_target, + a->ns_ip6_targets_num * sizeof(a->ns_ip6_target[0])); NM_CMP_FIELD_MEMCMP_LEN(a, b, arp_ip_target, diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 61173a6cc..08a7716e3 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -764,43 +764,45 @@ extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default; #define NM_BOND_MAX_ARP_TARGETS 16 typedef struct { - int primary; - in_addr_t arp_ip_target[NM_BOND_MAX_ARP_TARGETS]; - guint32 arp_all_targets; - guint32 arp_interval; - guint32 arp_validate; - guint32 downdelay; - guint32 lp_interval; - guint32 miimon; - guint32 min_links; - guint32 packets_per_port; - guint32 peer_notif_delay; - guint32 resend_igmp; - guint32 updelay; - guint16 ad_actor_sys_prio; - guint16 ad_user_port_key; - NMEtherAddr ad_actor_system; - guint8 ad_select; - guint8 all_ports_active; - 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; - bool resend_igmp_has : 1; - bool tlb_dynamic_lb : 1; - bool tlb_dynamic_lb_has : 1; - bool updelay_has : 1; - bool use_carrier : 1; + struct in6_addr ns_ip6_target[NM_BOND_MAX_ARP_TARGETS]; + int primary; + in_addr_t arp_ip_target[NM_BOND_MAX_ARP_TARGETS]; + guint32 arp_all_targets; + guint32 arp_interval; + guint32 arp_validate; + guint32 downdelay; + guint32 lp_interval; + guint32 miimon; + guint32 min_links; + guint32 packets_per_port; + guint32 peer_notif_delay; + guint32 resend_igmp; + guint32 updelay; + guint16 ad_actor_sys_prio; + guint16 ad_user_port_key; + NMEtherAddr ad_actor_system; + guint8 ad_select; + guint8 all_ports_active; + guint8 arp_missed_max; + guint8 arp_ip_targets_num; + guint8 fail_over_mac; + guint8 lacp_active; + guint8 lacp_rate; + guint8 ns_ip6_targets_num; + 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; + bool resend_igmp_has : 1; + bool tlb_dynamic_lb : 1; + bool tlb_dynamic_lb_has : 1; + bool updelay_has : 1; + bool use_carrier : 1; } _nm_alignas(NMPlatformObject) NMPlatformLnkBond; typedef struct { diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c index 60a2cfd40..1770a2c75 100644 --- a/src/libnmc-setting/nm-meta-setting-desc.c +++ b/src/libnmc-setting/nm-meta-setting-desc.c @@ -2474,7 +2474,9 @@ _get_fcn_bond_options(ARGS_GET_FCN) nm_setting_bond_get_option(s_bond, i, &key, &val); - if (nm_streq(key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { + if (NM_IN_STRSET(key, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + NM_SETTING_BOND_OPTION_NS_IP6_TARGET)) { val_tmp = g_strdup(val); for (p = val_tmp; p && *p; p++) { if (*p == ',') @@ -2516,7 +2518,8 @@ _nm_meta_setting_bond_add_option(NMSetting *setting, value = nmc_bond_validate_mode(value, error); if (!value) return FALSE; - } else if (nm_streq(name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { + } else if (nm_streq(name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) + || nm_streq(name, NM_SETTING_BOND_OPTION_NS_IP6_TARGET)) { value = tmp_value = g_strdup(value); for (p = tmp_value; p && *p; p++) if (*p == ' ') diff --git a/src/nmtui/nmt-page-bond.c b/src/nmtui/nmt-page-bond.c index edcf681ec..3396320da 100644 --- a/src/nmtui/nmt-page-bond.c +++ b/src/nmtui/nmt-page-bond.c @@ -141,7 +141,7 @@ bond_options_changed(GObject *object, GParamSpec *pspec, gpointer user_data) nmt_newt_entry_set_text(priv->arp_interval, val ?: "0"); val = nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - ips = nm_utils_bond_option_arp_ip_targets_split(val); + ips = nm_utils_bond_option_ip_split(val); g_object_set(G_OBJECT(priv->arp_ip_target), "strings", ips ?: NM_PTRARRAY_EMPTY(const char *),