merge: branch 'fg/team_abstraction_tests_and_fixes_rh1398925'

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

(cherry picked from commit 4d1796b2c7)
This commit is contained in:
Francesco Giudici 2017-12-08 03:01:17 +01:00
commit f092cc0f94
25 changed files with 3691 additions and 1216 deletions

4
.gitignore vendored
View file

@ -155,9 +155,7 @@ test-*.trs
/libnm-core/tests/test-keyfile
/libnm-core/tests/test-need-secrets
/libnm-core/tests/test-secrets
/libnm-core/tests/test-setting-8021x
/libnm-core/tests/test-setting-bond
/libnm-core/tests/test-setting-dcb
/libnm-core/tests/test-setting
/libnm-core/nm-dbus-types.xml
/libnm-core/nm-vpn-dbus-types.xml

View file

@ -639,9 +639,7 @@ check_programs += \
libnm-core/tests/test-general \
libnm-core/tests/test-keyfile \
libnm-core/tests/test-secrets \
libnm-core/tests/test-setting-8021x \
libnm-core/tests/test-setting-bond \
libnm-core/tests/test-setting-dcb \
libnm-core/tests/test-setting \
libnm-core/tests/test-settings-defaults
GLIB_GENERATED += \
@ -665,9 +663,7 @@ libnm_core_tests_test_crypto_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_general_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_keyfile_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_secrets_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_setting_8021x_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_setting_bond_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_setting_dcb_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_setting_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_settings_defaults_CPPFLAGS = $(libnm_core_tests_cppflags)
libnm_core_tests_test_general_SOURCES = \
@ -687,9 +683,7 @@ libnm_core_tests_test_crypto_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_general_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_keyfile_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_secrets_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_setting_8021x_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_setting_bond_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_setting_dcb_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_setting_LDADD = $(libnm_core_tests_ldadd)
libnm_core_tests_test_settings_defaults_LDADD = $(libnm_core_tests_ldadd)
$(libnm_core_tests_test_compare_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
@ -697,9 +691,7 @@ $(libnm_core_tests_test_crypto_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_keyfile_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_secrets_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_setting_8021x_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_setting_bond_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_setting_dcb_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_setting_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_core_tests_test_settings_defaults_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
# test-cert.p12 created with:

View file

@ -241,6 +241,150 @@ _parse_ip_route (int family,
return route;
}
static char *
_dump_team_link_watcher (NMTeamLinkWatcher *watcher)
{
const char *name;
NMTeamLinkWatcherArpPingFlags flags;
GString *w_dump;
if (!watcher)
return NULL;
w_dump = g_string_new (NULL);
name = nm_team_link_watcher_get_name (watcher);
g_string_append_printf (w_dump, "name=%s", name);
#define DUMP_WATCHER_INT(str, watcher, name, key) \
G_STMT_START { \
int _val = nm_team_link_watcher_get_##key (watcher); \
\
if (_val) \
g_string_append_printf (str, " %s=%d", name, _val); \
} G_STMT_END;
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
DUMP_WATCHER_INT (w_dump, watcher, "delay-up", delay_up);
DUMP_WATCHER_INT (w_dump, watcher, "delay-down", delay_down);
return g_string_free (w_dump, FALSE);
}
/* NM_TEAM_LINK_WATCHER_NSNA_PING and NM_TEAM_LINK_WATCHER_ARP_PING */
DUMP_WATCHER_INT (w_dump, watcher, "init-wait", init_wait);
DUMP_WATCHER_INT (w_dump, watcher, "initerval", interval);
DUMP_WATCHER_INT (w_dump, watcher, "missed-max", missed_max);
#undef DUMP_WATCHER_INT
g_string_append_printf (w_dump, " target-host=%s",
nm_team_link_watcher_get_target_host (watcher));
if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
return g_string_free (w_dump, FALSE);
g_string_append_printf (w_dump, " source-host=%s",
nm_team_link_watcher_get_source_host (watcher));
flags = nm_team_link_watcher_get_flags (watcher);
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE)
g_string_append_printf (w_dump, " validate-active=true");
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE)
g_string_append_printf (w_dump, " validate-inactive=true");
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS)
g_string_append_printf (w_dump, "send-always=true");
return g_string_free (w_dump, FALSE);
}
static NMTeamLinkWatcher *
_parse_team_link_watcher (const char *str,
GError **error)
{
gs_strfreev char **watcherv = NULL;
gs_free char *str_clean = NULL;
guint i;
gs_free const char *name = NULL;
int val1 = 0, val2 = 0, val3 = 3;
gs_free const char *target_host = NULL;
gs_free const char *source_host = NULL;
NMTeamLinkWatcherArpPingFlags flags = 0;
nm_assert (str);
nm_assert (!error || !*error);
str_clean = g_strstrip (g_strdup (str));
watcherv = nmc_strsplit_set (str_clean, " \t", 0);
if (!watcherv || !watcherv[0]) {
g_set_error (error, 1, 0, "'%s' is not valid", str);
return NULL;
}
for (i = 0; watcherv[i]; i++) {
gs_strfreev char **pair = NULL;
pair = nmc_strsplit_set (watcherv[i], "=", 0);
if (!pair[0]) {
g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i],
"properties should be specified as 'key=value'");
return NULL;
}
if (!pair[1]) {
g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i],
"missing key value");
return NULL;
}
if (pair[2]) {
g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i],
"properties should be specified as 'key=value'");
return NULL;
}
if (nm_streq (pair[0], "name"))
name = g_strdup (pair[1]);
else if ( nm_streq (pair[0], "delay-up")
|| nm_streq (pair[0], "init-wait"))
val1 = _nm_utils_ascii_str_to_int64 (pair[1], 10, 0, G_MAXINT32, -1);
else if ( nm_streq (pair[0], "delay-down")
|| nm_streq (pair[0], "interval"))
val2 = _nm_utils_ascii_str_to_int64 (pair[1], 10, 0, G_MAXINT32, -1);
else if (nm_streq (pair[0], "missed-max"))
val3 = _nm_utils_ascii_str_to_int64 (pair[1], 10, 0, G_MAXINT32, -1);
else if (nm_streq (pair[0], "target-host"))
target_host = g_strdup (pair[1]);
else if (nm_streq (pair[0], "source-host"))
source_host = g_strdup (pair[1]);
else if (nm_streq (pair[0], "validate-active")) {
if (nm_streq (pair[1], "true"))
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE;
} else if (nm_streq (pair[0], "validate-inactive")) {
if (nm_streq (pair[1], "true"))
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE;
} else if (nm_streq (pair[0], "send-always")) {
if (nm_streq (pair[1], "true"))
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS;
} else {
g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i],
"unknown key");
return NULL;
}
if ((val1 < 0) || (val2 < 0) || (val3 < 0)) {
g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i],
"value is not a valid number [0, MAXINT]");
return NULL;
}
}
if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ETHTOOL))
return nm_team_link_watcher_new_ethtool (val1, val2, error);
else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
return nm_team_link_watcher_new_nsna_ping (val1, val2, val3, target_host, error);
else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ARP_PING))
return nm_team_link_watcher_new_arp_ping (val1, val2, val3, target_host, source_host, flags, error);
if (!name)
g_set_error (error, 1, 0, "link watcher name missing");
else
g_set_error (error, 1, 0, "unknown link watcher name: '%s'", name);
return NULL;
}
/* Max priority values from libnm-core/nm-setting-vlan.c */
#define MAX_SKB_PRIO G_MAXUINT32
#define MAX_8021P_PRIO 7 /* Max 802.1p priority */
@ -3707,6 +3851,150 @@ DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_team_runner_tx_hash,
nm_setting_team_remove_runner_tx_hash,
_validate_and_remove_team_runner_tx_hash)
static gconstpointer
_get_fcn_team_link_watchers (ARGS_GET_FCN)
{
NMSettingTeam *s_team = NM_SETTING_TEAM (setting);
GString *printable;
guint32 num_watchers, i;
NMTeamLinkWatcher *watcher;
char *watcher_str;
RETURN_UNSUPPORTED_GET_TYPE ();
printable = g_string_new (NULL);
num_watchers = nm_setting_team_get_num_link_watchers (s_team);
for (i = 0; i < num_watchers; i++) {
watcher = nm_setting_team_get_link_watcher (s_team, i);
watcher_str = _dump_team_link_watcher (watcher);
if (watcher_str) {
if (printable->len > 0)
g_string_append (printable, ", ");
g_string_append (printable, watcher_str);
g_free (watcher_str);
}
}
RETURN_STR_TO_FREE (g_string_free (printable, FALSE));
}
static gboolean
_set_fcn_team_link_watchers (ARGS_SET_FCN)
{
gs_strfreev char **strv = NULL;
const char *const*iter;
NMTeamLinkWatcher *watcher;
strv = nmc_strsplit_set (value, ",", 0);
for (iter = (const char *const*) strv; *iter; iter++) {
watcher = _parse_team_link_watcher (*iter, error);
if (!watcher)
return FALSE;
nm_setting_team_add_link_watcher (NM_SETTING_TEAM (setting), watcher);
nm_team_link_watcher_unref (watcher);
}
return TRUE;
}
static gboolean
_validate_and_remove_team_link_watcher (NMSettingTeam *setting,
const char *watcher_str,
GError **error)
{
NMTeamLinkWatcher *watcher;
gboolean ret;
watcher = _parse_team_link_watcher (watcher_str, error);
if (!watcher)
return FALSE;
ret = nm_setting_team_remove_link_watcher_by_value (setting, watcher);
if (!ret) {
g_set_error (error, 1, 0, _("the property doesn't contain link watcher '%s'"),
watcher_str);
}
nm_team_link_watcher_unref (watcher);
return ret;
}
DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_team_link_watchers,
NM_SETTING_TEAM,
nm_setting_team_get_num_link_watchers,
nm_setting_team_remove_link_watcher,
_validate_and_remove_team_link_watcher)
static gconstpointer
_get_fcn_team_port_link_watchers (ARGS_GET_FCN)
{
NMSettingTeamPort *s_team_port = NM_SETTING_TEAM_PORT (setting);
GString *printable;
guint32 num_watchers, i;
NMTeamLinkWatcher *watcher;
char *watcher_str;
RETURN_UNSUPPORTED_GET_TYPE ();
printable = g_string_new (NULL);
num_watchers = nm_setting_team_port_get_num_link_watchers (s_team_port);
for (i = 0; i < num_watchers; i++) {
watcher = nm_setting_team_port_get_link_watcher (s_team_port, i);
watcher_str = _dump_team_link_watcher (watcher);
if (watcher_str) {
if (printable->len > 0)
g_string_append (printable, ", ");
g_string_append (printable, watcher_str);
g_free (watcher_str);
}
}
RETURN_STR_TO_FREE (g_string_free (printable, FALSE));
}
static gboolean
_set_fcn_team_port_link_watchers (ARGS_SET_FCN)
{
gs_strfreev char **strv = NULL;
const char *const*iter;
NMTeamLinkWatcher *watcher;
strv = nmc_strsplit_set (value, ",", 0);
for (iter = (const char *const*) strv; *iter; iter++) {
watcher = _parse_team_link_watcher (*iter, error);
if (!watcher)
return FALSE;
nm_setting_team_port_add_link_watcher (NM_SETTING_TEAM_PORT (setting), watcher);
nm_team_link_watcher_unref (watcher);
}
return TRUE;
}
static gboolean
_validate_and_remove_team_port_link_watcher (NMSettingTeamPort *setting,
const char *watcher_str,
GError **error)
{
NMTeamLinkWatcher *watcher;
gboolean ret;
watcher = _parse_team_link_watcher (watcher_str, error);
if (!watcher)
return FALSE;
ret = nm_setting_team_port_remove_link_watcher_by_value (setting, watcher);
if (!ret) {
g_set_error (error, 1, 0, _("the property doesn't contain link watcher '%s'"),
watcher_str);
}
nm_team_link_watcher_unref (watcher);
return ret;
}
DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_team_port_link_watchers,
NM_SETTING_TEAM_PORT,
nm_setting_team_port_get_num_link_watchers,
nm_setting_team_port_remove_link_watcher,
_validate_and_remove_team_port_link_watcher)
static gconstpointer
_get_fcn_vlan_flags (ARGS_GET_FCN)
{
@ -4505,6 +4793,24 @@ static const NMMetaPropertyType _pt_gobject_devices = {
"{ \"device\": \"team0\", \"runner\": {\"name\": \"roundrobin\"}, \"ports\": {\"eth1\": {}, \"eth2\": {}} }\n" \
" set team.config /etc/my-team.conf\n")
#define TEAM_LINK_WATCHERS_DESCRIBE_MESSAGE \
N_("Enter a list of link watchers formatted as dictionaries where the keys " \
"are teamd properties. Dictionary pairs are in the form: key=value and pairs " \
"are separated by ' '. Dictionaries are separated with ','.\n" \
"The keys allowed/required in the dictionary change on the basis of the link " \
"watcher type, while the only property common to all the link watchers is " \
" 'name'*, which defines the link watcher to be specified.\n\n" \
"Properties available for the 'ethtool' link watcher:\n" \
" 'delay-up', 'delay-down'\n\n" \
"Properties available for the 'nsna_ping' link watcher:\n" \
" 'init-wait', 'interval', 'missed-max', 'target-host'*\n\n" \
"Properties available for the 'arp_ping' include all the ones for 'nsna_ping' and:\n" \
" 'source-host', 'validate-active', 'validate-inactive', 'send-always'.\n\n" \
"Properties flagged with a '*' are mandatory.\n\n" \
"Example:\n" \
" name=arp_ping,source-host=172.16.1.1,target-host=172.16.1.254; name=ethtool,delay-up=3\n")
#define DEFINE_DCB_PROPRITY_PROPERTY_TYPE \
.property_type = &_pt_gobject_int, \
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \
@ -6189,6 +6495,14 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = {
NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG),
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_LINK_WATCHERS,
.describe_message = TEAM_LINK_WATCHERS_DESCRIBE_MESSAGE,
.property_type = DEFINE_PROPERTY_TYPE (
.get_fcn = _get_fcn_team_link_watchers,
.set_fcn = _set_fcn_team_link_watchers,
.remove_fcn = _remove_fcn_team_link_watchers,
),
),
NULL
};
@ -6252,6 +6566,14 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = {
),
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_LINK_WATCHERS,
.describe_message = TEAM_LINK_WATCHERS_DESCRIBE_MESSAGE,
.property_type = DEFINE_PROPERTY_TYPE (
.get_fcn = _get_fcn_team_port_link_watchers,
.set_fcn = _set_fcn_team_port_link_watchers,
.remove_fcn = _remove_fcn_team_port_link_watchers,
),
),
NULL
};

View file

@ -316,6 +316,7 @@
#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_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-incative', 'send-always'. See teamd.conf man for more details.")
#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\".")
@ -334,6 +335,7 @@
#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_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-incative', 'send-always'. See teamd.conf man for more details.")
#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.")

View file

@ -501,6 +501,15 @@ cert_writer (KeyfileWriterInfo *info,
cert_writer_default (info->connection, info->keyfile, &type_data);
}
static void
null_writer (KeyfileWriterInfo *info,
NMSetting *setting,
const char *key,
const GValue *value)
{
/* skip */
}
/*****************************************************************************/
typedef struct {
@ -576,6 +585,69 @@ static KeyWriter key_writers[] = {
{ NM_SETTING_802_1X_SETTING_NAME,
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
cert_writer },
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_NOTIFY_PEERS_COUNT,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_MCAST_REJOIN_COUNT,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_HWADDR_POLICY,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_TX_HASH,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_TX_BALANCER,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_ACTIVE,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_FAST_RATE,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_SYS_PRIO,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_MIN_PORTS,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY,
null_writer},
{ NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TEAM_LINK_WATCHERS,
null_writer},
{ NM_SETTING_TEAM_PORT_SETTING_NAME,
NM_SETTING_TEAM_PORT_QUEUE_ID,
null_writer},
{ NM_SETTING_TEAM_PORT_SETTING_NAME,
NM_SETTING_TEAM_PORT_PRIO,
null_writer},
{ NM_SETTING_TEAM_PORT_SETTING_NAME,
NM_SETTING_TEAM_PORT_STICKY,
null_writer},
{ NM_SETTING_TEAM_PORT_SETTING_NAME,
NM_SETTING_TEAM_PORT_LACP_PRIO,
null_writer},
{ NM_SETTING_TEAM_PORT_SETTING_NAME,
NM_SETTING_TEAM_PORT_LACP_KEY,
null_writer},
{ NM_SETTING_TEAM_PORT_SETTING_NAME,
NM_SETTING_TEAM_PORT_LINK_WATCHERS,
null_writer},
{ NULL, NULL, NULL }
};

View file

@ -55,6 +55,38 @@ _nm_property_compare_collection (GVariant *value1, GVariant *value2)
return 0;
}
static gint
_nm_property_compare_vardict (GVariant *value1, GVariant *value2)
{
GVariantIter iter;
int len1, len2;
const char *key;
GVariant *val1, *val2;
len1 = g_variant_n_children (value1);
len2 = g_variant_n_children (value2);
if (len1 != len2)
return len1 < len2 ? -1 : 1;
g_variant_iter_init (&iter, value1);
while (g_variant_iter_next (&iter, "{&sv}", &key, &val1)) {
if (!g_variant_lookup (value2, key, "v", &val2)) {
g_variant_unref (val1);
return -1;
}
if (!g_variant_equal (val1, val2)) {
g_variant_unref (val1);
g_variant_unref (val2);
return -1;
}
g_variant_unref (val1);
g_variant_unref (val2);
}
return 0;
}
static gint
_nm_property_compare_strdict (GVariant *value1, GVariant *value2)
{
@ -106,6 +138,8 @@ nm_property_compare (GVariant *value1, GVariant *value2)
ret = g_variant_compare (value1, value2);
else if (g_variant_is_of_type (value1, G_VARIANT_TYPE ("a{ss}")))
ret = _nm_property_compare_strdict (value1, value2);
else if (g_variant_is_of_type (value1, G_VARIANT_TYPE ("a{sv}")))
ret = _nm_property_compare_vardict (value1, value2);
else if (g_variant_type_is_array (type1))
ret = _nm_property_compare_collection (value1, value2);
else if (g_variant_type_is_tuple (type1))

View file

@ -15,6 +15,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
* Copyright 2013 Jiri Pirko <jiri@resnulli.us>
*/
@ -29,7 +30,6 @@
#include "nm-utils-private.h"
#include "nm-connection-private.h"
#include "nm-setting-connection.h"
#include "nm-setting-team.h"
/**
* SECTION:nm-setting-team-port
@ -52,6 +52,7 @@ typedef struct {
gboolean sticky;
int lacp_prio;
int lacp_key;
GPtrArray *link_watchers; /* Array of NMTeamLinkWatcher */
} NMSettingTeamPortPrivate;
/* Keep aligned with _prop_to_keys[] */
@ -63,18 +64,20 @@ enum {
PROP_STICKY,
PROP_LACP_PRIO,
PROP_LACP_KEY,
PROP_LINK_WATCHERS,
LAST_PROP
};
/* Keep aligned with team-port properties enum */
static const _NMUtilsTeamPropertyKeys _prop_to_keys[LAST_PROP] = {
[PROP_0] = { NULL, NULL, NULL, 0 },
[PROP_CONFIG] = { NULL, NULL, NULL, 0 },
[PROP_QUEUE_ID] = { "queue_id", NULL, NULL, NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT },
[PROP_PRIO] = { "prio", NULL, NULL, 0 },
[PROP_STICKY] = { "sticky", NULL, NULL, 0 },
[PROP_LACP_PRIO] = { "lacp_prio", NULL, NULL, NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT },
[PROP_LACP_KEY] = { "lacp_key", NULL, NULL, 0 },
[PROP_0] = { NULL, NULL, NULL, 0 },
[PROP_CONFIG] = { NULL, NULL, NULL, 0 },
[PROP_QUEUE_ID] = { "queue_id", NULL, NULL, NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT },
[PROP_PRIO] = { "prio", NULL, NULL, 0 },
[PROP_STICKY] = { "sticky", NULL, NULL, 0 },
[PROP_LACP_PRIO] = { "lacp_prio", NULL, NULL, NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT },
[PROP_LACP_KEY] = { "lacp_key", NULL, NULL, 0 },
[PROP_LINK_WATCHERS] = { "link_watch", NULL, NULL, 0 }
};
@ -185,6 +188,159 @@ nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting)
return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->lacp_key;
}
/**
* nm_setting_team_port_get_num_link_watchers:
* @setting: the #NMSettingTeamPort
*
* Returns: the number of configured link watchers
*
* Since: 1.10.2
**/
guint
nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting)
{
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
return priv->link_watchers->len;
}
/**
* nm_setting_team_port_get_link_watcher:
* @setting: the #NMSettingTeamPort
* @idx: index number of the link watcher to return
*
* Returns: (transfer none): the link watcher at index @idx.
*
* Since: 1.10.2
**/
NMTeamLinkWatcher *
nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx)
{
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), NULL);
g_return_val_if_fail (idx < priv->link_watchers->len, NULL);
return priv->link_watchers->pdata[idx];
}
/**
* nm_setting_team_port_add_link_watcher:
* @setting: the #NMSettingTeamPort
* @link_watcher: the link watcher to add
*
* Appends a new link watcher to the setting.
*
* Returns: %TRUE if the link watcher is added; %FALSE if an identical link
* watcher was already there.
*
* Since: 1.10.2
**/
gboolean
nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting,
NMTeamLinkWatcher *link_watcher)
{
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
guint i;
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), FALSE);
g_return_val_if_fail (link_watcher != NULL, FALSE);
for (i = 0; i < priv->link_watchers->len; i++) {
if (nm_team_link_watcher_equal (priv->link_watchers->pdata[i], link_watcher))
return FALSE;
}
g_ptr_array_add (priv->link_watchers, nm_team_link_watcher_dup (link_watcher));
g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS);
return TRUE;
}
/**
* nm_setting_team_port_remove_link_watcher:
* @setting: the #NMSettingTeamPort
* @idx: index number of the link watcher to remove
*
* Removes the link watcher at index #idx.
*
* Since: 1.10.2
**/
void
nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx)
{
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
g_return_if_fail (NM_IS_SETTING_TEAM_PORT (setting));
g_return_if_fail (idx < priv->link_watchers->len);
g_ptr_array_remove_index (priv->link_watchers, idx);
g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS);
}
/**
* nm_setting_team_port_remove_link_watcher_by_value:
* @setting: the #NMSettingTeamPort
* @link_watcher: the link watcher to remove
*
* Removes the link watcher entry matching link_watcher.
*
* Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise.
*
* Since: 1.10.2
**/
gboolean
nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting,
NMTeamLinkWatcher *link_watcher)
{
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
guint i;
g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), FALSE);
for (i = 0; i < priv->link_watchers->len; i++) {
if (nm_team_link_watcher_equal (priv->link_watchers->pdata[i], link_watcher)) {
g_ptr_array_remove_index (priv->link_watchers, i);
g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS);
return TRUE;
}
}
return FALSE;
}
/**
* nm_setting_team_port_clear_link_watchers:
* @setting: the #NMSettingTeamPort
*
* Removes all configured link watchers.
*
* Since: 1.10.2
**/
void
nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting)
{
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
g_return_if_fail (NM_IS_SETTING_TEAM_PORT (setting));
g_ptr_array_set_size (priv->link_watchers, 0);
g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS);
}
static GVariant *
team_link_watchers_to_dbus (const GValue *prop_value)
{
return _nm_utils_team_link_watchers_to_variant (g_value_get_boxed (prop_value));
}
static void
team_link_watchers_from_dbus (GVariant *dbus_value,
GValue *prop_value)
{
g_value_take_boxed (prop_value, _nm_utils_team_link_watchers_from_variant (dbus_value));
}
static gboolean
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
@ -253,6 +409,8 @@ compare_property (NMSetting *setting,
NMSettingCompareFlags flags)
{
NMSettingClass *parent_class;
NMSettingTeamPortPrivate *a_priv, *b_priv;
guint i, j;
/* If we are trying to match a connection in order to assume it (and thus
* @flags contains INFERRABLE), use the "relaxed" matching for team
@ -265,6 +423,24 @@ compare_property (NMSetting *setting,
NM_SETTING_TEAM_PORT_GET_PRIVATE (other)->config,
TRUE);
}
if (nm_streq0 (prop_spec->name, NM_SETTING_TEAM_PORT_LINK_WATCHERS)) {
a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (other);
if (a_priv->link_watchers->len != b_priv->link_watchers->len)
return FALSE;
for (i = 0; i < a_priv->link_watchers->len; i++) {
for (j = 0; j < b_priv->link_watchers->len; j++) {
if (nm_team_link_watcher_equal (a_priv->link_watchers->pdata[i],
b_priv->link_watchers->pdata[j])) {
break;
}
}
if (j == b_priv->link_watchers->len)
return FALSE;
}
return TRUE;
}
/* Otherwise chain up to parent to handle generic compare */
parent_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class);
@ -278,6 +454,7 @@ nm_setting_team_port_init (NMSettingTeamPort *setting)
priv->queue_id = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT;
priv->lacp_prio = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT;
priv->link_watchers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref);
}
#define JSON_TO_VAL(typ, id) _nm_utils_json_extract_##typ (priv->config, _prop_to_keys[id], TRUE)
@ -299,6 +476,9 @@ set_property (GObject *object, guint prop_id,
priv->sticky = JSON_TO_VAL (boolean, PROP_STICKY);
priv->lacp_prio = JSON_TO_VAL (int, PROP_LACP_PRIO);
priv->lacp_key = JSON_TO_VAL (int, PROP_LACP_KEY);
g_ptr_array_unref (priv->link_watchers);
priv->link_watchers = JSON_TO_VAL (ptr_array, PROP_LINK_WATCHERS);
break;
case PROP_QUEUE_ID:
if (priv->queue_id == g_value_get_int (value))
@ -341,6 +521,15 @@ set_property (GObject *object, guint prop_id,
align_value = value;
align_config = TRUE;
break;
case PROP_LINK_WATCHERS:
g_ptr_array_unref (priv->link_watchers);
priv->link_watchers = _nm_utils_copy_array (g_value_get_boxed (value),
(NMUtilsCopyFunc) nm_team_link_watcher_dup,
(GDestroyNotify) nm_team_link_watcher_unref);
if (priv->link_watchers->len)
align_value = value;
align_config = TRUE;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -375,6 +564,11 @@ get_property (GObject *object, guint prop_id,
case PROP_LACP_KEY:
g_value_set_int (value, priv->lacp_key);
break;
case PROP_LINK_WATCHERS:
g_value_take_boxed (value, _nm_utils_copy_array (priv->link_watchers,
(NMUtilsCopyFunc) nm_team_link_watcher_dup,
(GDestroyNotify) nm_team_link_watcher_unref));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -387,6 +581,7 @@ finalize (GObject *object)
NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (object);
g_free (priv->config);
g_ptr_array_unref (priv->link_watchers);
G_OBJECT_CLASS (nm_setting_team_port_parent_class)->finalize (object);
}
@ -500,5 +695,31 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingTeamPort:link-watchers:
*
* Link watchers configuration for the connection: each link watcher is
* defined by a dictionary, whose keys depend upon the selected link
* watcher. Available link watchers are 'ethtool', 'nsna_ping' and
* 'arp_ping' and it is specified in the dictionary with the key 'name'.
* Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait';
* nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host';
* arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active',
* 'validate-incative', 'send-always'. See teamd.conf man for more details.
*
* Element-Type: NMTeamLinkWatcher
* Since: 1.10.2
**/
g_object_class_install_property
(object_class, PROP_LINK_WATCHERS,
g_param_spec_boxed (NM_SETTING_TEAM_PORT_LINK_WATCHERS, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class,
NM_SETTING_TEAM_PORT_LINK_WATCHERS,
G_VARIANT_TYPE ("aa{sv}"),
team_link_watchers_to_dbus,
team_link_watchers_from_dbus);
}

View file

@ -26,6 +26,7 @@
#endif
#include "nm-setting.h"
#include "nm-setting-team.h"
G_BEGIN_DECLS
@ -38,12 +39,13 @@ 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_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_LINK_WATCHERS "link-watchers"
#define NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT -1
#define NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT 255
@ -79,7 +81,24 @@ 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);
NM_AVAILABLE_IN_1_10_2
guint nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcher *
nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx);
NM_AVAILABLE_IN_1_10_2
gboolean
nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting,
NMTeamLinkWatcher *link_watcher);
NM_AVAILABLE_IN_1_10_2
void
nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx);
NM_AVAILABLE_IN_1_10_2
gboolean
nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting,
NMTeamLinkWatcher *link_watcher);
NM_AVAILABLE_IN_1_10_2
void nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting);
G_END_DECLS
#endif /* __NM_SETTING_TEAM_PORT_H__ */

File diff suppressed because it is too large Load diff

View file

