2019-05-06 12:11:23 +02:00
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
|
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
2019-05-06 12:36:41 +02:00
|
|
|
#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);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2019-05-22 18:56:09 +02:00
|
|
|
GPtrArray *_nm_utils_team_link_watchers_from_variant (GVariant *value,
|
|
|
|
|
gboolean strict_parsing,
|
|
|
|
|
GError **error);
|
2019-05-22 16:27:28 +02:00
|
|
|
GVariant *_nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
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
2019-05-06 12:36:41 +02:00
|
|
|
gboolean nm_team_setting_maybe_changed (struct _NMSetting *source,
|
|
|
|
|
const GParamSpec *const*obj_properties,
|
|
|
|
|
guint32 changed);
|
|
|
|
|
|
2019-05-06 12:11:23 +02:00
|
|
|
#endif /* __NM_TEAM_UITLS_H__ */
|