mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-05 01:47:58 +02:00
libnm/team: merge branch 'th/libnm-team'
https://bugzilla.redhat.com/show_bug.cgi?id=1691619 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/146
This commit is contained in:
commit
3f760601d4
33 changed files with 4291 additions and 2084 deletions
28
Makefile.am
28
Makefile.am
|
|
@ -343,6 +343,8 @@ shared_nm_glib_aux_libnm_glib_aux_la_SOURCES = \
|
|||
shared/nm-glib-aux/nm-io-utils.c \
|
||||
shared/nm-glib-aux/nm-io-utils.h \
|
||||
shared/nm-glib-aux/nm-jansson.h \
|
||||
shared/nm-glib-aux/nm-json-aux.c \
|
||||
shared/nm-glib-aux/nm-json-aux.h \
|
||||
shared/nm-glib-aux/nm-keyfile-aux.c \
|
||||
shared/nm-glib-aux/nm-keyfile-aux.h \
|
||||
shared/nm-glib-aux/nm-logging-fwd.h \
|
||||
|
|
@ -356,6 +358,7 @@ shared_nm_glib_aux_libnm_glib_aux_la_SOURCES = \
|
|||
shared/nm-glib-aux/nm-shared-utils.h \
|
||||
shared/nm-glib-aux/nm-time-utils.c \
|
||||
shared/nm-glib-aux/nm-time-utils.h \
|
||||
shared/nm-glib-aux/nm-value-type.h \
|
||||
$(NULL)
|
||||
|
||||
shared_nm_glib_aux_libnm_glib_aux_la_LDFLAGS = \
|
||||
|
|
@ -788,21 +791,25 @@ libnm_core_lib_h_pub_real = \
|
|||
libnm-core/nm-version.h \
|
||||
libnm-core/nm-vpn-dbus-interface.h \
|
||||
libnm-core/nm-vpn-editor-plugin.h \
|
||||
libnm-core/nm-vpn-plugin-info.h
|
||||
libnm-core/nm-vpn-plugin-info.h \
|
||||
$(NULL)
|
||||
libnm_core_lib_h_pub_mkenums = \
|
||||
libnm-core/nm-core-enum-types.h
|
||||
libnm-core/nm-core-enum-types.h \
|
||||
$(NULL)
|
||||
libnm_core_lib_h_priv = \
|
||||
shared/nm-meta-setting.h \
|
||||
libnm-core/nm-crypto.h \
|
||||
libnm-core/nm-crypto-impl.h \
|
||||
libnm-core/nm-connection-private.h \
|
||||
libnm-core/nm-core-internal.h \
|
||||
libnm-core/nm-core-types-internal.h \
|
||||
libnm-core/nm-crypto-impl.h \
|
||||
libnm-core/nm-crypto.h \
|
||||
libnm-core/nm-keyfile-internal.h \
|
||||
libnm-core/nm-keyfile-utils.h \
|
||||
libnm-core/nm-property-compare.h \
|
||||
libnm-core/nm-setting-private.h \
|
||||
libnm-core/nm-utils-private.h
|
||||
libnm-core/nm-team-utils.h \
|
||||
libnm-core/nm-utils-private.h \
|
||||
$(NULL)
|
||||
libnm_core_lib_c_settings_real = \
|
||||
libnm-core/nm-setting-6lowpan.c \
|
||||
libnm-core/nm-setting-8021x.c \
|
||||
|
|
@ -850,22 +857,25 @@ libnm_core_lib_c_settings_real = \
|
|||
libnm-core/nm-setting-wireguard.c \
|
||||
libnm-core/nm-setting-wireless-security.c \
|
||||
libnm-core/nm-setting-wireless.c \
|
||||
libnm-core/nm-setting-wpan.c
|
||||
libnm-core/nm-setting-wpan.c \
|
||||
$(NULL)
|
||||
libnm_core_lib_c_real = \
|
||||
$(libnm_core_lib_c_settings_real) \
|
||||
shared/nm-meta-setting.c \
|
||||
libnm-core/nm-crypto.c \
|
||||
libnm-core/nm-connection.c \
|
||||
libnm-core/nm-crypto.c \
|
||||
libnm-core/nm-dbus-utils.c \
|
||||
libnm-core/nm-errors.c \
|
||||
libnm-core/nm-keyfile.c \
|
||||
libnm-core/nm-keyfile-utils.c \
|
||||
libnm-core/nm-keyfile.c \
|
||||
libnm-core/nm-property-compare.c \
|
||||
libnm-core/nm-setting.c \
|
||||
libnm-core/nm-simple-connection.c \
|
||||
libnm-core/nm-team-utils.c \
|
||||
libnm-core/nm-utils.c \
|
||||
libnm-core/nm-vpn-editor-plugin.c \
|
||||
libnm-core/nm-vpn-plugin-info.c
|
||||
libnm-core/nm-vpn-plugin-info.c \
|
||||
$(NULL)
|
||||
|
||||
if WITH_JSON_VALIDATION
|
||||
libnm_core_lib_h_priv += \
|
||||
|
|
|
|||
|
|
@ -554,7 +554,6 @@ nmc_team_check_config (const char *config, char **out_config, GError **error)
|
|||
_TEAM_CONFIG_TYPE_FILE,
|
||||
_TEAM_CONFIG_TYPE_JSON,
|
||||
} desired_type = _TEAM_CONFIG_TYPE_GUESS;
|
||||
const char *filename = NULL;
|
||||
size_t c_len = 0;
|
||||
gs_free char *config_clone = NULL;
|
||||
|
||||
|
|
@ -588,22 +587,10 @@ nmc_team_check_config (const char *config, char **out_config, GError **error)
|
|||
config);
|
||||
return FALSE;
|
||||
}
|
||||
filename = config;
|
||||
config = config_clone = g_steal_pointer (&contents);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nm_utils_is_json_object (config, NULL)) {
|
||||
if (filename) {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||
_("'%s' does not contain a valid team configuration"), filename);
|
||||
} else {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||
_("team configuration must be a JSON object"));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_config = (config == config_clone)
|
||||
? g_steal_pointer (&config_clone)
|
||||
: g_strdup (config);
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL N_("Corresponds to the teamd mcast_rejoin.interval.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_NOTIFY_PEERS_COUNT N_("Corresponds to the teamd notify_peers.count.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL N_("Corresponds to the teamd notify_peers.interval.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER N_("Corresponds to the teamd runner.name. Permitted values are: \"roundrobin\", \"broadcast\", \"activebackup\", \"loadbalance\", \"lacp\", \"random\". When setting the runner, all the properties specific to the runner will be reset to the default value; all the properties specific to other runners will be set to an empty value (or if not possible to a default value).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER N_("Corresponds to the teamd runner.name. Permitted values are: \"roundrobin\", \"broadcast\", \"activebackup\", \"loadbalance\", \"lacp\", \"random\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_ACTIVE N_("Corresponds to the teamd runner.active.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY N_("Corresponds to the teamd runner.agg_select_policy.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_FAST_RATE N_("Corresponds to the teamd runner.fast_rate.")
|
||||
|
|
|
|||
|
|
@ -112,15 +112,16 @@ libnm_core_settings_sources = files(
|
|||
)
|
||||
|
||||
libnm_core_sources = libnm_core_settings_sources + files(
|
||||
'nm-crypto.c',
|
||||
'nm-connection.c',
|
||||
'nm-crypto.c',
|
||||
'nm-dbus-utils.c',
|
||||
'nm-errors.c',
|
||||
'nm-keyfile.c',
|
||||
'nm-keyfile-utils.c',
|
||||
'nm-keyfile.c',
|
||||
'nm-property-compare.c',
|
||||
'nm-setting.c',
|
||||
'nm-simple-connection.c',
|
||||
'nm-team-utils.c',
|
||||
'nm-utils.c',
|
||||
'nm-vpn-editor-plugin.c',
|
||||
'nm-vpn-plugin-info.c',
|
||||
|
|
|
|||
|
|
@ -534,20 +534,18 @@ gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean _nm_team_link_watchers_equal (GPtrArray *a, GPtrArray *b, gboolean ignore_order);
|
||||
NMTeamLinkWatcher *_nm_team_link_watcher_ref (NMTeamLinkWatcher *watcher);
|
||||
|
||||
gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, gboolean port);
|
||||
GValue *_nm_utils_team_config_get (const char *conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
gboolean port_config);
|
||||
int nm_team_link_watcher_cmp (const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other);
|
||||
|
||||
gboolean _nm_utils_team_config_set (char **conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
const GValue *value);
|
||||
int nm_team_link_watchers_cmp (const NMTeamLinkWatcher *const*a,
|
||||
const NMTeamLinkWatcher *const*b,
|
||||
gsize len,
|
||||
gboolean ignore_order);
|
||||
|
||||
gboolean nm_team_link_watchers_equal (const GPtrArray *a,
|
||||
const GPtrArray *b,
|
||||
gboolean ignore_order);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -1619,16 +1619,16 @@ team_config_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key
|
|||
gs_free_error GError *error = NULL;
|
||||
|
||||
conf = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL);
|
||||
|
||||
g_object_set (G_OBJECT (setting), key, conf, NULL);
|
||||
|
||||
if ( conf
|
||||
&& conf[0]
|
||||
&& !nm_utils_is_json_object (conf, &error)) {
|
||||
&& !nm_setting_verify (setting, NULL, &error)) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("ignoring invalid team configuration: %s"),
|
||||
error->message);
|
||||
g_clear_pointer (&conf, g_free);
|
||||
g_object_set (G_OBJECT (setting), key, NULL, NULL);
|
||||
}
|
||||
|
||||
g_object_set (G_OBJECT (setting), key, conf, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "nm-utils-private.h"
|
||||
#include "nm-connection-private.h"
|
||||
#include "nm-setting-connection.h"
|
||||
#include "nm-team-utils.h"
|
||||
|
||||
/**
|
||||
* SECTION:nm-setting-team-port
|
||||
|
|
@ -41,34 +42,10 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NMSettingTeamPort,
|
||||
PROP_CONFIG,
|
||||
PROP_QUEUE_ID,
|
||||
PROP_PRIO,
|
||||
PROP_STICKY,
|
||||
PROP_LACP_PRIO,
|
||||
PROP_LACP_KEY,
|
||||
PROP_LINK_WATCHERS,
|
||||
);
|
||||
|
||||
static const _NMUtilsTeamPropertyKeys _prop_to_keys[_PROPERTY_ENUMS_LAST] = {
|
||||
[PROP_CONFIG] = { },
|
||||
[PROP_QUEUE_ID] = { .key1 = "queue_id", .default_int = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT, },
|
||||
[PROP_PRIO] = { .key1 = "prio", },
|
||||
[PROP_STICKY] = { .key1 = "sticky", },
|
||||
[PROP_LACP_PRIO] = { .key1 = "lacp_prio", .default_int = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT, },
|
||||
[PROP_LACP_KEY] = { .key1 = "lacp_key", },
|
||||
[PROP_LINK_WATCHERS] = { .key1 = "link_watch", },
|
||||
};
|
||||
static GParamSpec *obj_properties[_NM_TEAM_ATTRIBUTE_PORT_NUM] = { NULL, };
|
||||
|
||||
typedef struct {
|
||||
char *config;
|
||||
int queue_id;
|
||||
int prio;
|
||||
gboolean sticky;
|
||||
int lacp_prio;
|
||||
int lacp_key;
|
||||
GPtrArray *link_watchers; /* Array of NMTeamLinkWatcher */
|
||||
NMTeamSetting *team_setting;
|
||||
} NMSettingTeamPortPrivate;
|
||||
|
||||
G_DEFINE_TYPE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING)
|
||||
|
|
@ -77,6 +54,17 @@ G_DEFINE_TYPE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _maybe_changed(self, changed) \
|
||||
nm_team_setting_maybe_changed (NM_SETTING (_NM_ENSURE_TYPE (NMSettingTeamPort *, self)), (const GParamSpec *const*) obj_properties, (changed))
|
||||
|
||||
#define _maybe_changed_with_assert(self, changed) \
|
||||
G_STMT_START { \
|
||||
if (!_maybe_changed ((self), (changed))) \
|
||||
nm_assert_not_reached (); \
|
||||
} G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_setting_team_port_get_config:
|
||||
* @setting: the #NMSettingTeamPort
|
||||
|
|
@ -88,7 +76,7 @@ nm_setting_team_port_get_config (NMSettingTeamPort *setting)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), NULL);
|
||||
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->config;
|
||||
return nm_team_setting_config_get (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,7 +92,7 @@ nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), -1);
|
||||
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->queue_id;
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting->d.port.queue_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -120,7 +108,7 @@ nm_setting_team_port_get_prio (NMSettingTeamPort *setting)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
|
||||
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->prio;
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting->d.port.prio;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,7 +124,7 @@ nm_setting_team_port_get_sticky (NMSettingTeamPort *setting)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), FALSE);
|
||||
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->sticky;
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting->d.port.sticky;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -152,7 +140,7 @@ nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
|
||||
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->lacp_prio;
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting->d.port.lacp_prio;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -168,7 +156,7 @@ nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
|
||||
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->lacp_key;
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting->d.port.lacp_key;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -182,11 +170,9 @@ nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting)
|
|||
guint
|
||||
nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
|
||||
|
||||
return priv->link_watchers->len;
|
||||
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting->d.link_watchers->len;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -201,12 +187,15 @@ nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting)
|
|||
NMTeamLinkWatcher *
|
||||
nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
NMSettingTeamPortPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), NULL);
|
||||
g_return_val_if_fail (idx < priv->link_watchers->len, NULL);
|
||||
|
||||
return priv->link_watchers->pdata[idx];
|
||||
priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
|
||||
g_return_val_if_fail (idx < priv->team_setting->d.link_watchers->len, NULL);
|
||||
|
||||
return priv->team_setting->d.link_watchers->pdata[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -225,20 +214,12 @@ gboolean
|
|||
nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting,
|
||||
NMTeamLinkWatcher *link_watcher)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), FALSE);
|
||||
g_return_val_if_fail (link_watcher != NULL, FALSE);
|
||||
|
||||
for (i = 0; i < priv->link_watchers->len; i++) {
|
||||
if (nm_team_link_watcher_equal (priv->link_watchers->pdata[i], link_watcher))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_ptr_array_add (priv->link_watchers, nm_team_link_watcher_dup (link_watcher));
|
||||
_notify (setting, PROP_LINK_WATCHERS);
|
||||
return TRUE;
|
||||
return _maybe_changed (setting,
|
||||
nm_team_setting_value_link_watchers_add (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting,
|
||||
link_watcher));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -253,13 +234,17 @@ nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting,
|
|||
void
|
||||
nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
NMSettingTeamPortPrivate *priv;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTING_TEAM_PORT (setting));
|
||||
g_return_if_fail (idx < priv->link_watchers->len);
|
||||
|
||||
g_ptr_array_remove_index (priv->link_watchers, idx);
|
||||
_notify (setting, PROP_LINK_WATCHERS);
|
||||
priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
|
||||
g_return_if_fail (idx < priv->team_setting->d.link_watchers->len);
|
||||
|
||||
_maybe_changed_with_assert (setting,
|
||||
nm_team_setting_value_link_watchers_remove (priv->team_setting,
|
||||
idx));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -277,19 +262,12 @@ gboolean
|
|||
nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting,
|
||||
NMTeamLinkWatcher *link_watcher)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), FALSE);
|
||||
g_return_val_if_fail (link_watcher, FALSE);
|
||||
|
||||
for (i = 0; i < priv->link_watchers->len; i++) {
|
||||
if (nm_team_link_watcher_equal (priv->link_watchers->pdata[i], link_watcher)) {
|
||||
g_ptr_array_remove_index (priv->link_watchers, i);
|
||||
_notify (setting, PROP_LINK_WATCHERS);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return _maybe_changed (setting,
|
||||
nm_team_setting_value_link_watchers_remove_by_value (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting,
|
||||
link_watcher));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -303,14 +281,12 @@ nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting,
|
|||
void
|
||||
nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
|
||||
g_return_if_fail (NM_IS_SETTING_TEAM_PORT (setting));
|
||||
|
||||
if (priv->link_watchers->len != 0) {
|
||||
g_ptr_array_set_size (priv->link_watchers, 0);
|
||||
_notify (setting, PROP_LINK_WATCHERS);
|
||||
}
|
||||
_maybe_changed (setting,
|
||||
nm_team_setting_value_link_watchers_set_list (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting,
|
||||
NULL,
|
||||
0));
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
|
|
@ -323,7 +299,7 @@ static void
|
|||
team_link_watchers_from_dbus (GVariant *dbus_value,
|
||||
GValue *prop_value)
|
||||
{
|
||||
g_value_take_boxed (prop_value, _nm_utils_team_link_watchers_from_variant (dbus_value));
|
||||
g_value_take_boxed (prop_value, _nm_utils_team_link_watchers_from_variant (dbus_value, FALSE, NULL));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -360,29 +336,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
if (priv->config) {
|
||||
if (strlen (priv->config) > 1*1024*1024) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("team config exceeds size limit"));
|
||||
g_prefix_error (error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_TEAM_PORT_SETTING_NAME,
|
||||
NM_SETTING_TEAM_PORT_CONFIG);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_utils_is_json_object (priv->config, error)) {
|
||||
g_prefix_error (error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_TEAM_PORT_SETTING_NAME,
|
||||
NM_SETTING_TEAM_PORT_CONFIG);
|
||||
/* We treat an empty string as no config for compatibility. */
|
||||
return *priv->config ? FALSE : NM_SETTING_VERIFY_NORMALIZABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: normalizable/normalizable-errors must appear at the end with decreasing severity.
|
||||
* Take care to properly order statements with priv->config above. */
|
||||
if (!nm_team_setting_verify (priv->team_setting, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -407,27 +362,26 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||
return TRUE;
|
||||
a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_a);
|
||||
b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_b);
|
||||
return _nm_team_link_watchers_equal (a_priv->link_watchers,
|
||||
b_priv->link_watchers,
|
||||
TRUE);
|
||||
return nm_team_link_watchers_equal (a_priv->team_setting->d.link_watchers,
|
||||
b_priv->team_setting->d.link_watchers,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_CONFIG)) {
|
||||
if (set_b) {
|
||||
a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_a);
|
||||
b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_b);
|
||||
|
||||
if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) {
|
||||
/* If we are trying to match a connection in order to assume it (and thus
|
||||
* @flags contains INFERRABLE), use the "relaxed" matching for team
|
||||
* configuration. Otherwise, for all other purposes (including connection
|
||||
* comparison before an update), resort to the default string comparison. */
|
||||
return _nm_utils_team_config_equal (a_priv->config,
|
||||
b_priv->config,
|
||||
TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return nm_streq0 (a_priv->config, b_priv->config);
|
||||
a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_a);
|
||||
b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (set_b);
|
||||
|
||||
return nm_streq0 (nm_team_setting_config_get (a_priv->team_setting),
|
||||
nm_team_setting_config_get (b_priv->team_setting));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -442,6 +396,37 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||
flags);
|
||||
}
|
||||
|
||||
static void
|
||||
duplicate_copy_properties (const NMSettInfoSetting *sett_info,
|
||||
NMSetting *src,
|
||||
NMSetting *dst)
|
||||
{
|
||||
_maybe_changed (NM_SETTING_TEAM_PORT (dst),
|
||||
nm_team_setting_reset (NM_SETTING_TEAM_PORT_GET_PRIVATE (dst)->team_setting,
|
||||
NM_SETTING_TEAM_PORT_GET_PRIVATE (src)->team_setting));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_from_dbus (NMSetting *setting,
|
||||
GHashTable *keys,
|
||||
GVariant *setting_dict,
|
||||
GVariant *connection_dict,
|
||||
guint /* NMSettingParseFlags */ parse_flags,
|
||||
GError **error)
|
||||
{
|
||||
guint32 changed = 0;
|
||||
gboolean success;
|
||||
|
||||
success = nm_team_setting_reset_from_dbus (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting,
|
||||
setting_dict,
|
||||
keys,
|
||||
&changed,
|
||||
parse_flags,
|
||||
error);
|
||||
_maybe_changed (NM_SETTING_TEAM_PORT (setting), changed);
|
||||
return success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -452,27 +437,26 @@ get_property (GObject *object, guint prop_id,
|
|||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONFIG:
|
||||
g_value_set_string (value, nm_setting_team_port_get_config (setting));
|
||||
case NM_TEAM_ATTRIBUTE_CONFIG:
|
||||
g_value_set_string (value,
|
||||
nm_team_setting_config_get (priv->team_setting));
|
||||
break;
|
||||
case PROP_QUEUE_ID:
|
||||
g_value_set_int (value, priv->queue_id);
|
||||
case NM_TEAM_ATTRIBUTE_PORT_STICKY:
|
||||
g_value_set_boolean (value,
|
||||
nm_team_setting_value_get_bool (priv->team_setting,
|
||||
prop_id));
|
||||
break;
|
||||
case PROP_PRIO:
|
||||
g_value_set_int (value, priv->prio);
|
||||
case NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID:
|
||||
case NM_TEAM_ATTRIBUTE_PORT_PRIO:
|
||||
case NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO:
|
||||
case NM_TEAM_ATTRIBUTE_PORT_LACP_KEY:
|
||||
g_value_set_int (value,
|
||||
nm_team_setting_value_get_int32 (priv->team_setting,
|
||||
prop_id));
|
||||
break;
|
||||
case PROP_STICKY:
|
||||
g_value_set_boolean (value, priv->sticky);
|
||||
break;
|
||||
case PROP_LACP_PRIO:
|
||||
g_value_set_int (value, priv->lacp_prio);
|
||||
break;
|
||||
case PROP_LACP_KEY:
|
||||
g_value_set_int (value, priv->lacp_key);
|
||||
break;
|
||||
case PROP_LINK_WATCHERS:
|
||||
g_value_take_boxed (value, _nm_utils_copy_array (priv->link_watchers,
|
||||
(NMUtilsCopyFunc) nm_team_link_watcher_dup,
|
||||
case NM_TEAM_ATTRIBUTE_LINK_WATCHERS:
|
||||
g_value_take_boxed (value, _nm_utils_copy_array (priv->team_setting->d.link_watchers,
|
||||
(NMUtilsCopyFunc) _nm_team_link_watcher_ref,
|
||||
(GDestroyNotify) nm_team_link_watcher_unref));
|
||||
break;
|
||||
default:
|
||||
|
|
@ -485,81 +469,40 @@ static void
|
|||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (object);
|
||||
const GValue *align_value = NULL;
|
||||
gboolean align_config = FALSE;
|
||||
|
||||
#define JSON_TO_VAL(typ, id) _nm_utils_json_extract_##typ (priv->config, _prop_to_keys[id], TRUE)
|
||||
NMSettingTeamPort *setting = NM_SETTING_TEAM_PORT (object);
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
guint32 changed;
|
||||
const GPtrArray *v_ptrarr;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONFIG:
|
||||
g_free (priv->config);
|
||||
priv->config = g_value_dup_string (value);
|
||||
priv->queue_id = JSON_TO_VAL (int, PROP_QUEUE_ID);
|
||||
priv->prio = JSON_TO_VAL (int, PROP_PRIO);
|
||||
priv->sticky = JSON_TO_VAL (boolean, PROP_STICKY);
|
||||
priv->lacp_prio = JSON_TO_VAL (int, PROP_LACP_PRIO);
|
||||
priv->lacp_key = JSON_TO_VAL (int, PROP_LACP_KEY);
|
||||
|
||||
g_ptr_array_unref (priv->link_watchers);
|
||||
priv->link_watchers = JSON_TO_VAL (ptr_array, PROP_LINK_WATCHERS);
|
||||
case NM_TEAM_ATTRIBUTE_CONFIG:
|
||||
changed = nm_team_setting_config_set (priv->team_setting, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_QUEUE_ID:
|
||||
if (priv->queue_id == g_value_get_int (value))
|
||||
break;
|
||||
priv->queue_id = g_value_get_int (value);
|
||||
if (priv->queue_id != NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT)
|
||||
align_value = value;
|
||||
align_config = TRUE;
|
||||
case NM_TEAM_ATTRIBUTE_PORT_STICKY:
|
||||
changed = nm_team_setting_value_set_bool (priv->team_setting,
|
||||
prop_id,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_PRIO:
|
||||
if (priv->prio == g_value_get_int (value))
|
||||
break;
|
||||
priv->prio = g_value_get_int (value);
|
||||
if (priv->prio)
|
||||
align_value = value;
|
||||
align_config = TRUE;
|
||||
case NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID:
|
||||
case NM_TEAM_ATTRIBUTE_PORT_PRIO:
|
||||
case NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO:
|
||||
case NM_TEAM_ATTRIBUTE_PORT_LACP_KEY:
|
||||
changed = nm_team_setting_value_set_int32 (priv->team_setting,
|
||||
prop_id,
|
||||
g_value_get_int (value));
|
||||
break;
|
||||
case PROP_STICKY:
|
||||
if (priv->sticky == g_value_get_boolean (value))
|
||||
break;
|
||||
priv->sticky = g_value_get_boolean (value);
|
||||
if (priv->sticky)
|
||||
align_value = value;
|
||||
align_config = TRUE;
|
||||
break;
|
||||
case PROP_LACP_PRIO:
|
||||
if (priv->lacp_prio == g_value_get_int (value))
|
||||
break;
|
||||
priv->lacp_prio = g_value_get_int (value);
|
||||
/* from libteam sources: lacp_prio default value is 0xff */
|
||||
if (priv->lacp_prio != NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT)
|
||||
align_value = value;
|
||||
align_config = TRUE;
|
||||
break;
|
||||
case PROP_LACP_KEY:
|
||||
if (priv->lacp_key == g_value_get_int (value))
|
||||
break;
|
||||
priv->lacp_key = g_value_get_int (value);
|
||||
if (priv->lacp_key)
|
||||
align_value = value;
|
||||
align_config = TRUE;
|
||||
break;
|
||||
case PROP_LINK_WATCHERS:
|
||||
g_ptr_array_unref (priv->link_watchers);
|
||||
priv->link_watchers = _nm_utils_copy_array (g_value_get_boxed (value),
|
||||
(NMUtilsCopyFunc) nm_team_link_watcher_dup,
|
||||
(GDestroyNotify) nm_team_link_watcher_unref);
|
||||
if (priv->link_watchers->len)
|
||||
align_value = value;
|
||||
align_config = TRUE;
|
||||
case NM_TEAM_ATTRIBUTE_LINK_WATCHERS:
|
||||
v_ptrarr = g_value_get_boxed (value);
|
||||
changed = nm_team_setting_value_link_watchers_set_list (priv->team_setting,
|
||||
v_ptrarr ? (const NMTeamLinkWatcher *const*) v_ptrarr->pdata : NULL,
|
||||
v_ptrarr ? v_ptrarr->len : 0u);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
if (align_config)
|
||||
_nm_utils_json_append_gvalue (&priv->config, _prop_to_keys[prop_id], align_value);
|
||||
|
||||
_maybe_changed (setting, changed & ~(((guint32) 1) << prop_id));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -569,9 +512,7 @@ nm_setting_team_port_init (NMSettingTeamPort *setting)
|
|||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
|
||||
|
||||
priv->queue_id = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT;
|
||||
priv->lacp_prio = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT;
|
||||
priv->link_watchers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref);
|
||||
priv->team_setting = nm_team_setting_new (TRUE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -592,8 +533,7 @@ finalize (GObject *object)
|
|||
{
|
||||
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (object);
|
||||
|
||||
g_free (priv->config);
|
||||
g_ptr_array_unref (priv->link_watchers);
|
||||
nm_team_setting_free (priv->team_setting);
|
||||
|
||||
G_OBJECT_CLASS (nm_setting_team_port_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
@ -611,8 +551,10 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
object_class->set_property = set_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->verify = verify;
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->verify = verify;
|
||||
setting_class->duplicate_copy_properties = duplicate_copy_properties;
|
||||
setting_class->init_from_dbus = init_from_dbus;
|
||||
|
||||
/**
|
||||
* NMSettingTeamPort:config:
|
||||
|
|
@ -628,7 +570,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
* description: Team port configuration in JSON. See man teamd.conf for details.
|
||||
* ---end---
|
||||
*/
|
||||
obj_properties[PROP_CONFIG] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_CONFIG] =
|
||||
g_param_spec_string (NM_SETTING_TEAM_PORT_CONFIG, "", "",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
|
|
@ -643,7 +585,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
obj_properties[PROP_QUEUE_ID] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID] =
|
||||
g_param_spec_int (NM_SETTING_TEAM_PORT_QUEUE_ID, "", "",
|
||||
G_MININT32, G_MAXINT32, 0,
|
||||
G_PARAM_READWRITE |
|
||||
|
|
@ -656,7 +598,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
obj_properties[PROP_PRIO] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_PORT_PRIO] =
|
||||
g_param_spec_int (NM_SETTING_TEAM_PORT_PRIO, "", "",
|
||||
G_MININT32, G_MAXINT32, 0,
|
||||
G_PARAM_READWRITE |
|
||||
|
|
@ -669,7 +611,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
obj_properties[PROP_STICKY] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_PORT_STICKY] =
|
||||
g_param_spec_boolean (NM_SETTING_TEAM_PORT_STICKY, "", "",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
|
|
@ -682,7 +624,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
obj_properties[PROP_LACP_PRIO] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO] =
|
||||
g_param_spec_int (NM_SETTING_TEAM_PORT_LACP_PRIO, "", "",
|
||||
G_MININT32, G_MAXINT32, 0,
|
||||
G_PARAM_READWRITE |
|
||||
|
|
@ -695,7 +637,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
obj_properties[PROP_LACP_KEY] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY] =
|
||||
g_param_spec_int (NM_SETTING_TEAM_PORT_LACP_KEY, "", "",
|
||||
G_MININT32, G_MAXINT32, 0,
|
||||
G_PARAM_READWRITE |
|
||||
|
|
@ -715,19 +657,19 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
|
|||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
obj_properties[PROP_LINK_WATCHERS] =
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS] =
|
||||
g_param_spec_boxed (NM_SETTING_TEAM_PORT_LINK_WATCHERS, "", "",
|
||||
G_TYPE_PTR_ARRAY,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
_properties_override_add_transform (properties_override,
|
||||
obj_properties[PROP_LINK_WATCHERS],
|
||||
obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS],
|
||||
G_VARIANT_TYPE ("aa{sv}"),
|
||||
team_link_watchers_to_dbus,
|
||||
team_link_watchers_from_dbus);
|
||||
|
||||
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_properties), obj_properties);
|
||||
|
||||
_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM_PORT,
|
||||
NULL, properties_override);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -88,29 +88,30 @@ void nm_team_link_watcher_ref (NMTeamLinkWatcher *watcher);
|
|||
NM_AVAILABLE_IN_1_12
|
||||
void nm_team_link_watcher_unref (NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
gboolean nm_team_link_watcher_equal (NMTeamLinkWatcher *watcher, NMTeamLinkWatcher *other);
|
||||
gboolean nm_team_link_watcher_equal (const NMTeamLinkWatcher *watcher,
|
||||
const NMTeamLinkWatcher *other);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
NMTeamLinkWatcher *nm_team_link_watcher_dup (NMTeamLinkWatcher *watcher);
|
||||
NMTeamLinkWatcher *nm_team_link_watcher_dup (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
const char *nm_team_link_watcher_get_name (NMTeamLinkWatcher *watcher);
|
||||
const char *nm_team_link_watcher_get_name (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
int nm_team_link_watcher_get_delay_up (NMTeamLinkWatcher *watcher);
|
||||
int nm_team_link_watcher_get_delay_up (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
int nm_team_link_watcher_get_delay_down (NMTeamLinkWatcher *watcher);
|
||||
int nm_team_link_watcher_get_delay_down (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
int nm_team_link_watcher_get_init_wait (NMTeamLinkWatcher *watcher);
|
||||
int nm_team_link_watcher_get_init_wait (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
int nm_team_link_watcher_get_interval (NMTeamLinkWatcher *watcher);
|
||||
int nm_team_link_watcher_get_interval (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
int nm_team_link_watcher_get_missed_max (NMTeamLinkWatcher *watcher);
|
||||
int nm_team_link_watcher_get_missed_max (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
const char *nm_team_link_watcher_get_target_host (NMTeamLinkWatcher *watcher);
|
||||
const char *nm_team_link_watcher_get_target_host (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
const char *nm_team_link_watcher_get_source_host (NMTeamLinkWatcher *watcher);
|
||||
const char *nm_team_link_watcher_get_source_host (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_12
|
||||
NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher);
|
||||
NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (const NMTeamLinkWatcher *watcher);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
int nm_team_link_watcher_get_vlanid (NMTeamLinkWatcher *watcher);
|
||||
int nm_team_link_watcher_get_vlanid (const NMTeamLinkWatcher *watcher);
|
||||
|
||||
#define NM_TYPE_SETTING_TEAM (nm_setting_team_get_type ())
|
||||
#define NM_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam))
|
||||
|
|
|
|||
|
|
@ -863,10 +863,9 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
NMSettingParseFlags parse_flags,
|
||||
GError **error)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *keys_keep_variant = NULL;
|
||||
gs_unref_object NMSetting *setting = NULL;
|
||||
gs_unref_hashtable GHashTable *keys = NULL;
|
||||
const NMSettInfoSetting *sett_info;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
|
||||
g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL);
|
||||
|
|
@ -890,18 +889,19 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) {
|
||||
GVariantIter iter;
|
||||
GVariant *entry, *entry_key;
|
||||
char *key;
|
||||
const char *key;
|
||||
|
||||
keys = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
|
||||
keys_keep_variant = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_unref);
|
||||
keys = g_hash_table_new (nm_str_hash, g_str_equal);
|
||||
|
||||
g_variant_iter_init (&iter, setting_dict);
|
||||
while ((entry = g_variant_iter_next_value (&iter))) {
|
||||
entry_key = g_variant_get_child_value (entry, 0);
|
||||
key = g_strdup (g_variant_get_string (entry_key, NULL));
|
||||
g_variant_unref (entry_key);
|
||||
g_ptr_array_add (keys_keep_variant, entry_key);
|
||||
g_variant_unref (entry);
|
||||
|
||||
if (!g_hash_table_add (keys, key)) {
|
||||
key = g_variant_get_string (entry_key, NULL);
|
||||
if (!g_hash_table_add (keys, (char *) key)) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING,
|
||||
_("duplicate property"));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
|
||||
|
|
@ -910,6 +910,47 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
}
|
||||
}
|
||||
|
||||
if (!NM_SETTING_GET_CLASS (setting)->init_from_dbus (setting,
|
||||
keys,
|
||||
setting_dict,
|
||||
connection_dict,
|
||||
parse_flags,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
if ( NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)
|
||||
&& g_hash_table_size (keys) > 0) {
|
||||
GHashTableIter iter;
|
||||
const char *key;
|
||||
|
||||
g_hash_table_iter_init (&iter, keys);
|
||||
if (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("unknown property"));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer (&setting);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_from_dbus (NMSetting *setting,
|
||||
GHashTable *keys,
|
||||
GVariant *setting_dict,
|
||||
GVariant *connection_dict,
|
||||
guint /* NMSettingParseFlags */ parse_flags,
|
||||
GError **error)
|
||||
{
|
||||
const NMSettInfoSetting *sett_info;
|
||||
|
||||
guint i;
|
||||
|
||||
nm_assert (NM_IS_SETTING (setting));
|
||||
nm_assert (!NM_FLAGS_ANY (parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL));
|
||||
nm_assert (!NM_FLAGS_ALL (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT));
|
||||
|
||||
sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting));
|
||||
|
||||
if (sett_info->detail.gendata_info) {
|
||||
|
|
@ -925,10 +966,12 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
g_hash_table_insert (hash,
|
||||
key,
|
||||
val);
|
||||
if (keys)
|
||||
g_hash_table_remove (keys, key);
|
||||
}
|
||||
|
||||
_nm_setting_gendata_notify (setting, TRUE);
|
||||
return g_steal_pointer (&setting);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
|
|
@ -942,7 +985,8 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
|
||||
value = g_variant_lookup_value (setting_dict, property_info->name, NULL);
|
||||
|
||||
if (value && keys)
|
||||
if ( value
|
||||
&& keys)
|
||||
g_hash_table_remove (keys, property_info->name);
|
||||
|
||||
if ( value
|
||||
|
|
@ -960,7 +1004,7 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
g_type_name (property_info->param_spec->value_type) : "(unknown)",
|
||||
g_variant_get_type_string (value));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!property_info->from_dbus_fcn (setting,
|
||||
|
|
@ -975,7 +1019,7 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
_("failed to set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
} else if ( !value
|
||||
&& property_info->missing_from_dbus_fcn) {
|
||||
|
|
@ -990,7 +1034,7 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
_("failed to set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
} else if ( value
|
||||
&& property_info->param_spec) {
|
||||
|
|
@ -1010,7 +1054,7 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
: "(unknown)"),
|
||||
g_variant_get_type_string (value));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_g_object_set_property (G_OBJECT (setting), property_info->param_spec->name, &object_value, &local)) {
|
||||
|
|
@ -1020,26 +1064,12 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
_("can not set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)
|
||||
&& g_hash_table_size (keys) > 0) {
|
||||
GHashTableIter iter;
|
||||
const char *key;
|
||||
|
||||
g_hash_table_iter_init (&iter, keys);
|
||||
if (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("unknown property"));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer (&setting);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2694,6 +2724,7 @@ nm_setting_class_init (NMSettingClass *setting_class)
|
|||
setting_class->duplicate_copy_properties = duplicate_copy_properties;
|
||||
setting_class->enumerate_values = enumerate_values;
|
||||
setting_class->aggregate = aggregate;
|
||||
setting_class->init_from_dbus = init_from_dbus;
|
||||
|
||||
/**
|
||||
* NMSetting:name:
|
||||
|
|
|
|||
|
|
@ -268,7 +268,15 @@ typedef struct {
|
|||
GVariantBuilder *setting_builder);
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[2];
|
||||
gboolean (*init_from_dbus) (NMSetting *setting,
|
||||
GHashTable *keys,
|
||||
GVariant *setting_dict,
|
||||
GVariant *connection_dict,
|
||||
guint /* NMSettingParseFlags */ parse_flags,
|
||||
GError **error);
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[1];
|
||||
|
||||
/*< private >*/
|
||||
const struct _NMMetaSettingInfo *setting_info;
|
||||
|
|
|
|||
2323
libnm-core/nm-team-utils.c
Normal file
2323
libnm-core/nm-team-utils.c
Normal file
File diff suppressed because it is too large
Load diff
280
libnm-core/nm-team-utils.h
Normal file
280
libnm-core/nm-team-utils.h
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_TEAM_UITLS_H__
|
||||
#define __NM_TEAM_UITLS_H__
|
||||
|
||||
#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE)
|
||||
#error Cannot use this header.
|
||||
#endif
|
||||
|
||||
#include "nm-glib-aux/nm-value-type.h"
|
||||
|
||||
struct _NMSetting;
|
||||
|
||||
struct NMTeamLinkWatcher;
|
||||
|
||||
typedef enum {
|
||||
|
||||
_NM_TEAM_ATTRIBUTE_0 = 0,
|
||||
NM_TEAM_ATTRIBUTE_CONFIG = 1,
|
||||
NM_TEAM_ATTRIBUTE_LINK_WATCHERS = 2,
|
||||
|
||||
_NM_TEAM_ATTRIBUTE_START = 3,
|
||||
|
||||
NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT = _NM_TEAM_ATTRIBUTE_START,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS,
|
||||
NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY,
|
||||
_NM_TEAM_ATTRIBUTE_MASTER_NUM,
|
||||
|
||||
NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID = _NM_TEAM_ATTRIBUTE_START,
|
||||
NM_TEAM_ATTRIBUTE_PORT_PRIO,
|
||||
NM_TEAM_ATTRIBUTE_PORT_STICKY,
|
||||
NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO,
|
||||
NM_TEAM_ATTRIBUTE_PORT_LACP_KEY,
|
||||
_NM_TEAM_ATTRIBUTE_PORT_NUM,
|
||||
|
||||
_NM_TEAM_ATTRIBUTE_NUM = NM_CONST_MAX (_NM_TEAM_ATTRIBUTE_MASTER_NUM, _NM_TEAM_ATTRIBUTE_PORT_NUM),
|
||||
|
||||
} NMTeamAttribute;
|
||||
|
||||
static inline guint32
|
||||
nm_team_attribute_to_flags (NMTeamAttribute team_attr)
|
||||
{
|
||||
nm_assert (_NM_INT_NOT_NEGATIVE (team_attr));
|
||||
nm_assert (team_attr < _NM_TEAM_ATTRIBUTE_NUM);
|
||||
G_STATIC_ASSERT_EXPR (_NM_TEAM_ATTRIBUTE_NUM < 32);
|
||||
|
||||
return ((guint32) 1) << team_attr;
|
||||
}
|
||||
|
||||
struct _NMTeamSettingData {
|
||||
|
||||
const char *_js_str;
|
||||
|
||||
const GPtrArray *link_watchers;
|
||||
|
||||
/* this means that @_js_str is unset and needs to be created by
|
||||
* converting the properties to JSON. This flag indicates that
|
||||
* we need to re-generate the JSON string on-demand (lazily). */
|
||||
bool _js_str_need_synthetize;
|
||||
|
||||
bool strict_validated:1;
|
||||
|
||||
/* indicates tha the JSON is invalid. Usually, we do a very relaxed validation of
|
||||
* the JSON config, in case !@strict_validated and accept all unknown fields. This
|
||||
* flag indicates that the JSON value is not even parsable as JSON. nm_connection_verify()
|
||||
* would reject such a setting. */
|
||||
bool js_str_invalid:1;
|
||||
|
||||
bool is_port:1;
|
||||
|
||||
union {
|
||||
struct {
|
||||
const GPtrArray *runner_tx_hash;
|
||||
const char *runner;
|
||||
const char *runner_hwaddr_policy;
|
||||
const char *runner_tx_balancer;
|
||||
const char *runner_agg_select_policy;
|
||||
gint32 notify_peers_count;
|
||||
gint32 notify_peers_interval;
|
||||
gint32 mcast_rejoin_count;
|
||||
gint32 mcast_rejoin_interval;
|
||||
gint32 runner_sys_prio;
|
||||
gint32 runner_min_ports;
|
||||
gint32 runner_tx_balancer_interval;
|
||||
bool runner_active;
|
||||
bool runner_fast_rate;
|
||||
} master;
|
||||
struct {
|
||||
gint32 queue_id;
|
||||
gint32 prio;
|
||||
gint32 lacp_prio;
|
||||
gint32 lacp_key;
|
||||
bool sticky;
|
||||
} port;
|
||||
};
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
const struct _NMTeamSettingData d;
|
||||
|
||||
struct _NMTeamSettingData _data_priv;
|
||||
};
|
||||
} NMTeamSetting;
|
||||
|
||||
NMTeamSetting *nm_team_setting_new (gboolean is_port,
|
||||
const char *js_str);
|
||||
|
||||
void nm_team_setting_free (NMTeamSetting *self);
|
||||
|
||||
NM_AUTO_DEFINE_FCN0 (NMTeamSetting *, _nm_auto_free_team_setting, nm_team_setting_free)
|
||||
#define nm_auto_free_team_setting nm_auto (_nm_auto_free_team_setting)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *nm_team_setting_config_get (const NMTeamSetting *self);
|
||||
|
||||
guint32 nm_team_setting_config_set (NMTeamSetting *self, const char *js_str);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gconstpointer _nm_team_setting_value_get (const NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr,
|
||||
NMValueType value_type);
|
||||
|
||||
static inline gboolean
|
||||
nm_team_setting_value_get_bool (const NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr)
|
||||
{
|
||||
const bool *p;
|
||||
|
||||
p = _nm_team_setting_value_get (self, team_attr, NM_VALUE_TYPE_BOOL);
|
||||
return p ? *p : 0;
|
||||
}
|
||||
|
||||
static inline gint32
|
||||
nm_team_setting_value_get_int32 (const NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr)
|
||||
{
|
||||
const gint32 *p;
|
||||
|
||||
p = _nm_team_setting_value_get (self, team_attr, NM_VALUE_TYPE_INT32);
|
||||
return p ? *p : 0;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nm_team_setting_value_get_string (const NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr)
|
||||
{
|
||||
const char *const*p;
|
||||
|
||||
p = _nm_team_setting_value_get (self, team_attr, NM_VALUE_TYPE_STRING);
|
||||
return p ? *p : NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
guint32 _nm_team_setting_value_set (NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr,
|
||||
NMValueType value_type,
|
||||
gconstpointer val);
|
||||
|
||||
static inline guint32
|
||||
nm_team_setting_value_set_bool (NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr,
|
||||
gboolean val)
|
||||
{
|
||||
const bool bool_val = val;
|
||||
|
||||
return _nm_team_setting_value_set (self, team_attr, NM_VALUE_TYPE_BOOL, &bool_val);
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
nm_team_setting_value_set_int32 (NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr,
|
||||
gint32 val)
|
||||
{
|
||||
return _nm_team_setting_value_set (self, team_attr, NM_VALUE_TYPE_INT32, &val);
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
nm_team_setting_value_set_string (NMTeamSetting *self,
|
||||
NMTeamAttribute team_attr,
|
||||
const char *arg)
|
||||
{
|
||||
return _nm_team_setting_value_set (self, team_attr, NM_VALUE_TYPE_STRING, &arg);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
guint32 nm_team_setting_value_link_watchers_add (NMTeamSetting *self,
|
||||
const struct NMTeamLinkWatcher *link_watcher);
|
||||
|
||||
guint32 nm_team_setting_value_link_watchers_remove (NMTeamSetting *self,
|
||||
guint idx);
|
||||
|
||||
guint32 nm_team_setting_value_link_watchers_remove_by_value (NMTeamSetting *self,
|
||||
const struct NMTeamLinkWatcher *link_watcher);
|
||||
|
||||
guint32 nm_team_setting_value_link_watchers_set_list (NMTeamSetting *self,
|
||||
const struct NMTeamLinkWatcher *const*arr,
|
||||
guint len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
guint32 nm_team_setting_value_master_runner_tx_hash_add (NMTeamSetting *self,
|
||||
const char *txhash);
|
||||
|
||||
guint32 nm_team_setting_value_master_runner_tx_hash_remove (NMTeamSetting *self,
|
||||
guint idx);
|
||||
|
||||
guint32 nm_team_setting_value_master_runner_tx_hash_set_list (NMTeamSetting *self,
|
||||
const char *const*arr,
|
||||
guint len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_team_setting_verify (const NMTeamSetting *self,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int nm_team_setting_cmp (const NMTeamSetting *self_a,
|
||||
const NMTeamSetting *self_b,
|
||||
gboolean ignore_js_str);
|
||||
|
||||
guint32 nm_team_setting_reset (NMTeamSetting *self,
|
||||
const NMTeamSetting *src);
|
||||
|
||||
gboolean nm_team_setting_reset_from_dbus (NMTeamSetting *self,
|
||||
GVariant *setting_dict,
|
||||
GHashTable *keys,
|
||||
guint32 *out_changed,
|
||||
guint /* NMSettingParseFlags */ parse_flags,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GPtrArray *_nm_utils_team_link_watchers_from_variant (GVariant *value,
|
||||
gboolean strict_parsing,
|
||||
GError **error);
|
||||
GVariant *_nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_team_setting_maybe_changed (struct _NMSetting *source,
|
||||
const GParamSpec *const*obj_properties,
|
||||
guint32 changed);
|
||||
|
||||
#endif /* __NM_TEAM_UITLS_H__ */
|
||||
|
|
@ -103,9 +103,6 @@ void _nm_utils_bytes_from_dbus (GVariant *dbus_value,
|
|||
|
||||
char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length);
|
||||
|
||||
GPtrArray * _nm_utils_team_link_watchers_from_variant (GVariant *value);
|
||||
GVariant * _nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers);
|
||||
|
||||
void _nm_utils_format_variant_attributes_full (GString *str,
|
||||
const NMUtilsNamedValue *values,
|
||||
guint num_values,
|
||||
|
|
@ -131,116 +128,4 @@ gboolean _nm_utils_bridge_vlan_verify_list (GPtrArray *vlans,
|
|||
const char *setting,
|
||||
const char *property);
|
||||
|
||||
/* JSON to GValue conversion macros */
|
||||
|
||||
static inline void
|
||||
_nm_auto_unset_and_free_gvalue (GValue **ptr)
|
||||
{
|
||||
if (*ptr) {
|
||||
g_value_unset (*ptr);
|
||||
g_free (*ptr);
|
||||
}
|
||||
}
|
||||
#define nm_auto_unset_and_free_gvalue nm_auto(_nm_auto_unset_and_free_gvalue)
|
||||
|
||||
typedef struct {
|
||||
const char *key1;
|
||||
const char *key2;
|
||||
const char *key3;
|
||||
union {
|
||||
int default_int;
|
||||
gboolean default_bool;
|
||||
const char *default_str;
|
||||
};
|
||||
} _NMUtilsTeamPropertyKeys;
|
||||
|
||||
static inline int
|
||||
_nm_utils_json_extract_int (char *conf,
|
||||
_NMUtilsTeamPropertyKeys key,
|
||||
gboolean is_port)
|
||||
{
|
||||
nm_auto_unset_and_free_gvalue GValue *t_value = NULL;
|
||||
|
||||
t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
|
||||
if ( !t_value
|
||||
|| !G_VALUE_HOLDS_INT (t_value))
|
||||
return key.default_int;
|
||||
return g_value_get_int (t_value);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
_nm_utils_json_extract_boolean (char *conf,
|
||||
_NMUtilsTeamPropertyKeys key,
|
||||
gboolean is_port)
|
||||
{
|
||||
nm_auto_unset_and_free_gvalue GValue *t_value = NULL;
|
||||
|
||||
t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
|
||||
if ( !t_value
|
||||
|| !G_VALUE_HOLDS_BOOLEAN (t_value))
|
||||
return key.default_bool;
|
||||
return g_value_get_boolean (t_value);
|
||||
}
|
||||
|
||||
static inline char *
|
||||
_nm_utils_json_extract_string (char *conf,
|
||||
_NMUtilsTeamPropertyKeys key,
|
||||
gboolean is_port)
|
||||
{
|
||||
nm_auto_unset_and_free_gvalue GValue *t_value = NULL;
|
||||
|
||||
t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
|
||||
if ( !t_value
|
||||
|| !G_VALUE_HOLDS_STRING (t_value))
|
||||
return g_strdup (key.default_str);
|
||||
return g_value_dup_string (t_value);
|
||||
}
|
||||
|
||||
static inline char **
|
||||
_nm_utils_json_extract_strv (char *conf,
|
||||
_NMUtilsTeamPropertyKeys key,
|
||||
gboolean is_port)
|
||||
{
|
||||
nm_auto_unset_and_free_gvalue GValue *t_value = NULL;
|
||||
|
||||
t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
|
||||
if ( !t_value
|
||||
|| !G_TYPE_CHECK_VALUE_TYPE (t_value, G_TYPE_STRV))
|
||||
return NULL;
|
||||
return g_strdupv (g_value_get_boxed (t_value))
|
||||
?: g_new0 (char *, 1);
|
||||
}
|
||||
|
||||
static inline GPtrArray *
|
||||
_nm_utils_json_extract_ptr_array (char *conf,
|
||||
_NMUtilsTeamPropertyKeys key,
|
||||
gboolean is_port)
|
||||
{
|
||||
nm_auto_unset_and_free_gvalue GValue *t_value = NULL;
|
||||
GPtrArray *data, *ret;
|
||||
guint i;
|
||||
|
||||
ret = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref);
|
||||
|
||||
t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
|
||||
if ( !t_value
|
||||
|| !G_TYPE_CHECK_VALUE_TYPE (t_value, G_TYPE_PTR_ARRAY))
|
||||
return ret;
|
||||
|
||||
data = g_value_get_boxed (t_value);
|
||||
if (!data)
|
||||
return ret;
|
||||
for (i = 0; i < data->len; i++)
|
||||
g_ptr_array_add (ret, nm_team_link_watcher_dup (data->pdata[i]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_nm_utils_json_append_gvalue (char **conf,
|
||||
_NMUtilsTeamPropertyKeys key,
|
||||
const GValue *val)
|
||||
{
|
||||
_nm_utils_team_config_set (conf, key.key1, key.key2, key.key3, val);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5378,429 +5378,6 @@ _nm_utils_is_json_object_no_validation (const char *str, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#if WITH_JSON_VALIDATION
|
||||
|
||||
static void
|
||||
_json_add_object (json_t *json,
|
||||
const char *key1,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
json_t *value)
|
||||
{
|
||||
json_t *json_element, *json_link;
|
||||
|
||||
json_element = json_object_get (json, key1);
|
||||
if (!json_element) {
|
||||
json_element = value;
|
||||
if (key2) {
|
||||
if (key3) {
|
||||
json_element = json_object ();
|
||||
json_object_set_new (json_element, key3, value);
|
||||
}
|
||||
json_link = json_object ();
|
||||
json_object_set_new (json_link, key2, json_element);
|
||||
json_element = json_link;
|
||||
}
|
||||
json_object_set_new (json, key1, json_element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key2)
|
||||
goto key_already_there;
|
||||
|
||||
json_link = json_element;
|
||||
json_element = json_object_get (json_element, key2);
|
||||
if (!json_element) {
|
||||
json_element = value;
|
||||
if (key3) {
|
||||
json_element = json_object ();
|
||||
json_object_set_new (json_element, key3, value);
|
||||
}
|
||||
json_object_set_new (json_link, key2, json_element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key3)
|
||||
goto key_already_there;
|
||||
|
||||
json_link = json_element;
|
||||
json_element = json_object_get (json_element, key3);
|
||||
if (!json_element) {
|
||||
json_object_set_new (json_link, key3, value);
|
||||
return;
|
||||
}
|
||||
|
||||
key_already_there:
|
||||
json_decref (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the specified key1[.key2.key3] from json.
|
||||
* Returns TRUE if json has been modified, FALSE otherwise. */
|
||||
static gboolean
|
||||
_json_del_object (json_t *json,
|
||||
const char *key1,
|
||||
const char *key2,
|
||||
const char *key3)
|
||||
{
|
||||
json_t *json_element = json;
|
||||
json_t *json_link = NULL;
|
||||
const char *iter_key = key1;
|
||||
|
||||
if (key2) {
|
||||
json_link = json;
|
||||
json_element = json_object_get (json, key1);
|
||||
if (!json_element)
|
||||
return FALSE;
|
||||
iter_key = key2;
|
||||
}
|
||||
if (key3) {
|
||||
json_link = json_element;
|
||||
json_element = json_object_get (json_element, key2);
|
||||
if (!json_element)
|
||||
return FALSE;
|
||||
iter_key = key3;
|
||||
}
|
||||
|
||||
if (json_object_del (json_element, iter_key) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* 1st level key only */
|
||||
if (!json_link)
|
||||
return TRUE;
|
||||
|
||||
if (json_object_size (json_element) == 0)
|
||||
json_object_del (json_link, (key3 ? key2 : key1));
|
||||
|
||||
if (key3 && json_object_size (json_link) == 0)
|
||||
json_object_del (json, key1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Adds in place to json the defaults for missing properties;
|
||||
* the "add_implicit" allows to add to the json also the default
|
||||
* values used but not shown with teamdctl */
|
||||
static void
|
||||
_json_team_add_defaults (json_t *json,
|
||||
gboolean port_config,
|
||||
gboolean add_implicit)
|
||||
{
|
||||
json_t *json_element;
|
||||
const char *runner = NULL;
|
||||
|
||||
if (port_config) {
|
||||
_json_add_object (json, "link_watch", "name", NULL,
|
||||
json_string (NM_TEAM_LINK_WATCHER_ETHTOOL));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Retrieve runner or add default one */
|
||||
json_element = json_object_get (json, "runner");
|
||||
if (json_element) {
|
||||
runner = json_string_value (json_object_get (json_element, "name"));
|
||||
} else {
|
||||
json_element = json_object ();
|
||||
json_object_set_new (json, "runner", json_element);
|
||||
}
|
||||
if (!runner) {
|
||||
runner = NM_SETTING_TEAM_RUNNER_DEFAULT;
|
||||
json_object_set_new (json_element, "name", json_string (runner));
|
||||
}
|
||||
|
||||
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) {
|
||||
_json_add_object (json, "notify_peers", "count", NULL,
|
||||
json_integer (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT));
|
||||
_json_add_object (json, "mcast_rejoin", "count", NULL,
|
||||
json_integer (NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT));
|
||||
} else if ( nm_streq (runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE)
|
||||
|| nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) {
|
||||
json_element = json_array ();
|
||||
json_array_append_new (json_element, json_string ("eth"));
|
||||
json_array_append_new (json_element, json_string ("ipv4"));
|
||||
json_array_append_new (json_element, json_string ("ipv6"));
|
||||
_json_add_object (json, "runner", "tx_hash", NULL, json_element);
|
||||
}
|
||||
|
||||
if (!add_implicit)
|
||||
return;
|
||||
|
||||
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP))
|
||||
_json_add_object (json, "runner", "hwaddr_policy", NULL, json_string ("same_all"));
|
||||
else if (NM_IN_STRSET (runner,
|
||||
NM_SETTING_TEAM_RUNNER_LOADBALANCE,
|
||||
NM_SETTING_TEAM_RUNNER_LACP)) {
|
||||
_json_add_object (json, "runner", "tx_balancer", "balancing_interval",
|
||||
json_integer (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT));
|
||||
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) {
|
||||
_json_add_object (json, "runner", "active", NULL, json_boolean (TRUE));
|
||||
_json_add_object (json, "runner", "sys_prio", NULL,
|
||||
json_integer (NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT));
|
||||
_json_add_object (json, "runner", "min_ports", NULL, json_integer (0));
|
||||
_json_add_object (json, "runner", "agg_select_policy", NULL,
|
||||
json_string (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static json_t *
|
||||
_json_find_object (json_t *json,
|
||||
const char *key1,
|
||||
const char *key2,
|
||||
const char *key3)
|
||||
{
|
||||
json_t *json_element;
|
||||
|
||||
if (!key1)
|
||||
return NULL;
|
||||
json_element = json_object_get (json, key1);
|
||||
if (!key2 || !json_element)
|
||||
return json_element;
|
||||
|
||||
json_element = json_object_get (json_element, key2);
|
||||
if (!key3 || !json_element)
|
||||
return json_element;
|
||||
|
||||
json_element = json_object_get (json_element, key3);
|
||||
return json_element;
|
||||
}
|
||||
|
||||
static void
|
||||
_json_delete_object_on_int_match (json_t *json,
|
||||
const char *key1,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
int val)
|
||||
{
|
||||
json_t *json_element;
|
||||
|
||||
json_element = _json_find_object (json, key1, key2, key3);
|
||||
if (!json_element || !json_is_integer (json_element))
|
||||
return;
|
||||
if (json_integer_value (json_element) == val)
|
||||
_json_del_object (json, key1, key2, key3);
|
||||
}
|
||||
|
||||
static void
|
||||
_json_delete_object_on_bool_match (json_t *json,
|
||||
const char *key1,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
gboolean val)
|
||||
{
|
||||
json_t *json_element;
|
||||
|
||||
json_element = _json_find_object (json, key1, key2, key3);
|
||||
if (!json_element || !json_is_boolean (json_element))
|
||||
return;
|
||||
if (json_boolean_value (json_element) == val)
|
||||
_json_del_object (json, key1, key2, key3);
|
||||
}
|
||||
|
||||
static void
|
||||
_json_delete_object_on_string_match (json_t *json,
|
||||
const char *key1,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
const char *val)
|
||||
{
|
||||
json_t *json_element;
|
||||
|
||||
json_element = _json_find_object (json, key1, key2, key3);
|
||||
if (!json_element || !json_is_string (json_element))
|
||||
return;
|
||||
if (nm_streq0 (json_string_value (json_element), val))
|
||||
_json_del_object (json, key1, key2, key3);
|
||||
}
|
||||
|
||||
static void
|
||||
_json_team_normalize_defaults (json_t *json, gboolean reset)
|
||||
{
|
||||
json_t *json_element;
|
||||
const char *runner = NM_SETTING_TEAM_RUNNER_DEFAULT;
|
||||
gs_free char *runner_free = NULL;
|
||||
int notify_peers_count = 0, notify_peers_interval = 0;
|
||||
int mcast_rejoin_count = 0, mcast_rejoin_interval = 0;
|
||||
int runner_tx_balancer_interval = -1;
|
||||
gboolean runner_active = FALSE, runner_fast_rate = FALSE;
|
||||
int runner_sys_prio = -1, runner_min_ports = -1;
|
||||
|
||||
json_element = _json_find_object (json, "runner", "name", NULL);
|
||||
if (json_element) {
|
||||
runner_free = g_strdup (json_string_value (json_element));
|
||||
runner = runner_free;
|
||||
_json_delete_object_on_string_match (json, "runner", "name", NULL,
|
||||
NM_SETTING_TEAM_RUNNER_DEFAULT);
|
||||
}
|
||||
|
||||
/* the runner changed: clear all the properties. Then team.config will be saved
|
||||
* and reloaded triggering the reset of the values through _nm_utils_team_config_get
|
||||
*/
|
||||
if (reset) {
|
||||
_json_del_object (json, "notify_peers", "count", NULL);
|
||||
_json_del_object (json, "notify_peers", "interval", NULL);
|
||||
_json_del_object (json, "mcast_rejoin", "count", NULL);
|
||||
_json_del_object (json, "mcast_rejoin", "interval", NULL);
|
||||
_json_del_object (json, "runner", "hwaddr_policy", NULL);
|
||||
_json_del_object (json, "runner", "tx_hash", NULL);
|
||||
_json_del_object (json, "runner", "tx_balancer", "name");
|
||||
_json_del_object (json, "runner", "tx_balancer", "balancing_interval");
|
||||
_json_del_object (json, "runner", "active", NULL);
|
||||
_json_del_object (json, "runner", "fast_rate", NULL);
|
||||
_json_del_object (json, "runner", "sys_prio", NULL);
|
||||
_json_del_object (json, "runner", "min_ports", NULL);
|
||||
_json_del_object (json, "runner", "agg_select_policy", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) {
|
||||
notify_peers_count = 1;
|
||||
mcast_rejoin_count = 1;
|
||||
_json_delete_object_on_string_match (json, "runner", "hwaddr_policy", NULL,
|
||||
NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT);
|
||||
} else if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) {
|
||||
runner_tx_balancer_interval = NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT;
|
||||
runner_active = TRUE;
|
||||
runner_sys_prio = NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT;
|
||||
runner_min_ports = 0;
|
||||
_json_delete_object_on_string_match (json, "runner", "agg_select_policy", NULL,
|
||||
NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT);
|
||||
} else if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE))
|
||||
runner_tx_balancer_interval = 50;
|
||||
|
||||
_json_delete_object_on_int_match (json, "notify_peers", "count", NULL, notify_peers_count);
|
||||
_json_delete_object_on_int_match (json, "notify_peers", "interval", NULL, notify_peers_interval);
|
||||
_json_delete_object_on_int_match (json, "mcast_rejoin", "count", NULL, mcast_rejoin_count);
|
||||
_json_delete_object_on_int_match (json, "macst_rejoin", "interval", NULL, mcast_rejoin_interval);
|
||||
_json_delete_object_on_int_match (json, "runner", "tx_balancer", "balancing_interval",
|
||||
runner_tx_balancer_interval);
|
||||
_json_delete_object_on_int_match (json, "runner", "sys_prio", NULL, runner_sys_prio);
|
||||
_json_delete_object_on_int_match (json, "runner", "min_ports", NULL, runner_min_ports);
|
||||
_json_delete_object_on_bool_match (json, "runner", "active", NULL, runner_active);
|
||||
_json_delete_object_on_bool_match (json, "runner", "active", NULL, runner_active);
|
||||
_json_delete_object_on_bool_match (json, "runner", "fast_rate", NULL, runner_fast_rate);
|
||||
}
|
||||
|
||||
static NMTeamLinkWatcher *
|
||||
_nm_utils_team_link_watcher_from_json (json_t *json_element)
|
||||
{
|
||||
const char *j_key;
|
||||
json_t *j_val;
|
||||
gs_free char *name = NULL, *target_host = NULL, *source_host = NULL;
|
||||
int val1 = 0, val2 = 0, val3 = 3, val4 = -1;
|
||||
NMTeamLinkWatcherArpPingFlags flags = 0;
|
||||
|
||||
g_return_val_if_fail (json_element, NULL);
|
||||
|
||||
json_object_foreach (json_element, j_key, j_val) {
|
||||
if (nm_streq (j_key, "name")) {
|
||||
g_free (name);
|
||||
name = strdup (json_string_value (j_val));
|
||||
} else if (nm_streq (j_key, "target_host")) {
|
||||
g_free (target_host);
|
||||
target_host = strdup (json_string_value (j_val));
|
||||
} else if (nm_streq (j_key, "source_host")) {
|
||||
g_free (source_host);
|
||||
source_host = strdup (json_string_value (j_val));
|
||||
} else if (NM_IN_STRSET (j_key, "delay_up", "init_wait"))
|
||||
val1 = json_integer_value (j_val);
|
||||
else if (NM_IN_STRSET (j_key, "delay_down", "interval"))
|
||||
val2 = json_integer_value (j_val);
|
||||
else if (nm_streq (j_key, "missed_max"))
|
||||
val3 = json_integer_value (j_val);
|
||||
else if (nm_streq (j_key, "vlanid"))
|
||||
val4 = json_integer_value (j_val);
|
||||
else if (nm_streq (j_key, "validate_active")) {
|
||||
if (json_is_true (j_val))
|
||||
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE;
|
||||
} else if (nm_streq (j_key, "validate_inactive")) {
|
||||
if (json_is_true (j_val))
|
||||
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE;
|
||||
} else if (nm_streq (j_key, "send_always")) {
|
||||
if (json_is_true (j_val))
|
||||
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ETHTOOL))
|
||||
return nm_team_link_watcher_new_ethtool (val1, val2, NULL);
|
||||
else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
|
||||
return nm_team_link_watcher_new_nsna_ping (val1, val2, val3, target_host, NULL);
|
||||
else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ARP_PING)) {
|
||||
return nm_team_link_watcher_new_arp_ping2 (val1, val2, val3, val4, target_host,
|
||||
source_host, flags, NULL);
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static json_t *
|
||||
_nm_utils_team_link_watcher_to_json (NMTeamLinkWatcher *watcher)
|
||||
{
|
||||
const char *name;
|
||||
int int_val;
|
||||
const char *str_val;
|
||||
NMTeamLinkWatcherArpPingFlags flags = 0;
|
||||
json_t *json_element;
|
||||
|
||||
g_return_val_if_fail (watcher, NULL);
|
||||
|
||||
json_element = json_object ();
|
||||
name = nm_team_link_watcher_get_name (watcher);
|
||||
if (!name)
|
||||
goto fail;
|
||||
|
||||
json_object_set_new (json_element, "name", json_string (name));
|
||||
|
||||
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
|
||||
int_val = nm_team_link_watcher_get_delay_up (watcher);
|
||||
if (int_val)
|
||||
json_object_set_new (json_element, "delay_up", json_integer (int_val));
|
||||
int_val = nm_team_link_watcher_get_delay_down (watcher);
|
||||
if (int_val)
|
||||
json_object_set_new (json_element, "delay_down", json_integer (int_val));
|
||||
return json_element;
|
||||
}
|
||||
|
||||
int_val = nm_team_link_watcher_get_init_wait (watcher);
|
||||
if (int_val)
|
||||
json_object_set_new (json_element, "init_wait", json_integer (int_val));
|
||||
int_val = nm_team_link_watcher_get_interval (watcher);
|
||||
if (int_val)
|
||||
json_object_set_new (json_element, "interval", json_integer (int_val));
|
||||
int_val = nm_team_link_watcher_get_missed_max (watcher);
|
||||
if (int_val != 3)
|
||||
json_object_set_new (json_element, "missed_max", json_integer (int_val));
|
||||
str_val = nm_team_link_watcher_get_target_host (watcher);
|
||||
if (!str_val)
|
||||
goto fail;
|
||||
json_object_set_new (json_element, "target_host", json_string (str_val));
|
||||
|
||||
if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
|
||||
return json_element;
|
||||
|
||||
int_val = nm_team_link_watcher_get_vlanid (watcher);
|
||||
if (int_val != -1)
|
||||
json_object_set_new (json_element, "vlanid", json_integer (int_val));
|
||||
str_val = nm_team_link_watcher_get_source_host (watcher);
|
||||
if (!str_val)
|
||||
goto fail;
|
||||
json_object_set_new (json_element, "source_host", json_string (str_val));
|
||||
|
||||
flags = nm_team_link_watcher_get_flags (watcher);
|
||||
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE)
|
||||
json_object_set_new (json_element, "validate_active", json_string ("true"));
|
||||
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE)
|
||||
json_object_set_new (json_element, "validate_inactive", json_string ("true"));
|
||||
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS)
|
||||
json_object_set_new (json_element, "send_always", json_string ("true"));
|
||||
|
||||
return json_element;
|
||||
|
||||
fail:
|
||||
json_decref (json_element);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_is_json_object:
|
||||
* @str: the JSON string to test
|
||||
|
|
@ -5816,6 +5393,7 @@ fail:
|
|||
gboolean
|
||||
nm_utils_is_json_object (const char *str, GError **error)
|
||||
{
|
||||
#if WITH_JSON_VALIDATION
|
||||
json_t *json;
|
||||
json_error_t jerror;
|
||||
|
||||
|
|
@ -5855,305 +5433,7 @@ nm_utils_is_json_object (const char *str, GError **error)
|
|||
|
||||
json_decref (json);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_utils_team_config_equal (const char *conf1,
|
||||
const char *conf2,
|
||||
gboolean port_config)
|
||||
{
|
||||
json_t *json1 = NULL, *json2 = NULL, *json;
|
||||
gs_free char *dump1 = NULL, *dump2 = NULL;
|
||||
json_t *value;
|
||||
json_error_t jerror;
|
||||
const char *key;
|
||||
gboolean ret;
|
||||
void *tmp;
|
||||
int i;
|
||||
|
||||
if (nm_streq0 (conf1, conf2))
|
||||
return TRUE;
|
||||
else if (!nm_jansson_load ())
|
||||
return FALSE;
|
||||
|
||||
/* A NULL configuration is equivalent to default value '{}' */
|
||||
json1 = json_loads (conf1 ?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
if (json1)
|
||||
json2 = json_loads (conf2 ?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
|
||||
if (!json1 || !json2) {
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Some properties are added by teamd when missing from the initial
|
||||
* configuration. Add them with the default value if necessary, depending
|
||||
* on the configuration type.
|
||||
*/
|
||||
for (i = 0, json = json1; i < 2; i++, json = json2)
|
||||
_json_team_add_defaults (json, port_config, FALSE);
|
||||
|
||||
/* Only consider a given subset of nodes, others can change depending on
|
||||
* current state */
|
||||
for (i = 0, json = json1; i < 2; i++, json = json2) {
|
||||
json_object_foreach_safe (json, tmp, key, value) {
|
||||
if (!NM_IN_STRSET (key, "runner", "link_watch"))
|
||||
json_object_del (json, key);
|
||||
}
|
||||
}
|
||||
|
||||
dump1 = json_dumps (json1, JSON_INDENT(0) | JSON_ENSURE_ASCII | JSON_SORT_KEYS);
|
||||
dump2 = json_dumps (json2, JSON_INDENT(0) | JSON_ENSURE_ASCII | JSON_SORT_KEYS);
|
||||
|
||||
ret = nm_streq0 (dump1, dump2);
|
||||
out:
|
||||
|
||||
if (json1)
|
||||
json_decref (json1);
|
||||
if (json2)
|
||||
json_decref (json2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GValue *
|
||||
_nm_utils_team_config_get (const char *conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
gboolean port_config)
|
||||
{
|
||||
json_t *json;
|
||||
json_t *json_element;
|
||||
GValue *value = NULL;
|
||||
json_error_t jerror;
|
||||
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
if (!nm_jansson_load ())
|
||||
return NULL;
|
||||
|
||||
json = json_loads (conf ?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
|
||||
/* Invalid json in conf */
|
||||
if (!json)
|
||||
return NULL;
|
||||
|
||||
/* Some properties are added by teamd when missing from the initial
|
||||
* configuration. Add them with the default value if necessary, depending
|
||||
* on the configuration type.
|
||||
* Skip this for port config, as some properties change on the basis of the
|
||||
* runner specified in the master connection... but we don't want to check
|
||||
* against properties in another connection. Moreover, for team-port we have
|
||||
* the link-watchers property only here: and for this compound property it is
|
||||
* fine to show the default value only if explicitly set.
|
||||
*/
|
||||
if (!port_config)
|
||||
_json_team_add_defaults (json, port_config, TRUE);
|
||||
|
||||
/* Now search the property to retrieve */
|
||||
json_element = json_object_get (json, key);
|
||||
if (json_element && key2)
|
||||
json_element = json_object_get (json_element, key2);
|
||||
if (json_element && key3)
|
||||
json_element = json_object_get (json_element, key3);
|
||||
|
||||
if (json_element) {
|
||||
value = g_new0 (GValue, 1);
|
||||
if (json_is_string (json_element)) {
|
||||
g_value_init (value, G_TYPE_STRING);
|
||||
g_value_set_string (value, json_string_value (json_element));
|
||||
} else if (json_is_integer (json_element)) {
|
||||
g_value_init (value, G_TYPE_INT);
|
||||
g_value_set_int (value, json_integer_value (json_element));
|
||||
} else if (json_is_boolean (json_element)) {
|
||||
g_value_init (value, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean (value, json_boolean_value (json_element));
|
||||
} else if (nm_streq (key, "link_watch")) {
|
||||
NMTeamLinkWatcher *watcher;
|
||||
GPtrArray *data = g_ptr_array_new_with_free_func
|
||||
((GDestroyNotify) nm_team_link_watcher_unref);
|
||||
|
||||
if (json_is_array (json_element)) {
|
||||
json_t *j_watcher;
|
||||
int index;
|
||||
|
||||
json_array_foreach (json_element, index, j_watcher) {
|
||||
watcher = _nm_utils_team_link_watcher_from_json (j_watcher);
|
||||
if (watcher)
|
||||
g_ptr_array_add (data, watcher);
|
||||
}
|
||||
} else {
|
||||
watcher = _nm_utils_team_link_watcher_from_json (json_element);
|
||||
if (watcher)
|
||||
g_ptr_array_add (data, watcher);
|
||||
}
|
||||
if (data->len) {
|
||||
g_value_init (value, G_TYPE_PTR_ARRAY);
|
||||
g_value_take_boxed (value, data);
|
||||
} else
|
||||
g_ptr_array_free (data, TRUE);
|
||||
|
||||
} else if (json_is_array (json_element)) {
|
||||
GPtrArray *data = g_ptr_array_new_with_free_func (g_free);
|
||||
json_t *str_element;
|
||||
int index;
|
||||
|
||||
json_array_foreach (json_element, index, str_element) {
|
||||
if (json_is_string (str_element))
|
||||
g_ptr_array_add (data, g_strdup (json_string_value (str_element)));
|
||||
}
|
||||
g_ptr_array_add (data, NULL);
|
||||
g_value_init (value, G_TYPE_STRV);
|
||||
g_value_take_boxed (value, g_ptr_array_free (data, FALSE));
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
g_free (value);
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (json)
|
||||
json_decref (json);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* if conf is updated in place returns TRUE */
|
||||
gboolean
|
||||
_nm_utils_team_config_set (char **conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
const GValue *value)
|
||||
{
|
||||
nm_auto_decref_json json_t *json = NULL;
|
||||
nm_auto_decref_json json_t *json_value = NULL;
|
||||
json_t *json_element;
|
||||
json_t *json_link;
|
||||
json_error_t jerror;
|
||||
const char *iter_key = key;
|
||||
gs_free char *conf_new = NULL;
|
||||
|
||||
g_return_val_if_fail (key, FALSE);
|
||||
|
||||
if (!nm_jansson_load ())
|
||||
return FALSE;
|
||||
|
||||
json = json_loads (*conf?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
if (!json)
|
||||
return FALSE;
|
||||
|
||||
if (!value) {
|
||||
if (!_json_del_object (json, key, key2, key3))
|
||||
return FALSE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (G_VALUE_HOLDS_STRING (value))
|
||||
json_value = json_string (g_value_get_string (value));
|
||||
else if (G_VALUE_HOLDS_INT (value))
|
||||
json_value = json_integer (g_value_get_int (value));
|
||||
else if (G_VALUE_HOLDS_BOOLEAN (value))
|
||||
json_value = json_boolean (g_value_get_boolean (value));
|
||||
else if (G_VALUE_HOLDS_BOXED (value)) {
|
||||
if (nm_streq (key, "link_watch")) {
|
||||
gboolean has_array = FALSE;
|
||||
GPtrArray *array;
|
||||
guint i;
|
||||
|
||||
array = g_value_get_boxed (value);
|
||||
if (!array || !array->len)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < array->len; i++) {
|
||||
json_t *el;
|
||||
|
||||
el = _nm_utils_team_link_watcher_to_json (array->pdata[i]);
|
||||
if (!el)
|
||||
continue;
|
||||
/* if there is only one watcher, it is added as-is. If there
|
||||
* are multiple watchers, they are added in an array. */
|
||||
if (!json_value) {
|
||||
json_value = el;
|
||||
continue;
|
||||
}
|
||||
if (!has_array) {
|
||||
json_t *el_arr;
|
||||
|
||||
has_array = TRUE;
|
||||
el_arr = json_array();
|
||||
json_array_append_new (el_arr, json_value);
|
||||
json_value = el_arr;
|
||||
}
|
||||
json_array_append_new (json_value, el);
|
||||
}
|
||||
} else if ( nm_streq (key, "runner")
|
||||
&& nm_streq0 (key2, "tx_hash")) {
|
||||
const char *const*strv;
|
||||
gsize i;
|
||||
|
||||
strv = g_value_get_boxed (value);
|
||||
if (!strv)
|
||||
return FALSE;
|
||||
|
||||
json_value = json_array ();
|
||||
for (i = 0; strv[i]; i++)
|
||||
json_array_append_new (json_value, json_string (strv[i]));
|
||||
} else {
|
||||
nm_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} else { /* G_VALUE_HOLDS_? */
|
||||
nm_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Simplest case: first level key only */
|
||||
json_element = json;
|
||||
json_link = NULL;
|
||||
|
||||
if (key2) {
|
||||
json_link = json;
|
||||
json_element = json_object_get (json, iter_key);
|
||||
if (!json_element) {
|
||||
json_element = json_object ();
|
||||
json_object_set_new (json_link, iter_key, json_element);
|
||||
}
|
||||
iter_key = key2;
|
||||
}
|
||||
if (key3) {
|
||||
json_link = json_element;
|
||||
json_element = json_object_get (json_link, iter_key);
|
||||
if (!json_element) {
|
||||
json_element = json_object ();
|
||||
json_object_set_new (json_link, iter_key, json_element);
|
||||
}
|
||||
iter_key = key3;
|
||||
}
|
||||
|
||||
json_object_set_new (json_element, iter_key, g_steal_pointer (&json_value));
|
||||
|
||||
done:
|
||||
_json_team_normalize_defaults (json, ( nm_streq0 (key, "runner")
|
||||
&& nm_streq0 (key2, "name")));
|
||||
conf_new = json_dumps (json, JSON_PRESERVE_ORDER);
|
||||
if (nm_streq0 (conf_new, "{}"))
|
||||
nm_clear_g_free (&conf_new);
|
||||
if (nm_streq0 (conf_new, *conf))
|
||||
return FALSE;
|
||||
g_free (*conf);
|
||||
*conf = g_steal_pointer (&conf_new);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else /* !WITH_JSON_VALIDATION */
|
||||
|
||||
gboolean
|
||||
nm_utils_is_json_object (const char *str, GError **error)
|
||||
{
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
||||
if (!str || !str[0]) {
|
||||
|
|
@ -6165,239 +5445,7 @@ nm_utils_is_json_object (const char *str, GError **error)
|
|||
}
|
||||
|
||||
return _nm_utils_is_json_object_no_validation (str, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_utils_team_config_equal (const char *conf1,
|
||||
const char *conf2,
|
||||
gboolean port_config)
|
||||
{
|
||||
return nm_streq0 (conf1, conf2);
|
||||
}
|
||||
|
||||
GValue *
|
||||
_nm_utils_team_config_get (const char *conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
gboolean port_config)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_utils_team_config_set (char **conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
const GValue *value)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* _nm_utils_team_link_watchers_to_variant:
|
||||
* @link_watchers: (element-type NMTeamLinkWatcher): array of #NMTeamLinkWatcher
|
||||
*
|
||||
* Utility function to convert a #GPtrArray of #NMTeamLinkWatcher objects
|
||||
* representing link watcher configuration for team devices into a #GVariant
|
||||
* of type 'aa{sv}' representing an array of link watchers.
|
||||
*
|
||||
* Returns: (transfer none): a new floating #GVariant representing link watchers.
|
||||
**/
|
||||
GVariant *
|
||||
_nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers)
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
int i;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
|
||||
|
||||
if (!link_watchers)
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < link_watchers->len; i++) {
|
||||
NMTeamLinkWatcher *watcher = link_watchers->pdata[i];
|
||||
GVariantBuilder watcher_builder;
|
||||
const char *name;
|
||||
int int_val;
|
||||
NMTeamLinkWatcherArpPingFlags flags;
|
||||
|
||||
g_variant_builder_init (&watcher_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
|
||||
name = nm_team_link_watcher_get_name (watcher);
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"name",
|
||||
g_variant_new_string (name));
|
||||
|
||||
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
|
||||
int_val = nm_team_link_watcher_get_delay_up (watcher);
|
||||
if (int_val) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"delay-up",
|
||||
g_variant_new_int32 (int_val));
|
||||
}
|
||||
int_val = nm_team_link_watcher_get_delay_down (watcher);
|
||||
if (int_val) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"delay-down",
|
||||
g_variant_new_int32 (int_val));
|
||||
}
|
||||
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Common properties for arp_ping and nsna_ping link watchers */
|
||||
int_val = nm_team_link_watcher_get_init_wait (watcher);
|
||||
if (int_val) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"init-wait",
|
||||
g_variant_new_int32 (int_val));
|
||||
}
|
||||
int_val = nm_team_link_watcher_get_interval (watcher);
|
||||
if (int_val) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"interval",
|
||||
g_variant_new_int32 (int_val));
|
||||
}
|
||||
int_val = nm_team_link_watcher_get_missed_max (watcher);
|
||||
if (int_val != 3) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"missed-max",
|
||||
g_variant_new_int32 (int_val));
|
||||
}
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"target-host",
|
||||
g_variant_new_string (nm_team_link_watcher_get_target_host (watcher)));
|
||||
|
||||
if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING)) {
|
||||
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* arp_ping watcher only */
|
||||
int_val = nm_team_link_watcher_get_vlanid (watcher);
|
||||
if (int_val != -1) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"vlanid",
|
||||
g_variant_new_int32 (int_val));
|
||||
}
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"source-host",
|
||||
g_variant_new_string (nm_team_link_watcher_get_source_host (watcher)));
|
||||
flags = nm_team_link_watcher_get_flags (watcher);
|
||||
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"validate-active",
|
||||
g_variant_new_boolean (TRUE));
|
||||
}
|
||||
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"validate-inactive",
|
||||
g_variant_new_boolean (TRUE));
|
||||
}
|
||||
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS) {
|
||||
g_variant_builder_add (&watcher_builder, "{sv}",
|
||||
"send-always",
|
||||
g_variant_new_boolean (TRUE));
|
||||
}
|
||||
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
|
||||
}
|
||||
end:
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* _nm_utils_team_link_watchers_from_variant:
|
||||
* @value: a #GVariant of type 'aa{sv}'
|
||||
*
|
||||
* Utility function to convert a #GVariant representing a list of team link
|
||||
* watchers int a #GPtrArray of #NMTeamLinkWatcher objects.
|
||||
*
|
||||
* Returns: (transfer full) (element-type NMTeamLinkWatcher): a newly allocated
|
||||
* #GPtrArray of #NMTeamLinkWatcher objects.
|
||||
**/
|
||||
GPtrArray *
|
||||
_nm_utils_team_link_watchers_from_variant (GVariant *value)
|
||||
{
|
||||
GPtrArray *link_watchers;
|
||||
GVariantIter iter;
|
||||
GVariant *watcher_var;
|
||||
|
||||
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
|
||||
|
||||
link_watchers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref);
|
||||
g_variant_iter_init (&iter, value);
|
||||
|
||||
while (g_variant_iter_next (&iter, "@a{sv}", &watcher_var)) {
|
||||
NMTeamLinkWatcher *watcher;
|
||||
const char *name;
|
||||
int val1, val2, val3 = 0, val4 = -1;
|
||||
const char *target_host = NULL, *source_host = NULL;
|
||||
gboolean bval;
|
||||
NMTeamLinkWatcherArpPingFlags flags = NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_variant_lookup (watcher_var, "name", "&s", &name))
|
||||
goto next;
|
||||
if (!NM_IN_STRSET (name,
|
||||
NM_TEAM_LINK_WATCHER_ETHTOOL,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING,
|
||||
NM_TEAM_LINK_WATCHER_NSNA_PING)) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
|
||||
if (!g_variant_lookup (watcher_var, "delay-up", "i", &val1))
|
||||
val1 = 0;
|
||||
if (!g_variant_lookup (watcher_var, "delay-down", "i", &val2))
|
||||
val2 = 0;
|
||||
watcher = nm_team_link_watcher_new_ethtool (val1, val2, &error);
|
||||
} else {
|
||||
if (!g_variant_lookup (watcher_var, "target-host", "&s", &target_host))
|
||||
goto next;
|
||||
if (!g_variant_lookup (watcher_var, "init_wait", "i", &val1))
|
||||
val1 = 0;
|
||||
if (!g_variant_lookup (watcher_var, "interval", "i", &val2))
|
||||
val2 = 0;
|
||||
if (!g_variant_lookup (watcher_var, "missed-max", "i", &val3))
|
||||
val3 = 3;
|
||||
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ARP_PING)) {
|
||||
if (!g_variant_lookup (watcher_var, "vlanid", "i", &val4))
|
||||
val4 = -1;
|
||||
if (!g_variant_lookup (watcher_var, "source-host", "&s", &source_host))
|
||||
goto next;
|
||||
if (!g_variant_lookup (watcher_var, "validate-active", "b", &bval))
|
||||
bval = FALSE;
|
||||
if (bval)
|
||||
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE;
|
||||
if (!g_variant_lookup (watcher_var, "validate-inactive", "b", &bval))
|
||||
bval = FALSE;
|
||||
if (bval)
|
||||
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE;
|
||||
if (!g_variant_lookup (watcher_var, "send-always", "b", &bval))
|
||||
bval = FALSE;
|
||||
if (bval)
|
||||
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS;
|
||||
watcher = nm_team_link_watcher_new_arp_ping2 (val1, val2, val3, val4,
|
||||
target_host, source_host,
|
||||
flags, &error);
|
||||
} else
|
||||
watcher = nm_team_link_watcher_new_nsna_ping (val1, val2, val3,
|
||||
target_host, &error);
|
||||
}
|
||||
if (!watcher) {
|
||||
g_clear_error (&error);
|
||||
goto next;
|
||||
}
|
||||
|
||||
g_ptr_array_add (link_watchers, watcher);
|
||||
next:
|
||||
g_variant_unref (watcher_var);
|
||||
}
|
||||
|
||||
return link_watchers;
|
||||
}
|
||||
|
||||
static char *
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "nm-utils-private.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-core-tests-enum-types.h"
|
||||
#include "nm-team-utils.h"
|
||||
|
||||
#include "nm-setting-8021x.h"
|
||||
#include "nm-setting-adsl.h"
|
||||
|
|
@ -6807,14 +6808,42 @@ _team_config_equal_check (const char *conf1,
|
|||
gboolean port_config,
|
||||
gboolean expected)
|
||||
{
|
||||
g_assert_cmpint (_nm_utils_team_config_equal (conf1, conf2, port_config), ==, expected);
|
||||
nm_auto_free_team_setting NMTeamSetting *team_a = NULL;
|
||||
nm_auto_free_team_setting NMTeamSetting *team_b = NULL;
|
||||
gboolean is_same;
|
||||
|
||||
if (nmtst_get_rand_bool ())
|
||||
NMTST_SWAP (conf1, conf2);
|
||||
|
||||
if (!nm_streq0 (conf1, conf2)) {
|
||||
_team_config_equal_check (conf1, conf1, port_config, TRUE);
|
||||
_team_config_equal_check (conf2, conf2, port_config, TRUE);
|
||||
}
|
||||
|
||||
team_a = nm_team_setting_new (port_config, conf1);
|
||||
team_b = nm_team_setting_new (port_config, conf2);
|
||||
|
||||
is_same = (nm_team_setting_cmp (team_a, team_b, TRUE) == 0);
|
||||
g_assert_cmpint (is_same, ==, expected);
|
||||
|
||||
if (nm_streq0 (conf1, conf2)) {
|
||||
g_assert_cmpint (nm_team_setting_cmp (team_a, team_b, FALSE), ==, 0);
|
||||
g_assert (expected);
|
||||
} else
|
||||
g_assert_cmpint (nm_team_setting_cmp (team_a, team_b, FALSE), !=, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nm_utils_team_config_equal (void)
|
||||
{
|
||||
#if WITH_JSON_VALIDATION
|
||||
_team_config_equal_check ("", "", TRUE, TRUE);
|
||||
_team_config_equal_check ("",
|
||||
"",
|
||||
TRUE,
|
||||
TRUE);
|
||||
_team_config_equal_check ("",
|
||||
" ",
|
||||
TRUE,
|
||||
TRUE);
|
||||
_team_config_equal_check ("{}",
|
||||
"{ }",
|
||||
TRUE,
|
||||
|
|
@ -6822,7 +6851,15 @@ test_nm_utils_team_config_equal (void)
|
|||
_team_config_equal_check ("{}",
|
||||
"{",
|
||||
TRUE,
|
||||
FALSE);
|
||||
TRUE);
|
||||
_team_config_equal_check ("{ \"a\": 1 }",
|
||||
"{ \"a\": 1 }",
|
||||
TRUE,
|
||||
TRUE);
|
||||
_team_config_equal_check ("{ \"a\": 1 }",
|
||||
"{ \"a\": 1 }",
|
||||
TRUE,
|
||||
TRUE);
|
||||
|
||||
/* team config */
|
||||
_team_config_equal_check ("{ }",
|
||||
|
|
@ -6832,11 +6869,11 @@ test_nm_utils_team_config_equal (void)
|
|||
_team_config_equal_check ("{ }",
|
||||
"{ \"runner\" : { \"name\" : \"random\"} }",
|
||||
FALSE,
|
||||
FALSE);
|
||||
!WITH_JSON_VALIDATION);
|
||||
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
|
||||
"{ \"runner\" : { \"name\" : \"random\"} }",
|
||||
FALSE,
|
||||
FALSE);
|
||||
!WITH_JSON_VALIDATION);
|
||||
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"} }",
|
||||
"{ \"runner\" : { \"name\" : \"random\"} }",
|
||||
FALSE,
|
||||
|
|
@ -6856,11 +6893,11 @@ test_nm_utils_team_config_equal (void)
|
|||
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
|
||||
"{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
|
||||
FALSE,
|
||||
FALSE);
|
||||
!WITH_JSON_VALIDATION);
|
||||
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
|
||||
"{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }",
|
||||
FALSE,
|
||||
FALSE);
|
||||
!WITH_JSON_VALIDATION);
|
||||
|
||||
/* team port config */
|
||||
_team_config_equal_check ("{ }",
|
||||
|
|
@ -6870,11 +6907,11 @@ test_nm_utils_team_config_equal (void)
|
|||
_team_config_equal_check ("{ }",
|
||||
"{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
|
||||
TRUE,
|
||||
FALSE);
|
||||
TRUE);
|
||||
_team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
|
||||
"{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
|
||||
TRUE,
|
||||
FALSE);
|
||||
TRUE);
|
||||
_team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
|
||||
"{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
|
||||
TRUE,
|
||||
|
|
@ -6883,13 +6920,6 @@ test_nm_utils_team_config_equal (void)
|
|||
"{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth1\" : {} } }",
|
||||
TRUE,
|
||||
TRUE);
|
||||
#else
|
||||
/* Without JSON library, strings are compared for equality */
|
||||
_team_config_equal_check ("", "", TRUE, TRUE);
|
||||
_team_config_equal_check ("", " ", TRUE, FALSE);
|
||||
_team_config_equal_check ("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, TRUE);
|
||||
_team_config_equal_check ("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -626,11 +626,15 @@ test_team_conf_read_valid (void)
|
|||
static void
|
||||
test_team_conf_read_invalid (void)
|
||||
{
|
||||
#if WITH_JSON_VALIDATION
|
||||
GKeyFile *keyfile = NULL;
|
||||
gs_unref_object NMConnection *con = NULL;
|
||||
NMSettingTeam *s_team;
|
||||
|
||||
if (!WITH_JSON_VALIDATION) {
|
||||
g_test_skip ("team test requires JSON validation");
|
||||
return;
|
||||
}
|
||||
|
||||
con = nmtst_create_connection_from_keyfile (
|
||||
"[connection]\n"
|
||||
"type=team\n"
|
||||
|
|
@ -645,7 +649,6 @@ test_team_conf_read_invalid (void)
|
|||
g_assert (nm_setting_team_get_config (s_team) == NULL);
|
||||
|
||||
CLEAR (&con, &keyfile);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -45,6 +45,15 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* assert that the define is just a plain integer (boolean). */
|
||||
|
||||
G_STATIC_ASSERT ( (WITH_JSON_VALIDATION) == 1
|
||||
|| (WITH_JSON_VALIDATION) == 0);
|
||||
|
||||
_nm_unused static const int _with_json_validation = WITH_JSON_VALIDATION;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* converts @dict to a connection. In this case, @dict must be good, without warnings, so that
|
||||
* NM_SETTING_PARSE_FLAGS_STRICT and NM_SETTING_PARSE_FLAGS_BEST_EFFORT yield the exact same results. */
|
||||
static NMConnection *
|
||||
|
|
@ -966,7 +975,6 @@ test_dcb_bandwidth_sums (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if WITH_JSON_VALIDATION
|
||||
static void
|
||||
_test_team_config_sync (const char *team_config,
|
||||
int notify_peer_count,
|
||||
|
|
@ -989,26 +997,31 @@ _test_team_config_sync (const char *team_config,
|
|||
guint i, j;
|
||||
gboolean found;
|
||||
|
||||
if (!WITH_JSON_VALIDATION) {
|
||||
g_test_skip ("team test requires JSON validation");
|
||||
return;
|
||||
}
|
||||
|
||||
s_team = (NMSettingTeam *) nm_setting_team_new ();
|
||||
g_assert (s_team);
|
||||
|
||||
g_object_set (s_team, NM_SETTING_TEAM_CONFIG, team_config, NULL);
|
||||
g_assert (nm_setting_team_get_notify_peers_count (s_team) == notify_peer_count);
|
||||
g_assert (nm_setting_team_get_notify_peers_interval (s_team) == notify_peers_interval);
|
||||
g_assert (nm_setting_team_get_mcast_rejoin_count (s_team) == mcast_rejoin_count);
|
||||
g_assert (nm_setting_team_get_mcast_rejoin_interval (s_team) == mcast_rejoin_interval);
|
||||
g_assert (nm_setting_team_get_runner_tx_balancer_interval (s_team) == runner_tx_balancer_interval);
|
||||
g_assert (nm_setting_team_get_runner_active (s_team) == runner_active);
|
||||
g_assert (nm_setting_team_get_runner_fast_rate (s_team) == runner_fast_rate);
|
||||
g_assert (nm_setting_team_get_runner_sys_prio (s_team) == runner_sys_prio);
|
||||
g_assert (nm_setting_team_get_runner_min_ports (s_team) == runner_min_ports);
|
||||
g_assert (nm_streq0 (nm_setting_team_get_runner (s_team), runner));
|
||||
g_assert (nm_streq0 (nm_setting_team_get_runner_hwaddr_policy (s_team), runner_hwaddr_policy));
|
||||
g_assert (nm_streq0 (nm_setting_team_get_runner_tx_balancer (s_team), runner_tx_balancer));
|
||||
g_assert (nm_streq0 (nm_setting_team_get_runner_agg_select_policy (s_team), runner_agg_select_policy));
|
||||
g_assert_cmpint (nm_setting_team_get_notify_peers_count (s_team), ==, notify_peer_count);
|
||||
g_assert_cmpint (nm_setting_team_get_notify_peers_interval (s_team), ==, notify_peers_interval);
|
||||
g_assert_cmpint (nm_setting_team_get_mcast_rejoin_count (s_team), ==, mcast_rejoin_count);
|
||||
g_assert_cmpint (nm_setting_team_get_mcast_rejoin_interval (s_team), ==, mcast_rejoin_interval);
|
||||
g_assert_cmpint (nm_setting_team_get_runner_tx_balancer_interval (s_team), ==, runner_tx_balancer_interval);
|
||||
g_assert_cmpint (nm_setting_team_get_runner_active (s_team), ==, runner_active);
|
||||
g_assert_cmpint (nm_setting_team_get_runner_fast_rate (s_team), ==, runner_fast_rate);
|
||||
g_assert_cmpint (nm_setting_team_get_runner_sys_prio (s_team), ==, runner_sys_prio);
|
||||
g_assert_cmpint (nm_setting_team_get_runner_min_ports (s_team), ==, runner_min_ports);
|
||||
g_assert_cmpstr (nm_setting_team_get_runner (s_team), ==, runner);
|
||||
g_assert_cmpstr (nm_setting_team_get_runner_hwaddr_policy (s_team), ==, runner_hwaddr_policy);
|
||||
g_assert_cmpstr (nm_setting_team_get_runner_tx_balancer (s_team), ==, runner_tx_balancer);
|
||||
g_assert_cmpstr (nm_setting_team_get_runner_agg_select_policy (s_team), ==, runner_agg_select_policy);
|
||||
|
||||
if (runner_tx_hash) {
|
||||
g_assert (runner_tx_hash->len == nm_setting_team_get_num_runner_tx_hash (s_team));
|
||||
g_assert_cmpint (runner_tx_hash->len, ==, nm_setting_team_get_num_runner_tx_hash (s_team));
|
||||
for (i = 0; i < runner_tx_hash->len; i++) {
|
||||
found = FALSE;
|
||||
for (j = 0; j < nm_setting_team_get_num_runner_tx_hash (s_team); j++) {
|
||||
|
|
@ -1023,7 +1036,7 @@ _test_team_config_sync (const char *team_config,
|
|||
}
|
||||
|
||||
if (link_watchers) {
|
||||
g_assert (link_watchers->len == nm_setting_team_get_num_link_watchers (s_team));
|
||||
g_assert_cmpint (link_watchers->len, ==, nm_setting_team_get_num_link_watchers (s_team));
|
||||
for (i = 0; i < link_watchers->len; i++) {
|
||||
found = FALSE;
|
||||
for (j = 0; j < nm_setting_team_get_num_link_watchers (s_team); j++) {
|
||||
|
|
@ -1250,6 +1263,11 @@ _test_team_port_config_sync (const char *team_port_config,
|
|||
guint i, j;
|
||||
gboolean found;
|
||||
|
||||
if (!WITH_JSON_VALIDATION) {
|
||||
g_test_skip ("team test requires JSON validation");
|
||||
return;
|
||||
}
|
||||
|
||||
s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new ();
|
||||
g_assert (s_team_port);
|
||||
|
||||
|
|
@ -1354,7 +1372,134 @@ test_team_port_full_config (void)
|
|||
"\"send_always\": true}]}",
|
||||
10, 20, true, 30, 40, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_check_team_setting (NMSetting *setting)
|
||||
{
|
||||
gs_unref_object NMSetting *setting2 = NULL;
|
||||
gs_unref_object NMSetting *setting_clone = NULL;
|
||||
gboolean is_port = NM_IS_SETTING_TEAM_PORT (setting);
|
||||
gs_unref_variant GVariant *variant2 = NULL;
|
||||
gs_unref_variant GVariant *variant3 = NULL;
|
||||
|
||||
g_assert (NM_IS_SETTING_TEAM (setting) || is_port);
|
||||
|
||||
setting_clone = nm_setting_duplicate (setting);
|
||||
|
||||
if (!is_port) {
|
||||
if (nm_setting_team_get_runner (NM_SETTING_TEAM (setting)) == NULL) {
|
||||
/* such a setting is invalid. We must first coerce it so that it becomes
|
||||
* valid. */
|
||||
setting = setting_clone;
|
||||
g_object_set (setting,
|
||||
NM_SETTING_TEAM_RUNNER,
|
||||
NM_SETTING_TEAM_RUNNER_DEFAULT,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
setting2 = g_object_new (G_OBJECT_TYPE (setting),
|
||||
is_port
|
||||
? NM_SETTING_TEAM_PORT_CONFIG
|
||||
: NM_SETTING_TEAM_CONFIG,
|
||||
is_port
|
||||
? nm_setting_team_port_get_config (NM_SETTING_TEAM_PORT (setting))
|
||||
: nm_setting_team_get_config (NM_SETTING_TEAM (setting)),
|
||||
NULL);
|
||||
|
||||
if (WITH_JSON_VALIDATION)
|
||||
nmtst_assert_setting_is_equal (setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT);
|
||||
|
||||
g_clear_object (&setting2);
|
||||
|
||||
nmtst_assert_setting_dbus_roundtrip (setting);
|
||||
|
||||
/* OK, now parse the setting only from the D-Bus variant, but removing the JSON config.
|
||||
* For that, we have to "drop" the JSON and we do that by resetting the property.
|
||||
* This causes JSON to be regenerated and it's in a normalized form that will compare
|
||||
* equal. */
|
||||
setting = setting_clone;
|
||||
if (is_port) {
|
||||
g_object_set (setting,
|
||||
NM_SETTING_TEAM_PORT_STICKY,
|
||||
nm_setting_team_port_get_sticky (NM_SETTING_TEAM_PORT (setting)),
|
||||
NULL);
|
||||
} else {
|
||||
g_object_set (setting,
|
||||
NM_SETTING_TEAM_RUNNER_SYS_PRIO,
|
||||
nm_setting_team_get_runner_sys_prio (NM_SETTING_TEAM (setting)),
|
||||
NULL);
|
||||
}
|
||||
variant2 = _nm_setting_to_dbus (setting, NULL, NM_CONNECTION_SERIALIZE_ALL);
|
||||
variant3 = nm_utils_gvariant_vardict_filter_drop_one (variant2, "config");
|
||||
setting2 = nmtst_assert_setting_dbus_new (G_OBJECT_TYPE (setting), variant3);
|
||||
nmtst_assert_setting_is_equal (setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT);
|
||||
}
|
||||
|
||||
static void
|
||||
test_team_setting (void)
|
||||
{
|
||||
gs_unref_variant GVariant *variant = nmtst_variant_from_string (G_VARIANT_TYPE_VARDICT,
|
||||
"{'config': <'{\"link_watch\": {\"name\": \"ethtool\"}}'>, 'interface-name': <'nm-team'>, 'link-watchers': <[{'name': <'ethtool'>}]>, 'runner': <'roundrobin'>, 'runner-min-ports': <-1>, 'runner-sys-prio': <-1>, 'runner-tx-balancer-interval': <-1>}");
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_object NMSetting *setting = NULL;
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher1 = nm_team_link_watcher_new_nsna_ping (1, 3, 4, "bbb", NULL);
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = nm_team_link_watcher_new_arp_ping2 (1, 3, 4, -1, "ccc", "ddd", 0, NULL);
|
||||
|
||||
g_assert (watcher1);
|
||||
g_assert (watcher2);
|
||||
|
||||
setting = _nm_setting_new_from_dbus (NM_TYPE_SETTING_TEAM,
|
||||
variant,
|
||||
NULL,
|
||||
NM_SETTING_PARSE_FLAGS_STRICT,
|
||||
&error);
|
||||
nmtst_assert_success (setting, error);
|
||||
_check_team_setting (setting);
|
||||
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{\"link_watch\": {\"name\": \"ethtool\"}}");
|
||||
g_assert_cmpint (nm_setting_team_get_num_link_watchers (NM_SETTING_TEAM (setting)), ==, 1);
|
||||
|
||||
g_object_set (setting,
|
||||
NM_SETTING_TEAM_RUNNER_SYS_PRIO,
|
||||
(int) 10,
|
||||
NULL);
|
||||
|
||||
_check_team_setting (setting);
|
||||
g_assert_cmpint (nm_setting_team_get_num_link_watchers (NM_SETTING_TEAM (setting)), ==, 1);
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"ethtool\"} }");
|
||||
|
||||
nm_setting_team_remove_link_watcher (NM_SETTING_TEAM (setting), 0);
|
||||
|
||||
_check_team_setting (setting);
|
||||
g_assert_cmpint (nm_setting_team_get_num_link_watchers (NM_SETTING_TEAM (setting)), ==, 0);
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 } }");
|
||||
|
||||
nm_setting_team_add_link_watcher (NM_SETTING_TEAM (setting), watcher1);
|
||||
_check_team_setting (setting);
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"nsna_ping\", \"target_host\": \"bbb\", \"init_wait\": 1, \"interval\": 3, \"missed_max\": 4} }");
|
||||
|
||||
nm_setting_team_add_link_watcher (NM_SETTING_TEAM (setting), watcher2);
|
||||
_check_team_setting (setting);
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": [ { \"name\": \"nsna_ping\", \"target_host\": \"bbb\", \"init_wait\": 1, \"interval\": 3, \"missed_max\": 4}, { \"name\": \"arp_ping\", \"target_host\": \"ccc\", \"source_host\": \"ddd\", \"init_wait\": 1, \"interval\": 3, \"missed_max\": 4} ] }");
|
||||
|
||||
nm_setting_team_remove_link_watcher (NM_SETTING_TEAM (setting), 0);
|
||||
nm_setting_team_remove_link_watcher (NM_SETTING_TEAM (setting), 0);
|
||||
g_object_set (setting,
|
||||
NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL,
|
||||
(int) 5,
|
||||
NULL);
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }");
|
||||
|
||||
g_object_set (setting,
|
||||
NM_SETTING_TEAM_RUNNER,
|
||||
NULL,
|
||||
NULL);
|
||||
_check_team_setting (setting);
|
||||
g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -3189,7 +3334,6 @@ main (int argc, char **argv)
|
|||
|
||||
g_test_add_func ("/libnm/settings/bridge/vlans", test_bridge_vlans);
|
||||
|
||||
#if WITH_JSON_VALIDATION
|
||||
g_test_add_func ("/libnm/settings/team/sync_runner_from_config_roundrobin",
|
||||
test_runner_roundrobin_sync_from_config);
|
||||
g_test_add_func ("/libnm/settings/team/sync_runner_from_config_broadcast",
|
||||
|
|
@ -3218,7 +3362,6 @@ main (int argc, char **argv)
|
|||
g_test_add_func ("/libnm/settings/team-port/sync_from_config_lacp_prio", test_team_port_lacp_prio);
|
||||
g_test_add_func ("/libnm/settings/team-port/sync_from_config_lacp_key", test_team_port_lacp_key);
|
||||
g_test_add_func ("/libnm/settings/team-port/sycn_from_config_full", test_team_port_full_config);
|
||||
#endif
|
||||
|
||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/general/0", GINT_TO_POINTER (0), test_roundtrip_conversion);
|
||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/1", GINT_TO_POINTER (1), test_roundtrip_conversion);
|
||||
|
|
@ -3229,5 +3372,7 @@ main (int argc, char **argv)
|
|||
|
||||
g_test_add_func ("/libnm/parse-tc-handle", test_parse_tc_handle);
|
||||
|
||||
g_test_add_func ("/libnm/test_team_setting", test_team_setting);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,8 @@ def get_default_value(setting, pspec, propxml):
|
|||
default_value = '[]'
|
||||
elif str(default_value).startswith('<'):
|
||||
default_value = None
|
||||
elif str(default_value).startswith('['):
|
||||
default_value = None
|
||||
|
||||
return default_value
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ libnm-core/nm-setting-wireless-security.c
|
|||
libnm-core/nm-setting-wireless.c
|
||||
libnm-core/nm-setting-wpan.c
|
||||
libnm-core/nm-setting.c
|
||||
libnm-core/nm-team-utils.c
|
||||
libnm-core/nm-utils.c
|
||||
libnm-core/nm-vpn-editor-plugin.c
|
||||
libnm-core/nm-vpn-plugin-info.c
|
||||
|
|
@ -173,3 +174,4 @@ src/nm-logging.c
|
|||
src/nm-manager.c
|
||||
src/settings/plugins/ibft/nms-ibft-plugin.c
|
||||
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
|
||||
src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ shared_nm_glib_aux = static_library(
|
|||
'nm-glib-aux/nm-errno.c',
|
||||
'nm-glib-aux/nm-hash-utils.c',
|
||||
'nm-glib-aux/nm-io-utils.c',
|
||||
'nm-glib-aux/nm-json-aux.c',
|
||||
'nm-glib-aux/nm-keyfile-aux.c',
|
||||
'nm-glib-aux/nm-random-utils.c',
|
||||
'nm-glib-aux/nm-secret-utils.c',
|
||||
|
|
|
|||
|
|
@ -44,6 +44,106 @@
|
|||
NM_AUTO_DEFINE_FCN0 (json_t *, _nm_auto_decref_json, json_decref)
|
||||
#define nm_auto_decref_json nm_auto(_nm_auto_decref_json)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_jansson_json_as_bool (const json_t *elem,
|
||||
bool *out_val)
|
||||
{
|
||||
if (!elem)
|
||||
return 0;
|
||||
|
||||
if (!json_is_boolean (elem))
|
||||
return -EINVAL;
|
||||
|
||||
NM_SET_OUT (out_val, json_boolean_value (elem));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_jansson_json_as_int32 (const json_t *elem,
|
||||
gint32 *out_val)
|
||||
{
|
||||
json_int_t v;
|
||||
|
||||
if (!elem)
|
||||
return 0;
|
||||
|
||||
if (!json_is_integer (elem))
|
||||
return -EINVAL;
|
||||
|
||||
v = json_integer_value (elem);
|
||||
if ( v < (gint64) G_MININT32
|
||||
|| v > (gint64) G_MAXINT32)
|
||||
return -ERANGE;
|
||||
|
||||
NM_SET_OUT (out_val, v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_jansson_json_as_int (const json_t *elem,
|
||||
int *out_val)
|
||||
{
|
||||
json_int_t v;
|
||||
|
||||
if (!elem)
|
||||
return 0;
|
||||
|
||||
if (!json_is_integer (elem))
|
||||
return -EINVAL;
|
||||
|
||||
v = json_integer_value (elem);
|
||||
if ( v < (gint64) G_MININT
|
||||
|| v > (gint64) G_MAXINT)
|
||||
return -ERANGE;
|
||||
|
||||
NM_SET_OUT (out_val, v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_jansson_json_as_string (const json_t *elem,
|
||||
const char **out_val)
|
||||
{
|
||||
if (!elem)
|
||||
return 0;
|
||||
|
||||
if (!json_is_string (elem))
|
||||
return -EINVAL;
|
||||
|
||||
NM_SET_OUT (out_val, json_string_value (elem));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
|
||||
#include "nm-value-type.h"
|
||||
static inline gboolean
|
||||
nm_value_type_from_json (NMValueType value_type,
|
||||
const json_t *elem,
|
||||
gpointer out_val)
|
||||
{
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: return (nm_jansson_json_as_bool (elem, out_val) > 0);
|
||||
case NM_VALUE_TYPE_INT32: return (nm_jansson_json_as_int32 (elem, out_val) > 0);
|
||||
case NM_VALUE_TYPE_INT: return (nm_jansson_json_as_int (elem, out_val) > 0);
|
||||
|
||||
/* warning: this overwrites/leaks the previous value. You better have *out_val
|
||||
* point to uninitialized memory or NULL. */
|
||||
case NM_VALUE_TYPE_STRING: return (nm_jansson_json_as_string (elem, out_val) > 0);
|
||||
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* WITH_JANSON */
|
||||
|
||||
#endif /* __NM_JANSSON_H__ */
|
||||
|
|
|
|||
149
shared/nm-glib-aux/nm-json-aux.c
Normal file
149
shared/nm-glib-aux/nm-json-aux.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-json-aux.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_gstr_append_string_len (GString *gstr,
|
||||
const char *str,
|
||||
gsize len)
|
||||
{
|
||||
g_string_append_c (gstr, '\"');
|
||||
|
||||
while (len > 0) {
|
||||
gsize n;
|
||||
const char *end;
|
||||
gboolean valid;
|
||||
|
||||
nm_assert (len > 0);
|
||||
|
||||
valid = g_utf8_validate (str, len, &end);
|
||||
|
||||
nm_assert ( end
|
||||
&& end >= str
|
||||
&& end <= &str[len]);
|
||||
|
||||
if (end > str) {
|
||||
const char *s;
|
||||
|
||||
for (s = str; s < end; s++) {
|
||||
nm_assert (s[0] != '\0');
|
||||
|
||||
if (s[0] < 0x20) {
|
||||
const char *text;
|
||||
|
||||
switch (s[0]) {
|
||||
case '\\': text = "\\\\"; break;
|
||||
case '\"': text = "\\\""; break;
|
||||
case '\b': text = "\\b"; break;
|
||||
case '\f': text = "\\f"; break;
|
||||
case '\n': text = "\\n"; break;
|
||||
case '\r': text = "\\r"; break;
|
||||
case '\t': text = "\\t"; break;
|
||||
default:
|
||||
g_string_append_printf (gstr, "\\u%04X", (guint) s[0]);
|
||||
continue;
|
||||
}
|
||||
g_string_append (gstr, text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NM_IN_SET (s[0], '\\', '\"'))
|
||||
g_string_append_c (gstr, '\\');
|
||||
g_string_append_c (gstr, s[0]);
|
||||
}
|
||||
} else
|
||||
nm_assert (!valid);
|
||||
|
||||
if (valid) {
|
||||
nm_assert (end == &str[len]);
|
||||
break;
|
||||
}
|
||||
|
||||
nm_assert (end < &str[len]);
|
||||
|
||||
if (end[0] == '\0') {
|
||||
/* there is a NUL byte in the string. Technically this is valid UTF-8, so we
|
||||
* encode it there. However, this will likely result in a truncated string when
|
||||
* parsing. */
|
||||
g_string_append (gstr, "\\u0000");
|
||||
} else {
|
||||
/* the character is not valid UTF-8. There is nothing we can do about it, because
|
||||
* JSON can only contain UTF-8 and even the escape sequences can only escape Unicode
|
||||
* codepoints (but not binary).
|
||||
*
|
||||
* The argument is not a a string (in any known encoding), hence we cannot represent
|
||||
* it as a JSON string (which are unicode strings).
|
||||
*
|
||||
* Print an underscore instead of the invalid char :) */
|
||||
g_string_append_c (gstr, '_');
|
||||
}
|
||||
|
||||
n = str - end;
|
||||
nm_assert (n < len);
|
||||
n++;
|
||||
str += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
g_string_append_c (gstr, '\"');
|
||||
}
|
||||
|
||||
void
|
||||
nm_json_aux_gstr_append_string_len (GString *gstr,
|
||||
const char *str,
|
||||
gsize n)
|
||||
{
|
||||
g_return_if_fail (gstr);
|
||||
|
||||
_gstr_append_string_len (gstr, str, n);
|
||||
}
|
||||
|
||||
void
|
||||
nm_json_aux_gstr_append_string (GString *gstr,
|
||||
const char *str)
|
||||
{
|
||||
g_return_if_fail (gstr);
|
||||
|
||||
if (!str)
|
||||
g_string_append (gstr, "null");
|
||||
else
|
||||
_gstr_append_string_len (gstr, str, strlen (str));
|
||||
}
|
||||
|
||||
void
|
||||
nm_json_aux_gstr_append_obj_name (GString *gstr,
|
||||
const char *key,
|
||||
char start_container)
|
||||
{
|
||||
g_return_if_fail (gstr);
|
||||
g_return_if_fail (key);
|
||||
|
||||
nm_json_aux_gstr_append_string (gstr, key);
|
||||
|
||||
if (start_container != '\0') {
|
||||
nm_assert (NM_IN_SET (start_container, '[', '{'));
|
||||
g_string_append_printf (gstr, ": %c ", start_container);
|
||||
} else
|
||||
g_string_append (gstr, ": ");
|
||||
}
|
||||
83
shared/nm-glib-aux/nm-json-aux.h
Normal file
83
shared/nm-glib-aux/nm-json-aux.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_JSON_AUX_H__
|
||||
#define __NM_JSON_AUX_H__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline GString *
|
||||
nm_json_aux_gstr_append_delimiter (GString *gstr)
|
||||
{
|
||||
g_string_append (gstr, ", ");
|
||||
return gstr;
|
||||
}
|
||||
|
||||
void nm_json_aux_gstr_append_string_len (GString *gstr,
|
||||
const char *str,
|
||||
gsize n);
|
||||
|
||||
void nm_json_aux_gstr_append_string (GString *gstr,
|
||||
const char *str);
|
||||
|
||||
static inline void
|
||||
nm_json_aux_gstr_append_bool (GString *gstr,
|
||||
gboolean v)
|
||||
{
|
||||
g_string_append (gstr, v ? "true" : "false");
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_json_aux_gstr_append_int64 (GString *gstr,
|
||||
gint64 v)
|
||||
{
|
||||
g_string_append_printf (gstr, "%"G_GINT64_FORMAT, v);
|
||||
}
|
||||
|
||||
void nm_json_aux_gstr_append_obj_name (GString *gstr,
|
||||
const char *key,
|
||||
char start_container);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
|
||||
#include "nm-value-type.h"
|
||||
static inline void
|
||||
nm_value_type_to_json (NMValueType value_type,
|
||||
GString *gstr,
|
||||
gconstpointer p_field)
|
||||
{
|
||||
nm_assert (p_field);
|
||||
nm_assert (gstr);
|
||||
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: nm_json_aux_gstr_append_bool (gstr, *((const bool *) p_field)); return;
|
||||
case NM_VALUE_TYPE_INT32: nm_json_aux_gstr_append_int64 (gstr, *((const gint32 *) p_field)); return;
|
||||
case NM_VALUE_TYPE_INT: nm_json_aux_gstr_append_int64 (gstr, *((const int *) p_field)); return;
|
||||
case NM_VALUE_TYPE_STRING: nm_json_aux_gstr_append_string (gstr, *((const char *const *) p_field)); return;
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_JSON_AUX_H__ */
|
||||
|
|
@ -865,6 +865,28 @@ fcn (void) \
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_strcmp0 (const char *s1, const char *s2)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* like g_strcmp0(), but this is inlinable.
|
||||
*
|
||||
* Also, it is guaranteed to return either -1, 0, or 1. */
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
if (!s1)
|
||||
return -1;
|
||||
if (!s2)
|
||||
return 1;
|
||||
c = strcmp (s1, s2);
|
||||
if (c < 0)
|
||||
return -1;
|
||||
if (c > 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nm_streq (const char *s1, const char *s2)
|
||||
{
|
||||
|
|
@ -989,10 +1011,9 @@ typedef enum { \
|
|||
} _PropertyEnums; \
|
||||
static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, }
|
||||
|
||||
#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \
|
||||
#define NM_GOBJECT_PROPERTIES_DEFINE_NOTIFY(obj_type, obj_properties, property_enums_type, prop_0) \
|
||||
static inline void \
|
||||
_nm_gobject_notify_together_impl (obj_type *obj, guint n, const _PropertyEnums *props) \
|
||||
_nm_gobject_notify_together_impl (obj_type *obj, guint n, const property_enums_type *props) \
|
||||
{ \
|
||||
const gboolean freeze_thaw = (n > 1); \
|
||||
\
|
||||
|
|
@ -1002,9 +1023,9 @@ _nm_gobject_notify_together_impl (obj_type *obj, guint n, const _PropertyEnums *
|
|||
if (freeze_thaw) \
|
||||
g_object_freeze_notify ((GObject *) obj); \
|
||||
while (n-- > 0) { \
|
||||
const _PropertyEnums prop = *props++; \
|
||||
const property_enums_type prop = *props++; \
|
||||
\
|
||||
if (prop != PROP_0) { \
|
||||
if (prop != prop_0) { \
|
||||
nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \
|
||||
nm_assert (obj_properties[prop]); \
|
||||
g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \
|
||||
|
|
@ -1015,11 +1036,15 @@ _nm_gobject_notify_together_impl (obj_type *obj, guint n, const _PropertyEnums *
|
|||
} \
|
||||
\
|
||||
static inline void \
|
||||
_notify (obj_type *obj, _PropertyEnums prop) \
|
||||
_notify (obj_type *obj, property_enums_type prop) \
|
||||
{ \
|
||||
_nm_gobject_notify_together_impl (obj, 1, &prop); \
|
||||
} \
|
||||
|
||||
#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_NOTIFY (obj_type, obj_properties, _PropertyEnums, PROP_0)
|
||||
|
||||
/* invokes _notify() for all arguments (of type _PropertyEnums). Note, that if
|
||||
* there are more than one prop arguments, this will involve a freeze/thaw
|
||||
* of GObject property notifications. */
|
||||
|
|
|
|||
|
|
@ -2288,7 +2288,7 @@ nm_utils_strv_make_deep_copied (const char **strv)
|
|||
{
|
||||
gsize i;
|
||||
|
||||
/* it takes a strv dictionary, and copies each
|
||||
/* it takes a strv list, and copies each
|
||||
* strings. Note that this updates @strv *in-place*
|
||||
* and returns it. */
|
||||
|
||||
|
|
@ -2300,6 +2300,23 @@ nm_utils_strv_make_deep_copied (const char **strv)
|
|||
return (char **) strv;
|
||||
}
|
||||
|
||||
char **
|
||||
nm_utils_strv_make_deep_copied_n (const char **strv, gsize len)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
/* it takes a strv array with len elements, and copies each
|
||||
* strings. Note that this updates @strv *in-place*
|
||||
* and returns it. */
|
||||
|
||||
if (!strv)
|
||||
return NULL;
|
||||
for (i = 0; i < len; i++)
|
||||
strv[i] = g_strdup (strv[i]);
|
||||
|
||||
return (char **) strv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gssize
|
||||
|
|
@ -3029,3 +3046,64 @@ fail:
|
|||
NM_SET_OUT (out_len, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GVariant *
|
||||
nm_utils_gvariant_vardict_filter (GVariant *src,
|
||||
gboolean (*filter_fcn) (const char *key,
|
||||
GVariant *val,
|
||||
char **out_key,
|
||||
GVariant **out_val,
|
||||
gpointer user_data),
|
||||
gpointer user_data)
|
||||
{
|
||||
GVariantIter iter;
|
||||
GVariantBuilder builder;
|
||||
const char *key;
|
||||
GVariant *val;
|
||||
|
||||
g_return_val_if_fail (src && g_variant_is_of_type (src, G_VARIANT_TYPE_VARDICT), NULL);
|
||||
g_return_val_if_fail (filter_fcn, NULL);
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
||||
|
||||
g_variant_iter_init (&iter, src);
|
||||
while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
|
||||
_nm_unused gs_unref_variant GVariant *val_free = val;
|
||||
gs_free char *key2 = NULL;
|
||||
gs_unref_variant GVariant *val2 = NULL;
|
||||
|
||||
if (filter_fcn (key,
|
||||
val,
|
||||
&key2,
|
||||
&val2,
|
||||
user_data)) {
|
||||
g_variant_builder_add (&builder,
|
||||
"{sv}",
|
||||
key2 ?: key,
|
||||
val2 ?: val);
|
||||
}
|
||||
}
|
||||
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gvariant_vardict_filter_drop_one (const char *key,
|
||||
GVariant *val,
|
||||
char **out_key,
|
||||
GVariant **out_val,
|
||||
gpointer user_data)
|
||||
{
|
||||
return !nm_streq (key, user_data);
|
||||
}
|
||||
|
||||
GVariant *
|
||||
nm_utils_gvariant_vardict_filter_drop_one (GVariant *src,
|
||||
const char *key)
|
||||
{
|
||||
return nm_utils_gvariant_vardict_filter (src,
|
||||
_gvariant_vardict_filter_drop_one,
|
||||
(gpointer) key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,6 +171,13 @@ nm_ip4_addr_is_localhost (in_addr_t addr4)
|
|||
return _cc < 0 ? -1 : 1; \
|
||||
} G_STMT_END
|
||||
|
||||
#define NM_CMP_RETURN_DIRECT(c) \
|
||||
G_STMT_START { \
|
||||
const int _cc = (c); \
|
||||
if (_cc) \
|
||||
return _cc; \
|
||||
} G_STMT_END
|
||||
|
||||
#define NM_CMP_SELF(a, b) \
|
||||
G_STMT_START { \
|
||||
typeof (a) _a = (a); \
|
||||
|
|
@ -197,7 +204,7 @@ nm_ip4_addr_is_localhost (in_addr_t addr4)
|
|||
NM_CMP_RETURN (memcmp ((a), (b), (size)))
|
||||
|
||||
#define NM_CMP_DIRECT_STRCMP0(a, b) \
|
||||
NM_CMP_RETURN (g_strcmp0 ((a), (b)))
|
||||
NM_CMP_RETURN_DIRECT (nm_strcmp0 ((a), (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_IN6ADDR(a, b) \
|
||||
G_STMT_START { \
|
||||
|
|
@ -229,12 +236,12 @@ nm_ip4_addr_is_localhost (in_addr_t addr4)
|
|||
const char *_b = ((b)->field); \
|
||||
\
|
||||
if (_a != _b) { \
|
||||
NM_CMP_RETURN (g_strcmp0 (_a, _b)); \
|
||||
NM_CMP_RETURN_DIRECT (nm_strcmp0 (_a, _b)); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
#define NM_CMP_FIELD_STR0(a, b, field) \
|
||||
NM_CMP_RETURN (g_strcmp0 (((a)->field), ((b)->field)))
|
||||
NM_CMP_RETURN_DIRECT (nm_strcmp0 (((a)->field), ((b)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
|
||||
NM_CMP_RETURN (memcmp (&((a)->field), &((b)->field), \
|
||||
|
|
@ -305,6 +312,20 @@ GVariant *nm_utils_gbytes_to_variant_ay (GBytes *bytes);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
GVariant *nm_utils_gvariant_vardict_filter (GVariant *src,
|
||||
gboolean (*filter_fcn) (const char *key,
|
||||
GVariant *val,
|
||||
char **out_key,
|
||||
GVariant **out_val,
|
||||
gpointer user_data),
|
||||
gpointer user_data);
|
||||
|
||||
GVariant *
|
||||
nm_utils_gvariant_vardict_filter_drop_one (GVariant *src,
|
||||
const char *key);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_utils_hexchar_to_int (char ch)
|
||||
{
|
||||
|
|
@ -944,6 +965,8 @@ nm_utils_strdict_get_keys (const GHashTable *hash,
|
|||
|
||||
char **nm_utils_strv_make_deep_copied (const char **strv);
|
||||
|
||||
char **nm_utils_strv_make_deep_copied_n (const char **strv, gsize len);
|
||||
|
||||
static inline char **
|
||||
nm_utils_strv_make_deep_copied_nonnull (const char **strv)
|
||||
{
|
||||
|
|
|
|||
206
shared/nm-glib-aux/nm-value-type.h
Normal file
206
shared/nm-glib-aux/nm-value-type.h
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_VALUE_TYPE_H__
|
||||
#define __NM_VALUE_TYPE_H__
|
||||
|
||||
typedef enum {
|
||||
NM_VALUE_TYPE_UNSPEC = 1,
|
||||
NM_VALUE_TYPE_BOOL = 2,
|
||||
NM_VALUE_TYPE_INT32 = 3,
|
||||
NM_VALUE_TYPE_INT = 4,
|
||||
NM_VALUE_TYPE_STRING = 5,
|
||||
} NMValueType;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
|
||||
|
||||
typedef union {
|
||||
bool v_bool;
|
||||
gint32 v_int32;
|
||||
int v_int;
|
||||
const char *v_string;
|
||||
|
||||
/* for convenience, also let the union contain other pointer types. These are
|
||||
* for NM_VALUE_TYPE_UNSPEC. */
|
||||
gconstpointer *v_ptr;
|
||||
const GPtrArray *v_ptrarray;
|
||||
|
||||
} NMValueTypUnion;
|
||||
|
||||
/* Set the NMValueTypUnion. You can also assign the member directly.
|
||||
* The only purpose of this is that it also returns a pointer to the
|
||||
* union. So, you can do
|
||||
*
|
||||
* ptr = NM_VALUE_TYP_UNION_SET (&value_typ_union_storage, v_bool, TRUE);
|
||||
*/
|
||||
#define NM_VALUE_TYP_UNION_SET(_arg, _type, _val) \
|
||||
({ \
|
||||
NMValueTypUnion *const _arg2 = (_arg); \
|
||||
\
|
||||
*_arg2 = (NMValueTypUnion) { \
|
||||
._type = (_val), \
|
||||
}; \
|
||||
_arg2; \
|
||||
})
|
||||
|
||||
typedef struct {
|
||||
bool has;
|
||||
NMValueTypUnion val;
|
||||
} NMValueTypUnioMaybe;
|
||||
|
||||
#define NM_VALUE_TYP_UNIO_MAYBE_SET(_arg, _type, _val) \
|
||||
({ \
|
||||
NMValueTypUnioMaybe *const _arg2 = (_arg); \
|
||||
\
|
||||
*_arg2 = (NMValueTypUnioMaybe) { \
|
||||
.has = TRUE, \
|
||||
.val._type = (_val), \
|
||||
}; \
|
||||
_arg2; \
|
||||
})
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_value_type_cmp (NMValueType value_type,
|
||||
gconstpointer p_a,
|
||||
gconstpointer p_b)
|
||||
{
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: NM_CMP_DIRECT (*((const bool *) p_a), *((const bool *) p_b)); return 0;
|
||||
case NM_VALUE_TYPE_INT32: NM_CMP_DIRECT (*((const gint32 *) p_a), *((const gint32 *) p_b)); return 0;
|
||||
case NM_VALUE_TYPE_INT: NM_CMP_DIRECT (*((const int *) p_a), *((const int *) p_b)); return 0;
|
||||
case NM_VALUE_TYPE_STRING: return nm_strcmp0 (*((const char *const*) p_a), *((const char *const*) p_b));
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nm_value_type_equal (NMValueType value_type,
|
||||
gconstpointer p_a,
|
||||
gconstpointer p_b)
|
||||
{
|
||||
return nm_value_type_cmp (value_type, p_a, p_b) == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_value_type_copy (NMValueType value_type,
|
||||
gpointer dst,
|
||||
gconstpointer src)
|
||||
{
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: (*((bool *) dst) = *((const bool *) src)); return;
|
||||
case NM_VALUE_TYPE_INT32: (*((gint32 *) dst) = *((const gint32 *) src)); return;
|
||||
case NM_VALUE_TYPE_INT: (*((int *) dst) = *((const int *) src)); return;
|
||||
case NM_VALUE_TYPE_STRING:
|
||||
/* self assignment safe! */
|
||||
if (*((char **) dst) != *((const char *const*) src)) {
|
||||
g_free (*((char **) dst));
|
||||
*((char **) dst) = g_strdup (*((const char *const*) src));
|
||||
}
|
||||
return;
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_value_type_get_from_variant (NMValueType value_type,
|
||||
gpointer dst,
|
||||
GVariant *variant,
|
||||
gboolean clone)
|
||||
{
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: *((bool *) dst) = g_variant_get_boolean (variant); return;
|
||||
case NM_VALUE_TYPE_INT32: *((gint32 *) dst) = g_variant_get_int32 (variant); return;
|
||||
case NM_VALUE_TYPE_STRING:
|
||||
if (clone) {
|
||||
g_free (*((char **) dst));
|
||||
*((char **) dst) = g_variant_dup_string (variant, NULL);
|
||||
} else {
|
||||
/* we don't clone the string, nor free the previous value. */
|
||||
*((const char **) dst) = g_variant_get_string (variant, NULL);
|
||||
}
|
||||
return;
|
||||
|
||||
case NM_VALUE_TYPE_INT:
|
||||
/* "int" also does not have a define variant type, because it's not
|
||||
* clear how many bits we would need. */
|
||||
|
||||
/* fall-through */
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
||||
static inline GVariant *
|
||||
nm_value_type_to_variant (NMValueType value_type,
|
||||
gconstpointer src)
|
||||
{
|
||||
const char *v_string;
|
||||
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: return g_variant_new_boolean (*((const bool *) src));
|
||||
case NM_VALUE_TYPE_INT32: return g_variant_new_int32 (*((const gint32 *) src));;
|
||||
case NM_VALUE_TYPE_STRING:
|
||||
v_string = *((const char *const*) src);
|
||||
return v_string ? g_variant_new_string (v_string) : NULL;
|
||||
|
||||
case NM_VALUE_TYPE_INT:
|
||||
/* "int" also does not have a define variant type, because it's not
|
||||
* clear how many bits we would need. */
|
||||
|
||||
/* fall-through */
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
||||
static inline const GVariantType *
|
||||
nm_value_type_get_variant_type (NMValueType value_type)
|
||||
{
|
||||
switch (value_type) {
|
||||
case NM_VALUE_TYPE_BOOL: return G_VARIANT_TYPE_BOOLEAN;
|
||||
case NM_VALUE_TYPE_INT32: return G_VARIANT_TYPE_INT32;
|
||||
case NM_VALUE_TYPE_STRING: return G_VARIANT_TYPE_STRING;
|
||||
|
||||
case NM_VALUE_TYPE_INT:
|
||||
/* "int" also does not have a define variant type, because it's not
|
||||
* clear how many bits we would need. */
|
||||
|
||||
/* fall-through */
|
||||
case NM_VALUE_TYPE_UNSPEC:
|
||||
break;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* NM_VALUE_TYPE_DEFINE_FUNCTIONS */
|
||||
|
||||
#endif /* __NM_VALUE_TYPE_H__ */
|
||||
|
|
@ -45,9 +45,9 @@ typedef struct {
|
|||
NMTeamLinkWatcherType watcher_type;
|
||||
KeyType key_type;
|
||||
union {
|
||||
int (*fint) (NMTeamLinkWatcher *watcher);
|
||||
gboolean (*fbool) (NMTeamLinkWatcher *watcher);
|
||||
const char *(*fstring) (NMTeamLinkWatcher *watcher);
|
||||
int (*fint) (const NMTeamLinkWatcher *watcher);
|
||||
gboolean (*fbool) (const NMTeamLinkWatcher *watcher);
|
||||
const char *(*fstring) (const NMTeamLinkWatcher *watcher);
|
||||
} get_fcn;
|
||||
union {
|
||||
int vint;
|
||||
|
|
@ -56,19 +56,19 @@ typedef struct {
|
|||
} TeamLinkWatcherKeyInfo;
|
||||
|
||||
static gboolean
|
||||
_team_link_watcher_validate_active (NMTeamLinkWatcher *watcher)
|
||||
_team_link_watcher_validate_active (const NMTeamLinkWatcher *watcher)
|
||||
{
|
||||
return NM_FLAGS_HAS (nm_team_link_watcher_get_flags (watcher), NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_team_link_watcher_validate_inactive (NMTeamLinkWatcher *watcher)
|
||||
_team_link_watcher_validate_inactive (const NMTeamLinkWatcher *watcher)
|
||||
{
|
||||
return NM_FLAGS_HAS (nm_team_link_watcher_get_flags (watcher), NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_team_link_watcher_send_always (NMTeamLinkWatcher *watcher)
|
||||
_team_link_watcher_send_always (const NMTeamLinkWatcher *watcher)
|
||||
{
|
||||
return NM_FLAGS_HAS (nm_team_link_watcher_get_flags (watcher), NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS);
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ _parse_data_get_bool (const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KE
|
|||
}
|
||||
|
||||
char *
|
||||
nm_utils_team_link_watcher_to_string (NMTeamLinkWatcher *watcher)
|
||||
nm_utils_team_link_watcher_to_string (const NMTeamLinkWatcher *watcher)
|
||||
{
|
||||
nm_auto_free_gstring GString *str = NULL;
|
||||
const char *name;
|
||||
|
|
@ -348,12 +348,12 @@ nm_utils_team_link_watcher_from_string (const char *str,
|
|||
}
|
||||
|
||||
#if NM_MORE_ASSERTS > 5
|
||||
{
|
||||
if (watcher) {
|
||||
gs_free char *str2 = NULL;
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = NULL;
|
||||
static _nm_thread_local int recursive;
|
||||
|
||||
nm_assert (watcher);
|
||||
nm_assert (!error || !*error);
|
||||
if (recursive == 0) {
|
||||
recursive = 1;
|
||||
str2 = nm_utils_team_link_watcher_to_string (watcher);
|
||||
|
|
@ -365,7 +365,8 @@ nm_utils_team_link_watcher_from_string (const char *str,
|
|||
nm_assert (recursive == 1);
|
||||
recursive = 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
nm_assert (!error || *error);
|
||||
#endif
|
||||
|
||||
return watcher;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ typedef enum {
|
|||
_NM_TEAM_LINK_WATCHER_KEY_NUM,
|
||||
} NMTeamLinkWatcherKeyId;
|
||||
|
||||
char *nm_utils_team_link_watcher_to_string (NMTeamLinkWatcher *watcher);
|
||||
char *nm_utils_team_link_watcher_to_string (const NMTeamLinkWatcher *watcher);
|
||||
|
||||
NMTeamLinkWatcher *nm_utils_team_link_watcher_from_string (const char *str,
|
||||
GError **error);
|
||||
|
|
|
|||
|
|
@ -1927,6 +1927,69 @@ nmtst_assert_setting_verify_fails (NMSetting *setting,
|
|||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nmtst_assert_setting_is_equal (gconstpointer /* const NMSetting * */ a,
|
||||
gconstpointer /* const NMSetting * */ b,
|
||||
NMSettingCompareFlags flags)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *hash = NULL;
|
||||
guint32 r = nmtst_get_rand_int ();
|
||||
|
||||
g_assert (NM_IS_SETTING (a));
|
||||
g_assert (NM_IS_SETTING (b));
|
||||
|
||||
if (NM_FLAGS_HAS (r, 0x4))
|
||||
NMTST_SWAP (a, b);
|
||||
|
||||
g_assert (nm_setting_compare ((NMSetting *) a,
|
||||
(NMSetting *) b,
|
||||
flags));
|
||||
|
||||
if (NM_FLAGS_HAS (r, 0x8))
|
||||
NMTST_SWAP (a, b);
|
||||
|
||||
g_assert (nm_setting_diff ((NMSetting *) a,
|
||||
(NMSetting *) b,
|
||||
flags,
|
||||
NM_FLAGS_HAS (r, 0x1),
|
||||
&hash));
|
||||
g_assert (!hash);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NM_SETTING_PRIVATE_H__
|
||||
static inline NMSetting *
|
||||
nmtst_assert_setting_dbus_new (GType gtype, GVariant *variant)
|
||||
{
|
||||
NMSetting *setting;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
g_assert (g_type_is_a (gtype, NM_TYPE_SETTING));
|
||||
g_assert (gtype != NM_TYPE_SETTING);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, NM_VARIANT_TYPE_SETTING));
|
||||
|
||||
setting = _nm_setting_new_from_dbus (gtype,
|
||||
variant,
|
||||
NULL,
|
||||
NM_SETTING_PARSE_FLAGS_STRICT,
|
||||
&error);
|
||||
nmtst_assert_success (setting, error);
|
||||
return setting;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nmtst_assert_setting_dbus_roundtrip (gconstpointer /* const NMSetting * */ setting)
|
||||
{
|
||||
gs_unref_object NMSetting *setting2 = NULL;
|
||||
gs_unref_variant GVariant *variant = NULL;
|
||||
|
||||
g_assert (NM_IS_SETTING (setting));
|
||||
|
||||
variant = _nm_setting_to_dbus ((NMSetting *) setting, NULL, NM_CONNECTION_SERIALIZE_ALL);
|
||||
setting2 = nmtst_assert_setting_dbus_new (G_OBJECT_TYPE (setting), variant);
|
||||
nmtst_assert_setting_is_equal (setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NM_UTILS_H__
|
||||
|
|
@ -2140,6 +2203,25 @@ typedef enum {
|
|||
|
||||
#endif /* __NM_CONNECTION_H__ */
|
||||
|
||||
static inline GVariant *
|
||||
nmtst_variant_from_string (const GVariantType *variant_type,
|
||||
const char *variant_str)
|
||||
{
|
||||
GVariant *variant;
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert (variant_type);
|
||||
g_assert (variant_str);
|
||||
|
||||
variant = g_variant_parse (variant_type,
|
||||
variant_str,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
nmtst_assert_success (variant, error);
|
||||
return variant;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline void
|
||||
|
|
|
|||
|
|
@ -4862,62 +4862,27 @@ bond_connection_from_ifcfg (const char *file,
|
|||
return connection;
|
||||
}
|
||||
|
||||
/* Check 'error' for errors. Missing config (NULL return value) is a valid case. */
|
||||
static char *
|
||||
read_team_config (shvarFile *ifcfg, const char *key, GError **error)
|
||||
{
|
||||
gs_free_error GError *local_error = NULL;
|
||||
gs_free char *value = NULL;
|
||||
size_t l;
|
||||
|
||||
value = svGetValueStr_cp (ifcfg, key);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
l = strlen (value);
|
||||
if (l > 1*1024*1024) {
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"%s too long (size %zd)", key, l);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!nm_utils_is_json_object (value, &local_error)) {
|
||||
PARSE_WARNING ("ignoring invalid team configuration: %s", local_error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_steal_pointer (&value);
|
||||
}
|
||||
|
||||
static NMSetting *
|
||||
make_team_setting (shvarFile *ifcfg,
|
||||
const char *file,
|
||||
GError **error)
|
||||
{
|
||||
NMSettingTeam *s_team;
|
||||
char *value;
|
||||
GError *local_err = NULL;
|
||||
NMSetting *s_team;
|
||||
gs_free char *value_device = NULL;
|
||||
gs_free char *value = NULL;
|
||||
|
||||
value = svGetValueStr_cp (ifcfg, "DEVICE");
|
||||
if (!value) {
|
||||
if (!svGetValueStr (ifcfg, "DEVICE", &value_device)) {
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"mandatory DEVICE keyword missing");
|
||||
return NULL;
|
||||
}
|
||||
g_free (value);
|
||||
|
||||
value = read_team_config (ifcfg, "TEAM_CONFIG", &local_err);
|
||||
if (local_err) {
|
||||
g_propagate_error (error, local_err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s_team = NM_SETTING_TEAM (nm_setting_team_new ());
|
||||
|
||||
g_object_set (s_team, NM_SETTING_TEAM_CONFIG, value, NULL);
|
||||
g_free (value);
|
||||
|
||||
return (NMSetting *) s_team;
|
||||
s_team = nm_setting_team_new ();
|
||||
g_object_set (s_team,
|
||||
NM_SETTING_TEAM_CONFIG,
|
||||
svGetValue (ifcfg, "TEAM_CONFIG", &value),
|
||||
NULL);
|
||||
return s_team;
|
||||
}
|
||||
|
||||
static NMConnection *
|
||||
|
|
@ -5276,20 +5241,18 @@ make_bridge_port_setting (shvarFile *ifcfg)
|
|||
static NMSetting *
|
||||
make_team_port_setting (shvarFile *ifcfg)
|
||||
{
|
||||
NMSetting *s_port = NULL;
|
||||
char *value;
|
||||
GError *error = NULL;
|
||||
NMSetting *s_port;
|
||||
gs_free char *value = NULL;
|
||||
|
||||
value = read_team_config (ifcfg, "TEAM_PORT_CONFIG", &error);
|
||||
if (value) {
|
||||
s_port = nm_setting_team_port_new ();
|
||||
g_object_set (s_port, NM_SETTING_TEAM_PORT_CONFIG, value, NULL);
|
||||
g_free (value);
|
||||
} else if (error) {
|
||||
PARSE_WARNING ("%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
value = svGetValueStr_cp (ifcfg, "TEAM_PORT_CONFIG");
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
s_port = nm_setting_team_port_new ();
|
||||
g_object_set (s_port,
|
||||
NM_SETTING_TEAM_PORT_CONFIG,
|
||||
value,
|
||||
NULL);
|
||||
return s_port;
|
||||
}
|
||||
|
||||
|
|
@ -5902,12 +5865,10 @@ connection_from_file_full (const char *filename,
|
|||
if (s_match)
|
||||
nm_connection_add_setting (connection, s_match);
|
||||
|
||||
/* Bridge port? */
|
||||
s_port = make_bridge_port_setting (main_ifcfg);
|
||||
if (s_port)
|
||||
nm_connection_add_setting (connection, s_port);
|
||||
|
||||
/* Team port? */
|
||||
s_port = make_team_port_setting (main_ifcfg);
|
||||
if (s_port)
|
||||
nm_connection_add_setting (connection, s_port);
|
||||
|
|
|
|||
|
|
@ -8938,25 +8938,16 @@ static void
|
|||
test_read_team_master_invalid (gconstpointer user_data)
|
||||
{
|
||||
const char *const PATH_NAME = user_data;
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingTeam *s_team;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_object NMConnection *connection = NULL;
|
||||
|
||||
NMTST_EXPECT_NM_WARN ("*ignoring invalid team configuration*");
|
||||
connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL);
|
||||
g_test_assert_expected_messages ();
|
||||
if (WITH_JSON_VALIDATION) {
|
||||
_connection_from_file_fail (PATH_NAME, NULL, TYPE_ETHERNET, &error);
|
||||
|
||||
g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "team0");
|
||||
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
g_assert (s_con);
|
||||
g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_TEAM_SETTING_NAME);
|
||||
|
||||
s_team = nm_connection_get_setting_team (connection);
|
||||
g_assert (s_team);
|
||||
g_assert (nm_setting_team_get_config (s_team) == NULL);
|
||||
|
||||
g_object_unref (connection);
|
||||
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
||||
g_assert (strstr (error->message, _("invalid json")));
|
||||
} else
|
||||
connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue