core: use nm_platform_master_*_option() for bonds
Acked-by: Dan Winship <danw@gnome.org>
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <netinet/ether.h>
|
#include <netinet/ether.h>
|
||||||
|
|
||||||
|
#include "gsystem-local-alloc.h"
|
||||||
#include "nm-device-bond.h"
|
#include "nm-device-bond.h"
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
#include "nm-utils.h"
|
#include "nm-utils.h"
|
||||||
@@ -179,10 +180,12 @@ match_l2_config (NMDevice *self, NMConnection *connection)
|
|||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
|
|
||||||
static const struct {
|
typedef struct {
|
||||||
const char *option;
|
const char *name;
|
||||||
const char *default_value;
|
const char *default_value;
|
||||||
} bonding_defaults[] = {
|
} Option;
|
||||||
|
|
||||||
|
static const Option master_options[] = {
|
||||||
{ "mode", "balance-rr" },
|
{ "mode", "balance-rr" },
|
||||||
{ "arp_interval", "0" },
|
{ "arp_interval", "0" },
|
||||||
{ "miimon", "0" },
|
{ "miimon", "0" },
|
||||||
@@ -204,98 +207,90 @@ static const struct {
|
|||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
remove_bonding_entries (const char *iface, const char *path)
|
option_valid_for_nm_setting (NMSettingBond *s_bond, const Option *option)
|
||||||
{
|
{
|
||||||
char cmd[20];
|
const char **valid_opts = nm_setting_bond_get_valid_options (s_bond);
|
||||||
char *value, **entries;
|
|
||||||
gboolean ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!g_file_get_contents (path, &value, NULL, NULL))
|
for (; *valid_opts; valid_opts++)
|
||||||
return;
|
if (!strcmp (option->name, *valid_opts))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_bonding_entries (NMDevice *device, const char *option)
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
|
||||||
|
g_return_if_fail (value);
|
||||||
|
|
||||||
entries = g_strsplit (value, " ", -1);
|
entries = g_strsplit (value, " ", -1);
|
||||||
for (i = 0; entries[i]; i++) {
|
for (entry = entries; *entry; entry++) {
|
||||||
snprintf (cmd, sizeof (cmd), "-%s", g_strstrip (entries[i]));
|
snprintf (cmd, sizeof (cmd), "-%s", g_strstrip (*entry));
|
||||||
ret = nm_utils_do_sysctl (path, cmd);
|
if (!nm_platform_master_set_option (ifindex, option, cmd))
|
||||||
if (!ret) {
|
|
||||||
nm_log_warn (LOGD_HW, "(%s): failed to remove entry '%s' from '%s'",
|
nm_log_warn (LOGD_HW, "(%s): failed to remove entry '%s' from '%s'",
|
||||||
iface, entries[i], path);
|
ifname, *entry, option);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_strfreev (entries);
|
g_strfreev (entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
option_valid_for_nm_setting (const char *option, const char **valid_opts)
|
apply_bonding_config (NMDevice *device, NMSettingBond *s_bond)
|
||||||
{
|
{
|
||||||
while (*valid_opts) {
|
int ifindex = nm_device_get_ifindex (device);
|
||||||
if (strcmp (option, *valid_opts) == 0)
|
const char *ifname = nm_device_get_iface (device);
|
||||||
return TRUE;
|
static const Option *option;
|
||||||
valid_opts++;
|
const char *value;
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
g_return_val_if_fail (ifindex, FALSE);
|
||||||
apply_bonding_config (const char *iface, NMSettingBond *s_bond)
|
|
||||||
{
|
|
||||||
const char **valid_opts;
|
|
||||||
const char *option, *value;
|
|
||||||
char path[FILENAME_MAX];
|
|
||||||
char *current, *space;
|
|
||||||
gboolean ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
g_return_val_if_fail (iface != NULL, FALSE);
|
|
||||||
|
|
||||||
/* Remove old slaves and arp_ip_targets */
|
/* Remove old slaves and arp_ip_targets */
|
||||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/arp_ip_target", iface);
|
remove_bonding_entries (device, "arp_ip_target");
|
||||||
remove_bonding_entries (iface, path);
|
remove_bonding_entries (device, "slaves");
|
||||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/slaves", iface);
|
|
||||||
remove_bonding_entries (iface, path);
|
|
||||||
|
|
||||||
/* Apply config/defaults */
|
/* Apply config/defaults */
|
||||||
valid_opts = nm_setting_bond_get_valid_options (s_bond);
|
for (option = master_options; option->name; option++) {
|
||||||
for (i = 0; bonding_defaults[i].option; i++) {
|
gs_free char *old_value = NULL;
|
||||||
option = bonding_defaults[i].option;
|
char *space;
|
||||||
if (option_valid_for_nm_setting (option, valid_opts))
|
|
||||||
value = nm_setting_bond_get_option_by_name (s_bond, option);
|
|
||||||
else
|
|
||||||
value = NULL;
|
|
||||||
if (!value)
|
|
||||||
value = bonding_defaults[i].default_value;
|
|
||||||
|
|
||||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/%s", iface, option);
|
value = NULL;
|
||||||
if (g_file_get_contents (path, ¤t, NULL, NULL)) {
|
if (option_valid_for_nm_setting (s_bond, option))
|
||||||
g_strstrip (current);
|
value = nm_setting_bond_get_option_by_name (s_bond, option->name);
|
||||||
space = strchr (current, ' ');
|
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)
|
if (space)
|
||||||
*space = '\0';
|
*space = '\0';
|
||||||
if (strcmp (current, value) != 0) {
|
|
||||||
ret = nm_utils_do_sysctl (path, value);
|
if (g_strcmp0 (value, old_value)) {
|
||||||
if (!ret) {
|
if (!nm_platform_master_set_option (ifindex, option->name, value))
|
||||||
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
||||||
"'%s' to '%s'", iface, option, value);
|
"'%s' to '%s'", ifname, option->name, value);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle arp_ip_target */
|
/* Handle arp_ip_target */
|
||||||
value = nm_setting_bond_get_option_by_name (s_bond, "arp_ip_target");
|
value = nm_setting_bond_get_option_by_name (s_bond, "arp_ip_target");
|
||||||
if (value) {
|
if (value) {
|
||||||
char **addresses, cmd[20];
|
char **addresses, **address;
|
||||||
|
|
||||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/arp_ip_target", iface);
|
|
||||||
addresses = g_strsplit (value, ",", -1);
|
addresses = g_strsplit (value, ",", -1);
|
||||||
for (i = 0; addresses[i]; i++) {
|
for (address = addresses; *address; address++) {
|
||||||
snprintf (cmd, sizeof (cmd), "+%s", g_strstrip (addresses[i]));
|
char cmd[20];
|
||||||
ret = nm_utils_do_sysctl (path, cmd);
|
|
||||||
if (!ret) {
|
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'",
|
nm_log_warn (LOGD_HW, "(%s): failed to add arp_ip_target '%s'",
|
||||||
iface, addresses[i]);
|
ifname, *address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_strfreev (addresses);
|
g_strfreev (addresses);
|
||||||
@@ -324,7 +319,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||||||
/* Interface must be down to set bond options */
|
/* Interface must be down to set bond options */
|
||||||
nm_device_take_down (dev, TRUE);
|
nm_device_take_down (dev, TRUE);
|
||||||
|
|
||||||
if (!apply_bonding_config (nm_device_get_ip_iface (dev), s_bond))
|
if (!apply_bonding_config (dev, s_bond))
|
||||||
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||||
|
|
||||||
nm_device_bring_up (dev, TRUE, &no_firmware);
|
nm_device_bring_up (dev, TRUE, &no_firmware);
|
||||||
|
Reference in New Issue
Block a user