summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-02-19 10:52:21 +0100
committerThomas Haller <thaller@redhat.com>2020-02-19 17:15:26 +0100
commit18c8f43c34f9bac9d751b93b0ac8ce0874f0774c (patch)
tree91765885dd527381f611c1e21aa56f27bab7b264
parent957bb2e1116091b4bc62b864546e8a46f58a15e4 (diff)
downloadNetworkManager-18c8f43c34f9bac9d751b93b0ac8ce0874f0774c.tar.gz
libnm: use binary search for finding bond options to validate
-rw-r--r--libnm-core/nm-core-internal.h1
-rw-r--r--libnm-core/nm-setting-bond.c272
2 files changed, 171 insertions, 102 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 f33f481404..ce651f9f35 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 } },
+);
/*****************************************************************************/
@@ -157,14 +244,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 +260,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 +330,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;
}
@@ -391,16 +475,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 +489,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 +520,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 (