about summary refs log tree commit diff
path: root/libnm-core/nm-setting-tc-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-setting-tc-config.c')
-rw-r--r--libnm-core/nm-setting-tc-config.c208
1 files changed, 144 insertions, 64 deletions
diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c
index a4960038..f50969fb 100644
--- a/libnm-core/nm-setting-tc-config.c
+++ b/libnm-core/nm-setting-tc-config.c
@@ -52,7 +52,7 @@ struct NMTCQdisc {
  *
  * Returns: (transfer full): the new #NMTCQdisc object, or %NULL on error
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCQdisc *
 nm_tc_qdisc_new (const char *kind,
@@ -92,7 +92,7 @@ nm_tc_qdisc_new (const char *kind,
  *
  * Increases the reference count of the object.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_qdisc_ref (NMTCQdisc *qdisc)
@@ -110,7 +110,7 @@ nm_tc_qdisc_ref (NMTCQdisc *qdisc)
  * Decreases the reference count of the object.  If the reference count
  * reaches zero, the object will be destroyed.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_qdisc_unref (NMTCQdisc *qdisc)
@@ -135,7 +135,7 @@ nm_tc_qdisc_unref (NMTCQdisc *qdisc)
  *
  * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other)
@@ -154,6 +154,19 @@ nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other)
 	return TRUE;
 }
 
+static guint
+_nm_tc_qdisc_hash (NMTCQdisc *qdisc)
+{
+	NMHashState h;
+
+	nm_hash_init (&h, 43869703);
+	nm_hash_update_vals (&h,
+	                     qdisc->handle,
+	                     qdisc->parent);
+	nm_hash_update_str0 (&h, qdisc->kind);
+	return nm_hash_complete (&h);
+}
+
 /**
  * nm_tc_qdisc_dup:
  * @qdisc: the #NMTCQdisc
@@ -162,7 +175,7 @@ nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other)
  *
  * Returns: (transfer full): a copy of @qdisc
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCQdisc *
 nm_tc_qdisc_dup (NMTCQdisc *qdisc)
@@ -184,7 +197,7 @@ nm_tc_qdisc_dup (NMTCQdisc *qdisc)
  *
  * Returns:
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 const char *
 nm_tc_qdisc_get_kind (NMTCQdisc *qdisc)
@@ -201,7 +214,7 @@ nm_tc_qdisc_get_kind (NMTCQdisc *qdisc)
  *
  * Returns: the queueing discipline handle
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 guint32
 nm_tc_qdisc_get_handle (NMTCQdisc *qdisc)
@@ -219,7 +232,7 @@ nm_tc_qdisc_get_handle (NMTCQdisc *qdisc)
  *
  * Sets the queueing discipline handle.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_qdisc_set_handle (NMTCQdisc *qdisc, guint32 handle)
@@ -236,7 +249,7 @@ nm_tc_qdisc_set_handle (NMTCQdisc *qdisc, guint32 handle)
  *
  * Returns: the parent class
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 guint32
 nm_tc_qdisc_get_parent (NMTCQdisc *qdisc)
@@ -268,7 +281,7 @@ struct NMTCAction {
  *
  * Returns: (transfer full): the new #NMTCAction object, or %NULL on error
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCAction *
 nm_tc_action_new (const char *kind,
@@ -298,7 +311,7 @@ nm_tc_action_new (const char *kind,
  *
  * Increases the reference count of the object.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_action_ref (NMTCAction *action)
@@ -316,7 +329,7 @@ nm_tc_action_ref (NMTCAction *action)
  * Decreases the reference count of the object.  If the reference count
  * reaches zero, the object will be destroyed.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_action_unref (NMTCAction *action)
@@ -343,7 +356,7 @@ nm_tc_action_unref (NMTCAction *action)
  *
  * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_tc_action_equal (NMTCAction *action, NMTCAction *other)
@@ -389,7 +402,7 @@ nm_tc_action_equal (NMTCAction *action, NMTCAction *other)
  *
  * Returns: (transfer full): a copy of @action
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCAction *
 nm_tc_action_dup (NMTCAction *action)
@@ -420,7 +433,7 @@ nm_tc_action_dup (NMTCAction *action)
  *
  * Returns:
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 const char *
 nm_tc_action_get_kind (NMTCAction *action)
@@ -442,22 +455,12 @@ nm_tc_action_get_kind (NMTCAction *action)
 char **
 nm_tc_action_get_attribute_names (NMTCAction *action)
 {
-	GHashTableIter iter;
-	const char *key;
-	GPtrArray *names;
+	const char **names;
 
-	g_return_val_if_fail (action != NULL, NULL);
-
-	names = g_ptr_array_new ();
+	g_return_val_if_fail (action, NULL);
 
-	if (action->attributes) {
-		g_hash_table_iter_init (&iter, action->attributes);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
-			g_ptr_array_add (names, g_strdup (key));
-	}
-	g_ptr_array_add (names, NULL);
-
-	return (char **) g_ptr_array_free (names, FALSE);
+	names = nm_utils_strdict_get_keys (action->attributes, TRUE, NULL);
+	return nm_utils_strv_make_deep_copied_nonnull (names);
 }
 
 /**
@@ -498,8 +501,8 @@ nm_tc_action_set_attribute (NMTCAction *action, const char *name, GVariant *valu
 	g_return_if_fail (strcmp (name, "kind") != 0);
 
 	if (!action->attributes) {
-		action->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
-		                                            g_free, (GDestroyNotify) g_variant_unref);
+		action->attributes = g_hash_table_new_full (nm_str_hash, g_str_equal,
+		                                             g_free, (GDestroyNotify) g_variant_unref);
 	}
 
 	if (value)
@@ -531,7 +534,7 @@ struct NMTCTfilter {
  *
  * Returns: (transfer full): the new #NMTCTfilter object, or %NULL on error
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCTfilter *
 nm_tc_tfilter_new (const char *kind,
@@ -571,7 +574,7 @@ nm_tc_tfilter_new (const char *kind,
  *
  * Increases the reference count of the object.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_tfilter_ref (NMTCTfilter *tfilter)
@@ -589,7 +592,7 @@ nm_tc_tfilter_ref (NMTCTfilter *tfilter)
  * Decreases the reference count of the object.  If the reference count
  * reaches zero, the object will be destroyed.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_tfilter_unref (NMTCTfilter *tfilter)
@@ -616,7 +619,7 @@ nm_tc_tfilter_unref (NMTCTfilter *tfilter)
  *
  * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other)
@@ -636,6 +639,38 @@ nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other)
 	return TRUE;
 }
 
+static guint
+_nm_tc_tfilter_hash (NMTCTfilter *tfilter)
+{
+	gs_free const char **names = NULL;
+	guint i, attr_hash;
+	GVariant *variant;
+	NMHashState h;
+	guint length;
+
+	nm_hash_init (&h, 63624437);
+	nm_hash_update_vals (&h,
+	                     tfilter->handle,
+	                     tfilter->parent);
+	nm_hash_update_str0 (&h, tfilter->kind);
+	if (tfilter->action) {
+		nm_hash_update_str0 (&h, tfilter->action->kind);
+		names = nm_utils_strdict_get_keys (tfilter->action->attributes, TRUE, &length);
+		for (i = 0; i < length; i++) {
+			nm_hash_update_str (&h, names[i]);
+			variant = g_hash_table_lookup (tfilter->action->attributes, names[i]);
+			if (g_variant_type_is_basic (g_variant_get_type (variant))) {
+				/* g_variant_hash() works only for basic types, thus
+				 * we ignore any non-basic attribute. Actions differing
+				 * only for non-basic attributes will collide. */
+				attr_hash = g_variant_hash (variant);
+				nm_hash_update_val (&h, attr_hash);
+			}
+		}
+	}
+	return nm_hash_complete (&h);
+}
+
 /**
  * nm_tc_tfilter_dup:
  * @tfilter: the #NMTCTfilter
@@ -644,7 +679,7 @@ nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other)
  *
  * Returns: (transfer full): a copy of @tfilter
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCTfilter *
 nm_tc_tfilter_dup (NMTCTfilter *tfilter)
@@ -667,7 +702,7 @@ nm_tc_tfilter_dup (NMTCTfilter *tfilter)
  *
  * Returns:
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 const char *
 nm_tc_tfilter_get_kind (NMTCTfilter *tfilter)
@@ -684,7 +719,7 @@ nm_tc_tfilter_get_kind (NMTCTfilter *tfilter)
  *
  * Returns: the queueing discipline handle
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 guint32
 nm_tc_tfilter_get_handle (NMTCTfilter *tfilter)
@@ -702,7 +737,7 @@ nm_tc_tfilter_get_handle (NMTCTfilter *tfilter)
  *
  * Sets the queueing discipline handle.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_tfilter_set_handle (NMTCTfilter *tfilter, guint32 handle)
@@ -719,7 +754,7 @@ nm_tc_tfilter_set_handle (NMTCTfilter *tfilter, guint32 handle)
  *
  * Returns: the parent class
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 guint32
 nm_tc_tfilter_get_parent (NMTCTfilter *tfilter)
@@ -736,7 +771,7 @@ nm_tc_tfilter_get_parent (NMTCTfilter *tfilter)
  *
  * Returns: the action associated with a traffic filter.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCAction *
 nm_tc_tfilter_get_action (NMTCTfilter *tfilter)
@@ -757,7 +792,7 @@ nm_tc_tfilter_get_action (NMTCTfilter *tfilter)
  *
  * Sets the action associated with a traffic filter.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_tc_tfilter_set_action (NMTCTfilter *tfilter, NMTCAction *action)
@@ -787,7 +822,7 @@ enum {
  *
  * Linux Traffic Contril Settings.
  *
- * Since: 1.10.2
+ * Since: 1.12
  */
 struct _NMSettingTCConfig {
         NMSetting parent;
@@ -810,7 +845,7 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TC_CONFIG)
  *
  * Returns: (transfer full): the new empty #NMSettingTCConfig object
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMSetting *
 nm_setting_tc_config_new (void)
@@ -824,7 +859,7 @@ nm_setting_tc_config_new (void)
  *
  * Returns: the number of configured queueing disciplines
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 guint
 nm_setting_tc_config_get_num_qdiscs (NMSettingTCConfig *self)
@@ -841,7 +876,7 @@ nm_setting_tc_config_get_num_qdiscs (NMSettingTCConfig *self)
  *
  * Returns: (transfer none): the qdisc at index @idx
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCQdisc *
 nm_setting_tc_config_get_qdisc (NMSettingTCConfig *self, guint idx)
@@ -864,7 +899,7 @@ nm_setting_tc_config_get_qdisc (NMSettingTCConfig *self, guint idx)
  *
  * Returns: %TRUE if the qdisc was added; %FALSE if the qdisc was already known.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_setting_tc_config_add_qdisc (NMSettingTCConfig *self,
@@ -892,7 +927,7 @@ nm_setting_tc_config_add_qdisc (NMSettingTCConfig *self,
  *
  * Removes the qdisc at index @idx.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_setting_tc_config_remove_qdisc (NMSettingTCConfig *self, guint idx)
@@ -914,7 +949,7 @@ nm_setting_tc_config_remove_qdisc (NMSettingTCConfig *self, guint idx)
  *
  * Returns: %TRUE if the qdisc was found and removed; %FALSE if it was not.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_setting_tc_config_remove_qdisc_by_value (NMSettingTCConfig *self,
@@ -941,7 +976,7 @@ nm_setting_tc_config_remove_qdisc_by_value (NMSettingTCConfig *self,
  *
  * Removes all configured queueing disciplines.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *self)
@@ -959,7 +994,7 @@ nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *self)
  *
  * Returns: the number of configured queueing disciplines
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 guint
 nm_setting_tc_config_get_num_tfilters (NMSettingTCConfig *self)
@@ -976,7 +1011,7 @@ nm_setting_tc_config_get_num_tfilters (NMSettingTCConfig *self)
  *
  * Returns: (transfer none): the tfilter at index @idx
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 NMTCTfilter *
 nm_setting_tc_config_get_tfilter (NMSettingTCConfig *self, guint idx)
@@ -999,7 +1034,7 @@ nm_setting_tc_config_get_tfilter (NMSettingTCConfig *self, guint idx)
  *
  * Returns: %TRUE if the tfilter was added; %FALSE if the tfilter was already known.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_setting_tc_config_add_tfilter (NMSettingTCConfig *self,
@@ -1027,7 +1062,7 @@ nm_setting_tc_config_add_tfilter (NMSettingTCConfig *self,
  *
  * Removes the tfilter at index @idx.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_setting_tc_config_remove_tfilter (NMSettingTCConfig *self, guint idx)
@@ -1048,7 +1083,7 @@ nm_setting_tc_config_remove_tfilter (NMSettingTCConfig *self, guint idx)
  *
  * Returns: %TRUE if the tfilter was found and removed; %FALSE if it was not.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 gboolean
 nm_setting_tc_config_remove_tfilter_by_value (NMSettingTCConfig *self,
@@ -1075,7 +1110,7 @@ nm_setting_tc_config_remove_tfilter_by_value (NMSettingTCConfig *self,
  *
  * Removes all configured queueing disciplines.
  *
- * Since: 1.10.2
+ * Since: 1.12
  **/
 void
 nm_setting_tc_config_clear_tfilters (NMSettingTCConfig *self)
@@ -1148,6 +1183,55 @@ finalize (GObject *object)
 }
 
 static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingTCConfig *self = NM_SETTING_TC_CONFIG (setting);
+	guint i;
+
+	if (self->qdiscs->len != 0) {
+		gs_unref_hashtable GHashTable *ht = NULL;
+
+		ht = g_hash_table_new ((GHashFunc) _nm_tc_qdisc_hash,
+		                       (GEqualFunc) nm_tc_qdisc_equal);
+		for (i = 0; i < self->qdiscs->len; i++) {
+			if (!g_hash_table_add (ht, self->qdiscs->pdata[i])) {
+				g_set_error_literal (error,
+				                     NM_CONNECTION_ERROR,
+				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+				                     _("there are duplicate TC qdiscs"));
+				g_prefix_error (error,
+				                "%s.%s: ",
+				                NM_SETTING_TC_CONFIG_SETTING_NAME,
+				                NM_SETTING_TC_CONFIG_QDISCS);
+				return FALSE;
+			}
+		}
+	}
+
+	if (self->tfilters->len != 0) {
+		gs_unref_hashtable GHashTable *ht = NULL;
+
+		ht = g_hash_table_new ((GHashFunc) _nm_tc_tfilter_hash,
+		                       (GEqualFunc) nm_tc_tfilter_equal);
+		for (i = 0; i < self->tfilters->len; i++) {
+			if (!g_hash_table_add (ht, self->tfilters->pdata[i])) {
+				g_set_error_literal (error,
+				                     NM_CONNECTION_ERROR,
+				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+				                     _("there are duplicate TC filters"));
+				g_prefix_error (error,
+				                "%s.%s: ",
+				                NM_SETTING_TC_CONFIG_SETTING_NAME,
+				                NM_SETTING_TC_CONFIG_TFILTERS);
+				return FALSE;
+			}
+		}
+	}
+
+	return TRUE;
+}
+
+static gboolean
 compare_property (NMSetting *setting,
                   NMSetting *other,
                   const GParamSpec *prop_spec,
@@ -1329,7 +1413,7 @@ _action_to_variant (NMTCAction *action)
 
 	for (i = 0; attrs[i]; i++) {
 		g_variant_builder_add (&builder, "{sv}", attrs[i],
-				       nm_tc_action_get_attribute (action, attrs[i]));
+		                       nm_tc_action_get_attribute (action, attrs[i]));
 	}
 
 	return g_variant_builder_end (&builder);
@@ -1433,7 +1517,6 @@ _tfilters_from_variant (GVariant *value)
 
 		action_var = g_variant_lookup_value (tfilter_var, "action", G_VARIANT_TYPE_VARDICT);
 
-
 		if (action_var) {
 			if (!g_variant_lookup (action_var, "kind", "&s", &action_kind)) {
 				//g_warning ("Ignoring tfilter with invalid action");
@@ -1513,15 +1596,14 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class)
 	object_class->get_property     = get_property;
 	object_class->finalize         = finalize;
 	parent_class->compare_property = compare_property;
+	parent_class->verify           = verify;
 
 	/* Properties */
 
 	/**
-	 * NMSettingTCConfig:qdiscs:
+	 * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc))
 	 *
 	 * Array of TC queuening disciplines.
-	 *
-	 * Element-Type: NMTCQdisc
 	 **/
 	/* ---ifcfg-rh---
 	 * property: qdiscs
@@ -1546,11 +1628,9 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class)
 	                                     NULL);
 
 	/**
-	 * NMSettingTCConfig:tfilters:
+	 * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter))
 	 *
 	 * Array of TC traffic filters.
-	 *
-	 * Element-Type: NMTCTfilter
 	 **/
 	/* ---ifcfg-rh---
 	 * property: qdiscs