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.c1885
1 files changed, 0 insertions, 1885 deletions
diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c
deleted file mode 100644
index 31e829c1..00000000
--- a/libnm-core/nm-setting-tc-config.c
+++ /dev/null
@@ -1,1885 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#include "libnm-core/nm-default-libnm-core.h"
-
-#include "nm-setting-tc-config.h"
-
-#include <linux/pkt_sched.h>
-
-#include "nm-setting-private.h"
-
-/**
- * SECTION:nm-setting-tc-config
- * @short_description: Describes connection properties for the Linux Traffic Control
- * @include: nm-setting-tc-config.h
- **/
-
-/*****************************************************************************/
-
-G_DEFINE_BOXED_TYPE(NMTCQdisc, nm_tc_qdisc, nm_tc_qdisc_dup, nm_tc_qdisc_unref)
-
-struct NMTCQdisc {
-    guint refcount;
-
-    char *      kind;
-    guint32     handle;
-    guint32     parent;
-    GHashTable *attributes;
-};
-
-/**
- * nm_tc_qdisc_new:
- * @kind: name of the queueing discipline
- * @parent: the parent queueing discipline
- * @error: location to store error, or %NULL
- *
- * Creates a new #NMTCQdisc object.
- *
- * Returns: (transfer full): the new #NMTCQdisc object, or %NULL on error
- *
- * Since: 1.12
- **/
-NMTCQdisc *
-nm_tc_qdisc_new(const char *kind, guint32 parent, GError **error)
-{
-    NMTCQdisc *qdisc;
-
-    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,
-                    _("'%s' is not a valid kind"),
-                    kind);
-        return NULL;
-    }
-
-    if (!parent) {
-        g_set_error_literal(error,
-                            NM_CONNECTION_ERROR,
-                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
-                            _("parent handle missing"));
-        return NULL;
-    }
-
-    qdisc           = g_slice_new0(NMTCQdisc);
-    qdisc->refcount = 1;
-
-    qdisc->kind   = g_strdup(kind);
-    qdisc->parent = parent;
-
-    return qdisc;
-}
-
-/**
- * nm_tc_qdisc_ref:
- * @qdisc: the #NMTCQdisc
- *
- * Increases the reference count of the object.
- *
- * Since: 1.12
- **/
-void
-nm_tc_qdisc_ref(NMTCQdisc *qdisc)
-{
-    g_return_if_fail(qdisc != NULL);
-    g_return_if_fail(qdisc->refcount > 0);
-
-    qdisc->refcount++;
-}
-
-/**
- * nm_tc_qdisc_unref:
- * @qdisc: the #NMTCQdisc
- *
- * Decreases the reference count of the object.  If the reference count
- * reaches zero, the object will be destroyed.
- *
- * Since: 1.12
- **/
-void
-nm_tc_qdisc_unref(NMTCQdisc *qdisc)
-{
-    g_return_if_fail(qdisc != NULL);
-    g_return_if_fail(qdisc->refcount > 0);
-
-    qdisc->refcount--;
-    if (qdisc->refcount == 0) {
-        g_free(qdisc->kind);
-        if (qdisc->attributes)
-            g_hash_table_unref(qdisc->attributes);
-        g_slice_free(NMTCQdisc, qdisc);
-    }
-}
-
-/**
- * nm_tc_qdisc_equal:
- * @qdisc: the #NMTCQdisc
- * @other: the #NMTCQdisc to compare @qdisc to.
- *
- * Determines if two #NMTCQdisc objects contain the same kind, * handle
- * and parent.
- *
- * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
- *
- * Since: 1.12
- **/
-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);
-
-    g_return_val_if_fail(other != NULL, FALSE);
-    g_return_val_if_fail(other->refcount > 0, FALSE);
-
-    if (qdisc->handle != other->handle || qdisc->parent != other->parent
-        || 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)
-{
-    NMUtilsNamedValue attrs_static[30];
-    gs_free NMUtilsNamedValue *attrs_free = NULL;
-    const NMUtilsNamedValue *  attrs;
-    NMHashState                h;
-    guint                      length;
-    guint                      i;
-
-    attrs =
-        nm_utils_named_values_from_strdict(qdisc->attributes, &length, attrs_static, &attrs_free);
-
-    nm_hash_init(&h, 43869703);
-    nm_hash_update_vals(&h, qdisc->handle, qdisc->parent, length);
-    nm_hash_update_str0(&h, qdisc->kind);
-    for (i = 0; i < length; i++) {
-        const char *        key     = attrs[i].name;
-        GVariant *          variant = attrs[i].value_ptr;
-        const GVariantType *vtype;
-
-        vtype = g_variant_get_type(variant);
-
-        nm_hash_update_str(&h, key);
-        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);
-}
-
-/**
- * nm_tc_qdisc_dup:
- * @qdisc: the #NMTCQdisc
- *
- * Creates a copy of @qdisc
- *
- * Returns: (transfer full): a copy of @qdisc
- *
- * Since: 1.12
- **/
-NMTCQdisc *
-nm_tc_qdisc_dup(NMTCQdisc *qdisc)
-{
-    NMTCQdisc *copy;
-
-    g_return_val_if_fail(qdisc != NULL, NULL);
-    g_return_val_if_fail(qdisc->refcount > 0, NULL);
-
-    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;
-}
-
-/**
- * nm_tc_qdisc_get_kind:
- * @qdisc: the #NMTCQdisc
- *
- * Returns:
- *
- * Since: 1.12
- **/
-const char *
-nm_tc_qdisc_get_kind(NMTCQdisc *qdisc)
-{
-    g_return_val_if_fail(qdisc != NULL, NULL);
-    g_return_val_if_fail(qdisc->refcount > 0, NULL);
-
-    return qdisc->kind;
-}
-
-/**
- * nm_tc_qdisc_get_handle:
- * @qdisc: the #NMTCQdisc
- *
- * Returns: the queueing discipline handle
- *
- * Since: 1.12
- **/
-guint32
-nm_tc_qdisc_get_handle(NMTCQdisc *qdisc)
-{
-    g_return_val_if_fail(qdisc != NULL, TC_H_UNSPEC);
-    g_return_val_if_fail(qdisc->refcount > 0, TC_H_UNSPEC);
-
-    return qdisc->handle;
-}
-
-/**
- * nm_tc_qdisc_set_handle:
- * @qdisc: the #NMTCQdisc
- * @handle: the queueing discipline handle
- *
- * Sets the queueing discipline handle.
- *
- * Since: 1.12
- **/
-void
-nm_tc_qdisc_set_handle(NMTCQdisc *qdisc, guint32 handle)
-{
-    g_return_if_fail(qdisc != NULL);
-    g_return_if_fail(qdisc->refcount > 0);
-
-    qdisc->handle = handle;
-}
-
-/**
- * nm_tc_qdisc_get_parent:
- * @qdisc: the #NMTCQdisc
- *
- * Returns: the parent class
- *
- * Since: 1.12
- **/
-guint32
-nm_tc_qdisc_get_parent(NMTCQdisc *qdisc)
-{
-    g_return_val_if_fail(qdisc != NULL, TC_H_UNSPEC);
-    g_return_val_if_fail(qdisc->refcount > 0, TC_H_UNSPEC);
-
-    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)
-
-struct NMTCAction {
-    guint refcount;
-
-    char *kind;
-
-    GHashTable *attributes;
-};
-
-/**
- * nm_tc_action_new:
- * @kind: name of the queueing discipline
- * @error: location to store error, or %NULL
- *
- * Creates a new #NMTCAction object.
- *
- * Returns: (transfer full): the new #NMTCAction object, or %NULL on error
- *
- * Since: 1.12
- **/
-NMTCAction *
-nm_tc_action_new(const char *kind, GError **error)
-{
-    NMTCAction *action;
-
-    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,
-                    _("'%s' is not a valid kind"),
-                    kind);
-        return NULL;
-    }
-
-    action           = g_slice_new0(NMTCAction);
-    action->refcount = 1;
-
-    action->kind = g_strdup(kind);
-
-    return action;
-}
-
-/**
- * nm_tc_action_ref:
- * @action: the #NMTCAction
- *
- * Increases the reference count of the object.
- *
- * Since: 1.12
- **/
-void
-nm_tc_action_ref(NMTCAction *action)
-{
-    g_return_if_fail(action != NULL);
-    g_return_if_fail(action->refcount > 0);
-
-    action->refcount++;
-}
-
-/**
- * nm_tc_action_unref:
- * @action: the #NMTCAction
- *
- * Decreases the reference count of the object.  If the reference count
- * reaches zero, the object will be destroyed.
- *
- * Since: 1.12
- **/
-void
-nm_tc_action_unref(NMTCAction *action)
-{
-    g_return_if_fail(action != NULL);
-    g_return_if_fail(action->refcount > 0);
-
-    action->refcount--;
-    if (action->refcount == 0) {
-        g_free(action->kind);
-        if (action->attributes)
-            g_hash_table_unref(action->attributes);
-        g_slice_free(NMTCAction, action);
-    }
-}
-
-/**
- * nm_tc_action_equal:
- * @action: the #NMTCAction
- * @other: the #NMTCAction to compare @action to.
- *
- * Determines if two #NMTCAction objects contain the same kind, family,
- * handle, parent and info.
- *
- * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
- *
- * Since: 1.12
- **/
-gboolean
-nm_tc_action_equal(NMTCAction *action, NMTCAction *other)
-{
-    GHashTableIter iter;
-    const char *   key;
-    GVariant *     value, *value2;
-    guint          n;
-
-    g_return_val_if_fail(!action || action->refcount > 0, FALSE);
-    g_return_val_if_fail(!other || other->refcount > 0, FALSE);
-
-    if (action == other)
-        return TRUE;
-    if (!action || !other)
-        return FALSE;
-
-    if (g_strcmp0(action->kind, other->kind) != 0)
-        return FALSE;
-
-    n = action->attributes ? g_hash_table_size(action->attributes) : 0;
-    if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0))
-        return FALSE;
-    if (n) {
-        g_hash_table_iter_init(&iter, action->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;
-}
-
-/**
- * nm_tc_action_dup:
- * @action: the #NMTCAction
- *
- * Creates a copy of @action
- *
- * Returns: (transfer full): a copy of @action
- *
- * Since: 1.12
- **/
-NMTCAction *
-nm_tc_action_dup(NMTCAction *action)
-{
-    NMTCAction *copy;
-
-    g_return_val_if_fail(action != NULL, NULL);
-    g_return_val_if_fail(action->refcount > 0, NULL);
-
-    copy = nm_tc_action_new(action->kind, NULL);
-
-    if (action->attributes) {
-        GHashTableIter iter;
-        const char *   key;
-        GVariant *     value;
-
-        g_hash_table_iter_init(&iter, action->attributes);
-        while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value))
-            nm_tc_action_set_attribute(copy, key, value);
-    }
-
-    return copy;
-}
-
-/**
- * nm_tc_action_get_kind:
- * @action: the #NMTCAction
- *
- * Returns:
- *
- * Since: 1.12
- **/
-const char *
-nm_tc_action_get_kind(NMTCAction *action)
-{
-    g_return_val_if_fail(action != NULL, NULL);
-    g_return_val_if_fail(action->refcount > 0, NULL);
-
-    return action->kind;
-}
-
-/**
- * nm_tc_action_get_attribute_names:
- * @action: the #NMTCAction
- *
- * Gets an array of attribute names defined on @action.
- *
- * Returns: (transfer full): a %NULL-terminated array of attribute names,
- *
- * Since: 1.12
- **/
-char **
-nm_tc_action_get_attribute_names(NMTCAction *action)
-{
-    const char **names;
-
-    g_return_val_if_fail(action, NULL);
-
-    names = nm_utils_strdict_get_keys(action->attributes, TRUE, NULL);
-    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
- * @name: the name of an action attribute
- *
- * Gets the value of the attribute with name @name on @action
- *
- * Returns: (transfer none): the value of the attribute with name @name on
- *   @action, or %NULL if @action has no such attribute.
- *
- * Since: 1.12
- **/
-GVariant *
-nm_tc_action_get_attribute(NMTCAction *action, const char *name)
-{
-    g_return_val_if_fail(action != NULL, NULL);
-    g_return_val_if_fail(name != NULL && *name != '\0', NULL);
-
-    if (action->attributes)
-        return g_hash_table_lookup(action->attributes, name);
-    else
-        return NULL;
-}
-
-/**
- * nm_tc_action_set_attribute:
- * @action: the #NMTCAction
- * @name: the name of an action attribute
- * @value: (transfer none) (allow-none): the value
- *
- * Sets or clears the named attribute on @action to the given value.
- *
- * Since: 1.12
- **/
-void
-nm_tc_action_set_attribute(NMTCAction *action, const char *name, GVariant *value)
-{
-    g_return_if_fail(action != NULL);
-    g_return_if_fail(name != NULL && *name != '\0');
-    g_return_if_fail(strcmp(name, "kind") != 0);
-
-    if (!action->attributes) {
-        action->attributes = g_hash_table_new_full(nm_str_hash,
-                                                   g_str_equal,
-                                                   g_free,
-                                                   (GDestroyNotify) g_variant_unref);
-    }
-
-    if (value)
-        g_hash_table_insert(action->attributes, g_strdup(name), g_variant_ref_sink(value));
-    else
-        g_hash_table_remove(action->attributes, name);
-}
-
-/*****************************************************************************/
-
-G_DEFINE_BOXED_TYPE(NMTCTfilter, nm_tc_tfilter, nm_tc_tfilter_dup, nm_tc_tfilter_unref)
-
-struct NMTCTfilter {
-    guint refcount;
-
-    char *      kind;
-    guint32     handle;
-    guint32     parent;
-    NMTCAction *action;
-};
-
-/**
- * nm_tc_tfilter_new:
- * @kind: name of the queueing discipline
- * @parent: the parent queueing discipline
- * @error: location to store error, or %NULL
- *
- * Creates a new #NMTCTfilter object.
- *
- * Returns: (transfer full): the new #NMTCTfilter object, or %NULL on error
- *
- * Since: 1.12
- **/
-NMTCTfilter *
-nm_tc_tfilter_new(const char *kind, guint32 parent, GError **error)
-{
-    NMTCTfilter *tfilter;
-
-    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,
-                    _("'%s' is not a valid kind"),
-                    kind);
-        return NULL;
-    }
-
-    if (!parent) {
-        g_set_error_literal(error,
-                            NM_CONNECTION_ERROR,
-                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
-                            _("parent handle missing"));
-        return NULL;
-    }
-
-    tfilter           = g_slice_new0(NMTCTfilter);
-    tfilter->refcount = 1;
-
-    tfilter->kind   = g_strdup(kind);
-    tfilter->parent = parent;
-
-    return tfilter;
-}
-
-/**
- * nm_tc_tfilter_ref:
- * @tfilter: the #NMTCTfilter
- *
- * Increases the reference count of the object.
- *
- * Since: 1.12
- **/
-void
-nm_tc_tfilter_ref(NMTCTfilter *tfilter)
-{
-    g_return_if_fail(tfilter != NULL);
-    g_return_if_fail(tfilter->refcount > 0);
-
-    tfilter->refcount++;
-}
-
-/**
- * nm_tc_tfilter_unref:
- * @tfilter: the #NMTCTfilter
- *
- * Decreases the reference count of the object.  If the reference count
- * reaches zero, the object will be destroyed.
- *
- * Since: 1.12
- **/
-void
-nm_tc_tfilter_unref(NMTCTfilter *tfilter)
-{
-    g_return_if_fail(tfilter != NULL);
-    g_return_if_fail(tfilter->refcount > 0);
-
-    tfilter->refcount--;
-    if (tfilter->refcount == 0) {
-        g_free(tfilter->kind);
-        if (tfilter->action)
-            nm_tc_action_unref(tfilter->action);
-        g_slice_free(NMTCTfilter, tfilter);
-    }
-}
-
-/**
- * nm_tc_tfilter_equal:
- * @tfilter: the #NMTCTfilter
- * @other: the #NMTCTfilter to compare @tfilter to.
- *
- * Determines if two #NMTCTfilter objects contain the same kind, family,
- * handle, parent and info.
- *
- * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
- *
- * Since: 1.12
- **/
-gboolean
-nm_tc_tfilter_equal(NMTCTfilter *tfilter, NMTCTfilter *other)
-{
-    g_return_val_if_fail(tfilter != NULL, FALSE);
-    g_return_val_if_fail(tfilter->refcount > 0, FALSE);
-
-    g_return_val_if_fail(other != NULL, FALSE);
-    g_return_val_if_fail(other->refcount > 0, FALSE);
-
-    if (tfilter->handle != other->handle || tfilter->parent != other->parent
-        || g_strcmp0(tfilter->kind, other->kind) != 0
-        || !nm_tc_action_equal(tfilter->action, other->action))
-        return FALSE;
-
-    return TRUE;
-}
-
-static guint
-_nm_tc_tfilter_hash(NMTCTfilter *tfilter)
-{
-    NMHashState h;
-
-    nm_hash_init(&h, 63624437);
-    nm_hash_update_vals(&h, tfilter->handle, tfilter->parent);
-    nm_hash_update_str0(&h, tfilter->kind);
-
-    if (tfilter->action) {
-        gs_free NMUtilsNamedValue *attrs_free = NULL;
-        NMUtilsNamedValue          attrs_static[30];
-        const NMUtilsNamedValue *  attrs;
-        guint                      length;
-        guint                      i;
-
-        nm_hash_update_str0(&h, tfilter->action->kind);
-
-        attrs = nm_utils_named_values_from_strdict(tfilter->action->attributes,
-                                                   &length,
-                                                   attrs_static,
-                                                   &attrs_free);
-        for (i = 0; i < length; i++) {
-            GVariant *variant = attrs[i].value_ptr;
-
-            nm_hash_update_str(&h, attrs[i].name);
-            if (g_variant_type_is_basic(g_variant_get_type(variant))) {
-                guint attr_hash;
-
-                /* 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
- *
- * Creates a copy of @tfilter
- *
- * Returns: (transfer full): a copy of @tfilter
- *
- * Since: 1.12
- **/
-NMTCTfilter *
-nm_tc_tfilter_dup(NMTCTfilter *tfilter)
-{
-    NMTCTfilter *copy;
-
-    g_return_val_if_fail(tfilter != NULL, NULL);
-    g_return_val_if_fail(tfilter->refcount > 0, NULL);
-
-    copy = nm_tc_tfilter_new(tfilter->kind, tfilter->parent, NULL);
-    nm_tc_tfilter_set_handle(copy, tfilter->handle);
-    nm_tc_tfilter_set_action(copy, tfilter->action);
-
-    return copy;
-}
-
-/**
- * nm_tc_tfilter_get_kind:
- * @tfilter: the #NMTCTfilter
- *
- * Returns:
- *
- * Since: 1.12
- **/
-const char *
-nm_tc_tfilter_get_kind(NMTCTfilter *tfilter)
-{
-    g_return_val_if_fail(tfilter != NULL, NULL);
-    g_return_val_if_fail(tfilter->refcount > 0, NULL);
-
-    return tfilter->kind;
-}
-
-/**
- * nm_tc_tfilter_get_handle:
- * @tfilter: the #NMTCTfilter
- *
- * Returns: the queueing discipline handle
- *
- * Since: 1.12
- **/
-guint32
-nm_tc_tfilter_get_handle(NMTCTfilter *tfilter)
-{
-    g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC);
-    g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC);
-
-    return tfilter->handle;
-}
-
-/**
- * nm_tc_tfilter_set_handle:
- * @tfilter: the #NMTCTfilter
- * @handle: the queueing discipline handle
- *
- * Sets the queueing discipline handle.
- *
- * Since: 1.12
- **/
-void
-nm_tc_tfilter_set_handle(NMTCTfilter *tfilter, guint32 handle)
-{
-    g_return_if_fail(tfilter != NULL);
-    g_return_if_fail(tfilter->refcount > 0);
-
-    tfilter->handle = handle;
-}
-
-/**
- * nm_tc_tfilter_get_parent:
- * @tfilter: the #NMTCTfilter
- *
- * Returns: the parent class
- *
- * Since: 1.12
- **/
-guint32
-nm_tc_tfilter_get_parent(NMTCTfilter *tfilter)
-{
-    g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC);
-    g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC);
-
-    return tfilter->parent;
-}
-
-/**
- * nm_tc_tfilter_get_action:
- * @tfilter: the #NMTCTfilter
- *
- * Returns: the action associated with a traffic filter.
- *
- * Since: 1.12
- **/
-NMTCAction *
-nm_tc_tfilter_get_action(NMTCTfilter *tfilter)
-{
-    g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC);
-    g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC);
-
-    if (tfilter->action == NULL)
-        return NULL;
-
-    return tfilter->action;
-}
-
-/**
- * nm_tc_tfilter_set_action:
- * @tfilter: the #NMTCTfilter
- * @action: the action object
- *
- * Sets the action associated with a traffic filter.
- *
- * Since: 1.12
- **/
-void
-nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action)
-{
-    g_return_if_fail(tfilter != NULL);
-    g_return_if_fail(tfilter->refcount > 0);
-
-    if (action)
-        nm_tc_action_ref(action);
-    if (tfilter->action)
-        nm_tc_action_unref(tfilter->action);
-    tfilter->action = action;
-}
-
-/*****************************************************************************/
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMSettingTCConfig, PROP_QDISCS, PROP_TFILTERS, );
-
-/**
- * NMSettingTCConfig:
- *
- * Linux Traffic Control Settings
- *
- * Since: 1.12
- */
-struct _NMSettingTCConfig {
-    NMSetting  parent;
-    GPtrArray *qdiscs;
-    GPtrArray *tfilters;
-};
-
-struct _NMSettingTCConfigClass {
-    NMSettingClass parent;
-};
-
-G_DEFINE_TYPE(NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING)
-
-/*****************************************************************************/
-
-/**
- * nm_setting_tc_config_get_num_qdiscs:
- * @setting: the #NMSettingTCConfig
- *
- * Returns: the number of configured queueing disciplines
- *
- * Since: 1.12
- **/
-guint
-nm_setting_tc_config_get_num_qdiscs(NMSettingTCConfig *self)
-{
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), 0);
-
-    return self->qdiscs->len;
-}
-
-/**
- * nm_setting_tc_config_get_qdisc:
- * @setting: the #NMSettingTCConfig
- * @idx: index number of the qdisc to return
- *
- * Returns: (transfer none): the qdisc at index @idx
- *
- * Since: 1.12
- **/
-NMTCQdisc *
-nm_setting_tc_config_get_qdisc(NMSettingTCConfig *self, guint idx)
-{
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), NULL);
-    g_return_val_if_fail(idx < self->qdiscs->len, NULL);
-
-    return self->qdiscs->pdata[idx];
-}
-
-/**
- * nm_setting_tc_config_add_qdisc:
- * @setting: the #NMSettingTCConfig
- * @qdisc: the qdisc to add
- *
- * Appends a new qdisc and associated information to the setting.  The
- * given qdisc is duplicated internally and is not changed by this function.
- * If an identical qdisc (considering attributes as well) already exists, the
- * qdisc is not added and the function returns %FALSE.
- *
- * Returns: %TRUE if the qdisc was added; %FALSE if the qdisc was already known.
- *
- * Since: 1.12
- **/
-gboolean
-nm_setting_tc_config_add_qdisc(NMSettingTCConfig *self, NMTCQdisc *qdisc)
-{
-    guint i;
-
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE);
-    g_return_val_if_fail(qdisc != NULL, FALSE);
-
-    for (i = 0; i < self->qdiscs->len; i++) {
-        if (nm_tc_qdisc_equal(self->qdiscs->pdata[i], qdisc))
-            return FALSE;
-    }
-
-    g_ptr_array_add(self->qdiscs, nm_tc_qdisc_dup(qdisc));
-    _notify(self, PROP_QDISCS);
-    return TRUE;
-}
-
-/**
- * nm_setting_tc_config_remove_qdisc:
- * @setting: the #NMSettingTCConfig
- * @idx: index number of the qdisc
- *
- * Removes the qdisc at index @idx.
- *
- * Since: 1.12
- **/
-void
-nm_setting_tc_config_remove_qdisc(NMSettingTCConfig *self, guint idx)
-{
-    g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self));
-
-    g_return_if_fail(idx < self->qdiscs->len);
-
-    g_ptr_array_remove_index(self->qdiscs, idx);
-    _notify(self, PROP_QDISCS);
-}
-
-/**
- * nm_setting_tc_config_remove_qdisc_by_value:
- * @setting: the #NMSettingTCConfig
- * @qdisc: the qdisc to remove
- *
- * Removes the first matching qdisc that matches @qdisc.
- *
- * Returns: %TRUE if the qdisc was found and removed; %FALSE if it was not.
- *
- * Since: 1.12
- **/
-gboolean
-nm_setting_tc_config_remove_qdisc_by_value(NMSettingTCConfig *self, NMTCQdisc *qdisc)
-{
-    guint i;
-
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE);
-    g_return_val_if_fail(qdisc != NULL, FALSE);
-
-    for (i = 0; i < self->qdiscs->len; i++) {
-        if (nm_tc_qdisc_equal(self->qdiscs->pdata[i], qdisc)) {
-            g_ptr_array_remove_index(self->qdiscs, i);
-            _notify(self, PROP_QDISCS);
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-/**
- * nm_setting_tc_config_clear_qdiscs:
- * @setting: the #NMSettingTCConfig
- *
- * Removes all configured queueing disciplines.
- *
- * Since: 1.12
- **/
-void
-nm_setting_tc_config_clear_qdiscs(NMSettingTCConfig *self)
-{
-    g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self));
-
-    if (self->qdiscs->len != 0) {
-        g_ptr_array_set_size(self->qdiscs, 0);
-        _notify(self, PROP_QDISCS);
-    }
-}
-
-/*****************************************************************************/
-/**
- * nm_setting_tc_config_get_num_tfilters:
- * @setting: the #NMSettingTCConfig
- *
- * Returns: the number of configured queueing disciplines
- *
- * Since: 1.12
- **/
-guint
-nm_setting_tc_config_get_num_tfilters(NMSettingTCConfig *self)
-{
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), 0);
-
-    return self->tfilters->len;
-}
-
-/**
- * nm_setting_tc_config_get_tfilter:
- * @setting: the #NMSettingTCConfig
- * @idx: index number of the tfilter to return
- *
- * Returns: (transfer none): the tfilter at index @idx
- *
- * Since: 1.12
- **/
-NMTCTfilter *
-nm_setting_tc_config_get_tfilter(NMSettingTCConfig *self, guint idx)
-{
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), NULL);
-    g_return_val_if_fail(idx < self->tfilters->len, NULL);
-
-    return self->tfilters->pdata[idx];
-}
-
-/**
- * nm_setting_tc_config_add_tfilter:
- * @setting: the #NMSettingTCConfig
- * @tfilter: the tfilter to add
- *
- * Appends a new tfilter and associated information to the setting.  The
- * given tfilter is duplicated internally and is not changed by this function.
- * If an identical tfilter (considering attributes as well) already exists, the
- * tfilter is not added and the function returns %FALSE.
- *
- * Returns: %TRUE if the tfilter was added; %FALSE if the tfilter was already known.
- *
- * Since: 1.12
- **/
-gboolean
-nm_setting_tc_config_add_tfilter(NMSettingTCConfig *self, NMTCTfilter *tfilter)
-{
-    guint i;
-
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE);
-    g_return_val_if_fail(tfilter != NULL, FALSE);
-
-    for (i = 0; i < self->tfilters->len; i++) {
-        if (nm_tc_tfilter_equal(self->tfilters->pdata[i], tfilter))
-            return FALSE;
-    }
-
-    g_ptr_array_add(self->tfilters, nm_tc_tfilter_dup(tfilter));
-    _notify(self, PROP_TFILTERS);
-    return TRUE;
-}
-
-/**
- * nm_setting_tc_config_remove_tfilter:
- * @setting: the #NMSettingTCConfig
- * @idx: index number of the tfilter
- *
- * Removes the tfilter at index @idx.
- *
- * Since: 1.12
- **/
-void
-nm_setting_tc_config_remove_tfilter(NMSettingTCConfig *self, guint idx)
-{
-    g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self));
-    g_return_if_fail(idx < self->tfilters->len);
-
-    g_ptr_array_remove_index(self->tfilters, idx);
-    _notify(self, PROP_TFILTERS);
-}
-
-/**
- * nm_setting_tc_config_remove_tfilter_by_value:
- * @setting: the #NMSettingTCConfig
- * @tfilter: the tfilter to remove
- *
- * Removes the first matching tfilter that matches @tfilter.
- *
- * Returns: %TRUE if the tfilter was found and removed; %FALSE if it was not.
- *
- * Since: 1.12
- **/
-gboolean
-nm_setting_tc_config_remove_tfilter_by_value(NMSettingTCConfig *self, NMTCTfilter *tfilter)
-{
-    guint i;
-
-    g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE);
-    g_return_val_if_fail(tfilter != NULL, FALSE);
-
-    for (i = 0; i < self->tfilters->len; i++) {
-        if (nm_tc_tfilter_equal(self->tfilters->pdata[i], tfilter)) {
-            g_ptr_array_remove_index(self->tfilters, i);
-            _notify(self, PROP_TFILTERS);
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-/**
- * nm_setting_tc_config_clear_tfilters:
- * @setting: the #NMSettingTCConfig
- *
- * Removes all configured queueing disciplines.
- *
- * Since: 1.12
- **/
-void
-nm_setting_tc_config_clear_tfilters(NMSettingTCConfig *self)
-{
-    g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self));
-
-    if (self->tfilters->len != 0) {
-        g_ptr_array_set_size(self->tfilters, 0);
-        _notify(self, PROP_TFILTERS);
-    }
-}
-
-/*****************************************************************************/
-
-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 NMTernary
-compare_property(const NMSettInfoSetting *sett_info,
-                 guint                    property_idx,
-                 NMConnection *           con_a,
-                 NMSetting *              set_a,
-                 NMConnection *           con_b,
-                 NMSetting *              set_b,
-                 NMSettingCompareFlags    flags)
-{
-    NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG(set_a);
-    NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG(set_b);
-    guint              i;
-
-    if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_QDISCS)) {
-        if (set_b) {
-            if (a_tc_config->qdiscs->len != b_tc_config->qdiscs->len)
-                return FALSE;
-            for (i = 0; i < a_tc_config->qdiscs->len; i++) {
-                if (!nm_tc_qdisc_equal(a_tc_config->qdiscs->pdata[i],
-                                       b_tc_config->qdiscs->pdata[i]))
-                    return FALSE;
-            }
-        }
-        return TRUE;
-    }
-
-    if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_TFILTERS)) {
-        if (set_b) {
-            if (a_tc_config->tfilters->len != b_tc_config->tfilters->len)
-                return FALSE;
-            for (i = 0; i < a_tc_config->tfilters->len; i++) {
-                if (!nm_tc_tfilter_equal(a_tc_config->tfilters->pdata[i],
-                                         b_tc_config->tfilters->pdata[i]))
-                    return FALSE;
-            }
-        }
-        return TRUE;
-    }
-
-    return NM_SETTING_CLASS(nm_setting_tc_config_parent_class)
-        ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags);
-}
-
-/**
- * _qdiscs_to_variant:
- * @qdiscs: (element-type NMTCQdisc): an array of #NMTCQdisc objects
- *
- * Utility function to convert a #GPtrArray of #NMTCQdisc objects representing
- * TC qdiscs into a #GVariant of type 'aa{sv}' representing an array
- * of NetworkManager TC qdiscs.
- *
- * Returns: (transfer none): a new floating #GVariant representing @qdiscs.
- **/
-static GVariant *
-_qdiscs_to_variant(GPtrArray *qdiscs)
-{
-    GVariantBuilder builder;
-    int             i;
-
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
-    if (qdiscs) {
-        for (i = 0; i < qdiscs->len; i++) {
-            NMUtilsNamedValue attrs_static[30];
-            gs_free NMUtilsNamedValue *attrs_free = NULL;
-            const NMUtilsNamedValue *  attrs;
-            NMTCQdisc *                qdisc = qdiscs->pdata[i];
-            guint                      length;
-            GVariantBuilder            qdisc_builder;
-            guint                      y;
-
-            g_variant_builder_init(&qdisc_builder, G_VARIANT_TYPE_VARDICT);
-
-            g_variant_builder_add(&qdisc_builder,
-                                  "{sv}",
-                                  "kind",
-                                  g_variant_new_string(nm_tc_qdisc_get_kind(qdisc)));
-
-            g_variant_builder_add(&qdisc_builder,
-                                  "{sv}",
-                                  "handle",
-                                  g_variant_new_uint32(nm_tc_qdisc_get_handle(qdisc)));
-
-            g_variant_builder_add(&qdisc_builder,
-                                  "{sv}",
-                                  "parent",
-                                  g_variant_new_uint32(nm_tc_qdisc_get_parent(qdisc)));
-
-            attrs = nm_utils_named_values_from_strdict(qdisc->attributes,
-                                                       &length,
-                                                       attrs_static,
-                                                       &attrs_free);
-            for (y = 0; y < length; y++) {
-                g_variant_builder_add(&qdisc_builder, "{sv}", attrs[y].name, attrs[y].value_ptr);
-            }
-
-            g_variant_builder_add(&builder, "a{sv}", &qdisc_builder);
-        }
-    }
-
-    return g_variant_builder_end(&builder);
-}
-
-/**
- * _qdiscs_from_variant:
- * @value: a #GVariant of type 'aa{sv}'
- *
- * Utility function to convert a #GVariant representing a list of TC qdiscs
- * into a #GPtrArray of * #NMTCQdisc objects.
- *
- * Returns: (transfer full) (element-type NMTCQdisc): a newly allocated
- *   #GPtrArray of #NMTCQdisc objects
- **/
-static GPtrArray *
-_qdiscs_from_variant(GVariant *value)
-{
-    GPtrArray *  qdiscs;
-    GVariant *   qdisc_var;
-    GVariantIter iter;
-    GError *     error = NULL;
-
-    g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL);
-
-    g_variant_iter_init(&iter, value);
-    qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref);
-
-    while (g_variant_iter_next(&iter, "@a{sv}", &qdisc_var)) {
-        const char * kind;
-        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)) {
-            //g_warning ("Ignoring invalid qdisc");
-            goto next;
-        }
-
-        qdisc = nm_tc_qdisc_new(kind, parent, &error);
-        if (!qdisc) {
-            //g_warning ("Ignoring invalid qdisc: %s", error->message);
-            g_clear_error(&error);
-            goto next;
-        }
-
-        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:
-        g_variant_unref(qdisc_var);
-    }
-
-    return qdiscs;
-}
-
-static GVariant *
-tc_qdiscs_get(const NMSettInfoSetting *               sett_info,
-              guint                                   property_idx,
-              NMConnection *                          connection,
-              NMSetting *                             setting,
-              NMConnectionSerializationFlags          flags,
-              const NMConnectionSerializationOptions *options)
-{
-    gs_unref_ptrarray GPtrArray *qdiscs = NULL;
-
-    g_object_get(setting, NM_SETTING_TC_CONFIG_QDISCS, &qdiscs, NULL);
-    return _qdiscs_to_variant(qdiscs);
-}
-
-static gboolean
-tc_qdiscs_set(NMSetting *         setting,
-              GVariant *          connection_dict,
-              const char *        property,
-              GVariant *          value,
-              NMSettingParseFlags parse_flags,
-              GError **           error)
-{
-    GPtrArray *qdiscs;
-
-    qdiscs = _qdiscs_from_variant(value);
-    g_object_set(setting, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL);
-    g_ptr_array_unref(qdiscs);
-
-    return TRUE;
-}
-
-static GVariant *
-_action_to_variant(NMTCAction *action)
-{
-    GVariantBuilder    builder;
-    gs_strfreev char **attrs = nm_tc_action_get_attribute_names(action);
-    int                i;
-
-    g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
-
-    g_variant_builder_add(&builder,
-                          "{sv}",
-                          "kind",
-                          g_variant_new_string(nm_tc_action_get_kind(action)));
-
-    for (i = 0; attrs[i]; i++) {
-        g_variant_builder_add(&builder,
-                              "{sv}",
-                              attrs[i],
-                              nm_tc_action_get_attribute(action, attrs[i]));
-    }
-
-    return g_variant_builder_end(&builder);
-}
-
-/**
- * _tfilters_to_variant:
- * @tfilters: (element-type NMTCTfilter): an array of #NMTCTfilter objects
- *
- * Utility function to convert a #GPtrArray of #NMTCTfilter objects representing
- * TC tfilters into a #GVariant of type 'aa{sv}' representing an array
- * of NetworkManager TC tfilters.
- *
- * Returns: (transfer none): a new floating #GVariant representing @tfilters.
- **/
-static GVariant *
-_tfilters_to_variant(GPtrArray *tfilters)
-{
-    GVariantBuilder builder;
-    int             i;
-
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
-    if (tfilters) {
-        for (i = 0; i < tfilters->len; i++) {
-            NMTCTfilter *   tfilter = tfilters->pdata[i];
-            NMTCAction *    action  = nm_tc_tfilter_get_action(tfilter);
-            GVariantBuilder tfilter_builder;
-
-            g_variant_builder_init(&tfilter_builder, G_VARIANT_TYPE("a{sv}"));
-
-            g_variant_builder_add(&tfilter_builder,
-                                  "{sv}",
-                                  "kind",
-                                  g_variant_new_string(nm_tc_tfilter_get_kind(tfilter)));
-            g_variant_builder_add(&tfilter_builder,
-                                  "{sv}",
-                                  "handle",
-                                  g_variant_new_uint32(nm_tc_tfilter_get_handle(tfilter)));
-            g_variant_builder_add(&tfilter_builder,
-                                  "{sv}",
-                                  "parent",
-                                  g_variant_new_uint32(nm_tc_tfilter_get_parent(tfilter)));
-
-            if (action) {
-                g_variant_builder_add(&tfilter_builder,
-                                      "{sv}",
-                                      "action",
-                                      _action_to_variant(action));
-            }
-
-            g_variant_builder_add(&builder, "a{sv}", &tfilter_builder);
-        }
-    }
-
-    return g_variant_builder_end(&builder);
-}
-
-/**
- * _tfilters_from_variant:
- * @value: a #GVariant of type 'aa{sv}'
- *
- * Utility function to convert a #GVariant representing a list of TC tfilters
- * into a #GPtrArray of * #NMTCTfilter objects.
- *
- * Returns: (transfer full) (element-type NMTCTfilter): a newly allocated
- *   #GPtrArray of #NMTCTfilter objects
- **/
-static GPtrArray *
-_tfilters_from_variant(GVariant *value)
-{
-    GPtrArray *  tfilters;
-    GVariant *   tfilter_var;
-    GVariantIter iter;
-    GError *     error = NULL;
-
-    g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL);
-
-    g_variant_iter_init(&iter, value);
-    tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref);
-
-    while (g_variant_iter_next(&iter, "@a{sv}", &tfilter_var)) {
-        NMTCTfilter *tfilter = NULL;
-        const char * kind;
-        guint32      handle;
-        guint32      parent;
-        NMTCAction * action;
-        const char * action_kind = NULL;
-        char *       action_key;
-        GVariantIter action_iter;
-        GVariant *   action_var = NULL;
-        GVariant *   action_val;
-
-        if (!g_variant_lookup(tfilter_var, "kind", "&s", &kind)
-            || !g_variant_lookup(tfilter_var, "parent", "u", &parent)) {
-            //g_warning ("Ignoring invalid tfilter");
-            goto next;
-        }
-
-        tfilter = nm_tc_tfilter_new(kind, parent, &error);
-        if (!tfilter) {
-            //g_warning ("Ignoring invalid tfilter: %s", error->message);
-            g_clear_error(&error);
-            goto next;
-        }
-
-        if (g_variant_lookup(tfilter_var, "handle", "u", &handle))
-            nm_tc_tfilter_set_handle(tfilter, handle);
-
-        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");
-                goto next;
-            }
-
-            action = nm_tc_action_new(action_kind, &error);
-            if (!action) {
-                //g_warning ("Ignoring tfilter with invalid action: %s", error->message);
-                g_clear_error(&error);
-                goto next;
-            }
-
-            g_variant_iter_init(&action_iter, action_var);
-            while (g_variant_iter_next(&action_iter, "{&sv}", &action_key, &action_val)) {
-                if (strcmp(action_key, "kind") != 0)
-                    nm_tc_action_set_attribute(action, action_key, action_val);
-                g_variant_unref(action_val);
-            }
-
-            nm_tc_tfilter_set_action(tfilter, action);
-            nm_tc_action_unref(action);
-        }
-
-        nm_tc_tfilter_ref(tfilter);
-        g_ptr_array_add(tfilters, tfilter);
-next:
-        if (tfilter)
-            nm_tc_tfilter_unref(tfilter);
-        if (action_var)
-            g_variant_unref(action_var);
-        g_variant_unref(tfilter_var);
-    }
-
-    return tfilters;
-}
-
-static GVariant *
-tc_tfilters_get(const NMSettInfoSetting *               sett_info,
-                guint                                   property_idx,
-                NMConnection *                          connection,
-                NMSetting *                             setting,
-                NMConnectionSerializationFlags          flags,
-                const NMConnectionSerializationOptions *options)
-{
-    gs_unref_ptrarray GPtrArray *tfilters = NULL;
-
-    g_object_get(setting, NM_SETTING_TC_CONFIG_TFILTERS, &tfilters, NULL);
-    return _tfilters_to_variant(tfilters);
-}
-
-static gboolean
-tc_tfilters_set(NMSetting *         setting,
-                GVariant *          connection_dict,
-                const char *        property,
-                GVariant *          value,
-                NMSettingParseFlags parse_flags,
-                GError **           error)
-{
-    gs_unref_ptrarray GPtrArray *tfilters = NULL;
-
-    tfilters = _tfilters_from_variant(value);
-    g_object_set(setting, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL);
-    return TRUE;
-}
-
-/*****************************************************************************/
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-    NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object);
-
-    switch (prop_id) {
-    case PROP_QDISCS:
-        g_value_take_boxed(value,
-                           _nm_utils_copy_array(self->qdiscs,
-                                                (NMUtilsCopyFunc) nm_tc_qdisc_dup,
-                                                (GDestroyNotify) nm_tc_qdisc_unref));
-        break;
-    case PROP_TFILTERS:
-        g_value_take_boxed(value,
-                           _nm_utils_copy_array(self->tfilters,
-                                                (NMUtilsCopyFunc) nm_tc_tfilter_dup,
-                                                (GDestroyNotify) nm_tc_tfilter_unref));
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-        break;
-    }
-}
-
-static void
-set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-    NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object);
-
-    switch (prop_id) {
-    case PROP_QDISCS:
-        g_ptr_array_unref(self->qdiscs);
-        self->qdiscs = _nm_utils_copy_array(g_value_get_boxed(value),
-                                            (NMUtilsCopyFunc) nm_tc_qdisc_dup,
-                                            (GDestroyNotify) nm_tc_qdisc_unref);
-        break;
-    case PROP_TFILTERS:
-        g_ptr_array_unref(self->tfilters);
-        self->tfilters = _nm_utils_copy_array(g_value_get_boxed(value),
-                                              (NMUtilsCopyFunc) nm_tc_tfilter_dup,
-                                              (GDestroyNotify) nm_tc_tfilter_unref);
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-        break;
-    }
-}
-
-/*****************************************************************************/
-
-static void
-nm_setting_tc_config_init(NMSettingTCConfig *self)
-{
-    self->qdiscs   = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref);
-    self->tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref);
-}
-
-/**
- * nm_setting_tc_config_new:
- *
- * Creates a new #NMSettingTCConfig object with default values.
- *
- * Returns: (transfer full): the new empty #NMSettingTCConfig object
- *
- * Since: 1.12
- **/
-NMSetting *
-nm_setting_tc_config_new(void)
-{
-    return g_object_new(NM_TYPE_SETTING_TC_CONFIG, NULL);
-}
-
-static void
-finalize(GObject *object)
-{
-    NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object);
-
-    g_ptr_array_unref(self->qdiscs);
-    g_ptr_array_unref(self->tfilters);
-
-    G_OBJECT_CLASS(nm_setting_tc_config_parent_class)->finalize(object);
-}
-
-static void
-nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass)
-{
-    GObjectClass *  object_class        = G_OBJECT_CLASS(klass);
-    NMSettingClass *setting_class       = NM_SETTING_CLASS(klass);
-    GArray *        properties_override = _nm_sett_info_property_override_create_array();
-
-    object_class->get_property = get_property;
-    object_class->set_property = set_property;
-    object_class->finalize     = finalize;
-
-    setting_class->compare_property = compare_property;
-    setting_class->verify           = verify;
-
-    /**
-     * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc))
-     *
-     * Array of TC queueing disciplines.
-     *
-     * When the #NMSettingTCConfig setting is present, qdiscs from this
-     * property are applied upon activation. If the property is empty,
-     * all qdiscs are removed and the device will only
-     * have the default qdisc assigned by kernel according to the
-     * "net.core.default_qdisc" sysctl.
-     *
-     * If the #NMSettingTCConfig setting is not present, NetworkManager
-     * doesn't touch the qdiscs present on the interface.
-     **/
-    /* ---ifcfg-rh---
-     * property: qdiscs
-     * variable: QDISC1(+), QDISC2(+), ..., TC_COMMIT(+)
-     * description: Queueing disciplines to set on the interface. When no
-     *  QDISC1, QDISC2, ..., FILTER1, FILTER2, ... keys are present,
-     *  NetworkManager doesn't touch qdiscs and filters present on the
-     *  interface, unless TC_COMMIT is set to 'yes'.
-     * example: QDISC1=ingress, QDISC2="root handle 1234: fq_codel"
-     * ---end---
-     */
-    obj_properties[PROP_QDISCS] = g_param_spec_boxed(NM_SETTING_TC_CONFIG_QDISCS,
-                                                     "",
-                                                     "",
-                                                     G_TYPE_PTR_ARRAY,
-                                                     G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE
-                                                         | G_PARAM_STATIC_STRINGS);
-    _nm_properties_override_gobj(properties_override,
-                                 obj_properties[PROP_QDISCS],
-                                 NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"),
-                                                           .to_dbus_fcn   = tc_qdiscs_get,
-                                                           .from_dbus_fcn = tc_qdiscs_set, ));
-
-    /**
-     * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter))
-     *
-     * Array of TC traffic filters.
-     *
-     * When the #NMSettingTCConfig setting is present, filters from this
-     * property are applied upon activation. If the property is empty,
-     * NetworkManager removes all the filters.
-     *
-     * If the #NMSettingTCConfig setting is not present, NetworkManager
-     * doesn't touch the filters present on the interface.
-     **/
-    /* ---ifcfg-rh---
-     * property: qdiscs
-     * variable: FILTER1(+), FILTER2(+), ..., TC_COMMIT(+)
-     * description: Traffic filters to set on the interface. When no
-     *  QDISC1, QDISC2, ..., FILTER1, FILTER2, ... keys are present,
-     *  NetworkManager doesn't touch qdiscs and filters present on the
-     *  interface, unless TC_COMMIT is set to 'yes'.
-     * example: FILTER1="parent ffff: matchall action simple sdata Input", ...
-     * ---end---
-     */
-    obj_properties[PROP_TFILTERS] = g_param_spec_boxed(
-        NM_SETTING_TC_CONFIG_TFILTERS,
-        "",
-        "",
-        G_TYPE_PTR_ARRAY,
-        G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS);
-    _nm_properties_override_gobj(properties_override,
-                                 obj_properties[PROP_TFILTERS],
-                                 NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"),
-                                                           .to_dbus_fcn   = tc_tfilters_get,
-                                                           .from_dbus_fcn = tc_tfilters_set, ));
-
-    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-    _nm_setting_class_commit_full(setting_class,
-                                  NM_META_SETTING_TYPE_TC_CONFIG,
-                                  NULL,
-                                  properties_override);
-}