bond: merge branch 'th/bond-normalize'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/570

(cherry picked from commit ecba921920)
This commit is contained in:
Thomas Haller 2020-07-11 15:06:50 +02:00
commit 6225ace76f
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
10 changed files with 395 additions and 278 deletions

View file

@ -4273,45 +4273,36 @@ set_bond_option (NmCli *nmc, NMConnection *con, const OptionInfo *option, const
{
NMSettingBond *s_bond;
gboolean success;
gs_free char *name = NULL;
char *p;
s_bond = nm_connection_get_setting_bond (con);
g_return_val_if_fail (s_bond, FALSE);
if (!value)
return TRUE;
name = g_strdup (option->option);
for (p = name; p[0]; p++) {
if (p[0] == '-')
p[0] = '_';
}
if (strcmp (option->option, "mode") == 0) {
value = nmc_bond_validate_mode (value, error);
if (!value)
return FALSE;
if (nm_str_is_empty (value)) {
nm_setting_bond_remove_option (s_bond, name);
success = TRUE;
} else
success = _nm_meta_setting_bond_add_option (NM_SETTING (s_bond), name, value, error);
if (g_strcmp0 (value, "active-backup") == 0) {
const char *primary[] = { "primary", NULL };
enable_options (NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS, primary);
if (!success)
return FALSE;
if (success) {
if (nm_streq (name, NM_SETTING_BOND_OPTION_MODE)) {
value = nmc_bond_validate_mode (value, error);
if (nm_streq (value, "active-backup")) {
enable_options (NM_SETTING_BOND_SETTING_NAME,
NM_SETTING_BOND_OPTIONS,
NM_MAKE_STRV ("primary"));
}
}
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MODE, value);
} else if (strcmp (option->option, "primary") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_PRIMARY, value);
else if (strcmp (option->option, "miimon") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MIIMON, value);
else if (strcmp (option->option, "downdelay") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, value);
else if (strcmp (option->option, "updelay") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY, value);
else if (strcmp (option->option, "arp-interval") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL, value);
else if (strcmp (option->option, "arp-ip-target") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, value);
else if (strcmp (option->option, "lacp-rate") == 0)
success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_LACP_RATE, value);
else
g_return_val_if_reached (FALSE);
if (!success) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("Error: error adding bond option '%s=%s'."),
option->option, value);
}
return success;

View file

@ -2357,8 +2357,8 @@ _get_fcn_bond_options (ARGS_GET_FCN)
RETURN_STR_TO_FREE (g_string_free (str, FALSE));
}
static gboolean
_optionlist_set_fcn_bond_options (NMSetting *setting,
gboolean
_nm_meta_setting_bond_add_option (NMSetting *setting,
const char *name,
const char *value,
GError **error)
@ -2366,8 +2366,14 @@ _optionlist_set_fcn_bond_options (NMSetting *setting,
gs_free char *tmp_value = NULL;
char *p;
if (!value) {
nm_setting_bond_remove_option (NM_SETTING_BOND (setting), name);
if ( !value
|| !value[0]) {
if (!nm_setting_bond_remove_option (NM_SETTING_BOND (setting), name)) {
nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT,
_("failed to unset bond option \"%s\""),
name);
return FALSE;
}
return TRUE;
}
@ -2388,6 +2394,15 @@ _optionlist_set_fcn_bond_options (NMSetting *setting,
name);
return FALSE;
}
if (nm_streq (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL)) {
if (_nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT, 0) > 0)
_nm_setting_bond_remove_options_miimon (NM_SETTING_BOND (setting));
} else if (nm_streq (name, NM_SETTING_BOND_OPTION_MIIMON)) {
if (_nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT, 0) > 0)
_nm_setting_bond_remove_options_arp_interval (NM_SETTING_BOND (setting));
}
return TRUE;
}
@ -4883,7 +4898,7 @@ static const NMMetaPropertyInfo property_info_BOND_OPTIONS =
),
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
PROPERTY_TYP_DATA_SUBTYPE (optionlist,
.set_fcn = _optionlist_set_fcn_bond_options,
.set_fcn = _nm_meta_setting_bond_add_option,
),
.nested = &nm_meta_property_typ_data_bond,
),

View file

@ -524,4 +524,11 @@ extern const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond;
/*****************************************************************************/
gboolean _nm_meta_setting_bond_add_option (NMSetting *setting,
const char *name,
const char *value,
GError **error);
/*****************************************************************************/
#endif /* __NM_META_SETTING_DESC_H__ */

