summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Giudici <fgiudici@redhat.com>2017-11-09 17:57:01 +0100
committerFrancesco Giudici <fgiudici@redhat.com>2017-11-09 17:57:01 +0100
commit9022b14478a9224ed0cd9e8f3b5a9997597abc46 (patch)
tree2de98b1b23e50c6121716324f61106f4bba264ad
parent931910b7de1dd4fd09b7a020d5f687c60f468328 (diff)
parent3e34e404b475cd44fea7448e9b2b5176de709ef8 (diff)
merge: branch 'fg/team_abstraction_rh1398925'
https://bugzilla.redhat.com/show_bug.cgi?id=1398925
-rw-r--r--clients/common/nm-meta-setting-desc.c226
-rw-r--r--clients/common/settings-docs.c.in19
-rw-r--r--libnm-core/nm-core-internal.h13
-rw-r--r--libnm-core/nm-setting-team-port.c248
-rw-r--r--libnm-core/nm-setting-team-port.h18
-rw-r--r--libnm-core/nm-setting-team.c822
-rw-r--r--libnm-core/nm-setting-team.h77
-rw-r--r--libnm-core/nm-utils-private.h90
-rw-r--r--libnm-core/nm-utils.c294
-rw-r--r--libnm/libnm.ver23
-rw-r--r--shared/nm-utils/nm-jansson.h5
11 files changed, 1832 insertions, 3 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 1ed6b433d8..ea339dd62e 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -461,6 +461,7 @@ _get_text_hidden (NMMetaAccessorGetType get_type)
return NM_META_TEXT_HIDDEN;
}
+
/*****************************************************************************/
G_GNUC_PRINTF (4, 5)
@@ -3642,6 +3643,60 @@ _validate_fcn_team_config (const char *value, char **out_to_free, GError **error
RETURN_STR_TO_FREE (json);
}
+static gboolean
+_is_valid_team_runner_tx_hash_element (const char *tx_hash_element)
+{
+ const char *valid_tx_hashes[] = { "eth", "vlan", "ipv4", "ipv6", "ip",
+ "l3", "tcp", "udp", "sctp", "l4", NULL };
+ if (nmc_string_is_valid (tx_hash_element, valid_tx_hashes, NULL))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+_set_fcn_team_runner_tx_hash (ARGS_SET_FCN)
+{
+ char **strv = NULL;
+ guint i = 0;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ strv = _nm_utils_strv_cleanup (g_strsplit_set (value, " \t,", 0),
+ TRUE, TRUE, TRUE);
+ if (!verify_string_list (strv, property_info->property_name,
+ _is_valid_team_runner_tx_hash_element,
+ error)) {
+ g_strfreev (strv);
+ return FALSE;
+ }
+
+ while (strv && strv[i])
+ nm_setting_team_add_runner_tx_hash (NM_SETTING_TEAM (setting), strv[i++]);
+ g_strfreev (strv);
+
+ return TRUE;
+}
+
+static gboolean
+_validate_and_remove_team_runner_tx_hash (NMSettingTeam *setting,
+ const char *tx_hash,
+ GError **error)
+{
+ if (!nm_setting_team_remove_runner_tx_hash_by_value (setting, tx_hash)) {
+ g_set_error (error, 1, 0,
+ _("the property doesn't contain string '%s'"),
+ tx_hash);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_team_runner_tx_hash,
+ NM_SETTING_TEAM,
+ nm_setting_team_get_num_runner_tx_hash,
+ nm_setting_team_remove_runner_tx_hash,
+ _validate_and_remove_team_runner_tx_hash)
+
static gconstpointer
_get_fcn_vlan_flags (ARGS_GET_FCN)
{
@@ -6000,6 +6055,130 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = {
.validate_fcn = _validate_fcn_team_config,
),
),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "disabled",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_MCAST_REJOIN_COUNT,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "disabled",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER,
+ .property_type = &_pt_gobject_string,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
+ .values_static = VALUES_STATIC (NM_SETTING_TEAM_RUNNER_BROADCAST,
+ NM_SETTING_TEAM_RUNNER_ROUNDROBIN,
+ NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP,
+ NM_SETTING_TEAM_RUNNER_LOADBALANCE,
+ NM_SETTING_TEAM_RUNNER_LACP),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY,
+ .property_type = &_pt_gobject_string,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
+ .values_static = VALUES_STATIC (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL,
+ NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE,
+ NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_TX_HASH,
+ .property_type = DEFINE_PROPERTY_TYPE (
+ .get_fcn = _get_fcn_gobject,
+ .set_fcn = _set_fcn_team_runner_tx_hash,
+ .remove_fcn = _remove_fcn_team_runner_tx_hash,
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_TX_BALANCER,
+ .property_type = &_pt_gobject_string,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
+ .values_static = VALUES_STATIC ("basic"),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 50,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_ACTIVE,
+ .property_type = & _pt_gobject_bool,
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_FAST_RATE,
+ .property_type = & _pt_gobject_bool,
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_SYS_PRIO,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 255,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_MIN_PORTS,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY,
+ .property_type = &_pt_gobject_string,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
+ .values_static = VALUES_STATIC (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO,
+ NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO_STABLE,
+ NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_BANDWIDTH,
+ NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_COUNT,
+ NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG),
+ ),
+ ),
NULL
};
@@ -6016,6 +6195,53 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = {
.validate_fcn = _validate_fcn_team_config,
),
),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_QUEUE_ID,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = -1,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_PRIO,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_STICKY,
+ .property_type = &_pt_gobject_bool,
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_LACP_PRIO,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 255,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_LACP_KEY,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value = 0,
+ .nick = "default",
+ }
+ ),
+ ),
+ ),
NULL
};
diff --git a/clients/common/settings-docs.c.in b/clients/common/settings-docs.c.in
index 3547c833a7..3d6f012bf7 100644
--- a/clients/common/settings-docs.c.in
+++ b/clients/common/settings-docs.c.in
@@ -316,9 +316,28 @@
#define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
#define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in \"8n1\" for example.")
#define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_COUNT N_("Corresponds to the teamd mcast_rejoin.count.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL N_("Corresponds to the teamd mcast_rejoin.interval.")
#define DESCRIBE_DOC_NM_SETTING_TEAM_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#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\".")
+#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.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_HWADDR_POLICY N_("Corresponds to the teamd runner.hwaddr_policy.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_MIN_PORTS N_("Corresponds to the teamd runner.min_ports.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_SYS_PRIO N_("Corresponds to the teamd runner.sys_prio.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_TX_BALANCER N_("Corresponds to the teamd runner.tx_balancer.name.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL N_("Corresponds to the teamd runner.tx_balancer.interval.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_RUNNER_TX_HASH N_("Corresponds to the teamd runner.tx_hash.")
#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_CONFIG N_("The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LACP_KEY N_("Corresponds to the teamd ports.PORTIFNAME.lacp_key.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LACP_PRIO N_("Corresponds to the teamd ports.PORTIFNAME.lacp_prio.")
#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_PRIO N_("Corresponds to the teamd ports.PORTIFNAME.prio.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_QUEUE_ID N_("Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means the parameter is skipped from the json config.")
+#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_STICKY N_("Corresponds to the teamd ports.PORTIFNAME.sticky.")
#define DESCRIBE_DOC_NM_SETTING_TUN_GROUP N_("The group ID which will own the device. If set to NULL everyone will be able to use the device.")
#define DESCRIBE_DOC_NM_SETTING_TUN_MODE N_("The operating mode of the virtual device. Allowed values are NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and NM_SETTING_TUN_MODE_TAP (2) to create an Ethernet-like layer 2 one.")
#define DESCRIBE_DOC_NM_SETTING_TUN_MULTI_QUEUE N_("If the property is set to TRUE, the interface will support multiple file descriptors (queues) to parallelize packet sending or receiving. Otherwise, the interface will only support a single queue.")
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 60963c9cd9..5144a05077 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -435,7 +435,18 @@ gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr);
/*****************************************************************************/
-gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, gboolean port);
+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);
/*****************************************************************************/
diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c
index c030966579..9886cdc91e 100644
--- a/libnm-core/nm-setting-team-port.c
+++ b/libnm-core/nm-setting-team-port.c
@@ -47,14 +47,37 @@ 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;
} 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,
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 },
+};
+
+
/**
* nm_setting_team_port_new:
*
@@ -82,6 +105,86 @@ 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.12
+ **/
+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.12
+ **/
+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.12
+ **/
+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.12
+ **/
+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.12
+ **/
+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;
+}
+
static gboolean
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
@@ -171,23 +274,79 @@ 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;
}
+#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);
+ 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;
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 +354,27 @@ 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;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -253,4 +428,77 @@ 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.12
+ **/
+ 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.12
+ **/
+ 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.12
+ **/
+ 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.12
+ **/
+ 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.12
+ **/
+ 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));
+
+
}
diff --git a/libnm-core/nm-setting-team-port.h b/libnm-core/nm-setting-team-port.h
index 4fcc51083a..2643daba3c 100644
--- a/libnm-core/nm-setting-team-port.h
+++ b/libnm-core/nm-setting-team-port.h
@@ -39,6 +39,14 @@ G_BEGIN_DECLS
#define NM_SETTING_TEAM_PORT_SETTING_NAME "team-port"
#define NM_SETTING_TEAM_PORT_CONFIG "config"
+#define NM_SETTING_TEAM_PORT_QUEUE_ID "queue-id"
+#define NM_SETTING_TEAM_PORT_PRIO "prio"
+#define NM_SETTING_TEAM_PORT_STICKY "sticky"
+#define NM_SETTING_TEAM_PORT_LACP_PRIO "lacp-prio"
+#define NM_SETTING_TEAM_PORT_LACP_KEY "lacp-key"
+
+#define NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT -1
+#define NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT 255
/**
* NMSettingTeamPort:
@@ -61,6 +69,16 @@ GType nm_setting_team_port_get_type (void);
NMSetting * nm_setting_team_port_new (void);
const char * nm_setting_team_port_get_config (NMSettingTeamPort *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_port_get_prio (NMSettingTeamPort *setting);
+NM_AVAILABLE_IN_1_12
+gboolean nm_setting_team_port_get_sticky (NMSettingTeamPort *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting);
G_END_DECLS
diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c
index 0a09c4a677..884c370716 100644
--- a/libnm-core/nm-setting-team.c
+++ b/libnm-core/nm-setting-team.c
@@ -44,14 +44,67 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM)
typedef struct {
char *config;
+ gint notify_peers_count;
+ gint notify_peers_interval;
+ gint mcast_rejoin_count;
+ gint mcast_rejoin_interval;
+ char *runner;
+ char *runner_hwaddr_policy;
+ GPtrArray *runner_tx_hash;
+ char *runner_tx_balancer;
+ gint runner_tx_balancer_interval;
+ gboolean runner_active;
+ gboolean runner_fast_rate;
+ gint runner_sys_prio;
+ gint runner_min_ports;
+ char *runner_agg_select_policy;
} NMSettingTeamPrivate;
+/* Keep aligned with _prop_to_keys[] */
enum {
PROP_0,
PROP_CONFIG,
+ PROP_NOTIFY_PEERS_COUNT,
+ PROP_NOTIFY_PEERS_INTERVAL,
+ PROP_MCAST_REJOIN_COUNT,
+ PROP_MCAST_REJOIN_INTERVAL,
+ PROP_RUNNER,
+ PROP_RUNNER_HWADDR_POLICY,
+ PROP_RUNNER_TX_HASH,
+ PROP_RUNNER_TX_BALANCER,
+ PROP_RUNNER_TX_BALANCER_INTERVAL,
+ PROP_RUNNER_ACTIVE,
+ PROP_RUNNER_FAST_RATE,
+ PROP_RUNNER_SYS_PRIO,
+ PROP_RUNNER_MIN_PORTS,
+ PROP_RUNNER_AGG_SELECT_POLICY,
LAST_PROP
};
+/* Keep aligned with team properties enum */
+static const _NMUtilsTeamPropertyKeys _prop_to_keys[LAST_PROP] = {
+ [PROP_0] = { NULL, NULL, NULL, 0 },
+ [PROP_CONFIG] = { NULL, NULL, NULL, 0 },
+ [PROP_NOTIFY_PEERS_COUNT] = { "notify_peers", "count", NULL, 0 },
+ [PROP_NOTIFY_PEERS_INTERVAL] = { "notify_peers", "interval", NULL, 0 },
+ [PROP_MCAST_REJOIN_COUNT] = { "mcast_rejoin", "count", NULL, 0 },
+ [PROP_MCAST_REJOIN_INTERVAL] = { "mcast_rejoin", "interval", NULL, 0 },
+ [PROP_RUNNER] = { "runner", "name", NULL,
+ {.default_str = NM_SETTING_TEAM_RUNNER_DEFAULT} },
+ [PROP_RUNNER_HWADDR_POLICY] = { "runner", "hwaddr_policy", NULL, 0 },
+ [PROP_RUNNER_TX_HASH] = { "runner", "tx_hash", NULL, 0 },
+ [PROP_RUNNER_TX_BALANCER] = { "runner", "tx_balancer", "name", 0 },
+ [PROP_RUNNER_TX_BALANCER_INTERVAL] = { "runner", "tx_balancer", "interval",
+ NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT },
+ [PROP_RUNNER_ACTIVE] = { "runner", "active", NULL, 0 },
+ [PROP_RUNNER_FAST_RATE] = { "runner", "fast_rate", NULL, 0 },
+ [PROP_RUNNER_SYS_PRIO] = { "runner", "sys_prio", NULL,
+ NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT },
+ [PROP_RUNNER_MIN_PORTS] = { "runner", "min_ports", NULL, 0 },
+ [PROP_RUNNER_AGG_SELECT_POLICY] = { "runner", "agg_select_policy", NULL,
+ {.default_str = NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT} },
+};
+
/**
* nm_setting_team_new:
*
@@ -79,6 +132,339 @@ nm_setting_team_get_config (NMSettingTeam *setting)
return NM_SETTING_TEAM_GET_PRIVATE (setting)->config;
}
+/**
+ * nm_setting_team_get_notify_peers_count:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:notify-peers-count property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_notify_peers_count (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->notify_peers_count;
+}
+
+/**
+ * nm_setting_team_get_notify_peers_interval:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:notify-peers-interval property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->notify_peers_interval;
+}
+
+/**
+ * nm_setting_team_get_mcast_rejoin_count:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:mcast-rejoin-count property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->mcast_rejoin_count;
+}
+
+/**
+ * nm_setting_team_get_mcast_rejoin_interval:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:mcast-rejoin-interval property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->mcast_rejoin_interval;
+}
+
+/**
+ * nm_setting_team_get_runner:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner property of the setting
+ *
+ * Since 1.12
+ **/
+const char *
+nm_setting_team_get_runner (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner;
+}
+
+/**
+ * nm_setting_team_get_runner_hwaddr_policy:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-hwaddr-policy property of the setting
+ *
+ * Since 1.12
+ **/
+const char *
+nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_hwaddr_policy;
+}
+
+/**
+ * nm_setting_team_get_runner_tx_balancer:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-tx-balancer property of the setting
+ *
+ * Since 1.12
+ **/
+const char *
+nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_tx_balancer;
+}
+
+/**
+ * nm_setting_team_get_runner_tx_balancer_interval:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-tx-balancer_interval property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_tx_balancer_interval;
+}
+
+/**
+ * nm_setting_team_get_runner_active:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner_active property of the setting
+ *
+ * Since 1.12
+ **/
+gboolean
+nm_setting_team_get_runner_active (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), FALSE);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_active;
+}
+
+/**
+ * nm_setting_team_get_runner_fast_rate:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-fast-rate property of the setting
+ *
+ * Since 1.12
+ **/
+gboolean
+nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), FALSE);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_fast_rate;
+}
+
+/**
+ * nm_setting_team_get_runner_sys_prio:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-sys-prio property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_sys_prio;
+}
+
+/**
+ * nm_setting_team_get_runner_min_ports:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-min-ports property of the setting
+ *
+ * Since 1.12
+ **/
+gint
+nm_setting_team_get_runner_min_ports (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_min_ports;
+}
+
+/**
+ * nm_setting_team_get_runner_agg_select_policy:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the ##NMSettingTeam:runner-agg-select-policy property of the setting
+ *
+ * Since 1.12
+ **/
+const char *
+nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->runner_agg_select_policy;
+}
+
+/**
+ * nm_setting_team_remove_runner_tx_hash_by_value:
+ * @setting: the #NMSetetingTeam
+ * @txhash: the txhash element to remove
+ *
+ * Removes the txhash element #txhash
+ *
+ * Returns: %TRUE if the txhash element was found and removed; %FALSE if it was not.
+ *
+ * Since 1.12
+ **/
+gboolean
+nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting,
+ const char *txhash)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+ guint i;
+
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), FALSE);
+ g_return_val_if_fail (txhash != NULL, FALSE);
+ g_return_val_if_fail (txhash[0] != '\0', FALSE);
+
+ for (i = 0; i < priv->runner_tx_hash->len; i++) {
+ if (nm_streq (txhash, priv->runner_tx_hash->pdata[i])) {
+ g_ptr_array_remove_index (priv->runner_tx_hash, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_RUNNER_TX_HASH);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_team_get_num_runner_tx_hash:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the number of elements in txhash
+ *
+ * Since: 1.12
+ **/
+guint
+nm_setting_team_get_num_runner_tx_hash (NMSettingTeam *setting)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
+
+ return priv->runner_tx_hash ? priv->runner_tx_hash->len : 0;
+}
+
+/**
+ * nm_setting_team_get_runner_tx_hash
+ * @setting: the #NMSettingTeam
+ * @idx: index number of the txhash element to return
+ *
+ * Returns: the txhash element at index @idx
+ *
+ * Since 1.12
+ **/
+const char *
+nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, int idx)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+ g_return_val_if_fail (idx >= 0 && idx < priv->runner_tx_hash->len, NULL);
+
+ return priv->runner_tx_hash->pdata[idx];
+}
+
+/**
+ * nm_setting_team_remove_runner_tx_hash:
+ * @setting: the #NMSettingTeam
+ * @idx: index number of the element to remove from txhash
+ *
+ * Removes the txhash element at index @idx.
+ *
+ * Since 1.12
+ **/
+void
+nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, int idx)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+
+ g_return_if_fail (NM_IS_SETTING_TEAM (setting));
+ g_return_if_fail (idx >= 0 && idx < priv->runner_tx_hash->len);
+
+ g_ptr_array_remove_index (priv->runner_tx_hash, idx);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_RUNNER_TX_HASH);
+}
+
+/**
+ * nm_setting_team_add_runner_tx_hash:
+ * @setting: the #NMSettingTeam
+ * @txhash: the element to add to txhash
+ *
+ * Adds a new txhash element to the setting.
+ *
+ * Returns: %TRUE if the txhash element was added; %FALSE if the element
+ * was already knnown.
+ *
+ * Since 1.12
+ **/
+gboolean
+nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+ guint i;
+
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), FALSE);
+ g_return_val_if_fail (txhash != NULL, FALSE);
+ g_return_val_if_fail (txhash[0] != '\0', FALSE);
+
+ if (!priv->runner_tx_hash)
+ priv->runner_tx_hash = g_ptr_array_new_with_free_func (g_free);
+ for (i = 0; i < priv->runner_tx_hash->len; i++) {
+ if (nm_streq (txhash, priv->runner_tx_hash->pdata[i]))
+ return FALSE;
+ }
+
+ g_ptr_array_add (priv->runner_tx_hash, g_strdup (txhash));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_RUNNER_TX_HASH);
+ return TRUE;
+}
+
static gboolean
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
@@ -108,6 +494,19 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
}
}
+ if ( priv->runner
+ && g_ascii_strcasecmp (priv->runner, NM_SETTING_TEAM_RUNNER_BROADCAST)
+ && g_ascii_strcasecmp (priv->runner, NM_SETTING_TEAM_RUNNER_ROUNDROBIN)
+ && g_ascii_strcasecmp (priv->runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)
+ && g_ascii_strcasecmp (priv->runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE)
+ && g_ascii_strcasecmp (priv->runner, NM_SETTING_TEAM_RUNNER_LACP)) {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING,
+ _("invalid runner \"%s\""), priv->runner);
+
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_TEAM_RUNNER);
+ return FALSE;
+ }
+
/* NOTE: normalizable/normalizable-errors must appear at the end with decreasing severity.
* Take care to properly order statements with priv->config above. */
@@ -142,6 +541,11 @@ compare_property (NMSetting *setting,
static void
nm_setting_team_init (NMSettingTeam *setting)
{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+
+ priv->runner = g_strdup (NM_SETTING_TEAM_RUNNER_ROUNDROBIN);
+ priv->runner_sys_prio = NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT;
+ priv->runner_tx_balancer_interval = NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT;
}
static void
@@ -150,25 +554,200 @@ finalize (GObject *object)
NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (object);
g_free (priv->config);
+ g_free (priv->runner);
+ g_free (priv->runner_hwaddr_policy);
+ g_free (priv->runner_tx_balancer);
+ g_free (priv->runner_agg_select_policy);
+ if (priv->runner_tx_hash)
+ g_ptr_array_unref (priv->runner_tx_hash);
G_OBJECT_CLASS (nm_setting_team_parent_class)->finalize (object);
}
+
+#define JSON_TO_VAL(typ, id) _nm_utils_json_extract_##typ (priv->config, _prop_to_keys[id], FALSE)
+
+static void
+_align_team_properties (NMSettingTeam *setting)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+ char **strv;
+ int i;
+
+ priv->notify_peers_count = JSON_TO_VAL (int, PROP_NOTIFY_PEERS_COUNT);
+ priv->notify_peers_interval = JSON_TO_VAL (int, PROP_NOTIFY_PEERS_INTERVAL);
+ priv->mcast_rejoin_count = JSON_TO_VAL (int, PROP_MCAST_REJOIN_COUNT);
+ priv->mcast_rejoin_interval = JSON_TO_VAL (int, PROP_MCAST_REJOIN_INTERVAL);
+ priv->runner_tx_balancer_interval = JSON_TO_VAL (int, PROP_RUNNER_TX_BALANCER_INTERVAL);
+ priv->runner_sys_prio = JSON_TO_VAL (int, PROP_RUNNER_SYS_PRIO);
+ priv->runner_min_ports = JSON_TO_VAL (int, PROP_RUNNER_MIN_PORTS);
+
+ priv->runner_active = JSON_TO_VAL (boolean, PROP_RUNNER_ACTIVE);
+ priv->runner_fast_rate = JSON_TO_VAL (boolean, PROP_RUNNER_FAST_RATE);
+
+ g_free (priv->runner);
+ g_free (priv->runner_hwaddr_policy);
+ g_free (priv->runner_tx_balancer);
+ g_free (priv->runner_agg_select_policy);
+ priv->runner = JSON_TO_VAL (string, PROP_RUNNER);
+ priv->runner_hwaddr_policy = JSON_TO_VAL (string, PROP_RUNNER_HWADDR_POLICY);
+ priv->runner_tx_balancer = JSON_TO_VAL (string, PROP_RUNNER_TX_BALANCER);
+ priv->runner_agg_select_policy = JSON_TO_VAL (string, PROP_RUNNER_AGG_SELECT_POLICY);
+
+ if (priv->runner_tx_hash) {
+ g_ptr_array_unref (priv->runner_tx_hash);
+ priv->runner_tx_hash = NULL;
+ }
+ strv = JSON_TO_VAL (strv, PROP_RUNNER_TX_HASH);
+ if (strv) {
+ for (i = 0; strv[i]; i++)
+ nm_setting_team_add_runner_tx_hash (setting, strv[i]);
+ g_strfreev (strv);
+ }
+}
+
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
+ NMSettingTeam *setting = NM_SETTING_TEAM (object);
NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (object);
+ const GValue *align_value = NULL;
+ gboolean align_config = FALSE;
+ char **strv;
switch (prop_id) {
case PROP_CONFIG:
g_free (priv->config);
priv->config = g_value_dup_string (value);
+ _align_team_properties (setting);
+ break;
+ case PROP_NOTIFY_PEERS_COUNT:
+ if (priv->notify_peers_count == g_value_get_int (value))
+ break;
+ priv->notify_peers_count = g_value_get_int (value);
+ if (priv->notify_peers_count)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_NOTIFY_PEERS_INTERVAL:
+ if (priv->notify_peers_interval == g_value_get_int (value))
+ break;
+ priv->notify_peers_interval = g_value_get_int (value);
+ if (priv->notify_peers_interval)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_MCAST_REJOIN_COUNT:
+ if (priv->mcast_rejoin_count == g_value_get_int (value))
+ break;
+ priv->mcast_rejoin_count = g_value_get_int (value);
+ if (priv->mcast_rejoin_count)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_MCAST_REJOIN_INTERVAL:
+ if (priv->mcast_rejoin_interval == g_value_get_int (value))
+ break;
+ priv->mcast_rejoin_interval = g_value_get_int (value);
+ if (priv->mcast_rejoin_interval)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER:
+ g_free (priv->runner);
+ priv->runner = g_value_dup_string (value);
+ if ( priv->runner
+ && !nm_streq (priv->runner,
+ NM_SETTING_TEAM_RUNNER_DEFAULT))
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_HWADDR_POLICY:
+ g_free (priv->runner_hwaddr_policy);
+ priv->runner_hwaddr_policy = g_value_dup_string (value);
+ if ( priv->runner_hwaddr_policy
+ && !nm_streq (priv->runner_hwaddr_policy,
+ NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL)) {
+ align_value = value;
+ }
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_TX_HASH:
+ if (priv->runner_tx_hash)
+ g_ptr_array_unref (priv->runner_tx_hash);
+ strv = g_value_get_boxed (value);
+ if (strv && strv[0]) {
+ priv->runner_tx_hash = _nm_utils_strv_to_ptrarray (strv);
+ align_value = value;
+ } else
+ priv->runner_tx_hash = NULL;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_TX_BALANCER:
+ g_free (priv->runner_tx_balancer);
+ priv->runner_tx_balancer = g_value_dup_string (value);
+ if (priv->runner_tx_balancer)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_TX_BALANCER_INTERVAL:
+ if (priv->runner_tx_balancer_interval == g_value_get_int (value))
+ break;
+ priv->runner_tx_balancer_interval = g_value_get_int (value);
+ if (priv->runner_tx_balancer_interval !=
+ NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_ACTIVE:
+ if (priv->runner_active == g_value_get_boolean (value))
+ break;
+ priv->runner_active = g_value_get_boolean (value);
+ if (priv->runner_active)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_FAST_RATE:
+ if (priv->runner_fast_rate == g_value_get_boolean (value))
+ break;
+ priv->runner_fast_rate = g_value_get_boolean (value);
+ if (priv->runner_fast_rate)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_SYS_PRIO:
+ if (priv->runner_sys_prio == g_value_get_int (value))
+ break;
+ priv->runner_sys_prio = g_value_get_int (value);
+ if (priv->runner_sys_prio != NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_MIN_PORTS:
+ if (priv->runner_min_ports == g_value_get_int (value))
+ break;
+ priv->runner_min_ports = g_value_get_int (value);
+ if (priv->runner_min_ports)
+ align_value = value;
+ align_config = TRUE;
+ break;
+ case PROP_RUNNER_AGG_SELECT_POLICY:
+ g_free (priv->runner_agg_select_policy);
+ priv->runner_agg_select_policy = g_value_dup_string (value);
+ if ( priv->runner_agg_select_policy
+ && !nm_streq (priv->runner_agg_select_policy,
+ NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO))
+ 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
@@ -176,11 +755,55 @@ get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMSettingTeam *setting = NM_SETTING_TEAM (object);
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
switch (prop_id) {
case PROP_CONFIG:
g_value_set_string (value, nm_setting_team_get_config (setting));
break;
+ case PROP_NOTIFY_PEERS_COUNT:
+ g_value_set_int (value, priv->notify_peers_count);
+ break;
+ case PROP_NOTIFY_PEERS_INTERVAL:
+ g_value_set_int (value, priv->notify_peers_interval);
+ break;
+ case PROP_MCAST_REJOIN_COUNT:
+ g_value_set_int (value, priv->mcast_rejoin_count);
+ break;
+ case PROP_MCAST_REJOIN_INTERVAL:
+ g_value_set_int (value, priv->mcast_rejoin_interval);
+ break;
+ case PROP_RUNNER:
+ g_value_set_string (value, nm_setting_team_get_runner (setting));
+ break;
+ case PROP_RUNNER_HWADDR_POLICY:
+ g_value_set_string (value, nm_setting_team_get_runner_hwaddr_policy (setting));
+ break;
+ case PROP_RUNNER_TX_HASH:
+ g_value_take_boxed (value, priv->runner_tx_hash ?
+ _nm_utils_ptrarray_to_strv (priv->runner_tx_hash): NULL);
+ break;
+ case PROP_RUNNER_TX_BALANCER:
+ g_value_set_string (value, nm_setting_team_get_runner_tx_balancer (setting));
+ break;
+ case PROP_RUNNER_TX_BALANCER_INTERVAL:
+ g_value_set_int (value, priv->runner_tx_balancer_interval);
+ break;
+ case PROP_RUNNER_ACTIVE:
+ g_value_set_boolean (value, nm_setting_team_get_runner_active (setting));
+ break;
+ case PROP_RUNNER_FAST_RATE:
+ g_value_set_boolean (value, nm_setting_team_get_runner_fast_rate (setting));
+ break;
+ case PROP_RUNNER_SYS_PRIO:
+ g_value_set_int (value, priv->runner_sys_prio);
+ break;
+ case PROP_RUNNER_MIN_PORTS:
+ g_value_set_int (value, priv->runner_min_ports);
+ break;
+ case PROP_RUNNER_AGG_SELECT_POLICY:
+ g_value_set_string (value, nm_setting_team_get_runner_agg_select_policy (setting));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -225,6 +848,205 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class)
NM_SETTING_PARAM_INFERRABLE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * NMSettingTeam:notify-peers-count:
+ *
+ * Corresponds to the teamd notify_peers.count.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NOTIFY_PEERS_COUNT,
+ g_param_spec_int (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:notify-peers-interval:
+ *
+ * Corresponds to the teamd notify_peers.interval.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NOTIFY_PEERS_INTERVAL,
+ g_param_spec_int (NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:mcast-rejoin-count:
+ *
+ * Corresponds to the teamd mcast_rejoin.count.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MCAST_REJOIN_COUNT,
+ g_param_spec_int (NM_SETTING_TEAM_MCAST_REJOIN_COUNT, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:mcast-rejoin-interval:
+ *
+ * Corresponds to the teamd mcast_rejoin.interval.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MCAST_REJOIN_INTERVAL,
+ g_param_spec_int (NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner:
+ *
+ * Corresponds to the teamd runner.name.
+ * Permitted values are: "roundrobin", "broadcast", "activebackup",
+ * "loadbalance", "lacp".
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER,
+ g_param_spec_string (NM_SETTING_TEAM_RUNNER, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-hwaddr-policy:
+ *
+ * Corresponds to the teamd runner.hwaddr_policy.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_HWADDR_POLICY,
+ g_param_spec_string (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-tx-hash:
+ *
+ * Corresponds to the teamd runner.tx_hash.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_TX_HASH,
+ g_param_spec_boxed (NM_SETTING_TEAM_RUNNER_TX_HASH, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-tx-balancer:
+ *
+ * Corresponds to the teamd runner.tx_balancer.name.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_TX_BALANCER,
+ g_param_spec_string (NM_SETTING_TEAM_RUNNER_TX_BALANCER, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-tx-balancer-interval:
+ *
+ * Corresponds to the teamd runner.tx_balancer.interval.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_TX_BALANCER_INTERVAL,
+ g_param_spec_int (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-active:
+ *
+ * Corresponds to the teamd runner.active.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_ACTIVE,
+ g_param_spec_boolean (NM_SETTING_TEAM_RUNNER_ACTIVE, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-fast-rate:
+ *
+ * Corresponds to the teamd runner.fast_rate.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_FAST_RATE,
+ g_param_spec_boolean (NM_SETTING_TEAM_RUNNER_FAST_RATE, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-sys-prio:
+ *
+ * Corresponds to the teamd runner.sys_prio.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_SYS_PRIO,
+ g_param_spec_int (NM_SETTING_TEAM_RUNNER_SYS_PRIO, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-min-ports:
+ *
+ * Corresponds to the teamd runner.min_ports.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_MIN_PORTS,
+ g_param_spec_int (NM_SETTING_TEAM_RUNNER_MIN_PORTS, "", "",
+ G_MININT32, G_MAXINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingTeam:runner-agg-select-policy:
+ *
+ * Corresponds to the teamd runner.agg_select_policy.
+ *
+ * Since: 1.12
+ **/
+ g_object_class_install_property
+ (object_class, PROP_RUNNER_AGG_SELECT_POLICY,
+ g_param_spec_string (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
/* ---dbus---
* property: interface-name
* format: string
diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h
index 532963aacb..18811374d0 100644
--- a/libnm-core/nm-setting-team.h
+++ b/libnm-core/nm-setting-team.h
@@ -38,7 +38,45 @@ G_BEGIN_DECLS
#define NM_SETTING_TEAM_SETTING_NAME "team"
-#define NM_SETTING_TEAM_CONFIG "config"
+#define NM_SETTING_TEAM_CONFIG "config"
+#define NM_SETTING_TEAM_NOTIFY_PEERS_COUNT "notify-peers-count"
+#define NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL "notify-peers-interval"
+#define NM_SETTING_TEAM_MCAST_REJOIN_COUNT "mcast-rejoin-count"
+#define NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL "mcast-rejoin-interval"
+#define NM_SETTING_TEAM_RUNNER "runner"
+#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY "runner-hwaddr-policy"
+#define NM_SETTING_TEAM_RUNNER_TX_HASH "runner-tx-hash"
+#define NM_SETTING_TEAM_RUNNER_TX_BALANCER "runner-tx-balancer"
+#define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL "runner-tx-balancer-interval"
+#define NM_SETTING_TEAM_RUNNER_ACTIVE "runner-active"
+#define NM_SETTING_TEAM_RUNNER_FAST_RATE "runner-fast-rate"
+#define NM_SETTING_TEAM_RUNNER_SYS_PRIO "runner-sys-prio"
+#define NM_SETTING_TEAM_RUNNER_MIN_PORTS "runner-min-ports"
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY "runner-agg-select-policy"
+
+#define NM_SETTING_TEAM_RUNNER_BROADCAST "broadcast"
+#define NM_SETTING_TEAM_RUNNER_ROUNDROBIN "roundrobin"
+#define NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP "activebackup"
+#define NM_SETTING_TEAM_RUNNER_LOADBALANCE "loadbalance"
+#define NM_SETTING_TEAM_RUNNER_LACP "lacp"
+
+#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL "same_all"
+#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE "by_active"
+#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE "only_active"
+
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO "lacp_prio"
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO_STABLE "lacp_prio_stable"
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_BANDWIDTH "bandwidth"
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_COUNT "count"
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG "port_config"
+
+#define NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT 1
+#define NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT 1
+#define NM_SETTING_TEAM_RUNNER_DEFAULT NM_SETTING_TEAM_RUNNER_ROUNDROBIN
+#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL
+#define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT 50
+#define NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT 255
+#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO
/**
* NMSettingTeam:
@@ -61,7 +99,42 @@ GType nm_setting_team_get_type (void);
NMSetting * nm_setting_team_new (void);
const char * nm_setting_team_get_config (NMSettingTeam *setting);
-
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_notify_peers_count (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+const char * nm_setting_team_get_runner (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+const char * nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+const char * nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gboolean nm_setting_team_get_runner_active (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gboolean nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gint nm_setting_team_get_runner_min_ports (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+const char * nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+gboolean nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting, const char *txhash);
+NM_AVAILABLE_IN_1_12
+guint nm_setting_team_get_num_runner_tx_hash (NMSettingTeam *setting);
+NM_AVAILABLE_IN_1_12
+const char *nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, int idx);
+NM_AVAILABLE_IN_1_12
+void nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, int idx);
+NM_AVAILABLE_IN_1_12
+gboolean nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash);
G_END_DECLS
#endif /* __NM_SETTING_TEAM_H__ */
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
index 03c8790764..6b8d58726a 100644
--- a/libnm-core/nm-utils-private.h
+++ b/libnm-core/nm-utils-private.h
@@ -78,4 +78,94 @@ void _nm_utils_bytes_from_dbus (GVariant *dbus_value,
char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length);
+
+/* JSON to GValue conversion macros */
+
+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)
+{
+ gs_free GValue *t_value = NULL;
+ int ret;
+
+ t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
+ if (!t_value)
+ return key.default_int;
+
+ ret = g_value_get_int (t_value);
+ g_value_unset (t_value);
+ return ret;
+}
+
+static inline gboolean
+_nm_utils_json_extract_boolean (char *conf,
+ _NMUtilsTeamPropertyKeys key,
+ gboolean is_port)
+{
+ gs_free GValue *t_value = NULL;
+ gboolean ret;
+
+ t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
+ if (!t_value)
+ return key.default_bool;
+
+ ret = g_value_get_boolean (t_value);
+ g_value_unset (t_value);
+ return ret;
+}
+
+static inline char *
+_nm_utils_json_extract_string (char *conf,
+ _NMUtilsTeamPropertyKeys key,
+ gboolean is_port)
+{
+ gs_free GValue *t_value = NULL;
+ char *ret;
+
+ t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
+ if (!t_value)
+ return g_strdup (key.default_str);
+
+ ret = g_value_dup_string (t_value);
+ g_value_unset (t_value);
+ return ret;
+}
+
+static inline char **
+_nm_utils_json_extract_strv (char *conf,
+ _NMUtilsTeamPropertyKeys key,
+ gboolean is_port)
+{
+ gs_free GValue *t_value = NULL;
+ char **ret;
+
+ t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
+ if (!t_value)
+ return NULL;
+
+ ret = g_strdupv (g_value_get_boxed (t_value));
+ g_value_unset (t_value);
+ 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
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index f2fa73248d..6c8436cc5d 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -4441,6 +4441,280 @@ out:
return ret;
}
+
+
+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);
+}
+
+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;
+ const char *runner = NULL;
+
+ if (!key)
+ 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.
+ */
+ if (port_config) {
+ _json_add_object (json, "link_watch", "name", NULL, json_string ("ethtool"));
+ } else {
+ /* 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);
+ }
+ }
+ 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 (json_is_array (json_element)) {
+ GPtrArray *data = g_ptr_array_new_with_free_func ((GDestroyNotify) 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)));
+ }
+ if (data->len) {
+ g_value_init (value, G_TYPE_STRV);
+ g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (data));
+ }
+ g_ptr_array_free (data, TRUE);
+ } 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)
+{
+ json_t *json, *json_element, *json_link, *json_value = NULL;
+ json_error_t jerror;
+ gboolean updated = FALSE;
+ char **strv;
+ const char *iter_key = key;
+ int i;
+
+ json = json_loads (*conf?: "{}", JSON_REJECT_DUPLICATES, &jerror);
+ if (!json)
+ return FALSE;
+
+ /* no new value? delete element */
+ if (!value) {
+ json_element = json;
+ json_link = NULL;
+
+ if (key2) {
+ json_link = json;
+ json_element = json_object_get (json, key);
+ if (!json_element)
+ goto done;
+ iter_key = key2;
+ }
+ if (key3) {
+ json_link = json_element;
+ json_element = json_object_get (json_element, key2);
+ if (!json_element)
+ goto done;
+ iter_key = key3;
+ }
+ if (json_object_del (json_element, iter_key) != 0)
+ goto done;
+
+ updated = TRUE;
+
+ /* 1st level key only */
+ if (!json_link)
+ goto done;
+
+ if (json_object_size (json_element) == 0)
+ json_object_del (json_link, (key3 ? key2 : key));
+
+ if (key3 && json_object_size (json_link) == 0)
+ json_object_del (json, key);
+
+ goto done;
+ }
+
+ /* insert new value */
+ updated = TRUE;
+ 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)) {
+ strv = g_value_get_boxed (value);
+ if (strv) {
+ json_value = json_array ();
+ for (i = 0; strv[i]; i++)
+ json_array_append_new (json_value, json_string (strv[i]));
+ } else
+ return FALSE;
+ } else {
+ g_assert_not_reached ();
+ updated = FALSE;
+ goto done;
+ }
+
+ /* 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, json_value);
+
+done:
+ if (updated) {
+ g_free (*conf);
+ *conf = json_dumps (json, 0);
+ /* Don't save an empty config */
+ if (nm_streq0 (*conf, "{}")) {
+ g_free (*conf);
+ *conf = NULL;
+ }
+ }
+ json_decref (json);
+ return updated;
+}
+
#else /* WITH_JANSSON */
gboolean
@@ -4495,6 +4769,26 @@ _nm_utils_team_config_equal (const char *conf1,
{
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
static char *
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 7b234ca762..5e9feaffc8 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1235,4 +1235,27 @@ global:
nm_client_checkpoint_rollback_async;
nm_client_checkpoint_rollback_finish;
nm_client_get_checkpoints;
+ nm_setting_team_add_runner_tx_hash;
+ nm_setting_team_get_mcast_rejoin_count;
+ nm_setting_team_get_mcast_rejoin_interval;
+ nm_setting_team_get_notify_peers_count;
+ nm_setting_team_get_notify_peers_interval;
+ nm_setting_team_get_num_runner_tx_hash;
+ nm_setting_team_get_runner;
+ nm_setting_team_get_runner_hwaddr_policy;
+ nm_setting_team_get_runner_tx_balancer;
+ nm_setting_team_get_runner_tx_balancer_interval;
+ nm_setting_team_get_runner_tx_hash;
+ nm_setting_team_get_runner_active;
+ nm_setting_team_get_runner_fast_rate;
+ nm_setting_team_get_runner_sys_prio;
+ nm_setting_team_get_runner_min_ports;
+ nm_setting_team_get_runner_agg_select_policy;
+ nm_setting_team_port_get_queue_id;
+ nm_setting_team_port_get_prio;
+ nm_setting_team_port_get_sticky;
+ nm_setting_team_port_get_lacp_prio;
+ nm_setting_team_port_get_lacp_key;
+ nm_setting_team_remove_runner_tx_hash;
+ nm_setting_team_remove_runner_tx_hash_by_value;
} libnm_1_10_0;
diff --git a/shared/nm-utils/nm-jansson.h b/shared/nm-utils/nm-jansson.h
index 2b159e7872..ac95a2916b 100644
--- a/shared/nm-utils/nm-jansson.h
+++ b/shared/nm-utils/nm-jansson.h
@@ -47,6 +47,11 @@
index++)
#endif
+/* Added in Jansson v2.7 */
+#ifndef json_boolean_value
+#define json_boolean_value json_is_true
+#endif
+
/* Added in Jansson v2.8 */
#ifndef json_object_foreach_safe
#if JANSSON_VERSION_HEX < 0x020300