@ -29,6 +29,80 @@
G_BEGIN_DECLS
/**
* NMTeamLinkWatcherArpPingFlags:
* @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE: no one among the arp_ping link watcher
* boolean options ('validate_active', 'validate_inactive', 'send_always') is
* enabled (set to true).
* @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE: the arp_ping link watcher
* option 'validate_active' is enabled (set to true).
* @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE: the arp_ping link watcher
* option 'validate_inactive' is enabled (set to true).
* @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS: the arp_ping link watcher option
* 'send_always' is enabled (set to true).
*/
typedef enum { /*< flags >*/
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE = 0, /*< skip >*/
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE = (1 << 1),
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE = (1 << 2),
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS = (1 << 3)
} NMTeamLinkWatcherArpPingFlags;
#define NM_TEAM_LINK_WATCHER_ETHTOOL "ethtool"
#define NM_TEAM_LINK_WATCHER_ARP_PING "arp_ping"
#define NM_TEAM_LINK_WATCHER_NSNA_PING "nsna_ping"
typedef struct NMTeamLinkWatcher NMTeamLinkWatcher;
GType nm_team_link_watcher_get_type (void);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool (gint delay_up,
gint delay_down,
GError **error);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping (gint init_wait,
gint interval,
gint missed_max,
const char *target_host,
GError **error);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (gint init_wait,
gint interval,
gint missed_max,
const char *target_host,
const char *source_host,
NMTeamLinkWatcherArpPingFlags flags,
GError **error);
NM_AVAILABLE_IN_1_10_2
void nm_team_link_watcher_ref (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
void nm_team_link_watcher_unref (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
gboolean nm_team_link_watcher_equal (NMTeamLinkWatcher *watcher, NMTeamLinkWatcher *other);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcher *nm_team_link_watcher_dup (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
const char *nm_team_link_watcher_get_name (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
int nm_team_link_watcher_get_delay_up (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
int nm_team_link_watcher_get_delay_down (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
int nm_team_link_watcher_get_init_wait (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
int nm_team_link_watcher_get_interval (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
int nm_team_link_watcher_get_missed_max (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
const char *nm_team_link_watcher_get_target_host (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
const char *nm_team_link_watcher_get_source_host (NMTeamLinkWatcher *watcher);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher);
#define NM_TYPE_SETTING_TEAM (nm_setting_team_get_type ())
#define NM_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam))
#define NM_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEAM, NMSettingTeamClass))
@ -53,6 +127,7 @@ G_BEGIN_DECLS
#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_LINK_WATCHERS "link-watchers"
#define NM_SETTING_TEAM_RUNNER_BROADCAST "broadcast"
#define NM_SETTING_TEAM_RUNNER_ROUNDROBIN "roundrobin"
@ -78,6 +153,7 @@ G_BEGIN_DECLS
#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:
*
@ -130,11 +206,25 @@ gboolean nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting,
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);
const char *nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, guint idx);
NM_AVAILABLE_IN_1_10_2
void nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, int idx);
void nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, guint idx);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash);
NM_AVAILABLE_IN_1_10_2
guint nm_setting_team_get_num_link_watchers (NMSettingTeam *setting);
NM_AVAILABLE_IN_1_10_2
NMTeamLinkWatcher * nm_setting_team_get_link_watcher (NMSettingTeam *setting, guint idx);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_add_link_watcher (NMSettingTeam *setting,
NMTeamLinkWatcher *link_watcher);
NM_AVAILABLE_IN_1_10_2
void nm_setting_team_remove_link_watcher (NMSettingTeam *setting, guint idx);
NM_AVAILABLE_IN_1_10_2
gboolean nm_setting_team_remove_link_watcher_by_value (NMSettingTeam *setting,
NMTeamLinkWatcher *link_watcher);
NM_AVAILABLE_IN_1_10_2
void nm_setting_team_clear_link_watchers (NMSettingTeam *setting);
G_END_DECLS
#endif /* __NM_SETTING_TEAM_H__ */

View file

@ -78,6 +78,8 @@ void _nm_utils_bytes_from_dbus (GVariant *dbus_value,
char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length);
GPtrArray * _nm_utils_team_link_watchers_from_variant (GVariant *value);
GVariant * _nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers);
/* JSON to GValue conversion macros */
@ -160,6 +162,30 @@ _nm_utils_json_extract_strv (char *conf,
return ret;
}
static inline GPtrArray *
_nm_utils_json_extract_ptr_array (char *conf,
_NMUtilsTeamPropertyKeys key,
gboolean is_port)
{
gs_free GValue *t_value = NULL;
GPtrArray *data, *ret;
guint i;
ret = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref);
t_value = _nm_utils_team_config_get (conf, key.key1, key.key2, key.key3, is_port);
if (!t_value)
return ret;
data = g_value_get_boxed (t_value);
if (!data)
return ret;
for (i = 0; i < data->len; i++)
g_ptr_array_add (ret, nm_team_link_watcher_dup (data->pdata[i]));
g_value_unset (t_value);
return ret;
}
static inline void
_nm_utils_json_append_gvalue (char **conf,
_NMUtilsTeamPropertyKeys key,

View file

@ -4302,6 +4302,14 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to)
#if WITH_JANSSON
/* Added in Jansson v2.3 (released Jan 27 2012) */
#ifndef json_object_foreach
#define json_object_foreach(object, key, value) \
for(key = json_object_iter_key(json_object_iter(object)); \
key && (value = json_object_iter_value(json_object_iter_at (object, key) )); \
key = json_object_iter_key(json_object_iter_next(object, json_object_iter_at (object, key))))
#endif
/* 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())
@ -4320,6 +4328,419 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to)
#define json_boolean_value json_is_true
#endif
static void
_json_add_object (json_t *json,
const char *key1,
const char *key2,
const char *key3,
json_t *value)
{
json_t *json_element, *json_link;
json_element = json_object_get (json, key1);
if (!json_element) {
json_element = value;
if (key2) {
if (key3) {
json_element = json_object ();
json_object_set_new (json_element, key3, value);
}
json_link = json_object ();
json_object_set_new (json_link, key2, json_element);
json_element = json_link;
}
json_object_set_new (json, key1, json_element);
return;
}
if (!key2)
goto key_already_there;
json_link = json_element;
json_element = json_object_get (json_element, key2);
if (!json_element) {
json_element = value;
if (key3) {
json_element = json_object ();
json_object_set_new (json_element, key3, value);
}
json_object_set_new (json_link, key2, json_element);
return;
}
if (!key3)
goto key_already_there;
json_link = json_element;
json_element = json_object_get (json_element, key3);
if (!json_element) {
json_object_set_new (json_link, key3, value);
return;
}
key_already_there:
json_decref (value);
}
/*
* Removes the specified key1[.key2.key3] from json.
* Returns TRUE if json has been modified, FALSE otherwise. */
static gboolean
_json_del_object (json_t *json,
const char *key1,
const char *key2,
const char *key3)
{
json_t *json_element = json;
json_t *json_link = NULL;
const char *iter_key = key1;
if (key2) {
json_link = json;
json_element = json_object_get (json, key1);
if (!json_element)
return FALSE;
iter_key = key2;
}
if (key3) {
json_link = json_element;
json_element = json_object_get (json_element, key2);
if (!json_element)
return FALSE;
iter_key = key3;
}
if (json_object_del (json_element, iter_key) != 0)
return FALSE;
/* 1st level key only */
if (!json_link)
return TRUE;
if (json_object_size (json_element) == 0)
json_object_del (json_link, (key3 ? key2 : key1));
if (key3 && json_object_size (json_link) == 0)
json_object_del (json, key1);
return TRUE;
}
/* Adds in place to json the defaults for missing properties;
* the "add_implicit" allows to add to the json also the default
* values used but not shown with teamdctl */
static void
_json_team_add_defaults (json_t *json,
gboolean port_config,
gboolean add_implicit)
{
json_t *json_element;
const char *runner = NULL;
if (port_config) {
_json_add_object (json, "link_watch", "name", NULL,
json_string (NM_TEAM_LINK_WATCHER_ETHTOOL));
return;
}
/* Retrieve runner or add default one */
json_element = json_object_get (json, "runner");
if (json_element) {
runner = json_string_value (json_object_get (json_element, "name"));
} else {
json_element = json_object ();
json_object_set_new (json, "runner", json_element);
}
if (!runner) {
runner = NM_SETTING_TEAM_RUNNER_DEFAULT;
json_object_set_new (json_element, "name", json_string (runner));
}
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) {
_json_add_object (json, "notify_peers", "count", NULL,
json_integer (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT));
_json_add_object (json, "mcast_rejoin", "count", NULL,
json_integer (NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT));
} else if ( nm_streq (runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE)
|| nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) {
json_element = json_array ();
json_array_append_new (json_element, json_string ("eth"));
json_array_append_new (json_element, json_string ("ipv4"));
json_array_append_new (json_element, json_string ("ipv6"));
_json_add_object (json, "runner", "tx_hash", NULL, json_element);
}
if (!add_implicit)
return;
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP))
_json_add_object (json, "runner", "hwaddr_policy", NULL, json_string ("same_all"));
else if (NM_IN_STRSET (runner,
NM_SETTING_TEAM_RUNNER_LOADBALANCE,
NM_SETTING_TEAM_RUNNER_LACP)) {
_json_add_object (json, "runner", "tx_balancer", "balancing_interval",
json_integer (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT));
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) {
_json_add_object (json, "runner", "active", NULL, json_boolean (TRUE));
_json_add_object (json, "runner", "sys_prio", NULL,
json_integer (NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT));
_json_add_object (json, "runner", "min_ports", NULL, json_integer (0));
_json_add_object (json, "runner", "agg_select_policy", NULL,
json_string (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT));
}
}
}
static json_t *
_json_find_object (json_t *json,
const char *key1,
const char *key2,
const char *key3)
{
json_t *json_element;
if (!key1)
return NULL;
json_element = json_object_get (json, key1);
if (!key2 || !json_element)
return json_element;
json_element = json_object_get (json_element, key2);
if (!key3 || !json_element)
return json_element;
json_element = json_object_get (json_element, key3);
return json_element;
}
static inline void
_json_delete_object_on_int_match (json_t *json,
const char *key1,
const char *key2,
const char *key3,
int val)
{
json_t *json_element;
json_element = _json_find_object (json, key1, key2, key3);
if (!json_element || !json_is_integer (json_element))
return;
if (json_integer_value (json_element) == val)
_json_del_object (json, key1, key2, key3);
}
static inline void
_json_delete_object_on_bool_match (json_t *json,
const char *key1,
const char *key2,
const char *key3,
gboolean val)
{
json_t *json_element;
json_element = _json_find_object (json, key1, key2, key3);
if (!json_element || !json_is_boolean (json_element))
return;
if (json_boolean_value (json_element) == val)
_json_del_object (json, key1, key2, key3);
}
static inline void
_json_delete_object_on_string_match (json_t *json,
const char *key1,
const char *key2,
const char *key3,
const char *val)
{
json_t *json_element;
json_element = _json_find_object (json, key1, key2, key3);
if (!json_element || !json_is_string (json_element))
return;
if (nm_streq0 (json_string_value (json_element), val))
_json_del_object (json, key1, key2, key3);
}
static void
_json_team_normalize_defaults (json_t *json, gboolean reset)
{
json_t *json_element;
const char *runner = NM_SETTING_TEAM_RUNNER_DEFAULT;
int notify_peers_count = 0, notify_peers_interval = 0;
int mcast_rejoin_count = 0, mcast_rejoin_interval = 0;
int runner_tx_balancer_interval = -1;
gboolean runner_active = FALSE, runner_fast_rate = FALSE;
int runner_sys_prio = -1, runner_min_ports = -1;
json_element = _json_find_object (json, "runner", "name", NULL);
if (json_element) {
runner = json_string_value (json_element);
_json_delete_object_on_string_match (json, "runner", "name", NULL,
NM_SETTING_TEAM_RUNNER_DEFAULT);
}
/* the runner changed: clear all the properties. Then team.config will be saved
* and reloaded triggering the reset of the values through _nm_utils_team_config_get
*/
if (reset) {
_json_del_object (json, "notify_peers", "count", NULL);
_json_del_object (json, "notify_peers", "interval", NULL);
_json_del_object (json, "mcast_rejoin", "count", NULL);
_json_del_object (json, "mcast_rejoin", "interval", NULL);
_json_del_object (json, "runner", "hwaddr_policy", NULL);
_json_del_object (json, "runner", "tx_hash", NULL);
_json_del_object (json, "runner", "tx_balancer", "name");
_json_del_object (json, "runner", "tx_balancer", "balancing_interval");
_json_del_object (json, "runner", "active", NULL);
_json_del_object (json, "runner", "fast_rate", NULL);
_json_del_object (json, "runner", "sys_prio", NULL);
_json_del_object (json, "runner", "min_ports", NULL);
_json_del_object (json, "runner", "agg_select_policy", NULL);
return;
}
if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) {
notify_peers_count = 1;
mcast_rejoin_count = 1;
_json_delete_object_on_string_match (json, "runner", "hwaddr_policy", NULL,
NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT);
} else if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LACP)) {
runner_tx_balancer_interval = 50;
runner_active = TRUE;
runner_sys_prio = 255;
runner_min_ports = 0;
_json_delete_object_on_string_match (json, "runner", "agg_select_policy", NULL,
NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT);
} else if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE))
runner_tx_balancer_interval = 50;
_json_delete_object_on_int_match (json, "notify_peers", "count", NULL, notify_peers_count);
_json_delete_object_on_int_match (json, "notify_peers", "interval", NULL, notify_peers_interval);
_json_delete_object_on_int_match (json, "mcast_rejoin", "count", NULL, mcast_rejoin_count);
_json_delete_object_on_int_match (json, "macst_rejoin", "interval", NULL, mcast_rejoin_interval);
_json_delete_object_on_int_match (json, "runner", "tx_balancer", "balancing_interval",
runner_tx_balancer_interval);
_json_delete_object_on_int_match (json, "runner", "sys_prio", NULL, runner_sys_prio);
_json_delete_object_on_int_match (json, "runner", "min_ports", NULL, runner_min_ports);
_json_delete_object_on_bool_match (json, "runner", "active", NULL, runner_active);
_json_delete_object_on_bool_match (json, "runner", "active", NULL, runner_active);
_json_delete_object_on_bool_match (json, "runner", "fast_rate", NULL, runner_fast_rate);
}
static NMTeamLinkWatcher *
_nm_utils_team_link_watcher_from_json (json_t *json_element)
{
const char *j_key;
json_t *j_val;
gs_free char *name = NULL, *target_host = NULL, *source_host = NULL;
int val1 = 0, val2 = 0, val3 = 3;
NMTeamLinkWatcherArpPingFlags flags = 0;
g_return_val_if_fail (json_element, NULL);
json_object_foreach (json_element, j_key, j_val) {
if (nm_streq (j_key, "name"))
name = strdup (json_string_value (j_val));
else if (nm_streq (j_key, "target_host"))
target_host = strdup (json_string_value (j_val));
else if (nm_streq (j_key, "source_host"))
source_host = strdup (json_string_value (j_val));
else if (NM_IN_STRSET (j_key, "delay_up", "init_wait"))
val1 = json_integer_value (j_val);
else if (NM_IN_STRSET (j_key, "delay_down", "interval"))
val2 = json_integer_value (j_val);
else if (nm_streq (j_key, "missed_max"))
val3 = json_integer_value (j_val);
else if (nm_streq (j_key, "validate_active")) {
if (json_is_true (j_val))
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE;
} else if (nm_streq (j_key, "validate_inactive")) {
if (json_is_true (j_val))
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE;
} else if (nm_streq (j_key, "send_always")) {
if (json_is_true (j_val))
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS;
}
}
if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ETHTOOL))
return nm_team_link_watcher_new_ethtool (val1, val2, NULL);
else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
return nm_team_link_watcher_new_nsna_ping (val1, val2, val3, target_host, NULL);
else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ARP_PING)) {
return nm_team_link_watcher_new_arp_ping (val1, val2, val3, target_host,
source_host, flags, NULL);
} else
return NULL;
}
static json_t *
_nm_utils_team_link_watcher_to_json (NMTeamLinkWatcher *watcher)
{
const char *name;
int int_val;
const char *str_val;
NMTeamLinkWatcherArpPingFlags flags = 0;
json_t *json_element;
g_return_val_if_fail (watcher, NULL);
json_element = json_object ();
name = nm_team_link_watcher_get_name (watcher);
if (!name)
goto fail;
json_object_set_new (json_element, "name", json_string (name));
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
int_val = nm_team_link_watcher_get_delay_up (watcher);
if (int_val)
json_object_set_new (json_element, "delay_up", json_integer (int_val));
int_val = nm_team_link_watcher_get_delay_down (watcher);
if (int_val)
json_object_set_new (json_element, "delay_down", json_integer (int_val));
return json_element;
}
int_val = nm_team_link_watcher_get_init_wait (watcher);
if (int_val)
json_object_set_new (json_element, "init_wait", json_integer (int_val));
int_val = nm_team_link_watcher_get_interval (watcher);
if (int_val)
json_object_set_new (json_element, "interval", json_integer (int_val));
int_val = nm_team_link_watcher_get_missed_max (watcher);
if (int_val != 3)
json_object_set_new (json_element, "missed_max", json_integer (int_val));
str_val = nm_team_link_watcher_get_target_host (watcher);
if (!str_val)
goto fail;
json_object_set_new (json_element, "target_host", json_string (str_val));
if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
return json_element;
str_val = nm_team_link_watcher_get_source_host (watcher);
if (!str_val)
goto fail;
json_object_set_new (json_element, "source_host", json_string (str_val));
flags = nm_team_link_watcher_get_flags (watcher);
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE)
json_object_set_new (json_element, "validate_active", json_string ("true"));
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE)
json_object_set_new (json_element, "validate_inactive", json_string ("true"));
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS)
json_object_set_new (json_element, "send_always", json_string ("true"));
return json_element;
fail:
json_decref (json_element);
return NULL;
}
/**
* nm_utils_is_json_object:
* @str: the JSON string to test
@ -4388,9 +4809,8 @@ _nm_utils_team_config_equal (const char *conf1,
gboolean port_config)
{
json_t *json1 = NULL, *json2 = NULL, *json;
json_t *array, *name;
gs_free char *dump1 = NULL, *dump2 = NULL;
json_t *value, *property;
json_t *value;
json_error_t jerror;
const char *key;
gboolean ret;
@ -4414,33 +4834,8 @@ _nm_utils_team_config_equal (const char *conf1,
* configuration. Add them with the default value if necessary, depending
* on the configuration type.
*/
for (i = 0, json = json1; i < 2; i++, json = json2) {
if (port_config) {
property = json_object_get (json, "link_watch");
if (!property) {
property = json_object ();
json_object_set_new (property, "name", json_string ("ethtool"));
json_object_set_new (json, "link_watch", property);
}
} else {
property = json_object_get (json, "runner");
if (!property) {
property = json_object ();
json_object_set_new (property, "name", json_string ("roundrobin"));
json_object_set_new (json, "runner", property);
} else if ( (name = json_object_get (property, "name"))
&& NM_IN_STRSET (json_string_value (name), "lacp", "loadbalance")) {
/* Add default tx_hash when missing */
if (!json_object_get (property, "tx_hash")) {
array = json_array ();
json_array_append_new (array, json_string ("eth"));
json_array_append_new (array, json_string ("ipv4"));
json_array_append_new (array, json_string ("ipv6"));
json_object_set_new (property, "tx_hash", array);
}
}
}
}
for (i = 0, json = json1; i < 2; i++, json = json2)
_json_team_add_defaults (json, port_config, FALSE);
/* Only consider a given subset of nodes, others can change depending on
* current state */
@ -4466,61 +4861,6 @@ out:
}
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,
@ -4532,7 +4872,6 @@ _nm_utils_team_config_get (const char *conf,
json_t *json_element;
GValue *value = NULL;
json_error_t jerror;
const char *runner = NULL;
if (!key)
return NULL;
@ -4546,38 +4885,16 @@ _nm_utils_team_config_get (const char *conf,
/* Some properties are added by teamd when missing from the initial
* configuration. Add them with the default value if necessary, depending
* on the configuration type.
* Skip this for port config, as some properties change on the basis of the
* runner specified in the master connection... but we don't want to check
* against properties in another connection. Moreover, for team-port we have
* the link-watchers property only here: and for this compound property it is
* fine to show the default value only if explicitly set.
*/
if (port_config) {
_json_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 (!port_config)
_json_team_add_defaults (json, port_config, TRUE);
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);
}
}
/* Now search the property to retrieve */
json_element = json_object_get (json, key);
if (json_element && key2)
json_element = json_object_get (json_element, key2);
@ -4595,6 +4912,31 @@ _nm_utils_team_config_get (const char *conf,
} else if (json_is_boolean (json_element)) {
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, json_boolean_value (json_element));
} else if (nm_streq (key, "link_watch")) {
NMTeamLinkWatcher *watcher;
GPtrArray *data = g_ptr_array_new_with_free_func
((GDestroyNotify) nm_team_link_watcher_unref);
if (json_is_array (json_element)) {
json_t *j_watcher;
int index;
json_array_foreach (json_element, index, j_watcher) {
watcher = _nm_utils_team_link_watcher_from_json (j_watcher);
if (watcher)
g_ptr_array_add (data, watcher);
}
} else {
watcher = _nm_utils_team_link_watcher_from_json (json_element);
if (watcher)
g_ptr_array_add (data, watcher);
}
if (data->len) {
g_value_init (value, G_TYPE_PTR_ARRAY);
g_value_take_boxed (value, data);
} else
g_ptr_array_free (data, TRUE);
} else if (json_is_array (json_element)) {
GPtrArray *data = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
json_t *str_element;
@ -4634,8 +4976,12 @@ _nm_utils_team_config_set (char **conf,
json_error_t jerror;
gboolean updated = FALSE;
char **strv;
GPtrArray *array;
const char *iter_key = key;
int i;
NMTeamLinkWatcher *watcher;
g_return_val_if_fail (key, FALSE);
json = json_loads (*conf?: "{}", JSON_REJECT_DUPLICATES, &jerror);
if (!json)
@ -4643,38 +4989,7 @@ _nm_utils_team_config_set (char **conf,
/* 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);
updated = _json_del_object (json, key, key2, key3);
goto done;
}
@ -4687,14 +5002,51 @@ _nm_utils_team_config_set (char **conf,
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) {
if (nm_streq (key, "link_watch")) {
array = g_value_get_boxed (value);
if (!array || !array->len) {
updated = FALSE;
goto done;
}
/*
* json_value: will hold the final link_watcher json (array) object
* json_element: is the next link_watcher to append to json_value
* json_link: used to transit the json_value from a single link_watcher
* object to an array of link watcher objects
*/
json_value = NULL;
for (i = 0; i < array->len; i++) {
watcher = array->pdata[i];
json_element = _nm_utils_team_link_watcher_to_json (watcher);
if (!json_element)
continue;
if (!json_value) {
json_value = json_element;
continue;
}
if (!json_is_array (json_value)) {
json_link = json_value;
json_value = json_array ();
json_array_append_new (json_value, json_link);
}
json_array_append_new (json_value, json_element);
}
} else if ( nm_streq (key, "runner")
&& nm_streq0 (key2, "tx_hash")) {
strv = g_value_get_boxed (value);
if (!strv) {
updated = FALSE;
goto done;
}
json_value = json_array ();
for (i = 0; strv[i]; i++)
json_array_append_new (json_value, json_string (strv[i]));
} else
return FALSE;
} else {
} else {
updated = FALSE;
goto done;
}
} else { /* G_VALUE_HOLDS_? */
g_assert_not_reached ();
updated = FALSE;
goto done;
@ -4727,8 +5079,10 @@ _nm_utils_team_config_set (char **conf,
done:
if (updated) {
_json_team_normalize_defaults (json, ( nm_streq0 (key, "runner")
&& nm_streq0 (key2, "name")));
g_free (*conf);
*conf = json_dumps (json, 0);
*conf = json_dumps (json, JSON_PRESERVE_ORDER);
/* Don't save an empty config */
if (nm_streq0 (*conf, "{}")) {
g_free (*conf);
@ -4815,6 +5169,202 @@ _nm_utils_team_config_set (char **conf,
}
#endif
/**
* _nm_utils_team_link_watchers_to_variant:
* @link_watchers: (element-type NMTeamLinkWatcher): array of #NMTeamLinkWatcher
*
* Utility function to convert a #GPtrArray of #NMTeamLinkWatcher objects
* representing link watcher configuration for team devices into a #GVariant
* of type 'aa{sv}' representing an array of link watchers.
*
* Returns: (transfer none): a new floating #GVariant representing link watchers.
**/
GVariant *
_nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers)
{
GVariantBuilder builder;
int i;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
if (!link_watchers)
goto end;
for (i = 0; i < link_watchers->len; i++) {
NMTeamLinkWatcher *watcher = link_watchers->pdata[i];
GVariantBuilder watcher_builder;
const char *name;
int int_val;
NMTeamLinkWatcherArpPingFlags flags;
g_variant_builder_init (&watcher_builder, G_VARIANT_TYPE ("a{sv}"));
name = nm_team_link_watcher_get_name (watcher);
g_variant_builder_add (&watcher_builder, "{sv}",
"name",
g_variant_new_string (name));
if nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL) {
int_val = nm_team_link_watcher_get_delay_up (watcher);
if (int_val) {
g_variant_builder_add (&watcher_builder, "{sv}",
"delay-up",
g_variant_new_int32 (int_val));
}
int_val = nm_team_link_watcher_get_delay_down (watcher);
if (int_val) {
g_variant_builder_add (&watcher_builder, "{sv}",
"delay-down",
g_variant_new_int32 (int_val));
}
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
continue;
}
/* Common properties for arp_ping and nsna_ping link watchers */
int_val = nm_team_link_watcher_get_init_wait (watcher);
if (int_val) {
g_variant_builder_add (&watcher_builder, "{sv}",
"init-wait",
g_variant_new_int32 (int_val));
}
int_val = nm_team_link_watcher_get_interval (watcher);
if (int_val) {
g_variant_builder_add (&watcher_builder, "{sv}",
"interval",
g_variant_new_int32 (int_val));
}
int_val = nm_team_link_watcher_get_missed_max (watcher);
if (int_val != 3) {
g_variant_builder_add (&watcher_builder, "{sv}",
"missed-max",
g_variant_new_int32 (int_val));
}
g_variant_builder_add (&watcher_builder, "{sv}",
"target-host",
g_variant_new_string (nm_team_link_watcher_get_target_host (watcher)));
if nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING) {
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
continue;
}
/* arp_ping watcher only */
g_variant_builder_add (&watcher_builder, "{sv}",
"source-host",
g_variant_new_string (nm_team_link_watcher_get_source_host (watcher)));
flags = nm_team_link_watcher_get_flags (watcher);
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE) {
g_variant_builder_add (&watcher_builder, "{sv}",
"validate-active",
g_variant_new_boolean (TRUE));
}
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE) {
g_variant_builder_add (&watcher_builder, "{sv}",
"validate-inactive",
g_variant_new_boolean (TRUE));
}
if (flags & NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS) {
g_variant_builder_add (&watcher_builder, "{sv}",
"send-always",
g_variant_new_boolean (TRUE));
}
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
}
end:
return g_variant_builder_end (&builder);
}
/**
* _nm_utils_team_link_watchers_from_variant:
* @value: a #GVariant of type 'aa{sv}'
*
* Utility function to convert a #GVariant representing a list of team link
* watchers int a #GPtrArray of #NMTeamLinkWatcher objects.
*
* Returns: (transfer full) (element-type NMTeamLinkWatcher): a newly allocated
* #GPtrArray of #NMTeamLinkWatcher objects.
**/
GPtrArray *
_nm_utils_team_link_watchers_from_variant (GVariant *value)
{
GPtrArray *link_watchers;
GVariantIter iter;
GVariant *watcher_var;
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
link_watchers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref);
g_variant_iter_init (&iter, value);
while (g_variant_iter_next (&iter, "@a{sv}", &watcher_var)) {
NMTeamLinkWatcher *watcher;
const char *name;
int val1, val2, val3 = 0;
const char *target_host = NULL, *source_host = NULL;
gboolean bval;
NMTeamLinkWatcherArpPingFlags flags = NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE;
GError *error = NULL;
if (!g_variant_lookup (watcher_var, "name", "&s", &name))
goto next;
if (!NM_IN_STRSET (name,
NM_TEAM_LINK_WATCHER_ETHTOOL,
NM_TEAM_LINK_WATCHER_ARP_PING,
NM_TEAM_LINK_WATCHER_NSNA_PING)) {
goto next;
}
if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
if (!g_variant_lookup (watcher_var, "delay-up", "i", &val1))
val1 = 0;
if (!g_variant_lookup (watcher_var, "delay-down", "i", &val2))
val2 = 0;
watcher = nm_team_link_watcher_new_ethtool (val1, val2, &error);
} else {
if (!g_variant_lookup (watcher_var, "target-host", "&s", &target_host))
goto next;
if (!g_variant_lookup (watcher_var, "init_wait", "i", &val1))
val1 = 0;
if (!g_variant_lookup (watcher_var, "interval", "i", &val2))
val2 = 0;
if (!g_variant_lookup (watcher_var, "missed-max", "i", &val3))
val3 = 3;
if nm_streq (name, NM_TEAM_LINK_WATCHER_ARP_PING) {
if (!g_variant_lookup (watcher_var, "source-host", "&s", &source_host))
goto next;
if (!g_variant_lookup (watcher_var, "validate-active", "b", &bval))
bval = FALSE;
if (bval)
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE;
if (!g_variant_lookup (watcher_var, "validate-inactive", "b", &bval))
bval = FALSE;
if (bval)
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE;
if (!g_variant_lookup (watcher_var, "send-always", "b", &bval))
bval = FALSE;
if (bval)
flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS;
watcher = nm_team_link_watcher_new_arp_ping (val1, val2, val3,
target_host, source_host,
flags, &error);
} else
watcher = nm_team_link_watcher_new_nsna_ping (val1, val2, val3,
target_host, &error);
}
if (!watcher) {
g_clear_error (&error);
goto next;
}
g_ptr_array_add (link_watchers, watcher);
next:
g_variant_unref (watcher_var);
}
return link_watchers;
}
static char *
attribute_escape (const char *src, char c1, char c2)
{

View file

@ -1,404 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2008 - 2011 Red Hat, Inc.
*
*/
#include "nm-default.h"
#include <string.h>
#include "nm-utils.h"
#include "nm-setting-connection.h"
#include "nm-setting-8021x.h"
#include "nm-utils/nm-test-utils.h"
static void
compare_blob_data (const char *test,
const char *key_path,
GBytes *key)
{
char *contents = NULL;
gsize len = 0;
GError *error = NULL;
gboolean success;
g_assert (key && g_bytes_get_size (key) > 0);
success = g_file_get_contents (key_path, &contents, &len, &error);
nmtst_assert_success (success, error);
g_assert_cmpmem (contents, len, g_bytes_get_data (key, NULL), g_bytes_get_size (key));
g_free (contents);
}
static void
check_scheme_path (GBytes *value, const char *path)
{
const guint8 *p;
g_assert (value);
p = g_bytes_get_data (value, NULL);
g_assert (memcmp (p, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0);
p += strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
g_assert (memcmp (p, path, strlen (path)) == 0);
p += strlen (path);
g_assert (*p == '\0');
}
static void
test_private_key_import (const char *path,
const char *password,
NMSetting8021xCKScheme scheme)
{
NMSetting8021x *s_8021x;
gboolean success;
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
NMSetting8021xCKFormat tmp_fmt;
GError *error = NULL;
GBytes *tmp_key = NULL, *client_cert = NULL;
const char *pw;
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
g_assert (s_8021x);
success = nm_setting_802_1x_set_private_key (s_8021x,
path,
password,
scheme,
&format,
&error);
nmtst_assert_success (success, error);
g_assert (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
tmp_fmt = nm_setting_802_1x_get_private_key_format (s_8021x);
g_assert (tmp_fmt == format);
/* Make sure the password is what we expect */
pw = nm_setting_802_1x_get_private_key_password (s_8021x);
g_assert (pw != NULL);
g_assert_cmpstr (pw, ==, password);
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
tmp_key = nm_setting_802_1x_get_private_key_blob (s_8021x);
compare_blob_data ("private-key-import", path, tmp_key);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
g_object_get (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL);
check_scheme_path (tmp_key, path);
g_bytes_unref (tmp_key);
} else
g_assert_not_reached ();
/* If it's PKCS#12 ensure the client cert is the same value */
if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
g_object_get (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL);
g_assert (tmp_key);
g_object_get (s_8021x, NM_SETTING_802_1X_CLIENT_CERT, &client_cert, NULL);
g_assert (client_cert);
/* make sure they are the same */
g_assert (g_bytes_equal (tmp_key, client_cert));
g_bytes_unref (tmp_key);
g_bytes_unref (client_cert);
}
g_object_unref (s_8021x);
}
static void
test_phase2_private_key_import (const char *path,
const char *password,
NMSetting8021xCKScheme scheme)
{
NMSetting8021x *s_8021x;
gboolean success;
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
NMSetting8021xCKFormat tmp_fmt;
GError *error = NULL;
GBytes *tmp_key = NULL, *client_cert = NULL;
const char *pw;
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
g_assert (s_8021x);
success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
path,
password,
scheme,
&format,
&error);
nmtst_assert_success (success, error);
g_assert (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
tmp_fmt = nm_setting_802_1x_get_phase2_private_key_format (s_8021x);
g_assert (tmp_fmt == format);
/* Make sure the password is what we expect */
pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
g_assert (pw);
g_assert_cmpstr (pw, ==, password);
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
tmp_key = nm_setting_802_1x_get_phase2_private_key_blob (s_8021x);
compare_blob_data ("phase2-private-key-import", path, tmp_key);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL);
check_scheme_path (tmp_key, path);
g_bytes_unref (tmp_key);
} else
g_assert_not_reached ();
/* If it's PKCS#12 ensure the client cert is the same value */
if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL);
g_assert (tmp_key);
g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &client_cert, NULL);
g_assert (client_cert);
/* make sure they are the same */
g_assert (g_bytes_equal (tmp_key, client_cert));
g_bytes_unref (tmp_key);
g_bytes_unref (client_cert);
}
g_object_unref (s_8021x);
}
static void
test_wrong_password_keeps_data (const char *path, const char *password)
{
NMSetting8021x *s_8021x;
gboolean success;
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
GError *error = NULL;
const char *pw;
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
g_assert (s_8021x);
success = nm_setting_802_1x_set_private_key (s_8021x,
path,
password,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
&format,
&error);
nmtst_assert_success (success, error);
g_assert (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
/* Now try to set it to something that's not a certificate */
format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
success = nm_setting_802_1x_set_private_key (s_8021x,
"Makefile.am",
password,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
&format,
&error);
nmtst_assert_no_success (success, error);
g_assert (format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
g_clear_error (&error);
/* Make sure the password hasn't changed */
pw = nm_setting_802_1x_get_private_key_password (s_8021x);
g_assert (pw);
g_assert_cmpstr (pw, ==, password);
g_object_unref (s_8021x);
}
static void
test_clear_private_key (const char *path, const char *password)
{
NMSetting8021x *s_8021x;
gboolean success;
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
GError *error = NULL;
const char *pw;
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
g_assert (s_8021x);
success = nm_setting_802_1x_set_private_key (s_8021x,
path,
password,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
&format,
&error);
nmtst_assert_success (success, error);
g_assert (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
/* Make sure the password is what we expect */
pw = nm_setting_802_1x_get_private_key_password (s_8021x);
g_assert (pw);
g_assert_cmpstr (pw, ==, password);
/* Now clear it */
success = nm_setting_802_1x_set_private_key (s_8021x,
NULL,
NULL,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
NULL,
&error);
nmtst_assert_success (success, error);
/* Ensure the password is also now clear */
g_assert (!nm_setting_802_1x_get_private_key_password (s_8021x));
g_object_unref (s_8021x);
}
static void
test_wrong_phase2_password_keeps_data (const char *path, const char *password)
{
NMSetting8021x *s_8021x;
gboolean success;
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
GError *error = NULL;
const char *pw;
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
g_assert (s_8021x);
success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
path,
password,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
&format,
&error);
nmtst_assert_success (success, error);
g_assert (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
/* Now try to set it to something that's not a certificate */
format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
"Makefile.am",
password,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
&format,
&error);
nmtst_assert_no_success (success, error);
g_assert (format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
g_clear_error (&error);
/* Make sure the password hasn't changed */
pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
g_assert (pw);
g_assert_cmpstr (pw, ==, password);
g_object_unref (s_8021x);
}
static void
test_clear_phase2_private_key (const char *path, const char *password)
{
NMSetting8021x *s_8021x;
gboolean success;
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
GError *error = NULL;
const char *pw;
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
g_assert (s_8021x);
success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
path,
password,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
&format,
&error);
nmtst_assert_success (success, error);
g_assert (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
/* Make sure the password is what we expect */
pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
g_assert (pw);
g_assert_cmpstr (pw, ==, password);
/* Now clear it */
success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
NULL,
NULL,
NM_SETTING_802_1X_CK_SCHEME_BLOB,
NULL,
&error);
nmtst_assert_success (success, error);
/* Ensure the password is also now clear */
g_assert (!nm_setting_802_1x_get_phase2_private_key_password (s_8021x));
g_object_unref (s_8021x);
}
static void
do_8021x_test (gconstpointer test_data)
{
char **parts, *path, *password;
parts = g_strsplit ((const char *) test_data, ", ", -1);
g_assert_cmpint (g_strv_length (parts), ==, 2);
path = g_build_filename (TEST_CERT_DIR, parts[0], NULL);
password = parts[1];
/* Test phase1 and phase2 path scheme */
test_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_PATH);
test_phase2_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_PATH);
/* Test phase1 and phase2 blob scheme */
test_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB);
test_phase2_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB);
/* Test that using a wrong password does not change existing data */
test_wrong_password_keeps_data (path, password);
test_wrong_phase2_password_keeps_data (path, password);
/* Test clearing the private key */
test_clear_private_key (path, password);
test_clear_phase2_private_key (path, password);
g_free (path);
g_strfreev (parts);
}
NMTST_DEFINE ();
int
main (int argc, char **argv)
{
nmtst_init (&argc, &argv, TRUE);
g_test_add_data_func ("/libnm/setting-8021x/key-and-cert",
"test_key_and_cert.pem, test",
do_8021x_test);
g_test_add_data_func ("/libnm/setting-8021x/key-only",
"test-key-only.pem, test",
do_8021x_test);
g_test_add_data_func ("/libnm/setting-8021x/pkcs8-enc-key",
"pkcs8-enc-key.pem, 1234567890",
do_8021x_test);
g_test_add_data_func ("/libnm/setting-8021x/pkcs12",
"test-cert.p12, test",
do_8021x_test);
return g_test_run ();
}

