mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 21:50:18 +01:00
bond: handle bond options more gracefully
Support new bonding options and set them carefully. The options cannot be set arbitrarily because they interfere with each other. This commit is forward-ported from rhel-6.5, see patch rh901662-bond-more-options.patch, originally written by Dan Williams. https://bugzilla.redhat.com/show_bug.cgi?id=901662 https://bugzilla.redhat.com/show_bug.cgi?id=905532 Co-Authored-By: Dan Williams <dcbw@redhat.com> Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
parent
a4004fd2e9
commit
4b85408e34
4 changed files with 287 additions and 147 deletions
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
|
|
@ -81,19 +84,43 @@ enum {
|
|||
LAST_PROP
|
||||
};
|
||||
|
||||
enum {
|
||||
TYPE_INT,
|
||||
TYPE_STR,
|
||||
TYPE_BOTH,
|
||||
TYPE_IP,
|
||||
};
|
||||
|
||||
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" },
|
||||
{ NM_SETTING_BOND_OPTION_MIIMON, "100" },
|
||||
{ NM_SETTING_BOND_OPTION_DOWNDELAY, "0" },
|
||||
{ NM_SETTING_BOND_OPTION_UPDELAY, "0" },
|
||||
{ NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0" },
|
||||
{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "" },
|
||||
{ NM_SETTING_BOND_OPTION_PRIMARY, "" },
|
||||
{ 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_STR },
|
||||
{ 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 },
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -192,7 +219,61 @@ nm_setting_bond_get_option (NMSettingBond *setting,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
validate_option (const char *name)
|
||||
validate_int (const char *name, const char *value, const BondDefault *def)
|
||||
{
|
||||
glong num;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < strlen (value); i++) {
|
||||
if (!g_ascii_isdigit (value[i]) && value[i] != '-')
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
num = strtol (value, NULL, 10);
|
||||
if (errno)
|
||||
return FALSE;
|
||||
if (num < def->min || num > def->max)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
validate_list (const char *name, const char *value, const BondDefault *def)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; def->list && i < G_N_ELEMENTS (def->list) && def->list[i]; i++) {
|
||||
if (g_strcmp0 (def->list[i], value) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* empty validation list means all values pass */
|
||||
return (def->list == NULL || def->list[0] == NULL) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
validate_ip (const char *name, const char *value)
|
||||
{
|
||||
char **ips, **iter;
|
||||
gboolean success = TRUE;
|
||||
struct in_addr addr;
|
||||
|
||||
if (!value || !value[0])
|
||||
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;
|
||||
}
|
||||
|
||||
/* If value is NULL, validates name only */
|
||||
static gboolean
|
||||
validate_option (const char *name, const char *value)
|
||||
{
|
||||
guint i;
|
||||
|
||||
|
|
@ -200,8 +281,21 @@ validate_option (const char *name)
|
|||
g_return_val_if_fail (name[0] != '\0', FALSE);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
|
||||
if (g_strcmp0 (defaults[i].opt, name) == 0)
|
||||
return TRUE;
|
||||
if (g_strcmp0 (defaults[i].opt, name) == 0) {
|
||||
if (value == NULL)
|
||||
return TRUE;
|
||||
else if (defaults[i].opt_type == TYPE_INT)
|
||||
return validate_int (name, value, &defaults[i]);
|
||||
else if (defaults[i].opt_type == TYPE_STR)
|
||||
return validate_list (name, value, &defaults[i]);
|
||||
else if (defaults[i].opt_type == TYPE_BOTH)
|
||||
return validate_int (name, value, &defaults[i])
|
||||
|| validate_list (name, value, &defaults[i]);
|
||||
else if (defaults[i].opt_type == TYPE_IP)
|
||||
return validate_ip (name, value);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -222,7 +316,7 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting,
|
|||
const char *name)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
|
||||
g_return_val_if_fail (validate_option (name), NULL);
|
||||
g_return_val_if_fail (validate_option (name, NULL), NULL);
|
||||
|
||||
return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
|
||||
}
|
||||
|
|
@ -246,17 +340,13 @@ gboolean nm_setting_bond_add_option (NMSettingBond *setting,
|
|||
const char *value)
|
||||
{
|
||||
NMSettingBondPrivate *priv;
|
||||
size_t value_len;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
|
||||
g_return_val_if_fail (validate_option (name), FALSE);
|
||||
g_return_val_if_fail (validate_option (name, value), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
priv = NM_SETTING_BOND_GET_PRIVATE (setting);
|
||||
|
||||
value_len = strlen (value);
|
||||
g_return_val_if_fail (value_len > 0 && value_len < 200, FALSE);
|
||||
|
||||
g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value));
|
||||
|
||||
if ( !strcmp (name, NM_SETTING_BOND_OPTION_MIIMON)
|
||||
|
|
@ -293,7 +383,7 @@ nm_setting_bond_remove_option (NMSettingBond *setting,
|
|||
gboolean found;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
|
||||
g_return_val_if_fail (validate_option (name), FALSE);
|
||||
g_return_val_if_fail (validate_option (name, NULL), FALSE);
|
||||
|
||||
found = g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
|
||||
if (found)
|
||||
|
|
@ -338,7 +428,7 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
|
|||
guint i;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
|
||||
g_return_val_if_fail (validate_option (name), NULL);
|
||||
g_return_val_if_fail (validate_option (name, NULL), NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
|
||||
if (g_strcmp0 (defaults[i].opt, name) == 0)
|
||||
|
|
@ -386,10 +476,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
|
|||
|
||||
g_hash_table_iter_init (&iter, priv->options);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
|
||||
if ( !validate_option (key)
|
||||
|| !value[0]
|
||||
|| (strlen (value) > 200)
|
||||
|| strchr (value, ' ')) {
|
||||
if (!value[0] || !validate_option (key, value)) {
|
||||
g_set_error (error,
|
||||
NM_SETTING_BOND_ERROR,
|
||||
NM_SETTING_BOND_ERROR_INVALID_OPTION,
|
||||
|
|
@ -589,7 +676,6 @@ nm_setting_bond_init (NMSettingBond *setting)
|
|||
|
||||
/* Default values: */
|
||||
nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr");
|
||||
nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MIIMON, "100");
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -59,13 +59,20 @@ GQuark nm_setting_bond_error_quark (void);
|
|||
#define NM_SETTING_BOND_OPTIONS "options"
|
||||
|
||||
/* Valid options for the 'options' property */
|
||||
#define NM_SETTING_BOND_OPTION_MODE "mode"
|
||||
#define NM_SETTING_BOND_OPTION_MIIMON "miimon"
|
||||
#define NM_SETTING_BOND_OPTION_DOWNDELAY "downdelay"
|
||||
#define NM_SETTING_BOND_OPTION_UPDELAY "updelay"
|
||||
#define NM_SETTING_BOND_OPTION_ARP_INTERVAL "arp_interval"
|
||||
#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET "arp_ip_target"
|
||||
#define NM_SETTING_BOND_OPTION_PRIMARY "primary"
|
||||
#define NM_SETTING_BOND_OPTION_MODE "mode"
|
||||
#define NM_SETTING_BOND_OPTION_MIIMON "miimon"
|
||||
#define NM_SETTING_BOND_OPTION_DOWNDELAY "downdelay"
|
||||
#define NM_SETTING_BOND_OPTION_UPDELAY "updelay"
|
||||
#define NM_SETTING_BOND_OPTION_ARP_INTERVAL "arp_interval"
|
||||
#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET "arp_ip_target"
|
||||
#define NM_SETTING_BOND_OPTION_ARP_VALIDATE "arp_validate"
|
||||
#define NM_SETTING_BOND_OPTION_PRIMARY "primary"
|
||||
#define NM_SETTING_BOND_OPTION_PRIMARY_RESELECT "primary_reselect"
|
||||
#define NM_SETTING_BOND_OPTION_FAIL_OVER_MAC "fail_over_mac"
|
||||
#define NM_SETTING_BOND_OPTION_USE_CARRIER "use_carrier"
|
||||
#define NM_SETTING_BOND_OPTION_AD_SELECT "ad_select"
|
||||
#define NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY "xmit_hash_policy"
|
||||
#define NM_SETTING_BOND_OPTION_RESEND_IGMP "resend_igmp"
|
||||
|
||||
typedef struct {
|
||||
NMSetting parent;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <glib/gi18n.h>
|
||||
|
||||
#include <netinet/ether.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gsystem-local-alloc.h"
|
||||
#include "nm-device-bond.h"
|
||||
|
|
@ -180,150 +182,179 @@ match_l2_config (NMDevice *self, NMConnection *connection)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *default_value;
|
||||
} Option;
|
||||
|
||||
static const Option master_options[] = {
|
||||
{ "mode", "balance-rr" },
|
||||
{ "arp_interval", "0" },
|
||||
{ "miimon", "0" },
|
||||
|
||||
{ "ad_select", "stable" },
|
||||
{ "arp_validate", "none" },
|
||||
{ "downdelay", "0" },
|
||||
{ "fail_over_mac", "none" },
|
||||
{ "lacp_rate", "slow" },
|
||||
{ "min_links", "0" },
|
||||
{ "num_grat_arp", "1" },
|
||||
{ "num_unsol_na", "1" },
|
||||
{ "primary", "" },
|
||||
{ "primary_reselect", "always" },
|
||||
{ "resend_igmp", "1" },
|
||||
{ "updelay", "0" },
|
||||
{ "use_carrier", "1" },
|
||||
{ "xmit_hash_policy", "layer2" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static gboolean
|
||||
option_valid_for_nm_setting (NMSettingBond *s_bond, const Option *option)
|
||||
set_bond_attr (const char *iface, const char *attr, const char *value)
|
||||
{
|
||||
const char **valid_opts = nm_setting_bond_get_valid_options (s_bond);
|
||||
char file[FILENAME_MAX];
|
||||
gboolean ret;
|
||||
|
||||
for (; *valid_opts; valid_opts++)
|
||||
if (!strcmp (option->name, *valid_opts))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
snprintf (file, sizeof (file), "/sys/class/net/%s/bonding/%s", iface, attr);
|
||||
ret = nm_utils_do_sysctl (file, value);
|
||||
if (!ret) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
||||
"'%s' to '%s': %d", iface, attr, value, errno);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_bonding_entries (NMDevice *device, const char *option)
|
||||
set_arp_targets (const char *iface,
|
||||
const char *value,
|
||||
const char *delim,
|
||||
const char *prefix)
|
||||
{
|
||||
int ifindex = nm_device_get_ifindex (device);
|
||||
const char *ifname = nm_device_get_iface (device);
|
||||
gs_free char *value = nm_platform_master_get_option (ifindex, option);
|
||||
char **entries, **entry;
|
||||
char cmd[20];
|
||||
char **items, **iter, *tmp;
|
||||
|
||||
g_return_if_fail (value);
|
||||
|
||||
entries = g_strsplit (value, " ", -1);
|
||||
for (entry = entries; *entry; entry++) {
|
||||
snprintf (cmd, sizeof (cmd), "-%s", g_strstrip (*entry));
|
||||
if (!nm_platform_master_set_option (ifindex, option, cmd))
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to remove entry '%s' from '%s'",
|
||||
ifname, *entry, option);
|
||||
}
|
||||
g_strfreev (entries);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
apply_bonding_config (NMDevice *device, NMSettingBond *s_bond)
|
||||
{
|
||||
int ifindex = nm_device_get_ifindex (device);
|
||||
const char *ifname = nm_device_get_iface (device);
|
||||
static const Option *option;
|
||||
const char *value;
|
||||
|
||||
g_return_val_if_fail (ifindex, FALSE);
|
||||
|
||||
/* Remove old slaves and arp_ip_targets */
|
||||
remove_bonding_entries (device, "arp_ip_target");
|
||||
remove_bonding_entries (device, "slaves");
|
||||
|
||||
/* Apply config/defaults */
|
||||
for (option = master_options; option->name; option++) {
|
||||
gs_free char *old_value = NULL;
|
||||
char *space;
|
||||
|
||||
value = NULL;
|
||||
if (option_valid_for_nm_setting (s_bond, option))
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, option->name);
|
||||
if (!value)
|
||||
value = option->default_value;
|
||||
|
||||
old_value = nm_platform_master_get_option (ifindex, option->name);
|
||||
/* FIXME: This could be handled in nm-platform. */
|
||||
space = strchr (old_value, ' ');
|
||||
if (space)
|
||||
*space = '\0';
|
||||
|
||||
if (g_strcmp0 (value, old_value)) {
|
||||
if (!nm_platform_master_set_option (ifindex, option->name, value))
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
||||
"'%s' to '%s'", ifname, option->name, value);
|
||||
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 (iface, "arp_ip_target", tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
}
|
||||
g_strfreev (items);
|
||||
}
|
||||
|
||||
/* Handle arp_ip_target */
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, "arp_ip_target");
|
||||
if (value) {
|
||||
char **addresses, **address;
|
||||
static void
|
||||
set_simple_option (const char *iface,
|
||||
const char *attr,
|
||||
NMSettingBond *s_bond,
|
||||
const char *opt)
|
||||
{
|
||||
const char *value, *def;
|
||||
|
||||
addresses = g_strsplit (value, ",", -1);
|
||||
for (address = addresses; *address; address++) {
|
||||
char cmd[20];
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, opt);
|
||||
def = nm_setting_bond_get_option_default (s_bond, opt);
|
||||
set_bond_attr (iface, attr, value ? value : def);
|
||||
}
|
||||
|
||||
snprintf (cmd, sizeof (cmd), "+%s", g_strstrip (*address));
|
||||
if (!nm_platform_master_set_option (ifindex, "arp_ip_target", cmd)){
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to add arp_ip_target '%s'",
|
||||
ifname, *address);
|
||||
}
|
||||
}
|
||||
g_strfreev (addresses);
|
||||
static NMActStageReturn
|
||||
apply_bonding_config (NMDevice *device)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingBond *s_bond;
|
||||
const char *iface = nm_device_get_ip_iface (device);
|
||||
const char *mode, *value;
|
||||
char *path, *contents;
|
||||
gboolean set_arp_interval = TRUE;
|
||||
|
||||
/* Option restrictions:
|
||||
*
|
||||
* arp_interval conflicts miimon > 0
|
||||
* arp_interval conflicts [ alb, tlb ]
|
||||
* arp_validate needs [ active-backup ]
|
||||
* downdelay needs miimon
|
||||
* updelay needs miimon
|
||||
* primary needs [ active-backup, tlb, alb ]
|
||||
*
|
||||
* clearing miimon requires that arp_interval be 0, but clearing
|
||||
* arp_interval doesn't require miimon to be 0
|
||||
*/
|
||||
|
||||
connection = nm_device_get_connection (device);
|
||||
g_assert (connection);
|
||||
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";
|
||||
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
|
||||
if (value && atoi (value)) {
|
||||
/* clear arp interval */
|
||||
set_bond_attr (iface, "arp_interval", "0");
|
||||
set_arp_interval = FALSE;
|
||||
|
||||
set_bond_attr (iface, "miimon", value);
|
||||
set_simple_option (iface, "updelay", s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
|
||||
set_simple_option (iface, "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 (iface, "miimon", "100");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
/* The stuff after 'mode' requires the given mode or doesn't care */
|
||||
set_bond_attr (iface, "mode", mode);
|
||||
|
||||
/* arp_interval not compatible with ALB, TLB */
|
||||
if (g_strcmp0 (mode, "balance-alb") == 0 || g_strcmp0 (mode, "balance-tlb") == 0)
|
||||
set_arp_interval = FALSE;
|
||||
|
||||
if (set_arp_interval) {
|
||||
set_simple_option (iface, "arp_interval", s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
|
||||
|
||||
/* 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 (iface, "arp_validate", value);
|
||||
else
|
||||
set_bond_attr (iface, "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 (iface, "primary", value ? value : "");
|
||||
}
|
||||
|
||||
/* Clear ARP targets */
|
||||
path = g_strdup_printf ("/sys/class/net/%s/bonding/arp_ip_target", iface);
|
||||
if (g_file_get_contents (path, &contents, NULL, NULL)) {
|
||||
set_arp_targets (iface, contents, " \n", "-");
|
||||
g_free (contents);
|
||||
}
|
||||
g_free (path);
|
||||
|
||||
/* Add new ARP targets */
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
|
||||
if (value)
|
||||
set_arp_targets (iface, value, ",", "+");
|
||||
|
||||
set_simple_option (iface, "primary_reselect", s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT);
|
||||
set_simple_option (iface, "fail_over_mac", s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC);
|
||||
set_simple_option (iface, "use_carrier", s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER);
|
||||
set_simple_option (iface, "ad_select", s_bond, NM_SETTING_BOND_OPTION_AD_SELECT);
|
||||
set_simple_option (iface, "xmit_hash_policy", s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY);
|
||||
set_simple_option (iface, "resend_igmp", s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP);
|
||||
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
||||
{
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMConnection *connection;
|
||||
NMSettingBond *s_bond;
|
||||
gboolean no_firmware = FALSE;
|
||||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
||||
connection = nm_device_get_connection (dev);
|
||||
g_assert (connection);
|
||||
s_bond = nm_connection_get_setting_bond (connection);
|
||||
g_assert (s_bond);
|
||||
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* Interface must be down to set bond options */
|
||||
nm_device_take_down (dev, TRUE);
|
||||
/* Interface must be down to set bond options */
|
||||
nm_device_take_down (dev, TRUE);
|
||||
ret = apply_bonding_config (dev);
|
||||
nm_device_bring_up (dev, TRUE, &no_firmware);
|
||||
|
||||
if (!apply_bonding_config (dev, s_bond))
|
||||
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||
|
||||
nm_device_bring_up (dev, TRUE, &no_firmware);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3722,8 +3722,24 @@ handle_bond_option (NMSettingBond *s_bond,
|
|||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
if (!nm_setting_bond_add_option (s_bond, key, value))
|
||||
char *sanitized = NULL, *j;
|
||||
const char *p = value;
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static NMSetting *
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue