about summary refs log tree commit diff
path: root/libnm-core/nm-setting-tc-config.c
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2019-05-10 15:07:08 +0200
committerSebastien Bacher <seb128@ubuntu.com>2019-05-22 13:41:30 +0200
commitd57a1dd26f8e9859252b0983c2d2ec3b95eb5714 (patch)
tree46f1146e87af8cc7b58b751f7e575bd0abb2f59d /libnm-core/nm-setting-tc-config.c
parentad9ed8bfb963266b4eea524131845f406cfc55d7 (diff)
parent85563b7fc7ec2cd21e38debb9b28db342e2e8e7c (diff)
Import Debian changes 1.18.0-1ubuntu1
network-manager (1.18.0-1ubuntu1) eoan; urgency=medium

  * Update to 1.18, merge on Debian, new version includes nwe support for
    policy routing rules and for VLAN filtering for Linux bridge.
  * Remaining Ubuntu changes
    - Use systemd-resolved instead of dnsmasq
    - debian/control:
      + Depend on isc-dhcp-client instead of recommends
      + Recommend network-manager-pptp
      + Suggest avahi-autoipd for IPv4LL support
    - debian/rules, debian/network-manager.postinst:
      + Don't restart NetworkManager on upgrade but recommend restarting
        the computer
    - debian/rules, debian/network-manager.postinst:
      + Don't install sysvinit scripts or migrate from sysvinit
    - debian/network-manager.postinst:
      + Don't add the netdev group.
      + drop in an empty override file for NetworkManager to manage all
        devices for upgrade from any version, as long as there is no
        netplan configuration yet.
    - debian/default-wifi-powersave-on.conf, debian/rules:
      + Install a config file to enable WiFi powersave
    - Enable build tests
    - Add autopkgtests
    - debian/source_network-manager.py, debian/network-manager.install,
      debian/network-manager.links: Add apport hook
    - Add network-manager-config-connectivity-ubuntu package
    - NetworkManager.conf: disable MAC randomization feature. There is no
      easy way for desktop users to disable this feature yet. And there are
      reports that it doesn't work well with some systems.
    - Update Vcs links to point to Ubuntu branch
    - Add patches. See patch descriptions for more details:
      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
      + Update-dnsmasq-parameters.patch
      + Disable-general-with-expect.patch
      + libnm-Check-self-still-NMManager-or-not.patch
      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
      + Read-system-connections-from-run.patch
    - debian/tests/urfkill-integration - don't stop/start network manager
    - Revert "Add Conflicts to network-manager-dev against deprecated libraries"
      This reverts commit b4acc5e03e2b821e1cccc69529bb70826c741942.  We're still
      building libnm-glib for now, so these packages have a use in Ubuntu.
  * Removed delta, not needed anymore
    - debian/network-manager.maintscript
      + Remove /etc/dbus-1/system.d/nm-ofono.conf
Diffstat (limited to 'libnm-core/nm-setting-tc-config.c')
-rw-r--r--libnm-core/nm-setting-tc-config.c197
1 files changed, 190 insertions, 7 deletions
diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c
index 7425ae73..dc2f4f64 100644
--- a/libnm-core/nm-setting-tc-config.c
+++ b/libnm-core/nm-setting-tc-config.c
@@ -41,6 +41,7 @@ struct NMTCQdisc {
 	char *kind;
 	guint32 handle;
 	guint32 parent;
+	GHashTable *attributes;
 };
 
 /**
@@ -62,7 +63,15 @@ nm_tc_qdisc_new (const char *kind,
 {
 	NMTCQdisc *qdisc;
 
-	if (!kind || !*kind || strchr (kind, ' ') || strchr (kind, '\t')) {
+	if (!kind || !*kind) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("kind is missing"));
+		return NULL;
+	}
+
+	if (strchr (kind, ' ') || strchr (kind, '\t')) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -122,6 +131,8 @@ nm_tc_qdisc_unref (NMTCQdisc *qdisc)
 	qdisc->refcount--;
 	if (qdisc->refcount == 0) {
 		g_free (qdisc->kind);
+		if (qdisc->attributes)
+			g_hash_table_unref (qdisc->attributes);
 		g_slice_free (NMTCQdisc, qdisc);
 	}
 }
@@ -141,6 +152,11 @@ nm_tc_qdisc_unref (NMTCQdisc *qdisc)
 gboolean
 nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other)
 {
+	GHashTableIter iter;
+	const char *key;
+	GVariant *value, *value2;
+	guint n;
+
 	g_return_val_if_fail (qdisc != NULL, FALSE);
 	g_return_val_if_fail (qdisc->refcount > 0, FALSE);
 
@@ -152,19 +168,53 @@ nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other)
 	    || g_strcmp0 (qdisc->kind, other->kind) != 0)
 		return FALSE;
 
+	n = qdisc->attributes ? g_hash_table_size (qdisc->attributes) : 0;
+	if (n != (other->attributes ? g_hash_table_size (other->attributes) : 0))
+		return FALSE;
+	if (n) {
+		g_hash_table_iter_init (&iter, qdisc->attributes);
+		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
+			value2 = g_hash_table_lookup (other->attributes, key);
+			if (!value2)
+				return FALSE;
+			if (!g_variant_equal (value, value2))
+				return FALSE;
+		}
+	}
+
 	return TRUE;
 }
 
 static guint
 _nm_tc_qdisc_hash (NMTCQdisc *qdisc)
 {
+	gs_free const char **names = NULL;
+	GVariant *variant;
 	NMHashState h;
+	guint length;
+	guint i;
+
+	names = nm_utils_strdict_get_keys (qdisc->attributes, TRUE, &length);
 
 	nm_hash_init (&h, 43869703);
 	nm_hash_update_vals (&h,
 	                     qdisc->handle,
-	                     qdisc->parent);
+	                     qdisc->parent,
+	                     length);
 	nm_hash_update_str0 (&h, qdisc->kind);
+	for (i = 0; i < length; i++) {
+		const GVariantType *vtype;
+
+		variant = g_hash_table_lookup (qdisc->attributes, names[i]);
+
+		vtype = g_variant_get_type (variant);
+
+		nm_hash_update_str (&h, names[i]);
+		nm_hash_update_str (&h, (const char *) vtype);
+		if (g_variant_type_is_basic (vtype))
+			nm_hash_update_val (&h, g_variant_hash (variant));
+	}
+
 	return nm_hash_complete (&h);
 }
 
@@ -189,6 +239,16 @@ nm_tc_qdisc_dup (NMTCQdisc *qdisc)
 	copy = nm_tc_qdisc_new (qdisc->kind, qdisc->parent, NULL);
 	nm_tc_qdisc_set_handle (copy, qdisc->handle);
 
+	if (qdisc->attributes) {
+		GHashTableIter iter;
+		const char *key;
+		GVariant *value;
+
+		g_hash_table_iter_init (&iter, qdisc->attributes);
+		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
+			nm_tc_qdisc_set_attribute (copy, key, value);
+	}
+
 	return copy;
 }
 
@@ -261,6 +321,85 @@ nm_tc_qdisc_get_parent (NMTCQdisc *qdisc)
 	return qdisc->parent;
 }
 
+/**
+ * nm_tc_qdisc_get_attribute_names:
+ * @qdisc: the #NMTCQdisc
+ *
+ * Gets an array of attribute names defined on @qdisc.
+ *
+ * Returns: (transfer container): a %NULL-terminated array of attribute names
+ *   or %NULL if no attributes are set.
+ *
+ * Since: 1.18
+ **/
+const char **
+nm_tc_qdisc_get_attribute_names (NMTCQdisc *qdisc)
+{
+	g_return_val_if_fail (qdisc, NULL);
+
+	return nm_utils_strdict_get_keys (qdisc->attributes, TRUE, NULL);
+}
+
+GHashTable *
+_nm_tc_qdisc_get_attributes (NMTCQdisc *qdisc)
+{
+	nm_assert (qdisc);
+
+	return qdisc->attributes;
+}
+
+/**
+ * nm_tc_qdisc_get_attribute:
+ * @qdisc: the #NMTCQdisc
+ * @name: the name of an qdisc attribute
+ *
+ * Gets the value of the attribute with name @name on @qdisc
+ *
+ * Returns: (transfer none): the value of the attribute with name @name on
+ *   @qdisc, or %NULL if @qdisc has no such attribute.
+ *
+ * Since: 1.18
+ **/
+GVariant *
+nm_tc_qdisc_get_attribute (NMTCQdisc *qdisc, const char *name)
+{
+	g_return_val_if_fail (qdisc != NULL, NULL);
+	g_return_val_if_fail (name != NULL && *name != '\0', NULL);
+
+	if (qdisc->attributes)
+		return g_hash_table_lookup (qdisc->attributes, name);
+	else
+		return NULL;
+}
+
+/**
+ * nm_tc_qdisc_set_attribute:
+ * @qdisc: the #NMTCQdisc
+ * @name: the name of an qdisc attribute
+ * @value: (transfer none) (allow-none): the value
+ *
+ * Sets or clears the named attribute on @qdisc to the given value.
+ *
+ * Since: 1.18
+ **/
+void
+nm_tc_qdisc_set_attribute (NMTCQdisc *qdisc, const char *name, GVariant *value)
+{
+	g_return_if_fail (qdisc != NULL);
+	g_return_if_fail (name != NULL && *name != '\0');
+	g_return_if_fail (strcmp (name, "kind") != 0);
+
+	if (!qdisc->attributes) {
+		qdisc->attributes = g_hash_table_new_full (nm_str_hash, g_str_equal,
+		                                           g_free, (GDestroyNotify) g_variant_unref);
+	}
+
+	if (value)
+		g_hash_table_insert (qdisc->attributes, g_strdup (name), g_variant_ref_sink (value));
+	else
+		g_hash_table_remove (qdisc->attributes, name);
+}
+
 /*****************************************************************************/
 
 G_DEFINE_BOXED_TYPE (NMTCAction, nm_tc_action, nm_tc_action_dup, nm_tc_action_unref)
