merge: branch 'fg/team_abstraction_rh1398925'

https://bugzilla.redhat.com/show_bug.cgi?id=1398925

(cherry picked from commit 9022b14478)
This commit is contained in:
Francesco Giudici 2017-12-08 01:41:39 +01:00
commit f5e358eb46
10 changed files with 1846 additions and 3 deletions

View file

@ -461,6 +461,7 @@ _get_text_hidden (NMMetaAccessorGetType get_type)
return NM_META_TEXT_HIDDEN;
}
/*****************************************************************************/
G_GNUC_PRINTF (4, 5)
@ -3652,6 +3653,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)
{
@ -6010,6 +6065,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
};
@ -6026,6 +6205,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
};

View file

@ -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.")

View file

@ -445,7 +445,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);
/*****************************************************************************/

View file

@ -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.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;
}
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.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));
}

View file

@ -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_10_2
gint nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_port_get_prio (NMSettingTeamPort *setting);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_port_get_sticky (NMSettingTeamPort *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting);
G_END_DECLS

View file

@ -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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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.10.2
**/
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

View file

@ -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_10_2
gint nm_setting_team_get_notify_peers_count (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
const char * nm_setting_team_get_runner (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
const char * nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
const char * nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_get_runner_active (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gint nm_setting_team_get_runner_min_ports (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
const char * nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting, const char *txhash);
NM_AVAILABLE_IN_1_10_2
guint nm_setting_team_get_num_runner_tx_hash (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
const char *nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, int idx);
NM_AVAILABLE_IN_1_10_2
void nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, int idx);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash);
G_END_DECLS
#endif /* __NM_SETTING_TEAM_H__ */

View file

@ -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

View file

@ -4301,6 +4301,25 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to)
/*****************************************************************************/
#if WITH_JANSSON
/* Added in Jansson v2.4 (released Sep 23 2012), but travis.ci has v2.2. */
#ifndef json_boolean
#define json_boolean(val) ((val) ? json_true() : json_false())
#endif
/* Added in Jansson v2.5 (released Sep 19 2013), but travis.ci has v2.2. */
#ifndef json_array_foreach
#define json_array_foreach(array, index, value) \
for (index = 0; \
index < json_array_size(array) && (value = json_array_get(array, index)); \
index++)
#endif
/* Added in Jansson v2.7 */
#ifndef json_boolean_value
#define json_boolean_value json_is_true
#endif
/**
* nm_utils_is_json_object:
* @str: the JSON string to test
@ -4446,6 +4465,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
@ -4500,6 +4793,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 *

View file

@ -1226,5 +1226,28 @@ libnm_1_10_2 {
global:
nm_remote_connection_update2;
nm_remote_connection_update2_finish;
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;
nm_settings_update2_flags_get_type;
} libnm_1_10_0;