diff options
Diffstat (limited to 'libnm-core/nm-setting-team-port.c')
| -rw-r--r-- | libnm-core/nm-setting-team-port.c | 471 |
1 files changed, 470 insertions, 1 deletions
diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index c0309665..5ab8f691 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -15,6 +15,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * + * Copyright 2017 Red Hat, Inc. * Copyright 2013 Jiri Pirko <jiri@resnulli.us> */ @@ -29,7 +30,6 @@ #include "nm-utils-private.h" #include "nm-connection-private.h" #include "nm-setting-connection.h" -#include "nm-setting-team.h" /** * SECTION:nm-setting-team-port @@ -47,14 +47,40 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM_PORT) typedef struct { char *config; + int queue_id; + int prio; + gboolean sticky; + int lacp_prio; + int lacp_key; + GPtrArray *link_watchers; /* Array of NMTeamLinkWatcher */ } NMSettingTeamPortPrivate; +/* Keep aligned with _prop_to_keys[] */ enum { PROP_0, PROP_CONFIG, + PROP_QUEUE_ID, + PROP_PRIO, + PROP_STICKY, + PROP_LACP_PRIO, + PROP_LACP_KEY, + PROP_LINK_WATCHERS, LAST_PROP }; +/* Keep aligned with team-port properties enum */ +static const _NMUtilsTeamPropertyKeys _prop_to_keys[LAST_PROP] = { + [PROP_0] = { NULL, NULL, NULL, 0 }, + [PROP_CONFIG] = { NULL, NULL, NULL, 0 }, + [PROP_QUEUE_ID] = { "queue_id", NULL, NULL, NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT }, + [PROP_PRIO] = { "prio", NULL, NULL, 0 }, + [PROP_STICKY] = { "sticky", NULL, NULL, 0 }, + [PROP_LACP_PRIO] = { "lacp_prio", NULL, NULL, NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT }, + [PROP_LACP_KEY] = { "lacp_key", NULL, NULL, 0 }, + [PROP_LINK_WATCHERS] = { "link_watch", NULL, NULL, 0 } +}; + + /** * nm_setting_team_port_new: * @@ -82,6 +108,239 @@ nm_setting_team_port_get_config (NMSettingTeamPort *setting) return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->config; } +/** + * nm_setting_team_port_get_queue_id: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:queue_id property of the setting + * + * Since: 1.10.2 + **/ +gint +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; +} + +/** + * nm_setting_team_port_get_prio: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:prio property of the setting + * + * Since: 1.10.2 + **/ +gint +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; +} + +/** + * nm_setting_team_port_get_sticky: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:sticky property of the setting + * + * Since: 1.10.2 + **/ +gboolean +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; +} + +/** + * nm_setting_team_port_get_lacp_prio: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:lacp-prio property of the setting + * + * Since: 1.10.2 + **/ +gint +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; +} + +/** + * nm_setting_team_port_get_lacp_key: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:lacp-key property of the setting + * + * Since: 1.10.2 + **/ +gint +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; +} + +/** + * nm_setting_team_port_get_num_link_watchers: + * @setting: the #NMSettingTeamPort + * + * Returns: the number of configured link watchers + * + * Since: 1.10.2 + **/ +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; +} + +/** + * nm_setting_team_port_get_link_watcher: + * @setting: the #NMSettingTeamPort + * @idx: index number of the link watcher to return + * + * Returns: (transfer none): the link watcher at index @idx. + * + * Since: 1.10.2 + **/ +NMTeamLinkWatcher * +nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx) +{ + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting); + + 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]; +} + +/** + * nm_setting_team_port_add_link_watcher: + * @setting: the #NMSettingTeamPort + * @link_watcher: the link watcher to add + * + * Appends a new link watcher to the setting. + * + * Returns: %TRUE if the link watcher is added; %FALSE if an identical link + * watcher was already there. + * + * Since: 1.10.2 + **/ +gboolean +nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting, + NMTeamLinkWatcher *link_watcher) +{ + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting); + guint i; + + g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), FALSE); + g_return_val_if_fail (link_watcher != NULL, FALSE); + + for (i = 0; i < priv->link_watchers->len; i++) { + if (nm_team_link_watcher_equal (priv->link_watchers->pdata[i], link_watcher)) + return FALSE; + } + + g_ptr_array_add (priv->link_watchers, nm_team_link_watcher_dup (link_watcher)); + g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS); + return TRUE; +} + +/** + * nm_setting_team_port_remove_link_watcher: + * @setting: the #NMSettingTeamPort + * @idx: index number of the link watcher to remove + * + * Removes the link watcher at index #idx. + * + * Since: 1.10.2 + **/ +void +nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx) +{ + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting); + + 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); + g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS); +} + +/** + * nm_setting_team_port_remove_link_watcher_by_value: + * @setting: the #NMSettingTeamPort + * @link_watcher: the link watcher to remove + * + * Removes the link watcher entry matching link_watcher. + * + * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. + * + * Since: 1.10.2 + **/ +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); + + 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); + g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_team_port_clear_link_watchers: + * @setting: the #NMSettingTeamPort + * + * Removes all configured link watchers. + * + * Since: 1.10.2 + **/ +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)); + + g_ptr_array_set_size (priv->link_watchers, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS); +} + +static GVariant * +team_link_watchers_to_dbus (const GValue *prop_value) +{ + return _nm_utils_team_link_watchers_to_variant (g_value_get_boxed (prop_value)); +} + +static void +team_link_watchers_from_dbus (GVariant *dbus_value, + GValue *prop_value) +{ + g_value_take_boxed (prop_value, _nm_utils_team_link_watchers_from_variant (dbus_value)); +} + static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { @@ -150,6 +409,8 @@ compare_property (NMSetting *setting, NMSettingCompareFlags flags) { NMSettingClass *parent_class; + NMSettingTeamPortPrivate *a_priv, *b_priv; + guint i, j; /* If we are trying to match a connection in order to assume it (and thus * @flags contains INFERRABLE), use the "relaxed" matching for team @@ -162,6 +423,24 @@ compare_property (NMSetting *setting, NM_SETTING_TEAM_PORT_GET_PRIVATE (other)->config, TRUE); } + if (nm_streq0 (prop_spec->name, NM_SETTING_TEAM_PORT_LINK_WATCHERS)) { + a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting); + b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (other); + + if (a_priv->link_watchers->len != b_priv->link_watchers->len) + return FALSE; + for (i = 0; i < a_priv->link_watchers->len; i++) { + for (j = 0; j < b_priv->link_watchers->len; j++) { + if (nm_team_link_watcher_equal (a_priv->link_watchers->pdata[i], + b_priv->link_watchers->pdata[j])) { + break; + } + } + if (j == b_priv->link_watchers->len) + return FALSE; + } + return TRUE; + } /* Otherwise chain up to parent to handle generic compare */ parent_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class); @@ -171,23 +450,92 @@ compare_property (NMSetting *setting, static void 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); } +#define JSON_TO_VAL(typ, id) _nm_utils_json_extract_##typ (priv->config, _prop_to_keys[id], TRUE) + 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; 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); + 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; + 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; + break; + case PROP_STICKY: + if (priv->sticky == g_value_get_boolean (value)) + break; + priv->sticky = g_value_get_boolean (value); + if (priv->sticky) + align_value = value; + align_config = TRUE; + break; + case PROP_LACP_PRIO: + if (priv->lacp_prio == g_value_get_int (value)) + break; + priv->lacp_prio = g_value_get_int (value); + /* from libteam sources: lacp_prio default value is 0xff */ + if (priv->lacp_prio != NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT) + align_value = value; + align_config = TRUE; + break; + case PROP_LACP_KEY: + if (priv->lacp_key == g_value_get_int (value)) + break; + priv->lacp_key = g_value_get_int (value); + if (priv->lacp_key) + align_value = value; + align_config = TRUE; + break; + case PROP_LINK_WATCHERS: + g_ptr_array_unref (priv->link_watchers); + priv->link_watchers = _nm_utils_copy_array (g_value_get_boxed (value), + (NMUtilsCopyFunc) nm_team_link_watcher_dup, + (GDestroyNotify) nm_team_link_watcher_unref); + if (priv->link_watchers->len) + align_value = value; + align_config = TRUE; break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + if (align_config) + _nm_utils_json_append_gvalue (&priv->config, _prop_to_keys[prop_id], align_value); } static void @@ -195,11 +543,32 @@ get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMSettingTeamPort *setting = NM_SETTING_TEAM_PORT (object); + 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)); break; + case PROP_QUEUE_ID: + g_value_set_int (value, priv->queue_id); + break; + case PROP_PRIO: + g_value_set_int (value, priv->prio); + break; + case PROP_STICKY: + g_value_set_boolean (value, priv->sticky); + break; + case PROP_LACP_PRIO: + g_value_set_int (value, priv->lacp_prio); + break; + case PROP_LACP_KEY: + g_value_set_int (value, priv->lacp_key); + break; + case PROP_LINK_WATCHERS: + g_value_take_boxed (value, _nm_utils_copy_array (priv->link_watchers, + (NMUtilsCopyFunc) nm_team_link_watcher_dup, + (GDestroyNotify) nm_team_link_watcher_unref)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -212,6 +581,7 @@ finalize (GObject *object) NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (object); g_free (priv->config); + g_ptr_array_unref (priv->link_watchers); G_OBJECT_CLASS (nm_setting_team_port_parent_class)->finalize (object); } @@ -253,4 +623,103 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingTeamPort:queue-id: + * + * Corresponds to the teamd ports.PORTIFNAME.queue_id. + * When set to -1 means the parameter is skipped from the json config. + * + * Since: 1.10.2 + **/ + g_object_class_install_property + (object_class, PROP_QUEUE_ID, + g_param_spec_int (NM_SETTING_TEAM_PORT_QUEUE_ID, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingTeamPort:prio: + * + * Corresponds to the teamd ports.PORTIFNAME.prio. + * + * Since: 1.10.2 + **/ + g_object_class_install_property + (object_class, PROP_PRIO, + g_param_spec_int (NM_SETTING_TEAM_PORT_PRIO, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingTeamPort:sticky: + * + * Corresponds to the teamd ports.PORTIFNAME.sticky. + * + * Since: 1.10.2 + **/ + g_object_class_install_property + (object_class, PROP_STICKY, + g_param_spec_boolean (NM_SETTING_TEAM_PORT_STICKY, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingTeamPort:lacp-prio: + * + * Corresponds to the teamd ports.PORTIFNAME.lacp_prio. + * + * Since: 1.10.2 + **/ + g_object_class_install_property + (object_class, PROP_LACP_PRIO, + g_param_spec_int (NM_SETTING_TEAM_PORT_LACP_PRIO, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingTeamPort:lacp-key: + * + * Corresponds to the teamd ports.PORTIFNAME.lacp_key. + * + * Since: 1.10.2 + **/ + g_object_class_install_property + (object_class, PROP_LACP_KEY, + g_param_spec_int (NM_SETTING_TEAM_PORT_LACP_KEY, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingTeamPort:link-watchers: + * + * Link watchers configuration for the connection: each link watcher is + * defined by a dictionary, whose keys depend upon the selected link + * watcher. Available link watchers are 'ethtool', 'nsna_ping' and + * 'arp_ping' and it is specified in the dictionary with the key 'name'. + * Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; + * nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; + * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', + * 'validate-incative', 'send-always'. See teamd.conf man for more details. + * + * Element-Type: NMTeamLinkWatcher + * Since: 1.10.2 + **/ + g_object_class_install_property + (object_class, PROP_LINK_WATCHERS, + g_param_spec_boxed (NM_SETTING_TEAM_PORT_LINK_WATCHERS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + _nm_setting_class_transform_property (parent_class, + NM_SETTING_TEAM_PORT_LINK_WATCHERS, + G_VARIANT_TYPE ("aa{sv}"), + team_link_watchers_to_dbus, + team_link_watchers_from_dbus); + } |