@@ -290,7 +429,15 @@ nm_tc_action_new (const char *kind,
 {
 	NMTCAction *action;
 
-	if (!kind || !*kind || strchr (kind, ' ') || strchr (kind, '\t')) {
+	if (!kind || !*kind) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("kind is missing"));
+		return NULL;
+	}
+
+	if (strchr (kind, ' ') || strchr (kind, '\t')) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -464,6 +611,14 @@ nm_tc_action_get_attribute_names (NMTCAction *action)
 	return nm_utils_strv_make_deep_copied_nonnull (names);
 }
 
+GHashTable *
+_nm_tc_action_get_attributes (NMTCAction *action)
+{
+	nm_assert (action);
+
+	return action->attributes;
+}
+
 /**
  * nm_tc_action_get_attribute:
  * @action: the #NMTCAction
@@ -544,7 +699,15 @@ nm_tc_tfilter_new (const char *kind,
 {
 	NMTCTfilter *tfilter;
 
-	if (!kind || !*kind || strchr (kind, ' ') || strchr (kind, '\t')) {
+	if (!kind || !*kind) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("kind is missing"));
+		return NULL;
+	}
+
+	if (strchr (kind, ' ') || strchr (kind, '\t')) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -1222,7 +1385,10 @@ _qdiscs_to_variant (GPtrArray *qdiscs)
 	if (qdiscs) {
 		for (i = 0; i < qdiscs->len; i++) {
 			NMTCQdisc *qdisc = qdiscs->pdata[i];
+			guint length;
+			gs_free const char **attrs = nm_utils_strdict_get_keys (qdisc->attributes, TRUE, &length);
 			GVariantBuilder qdisc_builder;
+			guint y;
 
 			g_variant_builder_init (&qdisc_builder, G_VARIANT_TYPE_VARDICT);
 
@@ -1235,6 +1401,11 @@ _qdiscs_to_variant (GPtrArray *qdiscs)
 			g_variant_builder_add (&qdisc_builder, "{sv}", "parent",
 			                       g_variant_new_uint32 (nm_tc_qdisc_get_parent (qdisc)));
 
+			for (y = 0; y < length; y++) {
+				g_variant_builder_add (&qdisc_builder, "{sv}", attrs[y],
+				                       g_hash_table_lookup (qdisc->attributes, attrs[y]));
+			}
+
 			g_variant_builder_add (&builder, "a{sv}", &qdisc_builder);
 		}
 	}
@@ -1267,9 +1438,11 @@ _qdiscs_from_variant (GVariant *value)
 
 	while (g_variant_iter_next (&iter, "@a{sv}", &qdisc_var)) {
 		const char *kind;
-		guint32 handle;
 		guint32 parent;
 		NMTCQdisc *qdisc;
+		GVariantIter qdisc_iter;
+		const char *key;
+		GVariant *attr_value;
 
 		if (   !g_variant_lookup (qdisc_var, "kind", "&s", &kind)
 		    || !g_variant_lookup (qdisc_var, "parent", "u", &parent)) {
@@ -1284,8 +1457,18 @@ _qdiscs_from_variant (GVariant *value)
 			goto next;
 		}
 
-		if (g_variant_lookup (qdisc_var, "handle", "u", &handle))
-			nm_tc_qdisc_set_handle (qdisc, handle);
+		g_variant_iter_init (&qdisc_iter, qdisc_var);
+		while (g_variant_iter_next (&qdisc_iter, "{&sv}", &key, &attr_value)) {
+			if (   strcmp (key, "kind") == 0
+			    || strcmp (key, "parent") == 0) {
+				/* Already processed above */
+			} else if (strcmp (key, "handle") == 0) {
+				nm_tc_qdisc_set_handle (qdisc, g_variant_get_uint32 (attr_value));
+			} else {
+				nm_tc_qdisc_set_attribute (qdisc, key, attr_value);
+			}
+			g_variant_unref (attr_value);
+		}
 
 		g_ptr_array_add (qdiscs, qdisc);
 next: