mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-03 12:30:32 +01:00
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and NMSettingTeamPort. - team handling was added as rh#1398925. The goal is to have a more convenient way to set properties than constructing JSON. This requires libnm to implement the hard task of parsing JSON (and exposing well-understood properties) and generating JSON (based on these "artificial" properties). But not only libnm. In particular nmcli and the D-Bus API must make this "simpler" API accessible. - since NMSettingTeam and NMSettingTeamPort are conceptually the same, add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to handle the similar code side-by-sdie. The setting classes now just delegate for everything to NMTeamSetting. - Previously, there was a very fuzzy understanding of the provided JSON config. Tighten that up, when setting a JSON config it regenerates/parses all other properties and tries to make the best of it. When modifying any abstraction property, the entire JSON config gets regenerated. In particular, don't try to merge existing JSON config with the new fields. If the user uses the abstraction API, then the entire JSON gets replaced. For example note that nm_setting_team_add_link_watcher() would not be reflected in the JSON config (a bug). That only accidentally worked because client would serializing the changed link watcher to GVariant/D-Bus, then NetworkManager would set it via g_object_set(), which would renerate the JSON, and finally persist it to disk. But as far as libnm is concerned, nm_setting_team_add_link_watcher() would bring the settings instance in an inconsistent state where JSON and the link watcher property disagree. Setting any property must immediately update both the JSON and the abstraction API. - when constucting a team setting from D-Bus, we would previously parse both "config" and abstraction properties. That is wrong. Since our settings plugins only support JSON, all information must be present in the JSON config anyway. So, when "config" is present, only the JSON must be parsed. In the best case, the other information is redudant and contributes nothing. In the worse case, they information differs (which might happen if the client version differs from the server version). As the settings plugin only supports JSON, it's wrong to consider redundant, differing information from D-Bus. - we now only convert string to JSON or back when needed. Previously, setting a property resulted in parsing several JSON multiple times (per property). All operations should now scale well and be reasonably efficient. - also the property-changed signals are now handled correctly. Since NMTeamSetting knows the current state of all attributes, it can emit the exact property changed signals for what changed. - we no longer use libjansson to generate the JSON. JSON is supposed to be a machine readable exchange format, hence a major goal is to be easily handled by applications. While parsing JSON is not so trivial, writing a well-known set of values to JSON is. The advantage is that when you build libnm without libjansson support, then we still can convert the artificial properties to JSON. - Requiring libjansson in libnm is a burden, because most of the time it is not needed (as most users don't create team configurations). With this change we only require it to parse the team settings (no longer to write them). It should be reasonably simple to use a more minimalistic JSON parser that is sufficient for us, so that we can get rid of the libjansson dependency (for libnm). This also avoids the pain that we have due to the symbol collision of libjansson and libjson-glib. https://bugzilla.redhat.com/show_bug.cgi?id=1691619
This commit is contained in:
parent
539dfbcc42
commit
13f6f3a410
13 changed files with 2726 additions and 1581 deletions
|
|
@ -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.")
|
||||
|
|
|
|||
|
|
@ -547,19 +547,6 @@ gboolean nm_team_link_watchers_equal (const GPtrArray *a,
|
|||
const GPtrArray *b,
|
||||
gboolean ignore_order);
|
||||
|
||||
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);
|
||||
|
||||
gboolean _nm_utils_team_config_set (char **conf,
|
||||
const char *key,
|
||||
const char *key2,
|
||||
const char *key3,
|
||||
const GValue *value);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
guint32 _nm_utils_parse_tc_handle (const char *str,
|
||||
|
|
|
|||
|
|
@ -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_ref (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 *
|
||||
|
|
@ -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,
|
||||
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,26 +437,25 @@ 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,
|
||||
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;
|
||||
|
|
@ -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_ref,
|
||||
(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
File diff suppressed because it is too large
Load diff
|
|
@ -24,4 +24,250 @@
|
|||
#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);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_team_setting_maybe_changed (struct _NMSetting *source,
|
||||
const GParamSpec *const*obj_properties,
|
||||
guint32 changed);
|
||||
|
||||
#endif /* __NM_TEAM_UITLS_H__ */
|
||||
|
|
|
|||
|
|
@ -131,116 +131,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_ref (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,36 +5445,8 @@ 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:
|
||||
|
|
|
|||
|
|
@ -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,19 +6808,42 @@ _team_config_equal_check (const char *conf1,
|
|||
gboolean port_config,
|
||||
gboolean 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);
|
||||
}
|
||||
|
||||
g_assert_cmpint (_nm_utils_team_config_equal (conf1, conf2, port_config), ==, expected);
|
||||
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,
|
||||
|
|
@ -6827,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 ("{ }",
|
||||
|
|
@ -6837,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,
|
||||
|
|
@ -6861,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 ("{ }",
|
||||
|
|
@ -6875,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,
|
||||
|
|
@ -6888,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
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -1378,9 +1378,64 @@ test_team_port_full_config (void)
|
|||
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
|
||||
|
|
@ -1393,11 +1448,6 @@ test_team_setting (void)
|
|||
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);
|
||||
|
||||
if (!WITH_JSON_VALIDATION) {
|
||||
g_test_skip ("disabled test without json-validation");
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (watcher1);
|
||||
g_assert (watcher2);
|
||||
|
||||
|
|
@ -1410,7 +1460,6 @@ test_team_setting (void)
|
|||
_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,
|
||||
|
|
@ -1420,19 +1469,36 @@ test_team_setting (void)
|
|||
|
||||
_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)), ==, "{\"link_watch\": {\"name\": \"ethtool\"}, \"runner\": {\"sys_prio\": 10}}");
|
||||
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_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{\"link_watch\": {\"name\": \"ethtool\"}, \"runner\": {\"sys_prio\": 10}}");
|
||||
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)), ==, "{\"link_watch\": {\"name\": \"ethtool\"}, \"runner\": {\"sys_prio\": 10}}");
|
||||
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)), ==, "{\"link_watch\": {\"name\": \"ethtool\"}, \"runner\": {\"sys_prio\": 10}}");
|
||||
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 } }");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -8939,11 +8939,15 @@ test_read_team_master_invalid (gconstpointer user_data)
|
|||
{
|
||||
const char *const PATH_NAME = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_object NMConnection *connection = NULL;
|
||||
|
||||
_connection_from_file_fail (PATH_NAME, NULL, TYPE_ETHERNET, &error);
|
||||
if (WITH_JSON_VALIDATION) {
|
||||
_connection_from_file_fail (PATH_NAME, NULL, TYPE_ETHERNET, &error);
|
||||
|
||||
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
||||
g_assert (strstr (error->message, "JSON"));
|
||||
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