diff options
Diffstat (limited to 'libnm-core/nm-setting-bond.c')
| -rw-r--r-- | libnm-core/nm-setting-bond.c | 809 |
1 files changed, 515 insertions, 294 deletions
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index f3ae9ef5..8986e434 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -44,54 +44,285 @@ G_DEFINE_TYPE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) /*****************************************************************************/ +static const char *const valid_options_lst[] = { + /* mode must be the first element. nm-device-bond.c relies on that. */ + 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); + nm_assert (nm_streq (valid_options_lst[0], NM_SETTING_BOND_OPTION_MODE)); + } + }, + { 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 } }, +); /*****************************************************************************/ +#define BIT(x) (((guint32) 1) << (x)) + +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_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) +{ + nm_assert (option); + nm_assert (mode != NM_BOND_MODE_UNKNOWN); + nm_assert (_NM_INT_NOT_NEGATIVE (mode) && mode < 32); + + return !NM_FLAGS_ANY (_bond_option_unsupp_mode (option), BIT (mode)); +} + +static const char* +_bond_get_option (NMSettingBond *self, + const char *option) +{ + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + g_return_val_if_fail (option, NULL); + + return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (self)->options, option); +} + +static const char* +_bond_get_option_default (NMSettingBond *self, + const char *option) +{ + const OptionMeta *option_meta; + + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + + option_meta = _get_option_meta (option); + + g_return_val_if_fail (option_meta, NULL); + + return option_meta->val; +} + +static const char* +_bond_get_option_or_default (NMSettingBond *self, + const char *option) +{ + return _bond_get_option (self, option) + ?: _bond_get_option_default (self, option); +} + +static const char* +_bond_get_option_normalized (NMSettingBond* self, + const char* option, + gboolean get_default_only) +{ + const char *arp_interval_str; + const char *mode_str; + gint64 arp_interval; + NMBondMode mode; + const char *value = NULL; + + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + g_return_val_if_fail (option, NULL); + + mode_str = _bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_MODE); + mode = _nm_setting_bond_mode_from_string (mode_str); + g_return_val_if_fail (mode != NM_BOND_MODE_UNKNOWN, NULL); + + if (!_nm_setting_bond_option_supported (option, mode)) + return NULL; + + /* Apply custom NetworkManager policies here */ + if (!get_default_only) { + if (NM_IN_STRSET (option, + NM_SETTING_BOND_OPTION_UPDELAY, + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_MIIMON)) { + /* if arp_interval is explicitly set and miimon is not, then disable miimon + * (and related updelay and downdelay) as recommended by the kernel docs */ + arp_interval_str = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_INTERVAL); + arp_interval = _nm_utils_ascii_str_to_int64 (arp_interval_str, 10, 0, G_MAXINT, 0); + + if (!arp_interval || _bond_get_option (self, NM_SETTING_BOND_OPTION_MIIMON)) { + value = _bond_get_option (self, option); + } else { + return NULL; + } + } else if (NM_IN_STRSET (option, + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)) { + /* just get one of the 2, at kernel level they're the same bond option */ + value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); + if (!value) { + value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); + } + } else { + value = _bond_get_option (self, option); + } + } + + if (!value) { + /* Apply rules that change the default value of an option */ + if (nm_streq (option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { + /* The default value depends on the current mode */ + if (NM_IN_STRSET (mode_str, "4", "802.3ad")) + return "00:00:00:00:00:00"; + else + return ""; + } else { + return _bond_get_option_or_default (self, option); + } + } + + return value; +} + +const char* +nm_setting_bond_get_option_or_default (NMSettingBond *self, + const char *option) +{ + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + g_return_val_if_fail (option, NULL); + + return _bond_get_option_normalized (self, + option, + FALSE); +} + static int _atoi (const char *value) { @@ -120,6 +351,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 @@ -158,8 +409,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); @@ -167,14 +417,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; @@ -183,17 +433,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; + + nm_assert (option_meta->list); - for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) { - if (g_strcmp0 (def->list[i], value) == 0) + 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 @@ -232,9 +482,6 @@ validate_ip (const char *name, const char *value) static gboolean validate_ifname (const char *name, const char *value) { - if (!value || !value[0]) - return FALSE; - return nm_utils_ifname_valid_kernel (value, NULL); } @@ -253,33 +500,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; } @@ -303,7 +547,7 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting, if (!nm_setting_bond_validate_option (name, NULL)) return NULL; - return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name); + return _bond_get_option (setting, name); } /** @@ -340,17 +584,6 @@ 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); - } - _notify (setting, PROP_OPTIONS); return TRUE; @@ -401,16 +634,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; } /** @@ -424,28 +648,38 @@ nm_setting_bond_get_valid_options (NMSettingBond *setting) const char * nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name) { - 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); - - 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")) - 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; + if (!name) { + return NULL; } - /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */ - g_assert_not_reached (); + + return _bond_get_option_normalized (setting, + name, + TRUE); +} + +/** + * nm_setting_bond_get_option_normalized: + * @setting: the #NMSettingBond + * @name: the name of the option + * + * Since: 1.24 + * + * Returns: the value of the bond option after normalization, which is what NetworkManager + * will actually apply when activating the connection. %NULL if the option won't be applied + * to the connection. + **/ +const char * +nm_setting_bond_get_option_normalized (NMSettingBond *setting, + const char *name) +{ + g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL); + g_return_val_if_fail (name, NULL); + + return _bond_get_option_normalized (setting, + name, + FALSE); } /** @@ -458,131 +692,97 @@ 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); -NMBondMode -_nm_setting_bond_mode_from_string (const char *str) -{ - g_return_val_if_fail (str, NM_BOND_MODE_UNKNOWN); + g_return_val_if_fail (option_meta, NM_BOND_OPTION_TYPE_INT); - if (nm_streq (str, "balance-rr")) - return NM_BOND_MODE_ROUNDROBIN; - if (nm_streq (str, "active-backup")) - return NM_BOND_MODE_ACTIVEBACKUP; - if (nm_streq (str, "balance-xor")) - return NM_BOND_MODE_XOR; - if (nm_streq (str, "broadcast")) - return NM_BOND_MODE_BROADCAST; - if (nm_streq (str, "802.3ad")) - return NM_BOND_MODE_8023AD; - if (nm_streq (str, "balance-tlb")) - return NM_BOND_MODE_TLB; - if (nm_streq (str, "balance-alb")) - return NM_BOND_MODE_ALB; - - return NM_BOND_MODE_UNKNOWN; + return option_meta->opt_type; } -/*****************************************************************************/ - -#define BIT(x) (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)) }, - { 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)) }, -}; - -gboolean -_nm_setting_bond_option_supported (const char *option, NMBondMode mode) -{ - guint i; - - 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)); - } +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _nm_setting_bond_mode_from_string, + NMBondMode, + { g_return_val_if_fail (name, NM_BOND_MODE_UNKNOWN); }, + { return NM_BOND_MODE_UNKNOWN; }, + { "0", NM_BOND_MODE_ROUNDROBIN }, + { "1", NM_BOND_MODE_ACTIVEBACKUP }, + { "2", NM_BOND_MODE_XOR }, + { "3", NM_BOND_MODE_BROADCAST }, + { "4", NM_BOND_MODE_8023AD }, + { "5", NM_BOND_MODE_TLB }, + { "6", NM_BOND_MODE_ALB }, + { "802.3ad", NM_BOND_MODE_8023AD }, + { "active-backup", NM_BOND_MODE_ACTIVEBACKUP }, + { "balance-alb", NM_BOND_MODE_ALB }, + { "balance-rr", NM_BOND_MODE_ROUNDROBIN }, + { "balance-tlb", NM_BOND_MODE_TLB }, + { "balance-xor", NM_BOND_MODE_XOR }, + { "broadcast", NM_BOND_MODE_BROADCAST }, +); - return TRUE; -} +/*****************************************************************************/ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { + NMSettingBond *self = NM_SETTING_BOND (setting); 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 miimon; + int arp_interval; + int num_grat_arp; + int num_unsol_na; + const char *mode_str; const char *arp_ip_target = NULL; const char *lacp_rate; const char *primary; NMBondMode bond_mode; + guint i; + const NMUtilsNamedValue *n; - 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; + } } } - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MIIMON); - if (value) - miimon = atoi (value); - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - if (value) - arp_interval = atoi (value); - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); - if (value) - num_grat_arp = atoi (value); - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); - if (value) - num_unsol_na = atoi (value); - - /* Can only set one of miimon and arp_interval */ - if (miimon > 0 && arp_interval > 0) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("only one of '%s' and '%s' can be set"), - NM_SETTING_BOND_OPTION_MIIMON, - NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } + 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)); + 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)); + + /* Option restrictions: + * + * 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 ] + * downdelay needs miimon + * updelay needs miimon + * primary needs [ active-backup, tlb, alb ] + */ /* Verify bond mode */ - mode_orig = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE); - if (!mode_orig) { + mode_str = _bond_get_option (self, NM_SETTING_BOND_OPTION_MODE); + if (!mode_str) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -591,34 +791,42 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } - mode = nm_utils_bond_mode_string_to_int (mode_orig); - if (mode == -1) { + bond_mode = _nm_setting_bond_mode_from_string (mode_str); + if (bond_mode == NM_BOND_MODE_UNKNOWN) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid value for '%s'"), - value, NM_SETTING_BOND_OPTION_MODE); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + mode_str, + NM_SETTING_BOND_OPTION_MODE); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } - 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_SET (bond_mode, NM_BOND_MODE_TLB, + NM_BOND_MODE_ALB)) { if (arp_interval > 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_new, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_MODE, + mode_str, + NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } } - primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY); - if (strcmp (mode_new, "active-backup") == 0) { + primary = _bond_get_option (self, NM_SETTING_BOND_OPTION_PRIMARY); + if (bond_mode == NM_BOND_MODE_ACTIVEBACKUP) { GError *tmp_error = NULL; if (primary && !nm_utils_ifname_valid_kernel (primary, &tmp_error)) { @@ -627,58 +835,64 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not valid for the '%s' option: %s"), primary, NM_SETTING_BOND_OPTION_PRIMARY, tmp_error->message); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); g_error_free (tmp_error); return FALSE; } - } else { - if (primary) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option is only valid for '%s=%s'"), - NM_SETTING_BOND_OPTION_PRIMARY, - NM_SETTING_BOND_OPTION_MODE, "active-backup"); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } + } else if (primary) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is only valid for '%s=%s'"), + NM_SETTING_BOND_OPTION_PRIMARY, + NM_SETTING_BOND_OPTION_MODE, "active-backup"); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; } - if (connection && nm_connection_get_setting_infiniband (connection)) { - if (strcmp (mode_new, "active-backup") != 0) { + if ( connection + && nm_connection_get_setting_infiniband (connection)) { + if (bond_mode != NM_BOND_MODE_ACTIVEBACKUP) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s=%s' is not a valid configuration for '%s'"), - NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_INFINIBAND_SETTING_NAME); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_MODE, mode_str, NM_SETTING_INFINIBAND_SETTING_NAME); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } if (miimon == 0) { - gpointer delayopt; - /* updelay and downdelay need miimon to be enabled to be valid */ - delayopt = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_UPDELAY); - if (delayopt && _atoi (delayopt) > 0) { + if (_atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_UPDELAY))) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be enabled"), NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } - delayopt = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY); - if (delayopt && _atoi (delayopt) > 0) { + if (_atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_DOWNDELAY))) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be enabled"), NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } } @@ -686,19 +900,22 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) /* arp_ip_target can only be used with arp_interval, and must * contain a comma-separated list of IPv4 addresses. */ - arp_ip_target = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + arp_ip_target = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (arp_interval > 0) { char **addrs; guint32 addr; - int i; if (!arp_ip_target) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), - NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } @@ -709,7 +926,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is empty"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } @@ -720,8 +939,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid IPv4 address for '%s' option"), - NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + addrs[i]); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } @@ -733,17 +956,19 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), - NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_ARP_IP_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 = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_LACP_RATE); + lacp_rate = _bond_get_option (self, 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) { + && bond_mode != NM_BOND_MODE_8023AD + && !NM_IN_STRSET (lacp_rate, "0", "slow")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -753,8 +978,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if ( (num_grat_arp != -1 && num_unsol_na != -1) - && (num_grat_arp != num_unsol_na)) { + 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) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -770,7 +996,14 @@ 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_IN_STRSET (mode_str, + "802.3ad", + "active-backup", + "balance-rr", + "balance-alb", + "balance-tlb", + "balance-xor", + "broadcast")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -781,18 +1014,18 @@ 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); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + n->name, mode_str); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return NM_SETTING_VERIFY_NORMALIZABLE; } } @@ -807,9 +1040,8 @@ options_equal_asym (NMSettingBond *s_bond, NMSettingBond *s_bond2, NMSettingCompareFlags flags) { - GHashTable *options2 = NM_SETTING_BOND_GET_PRIVATE (s_bond2)->options; GHashTableIter iter; - const char *key, *value, *value2; + const char *key, *value; g_hash_table_iter_init (&iter, NM_SETTING_BOND_GET_PRIVATE (s_bond)->options); while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { @@ -824,18 +1056,7 @@ options_equal_asym (NMSettingBond *s_bond, continue; } - value2 = g_hash_table_lookup (options2, key); - - if (!value2) { - if (nm_streq (key, "num_grat_arp")) - value2 = g_hash_table_lookup (options2, "num_unsol_na"); - else if (nm_streq (key, "num_unsol_na")) - value2 = g_hash_table_lookup (options2, "num_grat_arp"); - } - - if (!value2) - value2 = nm_setting_bond_get_option_default (s_bond2, key); - if (!nm_streq (value, value2)) + if (!nm_streq0 (value, _bond_get_option (s_bond2, key))) return FALSE; } |