diff options
author | Thomas Haller <thaller@redhat.com> | 2020-02-19 17:28:33 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-02-19 17:28:33 +0100 |
commit | 1fbfbf743daf919dee2a7b7aaf248822760a882f (patch) | |
tree | 7a00cf9f2b1ae91a09f10f73d7f0ad645483af5d | |
parent | efc04b1285674ba2aea459039f4143b3307b4bcf (diff) | |
parent | 8775c25c331893b8b2f2540f9a6824363680cb11 (diff) | |
download | NetworkManager-1fbfbf743daf919dee2a7b7aaf248822760a882f.tar.gz |
bond: merge branch 'th/bond-allow-arp-validate'
https://bugzilla.redhat.com/show_bug.cgi?id=1789437
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/418
-rw-r--r-- | libnm-core/nm-core-internal.h | 1 | ||||
-rw-r--r-- | libnm-core/nm-setting-bond.c | 422 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-macros-internal.h | 18 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.c | 8 | ||||
-rw-r--r-- | shared/nm-glib-aux/nm-shared-utils.h | 72 | ||||
-rw-r--r-- | src/devices/nm-device-bond.c | 11 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected | 2 |
7 files changed, 340 insertions, 194 deletions
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 2bc7a53aae..444338abf9 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -488,7 +488,6 @@ NMSettingIPConfig *nm_connection_get_setting_ip_config (NMConnection *connection typedef enum { NM_BOND_OPTION_TYPE_INT, - NM_BOND_OPTION_TYPE_STRING, NM_BOND_OPTION_TYPE_BOTH, NM_BOND_OPTION_TYPE_IP, NM_BOND_OPTION_TYPE_MAC, diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index 9aad9c90c2..df8a8a4985 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -44,51 +44,138 @@ G_DEFINE_TYPE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) /*****************************************************************************/ +static const char *const valid_options_lst[] = { + NM_SETTING_BOND_OPTION_MODE, + NM_SETTING_BOND_OPTION_MIIMON, + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_UPDELAY, + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + NM_SETTING_BOND_OPTION_ARP_VALIDATE, + NM_SETTING_BOND_OPTION_PRIMARY, + NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, + NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, + NM_SETTING_BOND_OPTION_USE_CARRIER, + NM_SETTING_BOND_OPTION_AD_SELECT, + NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, + NM_SETTING_BOND_OPTION_RESEND_IGMP, + NM_SETTING_BOND_OPTION_LACP_RATE, + NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, + NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, + NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, + NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, + NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, + NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, + NM_SETTING_BOND_OPTION_MIN_LINKS, + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, + NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, + NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, + NM_SETTING_BOND_OPTION_LP_INTERVAL, + NULL, +}; + typedef struct { - const char *opt; const char *val; - guint opt_type; + NMBondOptionType opt_type; guint min; guint max; - char *list[10]; -} BondDefault; - -static const BondDefault defaults[] = { - { NM_SETTING_BOND_OPTION_MODE, "balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6, - { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } }, - { NM_SETTING_BOND_OPTION_MIIMON, "100", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_DOWNDELAY, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_UPDELAY, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { 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_VALIDATE, "none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, - { "none", "active", "backup", "all", "filter", "filter_active", "filter_backup", NULL } }, - { NM_SETTING_BOND_OPTION_PRIMARY, "", NM_BOND_OPTION_TYPE_IFNAME }, - { NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "always", NM_BOND_OPTION_TYPE_BOTH, 0, 2, - { "always", "better", "failure", NULL } }, - { NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, "none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, - { "none", "active", "follow", NULL } }, - { NM_SETTING_BOND_OPTION_USE_CARRIER, "1", NM_BOND_OPTION_TYPE_INT, 0, 1 }, - { NM_SETTING_BOND_OPTION_AD_SELECT, "stable", NM_BOND_OPTION_TYPE_BOTH, 0, 2, - { "stable", "bandwidth", "count", NULL } }, - { NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "layer2", NM_BOND_OPTION_TYPE_BOTH, 0, 4, - { "layer2", "layer3+4", "layer2+3", "encap2+3", "encap3+4", NULL } }, - { NM_SETTING_BOND_OPTION_RESEND_IGMP, "1", NM_BOND_OPTION_TYPE_INT, 0, 255 }, - { NM_SETTING_BOND_OPTION_LACP_RATE, "slow", NM_BOND_OPTION_TYPE_BOTH, 0, 1, - { "slow", "fast", NULL } }, - { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, "", NM_BOND_OPTION_TYPE_IFNAME }, - { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO,"65535", NM_BOND_OPTION_TYPE_INT, 1, 65535 }, - { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, NULL, NM_BOND_OPTION_TYPE_MAC }, - { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, "0", NM_BOND_OPTION_TYPE_INT, 0, 1023}, - { NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE,"0", NM_BOND_OPTION_TYPE_INT, 0, 1}, - { NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, "any", NM_BOND_OPTION_TYPE_BOTH, 0, 1, {"any", "all"}}, - { NM_SETTING_BOND_OPTION_MIN_LINKS, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { 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 }, - { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, "1", NM_BOND_OPTION_TYPE_INT, 0, 1 }, - { NM_SETTING_BOND_OPTION_LP_INTERVAL, "1", NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT }, -}; + const char *const*list; +} OptionMeta; + +static gboolean +_nm_assert_bond_meta (const OptionMeta *option_meta) +{ + nm_assert (option_meta); + + switch (option_meta->opt_type) { + case NM_BOND_OPTION_TYPE_BOTH: + nm_assert (option_meta->val); + nm_assert (option_meta->list); + nm_assert (option_meta->list[0]); + nm_assert (option_meta->min == 0); + nm_assert (option_meta->max == NM_PTRARRAY_LEN (option_meta->list) - 1); + nm_assert (g_strv_contains (option_meta->list, option_meta->val)); + return TRUE; + case NM_BOND_OPTION_TYPE_INT: + nm_assert (option_meta->val); + nm_assert (!option_meta->list); + nm_assert (option_meta->min < option_meta->max); + nm_assert (NM_STRCHAR_ALL (option_meta->val, ch, g_ascii_isdigit (ch))); + nm_assert (NM_STRCHAR_ALL (option_meta->val, ch, g_ascii_isdigit (ch))); + nm_assert (({ + _nm_utils_ascii_str_to_uint64 (option_meta->val, 10, option_meta->min, option_meta->max, 0); + errno == 0; + })); + return TRUE; + case NM_BOND_OPTION_TYPE_IP: + case NM_BOND_OPTION_TYPE_IFNAME: + nm_assert (option_meta->val); + /* fall-through */ + case NM_BOND_OPTION_TYPE_MAC: + nm_assert (!option_meta->list); + nm_assert (option_meta->min == 0); + nm_assert (option_meta->max == 0); + return TRUE; + } + + nm_assert_not_reached (); + return FALSE; +} + +static char const *const _option_default_strv_ad_select[] = NM_MAKE_STRV ("stable", "bandwidth", "count"); +static char const *const _option_default_strv_arp_all_targets[] = NM_MAKE_STRV ("any", "all"); +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", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb"); +static char const *const _option_default_strv_primary_reselect[] = NM_MAKE_STRV ("always", "better", "failure"); +static char const *const _option_default_strv_xmit_hash_policy[] = NM_MAKE_STRV ("layer2", "layer3+4", "layer2+3", "encap2+3", "encap3+4"); + +static +NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE ( + _get_option_meta, + OptionMeta, + { + G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (LIST) == G_N_ELEMENTS (valid_options_lst) - 1); + + if (NM_MORE_ASSERT_ONCE (5)) { + int i; + + nm_assert (G_N_ELEMENTS (LIST) == NM_PTRARRAY_LEN (valid_options_lst)); + for (i = 0; i < G_N_ELEMENTS (LIST); i++) + _nm_assert_bond_meta (&LIST[i].value); + } + }, + { return NULL; }, + { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, { "", NM_BOND_OPTION_TYPE_IFNAME } }, + { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, { "65535", NM_BOND_OPTION_TYPE_INT, 1, 65535 } }, + { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, { NULL, NM_BOND_OPTION_TYPE_MAC } }, + { NM_SETTING_BOND_OPTION_AD_SELECT, { "stable", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_ad_select } }, + { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, { "0", NM_BOND_OPTION_TYPE_INT, 0, 1023 } }, + { NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, { "0", NM_BOND_OPTION_TYPE_INT, 0, 1 } }, + { NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, { "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_VALIDATE, { "none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_arp_validate } }, + { 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_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 } }, + { NM_SETTING_BOND_OPTION_MIIMON, { "100", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { 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_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 } }, + { NM_SETTING_BOND_OPTION_PRIMARY, { "", NM_BOND_OPTION_TYPE_IFNAME } }, + { NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, { "always", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_primary_reselect } }, + { NM_SETTING_BOND_OPTION_RESEND_IGMP, { "1", NM_BOND_OPTION_TYPE_INT, 0, 255 } }, + { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, { "1", NM_BOND_OPTION_TYPE_INT, 0, 1 } }, + { NM_SETTING_BOND_OPTION_UPDELAY, { "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_USE_CARRIER, { "1", NM_BOND_OPTION_TYPE_INT, 0, 1 } }, + { NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, { "layer2", NM_BOND_OPTION_TYPE_BOTH, 0, 4, _option_default_strv_xmit_hash_policy } }, +); /*****************************************************************************/ @@ -110,6 +197,26 @@ nm_setting_bond_get_num_options (NMSettingBond *setting) return g_hash_table_size (NM_SETTING_BOND_GET_PRIVATE (setting)->options); } +static int +_get_option_sort (gconstpointer p_a, gconstpointer p_b, gpointer _unused) +{ + const char *a = *((const char *const*) p_a); + const char *b = *((const char *const*) p_b); + + NM_CMP_DIRECT (nm_streq (b, NM_SETTING_BOND_OPTION_MODE), + nm_streq (a, NM_SETTING_BOND_OPTION_MODE)); + NM_CMP_DIRECT_STRCMP (a, b); + nm_assert_not_reached (); + return 0; +} + +static void +_ensure_options_idx_cache (NMSettingBondPrivate *priv) +{ + if (!G_UNLIKELY (priv->options_idx_cache)) + priv->options_idx_cache = nm_utils_named_values_from_str_dict_with_sort (priv->options, NULL, _get_option_sort, NULL); +} + /** * nm_setting_bond_get_option: * @setting: the #NMSettingBond @@ -148,8 +255,7 @@ nm_setting_bond_get_option (NMSettingBond *setting, if (idx >= len) return FALSE; - if (!G_UNLIKELY (priv->options_idx_cache)) - priv->options_idx_cache = nm_utils_named_values_from_str_dict (priv->options, NULL); + _ensure_options_idx_cache (priv); NM_SET_OUT (out_name, priv->options_idx_cache[idx].name); NM_SET_OUT (out_value, priv->options_idx_cache[idx].value_str); @@ -157,14 +263,14 @@ nm_setting_bond_get_option (NMSettingBond *setting, } static gboolean -validate_int (const char *name, const char *value, const BondDefault *def) +validate_int (const char *name, const char *value, const OptionMeta *option_meta) { guint64 num; if (!NM_STRCHAR_ALL (value, ch, g_ascii_isdigit (ch))) return FALSE; - num = _nm_utils_ascii_str_to_uint64 (value, 10, def->min, def->max, G_MAXUINT64); + num = _nm_utils_ascii_str_to_uint64 (value, 10, option_meta->min, option_meta->max, G_MAXUINT64); if ( num == G_MAXUINT64 && errno != 0) return FALSE; @@ -173,17 +279,17 @@ validate_int (const char *name, const char *value, const BondDefault *def) } static gboolean -validate_list (const char *name, const char *value, const BondDefault *def) +validate_list (const char *name, const char *value, const OptionMeta *option_meta) { - guint i; + int i; - for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) { - if (g_strcmp0 (def->list[i], value) == 0) + nm_assert (option_meta->list); + + for (i = 0; option_meta->list[i]; i++) { + if (nm_streq (option_meta->list[i], value)) return TRUE; } - - /* empty validation list means all values pass */ - return def->list[0] == NULL ? TRUE : FALSE; + return FALSE; } static gboolean @@ -243,33 +349,30 @@ gboolean nm_setting_bond_validate_option (const char *name, const char *value) { - guint i; + const OptionMeta *option_meta; - if (!name || !name[0]) + option_meta = _get_option_meta (name); + if (!option_meta) return FALSE; - for (i = 0; i < G_N_ELEMENTS (defaults); i++) { - if (g_strcmp0 (defaults[i].opt, name) == 0) { - if (value == NULL) - return TRUE; - switch (defaults[i].opt_type) { - case NM_BOND_OPTION_TYPE_INT: - return validate_int (name, value, &defaults[i]); - case NM_BOND_OPTION_TYPE_STRING: - return validate_list (name, value, &defaults[i]); - case NM_BOND_OPTION_TYPE_BOTH: - return ( validate_int (name, value, &defaults[i]) - || validate_list (name, value, &defaults[i])); - case NM_BOND_OPTION_TYPE_IP: - return validate_ip (name, value); - case NM_BOND_OPTION_TYPE_MAC: - return nm_utils_hwaddr_valid (value, ETH_ALEN); - case NM_BOND_OPTION_TYPE_IFNAME: - return validate_ifname (name, value); - } - return FALSE; - } + if (!value) + return TRUE; + + switch (option_meta->opt_type) { + case NM_BOND_OPTION_TYPE_INT: + return validate_int (name, value, option_meta); + case NM_BOND_OPTION_TYPE_BOTH: + return ( validate_int (name, value, option_meta) + || validate_list (name, value, option_meta)); + case NM_BOND_OPTION_TYPE_IP: + return validate_ip (name, value); + case NM_BOND_OPTION_TYPE_MAC: + return nm_utils_hwaddr_valid (value, ETH_ALEN); + case NM_BOND_OPTION_TYPE_IFNAME: + return validate_ifname (name, value); } + + nm_assert_not_reached (); return FALSE; } @@ -330,15 +433,17 @@ nm_setting_bond_add_option (NMSettingBond *setting, nm_clear_g_free (&priv->options_idx_cache); g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value)); - if ( !strcmp (name, NM_SETTING_BOND_OPTION_MIIMON) - && strcmp (value, "0") != 0) { - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - } else if ( !strcmp (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL) - && strcmp (value, "0") != 0) { - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_MIIMON); - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY); - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY); + if (nm_streq (name, NM_SETTING_BOND_OPTION_MIIMON)) { + if (!nm_streq (value, "0")) { + g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + } + } else if (nm_streq (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL)) { + if (!nm_streq (value, "0")) { + g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_MIIMON); + g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY); + g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY); + } } _notify (setting, PROP_OPTIONS); @@ -391,16 +496,7 @@ nm_setting_bond_remove_option (NMSettingBond *setting, const char ** nm_setting_bond_get_valid_options (NMSettingBond *setting) { - static const char *array[G_N_ELEMENTS (defaults) + 1] = { NULL }; - int i; - - /* initialize the array once */ - if (G_UNLIKELY (array[0] == NULL)) { - for (i = 0; i < G_N_ELEMENTS (defaults); i++) - array[i] = defaults[i].opt; - array[i] = NULL; - } - return array; + return (const char **) valid_options_lst; } /** @@ -414,28 +510,25 @@ nm_setting_bond_get_valid_options (NMSettingBond *setting) const char * nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name) { + const OptionMeta *option_meta; const char *mode; - guint i; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL); - g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NULL); + + option_meta = _get_option_meta (name); + + g_return_val_if_fail (option_meta, NULL); if (nm_streq (name, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { /* The default value depends on the current mode */ mode = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_MODE); - if ( nm_streq0 (mode, "4") - || nm_streq0 (mode, "802.3ad")) + if (NM_IN_STRSET (mode, "4", "802.3ad")) return "00:00:00:00:00:00"; else return ""; } - for (i = 0; i < G_N_ELEMENTS (defaults); i++) { - if (g_strcmp0 (defaults[i].opt, name) == 0) - return defaults[i].val; - } - /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */ - g_assert_not_reached (); + return option_meta->val; } /** @@ -448,17 +541,15 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name) NMBondOptionType _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name) { - guint i; + const OptionMeta *option_meta; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NM_BOND_OPTION_TYPE_INT); - g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NM_BOND_OPTION_TYPE_INT); - for (i = 0; i < G_N_ELEMENTS (defaults); i++) { - if (nm_streq0 (defaults[i].opt, name)) - return defaults[i].opt_type; - } - /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */ - g_assert_not_reached (); + option_meta = _get_option_meta (name); + + g_return_val_if_fail (option_meta, NM_BOND_OPTION_TYPE_INT); + + return option_meta->opt_type; } NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( @@ -477,62 +568,71 @@ NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( /*****************************************************************************/ -#define BIT(x) (1 << (x)) +#define BIT(x) (((guint32) 1) << (x)) -static const struct { - const char *option; - NMBondMode unsupp_modes; -} bond_unsupp_modes[] = { - { NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT (NM_BOND_MODE_ROUNDROBIN)) }, - { NM_SETTING_BOND_OPTION_ARP_VALIDATE, BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB) }, - { NM_SETTING_BOND_OPTION_ARP_INTERVAL, BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB) }, - { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB) }, - { NM_SETTING_BOND_OPTION_LACP_RATE, ~(BIT (NM_BOND_MODE_8023AD)) }, - { NM_SETTING_BOND_OPTION_PRIMARY, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, +static +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _bond_option_unsupp_mode, + guint32, + { ; }, + { return 0; }, { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, - { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT (NM_BOND_MODE_TLB)) }, { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, ~(BIT (NM_BOND_MODE_8023AD)) }, { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, ~(BIT (NM_BOND_MODE_8023AD)) }, { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, ~(BIT (NM_BOND_MODE_8023AD)) }, -}; + { NM_SETTING_BOND_OPTION_ARP_INTERVAL, (BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, (BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_ARP_VALIDATE, (BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_LACP_RATE, ~(BIT (NM_BOND_MODE_8023AD)) }, + { NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT (NM_BOND_MODE_ROUNDROBIN)) }, + { NM_SETTING_BOND_OPTION_PRIMARY, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT (NM_BOND_MODE_TLB)) }, +) gboolean _nm_setting_bond_option_supported (const char *option, NMBondMode mode) { - guint i; + nm_assert (option); + nm_assert (_NM_INT_NOT_NEGATIVE (mode) && mode < 32); - for (i = 0; i < G_N_ELEMENTS (bond_unsupp_modes); i++) { - if (nm_streq (option, bond_unsupp_modes[i].option)) - return !NM_FLAGS_ANY (bond_unsupp_modes[i].unsupp_modes, BIT (mode)); - } - - return TRUE; + return !NM_FLAGS_ANY (_bond_option_unsupp_mode (option), BIT (mode)); } static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting); - GHashTableIter iter; - const char *key, *value; - int mode, miimon = 0, arp_interval = 0; - int num_grat_arp = -1, num_unsol_na = -1; - const char *mode_orig, *mode_new; + int mode; + int miimon = 0; + int arp_interval = 0; + int num_grat_arp = -1; + int num_unsol_na = -1; + const char *mode_orig; + const char *mode_new; const char *arp_ip_target = NULL; const char *lacp_rate; const char *primary; NMBondMode bond_mode; + guint i; + const NMUtilsNamedValue *n; + const char *value; - g_hash_table_iter_init (&iter, priv->options); - while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) { - if (!value[0] || !nm_setting_bond_validate_option (key, value)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid option '%s' or its value '%s'"), - key, value); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; + _ensure_options_idx_cache (priv); + + if (priv->options_idx_cache) { + for (i = 0; priv->options_idx_cache[i].name; i++) { + n = &priv->options_idx_cache[i]; + + if ( !n->value_str + || !nm_setting_bond_validate_option (n->name, n->value_str)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid option '%s' or its value '%s'"), + n->name, n->value_str); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } } } @@ -585,8 +685,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) mode_new = nm_utils_bond_mode_int_to_string (mode); /* Make sure mode is compatible with other settings */ - if ( strcmp (mode_new, "balance-alb") == 0 - || strcmp (mode_new, "balance-tlb") == 0) { + if (NM_IN_STRSET (mode_new, "balance-alb", + "balance-tlb")) { if (arp_interval > 0) { g_set_error (error, NM_CONNECTION_ERROR, @@ -599,7 +699,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY); - if (strcmp (mode_new, "active-backup") == 0) { + if (NM_IN_STRSET (mode_new, "active-backup")) { GError *tmp_error = NULL; if (primary && !nm_utils_ifname_valid_kernel (primary, &tmp_error)) { @@ -625,8 +725,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - if (connection && nm_connection_get_setting_infiniband (connection)) { - if (strcmp (mode_new, "active-backup") != 0) { + if ( connection + && nm_connection_get_setting_infiniband (connection)) { + if (!NM_IN_STRSET (mode_new, "active-backup")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -717,9 +818,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) lacp_rate = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_LACP_RATE); if ( lacp_rate - && g_strcmp0 (mode_new, "802.3ad") - && strcmp (lacp_rate, "slow") != 0 - && strcmp (lacp_rate, "0") != 0) { + && !nm_streq0 (mode_new, "802.3ad") + && !NM_IN_STRSET (lacp_rate, "0", "slow")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -746,7 +846,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ - if (g_strcmp0 (mode_orig, mode_new) != 0) { + if (!nm_streq0 (mode_orig, mode_new)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -758,16 +858,14 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) /* normalize unsupported options for the current mode */ bond_mode = _nm_setting_bond_mode_from_string (mode_new); - g_hash_table_iter_init (&iter, priv->options); - while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) { - if (nm_streq (key, "mode")) - continue; - if (!_nm_setting_bond_option_supported (key, bond_mode)) { + for (i = 0; priv->options_idx_cache[i].name; i++) { + n = &priv->options_idx_cache[i]; + if (!_nm_setting_bond_option_supported (n->name, bond_mode)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is not valid with mode '%s'"), - key, mode_new); + n->name, mode_new); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return NM_SETTING_VERIFY_NORMALIZABLE; } diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h index 52591040e2..3cb11a973f 100644 --- a/shared/nm-glib-aux/nm-macros-internal.h +++ b/shared/nm-glib-aux/nm-macros-internal.h @@ -1023,6 +1023,24 @@ nm_str_realloc (char *str) #define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END #endif +/* Usage: + * + * if (NM_MORE_ASSERT_ONCE (5)) { extra_check (); } + * + * This will only run the check once, and only if NM_MORE_ASSERT is >= than + * more_assert_level. + */ +#define NM_MORE_ASSERT_ONCE(more_assert_level) \ + ( (NM_MORE_ASSERTS >= (more_assert_level)) \ + && ({ \ + static volatile int _assert_once = 0; \ + \ + G_STATIC_ASSERT_EXPR ((more_assert_level) >= 0); \ + \ + G_UNLIKELY ( _assert_once == 0 \ + && g_atomic_int_compare_and_exchange (&_assert_once, 0, 1)); \ + })) + /*****************************************************************************/ #define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \ diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index aad16a7d00..0b28077119 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -2357,7 +2357,10 @@ nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll) /*****************************************************************************/ NMUtilsNamedValue * -nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len) +nm_utils_named_values_from_str_dict_with_sort (GHashTable *hash, + guint *out_len, + GCompareDataFunc compare_func, + gpointer user_data) { GHashTableIter iter; NMUtilsNamedValue *values; @@ -2380,7 +2383,8 @@ nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len) values[i].name = NULL; values[i].value_ptr = NULL; - nm_utils_named_value_list_sort (values, len, NULL, NULL); + if (compare_func) + nm_utils_named_value_list_sort (values, len, compare_func, user_data); NM_SET_OUT (out_len, len); return values; diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index 34c7db45d7..a5d2ee7292 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -1207,7 +1207,18 @@ typedef struct { }; } NMUtilsNamedValue; -NMUtilsNamedValue *nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len); +NMUtilsNamedValue *nm_utils_named_values_from_str_dict_with_sort (GHashTable *hash, + guint *out_len, + GCompareDataFunc compare_func, + gpointer user_data); + +static inline NMUtilsNamedValue * +nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len) +{ + G_STATIC_ASSERT (G_STRUCT_OFFSET (NMUtilsNamedValue, name) == 0); + + return nm_utils_named_values_from_str_dict_with_sort (hash, out_len, nm_strcmp_p_with_data, NULL); +} gssize nm_utils_named_value_list_find (const NMUtilsNamedValue *arr, gsize len, @@ -1536,35 +1547,32 @@ guint8 *nm_utils_hexstr2bin_alloc (const char *hexstr, /*****************************************************************************/ -#define NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \ - result_type, \ - entry_cmd, \ - unknown_val_cmd, \ - ...) \ -result_type \ +#define _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \ + value_type, \ + value_type_result, \ + entry_cmd, \ + unknown_val_cmd, \ + get_operator, \ + ...) \ +value_type_result \ fcn_name (const char *name) \ { \ static const struct { \ const char *name; \ - result_type value; \ + value_type value; \ } LIST[] = { \ __VA_ARGS__ \ }; \ \ { entry_cmd; } \ \ - if (NM_MORE_ASSERTS > 5) { \ - static gboolean checked = FALSE; \ + if (NM_MORE_ASSERT_ONCE (5)) { \ int i; \ \ - if (!checked) { \ - checked = TRUE; \ - \ - for (i = 0; i < G_N_ELEMENTS (LIST); i++) { \ - nm_assert (LIST[i].name); \ - if (i > 0) \ - nm_assert (strcmp (LIST[i - 1].name, LIST[i].name) < 0); \ - } \ + for (i = 0; i < G_N_ELEMENTS (LIST); i++) { \ + nm_assert (LIST[i].name); \ + if (i > 0) \ + nm_assert (strcmp (LIST[i - 1].name, LIST[i].name) < 0); \ } \ } \ \ @@ -1579,7 +1587,7 @@ fcn_name (const char *name) \ const int cmp = strcmp (LIST[imid].name, name); \ \ if (G_UNLIKELY (cmp == 0)) \ - return LIST[imid].value; \ + return get_operator (LIST[imid].value); \ \ if (cmp < 0) \ imin = imid + 1u; \ @@ -1597,6 +1605,32 @@ fcn_name (const char *name) \ { unknown_val_cmd; } \ } +#define NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE(fcn_name, \ + result_type, \ + entry_cmd, \ + unknown_val_cmd, \ + ...) \ + _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (fcn_name, \ + result_type, \ + const result_type *, \ + entry_cmd, \ + unknown_val_cmd, \ + &, \ + __VA_ARGS__) + +#define NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \ + result_type, \ + entry_cmd, \ + unknown_val_cmd, \ + ...) \ + _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (fcn_name, \ + result_type, \ + result_type, \ + entry_cmd, \ + unknown_val_cmd, \ + , \ + __VA_ARGS__) + /*****************************************************************************/ static inline GTask * diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 08a288601e..347d633248 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -214,7 +214,7 @@ apply_bonding_config (NMDeviceBond *self) * * arp_interval conflicts miimon > 0 * arp_interval conflicts [ alb, tlb ] - * arp_validate needs [ active-backup ] + * arp_validate does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ] * downdelay needs miimon * updelay needs miimon * primary needs [ active-backup, tlb, alb ] @@ -266,15 +266,8 @@ apply_bonding_config (NMDeviceBond *self) */ } - /* ARP validate: value > 0 only valid in active-backup mode */ value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE); - if ( value - && !nm_streq (value, "0") - && !nm_streq (value, "none") - && mode == NM_BOND_MODE_ACTIVEBACKUP) - set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value); - else - set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, "0"); + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value ?: "0"); /* Primary */ value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY); diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected index 36df7712ae..b288c04a47 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected @@ -1,4 +1,4 @@ -BONDING_OPTS="downdelay=5 miimon=100 mode=balance-rr updelay=10" +BONDING_OPTS="mode=balance-rr downdelay=5 miimon=100 updelay=10" TYPE=Bond BONDING_MASTER=yes HWADDR= |