summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2013-07-02 11:43:47 -0400
committerThomas Haller <thaller@redhat.com>2013-12-04 20:42:46 +0100
commit5348a72af8657a9a48cd2b6628248f3c7d8cf80e (patch)
tree06086f70f954fe1d0f064fef884318a6d53e6d23
parentc0e09de2b71299ea0fa54244107c24da6e8236cf (diff)
downloadNetworkManager-th/bondprobs.tar.gz
bond: add proper properties to NMSettingBondth/wip/bondprobsth/bondprobs
Make NMSettingBond have individual properties like other settings types. https://bugzilla.redhat.com/show_bug.cgi?id=1032808 Co-Authored-By: Thomas Haller <thaller@redhat.com> Co-Authored-By: Dan Williams <dcbw@redhat.com> Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--cli/src/connections.c47
-rw-r--r--cli/src/settings.c45
-rw-r--r--cli/src/utils.h1
-rw-r--r--libnm-util/libnm-util.ver23
-rw-r--r--libnm-util/nm-setting-bond.c1852
-rw-r--r--libnm-util/nm-setting-bond.h103
-rw-r--r--libnm-util/tests/test-general.c8
-rw-r--r--src/devices/nm-device-bond.c160
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c171
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c6
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c29
-rw-r--r--src/settings/plugins/keyfile/reader.c2
12 files changed, 1832 insertions, 615 deletions
diff --git a/cli/src/connections.c b/cli/src/connections.c
index f2eaddee3d..6c8de1d282 100644
--- a/cli/src/connections.c
+++ b/cli/src/connections.c
@@ -3739,14 +3739,15 @@ cleanup_vlan:
char *bond_arpinterval = NULL;
const char *bond_arpiptarget_c = NULL;
char *bond_arpiptarget = NULL;
- nmc_arg_t exp_args[] = { {"mode", TRUE, &bond_mode_c, FALSE},
- {"primary", TRUE, &bond_primary_c, FALSE},
- {"miimon", TRUE, &bond_miimon_c, FALSE},
- {"downdelay", TRUE, &bond_downdelay_c, FALSE},
- {"updelay", TRUE, &bond_updelay_c, FALSE},
- {"arp-interval", TRUE, &bond_arpinterval_c, FALSE},
- {"arp-ip-target", TRUE, &bond_arpiptarget_c, FALSE},
+ nmc_arg_t exp_args[] = { {NM_SETTING_BOND_MODE, TRUE, &bond_mode_c, FALSE, FALSE, &bond_mode},
+ {NM_SETTING_BOND_PRIMARY, TRUE, &bond_primary_c, FALSE, FALSE, &bond_primary},
+ {NM_SETTING_BOND_MIIMON, TRUE, &bond_miimon_c, FALSE, FALSE, &bond_miimon},
+ {NM_SETTING_BOND_DOWNDELAY, TRUE, &bond_downdelay_c, FALSE, FALSE, &bond_downdelay},
+ {NM_SETTING_BOND_UPDELAY, TRUE, &bond_updelay_c, FALSE, FALSE, &bond_updelay},
+ {NM_SETTING_BOND_ARP_INTERVAL, TRUE, &bond_arpinterval_c, FALSE, FALSE, &bond_arpinterval},
+ {NM_SETTING_BOND_ARP_IP_TARGET, TRUE, &bond_arpiptarget_c, FALSE, FALSE, &bond_arpiptarget},
{NULL} };
+ nmc_arg_t *option;
if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error))
return FALSE;
@@ -3780,7 +3781,9 @@ cleanup_vlan:
/* Set bond options */
g_object_set (s_bond, NM_SETTING_BOND_INTERFACE_NAME, bond_ifname, NULL);
+
if (bond_mode) {
+ /* resolve the bond option. */
GError *err = NULL;
const char *bm;
if (!(bm = nmc_bond_validate_mode (bond_mode, &err))) {
@@ -3789,27 +3792,25 @@ cleanup_vlan:
g_clear_error (&err);
goto cleanup_bond;
}
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MODE, bm);
+ g_free (bond_mode);
+ bond_mode = g_strdup (bm);
}
- if (bond_primary) {
- if (!nm_utils_iface_valid_name (bond_primary)) {
+ for(option = exp_args; option->name; option++) {
+ GError *err = NULL;
+ const char *value = *((const char **) option->value);
+ if (value && !nm_setting_bond_validate_string (option->name, value, &err)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
- _("Error: 'primary': '%s' is not a valid interface name."),
- bond_primary);
+ _("Error: '%s': %s."), option->name, err->message);
+ g_clear_error (&err);
goto cleanup_bond;
}
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_PRIMARY, bond_primary);
}
- if (bond_miimon)
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MIIMON, bond_miimon);
- if (bond_downdelay && strcmp (bond_downdelay, "0") != 0)
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, bond_downdelay);
- if (bond_updelay && strcmp (bond_updelay, "0") != 0)
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY, bond_updelay);
- if (bond_arpinterval && strcmp (bond_arpinterval, "0") != 0)
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL, bond_arpinterval);
- if (bond_arpiptarget)
- nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, bond_arpiptarget);
+ for(option = exp_args; option->name; option++) {
+ const char *value = *((const char **) option->value);
+
+ if (value)
+ nm_setting_bond_set_string (s_bond, option->name, *((char **) option->value));
+ }
success = TRUE;
cleanup_bond:
diff --git a/cli/src/settings.c b/cli/src/settings.c
index cf56cfbe98..84a162c001 100644
--- a/cli/src/settings.c
+++ b/cli/src/settings.c
@@ -1031,16 +1031,16 @@ nmc_property_bond_get_options (NMSetting *setting)
{
NMSettingBond *s_bond = NM_SETTING_BOND (setting);
GString *bond_options_s;
- int i;
+ const char *const* kernel_names;
bond_options_s = g_string_new (NULL);
- for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) {
- const char *key, *value;
-
- nm_setting_bond_get_option (s_bond, i, &key, &value);
- g_string_append_printf (bond_options_s, "%s=%s,", key, value);
+ kernel_names = nm_setting_bond_get_kernel_names ();
+ for (; *kernel_names; kernel_names++) {
+ g_string_append_printf (bond_options_s, "%s=%s,", *kernel_names,
+ nm_setting_bond_get_string (s_bond, *kernel_names));
}
- g_string_truncate (bond_options_s, bond_options_s->len-1); /* chop off trailing ',' */
+ if (bond_options_s->len > 0)
+ g_string_truncate (bond_options_s, bond_options_s->len-1); /* chop off trailing ',' */
return g_string_free (bond_options_s, FALSE);
}
@@ -2629,15 +2629,16 @@ static gboolean
_validate_and_remove_bond_option (NMSettingBond *setting, const char *option)
{
const char *opt;
- const char **valid_options;
+ const char *const*valid_options;
- valid_options = nm_setting_bond_get_valid_options (setting);
- opt = nmc_string_is_valid (option, valid_options, NULL);
+ valid_options = nm_setting_bond_get_kernel_names ();
+ opt = nmc_string_is_valid (option, (const char **) valid_options, NULL);
- if (opt)
- return nm_setting_bond_remove_option (setting, opt);
- else
+ if (!opt)
return FALSE;
+
+ nm_setting_bond_set_default (setting, opt);
+ return TRUE;
}
/* Validate bonding 'options' values */
@@ -2650,11 +2651,17 @@ _validate_bond_option_value (const char *option, const char *value, GError **err
return value;
}
+static const char **
+_nm_setting_bond_get_kernel_names (NMSettingBond *bond)
+{
+ return (const char **) nm_setting_bond_get_kernel_names ();
+}
+
DEFINE_SETTER_OPTIONS (nmc_property_bond_set_options,
NM_SETTING_BOND,
NMSettingBond,
- nm_setting_bond_add_option,
- nm_setting_bond_get_valid_options,
+ nm_setting_bond_set_string,
+ _nm_setting_bond_get_kernel_names,
_validate_bond_option_value)
DEFINE_REMOVER_OPTION (nmc_property_bond_remove_option_options,
NM_SETTING_BOND,
@@ -2664,11 +2671,11 @@ static const char *
nmc_property_bond_describe_options (NMSetting *setting, const char *prop)
{
static char *desc = NULL;
- const char **valid_options;
+ const char *const*valid_options;
char *options_str;
if (G_UNLIKELY (desc == NULL)) {
- valid_options = nm_setting_bond_get_valid_options (NM_SETTING_BOND (setting));
+ valid_options = nm_setting_bond_get_kernel_names ();
options_str = g_strjoinv (", ", (char **) valid_options);
desc = g_strdup_printf (_("Enter a list of bonding options formatted as:\n"
@@ -2691,11 +2698,11 @@ nmc_property_bond_describe_options (NMSetting *setting, const char *prop)
static const char *
nmc_property_bond_allowed_options (NMSetting *setting, const char *prop)
{
- const char **valid_options;
+ const char *const*valid_options;
static char *allowed_vals = NULL;
if (G_UNLIKELY (allowed_vals == NULL)) {
- valid_options = nm_setting_bond_get_valid_options (NM_SETTING_BOND (setting));
+ valid_options = nm_setting_bond_get_kernel_names ();
allowed_vals = g_strjoinv (", ", (char **) valid_options);
}
return allowed_vals;
diff --git a/cli/src/utils.h b/cli/src/utils.h
index c1c8824144..d6d6654203 100644
--- a/cli/src/utils.h
+++ b/cli/src/utils.h
@@ -32,6 +32,7 @@ typedef struct {
const char **value;
gboolean mandatory;
gboolean found;
+ void *user_data;
} nmc_arg_t;
/* === Functions === */
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index bcaa4260ae..00844df3ce 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -199,16 +199,37 @@ global:
nm_setting_bond_add_option;
nm_setting_bond_error_get_type;
nm_setting_bond_error_quark;
+ nm_setting_bond_get_ad_select;
+ nm_setting_bond_get_arp_interval;
+ nm_setting_bond_get_arp_ip_target;
+ nm_setting_bond_get_arp_validate;
+ nm_setting_bond_get_downdelay;
+ nm_setting_bond_get_fail_over_mac;
nm_setting_bond_get_interface_name;
+ nm_setting_bond_get_kernel_name;
+ nm_setting_bond_get_kernel_names;
+ nm_setting_bond_get_miimon;
+ nm_setting_bond_get_mode;
nm_setting_bond_get_num_options;
nm_setting_bond_get_option;
nm_setting_bond_get_option_by_name;
nm_setting_bond_get_option_default;
+ nm_setting_bond_get_primary;
+ nm_setting_bond_get_primary_reselect;
+ nm_setting_bond_get_property_name;
+ nm_setting_bond_get_resend_igmp;
+ nm_setting_bond_get_string;
nm_setting_bond_get_type;
+ nm_setting_bond_get_updelay;
+ nm_setting_bond_get_use_carrier;
nm_setting_bond_get_valid_options;
+ nm_setting_bond_get_xmit_hash_policy;
+ nm_setting_bond_is_default;
nm_setting_bond_new;
nm_setting_bond_remove_option;
- nm_setting_bond_validate_option;
+ nm_setting_bond_set_default;
+ nm_setting_bond_set_string;
+ nm_setting_bond_validate_string;
nm_setting_bridge_error_get_type;
nm_setting_bridge_error_quark;
nm_setting_bridge_get_ageing_time;
diff --git a/libnm-util/nm-setting-bond.c b/libnm-util/nm-setting-bond.c
index 3459300ec9..39e1494de3 100644
--- a/libnm-util/nm-setting-bond.c
+++ b/libnm-util/nm-setting-bond.c
@@ -34,6 +34,7 @@
#include "nm-utils.h"
#include "nm-utils-private.h"
#include "nm-dbus-glib-types.h"
+#include "nm-glib-compat.h"
#include "nm-setting-private.h"
/**
@@ -74,17 +75,52 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BOND)
typedef struct {
char *interface_name;
+
+ char *mode;
+ int miimon;
+ int downdelay;
+ int updelay;
+ int arp_interval;
+ char **arp_ip_target;
+ char *arp_validate;
+ char *primary;
+ char *primary_reselect;
+ char *fail_over_mac;
+ int use_carrier;
+ char *ad_select;
+ char *xmit_hash_policy;
+ int resend_igmp;
+
GHashTable *options;
} NMSettingBondPrivate;
enum {
PROP_0,
PROP_INTERFACE_NAME,
+
+ PROP_MODE,
+ PROP_MIIMON,
+ PROP_DOWNDELAY,
+ PROP_UPDELAY,
+ PROP_ARP_INTERVAL,
+ PROP_ARP_IP_TARGET,
+ PROP_ARP_VALIDATE,
+ PROP_PRIMARY,
+ PROP_PRIMARY_RESELECT,
+ PROP_FAIL_OVER_MAC,
+ PROP_USE_CARRIER,
+ PROP_AD_SELECT,
+ PROP_XMIT_HASH_POLICY,
+ PROP_RESEND_IGMP,
+
PROP_OPTIONS,
LAST_PROP
};
+#define _FIRST_KERNEL_PROP PROP_MODE
+#define _LAST_KERNEL_PROP PROP_RESEND_IGMP
enum {
+ TYPE_NONE, /* must be 0, so that it is the default in props if not explicitly set. */
TYPE_INT,
TYPE_STR,
TYPE_BOTH,
@@ -93,35 +129,37 @@ enum {
};
typedef struct {
- const char *opt;
- const char *val;
guint opt_type;
- guint min;
- guint max;
- char *list[10];
-} BondDefault;
-
-static const BondDefault defaults[] = {
- { NM_SETTING_BOND_OPTION_MODE, "balance-rr", TYPE_BOTH, 0, 6,
- { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } },
- { NM_SETTING_BOND_OPTION_MIIMON, "100", TYPE_INT, 0, G_MAXINT },
- { NM_SETTING_BOND_OPTION_DOWNDELAY, "0", TYPE_INT, 0, G_MAXINT },
- { NM_SETTING_BOND_OPTION_UPDELAY, "0", TYPE_INT, 0, G_MAXINT },
- { NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0", TYPE_INT, 0, G_MAXINT },
- { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "", TYPE_IP },
- { NM_SETTING_BOND_OPTION_ARP_VALIDATE, "0", TYPE_BOTH, 0, 3,
- { "none", "active", "backup", "all", NULL } },
- { NM_SETTING_BOND_OPTION_PRIMARY, "", TYPE_IFNAME },
- { NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "0", TYPE_BOTH, 0, 2,
- { "always", "better", "failure", NULL } },
- { NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, "0", TYPE_BOTH, 0, 2,
- { "none", "active", "follow", NULL } },
- { NM_SETTING_BOND_OPTION_USE_CARRIER, "1", TYPE_INT, 0, 1 },
- { NM_SETTING_BOND_OPTION_AD_SELECT, "0", TYPE_BOTH, 0, 2,
- { "stable", "bandwidth", "count", NULL } },
- { NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "0", TYPE_BOTH, 0, 2,
- { "layer2", "layer3+4", "layer2+3", NULL } },
- { NM_SETTING_BOND_OPTION_RESEND_IGMP, "1", TYPE_INT, 0, 255 },
+ const char *kernel_name;
+ const char *list[7];
+ const char *list_sentinel[1]; /* dummy, to NULL terminate the previous 'list' array */
+ GParamSpec *pspec;
+ char *defval;
+} BondProperty;
+
+static BondProperty props[LAST_PROP] = {
+ /* specifying the kernel name is only necessary, when it differs from the property name. */
+
+ [PROP_MODE] = { TYPE_BOTH, NULL,
+ { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb" } },
+ [PROP_MIIMON] = { TYPE_INT },
+ [PROP_DOWNDELAY] = { TYPE_INT },
+ [PROP_UPDELAY] = { TYPE_INT },
+ [PROP_ARP_INTERVAL] = { TYPE_INT, NM_SETTING_BOND_OPTION_ARP_INTERVAL },
+ [PROP_ARP_IP_TARGET] = { TYPE_IP, NM_SETTING_BOND_OPTION_ARP_IP_TARGET },
+ [PROP_ARP_VALIDATE] = { TYPE_BOTH, NM_SETTING_BOND_OPTION_ARP_VALIDATE,
+ { "none", "active", "backup", "all" } },
+ [PROP_PRIMARY] = { TYPE_IFNAME },
+ [PROP_PRIMARY_RESELECT] = { TYPE_BOTH, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT,
+ { "always", "better", "failure" } },
+ [PROP_FAIL_OVER_MAC] = { TYPE_BOTH, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,
+ { "none", "active", "follow" } },
+ [PROP_USE_CARRIER] = { TYPE_INT, NM_SETTING_BOND_OPTION_USE_CARRIER },
+ [PROP_AD_SELECT] = { TYPE_BOTH, NM_SETTING_BOND_OPTION_AD_SELECT,
+ { "stable", "bandwidth", "count" } },
+ [PROP_XMIT_HASH_POLICY] = { TYPE_STR, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY,
+ { "layer2", "layer2+3", "layer3+4", "encap2+3", "encap3+4" } },
+ [PROP_RESEND_IGMP] = { TYPE_INT, NM_SETTING_BOND_OPTION_RESEND_IGMP },
};
/**
@@ -137,6 +175,8 @@ nm_setting_bond_new (void)
return (NMSetting *) g_object_new (NM_TYPE_SETTING_BOND, NULL);
}
+/*****************************************************************************/
+
/**
* nm_setting_bond_get_interface_name:
* @setting: the #NMSettingBond
@@ -144,7 +184,7 @@ nm_setting_bond_new (void)
* Returns: the #NMSettingBond:interface-name property of the setting
**/
const char *
-nm_setting_bond_get_interface_name (NMSettingBond *setting)
+nm_setting_bond_get_interface_name (const NMSettingBond *setting)
{
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
@@ -152,178 +192,796 @@ nm_setting_bond_get_interface_name (NMSettingBond *setting)
}
/**
- * nm_setting_bond_get_num_options:
+ * nm_setting_bond_get_mode:
* @setting: the #NMSettingBond
*
- * Returns the number of options that should be set for this bond when it
- * is activated. This can be used to retrieve each option individually
- * using nm_setting_bond_get_option().
+ * Returns: the #NMSettingBond:mode property of the setting
*
- * Returns: the number of bonding options
+ * Since: 0.9.10
**/
-guint32
-nm_setting_bond_get_num_options (NMSettingBond *setting)
+const char *
+nm_setting_bond_get_mode (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->mode;
+}
+
+/**
+ * nm_setting_bond_get_miimon:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:miimon property of the setting
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_bond_get_miimon (const NMSettingBond *setting)
{
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
- return g_hash_table_size (NM_SETTING_BOND_GET_PRIVATE (setting)->options);
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->miimon;
}
/**
- * nm_setting_bond_get_option:
+ * nm_setting_bond_get_downdelay:
* @setting: the #NMSettingBond
- * @idx: index of the desired option, from 0 to
- * nm_setting_bond_get_num_options() - 1
- * @out_name: (out): on return, the name of the bonding option; this
- * value is owned by the setting and should not be modified
- * @out_value: (out): on return, the value of the name of the bonding
- * option; this value is owned by the setting and should not be modified
*
- * Given an index, return the value of the bonding option at that index. Indexes
- * are *not* guaranteed to be static across modifications to options done by
- * nm_setting_bond_add_option() and nm_setting_bond_remove_option(),
- * and should not be used to refer to options except for short periods of time
- * such as during option iteration.
+ * Returns: the #NMSettingBond:downdelay property of the setting
*
- * Returns: %TRUE on success if the index was valid and an option was found,
- * %FALSE if the index was invalid (ie, greater than the number of options
- * currently held by the setting)
+ * Since: 0.9.10
**/
-gboolean
-nm_setting_bond_get_option (NMSettingBond *setting,
- guint32 idx,
- const char **out_name,
- const char **out_value)
+guint
+nm_setting_bond_get_downdelay (const NMSettingBond *setting)
{
- NMSettingBondPrivate *priv;
- GList *keys;
- const char *_key = NULL, *_value = NULL;
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->downdelay;
+}
+
+/**
+ * nm_setting_bond_get_updelay:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:updelay property of the setting
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_bond_get_updelay (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->updelay;
+}
+
+/**
+ * nm_setting_bond_get_arp_interval:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:arp-interval property of the setting
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_bond_get_arp_interval (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->arp_interval;
+}
+
+/**
+ * nm_setting_bond_get_arp_ip_target:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: (transfer none): the #NMSettingBond:arp-ip-target property
+ * of the setting (which belongs to the setting and must not be freed).
+ *
+ * Since: 0.9.10
+ **/
+const char *const*
+nm_setting_bond_get_arp_ip_target (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ return (const char *const*) NM_SETTING_BOND_GET_PRIVATE (setting)->arp_ip_target;
+}
+
+/**
+ * nm_setting_bond_get_arp_validate:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:arp-validate property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_bond_get_arp_validate (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->arp_validate;
+}
+
+/**
+ * nm_setting_bond_get_primary:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:primary property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_bond_get_primary (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->primary;
+}
+
+/**
+ * nm_setting_bond_get_primary_reselect:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:primary-reselect property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_bond_get_primary_reselect (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->primary_reselect;
+}
+
+/**
+ * nm_setting_bond_get_fail_over_mac:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:fail-over-mac property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_bond_get_fail_over_mac (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->fail_over_mac;
+}
+
+/**
+ * nm_setting_bond_get_use_carrier:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:use-carrier property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_bond_get_use_carrier (const NMSettingBond *setting)
+{
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
- priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->use_carrier;
+}
- if (idx >= nm_setting_bond_get_num_options (setting))
- return FALSE;
+/**
+ * nm_setting_bond_get_ad_select:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:ad-select property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_bond_get_ad_select (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
- keys = g_hash_table_get_keys (priv->options);
- _key = g_list_nth_data (keys, idx);
- _value = g_hash_table_lookup (priv->options, _key);
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->ad_select;
+}
- if (out_name)
- *out_name = _key;
- if (out_value)
- *out_value = _value;
+/**
+ * nm_setting_bond_get_xmit_hash_policy:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:xmit-hash-policy property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_bond_get_xmit_hash_policy (const NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
- g_list_free (keys);
- return TRUE;
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->xmit_hash_policy;
}
-static gboolean
-validate_int (const char *name, const char *value, const BondDefault *def)
+/**
+ * nm_setting_bond_get_resend_igmp:
+ * @setting: the #NMSettingBond
+ *
+ * Returns: the #NMSettingBond:resend-igmp property of the setting
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_bond_get_resend_igmp (const NMSettingBond *setting)
{
- glong num;
- guint i;
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
- for (i = 0; i < strlen (value); i++) {
- if (!g_ascii_isdigit (value[i]) && value[i] != '-')
- return FALSE;
+ return NM_SETTING_BOND_GET_PRIVATE (setting)->resend_igmp;
+}
+
+/*****************************************************************************/
+
+static BondProperty *
+find_property_by_pspec (const GParamSpec *pspec, guint *out_idx, gboolean kernel_only)
+{
+ guint i = kernel_only ? _FIRST_KERNEL_PROP : PROP_0 + 1;
+ guint end = kernel_only ? _LAST_KERNEL_PROP + 1 : LAST_PROP;
+
+ g_return_val_if_fail (pspec != NULL, NULL);
+
+ for (; i < end; i++) {
+ if (props[i].pspec == pspec) {
+ if (out_idx)
+ *out_idx = i;
+ return &props[i];
+ }
}
+ if (out_idx)
+ *out_idx = LAST_PROP;
+ return NULL;
+}
- errno = 0;
- num = strtol (value, NULL, 10);
- if (errno)
- return FALSE;
- if (num < def->min || num > def->max)
+/* Depending on kernel_only, find only kernel properties. */
+static BondProperty *
+find_property_by_name (const char *name, guint *out_idx, gboolean kernel_only)
+{
+ guint i = kernel_only ? _FIRST_KERNEL_PROP : PROP_0 + 1;
+ guint end = kernel_only ? _LAST_KERNEL_PROP + 1 : LAST_PROP;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ for (; i < end; i++) {
+ const char *new_name = g_param_spec_get_name (props[i].pspec);
+
+ if (strcmp (name, new_name) == 0 || g_strcmp0 (name, props[i].kernel_name) == 0) {
+ if (out_idx)
+ *out_idx = i;
+ return &props[i];
+ }
+ }
+ if (out_idx)
+ *out_idx = LAST_PROP;
+ return NULL;
+}
+
+/* For a property or kernel name, returns the property name */
+static const char *
+get_property_name (const BondProperty *prop)
+{
+ return prop ? g_param_spec_get_name (prop->pspec) : NULL;
+}
+
+/* For a property or kernel name, returns the kernel option name */
+static const char *
+get_kernel_name (const BondProperty *prop)
+{
+ if (!prop)
+ return NULL;
+ return prop->kernel_name ? prop->kernel_name : g_param_spec_get_name (prop->pspec);
+}
+
+static gboolean
+int_from_string (const char *s, glong *out_num)
+{
+ long int n;
+ char *end;
+
+ if (!s)
return FALSE;
+ errno = 0;
+ n = strtol (s, &end, 10);
+ if (out_num)
+ *out_num = n;
+ return !errno && !*end;
+}
- return TRUE;
+static gboolean
+validate_int (const BondProperty *prop, const char *value, int *out_num)
+{
+ GParamSpecInt *ispec;
+ glong num = 0;
+ gboolean success = FALSE;
+
+ g_assert (G_IS_PARAM_SPEC_INT (prop->pspec));
+ if (!int_from_string (value, &num))
+ goto out;
+
+ ispec = G_PARAM_SPEC_INT (prop->pspec);
+ success = (num >= ispec->minimum && num <= ispec->maximum);
+out:
+ if (out_num)
+ *out_num = success ? num : 0;
+ return success;
}
static gboolean
-validate_list (const char *name, const char *value, const BondDefault *def)
+validate_list (const BondProperty *prop, const char *value)
{
- guint i;
+ const char *const*ptr;
- for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) {
- if (g_strcmp0 (def->list[i], value) == 0)
- return TRUE;
+ if (value) {
+ for (ptr = prop->list; *ptr; ptr++) {
+ if (strcmp (*ptr, value) == 0)
+ return TRUE;
+ }
}
-
- /* empty validation list means all values pass */
- return def->list[0] == NULL ? TRUE : FALSE;
+ return FALSE;
}
+/* by making it a macro, we don't have to worry about using glong as type of idx (otherwise, we would have to check for integer overflow too. */
+#define IS_VALID_LIST_INDEX(prop, idx) ( ((idx) >= 0) && ((idx) < g_strv_length ((char **) (prop)->list)) )
+
static gboolean
-validate_ip (const char *name, const char *value)
+validate_both (const BondProperty *prop, const char *value)
+{
+ glong num = -1;
+
+ if (!value)
+ return FALSE;
+
+ if (validate_list (prop, value))
+ return TRUE;
+
+ if (!int_from_string (value, &num))
+ return FALSE;
+
+ /* Ensure number is within bounds of string list */
+ return IS_VALID_LIST_INDEX (prop, num);
+}
+
+static char **
+parse_ip (const char *value, gboolean warn_on_error)
{
char **ips, **iter;
- gboolean success = TRUE;
struct in_addr addr;
- if (!value || !value[0])
+ if (!value || !value[0]) {
+ /* missing value is valid, just return NULL instead of an empty array. */
+ return NULL;
+ }
+
+ /* lets be more forgiving when accepting the input string. */
+ ips = g_strsplit_set (value, " ,", 0);
+ for (iter = ips; *iter; iter++) {
+ if (!*iter) {
+ /* don't be so strict, just skip over empty values. */
+ continue;
+ }
+ if (!inet_aton (*iter, &addr)) {
+ g_strfreev (ips);
+ g_return_val_if_fail (!warn_on_error, NULL);
+ return NULL;
+ }
+ }
+ return ips;
+}
+
+static gboolean
+validate_ip (const char *value)
+{
+ char **ips;
+
+ if (!value || !value[0]) {
+ /* there is only one TYPE_IP, and that property is not mandatory.
+ * Accept empty as valid.
+ **/
+ return TRUE;
+ }
+
+ /* make reuse of parse_ip, as it should validate the input anyway. */
+ ips = parse_ip (value, FALSE);
+ if (!ips)
return FALSE;
- ips = g_strsplit_set (value, ",", 0);
- for (iter = ips; iter && *iter && success; iter++)
- success = !!inet_aton (*iter, &addr);
g_strfreev (ips);
-
- return success;
+ return TRUE;
}
static gboolean
-validate_ifname (const char *name, const char *value)
+validate_ifname (const char *value)
{
- if (!value || !value[0])
- return FALSE;
+ if (!value || !value[0]) {
+ /* there is only one TYPE_IFNAME, and that property is not mandatory.
+ * Accept empty as valid.
+ **/
+ return TRUE;
+ }
return nm_utils_iface_valid_name (value);
}
+/* Checks whether @value is is a valid value for @prop.
+ *
+ * Returns: TRUE, if the @value is valid for the given name.
+ * If @value is NULL, false will be returned.
+ **/
+static gboolean
+validate_property (const BondProperty *prop, const char *value)
+{
+ switch (prop->opt_type) {
+ case TYPE_INT:
+ return validate_int (prop, value, NULL);
+ case TYPE_STR:
+ return validate_list (prop, value);
+ case TYPE_BOTH:
+ return validate_both (prop, value);
+ case TYPE_IP:
+ return validate_ip (value);
+ case TYPE_IFNAME:
+ return validate_ifname (value);
+ case TYPE_NONE:
+ default:
+ g_assert_not_reached();
+ }
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+const char *
+nm_setting_bond_get_property_name (const char *name)
+{
+ return get_property_name (find_property_by_name (name, NULL, TRUE));
+}
+
+const char *
+nm_setting_bond_get_kernel_name (const char *name)
+{
+ return get_kernel_name (find_property_by_name (name, NULL, TRUE));
+}
+
+const char *const*
+nm_setting_bond_get_kernel_names ()
+{
+ static const char *array[_LAST_KERNEL_PROP - _FIRST_KERNEL_PROP + 1 + 1] = { NULL };
+
+ /* initialize the array once */
+ if (G_UNLIKELY (array[0] == NULL)) {
+ guint prop, i;
+
+ for (prop = _FIRST_KERNEL_PROP, i = 0; prop <= _LAST_KERNEL_PROP; prop++, i++)
+ array[i] = get_kernel_name (&props[prop]);
+ }
+
+ return array;
+}
+
/**
- * nm_setting_bond_validate_option:
- * @name: the name of the option to validate
- * @value: the value of the option to validate
+ * nm_setting_bond_get_string:
+ * @setting: the #NMSettingBond
+ * @name: the option name for which to retrieve the value
*
- * Checks whether @name is a valid bond option and @value is a valid value for
- * the @name. If @value is NULL, the function only validates the option name.
+ * Returns the value for the given name, converted to string.
*
- * Returns: TRUE, if the @value is valid for the given name.
- * If the @name is not a valid option, FALSE will be returned.
+ * Returns: the value as string, or %NULL if the name does not
+ * exist.
+ **/
+const char *
+nm_setting_bond_get_string (const NMSettingBond *setting,
+ const char *name)
+{
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+ const char *value;
+ gboolean result;
+ BondProperty *prop;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ if (!name)
+ return NULL;
+
+ result = g_hash_table_lookup_extended (priv->options, name, NULL, (void **) &value);
+ if (result)
+ return value;
+
+ /* Try to lookup by property name instead of the kernel name that is used
+ * to index the options hash table... */
+ prop = find_property_by_name (name, NULL, TRUE);
+ if (!prop)
+ return NULL;
+
+ /* 'name' is a valid property name, but we did not find it in the options hash.
+ * Since every element *must* be in the options hash, this can only mean, that
+ * the user tried to lookup by property name for items that have a different
+ * kernel_name. Support lookup by this alias. */
+ result = g_hash_table_lookup_extended (priv->options, get_kernel_name (prop), NULL, (void **) &value);
+ g_assert (result);
+
+ return value;
+}
+
+gboolean
+nm_setting_bond_is_default (const NMSettingBond *setting, const char *name, GValue *default_value)
+{
+ GValue val = G_VALUE_INIT;
+ GValue def = G_VALUE_INIT;
+ BondProperty *prop;
+ gboolean is_default;
+
+ if (!NM_IS_SETTING_BOND (setting))
+ goto ERROR_OUT;
+ prop = find_property_by_name (name, NULL, TRUE);
+ if (!prop)
+ goto ERROR_OUT;
+
+ g_value_init (&val, prop->pspec->value_type);
+ g_value_init (&def, prop->pspec->value_type);
+
+ g_object_get_property (G_OBJECT (setting), get_property_name (prop), &val);
+ g_param_value_set_default (prop->pspec, &def);
+
+ if (G_VALUE_HOLDS_INT (&val))
+ is_default = g_value_get_int (&val) == g_value_get_int (&def);
+ else if (G_VALUE_HOLDS_STRING (&val))
+ is_default = g_strcmp0 (g_value_get_string (&val), g_value_get_string (&def)) == 0;
+ else if (G_VALUE_HOLDS (&val, G_TYPE_STRV)) {
+ char **v, **d;
+
+ v = (char **) g_value_get_boxed (&val);
+ d = (char **) g_value_get_boxed (&def);
+
+ is_default = v == d;
+ if (!is_default && v && d) {
+ /* We know, that our only STRV type (ARP_IP_TARGET) has a default value of NULL,
+ * so don't implement any further comparison now. */
+ g_assert_not_reached ();
+ }
+ } else
+ g_assert_not_reached();
+
+ if (default_value)
+ g_value_copy (&def, default_value);
+
+ g_value_unset (&val);
+ g_value_unset (&def);
+
+ return is_default;
+
+ERROR_OUT:
+ if (default_value)
+ g_value_unset (default_value);
+ g_return_val_if_fail (FALSE, FALSE);
+ return FALSE;
+}
+
+/**
+ * nm_setting_bond_set_string:
+ * @setting: the #NMSettingBond
+ * @name: name for the option
+ * @value: value for the option
+ *
+ * Set a parameter to a value given as string. The value will be
+ * converted into the proper type. If the string cannot be converted
+ * the function does nothing and returns %FALSE.
+ *
+ * Returns: %TRUE if the option was valid and successfully set, %FALSE if it was not.
*
* Since: 0.9.10
**/
gboolean
-nm_setting_bond_validate_option (const char *name,
- const char *value)
+nm_setting_bond_set_string (NMSettingBond *setting,
+ const char *name,
+ const char *value)
{
- guint i;
+ NMSettingBondPrivate *priv;
+ GObject *object = G_OBJECT (setting);
+ const BondProperty *prop = NULL;
+ const char *prop_name;
+ glong num = 0;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
+
+ priv = NM_SETTING_BOND_GET_PRIVATE (setting);
- if (!name || !name[0])
+ prop = find_property_by_name (name, NULL, TRUE);
+ prop_name = get_property_name (prop);
+ if (!prop_name)
+ return FALSE;
+ if (!validate_property (prop, value))
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 TYPE_INT:
- return validate_int (name, value, &defaults[i]);
- case TYPE_STR:
- return validate_list (name, value, &defaults[i]);
- case TYPE_BOTH:
- return validate_int (name, value, &defaults[i])
- || validate_list (name, value, &defaults[i]);
- case TYPE_IP:
- return validate_ip (name, value);
- case TYPE_IFNAME:
- return validate_ifname (name, value);
- }
- return FALSE;
+ switch (prop->opt_type) {
+ case TYPE_INT:
+ if (!int_from_string (value, &num))
+ g_assert_not_reached ();
+ g_object_set (object, prop_name, (gint) num, NULL);
+ break;
+ case TYPE_BOTH: {
+ const char *str_value = value;
+
+ /* Might be an integer-as-string; find the string */
+ if (int_from_string (value, &num)) {
+ /* FIXME: do we really want to coerce the value? verify() currently accepts numeric values
+ * for the TYPE_BOTH items. NMDeviceBond has to cope with the ambiguity of the options
+ * names anyway. It might be better, to support the same names as the kernel does,
+ * including numeric values. Also, when reading the value from sysfs, we will also
+ * encounter numeric values (so, either we ~always~ coerce -> set_property), or not at all.
+ **/
+ str_value = prop->list[num];
}
+ g_object_set (object, prop_name, str_value, NULL);
+ break;
}
- return FALSE;
+ case TYPE_IFNAME:
+ case TYPE_STR:
+ g_object_set (object, prop_name, value, NULL);
+ break;
+ case TYPE_IP: {
+ char **ip = parse_ip (value, TRUE);
+
+ g_object_set (object, prop_name, ip, NULL);
+ g_strfreev (ip);
+ break;
+ }
+ case TYPE_NONE:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_bond_set_default:
+ * @setting: the #NMSettingBond
+ * @name: name of the option to remove
+ *
+ * Resets the bonding option to the default value.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_bond_set_default (NMSettingBond *setting,
+ const char *name)
+{
+ GObject *object = G_OBJECT (setting);
+ NMSettingBondPrivate *priv;
+ const BondProperty *prop;
+ const char *prop_name;
+ GValue defval = G_VALUE_INIT;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
+ priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+
+ prop = find_property_by_name (name, NULL, TRUE);
+ prop_name = get_property_name (prop);
+ if (!prop_name)
+ return;
+
+ g_value_init (&defval, prop->pspec->value_type);
+ g_param_value_set_default (prop->pspec, &defval);
+ g_object_set_property (object, prop_name, &defval);
+ g_value_unset (&defval);
+}
+
+/**
+ * nm_setting_bond_validate_default:
+ * @name: the name of the option
+ * @value: name value to be validated.
+ * @error: (out) (allow-none): The error description
+ *
+ * Validates a given name and value, where the value is as string.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_bond_validate_string (const char *name, const char *value, GError **error)
+{
+ const BondProperty *prop = find_property_by_name (name, NULL, TRUE);
+
+ if (!prop) {
+ g_set_error_literal (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, name);
+ return FALSE;
+ }
+
+ if (!validate_property (prop, value)) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ value, name);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*****************************************************************************/
+
+/**
+ * nm_setting_bond_get_num_options:
+ * @setting: the #NMSettingBond
+ *
+ * Returns the number of options that are set in the legacy
+ * #NMSettingBond:options property. This does not include other bond
+ * properties which are not included in #NMSettingBond:options.
+ *
+ * Returns: the number of legacy bonding options
+ *
+ * Deprecated: use the option-specific getters instead.
+ **/
+guint32
+nm_setting_bond_get_num_options (NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
+
+ return _LAST_KERNEL_PROP - _FIRST_KERNEL_PROP + 1;
+}
+
+/**
+ * nm_setting_bond_get_option:
+ * @setting: the #NMSettingBond
+ * @idx: index of the desired option, from 0 to
+ * nm_setting_bond_get_num_options() - 1
+ * @out_name: (out): on return, the name of the bonding option; this
+ * value is owned by the setting and should not be modified
+ * @out_value: (out): on return, the value of the name of the bonding
+ * option; this value is owned by the setting and should not be modified
+ *
+ * Given an index, return the value of the bonding option at that index. Indexes
+ * are *not* guaranteed to be static across modifications to options done by
+ * nm_setting_bond_add_option() and nm_setting_bond_remove_option(),
+ * and should not be used to refer to options except for short periods of time
+ * such as during option iteration.
+ *
+ * Returns: %TRUE on success if the index was valid and an option was found,
+ * %FALSE if the index was invalid (ie, greater than the number of options
+ * currently held by the setting)
+ *
+ * Deprecated: use the option-specific getters instead.
+ **/
+gboolean
+nm_setting_bond_get_option (NMSettingBond *setting,
+ guint32 idx,
+ const char **out_name,
+ const char **out_value)
+{
+ NMSettingBondPrivate *priv;
+ const char *kernel_name = NULL, *value = NULL;
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
+ priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+
+ if (idx >= _LAST_KERNEL_PROP - _FIRST_KERNEL_PROP)
+ goto out;
+ idx += _FIRST_KERNEL_PROP;
+
+ kernel_name = get_kernel_name (&props[idx]);
+ g_assert (kernel_name);
+ result = g_hash_table_lookup_extended (priv->options, kernel_name, NULL, (void **) &value);
+ g_assert (result);
+
+out:
+ if (out_name)
+ *out_name = kernel_name;
+ if (out_value)
+ *out_value = value;
+ return result;
}
/**
@@ -336,17 +994,14 @@ nm_setting_bond_validate_option (const char *name,
*
* Returns: the value, or %NULL if the key/value pair was never added to the
* setting; the value is owned by the setting and must not be modified
+ *
+ * Deprecated: use the option-specific getters instead.
**/
const char *
nm_setting_bond_get_option_by_name (NMSettingBond *setting,
const char *name)
{
- g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
-
- if (!nm_setting_bond_validate_option (name, NULL))
- return NULL;
-
- return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+ return nm_setting_bond_get_string (setting, name);
}
/**
@@ -357,45 +1012,20 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting,
*
* Add an option to the table. The option is compared to an internal list
* of allowed options. Option names may contain only alphanumeric characters
- * (ie [a-zA-Z0-9]). Adding a new name replaces any existing name/value pair
+ * (ie [a-zA-Z0-9_]). Adding a new name replaces any existing name/value pair
* that may already exist.
*
- * The order of how to set several options is relevant because there are options
- * that conflict with each other.
- *
* Returns: %TRUE if the option was valid and was added to the internal option
* list, %FALSE if it was not.
+ *
+ * Deprecated: use the option-specific properties instead or nm_setting_bond_set_string()
**/
gboolean
nm_setting_bond_add_option (NMSettingBond *setting,
const char *name,
const char *value)
{
- NMSettingBondPrivate *priv;
-
- g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
-
- if (!value || !nm_setting_bond_validate_option (name, value))
- return FALSE;
-
- priv = NM_SETTING_BOND_GET_PRIVATE (setting);
-
- 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);
- }
-
- g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
-
- return TRUE;
+ return nm_setting_bond_set_string (setting, name, value);
}
/**
@@ -404,26 +1034,24 @@ nm_setting_bond_add_option (NMSettingBond *setting,
* @name: name of the option to remove
*
* Remove the bonding option referenced by @name from the internal option
- * list.
+ * list. As the option list is deprected, you can no longer actually remove
+ * an item from the option hash. Removing it is now equivalent to resetting
+ * the default value.
*
* Returns: %TRUE if the option was found and removed from the internal option
* list, %FALSE if it was not.
+ *
+ * Deprecated: use the option-specific properties instead.
**/
gboolean
nm_setting_bond_remove_option (NMSettingBond *setting,
const char *name)
{
- gboolean found;
-
- g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
-
- if (!nm_setting_bond_validate_option (name, NULL))
- return FALSE;
-
- found = g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
- if (found)
- g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
- return found;
+ /* We don't really remove the property, instead we reset the default value.
+ * Thus, the number of options is always constant (all of them) and the option
+ * hash always contains every kernel option. */
+ nm_setting_bond_set_default (setting, name);
+ return TRUE;
}
/**
@@ -433,20 +1061,14 @@ nm_setting_bond_remove_option (NMSettingBond *setting,
* Returns a list of valid bond options.
*
* Returns: (transfer none): a %NULL-terminated array of strings of valid bond options.
+ *
+ * Deprecated: the valid options are defined by the #NMSettingBond
+ * properties.
**/
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 **) nm_setting_bond_get_kernel_names ();
}
/**
@@ -456,42 +1078,77 @@ nm_setting_bond_get_valid_options (NMSettingBond *setting)
*
* Returns: the value of the bond option if not overridden by an entry in
* the #NMSettingBond:options property.
+ *
+ * Deprecated: Use the default values of the option-specific properties.
**/
const char *
nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
{
- guint i;
+ BondProperty *prop;
+ GValue defval = G_VALUE_INIT;
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
- g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NULL);
- for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
- if (g_strcmp0 (defaults[i].opt, name) == 0)
- return defaults[i].val;
+ prop = find_property_by_name (name, NULL, TRUE);
+
+ if (!prop)
+ return NULL;
+
+ if (G_UNLIKELY (prop->defval == NULL)) {
+ g_value_init (&defval, prop->pspec->value_type);
+ g_param_value_set_default (prop->pspec, &defval);
+ prop->defval = g_strdup_value_contents (&defval);
+ g_value_unset (&defval);
+ g_return_val_if_fail (prop->defval, NULL);
+ }
+ return prop->defval;
+}
+
+/*****************************************************************/
+
+static void
+set_properties_from_hash (NMSettingBond *self, GHashTable *options)
+{
+ const char *value;
+ guint i;
+
+ g_object_freeze_notify (G_OBJECT (self));
+
+ /* Set each property to the value given by @options, or if not present
+ * in @options, to the default value.
+ */
+ for (i = _FIRST_KERNEL_PROP; i <= _LAST_KERNEL_PROP; i++) {
+ const char *property_name = get_property_name (&props[i]);
+ const char *kernel_name = get_kernel_name (&props[i]);
+ GValue defval = G_VALUE_INIT;
+
+ if (!g_hash_table_lookup_extended (options, kernel_name, NULL, (void **)&value)) {
+ /* for setting options, we also support the new property names instead
+ * of the kernel names
+ **/
+ if (!g_hash_table_lookup_extended (options, property_name, NULL, (void **)&value))
+ value = NULL;
+ }
+
+ if (value)
+ nm_setting_bond_set_string (self, kernel_name, value);
+ else {
+ g_value_init (&defval, props[i].pspec->value_type);
+ g_param_value_set_default (props[i].pspec, &defval);
+ g_object_set_property (G_OBJECT (self), property_name, &defval);
+ g_value_unset (&defval);
+ }
}
- /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */
- g_assert_not_reached ();
+
+ g_object_thaw_notify (G_OBJECT (self));
}
static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
- GHashTableIter iter;
- const char *key, *value;
- const char *valid_modes[] = { "balance-rr",
- "active-backup",
- "balance-xor",
- "broadcast",
- "802.3ad",
- "balance-tlb",
- "balance-alb",
- NULL };
- int miimon = 0, arp_interval = 0;
- const char *arp_ip_target = NULL;
- const char *primary;
-
- if (!priv->interface_name || !strlen(priv->interface_name)) {
+
+ if (!priv->interface_name || !strlen (priv->interface_name)) {
g_set_error_literal (error,
NM_SETTING_BOND_ERROR,
NM_SETTING_BOND_ERROR_MISSING_PROPERTY,
@@ -499,7 +1156,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME);
return FALSE;
}
-
if (!nm_utils_iface_valid_name (priv->interface_name)) {
g_set_error_literal (error,
NM_SETTING_BOND_ERROR,
@@ -509,185 +1165,215 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return FALSE;
}
- 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_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("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;
- }
- }
-
- 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);
-
/* Can only set one of miimon and arp_interval */
- if (miimon > 0 && arp_interval > 0) {
+ if (priv->miimon > 0 && priv->arp_interval > 0) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_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);
+ NM_SETTING_BOND_MIIMON,
+ NM_SETTING_BOND_ARP_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME,
+ priv->arp_ip_target == NULL && priv->arp_ip_target[0] ? NM_SETTING_BOND_ARP_INTERVAL : NM_SETTING_BOND_MIIMON);
}
- value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE);
- if (!value) {
+ if (!priv->mode) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_MISSING_OPTION,
- _("mandatory option '%s' is missing"),
- NM_SETTING_BOND_OPTION_MODE);
- g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ NM_SETTING_BOND_ERROR_MISSING_PROPERTY,
+ _("mandatory property '%s' is missing"),
+ NM_SETTING_BOND_MODE);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_MODE);
return FALSE;
}
- if (!_nm_utils_string_in_list (value, valid_modes)) {
+ if (!validate_property (&props[PROP_MODE], priv->mode)) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_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);
+ priv->mode, NM_SETTING_BOND_MODE);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_MODE);
return FALSE;
}
/* Make sure mode is compatible with other settings */
- if ( strcmp (value, "balance-alb") == 0
- || strcmp (value, "balance-tlb") == 0) {
- if (arp_interval > 0) {
+ if (__NM_SETTING_BOND_MODE_IS_balance_alb (priv->mode) ||
+ __NM_SETTING_BOND_MODE_IS_balance_tlb (priv->mode)) {
+ if (priv->arp_interval > 0) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
_("'%s=%s' is incompatible with '%s > 0'"),
- NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
- g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ NM_SETTING_BOND_MODE, priv->mode,
+ NM_SETTING_BOND_ARP_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_ARP_INTERVAL);
return FALSE;
}
}
- primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY);
- if (strcmp (value, "active-backup") == 0) {
- if (primary && !nm_utils_iface_valid_name (primary)) {
+ if (__NM_SETTING_BOND_MODE_IS_active_backup (priv->mode)) {
+ if (priv->primary && !nm_utils_iface_valid_name (priv->primary)) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%s' is not a valid interface name for '%s' option"),
- primary, NM_SETTING_BOND_OPTION_PRIMARY);
- g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid interface name"),
+ priv->primary);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_PRIMARY);
return FALSE;
}
} else {
- if (primary) {
+ if (priv->primary) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%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);
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is only valid for '%s=%s'"),
+ NM_SETTING_BOND_PRIMARY,
+ NM_SETTING_BOND_MODE, "active-backup");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_PRIMARY);
return FALSE;
}
}
if (nm_setting_find_in_list (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME)) {
- if (strcmp (value, "active-backup") != 0) {
+ if (__NM_SETTING_BOND_MODE_IS_active_backup (priv->mode)) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
_("'%s=%s' is not a valid configuration for '%s'"),
- NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_INFINIBAND_SETTING_NAME);
- g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ NM_SETTING_BOND_MODE, priv->mode,
+ NM_SETTING_INFINIBAND_SETTING_NAME);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_MODE);
return FALSE;
}
}
- if (miimon == 0) {
+ if (priv->miimon == 0) {
/* updelay and downdelay can only be used with miimon */
- if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_UPDELAY)) {
+ if (priv->updelay > 0) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%s' option requires '%s' option to be set"),
- 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);
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' property requires '%s' property to be set"),
+ NM_SETTING_BOND_UPDELAY, NM_SETTING_BOND_MIIMON);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_UPDELAY);
return FALSE;
}
- if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY)) {
+ if (priv->downdelay > 0) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%s' option requires '%s' option to be set"),
- 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);
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' property requires '%s' property to be set"),
+ NM_SETTING_BOND_DOWNDELAY, NM_SETTING_BOND_MIIMON);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_DOWNDELAY);
return FALSE;
}
}
/* arp_ip_target can only be used with arp_interval, and must
- * contain a comma-separated list of IPv4 addresses.
+ * contain IPv4 addresses.
*/
- arp_ip_target = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
- if (arp_interval > 0) {
- char **addrs;
+ if (priv->arp_interval > 0) {
guint32 addr;
int i;
- if (!arp_ip_target) {
+ if (!priv->arp_ip_target) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_MISSING_OPTION,
- _("'%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_ERROR_MISSING_PROPERTY,
+ _("'%s' property requires '%s' property to be set"),
+ NM_SETTING_BOND_ARP_INTERVAL, NM_SETTING_BOND_ARP_IP_TARGET);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_ARP_IP_TARGET);
return FALSE;
}
- addrs = g_strsplit (arp_ip_target, ",", -1);
- if (!addrs[0]) {
+ if (!priv->arp_ip_target[0]) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%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_strfreev (addrs);
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' property is empty"),
+ NM_SETTING_BOND_ARP_IP_TARGET);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_ARP_IP_TARGET);
return FALSE;
}
- for (i = 0; addrs[i]; i++) {
- if (!inet_pton (AF_INET, addrs[i], &addr)) {
+ for (i = 0; priv->arp_ip_target[i]; i++) {
+ if (!inet_pton (AF_INET, priv->arp_ip_target[i], &addr)) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%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);
- g_strfreev (addrs);
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid IPv4 address for '%s' property"),
+ priv->arp_ip_target[i], NM_SETTING_BOND_ARP_IP_TARGET);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_ARP_IP_TARGET);
return FALSE;
}
}
- g_strfreev (addrs);
} else {
- if (arp_ip_target) {
+ if (priv->arp_ip_target && priv->arp_ip_target[0]) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_OPTION,
- _("'%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_ERROR_INVALID_PROPERTY,
+ _("'%s' property requires '%s' property to be set"),
+ NM_SETTING_BOND_ARP_IP_TARGET, NM_SETTING_BOND_ARP_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_ARP_IP_TARGET);
return FALSE;
}
}
+ /* FIXME: maybe we should not be too excessively about validating the strings,
+ * because the kernel might add new values (which we would then not support).
+ * OTOH, the checking above already requires some deep knowledge about the exact
+ * meaning of the flags, so, why check there, but not here?
+ **/
+ if (priv->arp_validate && !validate_property (&props[PROP_ARP_VALIDATE], priv->arp_validate)) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ priv->arp_validate, NM_SETTING_BOND_ARP_VALIDATE);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_ARP_VALIDATE);
+ return FALSE;
+ }
+
+ if (priv->primary_reselect && !validate_property (&props[PROP_PRIMARY_RESELECT], priv->primary_reselect)) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ priv->primary_reselect, NM_SETTING_BOND_PRIMARY_RESELECT);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_PRIMARY_RESELECT);
+ return FALSE;
+ }
+
+ if (priv->fail_over_mac && !validate_property (&props[PROP_FAIL_OVER_MAC], priv->fail_over_mac)) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ priv->fail_over_mac, NM_SETTING_BOND_FAIL_OVER_MAC);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_FAIL_OVER_MAC);
+ return FALSE;
+ }
+
+ if (priv->ad_select && !validate_property (&props[PROP_AD_SELECT], priv->ad_select)) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ priv->ad_select, NM_SETTING_BOND_AD_SELECT);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_AD_SELECT);
+ return FALSE;
+ }
+
+ if (priv->xmit_hash_policy && !validate_property (&props[PROP_XMIT_HASH_POLICY], priv->xmit_hash_policy)) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ priv->xmit_hash_policy, NM_SETTING_BOND_XMIT_HASH_POLICY);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_XMIT_HASH_POLICY);
+ return FALSE;
+ }
+
return TRUE;
}
@@ -699,18 +1385,140 @@ get_virtual_iface_name (NMSetting *setting)
return nm_setting_bond_get_interface_name (self);
}
+static gboolean
+compare_property (NMSetting *setting,
+ NMSetting *other,
+ const GParamSpec *prop_spec,
+ NMSettingCompareFlags flags)
+{
+ BondProperty *prop = find_property_by_pspec (prop_spec, NULL, TRUE);
+ gboolean result = FALSE;
+
+ if (!prop)
+ goto CHAIN;
+
+ switch (prop->opt_type) {
+ case TYPE_BOTH: {
+ char *a0, *b0;
+ const char *a, *b;
+
+ g_object_get (setting, prop_spec->name, &a0, NULL);
+ g_object_get (setting, prop_spec->name, &b0, NULL);
+
+ a = a0;
+ b = b0;
+ if (!a || !b)
+ result = (a == b);
+ else if (strcmp (a, b) == 0)
+ result = TRUE;
+ else {
+ int idx;
+
+ if (validate_int (prop, a, &idx)) {
+ if (!IS_VALID_LIST_INDEX (prop, idx))
+ goto BOTH_FINISHED;
+ a = prop->list[idx];
+ }
+ if (validate_int (prop, b, &idx)) {
+ if (!IS_VALID_LIST_INDEX (prop, idx))
+ goto BOTH_FINISHED;
+ b = prop->list[idx];
+ }
+ result = (strcmp (a, b) == 0);
+ }
+
+BOTH_FINISHED:
+ g_free (a0);
+ g_free (b0);
+ return result;
+ }
+ case TYPE_IP: {
+ char **a, **b;
+ struct in_addr *addr_a = NULL, *addr_b = NULL;
+
+ g_object_get (setting, prop_spec->name, &a, NULL);
+ g_object_get (setting, prop_spec->name, &b, NULL);
+
+ if (!a || !a[0] || !b || !b[0])
+ result = ((a ? a[0] : NULL) == (b ? b[0] : NULL));
+ else {
+ /* both arrays are not empty. We compare them by
+ * converting every item into a struct in_addr and looking
+ * whether we find it in the other array (and vice versa).
+ * If one of the addresses cannot be converted, the result
+ * is always false (because nothing compares to an invalid property).
+ **/
+
+ guint i, j;
+ guint alen = g_strv_length (a);
+ guint blen = g_strv_length (b);
+
+ /* convert all strings to struct in_addr */
+ addr_a = g_new (struct in_addr, alen);
+ for (i = 0; i < alen; i++) {
+ if (!inet_aton (a[i], &addr_a[i]))
+ goto IP_FINISHED;
+ }
+
+ addr_b = g_new (struct in_addr, blen);
+ for (i = 0; i < blen; i++) {
+ if (!inet_aton (b[i], &addr_b[i]))
+ goto IP_FINISHED;
+ }
+
+ /* ensure that we find every address in the other array too */
+ for (i = 0; i < alen; i++) {
+ for (j = 0; j < blen; j++) {
+ if (addr_a[i].s_addr == addr_b[j].s_addr)
+ break;
+ }
+ if (j >= blen)
+ goto IP_FINISHED;
+ }
+
+ for (i = 0; i < blen; i++) {
+ for (j = 0; j < alen; j++) {
+ if (addr_b[i].s_addr == addr_a[j].s_addr)
+ break;
+ }
+ if (j >= alen)
+ goto IP_FINISHED;
+ }
+ result = TRUE;
+ }
+IP_FINISHED:
+ g_free (addr_a);
+ g_free (addr_b);
+ g_strfreev (a);
+ g_strfreev (b);
+ return result;
+ }
+ default:
+ /* other types shall be compared by the default implementation. */
+ goto CHAIN;
+ }
+
+CHAIN:
+ return NM_SETTING_CLASS (nm_setting_bond_parent_class)->compare_property (setting, other, prop_spec, flags);
+}
+
+
static void
nm_setting_bond_init (NMSettingBond *setting)
{
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
- g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BOND_SETTING_NAME,
- NULL);
+ priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
- priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BOND_SETTING_NAME, NULL);
+}
+
+static void
+constructed (GObject *object)
+{
+ G_OBJECT_CLASS (nm_setting_bond_parent_class)->constructed (object);
- /* Default values: */
- nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr");
+ g_assert (g_hash_table_size (NM_SETTING_BOND_GET_PRIVATE (object)->options) == (_LAST_KERNEL_PROP - _FIRST_KERNEL_PROP + 1));
}
static void
@@ -718,54 +1526,168 @@ finalize (GObject *object)
{
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
+ g_assert (g_hash_table_size (priv->options) == (_LAST_KERNEL_PROP - _FIRST_KERNEL_PROP + 1));
+
g_free (priv->interface_name);
+ g_free (priv->mode);
+ g_free (priv->primary);
+ g_strfreev (priv->arp_ip_target);
g_hash_table_destroy (priv->options);
G_OBJECT_CLASS (nm_setting_bond_parent_class)->finalize (object);
}
static void
-copy_hash (gpointer key, gpointer value, gpointer user_data)
-{
- g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), g_strdup (value));
-}
-
-static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
+ NMSettingBond *setting = NM_SETTING_BOND (object);
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
- GHashTable *new_hash;
+ BondProperty *prop = find_property_by_pspec (pspec, NULL, TRUE);
+ char *kernel_value = NULL;
switch (prop_id) {
case PROP_INTERFACE_NAME:
g_free (priv->interface_name);
priv->interface_name = g_value_dup_string (value);
break;
+ case PROP_MODE:
+ g_free (priv->mode);
+ priv->mode = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_MIIMON:
+ priv->miimon = g_value_get_int (value);
+ kernel_value = g_strdup_printf ("%u", g_value_get_int (value));
+ break;
+ case PROP_DOWNDELAY:
+ priv->downdelay = g_value_get_int (value);
+ kernel_value = g_strdup_printf ("%u", g_value_get_int (value));
+ break;
+ case PROP_UPDELAY:
+ priv->updelay = g_value_get_int (value);
+ kernel_value = g_strdup_printf ("%u", g_value_get_int (value));
+ break;
+ case PROP_ARP_INTERVAL:
+ priv->arp_interval = g_value_get_int (value);
+ kernel_value = g_strdup_printf ("%u", g_value_get_int (value));
+ break;
+ case PROP_ARP_IP_TARGET:
+ g_strfreev (priv->arp_ip_target);
+ priv->arp_ip_target = g_value_dup_boxed (value);
+ kernel_value = priv->arp_ip_target ? g_strjoinv (",", priv->arp_ip_target) : g_strdup ("");
+ break;
+ case PROP_ARP_VALIDATE:
+ g_free (priv->arp_validate);
+ priv->arp_validate = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_PRIMARY:
+ g_free (priv->primary);
+ priv->primary = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_PRIMARY_RESELECT:
+ g_free (priv->primary_reselect);
+ priv->primary_reselect = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_FAIL_OVER_MAC:
+ g_free (priv->fail_over_mac);
+ priv->fail_over_mac = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_USE_CARRIER:
+ priv->use_carrier = !!g_value_get_int (value);
+ kernel_value = g_strdup_printf ("%u", priv->use_carrier);
+ break;
+ case PROP_AD_SELECT:
+ g_free (priv->ad_select);
+ priv->ad_select = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_XMIT_HASH_POLICY:
+ g_free (priv->xmit_hash_policy);
+ priv->xmit_hash_policy = g_value_dup_string (value);
+ kernel_value = g_value_dup_string (value);
+ break;
+ case PROP_RESEND_IGMP:
+ priv->resend_igmp = g_value_get_int (value);
+ kernel_value = g_strdup_printf ("%u", g_value_get_int (value));
+ break;
case PROP_OPTIONS:
- /* Must make a deep copy of the hash table here... */
- g_hash_table_remove_all (priv->options);
- new_hash = g_value_get_boxed (value);
- if (new_hash)
- g_hash_table_foreach (new_hash, copy_hash, priv->options);
+ set_properties_from_hash (setting, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+
+ if (prop) {
+ const char *kernel_name = get_kernel_name (prop);
+ const char *old_value;
+
+ if ( !g_hash_table_lookup_extended (priv->options, kernel_name, NULL, (void **) &old_value)
+ || g_strcmp0 (old_value, kernel_value)) {
+ g_hash_table_insert (priv->options, (void *) kernel_name, kernel_value);
+ g_object_notify (object, NM_SETTING_BOND_OPTIONS);
+ }
+ }
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
- NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
NMSettingBond *setting = NM_SETTING_BOND (object);
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
switch (prop_id) {
case PROP_INTERFACE_NAME:
g_value_set_string (value, nm_setting_bond_get_interface_name (setting));
break;
+ case PROP_MODE:
+ g_value_set_string (value, nm_setting_bond_get_mode (setting));
+ break;
+ case PROP_MIIMON:
+ g_value_set_int (value, nm_setting_bond_get_miimon (setting));
+ break;
+ case PROP_DOWNDELAY:
+ g_value_set_int (value, nm_setting_bond_get_downdelay (setting));
+ break;
+ case PROP_UPDELAY:
+ g_value_set_int (value, nm_setting_bond_get_updelay (setting));
+ break;
+ case PROP_ARP_INTERVAL:
+ g_value_set_int (value, nm_setting_bond_get_arp_interval (setting));
+ break;
+ case PROP_ARP_IP_TARGET:
+ g_value_set_boxed (value, nm_setting_bond_get_arp_ip_target (setting));
+ break;
+ case PROP_ARP_VALIDATE:
+ g_value_set_string (value, nm_setting_bond_get_arp_validate (setting));
+ break;
+ case PROP_PRIMARY:
+ g_value_set_string (value, nm_setting_bond_get_primary (setting));
+ break;
+ case PROP_PRIMARY_RESELECT:
+ g_value_set_string (value, nm_setting_bond_get_primary_reselect (setting));
+ break;
+ case PROP_FAIL_OVER_MAC:
+ g_value_set_string (value, nm_setting_bond_get_fail_over_mac (setting));
+ break;
+ case PROP_USE_CARRIER:
+ g_value_set_int (value, nm_setting_bond_get_use_carrier (setting));
+ break;
+ case PROP_AD_SELECT:
+ g_value_set_string (value, nm_setting_bond_get_ad_select (setting));
+ break;
+ case PROP_XMIT_HASH_POLICY:
+ g_value_set_string (value, nm_setting_bond_get_xmit_hash_policy (setting));
+ break;
+ case PROP_RESEND_IGMP:
+ g_value_set_int (value, nm_setting_bond_get_resend_igmp (setting));
+ break;
case PROP_OPTIONS:
g_value_set_boxed (value, priv->options);
break;
@@ -780,14 +1702,17 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+ guint i;
g_type_class_add_private (setting_class, sizeof (NMSettingBondPrivate));
/* virtual methods */
- object_class->set_property = set_property;
- object_class->get_property = get_property;
- object_class->finalize = finalize;
- parent_class->verify = verify;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->constructed = constructed;
+ object_class->finalize = finalize;
+ parent_class->verify = verify;
+ parent_class->compare_property = compare_property;
parent_class->get_virtual_iface_name = get_virtual_iface_name;
/* Properties */
@@ -796,29 +1721,252 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
*
* The name of the virtual in-kernel bonding network interface
**/
- g_object_class_install_property
- (object_class, PROP_INTERFACE_NAME,
- g_param_spec_string (NM_SETTING_BOND_INTERFACE_NAME,
- "InterfaceName",
- "The name of the virtual in-kernel bonding network interface",
- NULL,
- G_PARAM_READWRITE));
+ props[PROP_INTERFACE_NAME].pspec =
+ g_param_spec_string (NM_SETTING_BOND_INTERFACE_NAME,
+ "InterfaceName",
+ "The name of the virtual in-kernel bonding network interface",
+ NULL,
+ G_PARAM_READWRITE);
+
+ /**
+ * NMSettingBond:mode:
+ *
+ * The bonding mode. One of 'balance-rr', 'active-backup',
+ * 'balance-xor', 'broadcast', '802.3ad', 'balance-tlb', or
+ * 'balance-alb'.
+ **/
+ props[PROP_MODE].pspec =
+ g_param_spec_string (NM_SETTING_BOND_MODE,
+ "Mode",
+ "The bonding mode",
+ "balance-rr",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:miimon:
+ *
+ * The MII link monitoring frequency, in milliseconds. Either this
+ * or #NMSettingBond:arp-interval should be set, and they can't
+ * both be set.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_MIIMON].pspec =
+ g_param_spec_int (NM_SETTING_BOND_MIIMON,
+ "miimon",
+ "The MII link monitoring frequence",
+ 0, G_MAXINT, 100,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:downdelay:
+ *
+ * The time, in milliseconds, to wait before disabling a slave
+ * after it goes down. Only valid if #NMSettingBond:miimon is
+ * non-0.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_DOWNDELAY].pspec =
+ g_param_spec_int (NM_SETTING_BOND_DOWNDELAY,
+ "downdelay",
+ "downdelay",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:updelay:
+ *
+ * The time, in milliseconds, to wait before enabling a slave
+ * after it comes up. Only valid if #NMSettingBond:miimon is
+ * non-0.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_UPDELAY].pspec =
+ g_param_spec_int (NM_SETTING_BOND_UPDELAY,
+ "updelay",
+ "updelay",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:arp-interval:
+ *
+ * The ARP-based link monitoring frequency, in milliseconds.
+ * Either this or #NMSettingBond:miimon should be set, and they
+ * can't both be set.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_ARP_INTERVAL].pspec =
+ g_param_spec_int (NM_SETTING_BOND_ARP_INTERVAL,
+ "ARP interval",
+ "The ARP-based link monitoring frequence",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:arp-ip-target:
+ *
+ * An array of IPv4 addresses to ping when using ARP-based link monitoring.
+ * This only has an effect when #NMSettingBond:arp-interval is also set.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_ARP_IP_TARGET].pspec =
+ g_param_spec_boxed (NM_SETTING_BOND_ARP_IP_TARGET,
+ "ARP IP target",
+ "ARP monitoring target IP addresses",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:arp-validate:
+ *
+ * Specifies whether or not ARP probes and replies should be
+ * validated in the active-backup mode. One of
+ * 'none', 'active', 'backup', 'all'.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_ARP_VALIDATE].pspec =
+ g_param_spec_string (NM_SETTING_BOND_ARP_VALIDATE,
+ "arp-validate",
+ "Specifies whether or not ARP probes and replies should "
+ "be validate in the active-backup mode",
+ "none",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:primary:
+ *
+ * The primary interface to use in 'active-backup' mode.
+ **/
+ props[PROP_PRIMARY].pspec =
+ g_param_spec_string (NM_SETTING_BOND_PRIMARY,
+ "Primary",
+ "The primary interface",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:primary-reselect:
+ *
+ * Specifies the reselection policy for the primary slave.
+ * One of 'always', 'better', 'failure'.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_PRIMARY_RESELECT].pspec =
+ g_param_spec_string (NM_SETTING_BOND_PRIMARY_RESELECT,
+ "primary-reselect",
+ "Specifies the reselection policy for the primary slave",
+ "always",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:fail-over-mac:
+ *
+ * Specifies whether active-backup mode should set all slaves to
+ * the same MAC address at enslavement (the traditional
+ * behavior), or, when enabled, perform special handling of the
+ * bond's MAC address in accordance with the selected policy.
+ * One of 'none', 'active', 'follow'.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_FAIL_OVER_MAC].pspec =
+ g_param_spec_string (NM_SETTING_BOND_FAIL_OVER_MAC,
+ "fail-over-mac",
+ "fail_over_mac",
+ "none",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:use-carrier:
+ *
+ * Specifies whether or not miimon should use MII or ETHTOOL
+ * ioctls vs. netif_carrier_ok() to determine the link
+ * status.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_USE_CARRIER].pspec =
+ g_param_spec_int (NM_SETTING_BOND_USE_CARRIER,
+ "use-carrier",
+ "use_carrier",
+ 0, 1, 1,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:ad-select:
+ *
+ * Specifies the 802.3ad aggregation selection logic to use.
+ * One of 'stable', 'bandwidth', or 'count'.
+ **/
+ props[PROP_AD_SELECT].pspec =
+ g_param_spec_string (NM_SETTING_BOND_AD_SELECT,
+ "ad-select",
+ "ad_select",
+ "stable",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:xmit-hash-policy:
+ *
+ * Selects the transmit hash policy to use for slave selection in
+ * balance-xor and 802.3ad modes. One of 'layer2', 'layer2+3',
+ * 'layer3+4', 'encap2+3', or 'encap3+4'.
+ *
+ **/
+ props[PROP_XMIT_HASH_POLICY].pspec =
+ g_param_spec_string (NM_SETTING_BOND_XMIT_HASH_POLICY,
+ "xmit-hash-policy",
+ "xmit_hash_policy",
+ "layer2",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ /**
+ * NMSettingBond:resend-igmp:
+ *
+ * Specifies the number of IGMP membership reports to be issued after
+ * a failover event. One membership report is issued immediately after
+ * the failover, subsequent packets are sent in each 200ms interval.
+ *
+ * The valid range is 0 - 255; the default value is 1. A value of 0
+ * prevents the IGMP membership report from being issued in response
+ * to the failover event.
+ *
+ * Since: 0.9.10
+ **/
+ props[PROP_RESEND_IGMP].pspec =
+ g_param_spec_int (NM_SETTING_BOND_RESEND_IGMP,
+ "resend-igmp",
+ "resend_igmp",
+ 0, 255, 1,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
/**
* NMSettingBond:options:
*
* Dictionary of key/value pairs of bonding options. Both keys
* and values must be strings. Option names must contain only
- * alphanumeric characters (ie, [a-zA-Z0-9]).
+ * alphanumeric characters (ie, [a-zA-Z0-9_).
+ *
+ * Deprecated: use the specific properties
**/
- g_object_class_install_property
- (object_class, PROP_OPTIONS,
- _nm_param_spec_specialized (NM_SETTING_BOND_OPTIONS,
- "Options",
- "Dictionary of key/value pairs of bonding "
- "options. Both keys and values must be "
- "strings. Option names must contain only "
- "alphanumeric characters (ie, [a-zA-Z0-9]).",
- DBUS_TYPE_G_MAP_OF_STRING,
- G_PARAM_READWRITE));
+ props[PROP_OPTIONS].pspec =
+ _nm_param_spec_specialized (NM_SETTING_BOND_OPTIONS,
+ "Options",
+ "Dictionary of key/value pairs of bonding "
+ "options. Both keys and values must be "
+ "strings. Option names must contain only "
+ "alphanumeric characters (ie, [a-zA-Z0-9_]).",
+ DBUS_TYPE_G_MAP_OF_STRING,
+ G_PARAM_READWRITE);
+
+ /* Skip PROP_0 */
+ for (i = 1; i < LAST_PROP; i++)
+ g_object_class_install_property (object_class, i, props[i].pspec);
}
diff --git a/libnm-util/nm-setting-bond.h b/libnm-util/nm-setting-bond.h
index 383e0eadb3..65a7780096 100644
--- a/libnm-util/nm-setting-bond.h
+++ b/libnm-util/nm-setting-bond.h
@@ -55,10 +55,27 @@ typedef enum {
#define NM_SETTING_BOND_ERROR nm_setting_bond_error_quark ()
GQuark nm_setting_bond_error_quark (void);
-#define NM_SETTING_BOND_INTERFACE_NAME "interface-name"
-#define NM_SETTING_BOND_OPTIONS "options"
-
-/* Valid options for the 'options' property */
+#define NM_SETTING_BOND_INTERFACE_NAME "interface-name"
+#define NM_SETTING_BOND_MODE "mode"
+#define NM_SETTING_BOND_PRIMARY "primary"
+#define NM_SETTING_BOND_MIIMON "miimon"
+#define NM_SETTING_BOND_DOWNDELAY "downdelay"
+#define NM_SETTING_BOND_UPDELAY "updelay"
+#define NM_SETTING_BOND_ARP_INTERVAL "arp-interval"
+#define NM_SETTING_BOND_ARP_IP_TARGET "arp-ip-target"
+#define NM_SETTING_BOND_ARP_VALIDATE "arp-validate"
+#define NM_SETTING_BOND_PRIMARY "primary"
+#define NM_SETTING_BOND_PRIMARY_RESELECT "primary-reselect"
+#define NM_SETTING_BOND_FAIL_OVER_MAC "fail-over-mac"
+#define NM_SETTING_BOND_USE_CARRIER "use-carrier"
+#define NM_SETTING_BOND_AD_SELECT "ad-select"
+#define NM_SETTING_BOND_XMIT_HASH_POLICY "xmit-hash-policy"
+#define NM_SETTING_BOND_RESEND_IGMP "resend-igmp"
+
+/* Deprecated */
+#define NM_SETTING_BOND_OPTIONS "options"
+
+/* Valid options as named by the kernal */
#define NM_SETTING_BOND_OPTION_MODE "mode"
#define NM_SETTING_BOND_OPTION_MIIMON "miimon"
#define NM_SETTING_BOND_OPTION_DOWNDELAY "downdelay"
@@ -74,6 +91,14 @@ GQuark nm_setting_bond_error_quark (void);
#define NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY "xmit_hash_policy"
#define NM_SETTING_BOND_OPTION_RESEND_IGMP "resend_igmp"
+#define __NM_SETTING_BOND_MODE_IS_balance_rr(mode) ((mode) && (!strcmp ((mode), "0") || !strcmp ((mode), "balance-rr")))
+#define __NM_SETTING_BOND_MODE_IS_active_backup(mode) ((mode) && (!strcmp ((mode), "1") || !strcmp ((mode), "active-backup")))
+#define __NM_SETTING_BOND_MODE_IS_balance_xor(mode) ((mode) && (!strcmp ((mode), "2") || !strcmp ((mode), "balance-xor")))
+#define __NM_SETTING_BOND_MODE_IS_broadcast(mode) ((mode) && (!strcmp ((mode), "3") || !strcmp ((mode), "broadcast")))
+#define __NM_SETTING_BOND_MODE_IS_802_3ad(mode) ((mode) && (!strcmp ((mode), "4") || !strcmp ((mode), "802.3ad")))
+#define __NM_SETTING_BOND_MODE_IS_balance_tlb(mode) ((mode) && (!strcmp ((mode), "5") || !strcmp ((mode), "balance-tlb")))
+#define __NM_SETTING_BOND_MODE_IS_balance_alb(mode) ((mode) && (!strcmp ((mode), "6") || !strcmp ((mode), "balance-alb")))
+
typedef struct {
NMSetting parent;
} NMSettingBond;
@@ -90,28 +115,54 @@ typedef struct {
GType nm_setting_bond_get_type (void);
-NMSetting * nm_setting_bond_new (void);
-const char * nm_setting_bond_get_interface_name (NMSettingBond *setting);
-guint32 nm_setting_bond_get_num_options (NMSettingBond *setting);
-gboolean nm_setting_bond_get_option (NMSettingBond *setting,
- guint32 idx,
- const char **out_name,
- const char **out_value);
-const char * nm_setting_bond_get_option_by_name (NMSettingBond *setting,
- const char *name);
-gboolean nm_setting_bond_add_option (NMSettingBond *setting,
- const char *name,
- const char *value);
-gboolean nm_setting_bond_remove_option (NMSettingBond *setting,
- const char *name);
-
-gboolean nm_setting_bond_validate_option (const char *name,
- const char *value);
-
-const char **nm_setting_bond_get_valid_options (NMSettingBond *setting);
-
-const char * nm_setting_bond_get_option_default (NMSettingBond *setting,
- const char *name);
+NMSetting * nm_setting_bond_new (void);
+
+const char * nm_setting_bond_get_interface_name (const NMSettingBond *setting);
+
+const char * nm_setting_bond_get_mode (const NMSettingBond *setting);
+const char * nm_setting_bond_get_primary (const NMSettingBond *setting);
+guint nm_setting_bond_get_miimon (const NMSettingBond *setting);
+guint nm_setting_bond_get_downdelay (const NMSettingBond *setting);
+guint nm_setting_bond_get_updelay (const NMSettingBond *setting);
+guint nm_setting_bond_get_arp_interval (const NMSettingBond *setting);
+const char *const* nm_setting_bond_get_arp_ip_target (const NMSettingBond *setting);
+const char * nm_setting_bond_get_arp_validate (const NMSettingBond *setting);
+const char * nm_setting_bond_get_primary_reselect (const NMSettingBond *setting);
+const char * nm_setting_bond_get_fail_over_mac (const NMSettingBond *setting);
+gboolean nm_setting_bond_get_use_carrier (const NMSettingBond *setting);
+const char * nm_setting_bond_get_ad_select (const NMSettingBond *setting);
+const char * nm_setting_bond_get_xmit_hash_policy (const NMSettingBond *setting);
+guint nm_setting_bond_get_resend_igmp (const NMSettingBond *setting);
+
+const char * nm_setting_bond_get_property_name (const char *name);
+const char * nm_setting_bond_get_kernel_name (const char *name);
+const char *const* nm_setting_bond_get_kernel_names (void);
+
+const char * nm_setting_bond_get_string (const NMSettingBond *setting, const char *name);
+gboolean nm_setting_bond_is_default (const NMSettingBond *setting, const char *name, GValue *default_value);
+gboolean nm_setting_bond_validate_string (const char *name, const char *value, GError **error);
+gboolean nm_setting_bond_set_string (NMSettingBond *setting, const char *name, const char *value);
+void nm_setting_bond_set_default (NMSettingBond *setting, const char *name);
+
+
+/* Deprecated */
+G_GNUC_DEPRECATED guint32 nm_setting_bond_get_num_options (NMSettingBond *setting);
+G_GNUC_DEPRECATED gboolean nm_setting_bond_get_option (NMSettingBond *setting,
+ guint32 idx,
+ const char **out_name,
+ const char **out_value);
+G_GNUC_DEPRECATED const char * nm_setting_bond_get_option_by_name (NMSettingBond *setting,
+ const char *name);
+G_GNUC_DEPRECATED gboolean nm_setting_bond_add_option (NMSettingBond *setting,
+ const char *name,
+ const char *value);
+G_GNUC_DEPRECATED gboolean nm_setting_bond_remove_option (NMSettingBond *setting,
+ const char *name);
+
+G_GNUC_DEPRECATED const char **nm_setting_bond_get_valid_options (NMSettingBond *setting);
+
+G_GNUC_DEPRECATED const char * nm_setting_bond_get_option_default (NMSettingBond *setting,
+ const char *name);
G_END_DECLS
diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c
index 56d6e679e2..f555901c57 100644
--- a/libnm-util/tests/test-general.c
+++ b/libnm-util/tests/test-general.c
@@ -1756,9 +1756,11 @@ test_setting_bond_changed_signal (void)
s_bond = (NMSettingBond *) nm_setting_bond_new ();
nm_connection_add_setting (connection, NM_SETTING (s_bond));
- ASSERT_CHANGED (nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
- ASSERT_CHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY));
- ASSERT_UNCHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY));
+ ASSERT_CHANGED (nm_setting_bond_set_string (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
+ ASSERT_CHANGED (nm_setting_bond_set_string (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
+ ASSERT_UNCHANGED (nm_setting_bond_set_string (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10x"));
+ ASSERT_CHANGED (nm_setting_bond_set_default (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY));
+ ASSERT_CHANGED (g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_DOWNDELAY, 20, NULL));
g_object_unref (connection);
}
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 8d9939b096..f09cfbd893 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -200,14 +200,24 @@ set_bond_attr (NMDevice *device, const char *attr, const char *value)
return ret;
}
+static gboolean
+set_bond_attr_int (NMDevice *device, const char *attr, int value)
+{
+ char buf[20];
+
+ snprintf (buf, sizeof (buf), "%d", value);
+ buf[sizeof (buf) -1] = 0;
+ return set_bond_attr (device, attr, buf);
+}
+
/* Ignore certain bond options if they are zero (off/disabled) */
static gboolean
ignore_if_zero (const char *option, const char *value)
{
- if (strcmp (option, "arp_interval") &&
- strcmp (option, "miimon") &&
- strcmp (option, "downdelay") &&
- strcmp (option, "updelay"))
+ if (strcmp (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL) &&
+ strcmp (option, NM_SETTING_BOND_OPTION_MIIMON) &&
+ strcmp (option, NM_SETTING_BOND_OPTION_DOWNDELAY) &&
+ strcmp (option, NM_SETTING_BOND_OPTION_UPDELAY))
return FALSE;
return g_strcmp0 (value, "0") == 0 ? TRUE : FALSE;
@@ -219,72 +229,46 @@ update_connection (NMDevice *device, NMConnection *connection)
NMSettingBond *s_bond = nm_connection_get_setting_bond (connection);
const char *ifname = nm_device_get_iface (device);
int ifindex = nm_device_get_ifindex (device);
- const char **options;
+ const char *const*options;
if (!s_bond) {
s_bond = (NMSettingBond *) nm_setting_bond_new ();
- nm_connection_add_setting (connection, (NMSetting *) s_bond);
g_object_set (s_bond, NM_SETTING_BOND_INTERFACE_NAME, ifname, NULL);
+ nm_connection_add_setting (connection, (NMSetting *) s_bond);
}
/* Read bond options from sysfs and update the Bond setting to match */
- options = nm_setting_bond_get_valid_options (s_bond);
+ options = nm_setting_bond_get_kernel_names ();
while (options && *options) {
gs_free char *value = nm_platform_master_get_option (ifindex, *options);
- const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options);
-
- if (value && !ignore_if_zero (*options, value) && (g_strcmp0 (value, defvalue) != 0)) {
- /* Replace " " with "," for arp_ip_targets from the kernel */
- if (strcmp (*options, "arp_ip_target") == 0) {
- char *p = value;
-
- while (p && *p) {
- if (*p == ' ')
- *p = ',';
- p++;
- }
- }
- nm_setting_bond_add_option (s_bond, *options, value);
- }
+ /* FIXME: why this check for ignore_if_zero? */
+ if (value && !ignore_if_zero (*options, value)) {
+ if (!nm_setting_bond_set_string (s_bond, *options, value))
+ nm_log_dbg (LOGD_BOND, "Could not set bonding option %s from sysfs value '%s'", *options, value);
+ } else
+ nm_setting_bond_set_default (s_bond, *options);
options++;
}
}
static void
set_arp_targets (NMDevice *device,
- const char *value,
- const char *delim,
+ const char *const *values,
const char *prefix)
{
- char **items, **iter, *tmp;
+ char *tmp;
- if (!value || !*value)
+ if (!values)
return;
- items = g_strsplit_set (value, delim, 0);
- for (iter = items; iter && *iter; iter++) {
- if (*iter[0]) {
- tmp = g_strdup_printf ("%s%s", prefix, *iter);
- set_bond_attr (device, "arp_ip_target", tmp);
+ for (; *values; values++) {
+ if (*values[0]) {
+ tmp = g_strconcat (prefix, *values, NULL);
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, tmp);
g_free (tmp);
}
}
- g_strfreev (items);
-}
-
-static void
-set_simple_option (NMDevice *device,
- const char *attr,
- NMSettingBond *s_bond,
- const char *opt)
-{
- const char *value;
-
- value = nm_setting_bond_get_option_by_name (s_bond, opt);
- if (!value)
- value = nm_setting_bond_get_option_default (s_bond, opt);
- set_bond_attr (device, attr, value);
}
static NMActStageReturn
@@ -294,6 +278,7 @@ apply_bonding_config (NMDevice *device)
NMSettingBond *s_bond;
int ifindex = nm_device_get_ifindex (device);
const char *mode, *value;
+ int ivalue;
char *contents;
gboolean set_arp_interval = TRUE;
@@ -315,78 +300,65 @@ apply_bonding_config (NMDevice *device)
s_bond = nm_connection_get_setting_bond (connection);
g_assert (s_bond);
- mode = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
- if (mode == NULL)
- mode = "balance-rr";
+ mode = nm_setting_bond_get_mode (s_bond);
+ g_assert (mode && !mode[0]);
- value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
- if (value && atoi (value)) {
+ ivalue = nm_setting_bond_get_miimon (s_bond);
+ if (ivalue > 0) {
/* clear arp interval */
- set_bond_attr (device, "arp_interval", "0");
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0");
set_arp_interval = FALSE;
- set_bond_attr (device, "miimon", value);
- set_simple_option (device, "updelay", s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
- set_simple_option (device, "downdelay", s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
- } else if (!value) {
- /* If not given, and arp_interval is not given, default to 100 */
- long int val_int;
- char *end;
-
- value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
- errno = 0;
- val_int = strtol (value ? value : "0", &end, 10);
- if (!value || (val_int == 0 && errno == 0 && *end == '\0'))
- set_bond_attr (device, "miimon", "100");
+ set_bond_attr_int (device, NM_SETTING_BOND_OPTION_MIIMON, ivalue);
+ set_bond_attr_int (device, NM_SETTING_BOND_OPTION_UPDELAY, nm_setting_bond_get_updelay (s_bond));
+ set_bond_attr_int (device, NM_SETTING_BOND_OPTION_DOWNDELAY, nm_setting_bond_get_downdelay (s_bond));
}
/* The stuff after 'mode' requires the given mode or doesn't care */
- set_bond_attr (device, "mode", mode);
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_MODE, mode);
/* arp_interval not compatible with ALB, TLB */
- if (g_strcmp0 (mode, "balance-alb") == 0 || g_strcmp0 (mode, "balance-tlb") == 0)
+ if (__NM_SETTING_BOND_MODE_IS_balance_alb (mode) || __NM_SETTING_BOND_MODE_IS_balance_tlb (mode))
set_arp_interval = FALSE;
if (set_arp_interval) {
- set_simple_option (device, "arp_interval", s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ set_bond_attr_int (device, NM_SETTING_BOND_OPTION_ARP_INTERVAL, nm_setting_bond_get_arp_interval (s_bond));
/* Just let miimon get cleared automatically; even setting miimon to
* 0 (disabled) clears arp_interval.
*/
}
- value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE);
- /* arp_validate > 0 only valid in active-backup mode */
- if ( value
- && g_strcmp0 (value, "0") != 0
- && g_strcmp0 (value, "none") != 0
- && g_strcmp0 (mode, "active-backup") == 0)
- set_bond_attr (device, "arp_validate", value);
- else
- set_bond_attr (device, "arp_validate", "0");
-
- if ( g_strcmp0 (mode, "active-backup") == 0
- || g_strcmp0 (mode, "balance-alb") == 0
- || g_strcmp0 (mode, "balance-tlb") == 0) {
- value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
- set_bond_attr (device, "primary", value ? value : "");
+ value = nm_setting_bond_get_arp_validate (s_bond);
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value);
+
+ if ( __NM_SETTING_BOND_MODE_IS_active_backup (mode)
+ || __NM_SETTING_BOND_MODE_IS_balance_alb (mode)
+ || __NM_SETTING_BOND_MODE_IS_balance_tlb (mode)) {
+ value = nm_setting_bond_get_primary (s_bond);
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : "");
}
/* Clear ARP targets */
- contents = nm_platform_master_get_option (ifindex, "arp_ip_target");
- set_arp_targets (device, contents, " \n", "-");
+ contents = nm_platform_master_get_option (ifindex, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ if (contents && contents[0]) {
+ char **items;
+
+ items = g_strsplit_set (contents, " \n", 0);
+ set_arp_targets (device, (const char *const*) items, "-");
+ g_strfreev (items);
+ }
g_free (contents);
/* Add new ARP targets */
- value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
- set_arp_targets (device, value, ",", "+");
-
- set_simple_option (device, "primary_reselect", s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT);
- set_simple_option (device, "fail_over_mac", s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC);
- set_simple_option (device, "use_carrier", s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER);
- set_simple_option (device, "ad_select", s_bond, NM_SETTING_BOND_OPTION_AD_SELECT);
- set_simple_option (device, "xmit_hash_policy", s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY);
- set_simple_option (device, "resend_igmp", s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP);
+ set_arp_targets (device, nm_setting_bond_get_arp_ip_target (s_bond), "+");
+
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, nm_setting_bond_get_primary_reselect (s_bond));
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, nm_setting_bond_get_fail_over_mac (s_bond));
+ set_bond_attr_int (device, NM_SETTING_BOND_OPTION_USE_CARRIER, nm_setting_bond_get_use_carrier (s_bond));
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_AD_SELECT, nm_setting_bond_get_ad_select (s_bond));
+ set_bond_attr (device, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, nm_setting_bond_get_xmit_hash_policy (s_bond));
+ set_bond_attr_int (device, NM_SETTING_BOND_OPTION_RESEND_IGMP, nm_setting_bond_get_resend_igmp (s_bond));
return NM_ACT_STAGE_RETURN_SUCCESS;
}
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index e2cff0b2cf..b46daf9ca1 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -63,10 +63,10 @@
#include "reader.h"
#define PLUGIN_PRINT(pname, fmt, args...) \
- { g_message (" " pname ": " fmt, ##args); }
+ G_STMT_START { g_message (" " pname ": " fmt, ##args); } G_STMT_END
#define PLUGIN_WARN(pname, fmt, args...) \
- { g_warning (" " pname ": " fmt, ##args); }
+ G_STMT_START { g_warning (" " pname ": " fmt, ##args); } G_STMT_END
static gboolean
get_int (const char *str, int *value)
@@ -4059,29 +4059,93 @@ infiniband_connection_from_ifcfg (const char *file,
return connection;
}
+typedef void (*IfcfgRhOptFunc) (NMSetting *setting,
+ const char *key,
+ const char *value,
+ gpointer data);
+
+static void
+handle_ifcfg_rh_opts (NMSetting *setting,
+ const char *value,
+ IfcfgRhOptFunc func,
+ gpointer data)
+{
+ char **items, **iter;
+
+ g_return_if_fail (value);
+ if (!value || !*value)
+ return;
+
+ items = g_strsplit_set (value, " ", -1);
+ for (iter = items; *iter; iter++) {
+ if (**iter) {
+ char **keys, *key, *val;
+
+ keys = g_strsplit_set (*iter, "=", 2);
+ if (*keys) {
+ key = keys[0];
+ val = keys[1];
+ if (val && *key && *val)
+ func (setting, key, val, data);
+ }
+
+ g_strfreev (keys);
+ }
+ }
+ g_strfreev (items);
+}
+
static void
-handle_bond_option (NMSettingBond *s_bond,
+handle_bond_option (NMSetting *setting,
const char *key,
- const char *value)
+ const char *value,
+ gpointer data)
{
- char *sanitized = NULL, *j;
- const char *p = value;
+ NMSettingBond *s_bond = NM_SETTING_BOND (setting);
+ const char *value0 = value;
+ char *value_cleanup = NULL;
- /* Remove any quotes or +/- from arp_ip_target */
- if (!g_strcmp0 (key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) && value && value[0]) {
- if (*p == '\'' || *p == '"')
- p++;
- j = sanitized = g_malloc0 (strlen (p) + 1);
- while (*p) {
- if (*p != '+' && *p != '-' && *p != '\'' && *p != '"')
- *j++ = *p;
- p++;
+ g_return_if_fail (key);
+
+ if (!strcmp (key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) {
+ char **arp_ip_target = NULL;
+ char *sanitized = NULL, *j;
+ const char *p = value;
+
+ /* Remove any quotes or +/- from arp_ip_target */
+ if (value[0]) {
+ if (*p == '\'' || *p == '"')
+ p++;
+ j = sanitized = g_malloc0 (strlen (p) + 1);
+ while (*p) {
+ if (*p != '+' && *p != '-' && *p != '\'' && *p != '"')
+ *j++ = *p;
+ p++;
+ }
+ value = sanitized;
}
+
+ if (value && value[0]) {
+ arp_ip_target = g_strsplit (value, ",", -1);
+ /* don't set the GObject property to arp_ip_target, because we want to reuse the
+ * validation from nm_setting_bond_set_string. */
+ value_cleanup = g_strjoinv (",", arp_ip_target);
+ value = value_cleanup;
+ g_strfreev (arp_ip_target);
+ } else
+ value = NULL;
+ g_free (sanitized);
}
- if (!nm_setting_bond_add_option (s_bond, key, sanitized ? sanitized : value))
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid bonding option '%s'", key);
- g_free (sanitized);
+ if (!nm_setting_bond_set_string (s_bond, key, value)) {
+ if (!nm_setting_bond_get_property_name (key))
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: unrecognized bond property '%s'", key);
+ else
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid bond property '%s'='%s'", key, value0);
+ return;
+ }
+
+ g_free (value_cleanup);
}
static NMSetting *
@@ -4105,26 +4169,8 @@ make_bond_setting (shvarFile *ifcfg,
value = svGetValue (ifcfg, "BONDING_OPTS", FALSE);
if (value) {
- char **items, **iter;
-
- items = g_strsplit_set (value, " ", -1);
- for (iter = items; iter && *iter; iter++) {
- if (strlen (*iter)) {
- char **keys, *key, *val;
-
- keys = g_strsplit_set (*iter, "=", 2);
- if (keys && *keys) {
- key = *keys;
- val = *(keys + 1);
- if (val && strlen(key) && strlen(val))
- handle_bond_option (s_bond, key, val);
- }
-
- g_strfreev (keys);
- }
- }
+ handle_ifcfg_rh_opts (NM_SETTING (s_bond), value, handle_bond_option, NULL);
g_free (value);
- g_strfreev (items);
}
return (NMSetting *) s_bond;
@@ -4266,17 +4312,13 @@ team_connection_from_ifcfg (const char *file,
return connection;
}
-typedef void (*BridgeOptFunc) (NMSetting *setting,
- gboolean stp,
- const char *key,
- const char *value);
-
static void
handle_bridge_option (NMSetting *setting,
- gboolean stp,
const char *key,
- const char *value)
+ const char *value,
+ gpointer data)
{
+ gboolean stp = GPOINTER_TO_INT (data);
guint32 u = 0;
if (!strcmp (key, "priority")) {
@@ -4309,33 +4351,6 @@ handle_bridge_option (NMSetting *setting,
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: unhandled bridge option '%s'", key);
}
-static void
-handle_bridging_opts (NMSetting *setting,
- gboolean stp,
- const char *value,
- BridgeOptFunc func)
-{
- char **items, **iter;
-
- items = g_strsplit_set (value, " ", -1);
- for (iter = items; iter && *iter; iter++) {
- if (strlen (*iter)) {
- char **keys, *key, *val;
-
- keys = g_strsplit_set (*iter, "=", 2);
- if (keys && *keys) {
- key = *keys;
- val = *(keys + 1);
- if (val && strlen(key) && strlen(val))
- func (setting, stp, key, val);
- }
-
- g_strfreev (keys);
- }
- }
- g_strfreev (items);
-}
-
static NMSetting *
make_bridge_setting (shvarFile *ifcfg,
const char *file,
@@ -4391,7 +4406,8 @@ make_bridge_setting (shvarFile *ifcfg,
value = svGetValue (ifcfg, "BRIDGING_OPTS", FALSE);
if (value) {
- handle_bridging_opts (NM_SETTING (s_bridge), stp, value, handle_bridge_option);
+ handle_ifcfg_rh_opts (NM_SETTING (s_bridge), value, handle_bridge_option,
+ GINT_TO_POINTER (stp));
g_free (value);
}
@@ -4430,7 +4446,7 @@ bridge_connection_from_ifcfg (const char *file,
g_object_unref (connection);
return NULL;
}
- nm_connection_add_setting (connection, bridge_setting);
+ nm_connection_add_setting (connection, bridge_setting);
if (!nm_connection_verify (connection, error)) {
g_object_unref (connection);
@@ -4442,9 +4458,9 @@ bridge_connection_from_ifcfg (const char *file,
static void
handle_bridge_port_option (NMSetting *setting,
- gboolean stp,
const char *key,
- const char *value)
+ const char *value,
+ gpointer data)
{
guint32 u = 0;
@@ -4484,7 +4500,8 @@ make_bridge_port_setting (shvarFile *ifcfg)
s_port = nm_setting_bridge_port_new ();
value = svGetValue (ifcfg, "BRIDGING_OPTS", FALSE);
if (value)
- handle_bridging_opts (s_port, FALSE, value, handle_bridge_port_option);
+ handle_ifcfg_rh_opts (NM_SETTING (s_port), value, handle_bridge_port_option, NULL);
+
g_free (value);
}
@@ -4515,7 +4532,7 @@ is_bond_device (const char *name, shvarFile *parsed)
if (svTrueValue (parsed, "BONDING_MASTER", FALSE))
return TRUE;
-
+
/* XXX: Check for "bond[\d]+"? */
return FALSE;
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 14c4fb9f72..bc8c9740b9 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -12101,9 +12101,9 @@ test_read_bond_main (void)
"bond-main", "failed to verify %s: DEVICE=%s does not match bond0",
TEST_IFCFG_BOND_MAIN, nm_setting_bond_get_interface_name (s_bond));
- ASSERT (g_strcmp0 (nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON), "100") == 0,
- "bond-main", "failed to verify %s: miimon=%s does not match 100",
- TEST_IFCFG_BOND_MAIN, nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON));
+ ASSERT (nm_setting_bond_get_miimon (s_bond) == 100,
+ "bond-main", "failed to verify %s: miimon=%u does not match 100",
+ TEST_IFCFG_BOND_MAIN, nm_setting_bond_get_miimon (s_bond));
g_free (unmanaged);
g_free (keyfile);
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 6f302b4f7c..c83ee0a872 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -1250,7 +1250,8 @@ write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro
{
NMSettingBond *s_bond;
const char *iface;
- guint32 i, num_opts;
+ const char *const* kernel_names;
+ GString *str;
s_bond = nm_connection_get_setting_bond (connection);
if (!s_bond) {
@@ -1268,25 +1269,21 @@ write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro
svSetValue (ifcfg, "DEVICE", iface, FALSE);
svSetValue (ifcfg, "BONDING_OPTS", NULL, FALSE);
- num_opts = nm_setting_bond_get_num_options (s_bond);
- if (num_opts > 0) {
- GString *str = g_string_sized_new (64);
-
- for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) {
- const char *key, *value;
+ str = g_string_sized_new (64);
- if (!nm_setting_bond_get_option (s_bond, i, &key, &value))
- continue;
+ kernel_names = nm_setting_bond_get_kernel_names();
+ for (; *kernel_names; kernel_names++) {
+ if (nm_setting_bond_is_default (s_bond, *kernel_names, NULL)) {
+ const char *strval = nm_setting_bond_get_string (s_bond, *kernel_names);
- if (str->len)
- g_string_append_c (str, ' ');
-
- g_string_append_printf (str, "%s=%s", key, value);
+ /* FIXME: how to represent NULL values that are not default values? */
+ g_string_append_printf (str, "%s=%s ", *kernel_names, strval ? strval : "");
}
+ }
+ if (str->len > 0) {
+ g_string_truncate (str, str->len-1);
- if (str->len)
- svSetValue (ifcfg, "BONDING_OPTS", str->str, FALSE);
-
+ svSetValue (ifcfg, "BONDING_OPTS", str->str, FALSE);
g_string_free (str, TRUE);
}
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index 6949d1e5b1..d96a98dfbc 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -581,7 +581,7 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
}
if (NM_IS_SETTING_BOND (setting)) {
if (strcmp (*iter, NM_SETTING_BOND_INTERFACE_NAME))
- nm_setting_bond_add_option (NM_SETTING_BOND (setting), *iter, value);
+ nm_setting_bond_set_string (NM_SETTING_BOND (setting), *iter, value);
}
g_free (value);
}