View file

@ -16,6 +16,7 @@
#include "nmt-page-bond.h"
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
#include "nmt-mac-entry.h"
#include "nmt-address-list.h"
#include "nmt-slave-list.h"
@ -52,6 +53,14 @@ typedef struct {
gboolean updating;
} NmtPageBondPrivate;
/*****************************************************************************/
static void arp_ip_target_widget_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data);
/*****************************************************************************/
NmtEditorPage *
nmt_page_bond_new (NMConnection *conn,
NmtDeviceEntry *deventry)
@ -97,8 +106,10 @@ bond_options_changed (GObject *object,
NMSettingBond *s_bond = NM_SETTING_BOND (object);
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
gs_free const char **ips = NULL;
const char *val;
char **ips;
gboolean visible_mii;
NMBondMode mode;
if (priv->updating)
return;
@ -108,54 +119,47 @@ bond_options_changed (GObject *object,
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
nmt_newt_popup_set_active_id (priv->mode, val);
if (!strcmp (val, "active-backup")) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
nmt_newt_entry_set_text (priv->primary, val);
} else
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE);
mode = _nm_setting_bond_mode_from_string (val ?: "");
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
nmt_newt_entry_set_text (priv->primary, val);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), mode == NM_BOND_MODE_ACTIVEBACKUP);
if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_UNKNOWN) {
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
if (val && strcmp (val, "0") != 0)
if (_nm_utils_ascii_str_to_int64 (val, 10, 0, G_MAXINT, 0) > 0)
priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_ARP;
else
priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_MII;
}
nmt_newt_popup_set_active (priv->monitoring, priv->monitoring_mode);
if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
nmt_newt_entry_set_text (priv->miimon, val);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
nmt_newt_entry_set_text (priv->miimon, val ?: "0");
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
nmt_newt_entry_set_text (priv->updelay, val);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
nmt_newt_entry_set_text (priv->updelay, val ?: "0");
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
nmt_newt_entry_set_text (priv->downdelay, val);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
nmt_newt_entry_set_text (priv->downdelay, val ?: "0");
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), FALSE);
} else {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
nmt_newt_entry_set_text (priv->arp_interval, val);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
nmt_newt_entry_set_text (priv->arp_interval, val ?: "0");
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
ips = g_strsplit (val, ",", -1);
g_object_set (G_OBJECT (priv->arp_ip_target),
"strings", ips,
NULL);
g_strfreev (ips);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
ips = nm_utils_bond_option_arp_ip_targets_split (val);
g_object_set (G_OBJECT (priv->arp_ip_target),
"strings", ips ?: NM_PTRARRAY_EMPTY (const char *),
NULL);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), FALSE);
}
visible_mii = (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), !visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), !visible_mii);
priv->updating = FALSE;
}
@ -193,7 +197,23 @@ slaves_changed (GObject *object,
nmt_newt_component_set_sensitive (NMT_NEWT_COMPONENT (priv->mode), TRUE);
}
#define WIDGET_CHANGED_FUNC(widget, func, option) \
static void
_bond_add_option (NMSettingBond *s_bond,
const char *option,
const char *value)
{
if (nm_str_is_empty (value))
nm_setting_bond_remove_option (s_bond, option);
else
nm_setting_bond_add_option (s_bond, option, value);
if (nm_streq (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL))
_nm_setting_bond_remove_options_miimon (s_bond);
else if (nm_streq (option, NM_SETTING_BOND_OPTION_MIIMON))
_nm_setting_bond_remove_options_arp_interval (s_bond);
}
#define WIDGET_CHANGED_FUNC(widget, func, option, dflt) \
static void \
widget ## _widget_changed (GObject *object, \
GParamSpec *pspec, \
@ -201,20 +221,22 @@ widget ## _widget_changed (GObject *object, \
{ \
NmtPageBond *bond = NMT_PAGE_BOND (user_data); \
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond); \
const char *v; \
\
if (priv->updating) \
return; \
\
v = func (priv->widget); \
priv->updating = TRUE; \
nm_setting_bond_add_option (priv->s_bond, option, func (priv->widget)); \
_bond_add_option (priv->s_bond, option, v ?: dflt); \
priv->updating = FALSE; \
}
WIDGET_CHANGED_FUNC (primary, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_PRIMARY)
WIDGET_CHANGED_FUNC (miimon, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_MIIMON)
WIDGET_CHANGED_FUNC (updelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_UPDELAY)
WIDGET_CHANGED_FUNC (downdelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_DOWNDELAY)
WIDGET_CHANGED_FUNC (arp_interval, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_ARP_INTERVAL)
WIDGET_CHANGED_FUNC (primary, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_PRIMARY, NULL)
WIDGET_CHANGED_FUNC (miimon, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_MIIMON, "0")
WIDGET_CHANGED_FUNC (updelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_UPDELAY, "0")
WIDGET_CHANGED_FUNC (downdelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_DOWNDELAY, "0")
WIDGET_CHANGED_FUNC (arp_interval, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0")
static void
mode_widget_changed (GObject *object,
@ -230,7 +252,7 @@ mode_widget_changed (GObject *object,
mode = nmt_newt_popup_get_active_id (priv->mode);
priv->updating = TRUE;
nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_MODE, mode);
_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_MODE, mode);
priv->updating = FALSE;
if (!strcmp (mode, "balance-tlb") || !strcmp (mode, "balance-alb")) {
@ -241,8 +263,8 @@ mode_widget_changed (GObject *object,
if (!strcmp (mode, "active-backup")) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), TRUE);
nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY,
nmt_newt_entry_get_text (priv->primary));
_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY,
nmt_newt_entry_get_text (priv->primary));
} else {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE);
nm_setting_bond_remove_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
@ -256,25 +278,27 @@ monitoring_widget_changed (GObject *object,
{
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
gboolean visible_mii;
if (priv->updating)
return;
priv->monitoring_mode = nmt_newt_popup_get_active (priv->monitoring);
if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), TRUE);
visible_mii = (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), !visible_mii);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), !visible_mii);
if (visible_mii) {
miimon_widget_changed (NULL, NULL, bond);
updelay_widget_changed (NULL, NULL, bond);
downdelay_widget_changed (NULL, NULL, bond);
} else {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), FALSE);
arp_interval_widget_changed (NULL, NULL, bond);
arp_ip_target_widget_changed (NULL, NULL, bond);
}
}
@ -296,7 +320,7 @@ arp_ip_target_widget_changed (GObject *object,
target = g_strjoinv (",", ips);
priv->updating = TRUE;
nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, target);
_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, target);
priv->updating = FALSE;
g_free (target);

View file

@ -567,21 +567,6 @@ NMConnectionMultiConnect _nm_connection_get_multi_connect (NMConnection *connect
/*****************************************************************************/
typedef enum {
NM_BOND_MODE_UNKNOWN = -1,
/* The numeric values correspond to kernel's numbering of the modes. */
NM_BOND_MODE_ROUNDROBIN = 0,
NM_BOND_MODE_ACTIVEBACKUP = 1,
NM_BOND_MODE_XOR = 2,
NM_BOND_MODE_BROADCAST = 3,
NM_BOND_MODE_8023AD = 4,
NM_BOND_MODE_TLB = 5,
NM_BOND_MODE_ALB = 6,
_NM_BOND_MODE_NUM,
} NMBondMode;
NMBondMode _nm_setting_bond_mode_from_string (const char *str);
gboolean _nm_setting_bond_option_supported (const char *option, NMBondMode mode);
/*****************************************************************************/

View file

@ -10,6 +10,54 @@
/*****************************************************************************/
const char **
nm_utils_bond_option_arp_ip_targets_split (const char *arp_ip_target)
{
return nm_utils_strsplit_set_full (arp_ip_target, ",", NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
}
void
_nm_setting_bond_remove_options_miimon (NMSettingBond *s_bond)
{
g_return_if_fail (NM_IS_SETTING_BOND (s_bond));
nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
}
void
_nm_setting_bond_remove_options_arp_interval (NMSettingBond *s_bond)
{
g_return_if_fail (NM_IS_SETTING_BOND (s_bond));
nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
}
NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
_nm_setting_bond_mode_from_string,
NMBondMode,
{ g_return_val_if_fail (name, NM_BOND_MODE_UNKNOWN); },
{ return NM_BOND_MODE_UNKNOWN; },
{ "0", NM_BOND_MODE_ROUNDROBIN },
{ "1", NM_BOND_MODE_ACTIVEBACKUP },
{ "2", NM_BOND_MODE_XOR },
{ "3", NM_BOND_MODE_BROADCAST },
{ "4", NM_BOND_MODE_8023AD },
{ "5", NM_BOND_MODE_TLB },
{ "6", NM_BOND_MODE_ALB },
{ "802.3ad", NM_BOND_MODE_8023AD },
{ "active-backup", NM_BOND_MODE_ACTIVEBACKUP },
{ "balance-alb", NM_BOND_MODE_ALB },
{ "balance-rr", NM_BOND_MODE_ROUNDROBIN },
{ "balance-tlb", NM_BOND_MODE_TLB },
{ "balance-xor", NM_BOND_MODE_XOR },
{ "broadcast", NM_BOND_MODE_BROADCAST },
);
/*****************************************************************************/
gboolean
nm_utils_vlan_priority_map_parse_str (NMVlanPriorityMap map_type,
const char *str,

View file

@ -5,6 +5,7 @@
/****************************************************************************/
#include "nm-setting-bond.h"
#include "nm-setting-bridge.h"
#include "nm-setting-connection.h"
#include "nm-setting-ip-config.h"
@ -46,6 +47,29 @@ NM_AUTO_DEFINE_FCN0 (NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer
/****************************************************************************/
const char **nm_utils_bond_option_arp_ip_targets_split (const char *arp_ip_target);
void _nm_setting_bond_remove_options_miimon (NMSettingBond *s_bond);
void _nm_setting_bond_remove_options_arp_interval (NMSettingBond *s_bond);
typedef enum {
NM_BOND_MODE_UNKNOWN = -1,
/* The numeric values correspond to kernel's numbering of the modes. */
NM_BOND_MODE_ROUNDROBIN = 0,
NM_BOND_MODE_ACTIVEBACKUP = 1,
NM_BOND_MODE_XOR = 2,
NM_BOND_MODE_BROADCAST = 3,
NM_BOND_MODE_8023AD = 4,
NM_BOND_MODE_TLB = 5,
NM_BOND_MODE_ALB = 6,
_NM_BOND_MODE_NUM,
} NMBondMode;
NMBondMode _nm_setting_bond_mode_from_string (const char *str);
/*****************************************************************************/
static inline guint32
nm_utils_vlan_priority_map_get_max_prio (NMVlanPriorityMap map, gboolean from)
{

View file

@ -11,6 +11,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
#include "nm-utils.h"
#include "nm-utils-private.h"
#include "nm-connection-private.h"
@ -250,9 +251,7 @@ _bond_get_option_normalized (NMSettingBond* self,
const char* option,
gboolean get_default_only)
{
const char *arp_interval_str;
const char *mode_str;
gint64 arp_interval;
NMBondMode mode;
const char *value = NULL;
@ -261,7 +260,12 @@ _bond_get_option_normalized (NMSettingBond* self,
mode_str = _bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_MODE);
mode = _nm_setting_bond_mode_from_string (mode_str);
g_return_val_if_fail (mode != NM_BOND_MODE_UNKNOWN, NULL);
if (mode == NM_BOND_MODE_UNKNOWN) {
/* the mode is unknown, consequently, there is no normalized/default
* value either. */
return NULL;
}
if (!_nm_setting_bond_option_supported (option, mode))
return NULL;
@ -269,46 +273,44 @@ _bond_get_option_normalized (NMSettingBond* self,
/* Apply custom NetworkManager policies here */
if (!get_default_only) {
if (NM_IN_STRSET (option,
NM_SETTING_BOND_OPTION_UPDELAY,
NM_SETTING_BOND_OPTION_DOWNDELAY,
NM_SETTING_BOND_OPTION_MIIMON)) {
NM_SETTING_BOND_OPTION_ARP_INTERVAL,
NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) {
int miimon;
/* if arp_interval is explicitly set and miimon is not, then disable miimon
* (and related updelay and downdelay) as recommended by the kernel docs */
arp_interval_str = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
arp_interval = _nm_utils_ascii_str_to_int64 (arp_interval_str, 10, 0, G_MAXINT, 0);
if (!arp_interval || _bond_get_option (self, NM_SETTING_BOND_OPTION_MIIMON)) {
value = _bond_get_option (self, option);
} else {
return NULL;
miimon = _nm_utils_ascii_str_to_int64 (_bond_get_option (self, NM_SETTING_BOND_OPTION_MIIMON),
10, 0, G_MAXINT, 0);
if (miimon != 0) {
/* miimon is enabled. arp_interval values are unset. */
if (nm_streq (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL))
return "0";
return "";
}
value = _bond_get_option (self, option);
} else if (NM_IN_STRSET (option,
NM_SETTING_BOND_OPTION_NUM_GRAT_ARP,
NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)) {
/* just get one of the 2, at kernel level they're the same bond option */
value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP);
if (!value) {
if (!value)
value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA);
}
} else {
} else
value = _bond_get_option (self, option);
}
if (value)
return value;
}
if (!value) {
/* Apply rules that change the default value of an option */
if (nm_streq (option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) {
/* The default value depends on the current mode */
if (NM_IN_STRSET (mode_str, "4", "802.3ad"))
return "00:00:00:00:00:00";
else
return "";
} else {
return _bond_get_option_or_default (self, option);
}
/* Apply rules that change the default value of an option */
if (nm_streq (option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) {
/* The default value depends on the current mode */
if (mode == NM_BOND_MODE_8023AD)
return "00:00:00:00:00:00";
return "";
}
return value;
return _bond_get_option_or_default (self, option);
}
const char*
@ -447,34 +449,30 @@ validate_list (const char *name, const char *value, const OptionMeta *option_met
}
static gboolean
validate_ip (const char *name, const char *value)
validate_ip (const char *name, const char *value, GError **error)
{
gs_free char *value_clone = NULL;
struct in_addr addr;
gs_free const char **addrs = NULL;
gsize i;
if (!value || !value[0])
addrs = nm_utils_bond_option_arp_ip_targets_split (value);
if (!addrs) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' option is empty"),
name);
return FALSE;
value_clone = g_strdup (value);
value = value_clone;
for (;;) {
char *eow;
/* we do not skip over empty words. E.g
* "192.168.1.1," is an error.
*
* ... for no particular reason. */
eow = strchr (value, ',');
if (eow)
*eow = '\0';
if (inet_pton (AF_INET, value, &addr) != 1)
}
for (i = 0; addrs[i]; i++) {
if (!nm_utils_parse_inaddr_bin (AF_INET, addrs[i], NULL, NULL)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' is not a valid IPv4 address for '%s' option"),
addrs[i],
name);
return FALSE;
if (!eow)
break;
value = eow + 1;
}
}
return TRUE;
}
@ -485,6 +483,65 @@ validate_ifname (const char *name, const char *value)
return nm_utils_ifname_valid_kernel (value, NULL);
}
static gboolean
_setting_bond_validate_option (const char *name,
const char *value,
GError **error)
{
const OptionMeta *option_meta;
gboolean success;
option_meta = _get_option_meta (name);
if (!option_meta) {
if (!name) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("missing option name"));
} else {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid option '%s'"),
name);
}
return FALSE;
}
if (!value)
return TRUE;
switch (option_meta->opt_type) {
case NM_BOND_OPTION_TYPE_INT:
success = validate_int (name, value, option_meta);
goto handle_error;
case NM_BOND_OPTION_TYPE_BOTH:
success = ( validate_int (name, value, option_meta)
|| validate_list (name, value, option_meta));
goto handle_error;
case NM_BOND_OPTION_TYPE_IP:
nm_assert (nm_streq0 (name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
return validate_ip (name, value, error);
case NM_BOND_OPTION_TYPE_MAC:
success = nm_utils_hwaddr_valid (value, ETH_ALEN);
goto handle_error;
case NM_BOND_OPTION_TYPE_IFNAME:
success = validate_ifname (name, value);
goto handle_error;
}
nm_assert_not_reached ();
handle_error:
if (!success) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid value '%s' for option '%s'"),
value, name);
}
return success;
}
/**
* nm_setting_bond_validate_option:
* @name: the name of the option to validate
@ -500,31 +557,7 @@ gboolean
nm_setting_bond_validate_option (const char *name,
const char *value)
{
const OptionMeta *option_meta;
option_meta = _get_option_meta (name);
if (!option_meta)
return FALSE;
if (!value)
return TRUE;
switch (option_meta->opt_type) {
case NM_BOND_OPTION_TYPE_INT:
return validate_int (name, value, option_meta);
case NM_BOND_OPTION_TYPE_BOTH:
return ( validate_int (name, value, option_meta)
|| validate_list (name, value, option_meta));
case NM_BOND_OPTION_TYPE_IP:
return validate_ip (name, value);
case NM_BOND_OPTION_TYPE_MAC:
return nm_utils_hwaddr_valid (value, ETH_ALEN);
case NM_BOND_OPTION_TYPE_IFNAME:
return validate_ifname (name, value);
}
nm_assert_not_reached ();
return FALSE;
return _setting_bond_validate_option (name, value, NULL);
}
/**
@ -576,7 +609,8 @@ nm_setting_bond_add_option (NMSettingBond *setting,
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
if (!value || !nm_setting_bond_validate_option (name, value))
if ( !value
|| !nm_setting_bond_validate_option (name, value))
return FALSE;
priv = NM_SETTING_BOND_GET_PRIVATE (setting);
@ -650,9 +684,8 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
{
g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
if (!name) {
if (!name)
return NULL;
}
return _bond_get_option_normalized (setting,
name,
@ -703,27 +736,6 @@ _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name)
return option_meta->opt_type;
}
NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
_nm_setting_bond_mode_from_string,
NMBondMode,
{ g_return_val_if_fail (name, NM_BOND_MODE_UNKNOWN); },
{ return NM_BOND_MODE_UNKNOWN; },
{ "0", NM_BOND_MODE_ROUNDROBIN },
{ "1", NM_BOND_MODE_ACTIVEBACKUP },
{ "2", NM_BOND_MODE_XOR },
{ "3", NM_BOND_MODE_BROADCAST },
{ "4", NM_BOND_MODE_8023AD },
{ "5", NM_BOND_MODE_TLB },
{ "6", NM_BOND_MODE_ALB },
{ "802.3ad", NM_BOND_MODE_8023AD },
{ "active-backup", NM_BOND_MODE_ACTIVEBACKUP },
{ "balance-alb", NM_BOND_MODE_ALB },
{ "balance-rr", NM_BOND_MODE_ROUNDROBIN },
{ "balance-tlb", NM_BOND_MODE_TLB },
{ "balance-xor", NM_BOND_MODE_XOR },
{ "broadcast", NM_BOND_MODE_BROADCAST },
);
/*****************************************************************************/
static gboolean
@ -750,12 +762,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
n = &priv->options_idx_cache[i];
if ( !n->value_str
|| !nm_setting_bond_validate_option (n->name, n->value_str)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid option '%s' or its value '%s'"),
n->name, n->value_str);
|| !_setting_bond_validate_option (n->name, n->value_str, error)) {
g_prefix_error (error,
"%s.%s: ",
NM_SETTING_BOND_SETTING_NAME,
@ -902,9 +909,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
*/
arp_ip_target = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
if (arp_interval > 0) {
char **addrs;
guint32 addr;
if (!arp_ip_target) {
g_set_error (error,
NM_CONNECTION_ERROR,
@ -918,38 +922,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
NM_SETTING_BOND_OPTIONS);
return FALSE;
}
addrs = g_strsplit (arp_ip_target, ",", -1);
if (!addrs[0]) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' option is empty"),
NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
g_prefix_error (error, "%s.%s: ",
NM_SETTING_BOND_SETTING_NAME,
NM_SETTING_BOND_OPTIONS);
g_strfreev (addrs);
return FALSE;
}
for (i = 0; addrs[i]; i++) {
if (!inet_pton (AF_INET, addrs[i], &addr)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' is not a valid IPv4 address for '%s' option"),
NM_SETTING_BOND_OPTION_ARP_IP_TARGET,
addrs[i]);
g_prefix_error (error,
"%s.%s: ",
NM_SETTING_BOND_SETTING_NAME,
NM_SETTING_BOND_OPTIONS);
g_strfreev (addrs);
return FALSE;
}
}
g_strfreev (addrs);
} else {
if (arp_ip_target) {
g_set_error (error,

View file

@ -1830,6 +1830,7 @@ done2:
}
}
nm_assert (ptr && ptr[0]);
return ptr;
}

View file

@ -85,6 +85,16 @@ _set_bond_attr (NMDevice *device, const char *attr, const char *value)
return ret;
}
#define _set_bond_attr_take(device, attr, value) \
G_STMT_START { \
gs_free char *_tmp = (value); \
\
_set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, _tmp); \
} G_STMT_END
#define _set_bond_attr_printf(device, attr, fmt, ...) \
_set_bond_attr_take ((device), (attr), g_strdup_printf (fmt, __VA_ARGS__))
static gboolean
ignore_option (NMSettingBond *s_bond, const char *option, const char *value)
{
@ -173,22 +183,59 @@ master_update_slave_connection (NMDevice *self,
static void
set_arp_targets (NMDevice *device,
NMBondMode mode,
const char *value,
const char *delim,
const char *prefix)
const char *cur_arp_ip_target,
const char *new_arp_ip_target)
{
gs_free const char **value_v = NULL;
gs_unref_ptrarray GPtrArray *free_list = NULL;
gs_free const char **cur_strv = NULL;
gs_free const char **new_strv = NULL;
gsize cur_len;
gsize new_len;
gsize i;
gsize j;
value_v = nm_utils_strsplit_set (value, delim);
if (!value_v)
return;
for (i = 0; value_v[i]; i++) {
gs_free char *tmp = NULL;
cur_strv = nm_utils_strsplit_set_full (cur_arp_ip_target, NM_ASCII_SPACES, NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
new_strv = nm_utils_bond_option_arp_ip_targets_split (new_arp_ip_target);
tmp = g_strdup_printf ("%s%s", prefix, value_v[i]);
_set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, tmp);
cur_len = NM_PTRARRAY_LEN (cur_strv);
new_len = NM_PTRARRAY_LEN (new_strv);
if (new_len > 0) {
for (j = 0, i = 0; i < new_len; i++) {
const char *s;
in_addr_t a4;
s = new_strv[i];
if (nm_utils_parse_inaddr_bin (AF_INET, s, NULL, &a4)) {
char sbuf[INET_ADDRSTRLEN];
_nm_utils_inet4_ntop (a4, sbuf);
if (!nm_streq (s, sbuf)) {
if (!free_list)
free_list = g_ptr_array_new_with_free_func (g_free);
s = g_strdup (sbuf);
g_ptr_array_add (free_list, (gpointer) s);
}
}
if (nm_utils_strv_find_first ((char **) new_strv, i, s) < 0)
new_strv[j++] = s;
}
new_strv[j] = NULL;
new_len = j;
}
if ( cur_len == 0
&& new_len == 0)
return;
if (_nm_utils_strv_equal ((char **) cur_strv, (char **) new_strv))
return;
for (i = 0; i < cur_len; i++)
_set_bond_attr_printf (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "-%s", cur_strv[i]);
for (i = 0; i < new_len; i++)
_set_bond_attr_printf (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "+%s", new_strv[i]);
}
/*
@ -201,13 +248,17 @@ set_bond_attr_or_default (NMDevice *device,
const char *opt)
{
NMDeviceBond *self = NM_DEVICE_BOND (device);
const char *value = nm_setting_bond_get_option_or_default (s_bond, opt);
const char *value;
if (value) {
_set_bond_attr (device, opt, value);
} else {
_LOGD (LOGD_BOND, "bond option %s rejected due to incompatibility", opt);
value = nm_setting_bond_get_option_or_default (s_bond, opt);
if (!value) {
if ( _LOGT_ENABLED (LOGD_BOND)
&& nm_setting_bond_get_option_by_name (s_bond, opt))
_LOGT (LOGD_BOND, "bond option '%s' not set as it conflicts with other options", opt);
return;
}
_set_bond_attr (device, opt, value);
}
static gboolean
@ -218,8 +269,7 @@ apply_bonding_config (NMDeviceBond *self)
NMSettingBond *s_bond;
NMBondMode mode;
const char *mode_str;
const char *value;
char *contents;
gs_free char *cur_arp_ip_target = NULL;
s_bond = nm_device_get_applied_setting (device, NM_TYPE_SETTING_BOND);
g_return_val_if_fail (s_bond, FALSE);
@ -241,13 +291,13 @@ apply_bonding_config (NMDeviceBond *self)
set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
/* ARP targets: clear and initialize the list */
contents = nm_platform_sysctl_master_get_option (nm_device_get_platform (device),
ifindex,
NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
set_arp_targets (device, mode, contents, " \n", "-");
value = nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
set_arp_targets (device, mode, value, ",", "+");
g_free (contents);
cur_arp_ip_target = nm_platform_sysctl_master_get_option (nm_device_get_platform (device),
ifindex,
NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
set_arp_targets (device,
mode,
cur_arp_ip_target,
nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM);
set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);