mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 06:40:18 +01:00
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:
commit
f092cc0f94
25 changed files with 3691 additions and 1216 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -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
|
||||
|
||||
|
|
|
|||
16
Makefile.am
16
Makefile.am
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
@ -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 ();
|
||||
}
|
||||
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
1311
libnm-core/tests/test-setting.c
Normal file
1311
libnm-core/tests/test-setting.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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\"}}"
|
||||
|
||||
|
|
|
|||
|
|
@ -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\"}}"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue