summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Giudici <fgiudici@redhat.com>2017-11-07 14:38:45 +0100
committerFrancesco Giudici <fgiudici@redhat.com>2017-12-08 00:46:26 +0100
commitba4ce843fa796c3e99777743279187b8c95b4743 (patch)
tree42880b3a342fda02fd0a50f1ab2fa236b32fb674
parent72f6d08714f19598eedd5b9d96f032dce0e80c8b (diff)
downloadNetworkManager-ba4ce843fa796c3e99777743279187b8c95b4743.tar.gz
libnm-core: add backend for GVariant de/serialization of link_watchers.
-rw-r--r--libnm-core/nm-property-compare.c34
-rw-r--r--libnm-core/nm-utils-private.h2
-rw-r--r--libnm-core/nm-utils.c196
-rwxr-xr-xlibnm/generate-setting-docs.py1
4 files changed, 233 insertions, 0 deletions
diff --git a/libnm-core/nm-property-compare.c b/libnm-core/nm-property-compare.c
index d13d019f0a..64ed663c22 100644
--- a/libnm-core/nm-property-compare.c
+++ b/libnm-core/nm-property-compare.c
@@ -56,6 +56,38 @@ _nm_property_compare_collection (GVariant *value1, GVariant *value2)
}
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)
{
GVariantIter iter;
@@ -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))
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
index 6b8d58726a..31196694ca 100644
--- a/libnm-core/nm-utils-private.h
+++ b/libnm-core/nm-utils-private.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 */
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index cac5c5e9b4..7d3ad4e380 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -4783,6 +4783,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)
{
diff --git a/libnm/generate-setting-docs.py b/libnm/generate-setting-docs.py
index aa0c96ebb2..50ae9d4682 100755
--- a/libnm/generate-setting-docs.py
+++ b/libnm/generate-setting-docs.py
@@ -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',