View file

@ -1,247 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2016 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-utils.h"
#include "nm-setting-bond.h"
#include "nm-connection.h"
#include "nm-simple-connection.h"
#include "nm-setting-connection.h"
#include "nm-errors.h"
#include "nm-utils/nm-test-utils.h"
static void
create_bond_connection (NMConnection **con, NMSettingBond **s_bond)
{
NMSettingConnection *s_con;
g_assert (con);
g_assert (s_bond);
*con = nmtst_create_minimal_connection ("bond",
NULL,
NM_SETTING_BOND_SETTING_NAME,
&s_con);
g_assert (*con);
g_assert (s_con);
g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bond0", NULL);
*s_bond = (NMSettingBond *) nm_setting_bond_new ();
g_assert (*s_bond);
nm_connection_add_setting (*con, NM_SETTING (*s_bond));
}
#define test_verify_options(exp, ...) \
G_STMT_START { \
const char *__opts[] = { __VA_ARGS__ , NULL }; \
\
_test_verify_options (__opts, exp); \
} G_STMT_END
static void
_test_verify_options (const char **options, gboolean expected_result)
{
gs_unref_object NMConnection *con = NULL;
NMSettingBond *s_bond;
GError *error = NULL;
gboolean success;
const char **option;
create_bond_connection (&con, &s_bond);
for (option = options; option[0] && option[1]; option += 2)
g_assert (nm_setting_bond_add_option (s_bond, option[0], option[1]));
if (expected_result) {
nmtst_assert_connection_verifies_and_normalizable (con);
nmtst_connection_normalize (con);
success = nm_setting_verify ((NMSetting *) s_bond, con, &error);
nmtst_assert_success (success, error);
} else {
nmtst_assert_connection_unnormalizable (con,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
}
static void
test_verify (void)
{
test_verify_options (TRUE,
"mode", "3",
"arp_interval", "0");
test_verify_options (FALSE,
/* arp_interval not supported in balance-alb mode */
"mode", "balance-alb",
"arp_interval", "1",
"arp_ip_target", "1.2.3.4");
test_verify_options (FALSE,
/* arp_ip_target requires arp_interval */
"mode", "balance-rr",
"arp_ip_target", "1.2.3.4");
test_verify_options (TRUE,
"mode", "balance-rr",
"arp_interval", "1",
"arp_ip_target", "1.2.3.4");
test_verify_options (FALSE,
/* num_grat_arp, num_unsol_na cannot be different */
"mode", "balance-rr",
"num_grat_arp", "3",
"num_unsol_na", "4");
test_verify_options (TRUE,
"mode", "balance-rr",
"num_grat_arp", "5",
"num_unsol_na", "5");
test_verify_options (TRUE,
"mode", "active-backup",
"primary", "eth0");
test_verify_options (FALSE,
/* primary requires mode=active-backup */
"mode", "802.3ad",
"primary", "eth0");
test_verify_options (TRUE,
"mode", "802.3ad",
"lacp_rate", "fast");
test_verify_options (FALSE,
/* lacp_rate=fast requires mode=802.3ad */
"mode", "balance-rr",
"lacp_rate", "fast");
test_verify_options (TRUE,
"mode", "802.3ad",
"ad_actor_system", "ae:00:11:33:44:55");
}
static void
test_compare_options (gboolean exp_res, const char **opts1, const char **opts2)
{
gs_unref_object NMSettingBond *s_bond1 = NULL, *s_bond2 = NULL;
const char **p;
s_bond1 = (NMSettingBond *) nm_setting_bond_new ();
g_assert (s_bond1);
s_bond2 = (NMSettingBond *) nm_setting_bond_new ();
g_assert (s_bond2);
for (p = opts1; p[0] && p[1]; p += 2)
g_assert (nm_setting_bond_add_option (s_bond1, p[0], p[1]));
for (p = opts2; p[0] && p[1]; p += 2)
g_assert (nm_setting_bond_add_option (s_bond2, p[0], p[1]));
g_assert_cmpint (nm_setting_compare ((NMSetting *) s_bond1,
(NMSetting *) s_bond2,
NM_SETTING_COMPARE_FLAG_EXACT),
==,
exp_res);
}
static void
test_compare (void)
{
test_compare_options (TRUE,
((const char *[]){ "mode", "balance-rr", "miimon", "1", NULL }),
((const char *[]){ "mode", "balance-rr", "miimon", "1", NULL }));
test_compare_options (FALSE,
((const char *[]){ "mode", "balance-rr", "miimon", "1", NULL }),
((const char *[]){ "mode", "balance-rr", "miimon", "2", NULL }));
/* ignore default values */
test_compare_options (TRUE,
((const char *[]){ "miimon", "1", NULL }),
((const char *[]){ "miimon", "1", "updelay", "0", NULL }));
/* special handling of num_grat_arp, num_unsol_na */
test_compare_options (FALSE,
((const char *[]){ "num_grat_arp", "2", NULL }),
((const char *[]){ "num_grat_arp", "1", NULL }));
test_compare_options (TRUE,
((const char *[]){ "num_grat_arp", "3", NULL }),
((const char *[]){ "num_unsol_na", "3", NULL }));
test_compare_options (TRUE,
((const char *[]){ "num_grat_arp", "4", NULL }),
((const char *[]){ "num_unsol_na", "4", "num_grat_arp", "4", NULL }));
}
static void
test_normalize_options (const char **opts1, const char **opts2)
{
gs_unref_object NMConnection *con = NULL;
NMSettingBond *s_bond;
GError *error = NULL;
gboolean success;
const char **p;
int num = 0;
create_bond_connection (&con, &s_bond);
for (p = opts1; p[0] && p[1]; p += 2)
g_assert (nm_setting_bond_add_option (s_bond, p[0], p[1]));
nmtst_assert_connection_verifies_and_normalizable (con);
nmtst_connection_normalize (con);
success = nm_setting_verify ((NMSetting *) s_bond, con, &error);
nmtst_assert_success (success, error);
for (p = opts2; p[0] && p[1]; p += 2) {
g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, p[0]), ==, p[1]);
num++;
}
g_assert_cmpint (num, ==, nm_setting_bond_get_num_options (s_bond));
}
static void
test_normalize (void)
{
test_normalize_options (
((const char *[]){ "mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL }),
((const char *[]){ "mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL }));
test_normalize_options (
((const char *[]){ "mode", "1", "miimon", "1", NULL }),
((const char *[]){ "mode", "active-backup", "miimon", "1", NULL }));
test_normalize_options (
((const char *[]){ "mode", "balance-alb", "tlb_dynamic_lb", "1", NULL }),
((const char *[]){ "mode", "balance-alb", NULL }));
test_normalize_options (
((const char *[]){ "mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL }),
((const char *[]){ "mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL }));
test_normalize_options (
((const char *[]){ "mode", "balance-rr", "ad_actor_sys_prio", "4", "packets_per_slave", "3", NULL }),
((const char *[]){ "mode", "balance-rr", "packets_per_slave", "3", NULL }));
}
#define TPATH "/libnm/settings/bond/"
NMTST_DEFINE ();
int
main (int argc, char **argv)
{
nmtst_init (&argc, &argv, TRUE);
g_test_add_func (TPATH "verify", test_verify);
g_test_add_func (TPATH "compare", test_compare);
g_test_add_func (TPATH "normalize", test_normalize);
return g_test_run ();
}

View file

@ -1,321 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2013 Red Hat, Inc.
*
*/
#include "nm-default.h"
#include <string.h>
#include "nm-utils.h"
#include "nm-setting-dcb.h"
#include "nm-connection.h"
#include "nm-errors.h"
#include "nm-utils/nm-test-utils.h"
#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
NM_SETTING_DCB_FLAG_ADVERTISE | \
NM_SETTING_DCB_FLAG_WILLING)
static void
test_dcb_flags_valid (void)
{
gs_unref_object NMSettingDcb *s_dcb = NULL;
GError *error = NULL;
gboolean success;
guint i;
s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
g_assert (s_dcb);
g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, 0);
g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, 0);
g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, 0);
g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, 0);
g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, 0);
g_object_set (G_OBJECT (s_dcb),
NM_SETTING_DCB_APP_FCOE_FLAGS, DCB_FLAGS_ALL,
NM_SETTING_DCB_APP_ISCSI_FLAGS, DCB_FLAGS_ALL,
NM_SETTING_DCB_APP_FIP_FLAGS, DCB_FLAGS_ALL,
NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, DCB_FLAGS_ALL,
NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, DCB_FLAGS_ALL,
NULL);
/* Priority Group Bandwidth must total 100% */
for (i = 0; i < 7; i++)
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 12);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
g_assert_no_error (error);
g_assert (success);
g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, DCB_FLAGS_ALL);
g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, DCB_FLAGS_ALL);
g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, DCB_FLAGS_ALL);
g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, DCB_FLAGS_ALL);
g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, DCB_FLAGS_ALL);
}
#define TEST_FLAG(p, f, v) \
{ \
/* GObject property min/max should ensure the property does not get set to \
* the invalid value, so we ensure the value we just tried to set is 0 and \
* that verify is successful since the property never got set. \
*/ \
g_object_set (G_OBJECT (s_dcb), p, v, NULL); \
g_assert_cmpint (f (s_dcb), ==, 0); \
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
g_assert_no_error (error); \
g_assert (success); \
}
static void
test_dcb_flags_invalid (void)
{
gs_unref_object NMSettingDcb *s_dcb = NULL;
GError *error = NULL;
gboolean success;
s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
g_assert (s_dcb);
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
TEST_FLAG (NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523);
g_test_assert_expected_messages ();
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
TEST_FLAG (NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF);
g_test_assert_expected_messages ();
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
TEST_FLAG (NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111);
g_test_assert_expected_messages ();
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
TEST_FLAG (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, nm_setting_dcb_get_priority_flow_control_flags, G_MAXUINT32);
g_test_assert_expected_messages ();
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
TEST_FLAG (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, nm_setting_dcb_get_priority_group_flags,
(NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + 1);
g_test_assert_expected_messages ();
}
#define TEST_APP_PRIORITY(lcprop, ucprop, v) \
{ \
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
\
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, v, NULL); \
g_assert_cmpint (nm_setting_dcb_get_app_##lcprop##_priority (s_dcb), ==, v); \
\
/* Assert that the setting is invalid while the app is disabled unless v is default */ \
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
if (v >= 0) { \
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \
g_assert (success == FALSE); \
} else { \
g_assert_no_error (error); \
g_assert (success); \
} \
g_clear_error (&error); \
\
/* Set the enable flag and re-verify, this time it should be valid */ \
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
g_assert_no_error (error); \
g_assert (success); \
\
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, 0, NULL); \
}
static void
test_dcb_app_priorities (void)
{
gs_unref_object NMSettingDcb *s_dcb = NULL;
GError *error = NULL;
gboolean success;
s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
g_assert (s_dcb);
/* Defaults */
g_assert_cmpint (nm_setting_dcb_get_app_fcoe_priority (s_dcb), ==, -1);
g_assert_cmpint (nm_setting_dcb_get_app_iscsi_priority (s_dcb), ==, -1);
g_assert_cmpint (nm_setting_dcb_get_app_fip_priority (s_dcb), ==, -1);
TEST_APP_PRIORITY (fcoe, FCOE, 6);
TEST_APP_PRIORITY (iscsi, ISCSI, 5);
TEST_APP_PRIORITY (fip, FIP, 4);
TEST_APP_PRIORITY (fcoe, FCOE, -1);
TEST_APP_PRIORITY (iscsi, ISCSI, -1);
TEST_APP_PRIORITY (fip, FIP, -1);
}
#define TEST_PRIORITY_VALID(fn, id, val, flagsprop, verify) \
{ \
/* Assert that setting the value gets the same value back out */ \
nm_setting_dcb_set_priority_##fn (s_dcb, id, val); \
g_assert_cmpint (nm_setting_dcb_get_priority_##fn (s_dcb, id), ==, val); \
\
if (verify) { \
if (val != 0) { \
/* Assert that verify fails because the flags do not include 'enabled' \
* and a value has been set. \
*/ \
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \
g_assert (success == FALSE); \
g_clear_error (&error); \
} \
\
/* Assert that adding the 'enabled' flag verifies the setting */ \
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
g_assert_no_error (error); \
g_assert (success); \
} \
\
/* Reset everything */ \
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
nm_setting_dcb_set_priority_##fn (s_dcb, id, 0); \
}
/* If Priority Groups are enabled, PG bandwidth must equal 100% */
#define SET_VALID_PRIORITY_GROUP_BANDWIDTH \
{ \
guint x; \
for (x = 0; x < 7; x++) \
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, x, 12); \
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16); \
}
static void
test_dcb_priorities_valid (void)
{
gs_unref_object NMSettingDcb *s_dcb = NULL;
GError *error = NULL;
gboolean success;
guint i;
s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
g_assert (s_dcb);
for (i = 0; i < 8; i++)
TEST_PRIORITY_VALID (flow_control, i, TRUE, FLOW_CONTROL, TRUE);
SET_VALID_PRIORITY_GROUP_BANDWIDTH
for (i = 0; i < 8; i++) {
TEST_PRIORITY_VALID (group_id, i, i, GROUP, TRUE);
TEST_PRIORITY_VALID (group_id, i, 7 - i, GROUP, TRUE);
}
/* Clear PG bandwidth from earlier tests */
for (i = 0; i < 8; i++)
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 0);
/* Priority Group Bandwidth must add up to 100% if enabled, which requires
* some dancing for verifying individual values here.
*/
for (i = 0; i < 8; i++) {
guint other = 7 - (i % 8);
/* Set another priority group to the remaining bandwidth */
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - i);
TEST_PRIORITY_VALID (group_bandwidth, i, i, GROUP, TRUE);
/* Set another priority group to the remaining bandwidth */
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - (7 - i));
TEST_PRIORITY_VALID (group_bandwidth, i, 7 - i, GROUP, TRUE);
/* Clear remaining bandwidth */
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 0);
}
SET_VALID_PRIORITY_GROUP_BANDWIDTH
for (i = 0; i < 8; i++) {
TEST_PRIORITY_VALID (bandwidth, i, i, GROUP, TRUE);
TEST_PRIORITY_VALID (bandwidth, i, 7 - i, GROUP, TRUE);
}
SET_VALID_PRIORITY_GROUP_BANDWIDTH
for (i = 0; i < 8; i++)
TEST_PRIORITY_VALID (strict_bandwidth, i, TRUE, GROUP, TRUE);
SET_VALID_PRIORITY_GROUP_BANDWIDTH
for (i = 0; i < 8; i++) {
TEST_PRIORITY_VALID (traffic_class, i, i, GROUP, TRUE);
TEST_PRIORITY_VALID (traffic_class, i, 7 - i, GROUP, TRUE);
}
}
static void
test_dcb_bandwidth_sums (void)
{
gs_unref_object NMSettingDcb *s_dcb = NULL;
GError *error = NULL;
gboolean success;
s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
g_assert (s_dcb);
/* Assert that setting the value gets the same value back out */
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 0, 9);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 1, 10);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 2, 11);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 3, 12);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 13);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 5, 14);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 6, 15);
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
/* Assert verify success when sums total 100% */
g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL);
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
g_assert_no_error (error);
g_assert (success);
/* Assert verify fails when sums do not total 100% */
nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 20);
success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
g_assert (success == FALSE);
g_clear_error (&error);
}
#define TPATH "/libnm/settings/dcb/"
NMTST_DEFINE ();
int
main (int argc, char **argv)
{
nmtst_init (&argc, &argv, TRUE);
g_test_add_func (TPATH "flags-valid", test_dcb_flags_valid);
g_test_add_func (TPATH "flags-invalid", test_dcb_flags_invalid);
g_test_add_func (TPATH "app-priorities", test_dcb_app_priorities);
g_test_add_func (TPATH "priorities", test_dcb_priorities_valid);
g_test_add_func (TPATH "bandwidth-sums", test_dcb_bandwidth_sums);
return g_test_run ();
}

File diff suppressed because it is too large Load diff

View file

@ -54,6 +54,7 @@ dbus_type_name_map = {
'ay': 'byte array',
'a{ss}': 'dict of string to string',
'a{sv}': 'vardict',
'aa{sv}': 'array of vardict',
'aau': 'array of array of uint32',
'aay': 'array of byte array',
'a(ayuay)': 'array of legacy IPv6 address struct',

View file

@ -1226,11 +1226,15 @@ libnm_1_10_2 {
global:
nm_remote_connection_update2;
nm_remote_connection_update2_finish;
nm_setting_team_add_link_watcher;
nm_setting_team_add_runner_tx_hash;
nm_setting_team_clear_link_watchers;
nm_setting_team_get_link_watcher;
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_link_watchers;
nm_setting_team_get_num_runner_tx_hash;
nm_setting_team_get_runner;
nm_setting_team_get_runner_hwaddr_policy;
@ -1242,12 +1246,38 @@ global:
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_add_link_watcher;
nm_setting_team_port_clear_link_watchers;
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_port_get_link_watcher;
nm_setting_team_port_get_num_link_watchers;
nm_setting_team_port_remove_link_watcher;
nm_setting_team_port_remove_link_watcher_by_value;
nm_setting_team_remove_link_watcher;
nm_setting_team_remove_link_watcher_by_value;
nm_setting_team_remove_runner_tx_hash;
nm_setting_team_remove_runner_tx_hash_by_value;
nm_settings_update2_flags_get_type;
nm_team_link_watcher_arp_ping_flags_get_type;
nm_team_link_watcher_dup;
nm_team_link_watcher_equal;
nm_team_link_watcher_get_delay_down;
nm_team_link_watcher_get_delay_up;
nm_team_link_watcher_get_flags;
nm_team_link_watcher_get_init_wait;
nm_team_link_watcher_get_interval;
nm_team_link_watcher_get_missed_max;
nm_team_link_watcher_get_name;
nm_team_link_watcher_get_source_host;
nm_team_link_watcher_get_target_host;
nm_team_link_watcher_get_type;
nm_team_link_watcher_new_arp_ping;
nm_team_link_watcher_new_ethtool;
nm_team_link_watcher_new_nsna_ping;
nm_team_link_watcher_ref;
nm_team_link_watcher_unref;
} libnm_1_10_0;

View file

@ -1,6 +1,6 @@
CONNECTED_MODE=no
TYPE=InfiniBand
TEAM_PORT_CONFIG="{ \"inf1\": { \"prio\": -10, \"sticky\": true } }"
TEAM_PORT_CONFIG="{\"inf1\": {\"prio\": -10, \"sticky\": true}}"
NAME="Test Write Team Infiniband Port"
UUID=${UUID}
DEVICE=inf1

View file

@ -1,4 +1,4 @@
TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"
TEAM_PORT_CONFIG="{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"
NAME="Test Write Team Port"
UUID=${UUID}
ONBOOT=yes

View file

@ -2,5 +2,5 @@ DEVICE=team0
ONBOOT=no
DEVICETYPE=Team
BOOTPROTO=dhcp
TEAM_CONFIG="{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"
TEAM_CONFIG="{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"

View file

@ -1,5 +1,5 @@
DEVICE=team0
ONBOOT=no
BOOTPROTO=dhcp
TEAM_CONFIG="{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"
TEAM_CONFIG="{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"

View file

@ -1,5 +1,5 @@
TYPE=Ethernet
TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"
TEAM_PORT_CONFIG="{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"
DEVICE=p4p1
TEAM_MASTER=team0
DEVICETYPE=TeamPort

View file

@ -1,4 +1,4 @@
TYPE=Ethernet
TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"
TEAM_PORT_CONFIG="{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"
DEVICE=p4p1
TEAM_MASTER=team0

View file

@ -8695,7 +8695,7 @@ test_read_team_master (gconstpointer user_data)
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingTeam *s_team;
const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }";
const char *expected_config = "{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}";
connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL);
@ -8748,7 +8748,7 @@ test_write_team_master (void)
NMSettingWired *s_wired;
NMSettingIPConfig *s_ip4;
NMSettingIPConfig *s_ip6;
const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }";
const char *expected_config = "{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}";
shvarFile *f;
connection = nm_simple_connection_new ();
@ -8817,7 +8817,7 @@ test_read_team_port (gconstpointer user_data)
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingTeamPort *s_team_port;
const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }";
const char *expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}";
connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL);
@ -8842,7 +8842,7 @@ test_write_team_port (void)
NMSettingConnection *s_con;
NMSettingTeamPort *s_team_port;
NMSettingWired *s_wired;
const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }";
const char *expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}";
shvarFile *f;
connection = nm_simple_connection_new ();
@ -8897,7 +8897,7 @@ test_write_team_infiniband_port (void)
NMSettingConnection *s_con;
NMSettingTeamPort *s_team_port;
NMSettingInfiniband *s_inf;
const char *expected_config = "{ \"inf1\": { \"prio\": -10, \"sticky\": true } }";
const char *expected_config = "{\"inf1\": {\"prio\": -10, \"sticky\": true}}";
shvarFile *f;
connection = nm_simple_connection_new ();
@ -9258,7 +9258,9 @@ test_svUnescape (void)
V0 ("Bob outside LAN", NULL),
V1 ("x", "x"),
V1 ("'{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }'",
"{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"),
"{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"),
V1 ("'{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}'",
"{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"),
V1 ("x\"\"b", "xb"),
V1 ("x\"c\"b", "xcb"),
V1 ("\"c\"b", "cb"),