about summary refs log tree commit diff
path: root/src/platform/tests
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2021-02-11 18:11:46 +0100
committerMichael Biebl <biebl@debian.org>2021-02-11 18:11:46 +0100
commit80ec1decc49c72efec2a8b87c06245c92c0ab807 (patch)
treee3b229aa94e8dcf0590f2317664176e7b8f7607b /src/platform/tests
parent65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (diff)
New upstream version 1.29.90 upstream/1.29.90
Diffstat (limited to 'src/platform/tests')
-rw-r--r--src/platform/tests/meson.build43
-rw-r--r--src/platform/tests/monitor.c78
-rw-r--r--src/platform/tests/test-address.c465
-rw-r--r--src/platform/tests/test-cleanup.c188
-rw-r--r--src/platform/tests/test-common.c2569
-rw-r--r--src/platform/tests/test-common.h610
-rw-r--r--src/platform/tests/test-link.c3819
-rw-r--r--src/platform/tests/test-nmp-object.c617
-rw-r--r--src/platform/tests/test-platform-general.c772
-rw-r--r--src/platform/tests/test-route.c1926
-rw-r--r--src/platform/tests/test-tc.c222
11 files changed, 0 insertions, 11309 deletions
diff --git a/src/platform/tests/meson.build b/src/platform/tests/meson.build
deleted file mode 100644
index f96850cc..00000000
--- a/src/platform/tests/meson.build
+++ /dev/null
@@ -1,43 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1+
-
-test_fake_c_flags = test_c_flags + ['-DSETUP=nm_fake_platform_setup']
-test_linux_c_flags = test_c_flags + ['-DSETUP=nm_linux_platform_setup']
-
-test_units = [
-  ['test-address-fake', 'test-address.c', test_fake_c_flags, default_test_timeout],
-  ['test-address-linux', 'test-address.c', test_linux_c_flags, default_test_timeout],
-  ['test-cleanup-fake', 'test-cleanup.c', test_fake_c_flags, default_test_timeout],
-  ['test-cleanup-linux', 'test-cleanup.c', test_linux_c_flags, default_test_timeout],
-  ['test-link-fake', 'test-link.c', test_fake_c_flags, default_test_timeout],
-  ['test-link-linux', 'test-link.c', test_linux_c_flags, 900],
-  ['test-nmp-object', 'test-nmp-object.c', test_c_flags, default_test_timeout],
-  ['test-platform-general', 'test-platform-general.c', test_c_flags, default_test_timeout],
-  ['test-route-fake', 'test-route.c', test_fake_c_flags, default_test_timeout],
-  ['test-route-linux', 'test-route.c', test_linux_c_flags, default_test_timeout],
-  ['test-tc-fake', 'test-tc.c', test_fake_c_flags, default_test_timeout],
-  ['test-tc-linux', 'test-tc.c', test_linux_c_flags, default_test_timeout],
-]
-
-foreach test_unit: test_units
-  exe = executable(
-    test_unit[0],
-    test_unit[1],
-    dependencies: libnetwork_manager_test_dep,
-    c_args: test_unit[2],
-  )
-  test(
-    'platform/' + test_unit[0],
-    test_script,
-    timeout: test_unit[3],
-    args: test_args + [exe.full_path()],
-  )
-endforeach
-
-name = 'monitor'
-
-executable(
-  name,
-  name + '.c',
-  dependencies: libnetwork_manager_test_dep,
-  c_args: test_c_flags,
-)
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
deleted file mode 100644
index a8d0fad2..00000000
--- a/src/platform/tests/monitor.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include <stdlib.h>
-#include <syslog.h>
-
-#include "platform/nm-linux-platform.h"
-
-#include "nm-test-utils-core.h"
-
-NMTST_DEFINE();
-
-static struct {
-    gboolean persist;
-} global_opt = {
-    .persist = TRUE,
-};
-
-static gboolean
-read_argv(int *argc, char ***argv)
-{
-    GOptionContext *context;
-    GOptionEntry    options[] = {
-        {"no-persist",
-         'P',
-         G_OPTION_FLAG_REVERSE,
-         G_OPTION_ARG_NONE,
-         &global_opt.persist,
-         "Exit after processing netlink messages",
-         NULL},
-        {0},
-    };
-    gs_free_error GError *error = NULL;
-
-    context = g_option_context_new(NULL);
-    g_option_context_set_summary(context, "Monitor netlink events in NMPlatform.");
-    g_option_context_add_main_entries(context, options, NULL);
-
-    if (!g_option_context_parse(context, argc, argv, &error)) {
-        g_warning("Error parsing command line arguments: %s", error->message);
-        g_option_context_free(context);
-        return FALSE;
-    }
-
-    g_option_context_free(context);
-    return TRUE;
-}
-
-int
-main(int argc, char **argv)
-{
-    GMainLoop *loop;
-
-    if (!g_getenv("G_MESSAGES_DEBUG"))
-        g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
-
-    nmtst_init_with_logging(&argc, &argv, "DEBUG", "ALL");
-
-    if (!read_argv(&argc, &argv))
-        return 2;
-
-    nm_log_info(LOGD_PLATFORM, "platform monitor start");
-
-    loop = g_main_loop_new(NULL, FALSE);
-
-    nm_linux_platform_setup();
-
-    if (global_opt.persist)
-        g_main_loop_run(loop);
-
-    g_main_loop_unref(loop);
-
-    return EXIT_SUCCESS;
-}
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
deleted file mode 100644
index 5ea30a57..00000000
--- a/src/platform/tests/test-address.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "test-common.h"
-
-#define IP4_ADDRESS       "192.0.2.1"
-#define IP4_ADDRESS_PEER  "192.0.2.2"
-#define IP4_ADDRESS_PEER2 "192.0.3.1"
-#define IP4_PLEN          24
-#define IP6_ADDRESS       "2001:db8:a:b:1:2:3:4"
-#define IP6_PLEN          64
-
-#define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX
-#define EX             NMTSTP_ENV1_EX
-
-/*****************************************************************************/
-
-static void
-ip4_address_callback(NMPlatform *               platform,
-                     NMPObjectType              obj_type,
-                     int                        ifindex,
-                     NMPlatformIP4Address *     received,
-                     NMPlatformSignalChangeType change_type,
-                     SignalData *               data)
-{
-    g_assert(received);
-    g_assert_cmpint(received->ifindex, ==, ifindex);
-    g_assert(data && data->name);
-    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED);
-
-    if (data->ifindex && data->ifindex != received->ifindex)
-        return;
-    if (data->change_type != change_type)
-        return;
-
-    if (data->loop)
-        g_main_loop_quit(data->loop);
-
-    data->received_count++;
-    _LOGD("Received signal '%s' %dth time.", data->name, data->received_count);
-}
-
-static void
-ip6_address_callback(NMPlatform *               platform,
-                     NMPObjectType              obj_type,
-                     int                        ifindex,
-                     NMPlatformIP6Address *     received,
-                     NMPlatformSignalChangeType change_type,
-                     SignalData *               data)
-{
-    g_assert(received);
-    g_assert_cmpint(received->ifindex, ==, ifindex);
-    g_assert(data && data->name);
-    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED);
-
-    if (data->ifindex && data->ifindex != received->ifindex)
-        return;
-    if (data->change_type != change_type)
-        return;
-
-    if (data->loop)
-        g_main_loop_quit(data->loop);
-
-    data->received_count++;
-    _LOGD("Received signal '%s' %dth time.", data->name, data->received_count);
-}
-
-/*****************************************************************************/
-
-static void
-test_ip4_address_general(void)
-{
-    const int   ifindex         = DEVICE_IFINDEX;
-    SignalData *address_added   = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                                   NM_PLATFORM_SIGNAL_ADDED,
-                                                   ip4_address_callback,
-                                                   ifindex);
-    SignalData *address_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                                     NM_PLATFORM_SIGNAL_CHANGED,
-                                                     ip4_address_callback,
-                                                     ifindex);
-    SignalData *address_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                                     NM_PLATFORM_SIGNAL_REMOVED,
-                                                     ip4_address_callback,
-                                                     ifindex);
-    GArray *    addresses;
-    NMPlatformIP4Address *address;
-    in_addr_t             addr;
-    guint32               lifetime  = 2000;
-    guint32               preferred = 1000;
-
-    inet_pton(AF_INET, IP4_ADDRESS, &addr);
-
-    /* Add address */
-    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-    nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
-    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-    accept_signal(address_added);
-
-    /* Add address again (aka update) */
-    nmtstp_ip4_address_add(NULL,
-                           EX,
-                           ifindex,
-                           addr,
-                           IP4_PLEN,
-                           addr,
-                           lifetime + 100,
-                           preferred + 50,
-                           0,
-                           NULL);
-    accept_signals(address_changed, 0, 1);
-
-    /* Test address listing */
-    addresses = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
-    g_assert(addresses);
-    g_assert_cmpint(addresses->len, ==, 1);
-    address = &g_array_index(addresses, NMPlatformIP4Address, 0);
-    g_assert_cmpint(address->ifindex, ==, ifindex);
-    g_assert_cmphex(address->address, ==, addr);
-    g_assert_cmphex(address->peer_address, ==, addr);
-    g_assert_cmpint(address->plen, ==, IP4_PLEN);
-    g_array_unref(addresses);
-
-    /* Remove address */
-    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr);
-    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-    accept_signal(address_removed);
-
-    /* Remove address again */
-    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr);
-
-    free_signal(address_added);
-    free_signal(address_changed);
-    free_signal(address_removed);
-}
-
-static void
-test_ip6_address_general(void)
-{
-    const int   ifindex         = DEVICE_IFINDEX;
-    SignalData *address_added   = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
-                                                   NM_PLATFORM_SIGNAL_ADDED,
-                                                   ip6_address_callback,
-                                                   ifindex);
-    SignalData *address_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
-                                                     NM_PLATFORM_SIGNAL_CHANGED,
-                                                     ip6_address_callback,
-                                                     ifindex);
-    SignalData *address_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
-                                                     NM_PLATFORM_SIGNAL_REMOVED,
-                                                     ip6_address_callback,
-                                                     ifindex);
-    GArray *    addresses;
-    NMPlatformIP6Address *address;
-    struct in6_addr       addr;
-    guint32               lifetime  = 2000;
-    guint32               preferred = 1000;
-    guint                 flags     = 0;
-
-    inet_pton(AF_INET6, IP6_ADDRESS, &addr);
-
-    /* Add address */
-    g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-    nmtstp_ip6_address_add(NULL,
-                           EX,
-                           ifindex,
-                           addr,
-                           IP6_PLEN,
-                           in6addr_any,
-                           lifetime,
-                           preferred,
-                           flags);
-    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-    accept_signal(address_added);
-
-    /* Add address again (aka update) */
-    nmtstp_ip6_address_add(NULL,
-                           EX,
-                           ifindex,
-                           addr,
-                           IP6_PLEN,
-                           in6addr_any,
-                           lifetime,
-                           preferred,
-                           flags);
-    accept_signals(address_changed, 0, 2);
-
-    /* Test address listing */
-    addresses = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex);
-    g_assert(addresses);
-    g_assert_cmpint(addresses->len, ==, 1);
-    address = &g_array_index(addresses, NMPlatformIP6Address, 0);
-    g_assert_cmpint(address->ifindex, ==, ifindex);
-    g_assert(!memcmp(&address->address, &addr, sizeof(addr)));
-    g_assert_cmpint(address->plen, ==, IP6_PLEN);
-    g_array_unref(addresses);
-
-    /* Remove address */
-    nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN);
-    g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-    accept_signal(address_removed);
-
-    /* Remove address again */
-    nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN);
-
-    /* ensure not pending signal. */
-    accept_signals(address_changed, 0, 1);
-
-    free_signal(address_added);
-    free_signal(address_changed);
-    free_signal(address_removed);
-}
-
-static void
-test_ip4_address_general_2(void)
-{
-    const int   ifindex         = DEVICE_IFINDEX;
-    SignalData *address_added   = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                           NM_PLATFORM_SIGNAL_ADDED,
-                                           ip4_address_callback);
-    SignalData *address_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                             NM_PLATFORM_SIGNAL_REMOVED,
-                                             ip4_address_callback);
-    in_addr_t   addr;
-    guint32     lifetime  = 2000;
-    guint32     preferred = 1000;
-
-    inet_pton(AF_INET, IP4_ADDRESS, &addr);
-    g_assert(ifindex > 0);
-
-    /* Looks like addresses are not announced by kernel when the interface
-     * is down. Link-local IPv6 address is automatically added.
-     */
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, DEVICE_IFINDEX, NULL));
-
-    /* Add/delete notification */
-    nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
-    accept_signal(address_added);
-    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr);
-    accept_signal(address_removed);
-    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-
-    /* Add/delete conflict */
-    nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
-    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-    accept_signal(address_added);
-
-    free_signal(address_added);
-    free_signal(address_removed);
-}
-
-static void
-test_ip6_address_general_2(void)
-{
-    const int       ifindex         = DEVICE_IFINDEX;
-    SignalData *    address_added   = add_signal(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
-                                           NM_PLATFORM_SIGNAL_ADDED,
-                                           ip6_address_callback);
-    SignalData *    address_removed = add_signal(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
-                                             NM_PLATFORM_SIGNAL_REMOVED,
-                                             ip6_address_callback);
-    struct in6_addr addr;
-    guint32         lifetime  = 2000;
-    guint32         preferred = 1000;
-    guint           flags     = 0;
-
-    inet_pton(AF_INET6, IP6_ADDRESS, &addr);
-
-    /* Add/delete notification */
-    nmtstp_ip6_address_add(NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
-    accept_signal(address_added);
-    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-
-    nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN);
-    accept_signal(address_removed);
-    g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-
-    /* Add/delete conflict */
-    nmtstp_ip6_address_add(NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
-    accept_signal(address_added);
-    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-
-    nmtstp_ip6_address_add(NULL,
-                           EX,
-                           ifindex,
-                           addr,
-                           IP6_PLEN,
-                           in6addr_any,
-                           lifetime,
-                           preferred,
-                           flags);
-    ensure_no_signal(address_added);
-    g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr));
-
-    free_signal(address_added);
-    free_signal(address_removed);
-}
-
-/*****************************************************************************/
-
-static void
-test_ip4_address_peer(void)
-{
-    const int                   ifindex         = DEVICE_IFINDEX;
-    SignalData *                address_added   = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                           NM_PLATFORM_SIGNAL_ADDED,
-                                           ip4_address_callback);
-    SignalData *                address_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                             NM_PLATFORM_SIGNAL_REMOVED,
-                                             ip4_address_callback);
-    in_addr_t                   addr, addr_peer, addr_peer2;
-    guint32                     lifetime  = 2000;
-    guint32                     preferred = 1000;
-    const NMPlatformIP4Address *a;
-
-    inet_pton(AF_INET, IP4_ADDRESS, &addr);
-    inet_pton(AF_INET, IP4_ADDRESS_PEER, &addr_peer);
-    inet_pton(AF_INET, IP4_ADDRESS_PEER2, &addr_peer2);
-    g_assert(ifindex > 0);
-
-    g_assert(addr != addr_peer);
-
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL));
-    accept_signals(address_removed, 0, G_MAXINT);
-    accept_signals(address_added, 0, G_MAXINT);
-
-    /* Add/delete notification */
-    nmtstp_ip4_address_add(NULL,
-                           EX,
-                           ifindex,
-                           addr,
-                           IP4_PLEN,
-                           addr_peer,
-                           lifetime,
-                           preferred,
-                           0,
-                           NULL);
-    accept_signal(address_added);
-    a = nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer);
-    g_assert(a);
-    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
-
-    nmtstp_ip_address_assert_lifetime((NMPlatformIPAddress *) a, -1, lifetime, preferred);
-
-    nmtstp_ip4_address_add(NULL,
-                           EX,
-                           ifindex,
-                           addr,
-                           IP4_PLEN,
-                           addr_peer2,
-                           lifetime,
-                           preferred,
-                           0,
-                           NULL);
-    accept_signal(address_added);
-    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
-    a = nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2);
-    g_assert(a);
-
-    nmtstp_ip_address_assert_lifetime((NMPlatformIPAddress *) a, -1, lifetime, preferred);
-
-    g_assert(addr != addr_peer);
-    nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr_peer);
-    accept_signal(address_removed);
-    g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
-    g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
-
-    free_signal(address_added);
-    free_signal(address_removed);
-}
-
-/*****************************************************************************/
-
-static void
-test_ip4_address_peer_zero(void)
-{
-    const int   ifindex = DEVICE_IFINDEX;
-    in_addr_t   addr, addr_peer;
-    guint32     lifetime  = 2000;
-    guint32     preferred = 1000;
-    const gint8 plen      = 24;
-    const char *label     = NULL;
-    in_addr_t   peers[3], r_peers[3];
-    int         i;
-    GArray *    addrs;
-
-    g_assert(ifindex > 0);
-
-    inet_pton(AF_INET, "192.168.5.2", &addr);
-    inet_pton(AF_INET, "192.168.6.2", &addr_peer);
-    peers[0] = addr;
-    peers[1] = addr_peer;
-    peers[2] = 0;
-
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL));
-
-    nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers));
-    for (i = 0; i < G_N_ELEMENTS(peers); i++) {
-        g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
-
-        nmtstp_ip4_address_add(NULL,
-                               EX,
-                               ifindex,
-                               addr,
-                               plen,
-                               r_peers[i],
-                               lifetime,
-                               preferred,
-                               0,
-                               label);
-
-        addrs = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
-        g_assert(addrs);
-        g_assert_cmpint(addrs->len, ==, i + 1);
-        g_array_unref(addrs);
-    }
-
-    if (nmtst_is_debug() && nmtstp_is_root_test())
-        nmtstp_run_command_check("ip address show dev %s", DEVICE_NAME);
-
-    nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers));
-    for (i = 0; i < G_N_ELEMENTS(peers); i++) {
-        g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
-
-        nmtstp_ip4_address_del(NULL, EX, ifindex, addr, plen, r_peers[i]);
-
-        addrs = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
-        g_assert(addrs);
-        g_assert_cmpint(addrs->len, ==, G_N_ELEMENTS(peers) - i - 1);
-        g_array_unref(addrs);
-    }
-}
-
-/*****************************************************************************/
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
-    nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-/*****************************************************************************
- * SETUP TESTS
- *****************************************************************************/
-
-void
-_nmtstp_setup_tests(void)
-{
-#define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, FALSE)
-    add_test_func("/address/ipv4/general", test_ip4_address_general);
-    add_test_func("/address/ipv6/general", test_ip6_address_general);
-
-    add_test_func("/address/ipv4/general-2", test_ip4_address_general_2);
-    add_test_func("/address/ipv6/general-2", test_ip6_address_general_2);
-
-    add_test_func("/address/ipv4/peer", test_ip4_address_peer);
-    add_test_func("/address/ipv4/peer/zero", test_ip4_address_peer_zero);
-}
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
deleted file mode 100644
index c364bfa1..00000000
--- a/src/platform/tests/test-cleanup.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2016 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "test-common.h"
-
-static void
-test_cleanup_internal(void)
-{
-    SignalData *    link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                               NM_PLATFORM_SIGNAL_ADDED,
-                                               link_callback,
-                                               DEVICE_NAME);
-    int             ifindex;
-    GArray *        addresses4;
-    GArray *        addresses6;
-    GPtrArray *     routes4;
-    GPtrArray *     routes6;
-    in_addr_t       addr4;
-    in_addr_t       network4;
-    int             plen4 = 24;
-    in_addr_t       gateway4;
-    struct in6_addr addr6;
-    struct in6_addr network6;
-    int             plen6 = 64;
-    struct in6_addr gateway6;
-    int             lifetime  = NM_PLATFORM_LIFETIME_PERMANENT;
-    int             preferred = NM_PLATFORM_LIFETIME_PERMANENT;
-    int             metric    = 20;
-    int             mss       = 1000;
-    guint32         flags     = 0;
-
-    inet_pton(AF_INET, "192.0.2.1", &addr4);
-    inet_pton(AF_INET, "192.0.3.0", &network4);
-    inet_pton(AF_INET, "198.51.100.1", &gateway4);
-    inet_pton(AF_INET6, "2001:db8:a:b:1:2:3:4", &addr6);
-    inet_pton(AF_INET6, "2001:db8:c:d:0:0:0:0", &network6);
-    inet_pton(AF_INET6, "2001:db8:e:f:1:2:3:4", &gateway6);
-
-    /* Create and set up device */
-    g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL)));
-    accept_signal(link_added);
-    free_signal(link_added);
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET,
-                                     nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME),
-                                     NULL));
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert(ifindex > 0);
-
-    /* wait for kernel to add the IPv6 link local address... it takes a bit. */
-    NMTST_WAIT_ASSERT(300, {
-        gs_unref_array GArray *     addrs = NULL;
-        const NMPlatformIP6Address *a;
-
-        if (nmtst_wait_iteration > 0) {
-            nmtstp_wait_for_signal(NM_PLATFORM_GET, nmtst_wait_remaining_us / 1000);
-            nm_platform_process_events(NM_PLATFORM_GET);
-        }
-        addrs = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex);
-        if (addrs->len == 1 && (a = &g_array_index(addrs, NMPlatformIP6Address, 0))
-            && IN6_IS_ADDR_LINKLOCAL(&a->address))
-            break;
-    });
-
-    g_assert(nm_platform_ip4_address_add(NM_PLATFORM_GET,
-                                         ifindex,
-                                         addr4,
-                                         plen4,
-                                         addr4,
-                                         nm_platform_ip4_broadcast_address_create(addr4, plen4),
-                                         lifetime,
-                                         preferred,
-                                         0,
-                                         NULL));
-    g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET,
-                                         ifindex,
-                                         addr6,
-                                         plen6,
-                                         in6addr_any,
-                                         lifetime,
-                                         preferred,
-                                         flags));
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         gateway4,
-                         32,
-                         INADDR_ANY,
-                         0,
-                         metric,
-                         mss);
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network4,
-                         plen4,
-                         gateway4,
-                         0,
-                         metric,
-                         mss);
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         0,
-                         0,
-                         gateway4,
-                         0,
-                         metric,
-                         mss);
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         gateway6,
-                         128,
-                         in6addr_any,
-                         in6addr_any,
-                         metric,
-                         mss);
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network6,
-                         plen6,
-                         gateway6,
-                         in6addr_any,
-                         metric,
-                         mss);
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         in6addr_any,
-                         0,
-                         gateway6,
-                         in6addr_any,
-                         metric,
-                         mss);
-
-    addresses4 = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
-    addresses6 = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex);
-    routes4    = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex);
-    routes6    = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex);
-
-    g_assert_cmpint(addresses4->len, ==, 1);
-    g_assert_cmpint(addresses6->len, ==, 2); /* also has a IPv6 LL address. */
-    g_assert_cmpint(routes4->len, ==, 3);
-    g_assert_cmpint(routes6->len, ==, 3);
-
-    g_array_unref(addresses4);
-    g_array_unref(addresses6);
-    g_ptr_array_unref(routes4);
-    g_ptr_array_unref(routes6);
-
-    /* Delete interface with all addresses and routes */
-    g_assert(nm_platform_link_delete(NM_PLATFORM_GET, ifindex));
-
-    addresses4 = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex);
-    addresses6 = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex);
-    routes4    = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex);
-    routes6    = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex);
-
-    g_assert_cmpint(addresses4->len, ==, 0);
-    g_assert_cmpint(addresses6->len, ==, 0);
-    g_assert(!routes4);
-    g_assert(!routes6);
-
-    g_array_unref(addresses4);
-    g_array_unref(addresses6);
-}
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
-    nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-void
-_nmtstp_setup_tests(void)
-{
-    nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE);
-
-    g_test_add_func("/internal", test_cleanup_internal);
-    /* FIXME: add external cleanup check */
-}
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
deleted file mode 100644
index fb430046..00000000
--- a/src/platform/tests/test-common.c
+++ /dev/null
@@ -1,2569 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2016 - 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include <sys/mount.h>
-#include <sched.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <linux/if_tun.h>
-
-#include "test-common.h"
-
-#define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)"
-#define SIGNAL_DATA_ARG(data)                                                                     \
-    (data)->name, nm_platform_signal_change_type_to_string((data)->change_type), (data)->ifindex, \
-        (data)->ifname ? " ifname '" : "", (data)->ifname ?: "", (data)->ifname ? "'" : "",       \
-        (data)->received_count
-
-int NMTSTP_ENV1_IFINDEX = -1;
-int NMTSTP_ENV1_EX      = -1;
-
-/*****************************************************************************/
-
-void
-nmtstp_setup_platform(void)
-{
-    g_assert(_nmtstp_setup_platform_func);
-    _nmtstp_setup_platform_func();
-}
-
-gboolean
-nmtstp_is_root_test(void)
-{
-    g_assert(_nmtstp_setup_platform_func);
-    return _nmtstp_setup_platform_func == nm_linux_platform_setup;
-}
-
-gboolean
-nmtstp_is_sysfs_writable(void)
-{
-    return !nmtstp_is_root_test() || (access("/sys/devices", W_OK) == 0);
-}
-
-static void
-_init_platform(NMPlatform **platform, gboolean external_command)
-{
-    g_assert(platform);
-    if (!*platform)
-        *platform = NM_PLATFORM_GET;
-    g_assert(NM_IS_PLATFORM(*platform));
-
-    if (external_command)
-        g_assert(NM_IS_LINUX_PLATFORM(*platform));
-}
-
-/*****************************************************************************/
-
-static GArray *
-_ipx_address_get_all(NMPlatform *self, int ifindex, NMPObjectType obj_type)
-{
-    NMPLookup lookup;
-
-    g_assert(NM_IS_PLATFORM(self));
-    g_assert(ifindex > 0);
-    g_assert(NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS));
-    nmp_lookup_init_object(&lookup, obj_type, ifindex);
-    return nmp_cache_lookup_to_array(nm_platform_lookup(self, &lookup),
-                                     obj_type,
-                                     FALSE /*addresses are always visible. */);
-}
-
-GArray *
-nmtstp_platform_ip4_address_get_all(NMPlatform *self, int ifindex)
-{
-    return _ipx_address_get_all(self, ifindex, NMP_OBJECT_TYPE_IP4_ADDRESS);
-}
-
-GArray *
-nmtstp_platform_ip6_address_get_all(NMPlatform *self, int ifindex)
-{
-    return _ipx_address_get_all(self, ifindex, NMP_OBJECT_TYPE_IP6_ADDRESS);
-}
-
-const NMPlatformIPAddress *
-nmtstp_platform_ip_address_find(NMPlatform *self, int ifindex, int addr_family, gconstpointer addr)
-{
-    const gboolean             IS_IPv4 = NM_IS_IPv4(addr_family);
-    const NMPlatformIPAddress *found   = NULL;
-    NMDedupMultiIter           iter;
-    const NMPObject *          obj;
-    NMPLookup                  lookup;
-
-    g_assert(NM_IS_PLATFORM(self));
-    nm_assert(ifindex >= 0);
-    nm_assert_addr_family(addr_family);
-    nm_assert(addr);
-
-    nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex);
-    nm_platform_iter_obj_for_each(&iter, self, &lookup, &obj)
-    {
-        const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(obj);
-
-        g_assert(NMP_OBJECT_GET_ADDR_FAMILY(obj) == addr_family);
-        g_assert(ifindex <= 0 || a->ifindex == ifindex);
-
-        if (memcmp(addr, a->address_ptr, nm_utils_addr_family_to_size(addr_family)) != 0)
-            continue;
-
-        g_assert(!found);
-        found = a;
-    }
-
-    if (!IS_IPv4 && ifindex > 0)
-        g_assert(found
-                 == (const NMPlatformIPAddress *) nm_platform_ip6_address_get(self, ifindex, addr));
-
-    return found;
-}
-
-/*****************************************************************************/
-
-typedef struct {
-    NMIPAddr addr;
-    int      addr_family;
-    bool     found : 1;
-} IPAddressesAssertData;
-
-void
-_nmtstp_platform_ip_addresses_assert(const char *       filename,
-                                     int                lineno,
-                                     NMPlatform *       self,
-                                     int                ifindex,
-                                     gboolean           force_exact_4,
-                                     gboolean           force_exact_6,
-                                     gboolean           ignore_ll6,
-                                     guint              addrs_len,
-                                     const char *const *addrs)
-{
-    gs_free IPAddressesAssertData *addrs_bin = NULL;
-    int                            IS_IPv4;
-    guint                          i;
-
-    g_assert(filename);
-    g_assert(lineno >= 0);
-    g_assert(NM_IS_PLATFORM(self));
-    g_assert(ifindex >= 0);
-
-    addrs_bin = g_new(IPAddressesAssertData, addrs_len);
-
-    for (i = 0; i < addrs_len; i++) {
-        const char *addrstr = addrs[i];
-        int         addr_family;
-        NMIPAddr    a;
-
-        if (!addrstr) {
-            addr_family = AF_UNSPEC;
-            a           = nm_ip_addr_zero;
-        } else if (inet_pton(AF_INET, addrstr, &a) == 1)
-            addr_family = AF_INET;
-        else if (inet_pton(AF_INET6, addrstr, &a) == 1)
-            addr_family = AF_INET6;
-        else
-            g_error("%s:%d: invalid IP address in argument: %s", filename, lineno, addrstr);
-
-        addrs_bin[i] = (IPAddressesAssertData){
-            .addr_family = addr_family,
-            .addr        = a,
-            .found       = FALSE,
-        };
-    }
-
-    for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
-        const int         addr_family           = IS_IPv4 ? AF_INET : AF_INET6;
-        gs_unref_ptrarray GPtrArray *plat_addrs = NULL;
-        NMPLookup                    lookup;
-        guint                        j;
-
-        plat_addrs = nm_platform_lookup_clone(
-            self,
-            nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex),
-            NULL,
-            NULL);
-
-        for (i = 0; i < addrs_len; i++) {
-            IPAddressesAssertData *addr_bin = &addrs_bin[i];
-
-            if (addr_bin->addr_family != addr_family)
-                continue;
-
-            g_assert(!addr_bin->found);
-            for (j = 0; j < nm_g_ptr_array_len(plat_addrs);) {
-                const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(plat_addrs->pdata[j]);
-
-                if (memcmp(&addr_bin->addr,
-                           a->address_ptr,
-                           nm_utils_addr_family_to_size(addr_family))
-                    != 0) {
-                    j++;
-                    continue;
-                }
-
-                g_assert(!addr_bin->found);
-                addr_bin->found = TRUE;
-                g_ptr_array_remove_index_fast(plat_addrs, j);
-            }
-
-            if (!addr_bin->found) {
-                char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
-                g_error("%s:%d: IPv%c address %s was not found on ifindex %d",
-                        filename,
-                        lineno,
-                        nm_utils_addr_family_to_char(addr_bin->addr_family),
-                        nm_utils_inet_ntop(addr_bin->addr_family, &addr_bin->addr, sbuf),
-                        ifindex);
-            }
-        }
-        if (!IS_IPv4 && ignore_ll6 && nm_g_ptr_array_len(plat_addrs) > 0) {
-            /* we prune all remaining, non-matching IPv6 link local addresses. */
-            for (j = 0; j < nm_g_ptr_array_len(plat_addrs);) {
-                const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(plat_addrs->pdata[j]);
-
-                if (!IN6_IS_ADDR_LINKLOCAL(a->address_ptr)) {
-                    j++;
-                    continue;
-                }
-
-                g_ptr_array_remove_index_fast(plat_addrs, j);
-            }
-        }
-        if ((IS_IPv4 ? force_exact_4 : force_exact_6) && nm_g_ptr_array_len(plat_addrs) > 0) {
-            char sbuf[sizeof(_nm_utils_to_string_buffer)];
-
-            g_error("%s:%d: %u IPv%c addresses found on ifindex %d that should not be there (one "
-                    "is %s)",
-                    filename,
-                    lineno,
-                    plat_addrs->len,
-                    nm_utils_addr_family_to_char(addr_family),
-                    ifindex,
-                    nmp_object_to_string(plat_addrs->pdata[0],
-                                         NMP_OBJECT_TO_STRING_PUBLIC,
-                                         sbuf,
-                                         sizeof(sbuf)));
-        }
-    }
-}
-
-/*****************************************************************************/
-
-gboolean
-nmtstp_platform_ip4_route_delete(NMPlatform *platform,
-                                 int         ifindex,
-                                 in_addr_t   network,
-                                 guint8      plen,
-                                 guint32     metric)
-{
-    NMDedupMultiIter iter;
-
-    nm_platform_process_events(platform);
-
-    nm_dedup_multi_iter_for_each (
-        &iter,
-        nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex)) {
-        const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE(iter.current->obj);
-
-        if (r->ifindex != ifindex || r->network != network || r->plen != plen
-            || r->metric != metric) {
-            continue;
-        }
-
-        return nm_platform_object_delete(platform, NMP_OBJECT_UP_CAST(r));
-    }
-
-    return TRUE;
-}
-
-gboolean
-nmtstp_platform_ip6_route_delete(NMPlatform *    platform,
-                                 int             ifindex,
-                                 struct in6_addr network,
-                                 guint8          plen,
-                                 guint32         metric)
-{
-    NMDedupMultiIter iter;
-
-    nm_platform_process_events(platform);
-
-    nm_dedup_multi_iter_for_each (
-        &iter,
-        nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex)) {
-        const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE(iter.current->obj);
-
-        if (r->ifindex != ifindex || !IN6_ARE_ADDR_EQUAL(&r->network, &network) || r->plen != plen
-            || r->metric != metric) {
-            continue;
-        }
-
-        return nm_platform_object_delete(platform, NMP_OBJECT_UP_CAST(r));
-    }
-
-    return TRUE;
-}
-
-/*****************************************************************************/
-
-SignalData *
-add_signal_full(const char *               name,
-                NMPlatformSignalChangeType change_type,
-                GCallback                  callback,
-                int                        ifindex,
-                const char *               ifname)
-{
-    SignalData *data = g_new0(SignalData, 1);
-
-    data->name           = name;
-    data->change_type    = change_type;
-    data->received_count = 0;
-    data->handler_id     = g_signal_connect(NM_PLATFORM_GET, name, callback, data);
-    data->ifindex        = ifindex;
-    data->ifname         = ifname;
-
-    g_assert(data->handler_id > 0);
-
-    return data;
-}
-
-void
-_accept_signal(const char *file, int line, const char *func, SignalData *data)
-{
-    _LOGD("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal one time: " SIGNAL_DATA_FMT,
-          file,
-          line,
-          func,
-          SIGNAL_DATA_ARG(data));
-    if (data->received_count != 1)
-        g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal one "
-                "time: " SIGNAL_DATA_FMT,
-                file,
-                line,
-                func,
-                SIGNAL_DATA_ARG(data));
-    data->received_count = 0;
-}
-
-void
-_accept_signals(const char *file, int line, const char *func, SignalData *data, int min, int max)
-{
-    _LOGD("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal [%d,%d] times: " SIGNAL_DATA_FMT,
-          file,
-          line,
-          func,
-          min,
-          max,
-          SIGNAL_DATA_ARG(data));
-    if (data->received_count < min || data->received_count > max)
-        g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal [%d,%d] "
-                "times: " SIGNAL_DATA_FMT,
-                file,
-                line,
-                func,
-                min,
-                max,
-                SIGNAL_DATA_ARG(data));
-    data->received_count = 0;
-}
-
-void
-_ensure_no_signal(const char *file, int line, const char *func, SignalData *data)
-{
-    _LOGD("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal 0 times: " SIGNAL_DATA_FMT,
-          file,
-          line,
-          func,
-          SIGNAL_DATA_ARG(data));
-    if (data->received_count > 0)
-        g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal 0 "
-                "times: " SIGNAL_DATA_FMT,
-                file,
-                line,
-                func,
-                SIGNAL_DATA_ARG(data));
-}
-
-void
-_accept_or_wait_signal(const char *file, int line, const char *func, SignalData *data)
-{
-    _LOGD("NMPlatformSignalAssert: %s:%d, %s(): accept-or-wait signal: " SIGNAL_DATA_FMT,
-          file,
-          line,
-          func,
-          SIGNAL_DATA_ARG(data));
-    if (data->received_count == 0) {
-        data->loop = g_main_loop_new(NULL, FALSE);
-        g_main_loop_run(data->loop);
-        nm_clear_pointer(&data->loop, g_main_loop_unref);
-    }
-
-    _accept_signal(file, line, func, data);
-}
-
-void
-_wait_signal(const char *file, int line, const char *func, SignalData *data)
-{
-    _LOGD("NMPlatformSignalAssert: %s:%d, %s(): wait signal: " SIGNAL_DATA_FMT,
-          file,
-          line,
-          func,
-          SIGNAL_DATA_ARG(data));
-    if (data->received_count)
-        g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to wait for signal: " SIGNAL_DATA_FMT,
-                file,
-                line,
-                func,
-                SIGNAL_DATA_ARG(data));
-
-    data->loop = g_main_loop_new(NULL, FALSE);
-    g_main_loop_run(data->loop);
-    nm_clear_pointer(&data->loop, g_main_loop_unref);
-
-    _accept_signal(file, line, func, data);
-}
-
-void
-_free_signal(const char *file, int line, const char *func, SignalData *data)
-{
-    _LOGD("NMPlatformSignalAssert: %s:%d, %s(): free signal: " SIGNAL_DATA_FMT,
-          file,
-          line,
-          func,
-          SIGNAL_DATA_ARG(data));
-    if (data->received_count != 0)
-        g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to free non-accepted "
-                "signal: " SIGNAL_DATA_FMT,
-                file,
-                line,
-                func,
-                SIGNAL_DATA_ARG(data));
-
-    g_signal_handler_disconnect(NM_PLATFORM_GET, data->handler_id);
-    g_free(data);
-}
-
-void
-link_callback(NMPlatform *    platform,
-              int             obj_type_i,
-              int             ifindex,
-              NMPlatformLink *received,
-              int             change_type_i,
-              SignalData *    data)
-{
-    const NMPObjectType              obj_type    = obj_type_i;
-    const NMPlatformSignalChangeType change_type = change_type_i;
-    NMPLookup                        lookup;
-    NMDedupMultiIter                 iter;
-    const NMPlatformLink *           cached;
-
-    g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_LINK);
-    g_assert(received);
-    g_assert_cmpint(received->ifindex, ==, ifindex);
-    g_assert(data && data->name);
-    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_LINK_CHANGED);
-
-    if (data->ifindex && data->ifindex != received->ifindex)
-        return;
-    if (data->ifname
-        && g_strcmp0(data->ifname, nm_platform_link_get_name(NM_PLATFORM_GET, ifindex)) != 0)
-        return;
-    if (change_type != data->change_type)
-        return;
-
-    if (data->loop) {
-        _LOGD("Quitting main loop.");
-        g_main_loop_quit(data->loop);
-    }
-
-    data->received_count++;
-    _LOGD("Received signal '%s-%s' ifindex %d ifname '%s' %dth time.",
-          data->name,
-          nm_platform_signal_change_type_to_string(data->change_type),
-          ifindex,
-          received->name,
-          data->received_count);
-
-    if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
-        g_assert(!nm_platform_link_get_name(NM_PLATFORM_GET, ifindex));
-    else
-        g_assert(nm_platform_link_get_name(NM_PLATFORM_GET, ifindex));
-
-    /* Check the data */
-    g_assert(received->ifindex > 0);
-
-    nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK);
-    nmp_cache_iter_for_each_link (&iter, nm_platform_lookup(platform, &lookup), &cached) {
-        if (!nmp_object_is_visible(NMP_OBJECT_UP_CAST(cached)))
-            continue;
-        if (cached->ifindex == received->ifindex) {
-            g_assert_cmpint(nm_platform_link_cmp(cached, received), ==, 0);
-            g_assert(!memcmp(cached, received, sizeof(*cached)));
-            if (data->change_type == NM_PLATFORM_SIGNAL_REMOVED)
-                g_error("Deleted link still found in the local cache.");
-            return;
-        }
-    }
-
-    if (data->change_type != NM_PLATFORM_SIGNAL_REMOVED)
-        g_error("Added/changed link not found in the local cache.");
-}
-
-/*****************************************************************************/
-
-static const NMPlatformIP4Route *
-_ip4_route_get(NMPlatform *platform,
-               int         ifindex,
-               guint32     network,
-               int         plen,
-               guint32     metric,
-               guint8      tos,
-               guint *     out_c_exists)
-{
-    NMDedupMultiIter          iter;
-    NMPLookup                 lookup;
-    const NMPObject *         o = NULL;
-    guint                     c;
-    const NMPlatformIP4Route *r = NULL;
-
-    _init_platform(&platform, FALSE);
-
-    nmp_lookup_init_ip4_route_by_weak_id(&lookup, network, plen, metric, tos);
-
-    c = 0;
-    nmp_cache_iter_for_each (&iter, nm_platform_lookup(platform, &lookup), &o) {
-        if (NMP_OBJECT_CAST_IP4_ROUTE(o)->ifindex != ifindex && ifindex > 0)
-            continue;
-        if (!r)
-            r = NMP_OBJECT_CAST_IP4_ROUTE(o);
-        c++;
-    }
-
-    NM_SET_OUT(out_c_exists, c);
-    return r;
-}
-
-const NMPlatformIP4Route *
-_nmtstp_assert_ip4_route_exists(const char *file,
-                                guint       line,
-                                const char *func,
-                                NMPlatform *platform,
-                                int         c_exists,
-                                const char *ifname,
-                                guint32     network,
-                                int         plen,
-                                guint32     metric,
-                                guint8      tos)
-{
-    int                       ifindex;
-    guint                     c;
-    const NMPlatformIP4Route *r = NULL;
-
-    _init_platform(&platform, FALSE);
-
-    ifindex = -1;
-    if (ifname) {
-        ifindex = nm_platform_link_get_ifindex(platform, ifname);
-        g_assert(ifindex > 0);
-    }
-
-    r = _ip4_route_get(platform, ifindex, network, plen, metric, tos, &c);
-
-    if (c != c_exists && c_exists != -1) {
-        char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
-        g_error("[%s:%u] %s(): The ip4 route %s/%d metric %u tos %u shall exist %u times, but "
-                "platform has it %u times",
-                file,
-                line,
-                func,
-                _nm_utils_inet4_ntop(network, sbuf),
-                plen,
-                metric,
-                tos,
-                c_exists,
-                c);
-    }
-
-    return r;
-}
-
-const NMPlatformIP4Route *
-nmtstp_ip4_route_get(NMPlatform *platform,
-                     int         ifindex,
-                     guint32     network,
-                     int         plen,
-                     guint32     metric,
-                     guint8      tos)
-{
-    return _ip4_route_get(platform, ifindex, network, plen, metric, tos, NULL);
-}
-
-/*****************************************************************************/
-
-static const NMPlatformIP6Route *
-_ip6_route_get(NMPlatform *           platform,
-               int                    ifindex,
-               const struct in6_addr *network,
-               guint                  plen,
-               guint32                metric,
-               const struct in6_addr *src,
-               guint8                 src_plen,
-               guint *                out_c_exists)
-{
-    NMDedupMultiIter          iter;
-    NMPLookup                 lookup;
-    const NMPObject *         o = NULL;
-    guint                     c;
-    const NMPlatformIP6Route *r = NULL;
-
-    _init_platform(&platform, FALSE);
-
-    nmp_lookup_init_ip6_route_by_weak_id(&lookup, network, plen, metric, src, src_plen);
-
-    c = 0;
-    nmp_cache_iter_for_each (&iter, nm_platform_lookup(platform, &lookup), &o) {
-        if (NMP_OBJECT_CAST_IP6_ROUTE(o)->ifindex != ifindex && ifindex > 0)
-            continue;
-        if (!r)
-            r = NMP_OBJECT_CAST_IP6_ROUTE(o);
-        c++;
-    }
-
-    NM_SET_OUT(out_c_exists, c);
-    return r;
-}
-
-const NMPlatformIP6Route *
-_nmtstp_assert_ip6_route_exists(const char *           file,
-                                guint                  line,
-                                const char *           func,
-                                NMPlatform *           platform,
-                                int                    c_exists,
-                                const char *           ifname,
-                                const struct in6_addr *network,
-                                guint                  plen,
-                                guint32                metric,
-                                const struct in6_addr *src,
-                                guint8                 src_plen)
-{
-    int                       ifindex;
-    guint                     c;
-    const NMPlatformIP6Route *r = NULL;
-
-    _init_platform(&platform, FALSE);
-
-    ifindex = -1;
-    if (ifname) {
-        ifindex = nm_platform_link_get_ifindex(platform, ifname);
-        g_assert(ifindex > 0);
-    }
-
-    r = _ip6_route_get(platform, ifindex, network, plen, metric, src, src_plen, &c);
-
-    if (c != c_exists && c_exists != -1) {
-        char s_src[NM_UTILS_INET_ADDRSTRLEN];
-        char s_network[NM_UTILS_INET_ADDRSTRLEN];
-
-        g_error("[%s:%u] %s(): The ip6 route %s/%d metric %u src %s/%d shall exist %u times, but "
-                "platform has it %u times",
-                file,
-                line,
-                func,
-                _nm_utils_inet6_ntop(network, s_network),
-                plen,
-                metric,
-                _nm_utils_inet6_ntop(src, s_src),
-                src_plen,
-                c_exists,
-                c);
-    }
-
-    return r;
-}
-
-const NMPlatformIP6Route *
-nmtstp_ip6_route_get(NMPlatform *           platform,
-                     int                    ifindex,
-                     const struct in6_addr *network,
-                     guint                  plen,
-                     guint32                metric,
-                     const struct in6_addr *src,
-                     guint8                 src_plen)
-{
-    return _ip6_route_get(platform, ifindex, network, plen, metric, src, src_plen, NULL);
-}
-
-/*****************************************************************************/
-
-int
-nmtstp_run_command(const char *format, ...)
-{
-    int           result;
-    gs_free char *command = NULL;
-    va_list       ap;
-
-    va_start(ap, format);
-    command = g_strdup_vprintf(format, ap);
-    va_end(ap);
-
-    _LOGD("Running command: %s", command);
-    result = system(command);
-    _LOGD("Command finished: result=%d", result);
-
-    return result;
-}
-
-/*****************************************************************************/
-
-typedef struct {
-    GMainLoop *loop;
-    guint      signal_counts;
-    guint      id;
-} WaitForSignalData;
-
-static void
-_wait_for_signal_cb(NMPlatform *    platform,
-                    int             obj_type_i,
-                    int             ifindex,
-                    NMPlatformLink *plink,
-                    int             change_type_i,
-                    gpointer        user_data)
-{
-    WaitForSignalData *data = user_data;
-
-    data->signal_counts++;
-    nm_clear_g_source(&data->id);
-    g_main_loop_quit(data->loop);
-}
-
-static gboolean
-_wait_for_signal_timeout(gpointer user_data)
-{
-    WaitForSignalData *data = user_data;
-
-    g_assert(data->id);
-    data->id = 0;
-    g_main_loop_quit(data->loop);
-    return G_SOURCE_REMOVE;
-}
-
-guint
-nmtstp_wait_for_signal(NMPlatform *platform, gint64 timeout_msec)
-{
-    WaitForSignalData data = {0};
-    gulong            id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route;
-    gulong            id_qdisc, id_tfilter;
-
-    _init_platform(&platform, FALSE);
-
-    data.loop = g_main_loop_new(NULL, FALSE);
-
-    id_link        = g_signal_connect(platform,
-                               NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                               G_CALLBACK(_wait_for_signal_cb),
-                               &data);
-    id_ip4_address = g_signal_connect(platform,
-                                      NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
-                                      G_CALLBACK(_wait_for_signal_cb),
-                                      &data);
-    id_ip6_address = g_signal_connect(platform,
-                                      NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
-                                      G_CALLBACK(_wait_for_signal_cb),
-                                      &data);
-    id_ip4_route   = g_signal_connect(platform,
-                                    NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                    G_CALLBACK(_wait_for_signal_cb),
-                                    &data);
-    id_ip6_route   = g_signal_connect(platform,
-                                    NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
-                                    G_CALLBACK(_wait_for_signal_cb),
-                                    &data);
-    id_qdisc       = g_signal_connect(platform,
-                                NM_PLATFORM_SIGNAL_QDISC_CHANGED,
-                                G_CALLBACK(_wait_for_signal_cb),
-                                &data);
-    id_tfilter     = g_signal_connect(platform,
-                                  NM_PLATFORM_SIGNAL_TFILTER_CHANGED,
-                                  G_CALLBACK(_wait_for_signal_cb),
-                                  &data);
-
-    /* if timeout_msec is negative, it means the wait-time already expired.
-     * Maybe, we should do nothing and return right away, without even
-     * processing events from platform. However, that inconsistency (of not
-     * processing events from mainloop) is inconvenient.
-     *
-     * It's better that on the return of nmtstp_wait_for_signal(), we always
-     * have no events pending. So, a negative timeout is treated the same as
-     * a zero timeout: we check whether there are any events pending in platform,
-     * and quite the mainloop immediately afterwards. But we always check. */
-
-    data.id = g_timeout_add(CLAMP(timeout_msec, 0, G_MAXUINT32), _wait_for_signal_timeout, &data);
-
-    g_main_loop_run(data.loop);
-
-    g_assert(!data.id);
-    g_assert(nm_clear_g_signal_handler(platform, &id_link));
-    g_assert(nm_clear_g_signal_handler(platform, &id_ip4_address));
-    g_assert(nm_clear_g_signal_handler(platform, &id_ip6_address));
-    g_assert(nm_clear_g_signal_handler(platform, &id_ip4_route));
-    g_assert(nm_clear_g_signal_handler(platform, &id_ip6_route));
-    g_assert(nm_clear_g_signal_handler(platform, &id_tfilter));
-    g_assert(nm_clear_g_signal_handler(platform, &id_qdisc));
-
-    nm_clear_pointer(&data.loop, g_main_loop_unref);
-
-    /* return the number of signals, or 0 if timeout was reached .*/
-    return data.signal_counts;
-}
-
-guint
-nmtstp_wait_for_signal_until(NMPlatform *platform, gint64 until_ms)
-{
-    gint64 now;
-    guint  signal_counts;
-
-    while (TRUE) {
-        now = nm_utils_get_monotonic_timestamp_msec();
-
-        if (until_ms < now)
-            return 0;
-
-        signal_counts = nmtstp_wait_for_signal(platform, until_ms - now);
-        if (signal_counts)
-            return signal_counts;
-    }
-}
-
-const NMPlatformLink *
-nmtstp_wait_for_link(NMPlatform *platform,
-                     const char *ifname,
-                     NMLinkType  expected_link_type,
-                     gint64      timeout_msec)
-{
-    return nmtstp_wait_for_link_until(
-        platform,
-        ifname,
-        expected_link_type,
-        timeout_msec ? nm_utils_get_monotonic_timestamp_msec() + timeout_msec : 0);
-}
-
-const NMPlatformLink *
-nmtstp_wait_for_link_until(NMPlatform *platform,
-                           const char *ifname,
-                           NMLinkType  expected_link_type,
-                           gint64      until_ms)
-{
-    const NMPlatformLink *plink;
-    gint64                now;
-    gboolean              waited_once = FALSE;
-
-    _init_platform(&platform, FALSE);
-
-    while (TRUE) {
-        now = nm_utils_get_monotonic_timestamp_msec();
-
-        plink = nm_platform_link_get_by_ifname(platform, ifname);
-        if (plink && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type))
-            return plink;
-
-        if (until_ms == 0) {
-            /* don't wait, don't even poll the socket. */
-            return NULL;
-        }
-
-        if (waited_once && until_ms < now) {
-            /* timeout reached (+ we already waited for a signal at least once). */
-            return NULL;
-        }
-
-        waited_once = TRUE;
-        /* regardless of whether timeout is already reached, we poll the netlink
-         * socket a bit. */
-        nmtstp_wait_for_signal(platform, until_ms - now);
-    }
-}
-
-/*****************************************************************************/
-
-int
-nmtstp_run_command_check_external_global(void)
-{
-    if (!nmtstp_is_root_test())
-        return FALSE;
-    switch (nmtst_get_rand_uint32() % 3) {
-    case 0:
-        return -1;
-    case 1:
-        return FALSE;
-    default:
-        return TRUE;
-    }
-}
-
-gboolean
-nmtstp_run_command_check_external(int external_command)
-{
-    if (external_command != -1) {
-        g_assert(NM_IN_SET(external_command, FALSE, TRUE));
-        g_assert(!external_command || nmtstp_is_root_test());
-        return !!external_command;
-    }
-    if (!nmtstp_is_root_test())
-        return FALSE;
-    return (nmtst_get_rand_uint32() % 2) == 0;
-}
-
-/*****************************************************************************/
-
-#define CHECK_LIFETIME_MAX_DIFF 2
-
-gboolean
-nmtstp_ip_address_check_lifetime(const NMPlatformIPAddress *addr,
-                                 gint64                     now,
-                                 guint32                    expected_lifetime,
-                                 guint32                    expected_preferred)
-{
-    gint64 offset;
-    int    i;
-
-    g_assert(addr);
-
-    if (now == -1)
-        now = nm_utils_get_monotonic_timestamp_sec();
-    g_assert(now > 0);
-
-    g_assert(expected_preferred <= expected_lifetime);
-
-    if (expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT
-        && expected_preferred == NM_PLATFORM_LIFETIME_PERMANENT) {
-        return addr->timestamp == 0 && addr->lifetime == NM_PLATFORM_LIFETIME_PERMANENT
-               && addr->preferred == NM_PLATFORM_LIFETIME_PERMANENT;
-    }
-
-    if (addr->timestamp == 0)
-        return FALSE;
-
-    offset = (gint64) now - addr->timestamp;
-
-    for (i = 0; i < 2; i++) {
-        guint32 lft = i ? expected_lifetime : expected_preferred;
-        guint32 adr = i ? addr->lifetime : addr->preferred;
-
-        if (lft == NM_PLATFORM_LIFETIME_PERMANENT) {
-            if (adr != NM_PLATFORM_LIFETIME_PERMANENT)
-                return FALSE;
-        } else {
-            if (((gint64) adr) - offset <= ((gint64) lft) - CHECK_LIFETIME_MAX_DIFF
-                || ((gint64) adr) - offset >= ((gint64) lft) + CHECK_LIFETIME_MAX_DIFF)
-                return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-void
-nmtstp_ip_address_assert_lifetime(const NMPlatformIPAddress *addr,
-                                  gint64                     now,
-                                  guint32                    expected_lifetime,
-                                  guint32                    expected_preferred)
-{
-    gint64 n = now;
-    gint64 offset;
-    int    i;
-
-    g_assert(addr);
-
-    if (now == -1)
-        now = nm_utils_get_monotonic_timestamp_sec();
-    g_assert(now > 0);
-
-    g_assert(expected_preferred <= expected_lifetime);
-
-    if (expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT
-        && expected_preferred == NM_PLATFORM_LIFETIME_PERMANENT) {
-        g_assert_cmpint(addr->timestamp, ==, 0);
-        g_assert_cmpint(addr->lifetime, ==, NM_PLATFORM_LIFETIME_PERMANENT);
-        g_assert_cmpint(addr->preferred, ==, NM_PLATFORM_LIFETIME_PERMANENT);
-        return;
-    }
-
-    g_assert_cmpint(addr->timestamp, >, 0);
-    g_assert_cmpint(addr->timestamp, <=, now);
-
-    offset = (gint64) now - addr->timestamp;
-    g_assert_cmpint(offset, >=, 0);
-
-    for (i = 0; i < 2; i++) {
-        guint32 lft = i ? expected_lifetime : expected_preferred;
-        guint32 adr = i ? addr->lifetime : addr->preferred;
-
-        if (lft == NM_PLATFORM_LIFETIME_PERMANENT)
-            g_assert_cmpint(adr, ==, NM_PLATFORM_LIFETIME_PERMANENT);
-        else {
-            g_assert_cmpint(adr - offset, <=, lft + CHECK_LIFETIME_MAX_DIFF);
-            g_assert_cmpint(adr - offset, >=, lft - CHECK_LIFETIME_MAX_DIFF);
-        }
-    }
-
-    g_assert(nmtstp_ip_address_check_lifetime(addr, n, expected_lifetime, expected_preferred));
-}
-
-/*****************************************************************************/
-
-static void
-_ip_address_add(NMPlatform *    platform,
-                gboolean        external_command,
-                gboolean        is_v4,
-                int             ifindex,
-                const NMIPAddr *address,
-                int             plen,
-                const NMIPAddr *peer_address,
-                guint32         lifetime,
-                guint32         preferred,
-                guint32         flags,
-                const char *    label)
-{
-    gint64 end_time;
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        const char *  ifname;
-        gs_free char *s_valid     = NULL;
-        gs_free char *s_preferred = NULL;
-        gs_free char *s_label     = NULL;
-        char          b1[NM_UTILS_INET_ADDRSTRLEN];
-        char          b2[NM_UTILS_INET_ADDRSTRLEN];
-
-        ifname = nm_platform_link_get_name(platform, ifindex);
-        g_assert(ifname);
-
-        if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT)
-            s_valid = g_strdup_printf(" valid_lft %d", lifetime);
-        if (preferred != NM_PLATFORM_LIFETIME_PERMANENT)
-            s_preferred = g_strdup_printf(" preferred_lft %d", preferred);
-        if (label)
-            s_label = g_strdup_printf("%s:%s", ifname, label);
-
-        if (is_v4) {
-            char s_peer[NM_UTILS_INET_ADDRSTRLEN + 50];
-
-            g_assert(flags == 0);
-
-            if (peer_address->addr4 != address->addr4 || nmtst_get_rand_uint32() % 2) {
-                /* If the peer is the same as the local address, we can omit it. The result should be identical */
-                nm_sprintf_buf(s_peer, " peer %s", _nm_utils_inet4_ntop(peer_address->addr4, b2));
-            } else
-                s_peer[0] = '\0';
-
-            nmtstp_run_command_check("ip address change %s%s/%d dev %s%s%s%s",
-                                     _nm_utils_inet4_ntop(address->addr4, b1),
-                                     s_peer,
-                                     plen,
-                                     ifname,
-                                     s_valid ?: "",
-                                     s_preferred ?: "",
-                                     s_label ?: "");
-        } else {
-            g_assert(label == NULL);
-
-            /* flags not implemented (yet) */
-            g_assert(flags == 0);
-            nmtstp_run_command_check("ip address change %s%s%s/%d dev %s%s%s%s",
-                                     _nm_utils_inet6_ntop(&address->addr6, b1),
-                                     !IN6_IS_ADDR_UNSPECIFIED(&peer_address->addr6) ? " peer " : "",
-                                     !IN6_IS_ADDR_UNSPECIFIED(&peer_address->addr6)
-                                         ? _nm_utils_inet6_ntop(&peer_address->addr6, b2)
-                                         : "",
-                                     plen,
-                                     ifname,
-                                     s_valid ?: "",
-                                     s_preferred ?: "",
-                                     s_label ?: "");
-        }
-    } else {
-        gboolean success;
-
-        if (is_v4) {
-            success = nm_platform_ip4_address_add(platform,
-                                                  ifindex,
-                                                  address->addr4,
-                                                  plen,
-                                                  peer_address->addr4,
-                                                  0u,
-                                                  lifetime,
-                                                  preferred,
-                                                  flags,
-                                                  label);
-        } else {
-            g_assert(label == NULL);
-            success = nm_platform_ip6_address_add(platform,
-                                                  ifindex,
-                                                  address->addr6,
-                                                  plen,
-                                                  peer_address->addr6,
-                                                  lifetime,
-                                                  preferred,
-                                                  flags);
-        }
-        g_assert(success);
-    }
-
-    /* Let's wait until we see the address. */
-    end_time = nm_utils_get_monotonic_timestamp_msec() + 500;
-    do {
-        if (external_command)
-            nm_platform_process_events(platform);
-
-        /* let's wait until we see the address as we added it. */
-        if (is_v4) {
-            const NMPlatformIP4Address *a;
-
-            g_assert(flags == 0);
-            a = nm_platform_ip4_address_get(platform,
-                                            ifindex,
-                                            address->addr4,
-                                            plen,
-                                            peer_address->addr4);
-            if (a && a->peer_address == peer_address->addr4
-                && nmtstp_ip_address_check_lifetime((NMPlatformIPAddress *) a,
-                                                    -1,
-                                                    lifetime,
-                                                    preferred)
-                && strcmp(a->label, label ?: "") == 0)
-                break;
-        } else {
-            const NMPlatformIP6Address *a;
-
-            g_assert(label == NULL);
-            g_assert(flags == 0);
-
-            a = nm_platform_ip6_address_get(platform, ifindex, &address->addr6);
-            if (a
-                && !memcmp(nm_platform_ip6_address_get_peer(a),
-                           (IN6_IS_ADDR_UNSPECIFIED(&peer_address->addr6)
-                            || IN6_ARE_ADDR_EQUAL(&address->addr6, &peer_address->addr6))
-                               ? &address->addr6
-                               : &peer_address->addr6,
-                           sizeof(struct in6_addr))
-                && nmtstp_ip_address_check_lifetime((NMPlatformIPAddress *) a,
-                                                    -1,
-                                                    lifetime,
-                                                    preferred))
-                break;
-        }
-
-        /* for internal command, we expect not to reach this line.*/
-        g_assert(external_command);
-
-        nmtstp_assert_wait_for_signal_until(platform, end_time);
-    } while (TRUE);
-}
-
-void
-nmtstp_ip4_address_add(NMPlatform *platform,
-                       gboolean    external_command,
-                       int         ifindex,
-                       in_addr_t   address,
-                       int         plen,
-                       in_addr_t   peer_address,
-                       guint32     lifetime,
-                       guint32     preferred,
-                       guint32     flags,
-                       const char *label)
-{
-    _ip_address_add(platform,
-                    external_command,
-                    TRUE,
-                    ifindex,
-                    (NMIPAddr *) &address,
-                    plen,
-                    (NMIPAddr *) &peer_address,
-                    lifetime,
-                    preferred,
-                    flags,
-                    label);
-}
-
-void
-nmtstp_ip6_address_add(NMPlatform *    platform,
-                       gboolean        external_command,
-                       int             ifindex,
-                       struct in6_addr address,
-                       int             plen,
-                       struct in6_addr peer_address,
-                       guint32         lifetime,
-                       guint32         preferred,
-                       guint32         flags)
-{
-    _ip_address_add(platform,
-                    external_command,
-                    FALSE,
-                    ifindex,
-                    (NMIPAddr *) &address,
-                    plen,
-                    (NMIPAddr *) &peer_address,
-                    lifetime,
-                    preferred,
-                    flags,
-                    NULL);
-}
-
-void
-nmtstp_ip4_route_add(NMPlatform *     platform,
-                     int              ifindex,
-                     NMIPConfigSource source,
-                     in_addr_t        network,
-                     guint8           plen,
-                     in_addr_t        gateway,
-                     in_addr_t        pref_src,
-                     guint32          metric,
-                     guint32          mss)
-{
-    NMPlatformIP4Route route = {};
-
-    route.ifindex   = ifindex;
-    route.rt_source = source;
-    route.network   = network;
-    route.plen      = plen;
-    route.gateway   = gateway;
-    route.pref_src  = pref_src;
-    route.metric    = metric;
-    route.mss       = mss;
-
-    g_assert(
-        NMTST_NM_ERR_SUCCESS(nm_platform_ip4_route_add(platform, NMP_NLM_FLAG_REPLACE, &route)));
-}
-
-void
-nmtstp_ip6_route_add(NMPlatform *     platform,
-                     int              ifindex,
-                     NMIPConfigSource source,
-                     struct in6_addr  network,
-                     guint8           plen,
-                     struct in6_addr  gateway,
-                     struct in6_addr  pref_src,
-                     guint32          metric,
-                     guint32          mss)
-{
-    NMPlatformIP6Route route = {};
-
-    route.ifindex   = ifindex;
-    route.rt_source = source;
-    route.network   = network;
-    route.plen      = plen;
-    route.gateway   = gateway;
-    route.pref_src  = pref_src;
-    route.metric    = metric;
-    route.mss       = mss;
-
-    g_assert(
-        NMTST_NM_ERR_SUCCESS(nm_platform_ip6_route_add(platform, NMP_NLM_FLAG_REPLACE, &route)));
-}
-
-/*****************************************************************************/
-
-static void
-_ip_address_del(NMPlatform *    platform,
-                gboolean        external_command,
-                gboolean        is_v4,
-                int             ifindex,
-                const NMIPAddr *address,
-                int             plen,
-                const NMIPAddr *peer_address)
-{
-    gint64 end_time;
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        const char *ifname;
-        char        b1[NM_UTILS_INET_ADDRSTRLEN];
-        char        b2[NM_UTILS_INET_ADDRSTRLEN];
-        int         success;
-        gboolean    had_address;
-
-        ifname = nm_platform_link_get_name(platform, ifindex);
-        g_assert(ifname);
-
-        /* let's wait until we see the address as we added it. */
-        if (is_v4)
-            had_address = !!nm_platform_ip4_address_get(platform,
-                                                        ifindex,
-                                                        address->addr4,
-                                                        plen,
-                                                        peer_address->addr4);
-        else
-            had_address = !!nm_platform_ip6_address_get(platform, ifindex, &address->addr6);
-
-        if (is_v4) {
-            success = nmtstp_run_command("ip address delete %s%s%s/%d dev %s",
-                                         _nm_utils_inet4_ntop(address->addr4, b1),
-                                         peer_address->addr4 != address->addr4 ? " peer " : "",
-                                         peer_address->addr4 != address->addr4
-                                             ? _nm_utils_inet4_ntop(peer_address->addr4, b2)
-                                             : "",
-                                         plen,
-                                         ifname);
-        } else {
-            g_assert(!peer_address);
-            success = nmtstp_run_command("ip address delete %s/%d dev %s",
-                                         _nm_utils_inet6_ntop(&address->addr6, b1),
-                                         plen,
-                                         ifname);
-        }
-        g_assert(success == 0 || !had_address);
-    } else {
-        gboolean success;
-
-        if (is_v4) {
-            success = nm_platform_ip4_address_delete(platform,
-                                                     ifindex,
-                                                     address->addr4,
-                                                     plen,
-                                                     peer_address->addr4);
-        } else {
-            g_assert(!peer_address);
-            success = nm_platform_ip6_address_delete(platform, ifindex, address->addr6, plen);
-        }
-        g_assert(success);
-    }
-
-    /* Let's wait until we get the result */
-    end_time = nm_utils_get_monotonic_timestamp_msec() + 250;
-    do {
-        if (external_command)
-            nm_platform_process_events(platform);
-
-        /* let's wait until we see the address as we added it. */
-        if (is_v4) {
-            const NMPlatformIP4Address *a;
-
-            a = nm_platform_ip4_address_get(platform,
-                                            ifindex,
-                                            address->addr4,
-                                            plen,
-                                            peer_address->addr4);
-            if (!a)
-                break;
-        } else {
-            const NMPlatformIP6Address *a;
-
-            a = nm_platform_ip6_address_get(platform, ifindex, &address->addr6);
-            if (!a)
-                break;
-        }
-
-        /* for internal command, we expect not to reach this line.*/
-        g_assert(external_command);
-
-        nmtstp_assert_wait_for_signal_until(platform, end_time);
-    } while (TRUE);
-}
-
-void
-nmtstp_ip4_address_del(NMPlatform *platform,
-                       gboolean    external_command,
-                       int         ifindex,
-                       in_addr_t   address,
-                       int         plen,
-                       in_addr_t   peer_address)
-{
-    _ip_address_del(platform,
-                    external_command,
-                    TRUE,
-                    ifindex,
-                    (NMIPAddr *) &address,
-                    plen,
-                    (NMIPAddr *) &peer_address);
-}
-
-void
-nmtstp_ip6_address_del(NMPlatform *    platform,
-                       gboolean        external_command,
-                       int             ifindex,
-                       struct in6_addr address,
-                       int             plen)
-{
-    _ip_address_del(platform, external_command, FALSE, ifindex, (NMIPAddr *) &address, plen, NULL);
-}
-
-/*****************************************************************************/
-
-#define _assert_pllink(platform, success, pllink, name, type)                               \
-    G_STMT_START                                                                            \
-    {                                                                                       \
-        const NMPlatformLink *_pllink = (pllink);                                           \
-                                                                                            \
-        if ((success)) {                                                                    \
-            g_assert(_pllink);                                                              \
-            g_assert(_pllink                                                                \
-                     == nmtstp_link_get_typed(platform, _pllink->ifindex, (name), (type))); \
-        } else {                                                                            \
-            g_assert(!_pllink);                                                             \
-            g_assert(!nmtstp_link_get(platform, 0, (name)));                                \
-        }                                                                                   \
-    }                                                                                       \
-    G_STMT_END
-
-const NMPlatformLink *
-nmtstp_link_bridge_add(NMPlatform *               platform,
-                       gboolean                   external_command,
-                       const char *               name,
-                       const NMPlatformLnkBridge *lnk)
-{
-    const NMPlatformLink *     pllink = NULL;
-    const NMPlatformLnkBridge *ll     = NULL;
-    int                        r      = 0;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        char sbuf_gfw[100];
-        char sbuf_mhm[100];
-        char sbuf_mlmc[100];
-        char sbuf_mlmi[100];
-        char sbuf_mmi[100];
-        char sbuf_mqi[100];
-        char sbuf_mqii[100];
-        char sbuf_msqc[100];
-        char sbuf_msqi[100];
-        char sbuf_mqri[100];
-
-        r = nmtstp_run_command(
-            "ip link add %s type bridge "
-            "forward_delay %u "
-            "hello_time %u "
-            "max_age %u "
-            "ageing_time %u "
-            "stp_state %d "
-            "priority %u "
-            "vlan_protocol %u "
-            "vlan_stats_enabled %d "
-            "%s" /* group_fwd_mask */
-            "group_address " NM_ETHER_ADDR_FORMAT_STR " "
-            "mcast_snooping %d "
-            "mcast_router %u "
-            "mcast_query_use_ifaddr %d "
-            "mcast_querier %d "
-            "%s" /* mcast_hash_max */
-            "%s" /* mcast_last_member_count */
-            "%s" /* mcast_startup_query_count */
-            "%s" /* mcast_last_member_interval */
-            "%s" /* mcast_membership_interval */
-            "%s" /* mcast_querier_interval */
-            "%s" /* mcast_query_interval */
-            "%s" /* mcast_query_response_interval */
-            "%s" /* mcast_startup_query_interval */
-            "",
-            name,
-            lnk->forward_delay,
-            lnk->hello_time,
-            lnk->max_age,
-            lnk->ageing_time,
-            (int) lnk->stp_state,
-            lnk->priority,
-            lnk->vlan_protocol,
-            (int) lnk->vlan_stats_enabled,
-            lnk->group_fwd_mask != 0
-                ? nm_sprintf_buf(sbuf_gfw, "group_fwd_mask %#x ", lnk->group_fwd_mask)
-                : "",
-            NM_ETHER_ADDR_FORMAT_VAL(lnk->group_addr),
-            (int) lnk->mcast_snooping,
-            lnk->mcast_router,
-            (int) lnk->mcast_query_use_ifaddr,
-            (int) lnk->mcast_querier,
-            lnk->mcast_hash_max != NM_BRIDGE_MULTICAST_HASH_MAX_DEF
-                ? nm_sprintf_buf(sbuf_mhm, "mcast_hash_max %u ", lnk->mcast_hash_max)
-                : "",
-            lnk->mcast_last_member_count != NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF
-                ? nm_sprintf_buf(sbuf_mlmc,
-                                 "mcast_last_member_count %u ",
-                                 lnk->mcast_last_member_count)
-                : "",
-            lnk->mcast_startup_query_count != NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF
-                ? nm_sprintf_buf(sbuf_msqc,
-                                 "mcast_startup_query_count %u ",
-                                 lnk->mcast_startup_query_count)
-                : "",
-            lnk->mcast_last_member_interval != NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF
-                ? nm_sprintf_buf(sbuf_mlmi,
-                                 "mcast_last_member_interval %" G_GUINT64_FORMAT " ",
-                                 lnk->mcast_last_member_interval)
-                : "",
-            lnk->mcast_membership_interval != NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF
-                ? nm_sprintf_buf(sbuf_mmi,
-                                 "mcast_membership_interval %" G_GUINT64_FORMAT " ",
-                                 lnk->mcast_membership_interval)
-                : "",
-            lnk->mcast_querier_interval != NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF
-                ? nm_sprintf_buf(sbuf_mqi,
-                                 "mcast_querier_interval %" G_GUINT64_FORMAT " ",
-                                 lnk->mcast_querier_interval)
-                : "",
-            lnk->mcast_query_interval != NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF
-                ? nm_sprintf_buf(sbuf_mqii,
-                                 "mcast_query_interval %" G_GUINT64_FORMAT " ",
-                                 lnk->mcast_query_interval)
-                : "",
-            lnk->mcast_query_response_interval != NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF
-                ? nm_sprintf_buf(sbuf_mqri,
-                                 "mcast_query_response_interval %" G_GUINT64_FORMAT " ",
-                                 lnk->mcast_query_response_interval)
-                : "",
-            lnk->mcast_startup_query_interval != NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF
-                ? nm_sprintf_buf(sbuf_msqi,
-                                 "mcast_startup_query_interval %" G_GUINT64_FORMAT " ",
-                                 lnk->mcast_startup_query_interval)
-                : "");
-        if (r == 0)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_BRIDGE, 100);
-        else
-            _LOGI(
-                "Adding bridge device via iproute2 failed. Assume iproute2 is not up to the task.");
-    }
-
-    if (!pllink) {
-        r = nm_platform_link_bridge_add(platform, name, NULL, 0, 0, lnk, &pllink);
-    }
-
-    _assert_pllink(platform, r == 0, pllink, name, NM_LINK_TYPE_BRIDGE);
-
-    ll = NMP_OBJECT_CAST_LNK_BRIDGE(NMP_OBJECT_UP_CAST(pllink)->_link.netlink.lnk);
-
-    g_assert_cmpint(lnk->forward_delay, ==, ll->forward_delay);
-    g_assert_cmpint(lnk->hello_time, ==, ll->hello_time);
-    g_assert_cmpint(lnk->max_age, ==, ll->max_age);
-    g_assert_cmpint(lnk->ageing_time, ==, ll->ageing_time);
-    g_assert_cmpint(lnk->stp_state, ==, ll->stp_state);
-    g_assert_cmpint(lnk->priority, ==, ll->priority);
-    g_assert_cmpint(lnk->vlan_stats_enabled, ==, ll->vlan_stats_enabled);
-    g_assert_cmpint(lnk->group_fwd_mask, ==, ll->group_fwd_mask);
-    g_assert_cmpint(lnk->mcast_snooping, ==, ll->mcast_snooping);
-    g_assert_cmpint(lnk->mcast_router, ==, ll->mcast_router);
-    g_assert_cmpint(lnk->mcast_query_use_ifaddr, ==, ll->mcast_query_use_ifaddr);
-    g_assert_cmpint(lnk->mcast_querier, ==, ll->mcast_querier);
-    g_assert_cmpint(lnk->mcast_hash_max, ==, ll->mcast_hash_max);
-    g_assert_cmpint(lnk->mcast_last_member_count, ==, ll->mcast_last_member_count);
-    g_assert_cmpint(lnk->mcast_startup_query_count, ==, ll->mcast_startup_query_count);
-    g_assert_cmpint(lnk->mcast_last_member_interval, ==, ll->mcast_last_member_interval);
-    g_assert_cmpint(lnk->mcast_membership_interval, ==, ll->mcast_membership_interval);
-    g_assert_cmpint(lnk->mcast_querier_interval, ==, ll->mcast_querier_interval);
-    g_assert_cmpint(lnk->mcast_query_interval, ==, ll->mcast_query_interval);
-    g_assert_cmpint(lnk->mcast_query_response_interval, ==, ll->mcast_query_response_interval);
-    g_assert_cmpint(lnk->mcast_startup_query_interval, ==, ll->mcast_startup_query_interval);
-
-    return pllink;
-}
-const NMPlatformLink *
-nmtstp_link_veth_add(NMPlatform *platform,
-                     gboolean    external_command,
-                     const char *name,
-                     const char *peer)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        success = !nmtstp_run_command("ip link add dev %s type veth peer name %s", name, peer);
-        if (success) {
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VETH, 100);
-            nmtstp_assert_wait_for_link(platform, peer, NM_LINK_TYPE_VETH, 10);
-        }
-    } else
-        success = NMTST_NM_ERR_SUCCESS(nm_platform_link_veth_add(platform, name, peer, &pllink));
-
-    g_assert(success);
-    _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_VETH);
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_dummy_add(NMPlatform *platform, gboolean external_command, const char *name)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        success = !nmtstp_run_command("ip link add %s type dummy", name);
-        if (success)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_DUMMY, 100);
-    } else
-        success = NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(platform, name, &pllink));
-
-    g_assert(success);
-    _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_DUMMY);
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_gre_add(NMPlatform *            platform,
-                    gboolean                external_command,
-                    const char *            name,
-                    const NMPlatformLnkGre *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-    char                  b1[INET_ADDRSTRLEN];
-    char                  b2[INET_ADDRSTRLEN];
-    NMLinkType            link_type;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-    link_type        = lnk->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE;
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        gs_free char *dev = NULL;
-        char *        obj, *type;
-
-        if (lnk->parent_ifindex)
-            dev =
-                g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex));
-
-        obj  = lnk->is_tap ? "link" : "tunnel";
-        type = lnk->is_tap ? "type gretap" : "mode gre";
-
-        success = !nmtstp_run_command("ip %s add %s %s %s local %s remote %s ttl %u tos %02x %s",
-                                      obj,
-                                      name,
-                                      type,
-                                      dev ?: "",
-                                      _nm_utils_inet4_ntop(lnk->local, b1),
-                                      _nm_utils_inet4_ntop(lnk->remote, b2),
-                                      lnk->ttl,
-                                      lnk->tos,
-                                      lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
-        if (success)
-            pllink = nmtstp_assert_wait_for_link(platform, name, link_type, 100);
-    } else
-        success =
-            NMTST_NM_ERR_SUCCESS(nm_platform_link_gre_add(platform, name, NULL, 0, lnk, &pllink));
-
-    _assert_pllink(platform, success, pllink, name, link_type);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_ip6tnl_add(NMPlatform *               platform,
-                       gboolean                   external_command,
-                       const char *               name,
-                       const NMPlatformLnkIp6Tnl *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-    char                  b1[NM_UTILS_INET_ADDRSTRLEN];
-    char                  b2[NM_UTILS_INET_ADDRSTRLEN];
-    char                  encap[20];
-    char                  tclass[20];
-    gboolean              encap_ignore;
-    gboolean              tclass_inherit;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-    g_assert(!lnk->is_gre);
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        gs_free char *dev = NULL;
-        const char *  mode;
-
-        if (lnk->parent_ifindex)
-            dev =
-                g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex));
-
-        switch (lnk->proto) {
-        case IPPROTO_IPIP:
-            mode = "ipip6";
-            break;
-        case IPPROTO_IPV6:
-            mode = "ip6ip6";
-            break;
-        default:
-            g_assert_not_reached();
-        }
-
-        encap_ignore   = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_IGN_ENCAP_LIMIT);
-        tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS);
-
-        success = !nmtstp_run_command(
-            "ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %s encaplimit %s "
-            "flowlabel %x",
-            name,
-            mode,
-            dev,
-            _nm_utils_inet6_ntop(&lnk->local, b1),
-            _nm_utils_inet6_ntop(&lnk->remote, b2),
-            lnk->ttl,
-            tclass_inherit ? "inherit" : nm_sprintf_buf(tclass, "%02x", lnk->tclass),
-            encap_ignore ? "none" : nm_sprintf_buf(encap, "%u", lnk->encap_limit),
-            lnk->flow_label);
-        if (success)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_IP6TNL, 100);
-    } else
-        success = NMTST_NM_ERR_SUCCESS(nm_platform_link_ip6tnl_add(platform, name, lnk, &pllink));
-
-    _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_IP6TNL);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_ip6gre_add(NMPlatform *               platform,
-                       gboolean                   external_command,
-                       const char *               name,
-                       const NMPlatformLnkIp6Tnl *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-    char                  b1[NM_UTILS_INET_ADDRSTRLEN];
-    char                  b2[NM_UTILS_INET_ADDRSTRLEN];
-    char                  tclass[20];
-    gboolean              tclass_inherit;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-    g_assert(lnk->is_gre);
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        gs_free char *dev = NULL;
-
-        if (lnk->parent_ifindex)
-            dev =
-                g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex));
-
-        tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS);
-
-        success = !nmtstp_run_command(
-            "ip link add %s type %s %s local %s remote %s ttl %u tclass %s flowlabel %x",
-            name,
-            lnk->is_tap ? "ip6gretap" : "ip6gre",
-            dev,
-            _nm_utils_inet6_ntop(&lnk->local, b1),
-            _nm_utils_inet6_ntop(&lnk->remote, b2),
-            lnk->ttl,
-            tclass_inherit ? "inherit" : nm_sprintf_buf(tclass, "%02x", lnk->tclass),
-            lnk->flow_label);
-        if (success) {
-            pllink = nmtstp_assert_wait_for_link(platform,
-                                                 name,
-                                                 lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP
-                                                             : NM_LINK_TYPE_IP6GRE,
-                                                 100);
-        }
-    } else
-        success = NMTST_NM_ERR_SUCCESS(
-            nm_platform_link_ip6gre_add(platform, name, NULL, 0, lnk, &pllink));
-
-    _assert_pllink(platform,
-                   success,
-                   pllink,
-                   name,
-                   lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_ipip_add(NMPlatform *             platform,
-                     gboolean                 external_command,
-                     const char *             name,
-                     const NMPlatformLnkIpIp *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-    char                  b1[INET_ADDRSTRLEN];
-    char                  b2[INET_ADDRSTRLEN];
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        gs_free char *dev = NULL;
-
-        if (lnk->parent_ifindex)
-            dev =
-                g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex));
-
-        success = !nmtstp_run_command(
-            "ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s",
-            name,
-            dev,
-            _nm_utils_inet4_ntop(lnk->local, b1),
-            _nm_utils_inet4_ntop(lnk->remote, b2),
-            lnk->ttl,
-            lnk->tos,
-            lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
-        if (success)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_IPIP, 100);
-    } else
-        success = NMTST_NM_ERR_SUCCESS(nm_platform_link_ipip_add(platform, name, lnk, &pllink));
-
-    _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_IPIP);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_macvlan_add(NMPlatform *                platform,
-                        gboolean                    external_command,
-                        const char *                name,
-                        int                         parent,
-                        const NMPlatformLnkMacvlan *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-    NMLinkType            link_type;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    link_type = lnk->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN;
-
-    if (external_command) {
-        const char *dev;
-        char *      modes[] = {
-            [MACVLAN_MODE_BRIDGE]   = "bridge",
-            [MACVLAN_MODE_VEPA]     = "vepa",
-            [MACVLAN_MODE_PRIVATE]  = "private",
-            [MACVLAN_MODE_PASSTHRU] = "passthru",
-        };
-
-        dev = nm_platform_link_get_name(platform, parent);
-        g_assert(dev);
-        g_assert_cmpint(lnk->mode, <, G_N_ELEMENTS(modes));
-
-        success = !nmtstp_run_command("ip link add name %s link %s type %s mode %s %s",
-                                      name,
-                                      dev,
-                                      lnk->tap ? "macvtap" : "macvlan",
-                                      modes[lnk->mode],
-                                      lnk->no_promisc ? "nopromisc" : "");
-        if (success)
-            pllink = nmtstp_assert_wait_for_link(platform, name, link_type, 100);
-    } else
-        success = NMTST_NM_ERR_SUCCESS(
-            nm_platform_link_macvlan_add(platform, name, parent, lnk, &pllink));
-
-    _assert_pllink(platform, success, pllink, name, link_type);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_sit_add(NMPlatform *            platform,
-                    gboolean                external_command,
-                    const char *            name,
-                    const NMPlatformLnkSit *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    gboolean              success;
-    char                  b1[INET_ADDRSTRLEN];
-    char                  b2[INET_ADDRSTRLEN];
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        const char *dev = "";
-
-        if (lnk->parent_ifindex) {
-            const char *parent_name;
-
-            parent_name = nm_platform_link_get_name(platform, lnk->parent_ifindex);
-            g_assert(parent_name);
-            dev = nm_sprintf_bufa(100, " dev %s", parent_name);
-        }
-
-        success =
-            !nmtstp_run_command("ip tunnel add %s mode sit%s local %s remote %s ttl %u tos %02x %s",
-                                name,
-                                dev,
-                                _nm_utils_inet4_ntop(lnk->local, b1),
-                                _nm_utils_inet4_ntop(lnk->remote, b2),
-                                lnk->ttl,
-                                lnk->tos,
-                                lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
-        if (success)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_SIT, 100);
-    } else
-        success = NMTST_NM_ERR_SUCCESS(nm_platform_link_sit_add(platform, name, lnk, &pllink));
-
-    _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_SIT);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_tun_add(NMPlatform *            platform,
-                    gboolean                external_command,
-                    const char *            name,
-                    const NMPlatformLnkTun *lnk,
-                    int *                   out_fd)
-{
-    const NMPlatformLink *pllink = NULL;
-    int                   err;
-    int                   r;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-    g_assert(lnk);
-    g_assert(NM_IN_SET(lnk->type, IFF_TUN, IFF_TAP));
-    g_assert(!out_fd || *out_fd == -1);
-
-    if (!lnk->persist) {
-        /* ip tuntap does not support non-persistent devices.
-         *
-         * Add this device only via NMPlatform. */
-        if (external_command == -1)
-            external_command = FALSE;
-    }
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        g_assert(lnk->persist);
-
-        err = nmtstp_run_command(
-            "ip tuntap add"
-            " mode %s"
-            "%s" /* user */
-            "%s" /* group */
-            "%s" /* pi */
-            "%s" /* vnet_hdr */
-            "%s" /* multi_queue */
-            " name %s",
-            lnk->type == IFF_TUN ? "tun" : "tap",
-            lnk->owner_valid ? nm_sprintf_bufa(100, " user %u", (guint) lnk->owner) : "",
-            lnk->group_valid ? nm_sprintf_bufa(100, " group %u", (guint) lnk->group) : "",
-            lnk->pi ? " pi" : "",
-            lnk->vnet_hdr ? " vnet_hdr" : "",
-            lnk->multi_queue ? " multi_queue" : "",
-            name);
-        /* Older versions of iproute2 don't support adding  devices.
-         * On failure, fallback to using platform code. */
-        if (err == 0)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_TUN, 100);
-        else
-            g_error("failure to add tun/tap device via ip-route");
-    } else {
-        g_assert(lnk->persist || out_fd);
-        r = nm_platform_link_tun_add(platform, name, lnk, &pllink, out_fd);
-        g_assert_cmpint(r, ==, 0);
-    }
-
-    g_assert(pllink);
-    g_assert_cmpint(pllink->type, ==, NM_LINK_TYPE_TUN);
-    g_assert_cmpstr(pllink->name, ==, name);
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_vrf_add(NMPlatform *            platform,
-                    gboolean                external_command,
-                    const char *            name,
-                    const NMPlatformLnkVrf *lnk,
-                    gboolean *              out_not_supported)
-{
-    const NMPlatformLink *pllink = NULL;
-    int                   r      = 0;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    NM_SET_OUT(out_not_supported, FALSE);
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        r = nmtstp_run_command("ip link add %s type vrf table %u", name, lnk->table);
-
-        if (r == 0)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VRF, 100);
-        else
-            _LOGI("Adding vrf device via iproute2 failed. Assume iproute2 is not up to the task.");
-    }
-
-    if (!pllink) {
-        r = nm_platform_link_vrf_add(platform, name, lnk, &pllink);
-        if (r == -EOPNOTSUPP)
-            NM_SET_OUT(out_not_supported, TRUE);
-    }
-
-    _assert_pllink(platform, r == 0, pllink, name, NM_LINK_TYPE_VRF);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_vxlan_add(NMPlatform *              platform,
-                      gboolean                  external_command,
-                      const char *              name,
-                      const NMPlatformLnkVxlan *lnk)
-{
-    const NMPlatformLink *pllink = NULL;
-    int                   err;
-    int                   r;
-
-    g_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        gs_free char *dev = NULL;
-        char          local[NM_UTILS_INET_ADDRSTRLEN];
-        char          group[NM_UTILS_INET_ADDRSTRLEN];
-
-        if (lnk->parent_ifindex)
-            dev =
-                g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex));
-
-        if (lnk->local)
-            _nm_utils_inet4_ntop(lnk->local, local);
-        else if (memcmp(&lnk->local6, &in6addr_any, sizeof(in6addr_any)))
-            _nm_utils_inet6_ntop(&lnk->local6, local);
-        else
-            local[0] = '\0';
-
-        if (lnk->group)
-            _nm_utils_inet4_ntop(lnk->group, group);
-        else if (memcmp(&lnk->group6, &in6addr_any, sizeof(in6addr_any)))
-            _nm_utils_inet6_ntop(&lnk->group6, group);
-        else
-            group[0] = '\0';
-
-        err = nmtstp_run_command("ip link add %s type vxlan id %u %s local %s group %s ttl %u tos "
-                                 "%02x dstport %u srcport %u %u ageing %u",
-                                 name,
-                                 lnk->id,
-                                 dev ?: "",
-                                 local,
-                                 group,
-                                 lnk->ttl,
-                                 lnk->tos,
-                                 lnk->dst_port,
-                                 lnk->src_port_min,
-                                 lnk->src_port_max,
-                                 lnk->ageing);
-        /* Older versions of iproute2 don't support adding vxlan devices.
-         * On failure, fallback to using platform code. */
-        if (err == 0)
-            pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VXLAN, 100);
-        else
-            _LOGI(
-                "Adding vxlan device via iproute2 failed. Assume iproute2 is not up to the task.");
-    }
-    if (!pllink) {
-        r = nm_platform_link_vxlan_add(platform, name, lnk, &pllink);
-        g_assert(NMTST_NM_ERR_SUCCESS(r));
-        g_assert(pllink);
-    }
-
-    g_assert_cmpint(pllink->type, ==, NM_LINK_TYPE_VXLAN);
-    g_assert_cmpstr(pllink->name, ==, name);
-    return pllink;
-}
-
-/*****************************************************************************/
-
-const NMPlatformLink *
-nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type)
-{
-    const NMPlatformLink *pllink = NULL;
-
-    _init_platform(&platform, FALSE);
-
-    if (ifindex > 0) {
-        pllink = nm_platform_link_get(platform, ifindex);
-
-        if (pllink) {
-            g_assert_cmpint(pllink->ifindex, ==, ifindex);
-            if (name)
-                g_assert_cmpstr(name, ==, pllink->name);
-        } else {
-            if (name)
-                g_assert(!nm_platform_link_get_by_ifname(platform, name));
-        }
-    } else {
-        g_assert(name);
-
-        pllink = nm_platform_link_get_by_ifname(platform, name);
-
-        if (pllink)
-            g_assert_cmpstr(name, ==, pllink->name);
-    }
-
-    g_assert(!name || nm_utils_ifname_valid_kernel(name, NULL));
-
-    if (pllink && link_type != NM_LINK_TYPE_NONE)
-        g_assert_cmpint(pllink->type, ==, link_type);
-
-    return pllink;
-}
-
-const NMPlatformLink *
-nmtstp_link_get(NMPlatform *platform, int ifindex, const char *name)
-{
-    return nmtstp_link_get_typed(platform, ifindex, name, NM_LINK_TYPE_NONE);
-}
-
-/*****************************************************************************/
-
-void
-nmtstp_link_delete(NMPlatform *platform,
-                   gboolean    external_command,
-                   int         ifindex,
-                   const char *name,
-                   gboolean    require_exist)
-{
-    gint64                end_time;
-    const NMPlatformLink *pllink;
-    gboolean              success;
-    gs_free char *        name_copy = NULL;
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    pllink = nmtstp_link_get(platform, ifindex, name);
-
-    if (!pllink) {
-        g_assert(!require_exist);
-        return;
-    }
-
-    name = name_copy = g_strdup(pllink->name);
-    ifindex          = pllink->ifindex;
-
-    if (external_command) {
-        nmtstp_run_command_check("ip link delete %s", name);
-    } else {
-        success = nm_platform_link_delete(platform, ifindex);
-        g_assert(success);
-    }
-
-    /* Let's wait until we get the result */
-    end_time = nm_utils_get_monotonic_timestamp_msec() + 250;
-    do {
-        if (external_command)
-            nm_platform_process_events(platform);
-
-        if (!nm_platform_link_get(platform, ifindex)) {
-            g_assert(!nm_platform_link_get_by_ifname(platform, name));
-            break;
-        }
-
-        /* for internal command, we expect not to reach this line.*/
-        g_assert(external_command);
-
-        nmtstp_assert_wait_for_signal_until(platform, end_time);
-    } while (TRUE);
-}
-
-/*****************************************************************************/
-
-void
-nmtstp_link_set_updown(NMPlatform *platform, gboolean external_command, int ifindex, gboolean up)
-{
-    const NMPlatformLink *plink;
-    gint64                end_time;
-
-    external_command = nmtstp_run_command_check_external(external_command);
-
-    _init_platform(&platform, external_command);
-
-    if (external_command) {
-        const char *ifname;
-
-        ifname = nm_platform_link_get_name(platform, ifindex);
-        g_assert(ifname);
-
-        nmtstp_run_command_check("ip link set %s %s", ifname, up ? "up" : "down");
-    } else {
-        if (up)
-            g_assert(nm_platform_link_set_up(platform, ifindex, NULL));
-        else
-            g_assert(nm_platform_link_set_down(platform, ifindex));
-    }
-
-    /* Let's wait until we get the result */
-    end_time = nm_utils_get_monotonic_timestamp_msec() + 250;
-    do {
-        if (external_command)
-            nm_platform_process_events(platform);
-
-        /* let's wait until we see the address as we added it. */
-        plink = nm_platform_link_get(platform, ifindex);
-        g_assert(plink);
-
-        if (NM_FLAGS_HAS(plink->n_ifi_flags, IFF_UP) == !!up)
-            break;
-
-        /* for internal command, we expect not to reach this line.*/
-        g_assert(external_command);
-
-        nmtstp_assert_wait_for_signal_until(platform, end_time);
-    } while (TRUE);
-}
-
-/*****************************************************************************/
-
-gboolean
-nmtstp_kernel_support_get(NMPlatformKernelSupportType type)
-{
-    const NMPlatformLink *pllink;
-    NMTernary             v;
-
-    v = nm_platform_kernel_support_get_full(type, FALSE);
-    if (v != NM_TERNARY_DEFAULT)
-        return v != NM_TERNARY_FALSE;
-
-    switch (type) {
-    case NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED:
-        pllink = nmtstp_link_bridge_add(NULL, -1, "br-test-11", &nm_platform_lnk_bridge_default);
-        nmtstp_link_delete(NULL, -1, pllink->ifindex, NULL, TRUE);
-        v = nm_platform_kernel_support_get_full(type, FALSE);
-        g_assert(v != NM_TERNARY_DEFAULT);
-        return v;
-    default:
-        g_assert_not_reached();
-    }
-}
-
-/*****************************************************************************/
-
-struct _NMTstpNamespaceHandle {
-    pid_t pid;
-    int   pipe_fd;
-};
-
-NMTstpNamespaceHandle *
-nmtstp_namespace_create(int unshare_flags, GError **error)
-{
-    NMTstpNamespaceHandle *ns_handle;
-    int                    e;
-    int                    errsv;
-    pid_t                  pid, pid2;
-    int                    pipefd_c2p[2];
-    int                    pipefd_p2c[2];
-    ssize_t                r;
-
-    e = pipe2(pipefd_c2p, O_CLOEXEC);
-    if (e != 0) {
-        errsv = errno;
-        g_set_error(error,
-                    NM_UTILS_ERROR,
-                    NM_UTILS_ERROR_UNKNOWN,
-                    "pipe() failed with %d (%s)",
-                    errsv,
-                    nm_strerror_native(errsv));
-        return FALSE;
-    }
-
-    e = pipe2(pipefd_p2c, O_CLOEXEC);
-    if (e != 0) {
-        errsv = errno;
-        g_set_error(error,
-                    NM_UTILS_ERROR,
-                    NM_UTILS_ERROR_UNKNOWN,
-                    "pipe() failed with %d (%s)",
-                    errsv,
-                    nm_strerror_native(errsv));
-        nm_close(pipefd_c2p[0]);
-        nm_close(pipefd_c2p[1]);
-        return FALSE;
-    }
-
-    pid = fork();
-    if (pid < 0) {
-        errsv = errno;
-        g_set_error(error,
-                    NM_UTILS_ERROR,
-                    NM_UTILS_ERROR_UNKNOWN,
-                    "fork() failed with %d (%s)",
-                    errsv,
-                    nm_strerror_native(errsv));
-        nm_close(pipefd_c2p[0]);
-        nm_close(pipefd_c2p[1]);
-        nm_close(pipefd_p2c[0]);
-        nm_close(pipefd_p2c[1]);
-        return FALSE;
-    }
-
-    if (pid == 0) {
-        char read_buf[1];
-
-        nm_close(pipefd_c2p[0]); /* close read-end */
-        nm_close(pipefd_p2c[1]); /* close write-end */
-
-        if (unshare(unshare_flags) != 0) {
-            errsv = errno;
-            if (errsv == 0)
-                errsv = -1;
-        } else
-            errsv = 0;
-
-        /* sync with parent process and send result. */
-        do {
-            r = write(pipefd_c2p[1], &errsv, sizeof(errsv));
-        } while (r < 0 && errno == EINTR);
-        if (r != sizeof(errsv)) {
-            errsv = errno;
-            if (errsv == 0)
-                errsv = -2;
-        }
-        nm_close(pipefd_c2p[1]);
-
-        /* wait until parent process terminates (or kills us). */
-        if (errsv == 0) {
-            do {
-                r = read(pipefd_p2c[0], read_buf, sizeof(read_buf));
-            } while (r < 0 && errno == EINTR);
-        }
-        nm_close(pipefd_p2c[0]);
-        _exit(0);
-    }
-
-    nm_close(pipefd_c2p[1]); /* close write-end */
-    nm_close(pipefd_p2c[0]); /* close read-end */
-
-    /* sync with child process. */
-    do {
-        r = read(pipefd_c2p[0], &errsv, sizeof(errsv));
-    } while (r < 0 && errno == EINTR);
-
-    nm_close(pipefd_c2p[0]);
-
-    if (r != sizeof(errsv) || errsv != 0) {
-        int status;
-
-        if (r != sizeof(errsv)) {
-            g_set_error(error,
-                        NM_UTILS_ERROR,
-                        NM_UTILS_ERROR_UNKNOWN,
-                        "child process failed for unknown reason");
-        } else {
-            g_set_error(error,
-                        NM_UTILS_ERROR,
-                        NM_UTILS_ERROR_UNKNOWN,
-                        "child process signaled failure %d (%s)",
-                        errsv,
-                        nm_strerror_native(errsv));
-        }
-        nm_close(pipefd_p2c[1]);
-        kill(pid, SIGKILL);
-        do {
-            pid2 = waitpid(pid, &status, 0);
-        } while (pid2 == -1 && errno == EINTR);
-        return FALSE;
-    }
-
-    ns_handle          = g_new0(NMTstpNamespaceHandle, 1);
-    ns_handle->pid     = pid;
-    ns_handle->pipe_fd = pipefd_p2c[1];
-    return ns_handle;
-}
-
-pid_t
-nmtstp_namespace_handle_get_pid(NMTstpNamespaceHandle *ns_handle)
-{
-    g_return_val_if_fail(ns_handle, 0);
-    g_return_val_if_fail(ns_handle->pid > 0, 0);
-
-    return ns_handle->pid;
-}
-
-void
-nmtstp_namespace_handle_release(NMTstpNamespaceHandle *ns_handle)
-{
-    pid_t pid;
-    int   status;
-
-    if (!ns_handle)
-        return;
-
-    g_return_if_fail(ns_handle->pid > 0);
-
-    nm_close(ns_handle->pipe_fd);
-    ns_handle->pipe_fd = 0;
-
-    kill(ns_handle->pid, SIGKILL);
-
-    do {
-        pid = waitpid(ns_handle->pid, &status, 0);
-    } while (pid == -1 && errno == EINTR);
-    ns_handle->pid = 0;
-
-    g_free(ns_handle);
-}
-
-int
-nmtstp_namespace_get_fd_for_process(pid_t pid, const char *ns_name)
-{
-    char p[1000];
-
-    g_return_val_if_fail(pid > 0, 0);
-    g_return_val_if_fail(ns_name && ns_name[0] && strlen(ns_name) < 50, 0);
-
-    nm_sprintf_buf(p, "/proc/%lu/ns/%s", (unsigned long) pid, ns_name);
-
-    return open(p, O_RDONLY | O_CLOEXEC);
-}
-
-/*****************************************************************************/
-
-void
-nmtstp_netns_select_random(NMPlatform **platforms, gsize n_platforms, NMPNetns **netns)
-{
-    int i;
-
-    g_assert(platforms);
-    g_assert(n_platforms && n_platforms <= G_MAXINT32);
-    g_assert(netns && !*netns);
-    for (i = 0; i < n_platforms; i++)
-        g_assert(NM_IS_PLATFORM(platforms[i]));
-
-    i = nmtst_get_rand_uint32() % (n_platforms + 1);
-    if (i == 0)
-        return;
-    g_assert(nm_platform_netns_push(platforms[i - 1], netns));
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-static gboolean
-unshare_user(void)
-{
-    FILE *f;
-    uid_t uid = geteuid();
-    gid_t gid = getegid();
-
-    /* Already a root? */
-    if (gid == 0 && uid == 0)
-        return TRUE;
-
-    /* Become a root in new user NS. */
-    if (unshare(CLONE_NEWUSER) != 0)
-        return FALSE;
-
-    /* Since Linux 3.19 we have to disable setgroups() in order to map users.
-     * Just proceed if the file is not there. */
-    f = fopen("/proc/self/setgroups", "we");
-    if (f) {
-        fprintf(f, "deny");
-        fclose(f);
-    }
-
-    /* Map current UID to root in NS to be created. */
-    f = fopen("/proc/self/uid_map", "we");
-    if (!f)
-        return FALSE;
-    fprintf(f, "0 %d 1", uid);
-    fclose(f);
-
-    /* Map current GID to root in NS to be created. */
-    f = fopen("/proc/self/gid_map", "we");
-    if (!f)
-        return FALSE;
-    fprintf(f, "0 %d 1", gid);
-    fclose(f);
-
-    return TRUE;
-}
-
-int
-main(int argc, char **argv)
-{
-    int         result;
-    const char *program = *argv;
-
-    _nmtstp_init_tests(&argc, &argv);
-
-    if (nmtstp_is_root_test() && (geteuid() != 0 || getegid() != 0)) {
-        if (g_getenv("NMTST_FORCE_REAL_ROOT") || !unshare_user()) {
-            /* Try to exec as sudo, this function does not return, if a sudo-cmd is set. */
-            nmtst_reexec_sudo();
-
-#ifdef REQUIRE_ROOT_TESTS
-            g_print("Fail test: requires root privileges (%s)\n", program);
-            return EXIT_FAILURE;
-#else
-            g_print("Skipping test: requires root privileges (%s)\n", program);
-            return g_test_run();
-#endif
-        }
-    }
-
-    if (nmtstp_is_root_test() && !g_getenv("NMTST_NO_UNSHARE")) {
-        int errsv;
-
-        if (unshare(CLONE_NEWNET | CLONE_NEWNS) != 0) {
-            errsv = errno;
-            g_error("unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)",
-                    nm_strerror_native(errsv),
-                    errsv);
-        }
-
-        /* We need a read-only /sys so that the platform knows there's no udev. */
-        mount(NULL, "/sys", "sysfs", MS_SLAVE, NULL);
-        if (mount("sys", "/sys", "sysfs", MS_RDONLY, NULL) != 0) {
-            errsv = errno;
-            g_error("mount(\"/sys\") failed with %s (%d)", nm_strerror_native(errsv), errsv);
-        }
-    }
-
-    nmtstp_setup_platform();
-
-    _nmtstp_setup_tests();
-
-    result = g_test_run();
-
-    nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE);
-
-    g_object_unref(NM_PLATFORM_GET);
-    return result;
-}
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
deleted file mode 100644
index 1d996f46..00000000
--- a/src/platform/tests/test-common.h
+++ /dev/null
@@ -1,610 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2016 - 2017 Red Hat, Inc.
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <arpa/inet.h>
-#include <linux/if.h>
-#include <linux/if_link.h>
-#include <linux/ip6_tunnel.h>
-
-#include "platform/nm-platform.h"
-#include "platform/nmp-object.h"
-#include "platform/nm-fake-platform.h"
-#include "platform/nm-linux-platform.h"
-
-#include "nm-test-utils-core.h"
-
-#define DEVICE_NAME "nm-test-device"
-
-/*****************************************************************************/
-
-#define _NMLOG_PREFIX_NAME "platform-test"
-#define _NMLOG_DOMAIN      LOGD_PLATFORM
-#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, __VA_ARGS__)
-
-#define _LOG(level, domain, ...)                                                             \
-    G_STMT_START                                                                             \
-    {                                                                                        \
-        const NMLogLevel  __level  = (level);                                                \
-        const NMLogDomain __domain = (domain);                                               \
-                                                                                             \
-        if (nm_logging_enabled(__level, __domain)) {                                         \
-            gint64 _ts = nm_utils_get_monotonic_timestamp_nsec();                            \
-                                                                                             \
-            _nm_log(__level,                                                                 \
-                    __domain,                                                                \
-                    0,                                                                       \
-                    NULL,                                                                    \
-                    NULL,                                                                    \
-                    "%s[%ld.%09ld]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),                    \
-                    _NMLOG_PREFIX_NAME,                                                      \
-                    (long) (_ts / NM_UTILS_NSEC_PER_SEC),                                    \
-                    (long) (_ts % NM_UTILS_NSEC_PER_SEC) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
-        }                                                                                    \
-    }                                                                                        \
-    G_STMT_END
-
-/*****************************************************************************/
-
-gboolean nmtstp_is_root_test(void);
-gboolean nmtstp_is_sysfs_writable(void);
-
-/*****************************************************************************/
-
-typedef struct _NMTstpNamespaceHandle NMTstpNamespaceHandle;
-
-NMTstpNamespaceHandle *nmtstp_namespace_create(int flags, GError **error);
-
-void  nmtstp_namespace_handle_release(NMTstpNamespaceHandle *handle);
-pid_t nmtstp_namespace_handle_get_pid(NMTstpNamespaceHandle *handle);
-
-int nmtstp_namespace_get_fd_for_process(pid_t pid, const char *ns_name);
-
-/*****************************************************************************/
-
-void nmtstp_netns_select_random(NMPlatform **platforms, gsize n_platforms, NMPNetns **netns);
-
-/*****************************************************************************/
-
-typedef struct {
-    gulong                     handler_id;
-    const char *               name;
-    NMPlatformSignalChangeType change_type;
-    int                        received_count;
-    GMainLoop *                loop;
-    int                        ifindex;
-    const char *               ifname;
-} SignalData;
-
-SignalData *add_signal_full(const char *               name,
-                            NMPlatformSignalChangeType change_type,
-                            GCallback                  callback,
-                            int                        ifindex,
-                            const char *               ifname);
-#define add_signal(name, change_type, callback) \
-    add_signal_full(name, change_type, (GCallback) callback, 0, NULL)
-#define add_signal_ifindex(name, change_type, callback, ifindex) \
-    add_signal_full(name, change_type, (GCallback) callback, ifindex, NULL)
-#define add_signal_ifname(name, change_type, callback, ifname) \
-    add_signal_full(name, change_type, (GCallback) callback, 0, ifname)
-void _accept_signal(const char *file, int line, const char *func, SignalData *data);
-void
-_accept_signals(const char *file, int line, const char *func, SignalData *data, int min, int max);
-void _wait_signal(const char *file, int line, const char *func, SignalData *data);
-void _accept_or_wait_signal(const char *file, int line, const char *func, SignalData *data);
-void _ensure_no_signal(const char *file, int line, const char *func, SignalData *data);
-void _free_signal(const char *file, int line, const char *func, SignalData *data);
-#define accept_signal(data) _accept_signal(__FILE__, __LINE__, G_STRFUNC, data)
-#define accept_signals(data, min, max) \
-    _accept_signals(__FILE__, __LINE__, G_STRFUNC, data, min, max)
-#define wait_signal(data)           _wait_signal(__FILE__, __LINE__, G_STRFUNC, data)
-#define accept_or_wait_signal(data) _accept_or_wait_signal(__FILE__, __LINE__, G_STRFUNC, data)
-#define ensure_no_signal(data)      _ensure_no_signal(__FILE__, __LINE__, G_STRFUNC, data)
-#define free_signal(data)           _free_signal(__FILE__, __LINE__, G_STRFUNC, data)
-
-void link_callback(NMPlatform *    platform,
-                   int             obj_type_i,
-                   int             ifindex,
-                   NMPlatformLink *received,
-                   int             change_type_i,
-                   SignalData *    data);
-
-/*****************************************************************************/
-
-int nmtstp_run_command(const char *format, ...) _nm_printf(1, 2);
-#define nmtstp_run_command_check(...)                            \
-    do {                                                         \
-        g_assert_cmpint(nmtstp_run_command(__VA_ARGS__), ==, 0); \
-    } while (0)
-
-/*****************************************************************************/
-
-guint                 nmtstp_wait_for_signal(NMPlatform *platform, gint64 timeout_msec);
-guint                 nmtstp_wait_for_signal_until(NMPlatform *platform, gint64 until_ms);
-const NMPlatformLink *nmtstp_wait_for_link(NMPlatform *platform,
-                                           const char *ifname,
-                                           NMLinkType  expected_link_type,
-                                           gint64      timeout_msec);
-const NMPlatformLink *nmtstp_wait_for_link_until(NMPlatform *platform,
-                                                 const char *ifname,
-                                                 NMLinkType  expected_link_type,
-                                                 gint64      until_ms);
-
-#define nmtstp_assert_wait_for_signal(platform, timeout_msec)    \
-    G_STMT_START                                                 \
-    {                                                            \
-        if (nmtstp_wait_for_signal(platform, timeout_msec) == 0) \
-            g_assert_not_reached();                              \
-    }                                                            \
-    G_STMT_END
-
-#define nmtstp_assert_wait_for_signal_until(platform, until_ms)    \
-    G_STMT_START                                                   \
-    {                                                              \
-        if (nmtstp_wait_for_signal_until(platform, until_ms) == 0) \
-            g_assert_not_reached();                                \
-    }                                                              \
-    G_STMT_END
-
-#define nmtstp_assert_wait_for_link(platform, ifname, expected_link_type, timeout_msec) \
-    nmtst_assert_nonnull(nmtstp_wait_for_link(platform, ifname, expected_link_type, timeout_msec))
-
-#define nmtstp_assert_wait_for_link_until(platform, ifname, expected_link_type, until_ms) \
-    nmtst_assert_nonnull(nmtstp_wait_for_link_until(platform, ifname, expected_link_type, until_ms))
-
-/*****************************************************************************/
-
-int      nmtstp_run_command_check_external_global(void);
-gboolean nmtstp_run_command_check_external(int external_command);
-
-/*****************************************************************************/
-
-const NMPlatformIP4Route *_nmtstp_assert_ip4_route_exists(const char *file,
-                                                          guint       line,
-                                                          const char *func,
-                                                          NMPlatform *platform,
-                                                          int         c_exists,
-                                                          const char *ifname,
-                                                          guint32     network,
-                                                          int         plen,
-                                                          guint32     metric,
-                                                          guint8      tos);
-#define nmtstp_assert_ip4_route_exists(platform, c_exists, ifname, network, plen, metric, tos) \
-    _nmtstp_assert_ip4_route_exists(__FILE__,                                                  \
-                                    __LINE__,                                                  \
-                                    G_STRFUNC,                                                 \
-                                    platform,                                                  \
-                                    c_exists,                                                  \
-                                    ifname,                                                    \
-                                    network,                                                   \
-                                    plen,                                                      \
-                                    metric,                                                    \
-                                    tos)
-
-const NMPlatformIP4Route *nmtstp_ip4_route_get(NMPlatform *platform,
-                                               int         ifindex,
-                                               guint32     network,
-                                               int         plen,
-                                               guint32     metric,
-                                               guint8      tos);
-
-const NMPlatformIP6Route *_nmtstp_assert_ip6_route_exists(const char *           file,
-                                                          guint                  line,
-                                                          const char *           func,
-                                                          NMPlatform *           platform,
-                                                          int                    c_exists,
-                                                          const char *           ifname,
-                                                          const struct in6_addr *network,
-                                                          guint                  plen,
-                                                          guint32                metric,
-                                                          const struct in6_addr *src,
-                                                          guint8                 src_plen);
-#define nmtstp_assert_ip6_route_exists(platform, \
-                                       c_exists, \
-                                       ifname,   \
-                                       network,  \
-                                       plen,     \
-                                       metric,   \
-                                       src,      \
-                                       src_plen) \
-    _nmtstp_assert_ip6_route_exists(__FILE__,    \
-                                    __LINE__,    \
-                                    G_STRFUNC,   \
-                                    platform,    \
-                                    c_exists,    \
-                                    ifname,      \
-                                    network,     \
-                                    plen,        \
-                                    metric,      \
-                                    src,         \
-                                    src_plen)
-
-const NMPlatformIP6Route *nmtstp_ip6_route_get(NMPlatform *           platform,
-                                               int                    ifindex,
-                                               const struct in6_addr *network,
-                                               guint                  plen,
-                                               guint32                metric,
-                                               const struct in6_addr *src,
-                                               guint8                 src_plen);
-
-/*****************************************************************************/
-
-gboolean nmtstp_ip_address_check_lifetime(const NMPlatformIPAddress *addr,
-                                          gint64                     now,
-                                          guint32                    expected_lifetime,
-                                          guint32                    expected_preferred);
-void     nmtstp_ip_address_assert_lifetime(const NMPlatformIPAddress *addr,
-                                           gint64                     now,
-                                           guint32                    expected_lifetime,
-                                           guint32                    expected_preferred);
-
-void nmtstp_ip4_address_add(NMPlatform *platform,
-                            gboolean    external_command,
-                            int         ifindex,
-                            in_addr_t   address,
-                            int         plen,
-                            in_addr_t   peer_address,
-                            guint32     lifetime,
-                            guint32     preferred,
-                            guint32     flags,
-                            const char *label);
-void nmtstp_ip6_address_add(NMPlatform *    platform,
-                            gboolean        external_command,
-                            int             ifindex,
-                            struct in6_addr address,
-                            int             plen,
-                            struct in6_addr peer_address,
-                            guint32         lifetime,
-                            guint32         preferred,
-                            guint32         flags);
-void nmtstp_ip4_address_del(NMPlatform *platform,
-                            gboolean    external_command,
-                            int         ifindex,
-                            in_addr_t   address,
-                            int         plen,
-                            in_addr_t   peer_address);
-void nmtstp_ip6_address_del(NMPlatform *    platform,
-                            gboolean        external_command,
-                            int             ifindex,
-                            struct in6_addr address,
-                            int             plen);
-
-void nmtstp_ip4_route_add(NMPlatform *     platform,
-                          int              ifindex,
-                          NMIPConfigSource source,
-                          in_addr_t        network,
-                          guint8           plen,
-                          in_addr_t        gateway,
-                          in_addr_t        pref_src,
-                          guint32          metric,
-                          guint32          mss);
-
-void nmtstp_ip6_route_add(NMPlatform *     platform,
-                          int              ifindex,
-                          NMIPConfigSource source,
-                          struct in6_addr  network,
-                          guint8           plen,
-                          struct in6_addr  gateway,
-                          struct in6_addr  pref_src,
-                          guint32          metric,
-                          guint32          mss);
-
-static inline GPtrArray *
-nmtstp_ip4_route_get_all(NMPlatform *platform, int ifindex)
-{
-    return nm_platform_lookup_object_clone(
-        platform,
-        NMP_OBJECT_TYPE_IP4_ROUTE,
-        ifindex,
-        nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
-        NULL);
-}
-
-static inline GPtrArray *
-nmtstp_ip6_route_get_all(NMPlatform *platform, int ifindex)
-{
-    return nm_platform_lookup_object_clone(
-        platform,
-        NMP_OBJECT_TYPE_IP6_ROUTE,
-        ifindex,
-        nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
-        NULL);
-}
-
-/*****************************************************************************/
-
-GArray *nmtstp_platform_ip4_address_get_all(NMPlatform *self, int ifindex);
-GArray *nmtstp_platform_ip6_address_get_all(NMPlatform *self, int ifindex);
-
-/*****************************************************************************/
-
-const NMPlatformIPAddress *
-nmtstp_platform_ip_address_find(NMPlatform *self, int ifindex, int addr_family, gconstpointer addr);
-
-static inline const NMPlatformIP4Address *
-nmtstp_platform_ip4_address_find(NMPlatform *self, int ifindex, in_addr_t addr)
-{
-    return (const NMPlatformIP4Address *)
-        nmtstp_platform_ip_address_find(self, ifindex, AF_INET, &addr);
-}
-
-static inline const NMPlatformIP6Address *
-nmtstp_platform_ip6_address_find(NMPlatform *self, int ifindex, const struct in6_addr *addr)
-{
-    return (const NMPlatformIP6Address *)
-        nmtstp_platform_ip_address_find(self, ifindex, AF_INET6, addr);
-}
-
-void _nmtstp_platform_ip_addresses_assert(const char *       filename,
-                                          int                lineno,
-                                          NMPlatform *       self,
-                                          int                ifindex,
-                                          gboolean           force_exact_4,
-                                          gboolean           force_exact_6,
-                                          gboolean           ignore_ll6,
-                                          guint              addrs_len,
-                                          const char *const *addrs);
-
-#define nmtstp_platform_ip_addresses_assert(self,                                              \
-                                            ifindex,                                           \
-                                            force_exact_4,                                     \
-                                            force_exact_6,                                     \
-                                            ignore_ll6,                                        \
-                                            ...)                                               \
-    _nmtstp_platform_ip_addresses_assert(__FILE__,                                             \
-                                         __LINE__,                                             \
-                                         (self),                                               \
-                                         (ifindex),                                            \
-                                         (force_exact_4),                                      \
-                                         (force_exact_6),                                      \
-                                         (ignore_ll6),                                         \
-                                         NM_NARG(__VA_ARGS__),                                 \
-                                         ((const char *const[]){"dummy", ##__VA_ARGS__, NULL}) \
-                                             + 1)
-
-/*****************************************************************************/
-
-static inline gboolean
-_nmtstp_platform_routing_rules_get_all_predicate(const NMPObject *obj, gpointer user_data)
-{
-    int addr_family = GPOINTER_TO_INT(user_data);
-
-    g_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_ROUTING_RULE);
-
-    return addr_family == AF_UNSPEC
-           || NMP_OBJECT_CAST_ROUTING_RULE(obj)->addr_family == addr_family;
-}
-
-static inline GPtrArray *
-nmtstp_platform_routing_rules_get_all(NMPlatform *platform, int addr_family)
-{
-    NMPLookup lookup;
-
-    g_assert(NM_IS_PLATFORM(platform));
-    g_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
-    nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
-    return nm_platform_lookup_clone(platform,
-                                    &lookup,
-                                    _nmtstp_platform_routing_rules_get_all_predicate,
-                                    GINT_TO_POINTER(addr_family));
-}
-
-static inline guint
-nmtstp_platform_routing_rules_get_count(NMPlatform *platform, int addr_family)
-{
-    const NMDedupMultiHeadEntry *head_entry;
-    NMDedupMultiIter             iter;
-    const NMPObject *            obj;
-    NMPLookup                    lookup;
-    guint                        n;
-
-    g_assert(NM_IS_PLATFORM(platform));
-    g_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
-    nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
-    head_entry = nm_platform_lookup(platform, &lookup);
-
-    n = 0;
-    nmp_cache_iter_for_each (&iter, head_entry, &obj) {
-        if (_nmtstp_platform_routing_rules_get_all_predicate(obj, GINT_TO_POINTER(addr_family)))
-            n++;
-    }
-    return n;
-}
-
-gboolean nmtstp_platform_ip4_route_delete(NMPlatform *platform,
-                                          int         ifindex,
-                                          in_addr_t   network,
-                                          guint8      plen,
-                                          guint32     metric);
-gboolean nmtstp_platform_ip6_route_delete(NMPlatform *    platform,
-                                          int             ifindex,
-                                          struct in6_addr network,
-                                          guint8          plen,
-                                          guint32         metric);
-
-const NMPlatformLink *
-nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
-const NMPlatformLink *nmtstp_link_get(NMPlatform *platform, int ifindex, const char *name);
-
-gboolean nmtstp_kernel_support_get(NMPlatformKernelSupportType type);
-
-void
-nmtstp_link_set_updown(NMPlatform *platform, gboolean external_command, int ifindex, gboolean up);
-
-const NMPlatformLink *nmtstp_link_bridge_add(NMPlatform *               platform,
-                                             gboolean                   external_command,
-                                             const char *               name,
-                                             const NMPlatformLnkBridge *lnk);
-const NMPlatformLink *nmtstp_link_veth_add(NMPlatform *platform,
-                                           gboolean    external_command,
-                                           const char *name,
-                                           const char *peer);
-const NMPlatformLink *
-nmtstp_link_dummy_add(NMPlatform *platform, gboolean external_command, const char *name);
-const NMPlatformLink *nmtstp_link_gre_add(NMPlatform *            platform,
-                                          gboolean                external_command,
-                                          const char *            name,
-                                          const NMPlatformLnkGre *lnk);
-const NMPlatformLink *nmtstp_link_ip6tnl_add(NMPlatform *               platform,
-                                             gboolean                   external_command,
-                                             const char *               name,
-                                             const NMPlatformLnkIp6Tnl *lnk);
-const NMPlatformLink *nmtstp_link_ip6gre_add(NMPlatform *               platform,
-                                             gboolean                   external_command,
-                                             const char *               name,
-                                             const NMPlatformLnkIp6Tnl *lnk);
-const NMPlatformLink *nmtstp_link_ipip_add(NMPlatform *             platform,
-                                           gboolean                 external_command,
-                                           const char *             name,
-                                           const NMPlatformLnkIpIp *lnk);
-const NMPlatformLink *nmtstp_link_macvlan_add(NMPlatform *                platform,
-                                              gboolean                    external_command,
-                                              const char *                name,
-                                              int                         parent,
-                                              const NMPlatformLnkMacvlan *lnk);
-const NMPlatformLink *nmtstp_link_sit_add(NMPlatform *            platform,
-                                          gboolean                external_command,
-                                          const char *            name,
-                                          const NMPlatformLnkSit *lnk);
-const NMPlatformLink *nmtstp_link_tun_add(NMPlatform *            platform,
-                                          gboolean                external_command,
-                                          const char *            name,
-                                          const NMPlatformLnkTun *lnk,
-                                          int *                   out_fd);
-const NMPlatformLink *nmtstp_link_vrf_add(NMPlatform *            platform,
-                                          gboolean                external_command,
-                                          const char *            name,
-                                          const NMPlatformLnkVrf *lnk,
-                                          gboolean *              out_not_supported);
-const NMPlatformLink *nmtstp_link_vxlan_add(NMPlatform *              platform,
-                                            gboolean                  external_command,
-                                            const char *              name,
-                                            const NMPlatformLnkVxlan *lnk);
-
-void nmtstp_link_delete(NMPlatform *platform,
-                        gboolean    external_command,
-                        int         ifindex,
-                        const char *name,
-                        gboolean    require_exist);
-
-/*****************************************************************************/
-
-extern int NMTSTP_ENV1_IFINDEX;
-extern int NMTSTP_ENV1_EX;
-
-static inline void
-_nmtstp_env1_wrapper_setup(const NmtstTestData *test_data)
-{
-    int *    p_ifindex;
-    gpointer p_ifup;
-
-    nmtst_test_data_unpack(test_data, &p_ifindex, NULL, NULL, NULL, &p_ifup);
-
-    g_assert(p_ifindex && *p_ifindex == -1);
-
-    _LOGT("TEST[%s]: setup", test_data->testpath);
-
-    nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE);
-
-    g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL)));
-
-    *p_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert_cmpint(*p_ifindex, >, 0);
-    g_assert_cmpint(NMTSTP_ENV1_IFINDEX, ==, -1);
-
-    if (GPOINTER_TO_INT(p_ifup))
-        g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, *p_ifindex, NULL));
-
-    nm_platform_process_events(NM_PLATFORM_GET);
-
-    NMTSTP_ENV1_IFINDEX = *p_ifindex;
-    NMTSTP_ENV1_EX      = nmtstp_run_command_check_external_global();
-}
-
-static inline void
-_nmtstp_env1_wrapper_run(gconstpointer user_data)
-{
-    const NmtstTestData *test_data = user_data;
-    GTestDataFunc        test_func_data;
-    GTestFunc            test_func;
-    gconstpointer        d;
-
-    nmtst_test_data_unpack(test_data, NULL, &test_func, &test_func_data, &d, NULL);
-
-    _LOGT("TEST[%s]: run", test_data->testpath);
-    if (test_func)
-        test_func();
-    else
-        test_func_data(d);
-}
-
-static inline void
-_nmtstp_env1_wrapper_teardown(const NmtstTestData *test_data)
-{
-    int *p_ifindex;
-
-    nmtst_test_data_unpack(test_data, &p_ifindex, NULL, NULL, NULL, NULL);
-
-    g_assert_cmpint(NMTSTP_ENV1_IFINDEX, ==, *p_ifindex);
-    NMTSTP_ENV1_IFINDEX = -1;
-
-    _LOGT("TEST[%s]: teardown", test_data->testpath);
-
-    g_assert_cmpint(*p_ifindex, ==, nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME));
-    g_assert(nm_platform_link_delete(NM_PLATFORM_GET, *p_ifindex));
-
-    nm_platform_process_events(NM_PLATFORM_GET);
-
-    _LOGT("TEST[%s]: finished", test_data->testpath);
-
-    *p_ifindex = -1;
-}
-
-/* add test function, that set's up a particular environment, consisting
- * of a dummy device with ifindex NMTSTP_ENV1_IFINDEX. */
-#define _nmtstp_env1_add_test_func_full(testpath, test_func, test_data_func, arg, ifup) \
-    nmtst_add_test_func_full(testpath,                                                  \
-                             _nmtstp_env1_wrapper_run,                                  \
-                             _nmtstp_env1_wrapper_setup,                                \
-                             _nmtstp_env1_wrapper_teardown,                             \
-                             ({                                                         \
-                                 static int _ifindex = -1;                              \
-                                 &_ifindex;                                             \
-                             }),                                                        \
-                             ({                                                         \
-                                 GTestFunc _test_func = (test_func);                    \
-                                 _test_func;                                            \
-                             }),                                                        \
-                             ({                                                         \
-                                 GTestDataFunc _test_func = (test_data_func);           \
-                                 _test_func;                                            \
-                             }),                                                        \
-                             (arg),                                                     \
-                             ({                                                         \
-                                 gboolean _ifup = (ifup);                               \
-                                 GINT_TO_POINTER(_ifup);                                \
-                             }))
-
-#define nmtstp_env1_add_test_func_data(testpath, test_func, arg, ifup) \
-    _nmtstp_env1_add_test_func_full(testpath, NULL, test_func, arg, ifup)
-
-#define nmtstp_env1_add_test_func(testpath, test_func, ifup) \
-    _nmtstp_env1_add_test_func_full(testpath, test_func, NULL, NULL, ifup)
-
-/*****************************************************************************/
-
-typedef void (*NMTstpSetupFunc)(void);
-extern NMTstpSetupFunc const _nmtstp_setup_platform_func;
-
-void nmtstp_setup_platform(void);
-
-/*****************************************************************************/
-
-void _nmtstp_init_tests(int *argc, char ***argv);
-void _nmtstp_setup_tests(void);
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
deleted file mode 100644
index 5fd67ec4..00000000
--- a/src/platform/tests/test-link.c
+++ /dev/null
@@ -1,3819 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2016 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include <sched.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <linux/if_tun.h>
-
-#include "nm-glib-aux/nm-io-utils.h"
-#include "platform/nmp-object.h"
-#include "platform/nmp-netns.h"
-#include "platform/nm-platform-utils.h"
-
-#include "test-common.h"
-#include "nm-test-utils-core.h"
-
-#define LO_INDEX    1
-#define LO_NAME     "lo"
-#define LO_TYPEDESC "loopback"
-
-#define DUMMY_TYPEDESC "dummy"
-#define BOGUS_NAME     "nm-bogus-device"
-#define BOGUS_IFINDEX  INT_MAX
-#define SLAVE_NAME     "nm-test-slave"
-#define PARENT_NAME    "nm-test-parent"
-#define VLAN_ID        4077
-#define VLAN_FLAGS     0
-#define MTU            1357
-
-#define _ADD_DUMMY(platform, name) \
-    g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add((platform), (name), NULL)))
-
-static void
-test_bogus(void)
-{
-    size_t addrlen;
-
-    g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, BOGUS_NAME));
-    g_assert(!nm_platform_link_delete(NM_PLATFORM_GET, BOGUS_IFINDEX));
-    g_assert(!nm_platform_link_get_ifindex(NM_PLATFORM_GET, BOGUS_NAME));
-    g_assert(!nm_platform_link_get_name(NM_PLATFORM_GET, BOGUS_IFINDEX));
-    g_assert(!nm_platform_link_get_type(NM_PLATFORM_GET, BOGUS_IFINDEX));
-    g_assert(!nm_platform_link_get_type_name(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_set_up(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL));
-
-    g_assert(!nm_platform_link_set_down(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_set_arp(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_set_noarp(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, BOGUS_IFINDEX));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, BOGUS_IFINDEX));
-    g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_get_address(NM_PLATFORM_GET, BOGUS_IFINDEX, &addrlen));
-    g_assert(!addrlen);
-    g_assert(!nm_platform_link_get_address(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL));
-
-    g_assert(!NMTST_NM_ERR_SUCCESS(nm_platform_link_set_mtu(NM_PLATFORM_GET, BOGUS_IFINDEX, MTU)));
-
-    g_assert(!nm_platform_link_get_mtu(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_supports_carrier_detect(NM_PLATFORM_GET, BOGUS_IFINDEX));
-    g_assert(!nm_platform_link_supports_vlans(NM_PLATFORM_GET, BOGUS_IFINDEX));
-
-    g_assert(!nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL));
-    g_assert(!nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0));
-    g_assert(!nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0));
-}
-
-static void
-test_loopback(void)
-{
-    g_assert(nm_platform_link_get_by_ifname(NM_PLATFORM_GET, LO_NAME));
-    g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, LO_INDEX),
-                    ==,
-                    NM_LINK_TYPE_LOOPBACK);
-    g_assert_cmpint(nm_platform_link_get_ifindex(NM_PLATFORM_GET, LO_NAME), ==, LO_INDEX);
-    g_assert_cmpstr(nm_platform_link_get_name(NM_PLATFORM_GET, LO_INDEX), ==, LO_NAME);
-    g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, LO_INDEX), ==, LO_TYPEDESC);
-
-    g_assert(nm_platform_link_supports_carrier_detect(NM_PLATFORM_GET, LO_INDEX));
-    g_assert(!nm_platform_link_supports_vlans(NM_PLATFORM_GET, LO_INDEX));
-}
-
-static gboolean
-software_add(NMLinkType link_type, const char *name)
-{
-    switch (link_type) {
-    case NM_LINK_TYPE_DUMMY:
-        return NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, name, NULL));
-    case NM_LINK_TYPE_BRIDGE:
-        return NMTST_NM_ERR_SUCCESS(nm_platform_link_bridge_add(NM_PLATFORM_GET,
-                                                                name,
-                                                                NULL,
-                                                                0,
-                                                                0,
-                                                                &nm_platform_lnk_bridge_default,
-                                                                NULL));
-    case NM_LINK_TYPE_BOND:
-    {
-        gboolean bond0_exists = !!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "bond0");
-        int      r;
-
-        r = nm_platform_link_bond_add(NM_PLATFORM_GET, name, NULL);
-
-        /* Check that bond0 is *not* automatically created. */
-        if (!bond0_exists)
-            g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "bond0"));
-        return r >= 0;
-    }
-    case NM_LINK_TYPE_TEAM:
-        return NMTST_NM_ERR_SUCCESS(nm_platform_link_team_add(NM_PLATFORM_GET, name, NULL));
-    case NM_LINK_TYPE_VLAN:
-    {
-        SignalData *parent_added;
-        SignalData *parent_changed;
-
-        /* Don't call link_callback for the bridge interface */
-        parent_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                         NM_PLATFORM_SIGNAL_ADDED,
-                                         link_callback,
-                                         PARENT_NAME);
-        if (NMTST_NM_ERR_SUCCESS(nm_platform_link_bridge_add(NM_PLATFORM_GET,
-                                                             PARENT_NAME,
-                                                             NULL,
-                                                             0,
-                                                             0,
-                                                             &nm_platform_lnk_bridge_default,
-                                                             NULL)))
-            accept_signal(parent_added);
-        free_signal(parent_added);
-
-        {
-            int      parent_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME);
-            gboolean was_up         = nm_platform_link_is_up(NM_PLATFORM_GET, parent_ifindex);
-
-            parent_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                                NM_PLATFORM_SIGNAL_CHANGED,
-                                                link_callback,
-                                                parent_ifindex);
-            g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, parent_ifindex, NULL));
-            if (was_up) {
-                /* when NM is running in the background, it will mess with addrgenmode which might cause additional signals. */
-                accept_signals(parent_changed, 0, 1);
-            } else
-                accept_signals(parent_changed, 1, 2);
-            free_signal(parent_changed);
-
-            return NMTST_NM_ERR_SUCCESS(
-                nm_platform_link_vlan_add(NM_PLATFORM_GET, name, parent_ifindex, VLAN_ID, 0, NULL));
-        }
-    }
-    default:
-        g_error("Link type %d unhandled.", link_type);
-    }
-    g_assert_not_reached();
-}
-
-static void
-test_link_changed_signal_cb(NMPlatform *              platform,
-                            int                       obj_type_i,
-                            int                       ifindex,
-                            const NMPlatformIP4Route *route,
-                            int                       change_type_i,
-                            gboolean *                p_test_link_changed_signal_arg)
-{
-    const NMPObjectType              obj_type    = obj_type_i;
-    const NMPlatformSignalChangeType change_type = change_type_i;
-
-    /* test invocation of platform signals with multiple listeners
-     * connected to the signal. Platform signals have enum-typed
-     * arguments and there seem to be an issue with invoking such
-     * signals on s390x and ppc64 archs.
-     * https://bugzilla.redhat.com/show_bug.cgi?id=1260577
-     *
-     * As the test shows, the failure is not reproducible for
-     * platform signals.
-     */
-    g_assert(NM_IS_PLATFORM(platform));
-    g_assert(platform == NM_PLATFORM_GET);
-
-    g_assert(ifindex > 0);
-    g_assert(route);
-
-    g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_LINK);
-
-    g_assert_cmpint((gint64) change_type, !=, (gint64) 0);
-    g_assert_cmpint(change_type, !=, NM_PLATFORM_SIGNAL_NONE);
-
-    *p_test_link_changed_signal_arg = TRUE;
-}
-
-static void
-test_slave(int master, int type, SignalData *master_changed)
-{
-    int         ifindex;
-    SignalData *link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                               NM_PLATFORM_SIGNAL_ADDED,
-                                               link_callback,
-                                               SLAVE_NAME);
-    SignalData *link_changed, *link_removed;
-    char *      value;
-    NMLinkType  link_type = nm_platform_link_get_type(NM_PLATFORM_GET, master);
-    gboolean    test_link_changed_signal_arg1;
-    gboolean    test_link_changed_signal_arg2;
-
-    g_assert(NM_IN_SET(link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE));
-
-    g_assert(software_add(type, SLAVE_NAME));
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, SLAVE_NAME);
-    g_assert(ifindex > 0);
-    link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_CHANGED,
-                                      link_callback,
-                                      ifindex);
-    link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_REMOVED,
-                                      link_callback,
-                                      ifindex);
-    accept_signal(link_added);
-
-    /* Set the slave up to see whether master's IFF_LOWER_UP is set correctly.
-     *
-     * See https://bugzilla.redhat.com/show_bug.cgi?id=910348
-     */
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    ensure_no_signal(link_changed);
-
-    /* Enslave */
-    link_changed->ifindex = ifindex;
-    g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, master, ifindex));
-    g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex), ==, master);
-
-    accept_signals(link_changed, 1, 3);
-    accept_signals(master_changed, 0, 2);
-
-    /* enslaveing brings put the slave */
-    if (NM_IN_SET(link_type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM))
-        g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    else
-        g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-
-    test_link_changed_signal_arg1 = FALSE;
-    test_link_changed_signal_arg2 = FALSE;
-    g_signal_connect(NM_PLATFORM_GET,
-                     NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                     G_CALLBACK(test_link_changed_signal_cb),
-                     &test_link_changed_signal_arg1);
-    g_signal_connect(NM_PLATFORM_GET,
-                     NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                     G_CALLBACK(test_link_changed_signal_cb),
-                     &test_link_changed_signal_arg2);
-
-    /* Set master up */
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, master, NULL));
-    g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, master));
-    accept_signals(master_changed, 1, 3);
-
-    g_signal_handlers_disconnect_by_func(NM_PLATFORM_GET,
-                                         G_CALLBACK(test_link_changed_signal_cb),
-                                         &test_link_changed_signal_arg1);
-    g_signal_handlers_disconnect_by_func(NM_PLATFORM_GET,
-                                         G_CALLBACK(test_link_changed_signal_cb),
-                                         &test_link_changed_signal_arg2);
-    g_assert(test_link_changed_signal_arg1);
-    g_assert(test_link_changed_signal_arg2);
-
-    /* Master with a disconnected slave is disconnected
-     *
-     * For some reason, bonding and teaming slaves are automatically set up. We
-     * need to set them back down for this test.
-     */
-    switch (nm_platform_link_get_type(NM_PLATFORM_GET, master)) {
-    case NM_LINK_TYPE_BOND:
-    case NM_LINK_TYPE_TEAM:
-        g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex));
-        accept_signal(link_changed);
-        accept_signals(master_changed, 0, 3);
-        break;
-    default:
-        break;
-    }
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    if (nmtstp_is_root_test() && nm_platform_link_is_connected(NM_PLATFORM_GET, master)) {
-        if (nm_platform_link_get_type(NM_PLATFORM_GET, master) == NM_LINK_TYPE_TEAM) {
-            /* Older team versions (e.g. Fedora 17) have a bug that team master stays
-             * IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if
-             * `ip link` also claims master to be up, accept it. */
-            char *stdout_str = NULL;
-
-            nmtst_spawn_sync(NULL,
-                             &stdout_str,
-                             NULL,
-                             0,
-                             "/sbin/ip",
-                             "link",
-                             "show",
-                             "dev",
-                             nm_platform_link_get_name(NM_PLATFORM_GET, master));
-
-            g_assert(strstr(stdout_str, "LOWER_UP"));
-            g_free(stdout_str);
-        } else
-            g_assert_not_reached();
-    }
-
-    /* Set slave up and see if master gets up too */
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL));
-    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, master));
-    accept_signals(link_changed, 1, 3);
-    /* NM running, can cause additional change of addrgenmode */
-    accept_signals(master_changed, 0, 3);
-
-    /* Enslave again
-     *
-     * Gracefully succeed if already enslaved.
-     */
-    ensure_no_signal(link_changed);
-    g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, master, ifindex));
-    accept_signals(link_changed, 0, 2);
-    accept_signals(master_changed, 0, 2);
-
-    /* Set slave option */
-    switch (type) {
-    case NM_LINK_TYPE_BRIDGE:
-        if (nmtstp_is_sysfs_writable()) {
-            g_assert(
-                nm_platform_sysctl_slave_set_option(NM_PLATFORM_GET, ifindex, "priority", "614"));
-            value = nm_platform_sysctl_slave_get_option(NM_PLATFORM_GET, ifindex, "priority");
-            g_assert_cmpstr(value, ==, "614");
-            g_free(value);
-        }
-        break;
-    default:
-        break;
-    }
-
-    /* Release */
-    ensure_no_signal(link_added);
-    ensure_no_signal(link_changed);
-    ensure_no_signal(link_removed);
-    g_assert(nm_platform_link_release(NM_PLATFORM_GET, master, ifindex));
-    g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex), ==, 0);
-    if (link_changed->received_count > 0) {
-        accept_signals(link_added, 0, 1);
-        accept_signals(link_changed, 1, 5);
-        accept_signals(link_removed, 0, 1);
-    } else {
-        /* Due to https://bugzilla.redhat.com/show_bug.cgi?id=1285719 , kernel might send a
-         * wrong RTM_DELLINK message so that we instead see an removed+added signal. */
-        accept_signal(link_added);
-        ensure_no_signal(link_changed);
-        accept_signal(link_removed);
-    }
-    accept_signals(master_changed, 0, 3);
-
-    ensure_no_signal(master_changed);
-
-    /* Release again */
-    ensure_no_signal(link_changed);
-    g_assert(!nm_platform_link_release(NM_PLATFORM_GET, master, ifindex));
-
-    ensure_no_signal(master_changed);
-
-    /* Remove */
-    ensure_no_signal(link_added);
-    ensure_no_signal(link_changed);
-    ensure_no_signal(link_removed);
-    nmtstp_link_delete(NULL, -1, ifindex, NULL, TRUE);
-    accept_signals(master_changed, 0, 1);
-    accept_signals(link_changed, 0, 1);
-    accept_signal(link_removed);
-
-    free_signal(link_added);
-    free_signal(link_changed);
-    free_signal(link_removed);
-}
-
-static void
-test_software(NMLinkType link_type, const char *link_typename)
-{
-    int   ifindex;
-    char *value;
-    int   vlan_parent = -1, vlan_id;
-
-    SignalData *link_added, *link_changed, *link_removed;
-
-    /* Add */
-    link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                   NM_PLATFORM_SIGNAL_ADDED,
-                                   link_callback,
-                                   DEVICE_NAME);
-    g_assert(software_add(link_type, DEVICE_NAME));
-    accept_signal(link_added);
-    g_assert(nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME));
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert(ifindex >= 0);
-    g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, ifindex), ==, link_type);
-    g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, ifindex), ==, link_typename);
-    link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_CHANGED,
-                                      link_callback,
-                                      ifindex);
-    link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_REMOVED,
-                                      link_callback,
-                                      ifindex);
-    if (link_type == NM_LINK_TYPE_VLAN) {
-        const NMPlatformLink *   plink;
-        const NMPlatformLnkVlan *plnk;
-
-        plnk = nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, &plink);
-        g_assert(plnk);
-        g_assert(plink);
-
-        vlan_parent = plink->parent;
-        vlan_id     = plnk->id;
-        g_assert_cmpint(vlan_parent,
-                        ==,
-                        nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME));
-        g_assert_cmpint(vlan_id, ==, VLAN_ID);
-    }
-
-    /* Add again */
-    g_assert(!software_add(link_type, DEVICE_NAME));
-
-    /* Set ARP/NOARP */
-    g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_set_noarp(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    accept_signals(link_changed, 1, 2);
-    g_assert(nm_platform_link_set_arp(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    accept_signal(link_changed);
-
-    /* Set master option */
-    if (nmtstp_is_root_test()) {
-        switch (link_type) {
-        case NM_LINK_TYPE_BRIDGE:
-            if (nmtstp_is_sysfs_writable()) {
-                g_assert(nm_platform_sysctl_master_set_option(NM_PLATFORM_GET,
-                                                              ifindex,
-                                                              "forward_delay",
-                                                              "628"));
-                value =
-                    nm_platform_sysctl_master_get_option(NM_PLATFORM_GET, ifindex, "forward_delay");
-                g_assert_cmpstr(value, ==, "628");
-                g_free(value);
-            }
-            break;
-        case NM_LINK_TYPE_BOND:
-            if (nmtstp_is_sysfs_writable()) {
-                g_assert(nm_platform_sysctl_master_set_option(NM_PLATFORM_GET,
-                                                              ifindex,
-                                                              "mode",
-                                                              "active-backup"));
-                value = nm_platform_sysctl_master_get_option(NM_PLATFORM_GET, ifindex, "mode");
-                /* When reading back, the output looks slightly different. */
-                g_assert(g_str_has_prefix(value, "active-backup"));
-                g_free(value);
-            }
-            break;
-        default:
-            break;
-        }
-    }
-
-    /* Enslave and release */
-    switch (link_type) {
-    case NM_LINK_TYPE_BRIDGE:
-    case NM_LINK_TYPE_BOND:
-    case NM_LINK_TYPE_TEAM:
-        link_changed->ifindex = ifindex;
-        test_slave(ifindex, NM_LINK_TYPE_DUMMY, link_changed);
-        link_changed->ifindex = 0;
-        break;
-    default:
-        break;
-    }
-    free_signal(link_changed);
-
-    /* Delete */
-    nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE);
-    accept_signal(link_removed);
-
-    /* Delete again */
-    g_assert(nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME) <= 0);
-    g_assert(!nm_platform_link_delete(NM_PLATFORM_GET, ifindex));
-
-    /* VLAN: Delete parent */
-    if (link_type == NM_LINK_TYPE_VLAN) {
-        SignalData *link_removed_parent = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                                             NM_PLATFORM_SIGNAL_REMOVED,
-                                                             link_callback,
-                                                             vlan_parent);
-
-        nmtstp_link_delete(NULL, -1, vlan_parent, NULL, TRUE);
-        accept_signal(link_removed_parent);
-        free_signal(link_removed_parent);
-    }
-
-    /* No pending signal */
-    free_signal(link_added);
-    free_signal(link_removed);
-}
-
-static void
-test_bridge(void)
-{
-    test_software(NM_LINK_TYPE_BRIDGE, "bridge");
-}
-
-static int
-_system(const char *cmd)
-{
-    /* some gcc version really want to warn on -Werror=unused-result. Add a bogus wrapper
-     * function. */
-    return system(cmd);
-}
-
-static void
-test_bond(void)
-{
-    if (nmtstp_is_root_test() && !g_file_test("/proc/1/net/bonding", G_FILE_TEST_IS_DIR)
-        && _system("modprobe --show bonding") != 0) {
-        g_test_skip("Skipping test for bonding: bonding module not available");
-        return;
-    }
-
-    test_software(NM_LINK_TYPE_BOND, "bond");
-}
-
-static void
-test_team(void)
-{
-    int r;
-
-    if (nmtstp_is_root_test()) {
-        r = nm_platform_link_team_add(NM_PLATFORM_GET, "nm-team-check", NULL);
-
-        if (r < 0) {
-            g_assert_cmpint(r, ==, -EOPNOTSUPP);
-            g_test_skip("Skipping test for teaming: team module not functioning");
-            return;
-        }
-
-        nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, "nm-team-check", FALSE);
-    }
-
-    test_software(NM_LINK_TYPE_TEAM, "team");
-}
-
-static void
-test_vlan(void)
-{
-    test_software(NM_LINK_TYPE_VLAN, "vlan");
-}
-
-/*****************************************************************************/
-
-static void
-test_bridge_addr(void)
-{
-    char                  addr[ETH_ALEN];
-    NMPlatformLink        link;
-    const NMPlatformLink *plink = NULL;
-
-    nm_utils_hwaddr_aton("de:ad:be:ef:00:11", addr, sizeof(addr));
-
-    g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_bridge_add(NM_PLATFORM_GET,
-                                                              DEVICE_NAME,
-                                                              addr,
-                                                              sizeof(addr),
-                                                              0,
-                                                              &nm_platform_lnk_bridge_default,
-                                                              &plink)));
-    g_assert(plink);
-    link = *plink;
-    g_assert_cmpstr(link.name, ==, DEVICE_NAME);
-
-    g_assert_cmpint(link.l_address.len, ==, sizeof(addr));
-    g_assert(!memcmp(link.l_address.data, addr, sizeof(addr)));
-
-    plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex);
-    g_assert(plink);
-
-    if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) {
-        g_assert(!nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex));
-        g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv),
-                        ==,
-                        NM_IN6_ADDR_GEN_MODE_EUI64);
-
-        g_assert(NMTST_NM_ERR_SUCCESS(
-            nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex, TRUE)));
-        g_assert(nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex));
-        plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex);
-        g_assert(plink);
-        g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv),
-                        ==,
-                        NM_IN6_ADDR_GEN_MODE_NONE);
-
-        g_assert(NMTST_NM_ERR_SUCCESS(
-            nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex, FALSE)));
-        g_assert(!nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex));
-        plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex);
-        g_assert(plink);
-        g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv),
-                        ==,
-                        NM_IN6_ADDR_GEN_MODE_EUI64);
-    }
-
-    g_assert_cmpint(plink->l_address.len, ==, sizeof(addr));
-    g_assert(!memcmp(plink->l_address.data, addr, sizeof(addr)));
-
-    nmtstp_link_delete(NULL, -1, link.ifindex, link.name, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-test_internal(void)
-{
-    SignalData *link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                               NM_PLATFORM_SIGNAL_ADDED,
-                                               link_callback,
-                                               DEVICE_NAME);
-    SignalData *link_changed, *link_removed;
-    const char  mac[6] = {0x00, 0xff, 0x11, 0xee, 0x22, 0xdd};
-    const char *address;
-    size_t      addrlen;
-    int         ifindex;
-
-    /* Check the functions for non-existent devices */
-    g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME));
-    g_assert(!nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME));
-
-    /* Add device */
-    g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL)));
-    accept_signal(link_added);
-
-    /* Try to add again */
-    g_assert(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL) == -NME_PL_EXISTS);
-
-    /* Check device index, name and type */
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert(ifindex > 0);
-    g_assert_cmpstr(nm_platform_link_get_name(NM_PLATFORM_GET, ifindex), ==, DEVICE_NAME);
-    g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_DUMMY);
-    g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, ifindex), ==, DUMMY_TYPEDESC);
-    link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_CHANGED,
-                                      link_callback,
-                                      ifindex);
-    link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_REMOVED,
-                                      link_callback,
-                                      ifindex);
-
-    /* Up/connected */
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL));
-    g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    accept_signals(link_changed, 1, 2);
-    g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    accept_signal(link_changed);
-
-    /* arp/noarp */
-    g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_set_arp(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    accept_signal(link_changed);
-    g_assert(nm_platform_link_set_noarp(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    accept_signal(link_changed);
-
-    /* Features */
-    g_assert(!nm_platform_link_supports_carrier_detect(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_supports_vlans(NM_PLATFORM_GET, ifindex));
-
-    /* Set MAC address */
-    g_assert(NMTST_NM_ERR_SUCCESS(
-        nm_platform_link_set_address(NM_PLATFORM_GET, ifindex, mac, sizeof(mac))));
-    address = nm_platform_link_get_address(NM_PLATFORM_GET, ifindex, &addrlen);
-    g_assert(addrlen == sizeof(mac));
-    g_assert(!memcmp(address, mac, addrlen));
-    address = nm_platform_link_get_address(NM_PLATFORM_GET, ifindex, NULL);
-    g_assert(!memcmp(address, mac, addrlen));
-    accept_signal(link_changed);
-
-    /* Set MTU */
-    g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_set_mtu(NM_PLATFORM_GET, ifindex, MTU)));
-    g_assert_cmpint(nm_platform_link_get_mtu(NM_PLATFORM_GET, ifindex), ==, MTU);
-    accept_signal(link_changed);
-
-    /* Delete device */
-    nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE);
-    accept_signal(link_removed);
-
-    /* Try to delete again */
-    g_assert(!nm_platform_link_delete(NM_PLATFORM_GET, ifindex));
-
-    free_signal(link_added);
-    free_signal(link_changed);
-    free_signal(link_removed);
-}
-
-/*****************************************************************************/
-
-static void
-test_external(void)
-{
-    const NMPlatformLink *pllink;
-    SignalData *          link_added, *link_changed, *link_removed;
-    int                   ifindex;
-
-    link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                   NM_PLATFORM_SIGNAL_ADDED,
-                                   link_callback,
-                                   DEVICE_NAME);
-
-    nmtstp_run_command_check("ip link add %s type %s", DEVICE_NAME, "dummy");
-    wait_signal(link_added);
-
-    g_assert(nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME));
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert(ifindex > 0);
-    g_assert_cmpstr(nm_platform_link_get_name(NM_PLATFORM_GET, ifindex), ==, DEVICE_NAME);
-    g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_DUMMY);
-    g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, ifindex), ==, DUMMY_TYPEDESC);
-    link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_CHANGED,
-                                      link_callback,
-                                      ifindex);
-    link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                      NM_PLATFORM_SIGNAL_REMOVED,
-                                      link_callback,
-                                      ifindex);
-
-    pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex);
-    g_assert(pllink);
-    if (!pllink->initialized) {
-        /* we still lack the notification via UDEV. Expect another link changed signal. */
-        wait_signal(link_changed);
-    }
-
-    /* Up/connected/arp */
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-
-    nmtstp_run_command_check("ip link set %s up", DEVICE_NAME);
-    wait_signal(link_changed);
-
-    g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    nmtstp_run_command_check("ip link set %s down", DEVICE_NAME);
-    wait_signal(link_changed);
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-
-    nmtstp_run_command_check("ip link set %s arp on", DEVICE_NAME);
-    wait_signal(link_changed);
-    g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-    nmtstp_run_command_check("ip link set %s arp off", DEVICE_NAME);
-    wait_signal(link_changed);
-    g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex));
-
-    nmtstp_run_command_check("ip link del %s", DEVICE_NAME);
-    wait_signal(link_removed);
-    accept_signals(link_changed, 0, 1);
-    g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME));
-
-    free_signal(link_added);
-    free_signal(link_changed);
-    free_signal(link_removed);
-}
-
-/*****************************************************************************/
-
-static guint8 *
-_copy_base64(guint8 *dst, gsize dst_len, const char *base64_src)
-{
-    g_assert(dst);
-    g_assert(dst_len > 0);
-
-    if (!base64_src)
-        memset(dst, 0, dst_len);
-    else {
-        gs_free guint8 *b = NULL;
-        gsize           l;
-
-        b = g_base64_decode(base64_src, &l);
-        g_assert(b);
-        g_assert(l == dst_len);
-
-        memcpy(dst, b, dst_len);
-    }
-    return dst;
-}
-
-typedef struct {
-    const char *pri;
-    const char *pub;
-    const char *pre;
-} KeyPair;
-
-static void
-_test_wireguard_change(NMPlatform *platform, int ifindex, int test_mode)
-{
-    const KeyPair self_key  = {"yOWEsaXFxX9/DOkQPzqB9RufZOpfSP4LZZCErP0N0Xo=",
-                              "s6pVT2xPwktor9O5bVOSzcPqBu9uzQOUzPQHXLU2jmk="};
-    const KeyPair keys[100] = {
-        {"+BDHMh11bkheGfvlQpqt8P/H7N1sPXtVi05XraZS0E8=",
-         "QItu7PJadBVXFXGv55CMtVnbRHdrI6E2CGlu2N5oGx4=",
-         "2IvZnKTzbF1UlChznWSsEYtGbPjhYSTT41GXO6zLxvk="},
-        {"qGZyV2BO1nyY/FGYd6elBPirwJC9QyZwqbm2OJAgLkY=",
-         "v8L1FEitO0xo+wW/CVVUnALlw0zGveApSFdlITi/5lI=",
-         "/R2c0JmBNGJzT594NQ0mBJ2XJjxt2QUSo+ZiqeY0EQA="},
-        {"YDgsIb0oe+9NcxIx2r0HEEPQpRMxmRN0ALoLm9Sh40Q=",
-         "nFPs1HaU7uFBvE9xZCMF8oOAjzLpZ49AzDHOluY1O2E=",
-         "zsYED2Ef7zIHJoRBPcen+w4ktrRsLPEfYwZhWIuXfds="},
-        {"kHkosM503LWu43tdYXbNwVOpRrtPgd9XFqcN7k4t6G4=",
-         "b8e092WT+eNmnxCr5WE2QC/MXAjDagfG1g03cs2mBC0=",
-         "VXz0ShGWT7H0CBCg2awfatmOJF15ZtaSMPhMsp+hc3A="},
-        {"4C2w5CEnxH59Y2aa6CJXgLdDtWoNMS2UJounRCM1Jkk=",
-         "gC/R9umlnEQL+Qsz/Y64AlsdMge4ECe5/u/JHZCMWSs=",
-         "2bmL5ISr+V5a7l7xFJ695BLIJyBgx8xnxzybkxiRHOg="},
-        {"KHJSzFGkXcZf/wbH2rr99SYtGKWbL680wA2AcDE94lo=",
-         "BsN23h4aOi458Q3EgMQsodsWQxd9h/RxqskAUpsXfgg=",
-         "nK4Zv34YKEhjuexhq1SgK4oTd4MZJT5gcpYvEuPjc7Q="},
-        {"QGMulXJ9e3AVxtpi8+UUVqPOr/YBWvCNFVsWS9IUnUA=",
-         "kjVclP5Ifi6og2BBCEHKS/aa/WktArB4+ig06lYaVlg=",
-         "0+mmceDPcSRK3vFnYqHd9iAfY+Nyjzf/1KgDeYGlRkQ="},
-        {"AOJiDD4y6GA7P7gugjjQG9Cctvc5Y27fajHz6aU3gU4=",
-         "gEnHn6euHtcMEwZBlX6HANPeN9Of+voBDtltS38xDUw=",
-         "wIH1OxgX6GLxx/bnR+t3fbmjGZDTU3WMxp7t1XGezqM="},
-        {"COsls2BlCltaIrrq1+FU51cWddlmoPPppSeIDunOxGA=",
-         "+n6WuV8Tb1/iZArTrHsyNqkRHABbavBQt9Me72K2KEc=",
-         "t4baiprSO9ZbKD2/RutOY9cr+yCajQWZGCTnQdrFQj0="},
-        {"uHawQq2BRyJlsTPoCa+MfBVnv4MwtRoS+S9FEpFOEVg=",
-         "8lcmr27afeb6iI3BQCaDtvalF2Cl7gxRZgs+nyJ/fEg=",
-         "Eh9o/6W60iujBLIHuRfNrPhOWAn7PambT2JRln9iwA0="},
-        {"yL7hmoE/JfRGAotRzx9xOpjfrDA3BFlPEemFiQw40Wk=",
-         "BHK0PHi5kp7rOfQ46oc9xlVpB+pZeZYXTtH7EXr5TwU=",
-         "BS2h2ZZyW0BlYMmLR29xyHEcZ4jtO7rgj1jkz/EEaxU="},
-        {"ON8YrTHQgoC5e0mAR9FakZ8hZ/9I7ysuE21sG546J1Y=",
-         "Bm3l5I6iH1tDrv6EgdZU9PzHqp0H26Z6ggmmIypwxy8=",
-         "qKVfbCnK1EI3eC28SsL+jyBnEnIF/nRJQJzDevBFdNQ="},
-        {"KGLO0RI0VlQFCG+ETUqk25HdaKUnUPXKOKkTh/w8BXU=",
-         "sBDBwQFC7k8UMdMzuavKBkBjYYKigzvYmGF5rm6muQc=",
-         "BNfZF9d7540pUGGOQCh3iDxAZcPBqX4qqM00GSLPBek="},
-        {"KGdWyEodIn7KKI2e4EFK9tT6Bt3bNMFBRFVTKjjJm2E=",
-         "lrbjU/Xn9wDCZQiU8E5fY6igTSozghvo47QeVIIWaUk=",
-         "LczqW48MW8qDQIZYRELsz/VCzVDc5niROvk7OqrTxR0="},
-        {"wO3xinUGABgEmX+RJZbBbOtAmBuPPFG6oVdimvoo90w=",
-         "dCIvTzR6EerOOsRKnWly1a9WGzbJ4qc+6t3SSzLgWFk=",
-         "wFj0zpr5PadBoBy0couLuZ1qudZbXLbV/j3UT+AyKeo="},
-        {"+JNOBlO4tp9vvQk6UO4r3sILyEgjl+BBoWketZufyn0=",
-         "Q6LSv9y7YQkJEzQ/1mpjJEgOrO8GYPUTgcizjh7Cm34=",
-         "kg7AG9MuN04xPJ5Z0IcNZ4a8d1b/n4GsGIeyA4FaaSE="},
-        {"+EJcThLRwjZ+h1CNNFu15HWzznf4u/lPVw8hifTm2Ec=",
-         "Kkn2jFqwBzyIFQfD0OpmePFSmBYmhKagv4pGgkqsWgE=",
-         "jYpxojj8WKYe/XIXMP+uv1Fv0+TKrs83tqfzP0AGdcI="},
-        {"+DKFqSMNFmxriEFj3qatuzYeTJ9+xWYspZ4ydL3eC0Q=",
-         "3o37bsg6HhRg/M9+fTlLcFYc2w/Bz9rLQySvvYCKbRE=",
-         "Jb9qoDIBat1EexlgfpRbXa7OflptME8/zt93bldkiVE="},
-        {"EH3MjFOMqRoDFQz+hSlJpntWBeH3lTk6WPjTIQjr42o=",
-         "PbPewED/nxSBLdM7AXMj7uS3bCgAAg8M6F4iPLd0b1U=",
-         "pj4+UgOGkpJwlRvX5BRXZzmzAUnDtUtJsS7LzbcJWzw="},
-        {"kL6M2KvO+vPBLEc/a0DpEHTibQ1bwaMRT9b9SkzeP0Y=",
-         "pS3G2bHHlkOE6UHP0qVitDuxXgjEaZTviTjNc55RbVs=",
-         "ZVZpWOtYqhX3CpF1kATg/38J6pvUJo8AS1sVYjs3rUE="},
-        {"sFlcRLDn36fnew2Ld92IHJwnKifdS3aF1MWRPs6K3Wg=",
-         "OpjUOTiWExaDYULTINB4yQFqc3mnU3RjQzGRV+KtdFY=",
-         "of0V/uoFRNljv/XTt/tXgoquLRH93Ty0KNiaPUpEi2w="},
-        {"UJ8hjDsg3jfsnnfPH8Gw9FnCb6taTuviurAfZu+kEFg=",
-         "3byjHksUOv8CNjGGKvHvvrJDURBhCIL5UtfZbgyVWCE=",
-         "9f7dbWif51gGrE7R9LeuewQSrvGFGTOB3ceJC67jSkI="},
-        {"iFFPKGIfqeUKY/w72KAZSjd/PGTqCakHYBV10xMDfnI=",
-         "ehneHATNSXtsJTOiPjVSc0QARkihgcfcvoXKFWKfQnI=",
-         "yKdqDBcRwA7RCg4GiY/b5IsWcExPleOBde/hjxc36a4="},
-        {"GDGocdPJTPUAllxQo7SpXZKqMPn7lpxQELQUX9ETHmE=",
-         "n0ScNEou4ekfrXRRXvcADLu2Afj8g5D3TuDP/I4KrnY=",
-         "8QhswqAhi/ehhcmCwQF5aSh80TvIGC/gRL5jBn5wOH8="},
-        {"UCcrlN8fX2ZdNdhaEBNwktwL+H0ZO7fhaj7rgdUutmw=",
-         "LF8J728ilXs4TphnrgR6r0p7W3912DYnsXkGMEPQnRE=",
-         "cYfMjxl2REYir7frGeB0u+NHAaFYF02ysgpBhOL5ygc="},
-        {"SH0657XuIiHidVmViXZF30RUWtkuWXcWWHmKZHTiOG8=",
-         "7k6j49W1u5qgLE5MQUc1osPVW1oPPhzjrGvJ7o9YamY=",
-         "dV2+7rNk/3LR2IcwYg/c+Wvzep1yjY7/u1I+nnlTQ00="},
-        {"qFQWs6jzrscV42pGISQyA7JDvFFAvEQCWJi584VHD2g=",
-         "AT63nHKLC17yUvkR4lOVPxCr4DD3QhXmcmecOTn+Amc=",
-         "2Qe2fwJbFcu1CmKpktElOFkSQMqlyvlV3ZUIAd/Dcts="},
-        {"6J+yLxgPwWtUbk9I3zbeD8RuK6XkQjJ0wTJ1zSVhflQ=",
-         "NJzMBYyPZjk3eLmgdKaOeWyNER5YZF1mR8Umeiu9f28=",
-         "pp+4+XHw5ZmHGJ7WbZ1xLYRsnTI17QIbb0bzHzYZrBs="},
-        {"KJGoWYNVDUWcEMg+E4tljv1LiWAbdRw2QVapYqdFa1Y=",
-         "M2SGk9WVnzYNGnT777G/JE8uUsY2f7mszTwlue73UDE=",
-         "Jg8N7GbhbYB400foFP+OH0v+hCaL1jW61bajSA6EZqc="},
-        {"uAgrgppPyIvk8S1CHUmaCaORsgFFfBreB8pxXmbSdXw=",
-         "dJ22bER4fD3qF2/yIGWQ7SgmZ990sy/SbANjmUMkzws=",
-         "mKkd0OoAR9sClmD+k3fL9weBsoCy5GQGz9BP0kAQIjc="},
-        {"EI3Q8gePNPrtFyoMcv7hOihQgroF/dfjzPn8yvpGPWQ=",
-         "Y9QhJFeiyuuIZNPU56B6U//ZK+XTTe4EP7h/p3Q+dE8=",
-         "qBVUYw9rTWaxn55nUd55NpCWtxOUSWLt4WJGusiDS8Q="},
-        {"oEQvdRm/yHkx+JvlhHGT5RUFrFEUleKb9DCT55EqZ30=",
-         "8hsh/UHwWADTHntOJq4dy0o7ahcNAAlo2rDpjzzrVXk=",
-         "/GF2inW2mPtA26IgFdgOEBbBEerT740wWuP/8NyANdc="},
-        {"6OWrGKZKNsgfRezSUw29EnHymcgKyEKvX5/pZQlLmWs=",
-         "oaJeO6YSS2dodNEf97DvgWrYnFFelG5daEdN84jVVGw=",
-         "T5wvTdyVxK0LY96kouLjs06oUfhGChfty8OUL1Mddro="},
-        {"mPmzQbh2R+r1DC5hSquzKM1SDrxUdfnBPRPJrpqrgkE=",
-         "BtUHAnYWjDjBI42qBf9dJqezTUikYsF96o6PKEWPrVo=",
-         "MxU8EMmq+vVHpuK/AkFZrZDF2b+VbSqukZLPbNsCcgo="},
-        {"8GVxuoo1Veyr+nqxr5Q4vmsMf5qfiXwSlQ4q3+BU60g=",
-         "uSOLe/E9/OjIgUOk0NMBHB45E0+q4Rd+IUO2UOxmKlM=",
-         "+30F+56OE0Sr3wY2clKw4kgE+2XiucMg7xjK6EemXuk="},
-        {"qORPKb+qFuU/9TpFbRUupHsqm9iyk9pa6cpik+EVDkg=",
-         "bMZxxd+Z9I0XA1h9U8JEY+/mRxWGnvbXDZ5Dxz7YzS0=",
-         "SmkkqOz4OhHuSL6cxuRm9+Mlt50Sfd0sMDFTC78gqOE="},
-        {"2Ko3IYhXKcdOMIJGNpASk9saNSZsI64lyJPOoxpQ2kI=",
-         "xVOc9PxY1VFaZfemmKi+Ei2liHhmeTu+JMa+rS00gnA=",
-         "+398DlW8kWeI2aRaC4QfcrEjwqPKCohyDeWdaI1wvv0="},
-        {"CPioGCVpxnym62nH/QoCt1RiiaaxUcuFjvh5kRhjqHA=",
-         "W0XxlBLrZgFKhggMvvv6oFf/RJbfs92qv8JK9e+5i2o=",
-         "bsK2U6CRAUv1uVgYQ7NpqjWWswFIDiDPDEtU1XQygSA="},
-        {"AF17siKaeiO85hikYN0IWCMGWqPm1UOoCkXMltJGUVk=",
-         "B+PFos9aN2S5bLxzGZHljRZj41j3rIx8RWu0vDUzq1w=",
-         "Qb8d6iDYv3m1h7PE8j0Exl2cSwpHkim/fJ1S4P7MYvY="},
-        {"wMFDBTJzx5tDCBhMkrptYJ8w9EeURjc4xeDQpevxAWo=",
-         "4ec439EXE5WQzvtV9reSX+aMmdq5k7o9Ayt8oQp+RhQ=",
-         "jwQlvdNH5WtSSU10H+fh/JisOlaBaohDPEp/BYnTt1Q="},
-        {"4GaJpIFigNDwd31O84pLIMM/o2qhp0ydlI/ydD/2a2Q=",
-         "r/LdkCoK5/BPGdq2+XJO8sCRhI+8ULFmg0887V43PAI=",
-         "Da+3ZZvEJdx4TYFMIDUlbkmytILnSTNxTKX+sQdjMd4="},
-        {"gMnojGqCLmMfGp2m31xlKZ/rIV2b8ockw9DPahRyu0c=",
-         "H6tKCTosnM4BXKqflXrkTdJyNlCIZhQ3ZRxfrvSdrDk=",
-         "4Z6K3LKIMV89plcjMb9CzSzJl03SWRe/++geBMZcOtY="},
-        {"wKCg22aNNoHnDJ0oAKE46FcSSsREW4AaGn5WxCSeXUs=",
-         "9NDTFC0iPt4HbbWepLHhN5poNTN2fdxJKNadsNT7qzY=",
-         "GSVTOCnfLpJ1VCOLHaKSjCMv7/OlcnQiP5+5woqkud8="},
-        {"oCoykq7pcJcg2X2V5TBRzGwn8hzzHC05WUreuotdznY=",
-         "DxfwnbMqr5Wn5SAyFolfEmNQT6l84Oq69ngpg6H6Iio=",
-         "p1RHBuqhuDa1MAQ2lbqmUQFu0CTwYlf73fWZSj9tQhA="},
-        {"UO7YVyRUVkcKr7c63VWWV2zj36XD3HyDfLZCqvrZmFc=",
-         "360lzYtIyHq5lv/QXSCe4bL4G2J1jBXFJ8yS+Ycr7Bc=",
-         "RRPQ1XWF1HN8Us4dtfn2eemdjgtWm7U8r7mM3y00NOk="},
-        {"eCGFYV/NuGP4H552E8Of1xU+3IvZxGyX+p5UFGW8iHI=",
-         "LqhZ4AS9dQ/MhsQnE5Oy7Q8INXY+P+mrfGY5dtg9SlE=",
-         "SICfqs8T5wP6IzATDCT4ovamBKPdkZ7JP4Cfsb3izec="},
-        {"oI3HBZknoIMMZw1BuYMkTBylt25reX7AbCqtWQv8cno=",
-         "B7dUgLgvQhi0RGmvaMrmf26WdjEVrhaiBclVkCKd4AA=",
-         "5O9K9pLXwxFAt5lfMWh4qGbwX1BM7sz0QGYxAnR77dk="},
-        {"sBfYn14EFVIS2M/E1aahP7mOmRNbNtyDChDMS1s6aGs=",
-         "FLYv0ZvzxMkc9A7OzhC4P1ZRu1aKIQd7u6gqfdekC3c=",
-         "kaYLcNCXnCLgiB8fleMQuboUJsj5u3YAmXL9x3ywV0M="},
-        {"qFwZESU/XYZXUtxwrGsFU9qPAFTzjm7EhTS1Q6ajGlM=",
-         "hraQQaqJCkS2yQXv+ccMOVh9V9a/qgSZJgdMAhrt8ms=",
-         "72oDfnWOn39gdk/ncw8Lv267I0I+m73SwxrpYojpWYk="},
-        {"YHhp6Zf/miuc2QXeI2lTezy0lL0pTv2b+nWNkmjYQWI=",
-         "UhNO5arLzF0WlZSgNOx7+IjWN+GSxDdQxZRp8uIwsyI=",
-         "1Q39Nzv2NGI9zWKWMpYLURAMZUg+FP+OboHHzFU8Anc="},
-        {"mLBBXKaCJ+7qeBZpS3wxGi/SQ4kLzun+K+QwwdwfJVQ=",
-         "gIq/nh7NwCJ36MvRnyrWHaRWu8lTmwfN2NvsjVl6SXQ=",
-         "AahcNR91GDyJBIP+vC8ZuIV8ukqjSGtd8s+cmjVC2Ao="},
-        {"OJG4LZlNNngFtAEQdbVVWVm6QAjOOauGcMZGbQrb40M=",
-         "pFHAC6HaWAOtvTRRVfSHvzG05mp4SJZXKsN/tkSF0kM=",
-         "IoXT3wIqWNxQhYuHWl12ODq/P7RM9LwaqglhmjKg+0g="},
-        {"OOwBFOQNhepiqDf04DehQLh1gpBNOluDF1ia752Yfng=",
-         "u715uJ/XhdjXjThCTJ9w6zzXnIhp3VCxhtso1wk+oBQ=",
-         "5x1Ip3Ym0KzDjGhiYjmpeWWr+dgrZlYwfr02GngPOTM="},
-        {"eNPFnwkQy1qw+IjFAlrDA6+sIsxbWDlzbNSsBW8R1UA=",
-         "OaOXaAfPb1MRpWadawFje8YZ0oxJgdCIDIP8c5X+r1U=",
-         "NtfaRRD0GqujnaQQoNoBbtovgO4dfVwEmEQx/YgnDpw="},
-        {"OLdaZItbtxH3mGqItkibIJp7KV27FrQavjhd5zq6s3Q=",
-         "SLSmAYxkMCGj0DO35cMLkC3NVAqK2VmVFndbOZEdA24=",
-         "SnBO68XQTDjxYbmYaAeEHgLwD2u4D+BPT86raRuUQZM="},
-        {"UBQOEz08izwr4eEK/SnQUpkt+TxCjo6Sya/XOGMLOE0=",
-         "wQwrwezI9LzKevGsJJCBHDG8noR0yIEtOK5Rig97SSo=",
-         "DpyS+0d7lrlFWkztsniG2v/j44vcuvWz3sPeghRyb5A="},
-        {"mN98iuqUKh67ggUdq9ZIQNZCZM90fgycTVqYKEo+DkY=",
-         "GYdXVW1jpS0dN1q9zMehubP7LfYqs34kszN0bXQqxxA=",
-         "AJPIHffB4uvvJJki4xCG0VORVBbF6bc2mZQqUx+idPc="},
-        {"OEd/1it8C3o+NOWxDI3DfLMXVBHJQg15N3E8F8d99l8=",
-         "QL1NcuUkoXxDy7M9VjGslCejcUlnUDHRghFVnr+8fmA=",
-         "nven9Dicl8U6QXuDO8rRNtjd4NYaa90SU+Gmv435XKY="},
-        {"AFMCGDu2oAP68miucsi4fmYX2KeRZnsEGv8tQm8JEng=",
-         "1sNxvk8uZhFsBUgxOXmuCMjDAgBbjVeWe9oaFk5Osy0=",
-         "t5iI5XXd56S5q0Y9HC91gzgF9uGjL9FIy6NUaKqkydo="},
-        {"CIAwfJghQHHr4YlztN9at6/iWkrEVCGFAxNVuQCuT3I=",
-         "zpUOF1h17g7RpBzrVlN7oTRz6e+dxcDL8OsAtHwgLC8=",
-         "kOSwC1p6Uoti9E9Eg7ViPZwCytuvp5Fr5Buw677aogU="},
-        {"sC8vrAVBU0zvhWDRfzfySjvopXm2/cTMkTLmioyO3Es=",
-         "p6H7GWm8NfgyO5OCX/COjvVT4MAnTs9ZUj4uZMK8XHA=",
-         "9Tzqo57V/h7+6nSNAHSBKdmU7ultlvZbAnNKSRlrLi4="},
-        {"eI63gjxCZGnzqZxPEi/ifYphXhxIRI2ZxK8jzqo3mmU=",
-         "XyNzEuU9x37fxFCnrZH89Krs5/UqGVx5wNkGfQCAYz0=",
-         "vZ2fTlRPnJQ+q33YdS5p1aweqPGj/kTMc4Uq80FtFjI="},
-        {"aNJlGtm79/RS4SQ/PC4YM6LFo9zAqDr2/RjLqk/z/1A=",
-         "lgZ9akPrABmfHQMlfNFnnpAJzGtcsaU9mUjEYKfzZHc=",
-         "d0Xt1Bcgphd1HMI0RneA4VdBbMZL1qNGJAvFhb080eA="},
-        {"oONSnHirNh3cuH93Ty0C9AXKebGY+cdF3R0DtPzIQlo=",
-         "TuREKfA8EVQiYWsPx8veUzjN2cz/b72limSLWlrCWxw=",
-         "vEqqKbpZf0EM6EApMUaUH65r3Zr81Y/DSODhE4H7U3Y="},
-        {"+D6RyLEaHJ9YF9WDyOlwh87KaNJcc6lqX8Arp6yqHF0=",
-         "EpecjfIo1/EEbmsgUtzEDqLu2ut+SMmzqaBL9Z/MlCA=",
-         "oYfO6/7XQgEYT9zmr4sqFrk0muK/fEv3FfD8MzZzjkE="},
-        {"OCmW5KQql2PRMJnsMYQjXlr6TSYUbxJBknqZtXJPSHM=",
-         "ZZR2ghHlCwAJu/XlsEZuNS6XiGPwuXzyMPPywYFapVM=",
-         "fqSCXq+pKJJ6yNvlOi+tyQ9E4Y6kc4kblGrVqN2WuXA="},
-        {"APWXDAe8d2ia1CUbf/IzSPXOUjR8TVuJgmISiWw0/EY=",
-         "jrT5P5YCkG+U7cfNTvCKy0GSEgsjwmJtHg+8HBP6ZCA=",
-         "t75aUjZXMPir8Ao0yhVClh9/BdWxSL+11CjK3iELNWk="},
-        {"8Nw4sRis7M/6Om+3w5YHXthyMzLGuP48teqdzbHNPlA=",
-         "lj3q3ZYij3ZJ/QunK8n9I00cv/Z+O1TU1kFFl8x3DTE=",
-         "adqB79P7gbXEYYnSd1/UPCwFffTAPXa9kHWynRBYcGo="},
-        {"yOupps5XbjV0fIZKnGhrpcxB7yDQzbBILC0UMJyVS1c=",
-         "+MDV/t9UCIdgm3IkH3BZlxaRPJ3lejRmrm4UPApq4mk=",
-         "AOJPmQxsU6hjOd+9mHnF0VL7Afih3P1Fr625xFT4FtY="},
-        {"cD2DEl4MBwONuTV0db5XreoVjQAUZFNXqIeFEU3KFkE=",
-         "2CeHrjN7tBX48k4Sgv5fIHG06e57q/ucCL+8DIRmfXw=",
-         "3EUo6MRzs6rSoY/7AFs8wiBiTXPcHzerLh6Xp3aMGKo="},
-        {"EA+S3a9ZeOLiRbhTxaT2wkpyDheAmai+UJa6SFGzSm8=",
-         "GGByUKZx/FPa2OkJoqVTHXx+6jrIpIw5rf0rp43MHko=",
-         "BXoDA3yn0JcMV7hHVzEqhlwAORvhToFO1qG00nas92A="},
-        {"eBeJi/imBiV52WEqrwAprUQggqdQmvTTmWtLq8pDDkM=",
-         "zCX26ZTOZHLpq5x5aIUL1XhIVoXJLp/zcXwnmFA3jBo=",
-         "Dm/DCxXWYXEsmQgxAD3KREK2PF0bUSnV5WRAaya8s1I="},
-        {"8C7p+EQO+CnWUSjHVu3PpeWpUIbLy48zpftZu021plM=",
-         "DxpnF/IbKAh6kmWC5Jpj8iw387EDkrvjsjOb9fbTSng=",
-         "bGrk0OshJB+0oQOK0QGKU8+lotnIDz3oeUnMZGienyM="},
-        {"COIez7YcBJiOJCLxxWV5UGLW5/o009YI0aszlD/PiUc=",
-         "eD9USWV37LFIOxlDSHyOmfFqNJFpORRlzEI+HoF/czI=",
-         "n+/ra86gUSF2pNZS51nt2JgrzXnQJl+dWswOq/Ahs94="},
-        {"iBBSTG9VLC+T9+ahNaQ4umZoig8o7w1DaeOw+cD2BGc=",
-         "XnAxqDlvGnQ6aakv8ABGHVj07qVQfk4NChZbstTMBxg=",
-         "7KKSwu/4yWr1UzFmNMGtiaSwdYMhP/HKbrQLlABL4UE="},
-        {"eNmwattflehr9+KsVqTuwt1YaAc5ONkaIaTQt9Gkhn8=",
-         "1NNVvm++YTTGMKyAXfGOCZ4aDDdFFH5Um3vAg4XimDo=",
-         "bXNrnDTP0pBay9ytZe7xpiKoSi12F7WUXqoIeI++Xvo="},
-        {"QJotpmZINx9eptKpkh9j3JlEDcHdWnjEbicdBS7gPXM=",
-         "3gLYKeoruVZ/AYjym0gciDvRHj45UIWyHhNjWj2Wj28=",
-         "NwuUkkE5yOWT7wed7bltgAk71miz3cSooiIDAdv6kKw="},
-        {"OAYGuxH70OPQvhVIX4BhSCWUyzAI5H2IkYxKgC/AO0M=",
-         "Rj9iNF/FagkXfdLPqc9LHfaoGR8GlvY3gun2FilE508=",
-         "hkNXLVMlBRsMEaQKkSzevcEK2sMu0AShGKQJMNqdzWM="},
-        {"uBrgZ7wLHrOV/0dNiEqo7FjY9VnJqL5eUDHJWAc9QXg=",
-         "3Hnln8ZHfSaK4OzESJe5U6NcLaW56wzfZICzvzefnSo=",
-         "DhXsehe5FAmbUidXT5ZpZIAuu1eF9rkU6cF3FBoKwOE="},
-        {"sJknn3CHvx/812EWU3ddLdLLZFBKsc+wx35GXyiRsHY=",
-         "qqa2dNSt0jWozGyqpokP392H5/DOAUUZmUpyZDaUEEE=",
-         "1Dyz8CvmF17oKT/wG2fu3vRzPzgQv8/OY9GJYew4FG8="},
-        {"yOumS9HN68ZwIm+5hZol3jFQ0DB4SKuW/ld3y8wioGk=",
-         "6PowsbKj/fKSzXZMAfaSkP3fE+4AThL9xm6ysQzMDxg=",
-         "vF8cKu9X9FxgCjyVZ5RG7nuue8RelF5Qsb8Efme4M4A="},
-        {"mISm5vQfPdK72SsaHh6O1/ARvaWCtm+KZNcpTsyt500=",
-         "YCORDQDpb1U8vADdstBgXkg0N7QaAc5VoXJ4QFuA/UY=",
-         "JlrBmfaCgbfEVD9YQq3c03WwwsHWc1nBwp1JkFORC3A="},
-        {"cPyu3Qry6qbsiOJKFGRziZ9LJWJ47k3ZSXiGkQXuQm0=",
-         "/cmBZTbqEp8sababPAxGb3OvDAEE7MlwPOwEFHE+7yM=",
-         "lp0Hhc/rVtpT5FtLLccChqDl3El48XtP6Wm6JwjI7jo="},
-        {"YKsMYU0SINbPwWw4RDCJV6GnzDlSp1ZNwUw2euGWi0A=",
-         "/KmBReATQbFnLg8YKV0jwhqKeishRoWvlVtMX3550Vk=",
-         "7fXpPSMo1Fw2sOXtjTtvFU+DbZvS/FWB9wAsywWx6R4="},
-        {"WD0YI3y71eIp/GXw9i+7scEiQKSBkGihZWE+s6fGmWo=",
-         "RdthAL/qPnAZFb3xBgRMiAtGHNjgokzoKX9iO2K5qhc=",
-         "4dk4HGkT9dBmomGNorDE/hLr/HEFhljtl4zz3M4sG58="},
-        {"oD8KWhJYZVhutJRb0kZlZnB22QUXzi2FfPRD0ll65UM=",
-         "MYTBGHh4Ukj97pKj6qcfWmxGNQzmU3/aBOX2f1tfhG0=",
-         "VT1gC+a9nRJzYMi/TPvRVnn3IQlaop/jKmmxZePEME0="},
-        {"0Ns/1SOiqR2CpHRG03QNzJJd5gxTm1XJmSkFlugjQ3k=",
-         "KvQAI+ekNOa2xfEvfyc9JGcS+CTUrnnhsKrlyJGJixg=",
-         "J8LmSX6zElX3S9q4PNvh2NKUtAiQ3oHiYjSJ7yErPlY="},
-        {"mD6TeF4ezSPXN/csN1OhoAREFSXllI+zl4DUOInVq2Q=",
-         "WmLJ9ep2EqFcSftnYFJsmWyUxqL0zzuSzVEv94PcISM=",
-         "U2+ILy2NDmmfgSW78C8dl8GyHESUc1lXPHPpg5F+gr8="},
-        {"SMJoXOYgHz8HSzY+ByeWLcSP5qFwv7YjRe0bcKesRnM=",
-         "DEsNSOY3TEs9J2YgqroQ4xKq8T8xNJQjvvE4UrTItQw=",
-         "Bws1Hk2+lO+JQ7ME16EbwAdsBkWsGvti0Gb6LY2Lrms="},
-        {"iGhXF0Hg0tqZmpwAMiolxvbvTPClQ7LlBAspSSyFEHE=",
-         "7Xxzpwl7yRWehHNWTYVtFkdChJdXhtY4Mtw1fA9QcCg=",
-         "Swjfv0PjuaE8Oq3a17BVno5I+q49dZlPwKK1bPUoKNI="},
-        {"MIazjx3qTi6Qz3WzhtCPw3i4Q2uZBHcuMoh++ZGFYUk=",
-         "oni8pbFqk9Ya+Fx+911Nl1SN0FD/hR1jwb2RH3t/pRk=",
-         "ZYAFcj67LkbNURYbSnCCWGxAG8QLDGWwbl968mA6ZA4="},
-        {"MAadYdiFM2cPuJF19q20Yoo5KJabuR9TUQ9jG5nvA1w=",
-         "5OcE8XV+UPoBVbgqBQdVF62GZCW9DOQEdxrQsktPPBA=",
-         "FCZsEFXouy+xtxv8X7VroXtvPG1Z1HFHL724tz1jcUI="},
-        {"+GwxMmD2dee5+QmvXNI0NdP+rNWoSXTN42otbp0aZ24=",
-         "Y0N44baz9ihclCUnv6rRbDqCYu4BxQlBfNnTz3NNe2A=",
-         "/LqSgkVQNkQ/oBiZSgpM9Rw7BJv0RvRpEQpvlizvHy0="},
-        {"8FREpCtncOcT7+W2nW4aYSjmSbADtVSH9rIliQZZUH4=",
-         "fTNSd0JeREhXmPfjrmrAu6Lu/yHkB9GyxR3SyO4kZ28=",
-         "262KN/iG/iJEaZeerFm1yVtvhFVGgQFwSvtxTcjZzeg="},
-        {"EDhaRQGtscjoSE9wJOnSXoQVtVruIqyzknty+x/vDWo=",
-         "eMmMgws6ZxDIxZ6QSwGjZO1Mx/r5T+fJjSTKGMBk/BU=",
-         "0CyaJV6AG9bZ0C4yeZ/RDsOs9BdNqZpUxAsD30WmJO4="},
-        {"CJV0UB2YdvVDG1cs4oiJgHAS+f1FocGr/vGCfiovsWQ=",
-         "9/O9GWZEOXVm7On8lftL27PffRORju8OKl6gZd/74CA=",
-         "A+kXRVNOwIrA5DUa+3v7dpRC+Gbxm23LTiYmOUAXUyY="},
-        {"gCjDsJUwZGA7BjYVoCQsvdIgN9Q4lBHlSyKwUrl751A=",
-         "HRwS8T9y2qPYk7JVU/8Y+6cS+Bk8XCLCXxwN/ttbQiI=",
-         "iFotjA6rhUfkDv4S/wspJgEWunEmrlGSGsXcJ0+8laQ="},
-        {"6N5pL4gsuK+shHpDxirTnAGdyKXIlYHyfIhtB0njJGA=",
-         "CVZvW7NaN2XMEEKHodghBA9hLCwee/jrmttiWh/CmEg=",
-         "OpPEd3Sp8r6KdjNDTN4bVHETlGJ92BCK74FCdEaDe9g="},
-        {"UIPPTUdvhlg8qEDv6JRxM4/8F5ORjJz4ud82QZrgeEY=",
-         "7Nd13z5EpB3ChytvQC1CxvDY7n0H8r2Y7lzLEY8hdEk=",
-         "b22PvgU0M2QfNC7ZGN+RXNe5fjOzMsY32IcHTwLNIqw="},
-        {"oBn53Q5fmxKX02PgI6F47Rb+XoLeFQO07ok2tYhk0lE=",
-         "e0gtPDKXCZSoNW1uHqBPQXLfiYgyeqPMU2zZJgPXACI=",
-         "wmjW2wDT2EzFkyaGui7YWNLTRu8Q4eD/GVKM2utZkEs="},
-    };
-    gs_unref_ptrarray GPtrArray *allowed_ips_keep_alive = NULL;
-    gs_unref_array GArray *peers                        = NULL;
-    NMPlatformLnkWireGuard lnk_wireguard;
-    int                    r;
-    guint                  i;
-
-    allowed_ips_keep_alive = g_ptr_array_new_with_free_func(g_free);
-
-    peers = g_array_new(FALSE, TRUE, sizeof(NMPWireGuardPeer));
-
-    lnk_wireguard = (NMPlatformLnkWireGuard){
-        .listen_port = 50754,
-        .fwmark      = 0x1102,
-    };
-    _copy_base64(lnk_wireguard.private_key, sizeof(lnk_wireguard.private_key), self_key.pri);
-    _copy_base64(lnk_wireguard.public_key, sizeof(lnk_wireguard.public_key), self_key.pub);
-
-    if (test_mode == 0) {
-        /* no peers. */
-    } else if (NM_IN_SET(test_mode, 1, 2)) {
-        guint num_peers = (test_mode == 1) ? 1 : G_N_ELEMENTS(keys);
-
-        for (i = 0; i < num_peers; i++) {
-            NMPWireGuardPeer       peer;
-            char                   s_addr[NM_UTILS_INET_ADDRSTRLEN];
-            NMSockAddrUnion        endpoint;
-            guint                  i_allowed_ips, n_allowed_ips;
-            NMPWireGuardAllowedIP *allowed_ips;
-
-            if ((i % 2) == 1) {
-                endpoint = (NMSockAddrUnion){
-                    .in =
-                        {
-                            .sin_family = AF_INET,
-                            .sin_addr.s_addr =
-                                nmtst_inet4_from_string(nm_sprintf_buf(s_addr, "192.168.7.%d", i)),
-                            .sin_port = htons(14000 + i),
-                        },
-                };
-            } else {
-                endpoint = (NMSockAddrUnion){
-                    .in6 =
-                        {
-                            .sin6_family = AF_INET6,
-                            .sin6_addr   = *nmtst_inet6_from_string(
-                                nm_sprintf_buf(s_addr, "a:b:c:e::1:%d", i)),
-                            .sin6_port = htons(16000 + i),
-                        },
-                };
-            }
-
-            if (test_mode == 1)
-                n_allowed_ips = 1;
-            else
-                n_allowed_ips = i % 10;
-            allowed_ips = g_new0(NMPWireGuardAllowedIP, n_allowed_ips);
-            g_ptr_array_add(allowed_ips_keep_alive, allowed_ips);
-            for (i_allowed_ips = 0; i_allowed_ips < n_allowed_ips; i_allowed_ips++) {
-                NMPWireGuardAllowedIP *aip = &allowed_ips[i_allowed_ips];
-
-                aip->family = (i_allowed_ips % 2) ? AF_INET : AF_INET6;
-                if (aip->family == AF_INET) {
-                    aip->addr.addr4 = nmtst_inet4_from_string(
-                        nm_sprintf_buf(s_addr, "10.%u.%u.0", i, i_allowed_ips));
-                    aip->mask = 32 - (i_allowed_ips % 8);
-                } else {
-                    aip->addr.addr6 = *nmtst_inet6_from_string(
-                        nm_sprintf_buf(s_addr, "a:d:f:%02x:%02x::", i, i_allowed_ips));
-                    aip->mask = 128 - (i_allowed_ips % 10);
-                }
-            }
-
-            peer = (NMPWireGuardPeer){
-                .persistent_keepalive_interval = 60 + i,
-                .endpoint                      = endpoint,
-                .allowed_ips                   = n_allowed_ips > 0 ? allowed_ips : NULL,
-                .allowed_ips_len               = n_allowed_ips,
-            };
-            _copy_base64(peer.public_key, sizeof(peer.public_key), keys[i].pub);
-            _copy_base64(peer.preshared_key,
-                         sizeof(peer.preshared_key),
-                         (i % 3) ? NULL : keys[i].pre);
-
-            g_array_append_val(peers, peer);
-        }
-    } else
-        g_assert_not_reached();
-
-    r = nm_platform_link_wireguard_change(platform,
-                                          ifindex,
-                                          &lnk_wireguard,
-                                          (const NMPWireGuardPeer *) peers->data,
-                                          NULL,
-                                          peers->len,
-                                          NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY
-                                              | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT
-                                              | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK
-                                              | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS);
-    g_assert(NMTST_NM_ERR_SUCCESS(r));
-}
-
-/*****************************************************************************/
-
-typedef struct {
-    NMLinkType link_type;
-    int        test_mode;
-    gboolean   external_command;
-} TestAddSoftwareDetectData;
-
-static void
-test_software_detect(gconstpointer user_data)
-{
-    const TestAddSoftwareDetectData *test_data = user_data;
-    int                              ifindex, ifindex_parent;
-    const NMPlatformLink *           plink;
-    const NMPObject *                lnk;
-    int                              r;
-    guint                            i_step;
-    const gboolean                   ext        = test_data->external_command;
-    NMPlatformLnkBridge              lnk_bridge = {};
-    NMPlatformLnkTun                 lnk_tun;
-    NMPlatformLnkGre                 lnk_gre = {};
-    nm_auto_close int                tun_fd  = -1;
-
-    nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME);
-    ifindex_parent =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex;
-
-    switch (test_data->link_type) {
-    case NM_LINK_TYPE_BRIDGE:
-
-        lnk_bridge.forward_delay = 1560;
-        lnk_bridge.hello_time    = 150;
-        lnk_bridge.max_age       = 2100;
-        lnk_bridge.ageing_time   = 2200;
-        lnk_bridge.stp_state     = TRUE;
-        lnk_bridge.priority      = 22;
-        lnk_bridge.vlan_protocol = 0x8100;
-        lnk_bridge.vlan_stats_enabled =
-            nmtstp_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED)
-                ? TRUE
-                : FALSE;
-        lnk_bridge.group_fwd_mask             = 8;
-        lnk_bridge.group_addr                 = (NMEtherAddr){{0x01, 0x80, 0xC2, 0x00, 0x00, 0x08}};
-        lnk_bridge.mcast_snooping             = TRUE;
-        lnk_bridge.mcast_router               = 1;
-        lnk_bridge.mcast_query_use_ifaddr     = TRUE;
-        lnk_bridge.mcast_querier              = TRUE;
-        lnk_bridge.mcast_hash_max             = 1024;
-        lnk_bridge.mcast_last_member_count    = 2;
-        lnk_bridge.mcast_startup_query_count  = 3;
-        lnk_bridge.mcast_last_member_interval = 5000;
-        lnk_bridge.mcast_membership_interval  = 25000;
-        lnk_bridge.mcast_querier_interval     = 26000;
-        lnk_bridge.mcast_query_interval       = 12000;
-        lnk_bridge.mcast_query_response_interval = 5200;
-        lnk_bridge.mcast_startup_query_interval  = 3000;
-
-        if (!nmtstp_link_bridge_add(NULL, ext, DEVICE_NAME, &lnk_bridge))
-            g_error("Failed adding Bridge interface");
-        break;
-
-    case NM_LINK_TYPE_GRE:
-    {
-        gboolean gracefully_skip = FALSE;
-
-        lnk_gre.local              = nmtst_inet4_from_string("192.168.233.204");
-        lnk_gre.remote             = nmtst_inet4_from_string("172.168.10.25");
-        lnk_gre.parent_ifindex     = ifindex_parent;
-        lnk_gre.ttl                = 174;
-        lnk_gre.tos                = 37;
-        lnk_gre.path_mtu_discovery = TRUE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gre0")) {
-            /* Seems that the ip_gre module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0;
-        }
-
-        if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) {
-            if (gracefully_skip) {
-                g_test_skip(
-                    "Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding GRE tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_GRETAP:
-    {
-        gboolean gracefully_skip = FALSE;
-
-        lnk_gre.local              = nmtst_inet4_from_string("192.168.1.133");
-        lnk_gre.remote             = nmtst_inet4_from_string("172.168.101.2");
-        lnk_gre.parent_ifindex     = ifindex_parent;
-        lnk_gre.ttl                = 39;
-        lnk_gre.tos                = 12;
-        lnk_gre.path_mtu_discovery = FALSE;
-        lnk_gre.is_tap             = TRUE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gretap0")) {
-            /* Seems that the ip_gre module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0;
-        }
-
-        if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) {
-            if (gracefully_skip) {
-                g_test_skip("Cannot create gretap tunnel because of missing ip_gre module "
-                            "(modprobe ip_gre)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding GRETAP tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_IPIP:
-    {
-        NMPlatformLnkIpIp lnk_ipip        = {};
-        gboolean          gracefully_skip = FALSE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "tunl0")) {
-            /* Seems that the ipip module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ipip", NULL) != 0;
-        }
-
-        lnk_ipip.local              = nmtst_inet4_from_string("1.2.3.4");
-        lnk_ipip.remote             = nmtst_inet4_from_string("5.6.7.8");
-        lnk_ipip.parent_ifindex     = ifindex_parent;
-        lnk_ipip.tos                = 32;
-        lnk_ipip.path_mtu_discovery = FALSE;
-
-        if (!nmtstp_link_ipip_add(NULL, ext, DEVICE_NAME, &lnk_ipip)) {
-            if (gracefully_skip) {
-                g_test_skip(
-                    "Cannot create ipip tunnel because of missing ipip module (modprobe ipip)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding IPIP tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_IP6TNL:
-    {
-        NMPlatformLnkIp6Tnl lnk_ip6tnl      = {};
-        gboolean            gracefully_skip = FALSE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6tnl0")) {
-            /* Seems that the ip6_tunnel module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_tunnel", NULL) != 0;
-        }
-
-        switch (test_data->test_mode) {
-        case 0:
-            lnk_ip6tnl.local          = *nmtst_inet6_from_string("fd01::15");
-            lnk_ip6tnl.remote         = *nmtst_inet6_from_string("fd01::16");
-            lnk_ip6tnl.parent_ifindex = ifindex_parent;
-            lnk_ip6tnl.tclass         = 20;
-            lnk_ip6tnl.encap_limit    = 6;
-            lnk_ip6tnl.flow_label     = 1337;
-            lnk_ip6tnl.proto          = IPPROTO_IPV6;
-            break;
-        case 1:
-            lnk_ip6tnl.local          = *nmtst_inet6_from_string("fd01::17");
-            lnk_ip6tnl.remote         = *nmtst_inet6_from_string("fd01::18");
-            lnk_ip6tnl.parent_ifindex = ifindex_parent;
-            lnk_ip6tnl.tclass         = 0;
-            lnk_ip6tnl.encap_limit    = 0;
-            lnk_ip6tnl.flow_label     = 1338;
-            lnk_ip6tnl.proto          = IPPROTO_IPV6;
-            lnk_ip6tnl.flags          = IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS;
-            break;
-        }
-
-        if (!nmtstp_link_ip6tnl_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
-            if (gracefully_skip) {
-                g_test_skip("Cannot create ip6tnl tunnel because of missing ip6_tunnel module "
-                            "(modprobe ip6_tunnel)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding IP6TNL tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_IP6GRE:
-    {
-        NMPlatformLnkIp6Tnl lnk_ip6tnl      = {};
-        gboolean            gracefully_skip = FALSE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) {
-            /* Seems that the ip6_tunnel module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0;
-        }
-
-        lnk_ip6tnl.local          = *nmtst_inet6_from_string("fd01::42");
-        lnk_ip6tnl.remote         = *nmtst_inet6_from_string("fd01::aaaa");
-        lnk_ip6tnl.parent_ifindex = ifindex_parent;
-        lnk_ip6tnl.tclass         = 21;
-        lnk_ip6tnl.flow_label     = 1338;
-        lnk_ip6tnl.is_gre         = TRUE;
-
-        if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
-            if (gracefully_skip) {
-                g_test_skip("Cannot create ip6gre tunnel because of missing ip6_gre module "
-                            "(modprobe ip6_gre)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding IP6GRE tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_IP6GRETAP:
-    {
-        NMPlatformLnkIp6Tnl lnk_ip6tnl      = {};
-        gboolean            gracefully_skip = FALSE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) {
-            /* Seems that the ip6_tunnel module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0;
-        }
-
-        lnk_ip6tnl.local          = *nmtst_inet6_from_string("fe80::abcd");
-        lnk_ip6tnl.remote         = *nmtst_inet6_from_string("fc01::bbbb");
-        lnk_ip6tnl.parent_ifindex = ifindex_parent;
-        lnk_ip6tnl.ttl            = 10;
-        lnk_ip6tnl.tclass         = 22;
-        lnk_ip6tnl.flow_label     = 1339;
-        lnk_ip6tnl.is_gre         = TRUE;
-        lnk_ip6tnl.is_tap         = TRUE;
-
-        if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
-            if (gracefully_skip) {
-                g_test_skip("Cannot create ip6gretap tunnel because of missing ip6_gre module "
-                            "(modprobe ip6_gre)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding IP6GRETAP tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_MACVLAN:
-    {
-        NMPlatformLnkMacvlan  lnk_macvlan = {};
-        const NMPlatformLink *dummy;
-        char                  buf[256];
-        int                   i;
-
-        lnk_macvlan.mode       = MACVLAN_MODE_BRIDGE;
-        lnk_macvlan.no_promisc = FALSE;
-        lnk_macvlan.tap        = FALSE;
-
-        /* Since in old kernel versions sysfs files for macvtaps are not
-         * namespaced, the creation can fail if a macvtap in another namespace
-         * has the same index. Try to detect this situation and skip already
-         * used indexes.
-         * The fix (17af2bce) is included kernel 4.7, dated 24 July, 2016.
-         */
-        for (i = ifindex_parent + 1; i < ifindex_parent + 100; i++) {
-            snprintf(buf, sizeof(buf), "/sys/class/macvtap/tap%d", i);
-            if (!g_file_test(buf, G_FILE_TEST_IS_SYMLINK))
-                break;
-
-            _LOGD("skipping ifindex %d as already used by a macvtap", i);
-
-            dummy = nmtstp_link_dummy_add(NM_PLATFORM_GET, FALSE, "dummy-tmp");
-            g_assert_cmpint(dummy->ifindex, ==, i);
-            nmtstp_link_delete(NM_PLATFORM_GET, FALSE, dummy->ifindex, NULL, TRUE);
-        }
-
-        if (!nmtstp_link_macvlan_add(NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan))
-            g_error("Failed adding MACVLAN interface");
-        break;
-    }
-    case NM_LINK_TYPE_MACVTAP:
-    {
-        NMPlatformLnkMacvlan lnk_macvtap = {};
-
-        lnk_macvtap.mode       = MACVLAN_MODE_PRIVATE;
-        lnk_macvtap.no_promisc = FALSE;
-        lnk_macvtap.tap        = TRUE;
-
-        if (!nmtstp_link_macvlan_add(NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap))
-            g_error("Failed adding MACVTAP interface");
-        break;
-    }
-    case NM_LINK_TYPE_SIT:
-    {
-        NMPlatformLnkSit lnk_sit         = {};
-        gboolean         gracefully_skip = FALSE;
-
-        lnk_sit.local              = nmtst_inet4_from_string("192.168.200.1");
-        lnk_sit.remote             = nmtst_inet4_from_string("172.25.100.14");
-        lnk_sit.parent_ifindex     = ifindex_parent;
-        lnk_sit.ttl                = 0;
-        lnk_sit.tos                = 31;
-        lnk_sit.path_mtu_discovery = FALSE;
-
-        if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "sit0")) {
-            /* Seems that the sit module is not loaded... try to load it. */
-            gracefully_skip = nm_utils_modprobe(NULL, TRUE, "sit", NULL) != 0;
-        }
-
-        if (!nmtstp_link_sit_add(NULL, ext, DEVICE_NAME, &lnk_sit)) {
-            if (gracefully_skip) {
-                g_test_skip(
-                    "Cannot create sit tunnel because of missing sit module (modprobe sit)");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding SIT tunnel");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_VLAN:
-        nmtstp_run_command_check("ip link add name %s link %s type vlan id 1242",
-                                 DEVICE_NAME,
-                                 PARENT_NAME);
-        break;
-    case NM_LINK_TYPE_VRF:
-    {
-        NMPlatformLnkVrf lnk_vrf = {};
-        gboolean         not_supported;
-
-        lnk_vrf.table = 9876;
-
-        if (!nmtstp_link_vrf_add(NULL, ext, DEVICE_NAME, &lnk_vrf, &not_supported)) {
-            if (not_supported) {
-                g_test_skip("Cannot create VRF interface because of missing kernel support");
-                goto out_delete_parent;
-            }
-            g_error("Failed adding VRF interface");
-        }
-        break;
-    }
-    case NM_LINK_TYPE_VXLAN:
-    {
-        NMPlatformLnkVxlan lnk_vxlan = {};
-
-        switch (test_data->test_mode) {
-        case 0:
-            lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME);
-            lnk_vxlan.id             = 42;
-            lnk_vxlan.local          = nmtst_inet4_from_string("23.1.2.164");
-            lnk_vxlan.group          = nmtst_inet4_from_string("239.1.2.134");
-            lnk_vxlan.dst_port       = 4789;
-            lnk_vxlan.learning       = TRUE;
-            lnk_vxlan.ageing         = 1245;
-            break;
-        case 1:
-            lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME);
-            lnk_vxlan.id             = 11214423;
-            lnk_vxlan.local6         = *nmtst_inet6_from_string("1:2:3:4:334:23::23");
-            lnk_vxlan.group6         = *nmtst_inet6_from_string("ff0e::115");
-            lnk_vxlan.ttl            = 32;
-            lnk_vxlan.dst_port       = 57412;
-            lnk_vxlan.src_port_min   = 1000;
-            lnk_vxlan.src_port_max   = 1003;
-            lnk_vxlan.learning       = TRUE;
-            lnk_vxlan.ageing         = 3245;
-            break;
-        }
-
-        g_assert(nmtstp_link_vxlan_add(NULL, ext, DEVICE_NAME, &lnk_vxlan));
-        break;
-    }
-    case NM_LINK_TYPE_TUN:
-    {
-        gboolean owner_valid = nmtst_get_rand_bool();
-        gboolean group_valid = nmtst_get_rand_bool();
-
-        switch (test_data->test_mode) {
-        case 0:
-            lnk_tun = (NMPlatformLnkTun){
-                .type        = nmtst_get_rand_bool() ? IFF_TUN : IFF_TAP,
-                .owner       = owner_valid ? getuid() : 0,
-                .owner_valid = owner_valid,
-                .group       = group_valid ? getgid() : 0,
-                .group_valid = group_valid,
-                .pi          = nmtst_get_rand_bool(),
-                .vnet_hdr    = nmtst_get_rand_bool(),
-                .multi_queue = nmtst_get_rand_bool(),
-
-                /* if we add the device via iproute2 (external), we can only
-                 * create persistent devices. */
-                .persist = (ext == 1) ? TRUE : nmtst_get_rand_bool(),
-            };
-            break;
-        default:
-            g_assert_not_reached();
-            break;
-        }
-
-        g_assert(nmtstp_link_tun_add(NULL,
-                                     ext,
-                                     DEVICE_NAME,
-                                     &lnk_tun,
-                                     (!lnk_tun.persist || nmtst_get_rand_bool()) ? &tun_fd : NULL));
-        break;
-    }
-    case NM_LINK_TYPE_WIREGUARD:
-    {
-        const NMPlatformLink *link;
-
-        r = nm_platform_link_wireguard_add(NM_PLATFORM_GET, DEVICE_NAME, &link);
-        if (r == -EOPNOTSUPP) {
-            g_test_skip("wireguard not supported (modprobe wireguard?)");
-            goto out_delete_parent;
-        }
-
-        g_assert(NMTST_NM_ERR_SUCCESS(r));
-        g_assert(NMP_OBJECT_GET_TYPE(NMP_OBJECT_UP_CAST(link)) == NMP_OBJECT_TYPE_LINK);
-        break;
-    }
-    default:
-        g_assert_not_reached();
-    }
-
-    ifindex = nmtstp_assert_wait_for_link(NM_PLATFORM_GET, DEVICE_NAME, test_data->link_type, 100)
-                  ->ifindex;
-
-    nmtstp_link_set_updown(NULL, -1, ifindex_parent, TRUE);
-
-    for (i_step = 0; i_step < 5; i_step++) {
-        _LOGD("test-software-detect: step %u", i_step);
-        if (nmtst_is_debug())
-            nmtstp_run_command_check("ip -d link show %s", DEVICE_NAME);
-
-        if (i_step > 0) {
-            gboolean set_up = (i_step % 2) == 1;
-
-            if (test_data->link_type == NM_LINK_TYPE_VXLAN && set_up) {
-                /* On RHEL-7, we need to add a tiny sleep here, otherwise,
-                 * upping the vxlan device fails with EADDRINUSE.
-                 * https://bugzilla.redhat.com/show_bug.cgi?id=1277131 */
-                g_usleep(1);
-            }
-            nmtstp_link_set_updown(NULL, -1, ifindex, set_up);
-        }
-
-        lnk = nm_platform_link_get_lnk(NM_PLATFORM_GET, ifindex, test_data->link_type, &plink);
-        g_assert(plink);
-        g_assert_cmpint(plink->ifindex, ==, ifindex);
-
-        if (!lnk && test_data->link_type == NM_LINK_TYPE_TUN) {
-            /* this is ok. Kernel apparently does not support tun properties via netlink. We
-             * fetch them from sysfs below. */
-        } else
-            g_assert(lnk);
-
-        switch (test_data->link_type) {
-        case NM_LINK_TYPE_BRIDGE:
-        {
-            const NMPlatformLnkBridge *plnk = &lnk->lnk_bridge;
-
-            g_assert(plnk == nm_platform_link_get_lnk_bridge(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(nm_platform_lnk_bridge_cmp(&lnk_bridge, plnk), ==, 0);
-            g_assert_cmpint(plnk->forward_delay, ==, 1560);
-            g_assert_cmpint(plnk->hello_time, ==, 150);
-            g_assert_cmpint(plnk->max_age, ==, 2100);
-            g_assert_cmpint(plnk->ageing_time, ==, 2200);
-            g_assert_cmpint(plnk->stp_state, ==, TRUE);
-            g_assert_cmpint(plnk->priority, ==, 22);
-            g_assert_cmpint(plnk->vlan_protocol, ==, 0x8100);
-            g_assert_cmpint(plnk->vlan_stats_enabled, ==, lnk_bridge.vlan_stats_enabled);
-            g_assert_cmpint(plnk->group_fwd_mask, ==, 8);
-            g_assert_cmpint(plnk->mcast_snooping, ==, TRUE);
-            g_assert_cmpint(plnk->mcast_router, ==, 1);
-            g_assert_cmpint(plnk->mcast_query_use_ifaddr, ==, TRUE);
-            g_assert_cmpint(plnk->mcast_querier, ==, TRUE);
-            g_assert_cmpint(plnk->mcast_hash_max, ==, 1024);
-            g_assert_cmpint(plnk->mcast_last_member_count, ==, 2);
-            g_assert_cmpint(plnk->mcast_startup_query_count, ==, 3);
-            g_assert_cmpint(plnk->mcast_last_member_interval, ==, 5000);
-            g_assert_cmpint(plnk->mcast_membership_interval, ==, 25000);
-            g_assert_cmpint(plnk->mcast_querier_interval, ==, 26000);
-            g_assert_cmpint(plnk->mcast_query_interval, ==, 12000);
-            g_assert_cmpint(plnk->mcast_query_response_interval, ==, 5200);
-            g_assert_cmpint(plnk->mcast_startup_query_interval, ==, 3000);
-            g_assert_cmpint(nm_platform_lnk_bridge_cmp(&lnk_bridge, plnk), ==, 0);
-            break;
-        }
-        case NM_LINK_TYPE_GRE:
-        {
-            const NMPlatformLnkGre *plnk = &lnk->lnk_gre;
-
-            g_assert(plnk == nm_platform_link_get_lnk_gre(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert(nm_platform_lnk_gre_cmp(plnk, &lnk_gre) == 0);
-
-            break;
-        }
-        case NM_LINK_TYPE_GRETAP:
-        {
-            const NMPlatformLnkGre *plnk = &lnk->lnk_gre;
-
-            g_assert(plnk == nm_platform_link_get_lnk_gretap(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert(nm_platform_lnk_gre_cmp(plnk, &lnk_gre) == 0);
-            break;
-        }
-        case NM_LINK_TYPE_IP6TNL:
-        {
-            const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl;
-
-            switch (test_data->test_mode) {
-            case 0:
-                g_assert(plnk == nm_platform_link_get_lnk_ip6tnl(NM_PLATFORM_GET, ifindex, NULL));
-                g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-                nmtst_assert_ip6_address(&plnk->local, "fd01::15");
-                nmtst_assert_ip6_address(&plnk->remote, "fd01::16");
-                g_assert_cmpint(plnk->ttl, ==, 0);
-                g_assert_cmpint(plnk->tclass, ==, 20);
-                g_assert_cmpint(plnk->encap_limit, ==, 6);
-                g_assert_cmpint(plnk->flow_label, ==, 1337);
-                g_assert_cmpint(plnk->proto, ==, IPPROTO_IPV6);
-                break;
-            case 1:
-                g_assert(plnk == nm_platform_link_get_lnk_ip6tnl(NM_PLATFORM_GET, ifindex, NULL));
-                g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-                nmtst_assert_ip6_address(&plnk->local, "fd01::17");
-                nmtst_assert_ip6_address(&plnk->remote, "fd01::18");
-                g_assert_cmpint(plnk->ttl, ==, 0);
-                g_assert_cmpint(plnk->flow_label, ==, 1338);
-                g_assert_cmpint(plnk->proto, ==, IPPROTO_IPV6);
-                g_assert_cmpint(plnk->flags & 0xFFFF, /* ignore kernel internal flags */
-                                ==,
-                                IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS);
-                break;
-            }
-            break;
-        }
-        case NM_LINK_TYPE_IP6GRE:
-        {
-            const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl;
-
-            g_assert(plnk == nm_platform_link_get_lnk_ip6gre(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-            nmtst_assert_ip6_address(&plnk->local, "fd01::42");
-            nmtst_assert_ip6_address(&plnk->remote, "fd01::aaaa");
-            g_assert_cmpint(plnk->tclass, ==, 21);
-            g_assert_cmpint(plnk->flow_label, ==, 1338);
-            g_assert_cmpint(plnk->is_gre, ==, TRUE);
-            g_assert_cmpint(plnk->is_tap, ==, FALSE);
-            break;
-        }
-        case NM_LINK_TYPE_IP6GRETAP:
-        {
-            const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl;
-
-            g_assert(plnk == nm_platform_link_get_lnk_ip6gretap(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-            nmtst_assert_ip6_address(&plnk->local, "fe80::abcd");
-            nmtst_assert_ip6_address(&plnk->remote, "fc01::bbbb");
-            g_assert_cmpint(plnk->ttl, ==, 10);
-            g_assert_cmpint(plnk->tclass, ==, 22);
-            g_assert_cmpint(plnk->flow_label, ==, 1339);
-            g_assert_cmpint(plnk->is_gre, ==, TRUE);
-            g_assert_cmpint(plnk->is_tap, ==, TRUE);
-            break;
-        }
-        case NM_LINK_TYPE_IPIP:
-        {
-            const NMPlatformLnkIpIp *plnk = &lnk->lnk_ipip;
-
-            g_assert(plnk == nm_platform_link_get_lnk_ipip(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-            nmtst_assert_ip4_address(plnk->local, "1.2.3.4");
-            nmtst_assert_ip4_address(plnk->remote, "5.6.7.8");
-            g_assert_cmpint(plnk->ttl, ==, 0);
-            g_assert_cmpint(plnk->tos, ==, 32);
-            g_assert_cmpint(plnk->path_mtu_discovery, ==, FALSE);
-            break;
-        }
-        case NM_LINK_TYPE_MACVLAN:
-        {
-            const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan;
-
-            g_assert(plnk == nm_platform_link_get_lnk_macvlan(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->no_promisc, ==, FALSE);
-            g_assert_cmpint(plnk->mode, ==, MACVLAN_MODE_BRIDGE);
-            break;
-        }
-        case NM_LINK_TYPE_MACVTAP:
-        {
-            const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan;
-
-            g_assert(plnk == nm_platform_link_get_lnk_macvtap(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->no_promisc, ==, FALSE);
-            g_assert_cmpint(plnk->mode, ==, MACVLAN_MODE_PRIVATE);
-            break;
-        }
-        case NM_LINK_TYPE_SIT:
-        {
-            const NMPlatformLnkSit *plnk = &lnk->lnk_sit;
-
-            g_assert(plnk == nm_platform_link_get_lnk_sit(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-            nmtst_assert_ip4_address(plnk->local, "192.168.200.1");
-            nmtst_assert_ip4_address(plnk->remote, "172.25.100.14");
-            g_assert_cmpint(plnk->ttl, ==, 0);
-            g_assert_cmpint(plnk->tos, ==, 31);
-            g_assert_cmpint(plnk->path_mtu_discovery, ==, FALSE);
-            break;
-        }
-        case NM_LINK_TYPE_TUN:
-        {
-            const NMPlatformLnkTun *plnk;
-            NMPlatformLnkTun        lnk_tun2;
-
-            g_assert((lnk ? &lnk->lnk_tun : NULL)
-                     == nm_platform_link_get_lnk_tun(NM_PLATFORM_GET, ifindex, NULL));
-
-            /* kernel might not expose tun options via netlink. Either way, try
-             * to read them (either from platform cache, or fallback to sysfs).
-             * See also: rh#1547213. */
-            if (!nm_platform_link_tun_get_properties(NM_PLATFORM_GET, ifindex, &lnk_tun2))
-                g_assert_not_reached();
-
-            plnk = lnk ? &lnk->lnk_tun : &lnk_tun2;
-            if (lnk)
-                g_assert(memcmp(plnk, &lnk_tun2, sizeof(NMPlatformLnkTun)) == 0);
-
-            if (i_step == 0) {
-                /* Before we upped the device for the first time the kernel didn't notify
-                 * us of the owner set after the link creation:
-                 * https://bugzilla.redhat.com/show_bug.cgi?id=1566062
-                 */
-                break;
-            }
-
-            g_assert(nm_platform_lnk_tun_cmp(plnk, &lnk_tun) == 0);
-            break;
-        }
-        case NM_LINK_TYPE_VLAN:
-        {
-            const NMPlatformLnkVlan *plnk = &lnk->lnk_vlan;
-
-            g_assert(plnk == nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->id, ==, 1242);
-            break;
-        }
-        case NM_LINK_TYPE_VRF:
-        {
-            const NMPlatformLnkVrf *plnk = &lnk->lnk_vrf;
-
-            g_assert(plnk == nm_platform_link_get_lnk_vrf(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->table, ==, 9876);
-            break;
-        }
-        case NM_LINK_TYPE_VXLAN:
-        {
-            const NMPlatformLnkVxlan *plnk = &lnk->lnk_vxlan;
-
-            g_assert(plnk == nm_platform_link_get_lnk_vxlan(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, !=, 0);
-            g_assert_cmpint(plnk->tos, ==, 0);
-            g_assert_cmpint(plnk->learning, ==, TRUE);
-            g_assert_cmpint(plnk->limit, ==, 0);
-            g_assert_cmpint(plnk->proxy, ==, FALSE);
-            g_assert_cmpint(plnk->rsc, ==, FALSE);
-            g_assert_cmpint(plnk->l2miss, ==, FALSE);
-            g_assert_cmpint(plnk->l3miss, ==, FALSE);
-
-            switch (test_data->test_mode) {
-            case 0:
-                g_assert_cmpint(plnk->id, ==, 42);
-                nmtst_assert_ip4_address(plnk->local, "23.1.2.164");
-                nmtst_assert_ip4_address(plnk->group, "239.1.2.134");
-                nmtst_assert_ip6_address(&plnk->group6, "::");
-                nmtst_assert_ip6_address(&plnk->local6, "::");
-                g_assert_cmpint(plnk->ttl, ==, 0);
-                g_assert_cmpint(plnk->ageing, ==, 1245);
-                g_assert_cmpint(plnk->dst_port, ==, 4789);
-                if (plnk->src_port_min != 0 || plnk->src_port_max != 0) {
-                    /* on some kernels, omitting the port range results in setting
-                     * following default port range. */
-                    g_assert_cmpint(plnk->src_port_min, ==, 32768);
-                    g_assert_cmpint(plnk->src_port_max, ==, 61000);
-                }
-                break;
-            case 1:
-                g_assert_cmpint(plnk->id, ==, 11214423);
-                nmtst_assert_ip4_address(plnk->local, "0.0.0.0");
-                nmtst_assert_ip4_address(plnk->group, "0.0.0.0");
-                nmtst_assert_ip6_address(&plnk->group6, "ff0e::115");
-                nmtst_assert_ip6_address(&plnk->local6, "1:2:3:4:334:23::23");
-                g_assert_cmpint(plnk->ageing, ==, 3245);
-                g_assert_cmpint(plnk->dst_port, ==, 57412);
-                g_assert_cmpint(plnk->ttl, ==, 32);
-                g_assert_cmpint(plnk->src_port_min, ==, 1000);
-                g_assert_cmpint(plnk->src_port_max, ==, 1003);
-                break;
-            }
-            break;
-        }
-        case NM_LINK_TYPE_WIREGUARD:
-        {
-            const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard;
-
-            g_assert(plnk == nm_platform_link_get_lnk_wireguard(NM_PLATFORM_GET, ifindex, NULL));
-
-            if (plink->n_ifi_flags & IFF_UP) {
-                _test_wireguard_change(NM_PLATFORM_GET, plink->ifindex, test_data->test_mode);
-                if (_LOGD_ENABLED())
-                    _system("WG_HIDE_KEYS=never wg show all");
-            }
-            break;
-        }
-        default:
-            g_assert_not_reached();
-        }
-    }
-
-    nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE);
-out_delete_parent:
-    nmtstp_link_delete(NULL, -1, ifindex_parent, PARENT_NAME, TRUE);
-}
-
-static void
-test_software_detect_add(const char *testpath, NMLinkType link_type, int test_mode)
-{
-    TestAddSoftwareDetectData *test_data;
-    char *                     path;
-
-    test_data                   = g_new0(TestAddSoftwareDetectData, 1);
-    test_data->link_type        = link_type;
-    test_data->test_mode        = test_mode;
-    test_data->external_command = TRUE;
-
-    path = g_strdup_printf("%s/external", testpath);
-    g_test_add_data_func_full(path, test_data, test_software_detect, g_free);
-    g_free(path);
-
-    test_data                   = g_new0(TestAddSoftwareDetectData, 1);
-    test_data->link_type        = link_type;
-    test_data->test_mode        = test_mode;
-    test_data->external_command = FALSE;
-
-    path = g_strdup_printf("%s/platform", testpath);
-    g_test_add_data_func_full(path, test_data, test_software_detect, g_free);
-    g_free(path);
-
-    test_data                   = g_new0(TestAddSoftwareDetectData, 1);
-    test_data->link_type        = link_type;
-    test_data->test_mode        = test_mode;
-    test_data->external_command = -1;
-
-    path = g_strdup_printf("%s/random", testpath);
-    g_test_add_data_func_full(path, test_data, test_software_detect, g_free);
-    g_free(path);
-}
-
-/*****************************************************************************/
-
-static void
-_assert_xgress_qos_mappings_impl(int ifindex, gboolean is_ingress_map, int n_entries, int n, ...)
-{
-    const NMPlatformLink *  plink;
-    const NMPObject *       lnk;
-    guint                   n_map;
-    const NMVlanQosMapping *map;
-    va_list                 ap;
-    guint                   i;
-
-    lnk = nm_platform_link_get_lnk(NM_PLATFORM_GET, ifindex, NM_LINK_TYPE_VLAN, &plink);
-
-    g_assert(plink);
-    g_assert_cmpint(plink->ifindex, ==, ifindex);
-    g_assert(lnk);
-    g_assert(&lnk->lnk_vlan == nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, NULL));
-
-    if (nmtst_is_debug())
-        nmtstp_run_command_check("ip -d link show %s", plink->name);
-
-    if (is_ingress_map) {
-        map   = lnk->_lnk_vlan.ingress_qos_map;
-        n_map = lnk->_lnk_vlan.n_ingress_qos_map;
-    } else {
-        map   = lnk->_lnk_vlan.egress_qos_map;
-        n_map = lnk->_lnk_vlan.n_egress_qos_map;
-    }
-
-    if (n_entries != -1)
-        g_assert_cmpint(n_map, ==, n_entries);
-
-    for (i = 0; i < n_map; i++) {
-        if (is_ingress_map) {
-            g_assert_cmpint(map[i].from, >=, 0);
-            g_assert_cmpint(map[i].from, <=, 7);
-        }
-        if (i > 0)
-            g_assert_cmpint(map[i - 1].from, <, map[i].from);
-    }
-
-    va_start(ap, n);
-    for (; n > 0; n--) {
-        gboolean found = FALSE;
-        guint    from  = va_arg(ap, guint);
-        guint    to    = va_arg(ap, guint);
-
-        for (i = 0; i < n_map; i++) {
-            if (map[i].from == from) {
-                g_assert(!found);
-                found = TRUE;
-
-                g_assert(map[i].to == to);
-            }
-        }
-        g_assert(found);
-    }
-    va_end(ap);
-}
-#define _assert_xgress_qos_mappings(ifindex, is_ingress_map, n_entries, ...)               \
-    _assert_xgress_qos_mappings_impl(                                                      \
-        (ifindex),                                                                         \
-        (is_ingress_map),                                                                  \
-        (n_entries),                                                                       \
-        (G_STATIC_ASSERT_EXPR((NM_NARG(__VA_ARGS__) % 2) == 0), NM_NARG(__VA_ARGS__) / 2), \
-        __VA_ARGS__)
-#define _assert_ingress_qos_mappings(ifindex, n_entries, ...) \
-    _assert_xgress_qos_mappings(ifindex, TRUE, n_entries, __VA_ARGS__)
-#define _assert_egress_qos_mappings(ifindex, n_entries, ...) \
-    _assert_xgress_qos_mappings(ifindex, FALSE, n_entries, __VA_ARGS__)
-
-static void
-_assert_vlan_flags(int ifindex, NMVlanFlags flags)
-{
-    const NMPlatformLnkVlan *plnk;
-
-    plnk = nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, NULL);
-    g_assert(plnk);
-    g_assert_cmpint(plnk->flags, ==, flags);
-}
-
-static void
-test_vlan_set_xgress(void)
-{
-    int ifindex, ifindex_parent;
-
-    nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME);
-    ifindex_parent =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex;
-
-    nmtstp_run_command_check("ip link add name %s link %s type vlan id 1245",
-                             DEVICE_NAME,
-                             PARENT_NAME);
-    ifindex =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, DEVICE_NAME, NM_LINK_TYPE_VLAN, 100)->ifindex;
-
-    /* ingress-qos-map */
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 4, 5));
-    _assert_ingress_qos_mappings(ifindex, 1, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 3, 7));
-    _assert_ingress_qos_mappings(ifindex, 2, 3, 7, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 3, 8));
-    _assert_ingress_qos_mappings(ifindex, 2, 3, 8, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 4));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, 4, 3, 8, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, G_MAXUINT32));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, G_MAXUINT32, 3, 8, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, G_MAXUINT32 - 1));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, G_MAXUINT32 - 1, 3, 8, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 5));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 5));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
-
-    /* Set invalid values: */
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 8, 3));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
-
-    g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 9, 4));
-    _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
-
-    /* egress-qos-map */
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 7, 3));
-    _assert_egress_qos_mappings(ifindex, 1, 7, 3);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 8, 4));
-    _assert_egress_qos_mappings(ifindex, 2, 7, 3, 8, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 0, 4));
-    _assert_egress_qos_mappings(ifindex, 3, 0, 4, 7, 3, 8, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 1, 4));
-    _assert_egress_qos_mappings(ifindex, 4, 0, 4, 1, 4, 7, 3, 8, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 1, 5));
-    _assert_egress_qos_mappings(ifindex, 4, 0, 4, 1, 5, 7, 3, 8, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 9, 5));
-    _assert_egress_qos_mappings(ifindex, 5, 0, 4, 1, 5, 7, 3, 8, 4, 9, 5);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 8, 5));
-    _assert_egress_qos_mappings(ifindex, 5, 0, 4, 1, 5, 7, 3, 8, 5, 9, 5);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 8, 0));
-    _assert_egress_qos_mappings(ifindex, 4, 0, 4, 1, 5, 7, 3, 9, 5);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 0, 0));
-    _assert_egress_qos_mappings(ifindex, 3, 1, 5, 7, 3, 9, 5);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 100, 4));
-    _assert_egress_qos_mappings(ifindex, 4, 1, 5, 7, 3, 9, 5, 100, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, G_MAXUINT32, 4));
-    _assert_egress_qos_mappings(ifindex, 5, 1, 5, 7, 3, 9, 5, 100, 4, G_MAXUINT32, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, G_MAXUINT32, 8));
-    _assert_egress_qos_mappings(ifindex, 5, 1, 5, 7, 3, 9, 5, 100, 4, G_MAXUINT32, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, G_MAXUINT32, 0));
-    _assert_egress_qos_mappings(ifindex, 4, 1, 5, 7, 3, 9, 5, 100, 4);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 100, 0));
-    _assert_egress_qos_mappings(ifindex, 3, 1, 5, 7, 3, 9, 5);
-
-    g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 1, 0));
-    _assert_egress_qos_mappings(ifindex, 2, 7, 3, 9, 5);
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 1, .to = 5},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              TRUE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              FALSE,
-                                              NULL,
-                                              0));
-        _assert_ingress_qos_mappings(ifindex, 1, 1, 5);
-    }
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 3, .to = 5},
-            {.from = 7, .to = 1655},
-            {.from = 7, .to = 17655},
-            {.from = 5, .to = 754},
-            {.from = 4, .to = 12},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              TRUE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              FALSE,
-                                              NULL,
-                                              0));
-        _assert_ingress_qos_mappings(ifindex, 4, 3, 5, 4, 12, 7, 17655, 5, 754);
-    }
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 3, .to = 18},
-            {.from = 6, .to = 121},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              FALSE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              FALSE,
-                                              NULL,
-                                              0));
-        _assert_ingress_qos_mappings(ifindex, 5, 3, 18, 4, 12, 6, 121, 7, 17655, 5, 754);
-    }
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 3, .to = 0},
-            {.from = 6, .to = 7},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              TRUE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              FALSE,
-                                              NULL,
-                                              0));
-        _assert_ingress_qos_mappings(ifindex, 1, 6, 7);
-    }
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 1, .to = 5},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              TRUE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              FALSE,
-                                              NULL,
-                                              0));
-        _assert_ingress_qos_mappings(ifindex, 1, 1, 5);
-    }
-
-    {
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 5, .to = 1},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              FALSE,
-                                              NULL,
-                                              0,
-                                              TRUE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_egress_qos_mappings(ifindex, 1, 5, 1);
-    }
-
-    {
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 5, .to = 3},
-            {.from = 1655, .to = 5},
-            {.from = 1655, .to = 7},
-            {.from = G_MAXUINT32, .to = 6},
-            {.from = G_MAXUINT32, .to = 8},
-            {.from = 754, .to = 4},
-            {.from = 3, .to = 2},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              FALSE,
-                                              NULL,
-                                              0,
-                                              TRUE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_egress_qos_mappings(ifindex, 5, 3, 2, 5, 3, 754, 4, 1655, 7, G_MAXUINT32, 6);
-    }
-
-    {
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 754, .to = 3},
-            {.from = 755, .to = 8},
-            {.from = 1655, .to = 0},
-            {.from = 6, .to = 1},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              FALSE,
-                                              NULL,
-                                              0,
-                                              FALSE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_egress_qos_mappings(ifindex, 5, 3, 2, 5, 3, 6, 1, 754, 3, G_MAXUINT32, 6);
-    }
-
-    {
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 6, .to = 0},
-            {.from = 3, .to = 4},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              FALSE,
-                                              NULL,
-                                              0,
-                                              TRUE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_egress_qos_mappings(ifindex, 1, 3, 4);
-    }
-
-    {
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 1, .to = 5},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              0,
-                                              0,
-                                              FALSE,
-                                              NULL,
-                                              0,
-                                              TRUE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_egress_qos_mappings(ifindex, 1, 1, 5);
-    }
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 6, .to = 145},
-            {.from = 4, .to = 1},
-            {.from = 6, .to = 12},
-        };
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 1, .to = 5},
-            {.from = 3232, .to = 7},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP,
-                                              NM_VLAN_FLAG_REORDER_HEADERS,
-                                              TRUE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              TRUE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_ingress_qos_mappings(ifindex, 2, 4, 1, 6, 12);
-        _assert_egress_qos_mappings(ifindex, 2, 1, 5, 3232, 7);
-        _assert_vlan_flags(ifindex, NM_VLAN_FLAG_REORDER_HEADERS);
-    }
-
-    {
-        const NMVlanQosMapping ingress_map[] = {
-            {.from = 6, .to = 145},
-            {.from = 4, .to = 1},
-            {.from = 6, .to = 12},
-        };
-        const NMVlanQosMapping egress_map[] = {
-            {.from = 1, .to = 7},
-            {.from = 64, .to = 10},
-            {.from = 64, .to = 10},
-            {.from = 64, .to = 10},
-            {.from = 64, .to = 10},
-            {.from = 3232, .to = 0},
-            {.from = 64, .to = 4},
-        };
-
-        g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET,
-                                              ifindex,
-                                              NM_VLAN_FLAG_GVRP,
-                                              NM_VLAN_FLAG_GVRP,
-                                              FALSE,
-                                              ingress_map,
-                                              G_N_ELEMENTS(ingress_map),
-                                              FALSE,
-                                              egress_map,
-                                              G_N_ELEMENTS(egress_map)));
-        _assert_ingress_qos_mappings(ifindex, 2, 4, 1, 6, 12);
-        _assert_egress_qos_mappings(ifindex, 2, 1, 7, 64, 4);
-        _assert_vlan_flags(ifindex, NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP);
-    }
-
-    nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE);
-    nmtstp_link_delete(NULL, -1, ifindex_parent, PARENT_NAME, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-test_create_many_links_do(guint n_devices)
-{
-    gint64                time, start_time = nm_utils_get_monotonic_timestamp_nsec();
-    guint                 i;
-    char                  name[64];
-    const NMPlatformLink *pllink;
-    gs_unref_array GArray *ifindexes = g_array_sized_new(FALSE, FALSE, sizeof(int), n_devices);
-    const int              EX        = ((int) (nmtst_get_rand_uint32() % 4)) - 1;
-
-    g_assert(EX >= -1 && EX <= 2);
-
-    _LOGI(">>> create devices (EX=%d)...", EX);
-
-    for (i = 0; i < n_devices; i++) {
-        nm_sprintf_buf(name, "t-%05u", i);
-        if (EX == 2) {
-            /* This mode is different from letting nmtstp_link_dummy_add()
-             * because in this case we don't process any platform events
-             * while adding all the links. */
-            nmtstp_run_command_check("ip link add %s type dummy", name);
-        } else
-            nmtstp_link_dummy_add(NULL, EX, name);
-    }
-
-    _LOGI(">>> process events after creating devices...");
-
-    nm_platform_process_events(NM_PLATFORM_GET);
-
-    _LOGI(">>> check devices...");
-
-    for (i = 0; i < n_devices; i++) {
-        nm_sprintf_buf(name, "t-%05u", i);
-
-        pllink = nm_platform_link_get_by_ifname(NM_PLATFORM_GET, name);
-        g_assert(pllink);
-        g_assert_cmpint(pllink->type, ==, NM_LINK_TYPE_DUMMY);
-        g_assert_cmpstr(pllink->name, ==, name);
-
-        g_array_append_val(ifindexes, pllink->ifindex);
-    }
-
-    _LOGI(">>> delete devices...");
-
-    g_assert_cmpint(ifindexes->len, ==, n_devices);
-    for (i = 0; i < n_devices; i++) {
-        nm_sprintf_buf(name, "t-%05u", i);
-
-        if (EX == 2)
-            nmtstp_run_command_check("ip link delete %s", name);
-        else
-            nmtstp_link_delete(NULL, EX, g_array_index(ifindexes, int, i), name, TRUE);
-    }
-
-    _LOGI(">>> process events after deleting devices...");
-    nm_platform_process_events(NM_PLATFORM_GET);
-
-    time = nm_utils_get_monotonic_timestamp_nsec() - start_time;
-    _LOGI(">>> finished in %ld.%09ld seconds",
-          (long) (time / NM_UTILS_NSEC_PER_SEC),
-          (long) (time % NM_UTILS_NSEC_PER_SEC));
-}
-
-static void
-test_create_many_links(gconstpointer user_data)
-{
-    guint n_devices = GPOINTER_TO_UINT(user_data);
-
-    if (n_devices > 100 && nmtst_test_quick()) {
-        g_print("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n",
-                g_get_prgname() ?: "test-link-linux");
-        g_test_skip("Skip long running test");
-        return;
-    }
-
-    test_create_many_links_do(n_devices);
-}
-
-/*****************************************************************************/
-
-static void
-test_nl_bugs_veth(void)
-{
-    const char *          IFACE_VETH0 = "nm-test-veth0";
-    const char *          IFACE_VETH1 = "nm-test-veth1";
-    int                   ifindex_veth0, ifindex_veth1;
-    int                   i;
-    const NMPlatformLink *pllink_veth0, *pllink_veth1;
-    gs_free_error GError * error     = NULL;
-    NMTstpNamespaceHandle *ns_handle = NULL;
-
-    /* create veth pair. */
-    ifindex_veth0 = nmtstp_link_veth_add(NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex;
-    ifindex_veth1 =
-        nmtstp_link_get_typed(NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex;
-
-    /* assert that nm_platform_link_veth_get_properties() returns the expected peer ifindexes. */
-    g_assert(nm_platform_link_veth_get_properties(NM_PLATFORM_GET, ifindex_veth0, &i));
-    g_assert_cmpint(i, ==, ifindex_veth1);
-
-    g_assert(nm_platform_link_veth_get_properties(NM_PLATFORM_GET, ifindex_veth1, &i));
-    g_assert_cmpint(i, ==, ifindex_veth0);
-
-    /* assert that NMPlatformLink.parent is the peer-ifindex. */
-    pllink_veth0 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth0);
-    g_assert(pllink_veth0);
-    if (pllink_veth0->parent == 0) {
-        /* Kernels prior to 4.1 dated 21 June, 2015 don't support exposing the veth peer
-         * as IFA_LINK. skip the remainder of the test. */
-        goto out;
-    }
-    g_assert_cmpint(pllink_veth0->parent, ==, ifindex_veth1);
-
-    /* The following tests whether we have a workaround for kernel bug
-     * https://bugzilla.redhat.com/show_bug.cgi?id=1285827 in place. */
-    pllink_veth1 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth1);
-    g_assert(pllink_veth1);
-    g_assert_cmpint(pllink_veth1->parent, ==, ifindex_veth0);
-
-    /* move one veth peer to another namespace and check that the
-     * parent/IFLA_LINK of the remaining peer properly updates
-     * (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */
-    ns_handle = nmtstp_namespace_create(CLONE_NEWNET, &error);
-    g_assert_no_error(error);
-    g_assert(ns_handle);
-
-    nmtstp_run_command_check("ip link set %s netns %ld",
-                             IFACE_VETH1,
-                             (long) nmtstp_namespace_handle_get_pid(ns_handle));
-    NMTST_WAIT_ASSERT(100, {
-        nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-        nm_platform_process_events(NM_PLATFORM_GET);
-
-        pllink_veth1 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth1);
-        pllink_veth0 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth0);
-        if (!pllink_veth1 && pllink_veth0 && pllink_veth0->parent == NM_PLATFORM_LINK_OTHER_NETNS) {
-            break;
-        }
-    });
-
-out:
-    nmtstp_link_delete(NULL, -1, ifindex_veth0, IFACE_VETH0, TRUE);
-    g_assert(!nmtstp_link_get(NM_PLATFORM_GET, ifindex_veth0, IFACE_VETH0));
-    g_assert(!nmtstp_link_get(NM_PLATFORM_GET, ifindex_veth1, IFACE_VETH1));
-    nmtstp_namespace_handle_release(ns_handle);
-}
-
-/*****************************************************************************/
-
-static void
-test_nl_bugs_spuroius_newlink(void)
-{
-    const char *          IFACE_BOND0  = "nm-test-bond0";
-    const char *          IFACE_DUMMY0 = "nm-test-dummy0";
-    int                   ifindex_bond0, ifindex_dummy0;
-    const NMPlatformLink *pllink;
-    gboolean              wait_for_settle;
-
-    /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */
-
-    nmtstp_run_command_check("ip link add %s type dummy", IFACE_DUMMY0);
-    ifindex_dummy0 =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)
-            ->ifindex;
-
-    nmtstp_run_command_check("ip link add %s type bond", IFACE_BOND0);
-    ifindex_bond0 =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex;
-
-    nmtstp_link_set_updown(NULL, -1, ifindex_bond0, TRUE);
-
-    nmtstp_run_command_check("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0);
-    NMTST_WAIT_ASSERT(100, {
-        nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-
-        pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0);
-        g_assert(pllink);
-        if (pllink->master == ifindex_bond0)
-            break;
-    });
-
-    nmtstp_run_command_check("ip link del %s", IFACE_BOND0);
-
-    wait_for_settle = TRUE;
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-again:
-    nm_platform_process_events(NM_PLATFORM_GET);
-    pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_bond0);
-    g_assert(!pllink);
-
-    if (wait_for_settle) {
-        wait_for_settle = FALSE;
-        NMTST_WAIT(300, { nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); });
-        goto again;
-    }
-
-    g_assert(!nmtstp_link_get(NM_PLATFORM_GET, ifindex_bond0, IFACE_BOND0));
-    nmtstp_link_delete(NULL, -1, ifindex_dummy0, IFACE_DUMMY0, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-test_nl_bugs_spuroius_dellink(void)
-{
-    const char *          IFACE_BRIDGE0 = "nm-test-bridge0";
-    const char *          IFACE_DUMMY0  = "nm-test-dummy0";
-    int                   ifindex_bridge0, ifindex_dummy0;
-    const NMPlatformLink *pllink;
-    gboolean              wait_for_settle;
-
-    /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */
-
-    nmtstp_run_command_check("ip link add %s type dummy", IFACE_DUMMY0);
-    ifindex_dummy0 =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)
-            ->ifindex;
-
-    nmtstp_run_command_check("ip link add %s type bridge", IFACE_BRIDGE0);
-    ifindex_bridge0 =
-        nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)
-            ->ifindex;
-
-    nmtstp_link_set_updown(NULL, -1, ifindex_bridge0, TRUE);
-
-    nmtstp_run_command_check("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0);
-    NMTST_WAIT_ASSERT(100, {
-        nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-
-        pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0);
-        g_assert(pllink);
-        if (pllink->master == ifindex_bridge0)
-            break;
-    });
-
-    nm_platform_process_events(NM_PLATFORM_GET);
-
-    nmtstp_run_command_check("ip link set %s nomaster", IFACE_DUMMY0);
-
-    wait_for_settle = TRUE;
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-again:
-    nm_platform_process_events(NM_PLATFORM_GET);
-    pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_bridge0);
-    g_assert(pllink);
-    pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0);
-    g_assert(pllink);
-    g_assert_cmpint(pllink->parent, ==, 0);
-
-    if (wait_for_settle) {
-        wait_for_settle = FALSE;
-        NMTST_WAIT(300, { nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); });
-        goto again;
-    }
-
-    nmtstp_link_delete(NULL, -1, ifindex_bridge0, IFACE_BRIDGE0, TRUE);
-    nmtstp_link_delete(NULL, -1, ifindex_dummy0, IFACE_DUMMY0, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-_test_netns_setup(gpointer fixture, gconstpointer test_data)
-{
-    /* the singleton platform instance has netns support disabled.
-     * Destroy the instance before the test and re-create it afterwards. */
-    g_object_unref(NM_PLATFORM_GET);
-}
-
-static void
-_test_netns_teardown(gpointer fixture, gconstpointer test_data)
-{
-    nmtstp_setup_platform();
-}
-
-static NMPlatform *
-_test_netns_create_platform(void)
-{
-    NMPNetns *  netns;
-    NMPlatform *platform;
-
-    netns = nmp_netns_new();
-    g_assert(NMP_IS_NETNS(netns));
-
-    platform = nm_linux_platform_new(TRUE, TRUE);
-    g_assert(NM_IS_LINUX_PLATFORM(platform));
-
-    nmp_netns_pop(netns);
-    g_object_unref(netns);
-
-    return platform;
-}
-
-static gboolean
-_test_netns_check_skip(void)
-{
-    static int      support       = -1;
-    static int      support_errsv = 0;
-    NMPNetns *      netns;
-    gs_unref_object NMPNetns *netns2 = NULL;
-
-    netns = nmp_netns_get_current();
-    if (!netns) {
-        g_test_skip("No netns support");
-        return TRUE;
-    }
-
-    g_assert(nmp_netns_get_fd_net(netns) > 0);
-
-    if (support == -1) {
-        support = (setns(nmp_netns_get_fd_net(netns), CLONE_NEWNET) == 0);
-        if (!support)
-            support_errsv = errno;
-    }
-    if (!support) {
-        _LOGD("setns() failed with \"%s\". This indicates missing support (valgrind?)",
-              nm_strerror_native(support_errsv));
-        g_test_skip("No netns support (setns failed)");
-        return TRUE;
-    }
-
-    netns2 = nmp_netns_new();
-    if (!netns2) {
-        /* skip tests for https://bugzilla.gnome.org/show_bug.cgi?id=790214 */
-        g_assert_cmpint(errno, ==, EINVAL);
-        g_test_skip("No netns support to create another netns");
-        return TRUE;
-    }
-    nmp_netns_pop(netns2);
-
-    return FALSE;
-}
-
-static gboolean
-_check_sysctl_skip(void)
-{
-    if (access("/proc/sys/net/ipv4/ip_forward", W_OK) == -1) {
-        g_test_skip("Can not write sysctls");
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-/*****************************************************************************/
-
-#define _sysctl_assert_eq(plat, path, value)                                   \
-    G_STMT_START                                                               \
-    {                                                                          \
-        gs_free char *_val = NULL;                                             \
-                                                                               \
-        _val = nm_platform_sysctl_get(plat, NMP_SYSCTL_PATHID_ABSOLUTE(path)); \
-        g_assert_cmpstr(_val, ==, value);                                      \
-    }                                                                          \
-    G_STMT_END
-
-static void
-test_netns_general(gpointer fixture, gconstpointer test_data)
-{
-    gs_unref_object NMPlatform *platform_1 = NULL;
-    gs_unref_object NMPlatform *platform_2 = NULL;
-    NMPNetns *                  netns_tmp;
-    char                        sbuf[100];
-    int                         i, j, k;
-    gboolean                    ethtool_support;
-    NMPUtilsEthtoolDriverInfo   driver_info;
-
-    if (_test_netns_check_skip())
-        return;
-
-    if (_check_sysctl_skip())
-        return;
-
-    platform_1 = nm_linux_platform_new(TRUE, TRUE);
-    platform_2 = _test_netns_create_platform();
-
-    /* add some dummy devices. The "other-*" devices are there to bump the ifindex */
-    for (k = 0; k < 2; k++) {
-        NMPlatform *p  = (k == 0 ? platform_1 : platform_2);
-        const char *id = (k == 0 ? "a" : "b");
-
-        for (i = 0, j = nmtst_get_rand_uint32() % 5; i < j; i++)
-            _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "other-a-%s-%02d", id, i));
-
-        _ADD_DUMMY(p, "dummy1_");
-
-        for (i = 0, j = nmtst_get_rand_uint32() % 5; i < j; i++)
-            _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "other-b-%s-%02d", id, i));
-
-        _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "dummy2%s", id));
-
-        for (i = 0, j = nmtst_get_rand_uint32() % 5; i < j; i++)
-            _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "other-c-%s-%02d", id, i));
-    }
-
-    _sysctl_assert_eq(
-        platform_1,
-        "/sys/devices/virtual/net/dummy1_/ifindex",
-        nm_sprintf_buf(
-            sbuf,
-            "%d",
-            nmtstp_link_get_typed(platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex));
-    _sysctl_assert_eq(
-        platform_1,
-        "/sys/devices/virtual/net/dummy2a/ifindex",
-        nm_sprintf_buf(
-            sbuf,
-            "%d",
-            nmtstp_link_get_typed(platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex));
-    _sysctl_assert_eq(platform_1, "/sys/devices/virtual/net/dummy2b/ifindex", NULL);
-
-    _sysctl_assert_eq(
-        platform_2,
-        "/sys/devices/virtual/net/dummy1_/ifindex",
-        nm_sprintf_buf(
-            sbuf,
-            "%d",
-            nmtstp_link_get_typed(platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex));
-    _sysctl_assert_eq(platform_2, "/sys/devices/virtual/net/dummy2a/ifindex", NULL);
-    _sysctl_assert_eq(
-        platform_2,
-        "/sys/devices/virtual/net/dummy2b/ifindex",
-        nm_sprintf_buf(
-            sbuf,
-            "%d",
-            nmtstp_link_get_typed(platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex));
-
-    for (i = 0; i < 10; i++) {
-        NMPlatform *pl;
-        const char *path;
-
-        j = nmtst_get_rand_uint32() % 2;
-
-        if (nmtst_get_rand_uint32() % 2) {
-            pl = platform_1;
-            if (nmtst_get_rand_uint32() % 2)
-                path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6";
-            else
-                path = "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6";
-        } else {
-            pl = platform_2;
-            if (nmtst_get_rand_uint32() % 2)
-                path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6";
-            else
-                path = "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6";
-        }
-        g_assert(nm_platform_sysctl_set(pl,
-                                        NMP_SYSCTL_PATHID_ABSOLUTE(path),
-                                        nm_sprintf_buf(sbuf, "%d", j)));
-        _sysctl_assert_eq(pl, path, nm_sprintf_buf(sbuf, "%d", j));
-    }
-
-    _sysctl_assert_eq(platform_1, "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6", NULL);
-    _sysctl_assert_eq(platform_2, "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6", NULL);
-
-    /* Kernels prior to 3.19 dated 8 February, 2015 don't support ethtool -i for dummy devices.
-     * Work around that and skip asserts that are known to fail. */
-    ethtool_support = nmtstp_run_command("ethtool -i dummy1_ > /dev/null") == 0;
-    if (ethtool_support) {
-        g_assert(nmp_utils_ethtool_get_driver_info(
-            nmtstp_link_get_typed(platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex,
-            &driver_info));
-        g_assert(nmp_utils_ethtool_get_driver_info(
-            nmtstp_link_get_typed(platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex,
-            &driver_info));
-        g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0);
-        g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2a > /dev/null"), ==, 0);
-        g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2b 2> /dev/null"), !=, 0);
-    }
-
-    g_assert(nm_platform_netns_push(platform_2, &netns_tmp));
-
-    if (ethtool_support) {
-        g_assert(nmp_utils_ethtool_get_driver_info(
-            nmtstp_link_get_typed(platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex,
-            &driver_info));
-        g_assert(nmp_utils_ethtool_get_driver_info(
-            nmtstp_link_get_typed(platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex,
-            &driver_info));
-        g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0);
-        g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2a 2> /dev/null"), !=, 0);
-        g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2b > /dev/null"), ==, 0);
-    }
-
-    nmp_netns_pop(netns_tmp);
-}
-
-/*****************************************************************************/
-
-static void
-test_netns_set_netns(gpointer fixture, gconstpointer test_data)
-{
-    NMPlatform *    platforms[3];
-    gs_unref_object NMPlatform *platform_0 = NULL;
-    gs_unref_object NMPlatform *platform_1 = NULL;
-    gs_unref_object NMPlatform *platform_2 = NULL;
-    nm_auto_pop_netns NMPNetns *netns_pop  = NULL;
-
-    if (_test_netns_check_skip())
-        return;
-
-    platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE);
-    platforms[1] = platform_1 = _test_netns_create_platform();
-    platforms[2] = platform_2 = _test_netns_create_platform();
-
-    nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop);
-
-#define LINK_MOVE_NAME "link-move"
-    g_assert(!nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME));
-    g_assert(!nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME));
-    _ADD_DUMMY(platform_1, LINK_MOVE_NAME);
-    g_assert(nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME));
-    g_assert(!nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME));
-    g_assert(nm_platform_link_set_netns(
-        platform_1,
-        nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME)->ifindex,
-        nmp_netns_get_fd_net(nm_platform_netns_get(platform_2))));
-    g_assert(!nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME));
-    g_assert(!nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME));
-    nmtstp_assert_wait_for_link(platform_2, LINK_MOVE_NAME, NM_LINK_TYPE_DUMMY, 100);
-    g_assert(!nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME));
-    g_assert(nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME));
-}
-
-/*****************************************************************************/
-
-static char *
-_get_current_namespace_id(int ns_type)
-{
-    const char *p;
-    GError *    error = NULL;
-    char *      id;
-
-    switch (ns_type) {
-    case CLONE_NEWNET:
-        p = "/proc/self/ns/net";
-        break;
-    case CLONE_NEWNS:
-        p = "/proc/self/ns/mnt";
-        break;
-    default:
-        g_assert_not_reached();
-    }
-
-    id = g_file_read_link(p, &error);
-    g_assert_no_error(error);
-    g_assert(id);
-    return id;
-}
-
-static char *
-_get_sysctl_value(const char *path)
-{
-    char *        data          = NULL;
-    gs_free_error GError *error = NULL;
-
-    if (!g_file_get_contents(path, &data, NULL, &error)) {
-        nmtst_assert_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, NULL);
-        g_assert(!data);
-    } else {
-        g_assert_no_error(error);
-        g_assert(data);
-        g_strstrip(data);
-    }
-    return data;
-}
-
-static void
-test_netns_push(gpointer fixture, gconstpointer test_data)
-{
-    gs_unref_object NMPlatform *platform_0    = NULL;
-    gs_unref_object NMPlatform *platform_1    = NULL;
-    gs_unref_object NMPlatform *platform_2    = NULL;
-    nm_auto_pop_netns NMPNetns *netns_pop     = NULL;
-    gs_unref_ptrarray GPtrArray *device_names = g_ptr_array_new_with_free_func(g_free);
-    int                          i, j;
-    const int ns_types_list[] = {CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWNET | CLONE_NEWNS};
-    const int ns_types_test[] = {CLONE_NEWNET, CLONE_NEWNS};
-    typedef struct {
-        NMPlatform *platform;
-        const char *device_name;
-        const char *sysctl_path;
-        const char *sysctl_value;
-        const char *ns_net;
-        const char *ns_mnt;
-    } PlatformData;
-    PlatformData  pl[3] = {};
-    PlatformData *pl_base;
-    struct {
-        PlatformData *pl;
-        int           ns_types;
-    } stack[6] = {};
-    int nstack;
-
-    if (_test_netns_check_skip())
-        return;
-
-    if (_check_sysctl_skip())
-        return;
-
-    pl[0].platform = platform_0 = nm_linux_platform_new(TRUE, TRUE);
-    pl[1].platform = platform_1 = _test_netns_create_platform();
-    pl[2].platform = platform_2 = _test_netns_create_platform();
-
-    pl_base = &pl[0];
-    i       = nmtst_get_rand_uint32() % (G_N_ELEMENTS(pl) + 1);
-    if (i < G_N_ELEMENTS(pl)) {
-        pl_base = &pl[i];
-        g_assert(nm_platform_netns_push(pl[i].platform, &netns_pop));
-    }
-
-    for (i = 0; i < G_N_ELEMENTS(pl); i++) {
-        nm_auto_pop_netns NMPNetns *netns_free = NULL;
-        char *                      tmp;
-
-        g_assert(nm_platform_netns_push(pl[i].platform, &netns_free));
-
-        tmp = g_strdup_printf("nmtst-dev-%d", i);
-        g_ptr_array_add(device_names, tmp);
-        pl[i].device_name = tmp;
-
-        tmp = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", pl[i].device_name);
-        g_ptr_array_add(device_names, tmp);
-        pl[i].sysctl_path = tmp;
-
-        pl[i].sysctl_value = nmtst_get_rand_uint32() % 2 ? "1" : "0";
-
-        _ADD_DUMMY(pl[i].platform, pl[i].device_name);
-
-        g_assert(nm_platform_sysctl_set(pl[i].platform,
-                                        NMP_SYSCTL_PATHID_ABSOLUTE(pl[i].sysctl_path),
-                                        pl[i].sysctl_value));
-
-        tmp = _get_current_namespace_id(CLONE_NEWNET);
-        g_ptr_array_add(device_names, tmp);
-        pl[i].ns_net = tmp;
-
-        tmp = _get_current_namespace_id(CLONE_NEWNS);
-        g_ptr_array_add(device_names, tmp);
-        pl[i].ns_mnt = tmp;
-    }
-
-    nstack = nmtst_get_rand_uint32() % (G_N_ELEMENTS(stack) + 1);
-    for (i = 0; i < nstack; i++) {
-        stack[i].pl       = &pl[nmtst_get_rand_uint32() % G_N_ELEMENTS(pl)];
-        stack[i].ns_types = ns_types_list[nmtst_get_rand_uint32() % G_N_ELEMENTS(ns_types_list)];
-
-        nmp_netns_push_type(nm_platform_netns_get(stack[i].pl->platform), stack[i].ns_types);
-    }
-
-    /* pop some again. */
-    for (i = nmtst_get_rand_uint32() % (nstack + 1); i > 0; i--) {
-        g_assert(nstack > 0);
-        nstack--;
-        nmp_netns_pop(nm_platform_netns_get(stack[nstack].pl->platform));
-    }
-
-    for (i = 0; i < G_N_ELEMENTS(ns_types_test); i++) {
-        int           ns_type = ns_types_test[i];
-        PlatformData *p;
-        gs_free char *current_namespace_id = NULL;
-
-        p = pl_base;
-        for (j = nstack; j >= 1;) {
-            j--;
-            if (NM_FLAGS_ANY(stack[j].ns_types, ns_type)) {
-                p = stack[j].pl;
-                break;
-            }
-        }
-
-        current_namespace_id = _get_current_namespace_id(ns_type);
-
-        if (ns_type == CLONE_NEWNET) {
-            g_assert_cmpstr(current_namespace_id, ==, p->ns_net);
-            for (j = 0; j < G_N_ELEMENTS(pl); j++) {
-                gs_free char *data = NULL;
-
-                if (p == &pl[j])
-                    g_assert_cmpint(
-                        nmtstp_run_command("ip link show %s 1>/dev/null", pl[j].device_name),
-                        ==,
-                        0);
-                else
-                    g_assert_cmpint(
-                        nmtstp_run_command("ip link show %s 2>/dev/null", pl[j].device_name),
-                        !=,
-                        0);
-
-                data = _get_sysctl_value(pl[j].sysctl_path);
-                if (p == &pl[j])
-                    g_assert_cmpstr(data, ==, pl[j].sysctl_value);
-                else
-                    g_assert(!data);
-            }
-        } else if (ns_type == CLONE_NEWNS) {
-            g_assert_cmpstr(current_namespace_id, ==, p->ns_mnt);
-            for (j = 0; j < G_N_ELEMENTS(pl); j++) {
-                char          path[600];
-                gs_free char *data = NULL;
-
-                nm_sprintf_buf(path, "/sys/devices/virtual/net/%s/ifindex", pl[j].device_name);
-
-                data = _get_sysctl_value(path);
-                if (p == &pl[j])
-                    g_assert_cmpstr(data,
-                                    ==,
-                                    nm_sprintf_buf(path,
-                                                   "%d",
-                                                   nmtstp_link_get_typed(p->platform,
-                                                                         0,
-                                                                         p->device_name,
-                                                                         NM_LINK_TYPE_DUMMY)
-                                                       ->ifindex));
-                else
-                    g_assert(!data);
-            }
-        } else
-            g_assert_not_reached();
-    }
-
-    for (i = nstack; i >= 1;) {
-        i--;
-        nmp_netns_pop(nm_platform_netns_get(stack[i].pl->platform));
-    }
-}
-
-/*****************************************************************************/
-
-static void
-test_netns_bind_to_path(gpointer fixture, gconstpointer test_data)
-{
-#define P_VAR_RUN                "/run"
-#define P_VAR_RUN_NETNS          "/run/netns"
-#define P_VAR_RUN_NETNS_BINDNAME "/run/netns/" P_NETNS_BINDNAME
-#define P_NETNS_BINDNAME         "nmtst-iproute2-netns"
-    gs_unref_object NMPlatform *platform_0 = NULL;
-    gs_unref_object NMPlatform *platform_1 = NULL;
-    gs_unref_object NMPlatform *platform_2 = NULL;
-    nm_auto_pop_netns NMPNetns *netns_pop  = NULL;
-    NMPlatform *                platforms[3];
-    NMPNetns *                  netns;
-    int                         i;
-
-    if (_test_netns_check_skip())
-        return;
-
-    platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE);
-    platforms[1] = platform_1 = _test_netns_create_platform();
-    platforms[2] = platform_2 = _test_netns_create_platform();
-
-    nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop);
-
-    g_assert_cmpint(
-        mount("tmpfs", P_VAR_RUN, "tmpfs", MS_NOATIME | MS_NODEV | MS_NOSUID, "mode=0755,size=32K"),
-        ==,
-        0);
-    g_assert_cmpint(mkdir(P_VAR_RUN_NETNS, 755), ==, 0);
-
-    i     = (nmtst_get_rand_uint32() % 2) + 1;
-    netns = nm_platform_netns_get(platforms[i]);
-
-    _ADD_DUMMY(platforms[i], "dummy2b");
-
-    g_assert(!g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS));
-    g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true 2>/dev/null"),
-                    !=,
-                    0);
-
-    g_assert(nmp_netns_bind_to_path(netns, P_VAR_RUN_NETNS_BINDNAME, NULL));
-
-    g_assert(g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS));
-    g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true"), ==, 0);
-    g_assert_cmpint(
-        nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " ip link show dummy2b 1>/dev/null"),
-        ==,
-        0);
-
-    g_assert(nmp_netns_bind_to_path_destroy(netns, P_VAR_RUN_NETNS_BINDNAME));
-
-    g_assert(!g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS));
-    g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true 2>/dev/null"),
-                    !=,
-                    0);
-
-    g_assert_cmpint(umount(P_VAR_RUN), ==, 0);
-}
-
-/*****************************************************************************/
-
-static void
-test_sysctl_rename(void)
-{
-    NMPlatform *const PL        = NM_PLATFORM_GET;
-    const char *const IFNAME[3] = {
-        "nm-dummy-0",
-        "nm-dummy-1",
-        "nm-dummy-2",
-    };
-    int                   ifindex[G_N_ELEMENTS(IFNAME)] = {0};
-    nm_auto_close int     dirfd                         = -1;
-    int                   i;
-    char                  ifname_buf[IFNAMSIZ];
-    char *                s;
-    const NMPlatformLink *pllink;
-
-    ifindex[0] = nmtstp_link_dummy_add(PL, -1, IFNAME[0])->ifindex;
-    ifindex[1] = nmtstp_link_dummy_add(PL, -1, IFNAME[1])->ifindex;
-
-    s = (nmtst_get_rand_uint32() % 2) ? NULL : ifname_buf;
-
-    if (nmtst_get_rand_uint32() % 2) {
-        /* bring the platform cache out of sync */
-        nmtstp_run_command_check("ip link set %s name %s", IFNAME[0], IFNAME[2]);
-        nm_platform_process_events(PL);
-        nmtstp_run_command_check("ip link set %s name %s", IFNAME[2], IFNAME[0]);
-
-        pllink = nm_platform_link_get_by_ifname(PL, IFNAME[2]);
-        g_assert(pllink && pllink->ifindex == ifindex[0]);
-        pllink = nm_platform_link_get_by_ifname(PL, IFNAME[0]);
-        g_assert(!pllink);
-    }
-
-    /* open dirfd for IFNAME[0] */
-    i = nmtst_get_rand_uint32() % (2 + G_N_ELEMENTS(IFNAME));
-    if (i == 0) {
-        dirfd = nm_platform_sysctl_open_netdir(PL, ifindex[0], s);
-    } else {
-        const char *ifname_guess;
-
-        /* provide a wrong or no guess. */
-        ifname_guess = i == 1 ? NULL : IFNAME[i - 2];
-        dirfd        = nmp_utils_sysctl_open_netdir(ifindex[0], ifname_guess, s);
-    }
-    g_assert(dirfd >= 0);
-    if (s)
-        g_assert_cmpstr(s, ==, IFNAME[0]);
-
-    /* possibly rename the interfaces. */
-    switch (nmtst_get_rand_uint32() % 4) {
-    case 0:
-        break;
-    case 1:
-        nmtstp_run_command_check("ip link set %s name %s", IFNAME[0], IFNAME[2]);
-        break;
-    case 2:
-        nmtstp_run_command_check("ip link set %s name %s", IFNAME[0], IFNAME[2]);
-        nmtstp_run_command_check("ip link set %s name %s", IFNAME[1], IFNAME[0]);
-        break;
-    }
-
-    /* possibly, resync platform cache (should make no difference). */
-    if (nmtst_get_rand_uint32() % 2)
-        nm_platform_process_events(PL);
-
-    /* check that we still read the same file. */
-    switch (nmtst_get_rand_uint32() % 2) {
-    case 0:
-    {
-        gs_free char *c = NULL;
-
-        if (!nm_utils_file_get_contents(dirfd,
-                                        "ifindex",
-                                        1 * 1024 * 1024,
-                                        NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
-                                        &c,
-                                        NULL,
-                                        NULL,
-                                        NULL))
-            g_assert_not_reached();
-        g_assert_cmpint(ifindex[0], ==, (int) _nm_utils_ascii_str_to_int64(c, 10, 0, G_MAXINT, -1));
-        break;
-    }
-    case 1:
-    {
-        g_assert_cmpint(ifindex[0],
-                        ==,
-                        (gint32) nm_platform_sysctl_get_int32(
-                            PL,
-                            NMP_SYSCTL_PATHID_NETDIR(dirfd, s ?: "<unknown>", "ifindex"),
-                            -1));
-        break;
-    }
-    }
-
-    nm_platform_process_events(PL);
-    nmtstp_link_delete(PL, -1, ifindex[0], NULL, TRUE);
-    nmtstp_link_delete(PL, -1, ifindex[1], NULL, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-test_sysctl_netns_switch(void)
-{
-    const char *const IFNAME = "nm-dummy-0";
-    int               ifindex, ifindex_tmp;
-    nm_auto_close int dirfd = -1;
-    char              ifname_buf[IFNAMSIZ];
-    char *            s;
-    gs_unref_object NMPlatform *platform_0  = NULL;
-    gs_unref_object NMPlatform *platform_1  = NULL;
-    gs_unref_object NMPlatform *platform_2  = NULL;
-    nm_auto_pop_netns NMPNetns *netns_pop_1 = NULL;
-    nm_auto_pop_netns NMPNetns *netns_pop_2 = NULL;
-    nm_auto_pop_netns NMPNetns *netns_pop_3 = NULL;
-    NMPlatform *                PL;
-    NMPlatform *                platforms[3];
-
-    if (_test_netns_check_skip())
-        return;
-
-    platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE);
-    platforms[1] = platform_1 = _test_netns_create_platform();
-    platforms[2] = platform_2 = _test_netns_create_platform();
-    PL                        = platforms[nmtst_get_rand_uint32() % 3];
-
-    nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop_1);
-
-    ifindex = nmtstp_link_dummy_add(PL, FALSE, IFNAME)->ifindex;
-
-    nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop_2);
-
-    s     = (nmtst_get_rand_uint32() % 2) ? NULL : ifname_buf;
-    dirfd = nm_platform_sysctl_open_netdir(PL, ifindex, s);
-    g_assert(dirfd >= 0);
-    if (s)
-        g_assert_cmpstr(s, ==, IFNAME);
-
-    nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop_3);
-
-    /* even if we switch to other namespaces, we can still lookup the path correctly,
-     * either using dirfd or via the platform instance (which switches namespace as needed). */
-    {
-        gs_free char *c = NULL;
-
-        if (!nm_utils_file_get_contents(dirfd,
-                                        "ifindex",
-                                        0,
-                                        NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
-                                        &c,
-                                        NULL,
-                                        NULL,
-                                        NULL))
-            g_assert_not_reached();
-        g_assert_cmpint(ifindex, ==, (int) _nm_utils_ascii_str_to_int64(c, 10, 0, G_MAXINT, -1));
-    }
-    g_assert_cmpint(ifindex,
-                    ==,
-                    (gint32) nm_platform_sysctl_get_int32(
-                        PL,
-                        NMP_SYSCTL_PATHID_NETDIR(dirfd, s ?: "<unknown>", "ifindex"),
-                        -1));
-    g_assert_cmpint(
-        ifindex,
-        ==,
-        (gint32) nm_platform_sysctl_get_int32(
-            PL,
-            NMP_SYSCTL_PATHID_ABSOLUTE(nm_sprintf_bufa(100, "/sys/class/net/%s/ifindex", IFNAME)),
-            -1));
-
-    /* also test that nm_platform_sysctl_get() sets errno to ENOENT for non-existing paths. */
-    {
-        gint64 i64;
-        int    errsv;
-        char * v;
-
-        errno = ESRCH;
-        v     = nm_platform_sysctl_get(
-            PL,
-            NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/not-existing/ifindex"));
-        errsv = errno;
-        g_assert(!v);
-        g_assert_cmpint(errsv, ==, ENOENT);
-
-        errno = ESRCH;
-        i64   = nm_platform_sysctl_get_int_checked(
-            PL,
-            NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/not-existing/ifindex"),
-            10,
-            1,
-            G_MAXINT,
-            -1);
-        errsv = errno;
-        g_assert_cmpint(i64, ==, -1);
-        g_assert_cmpint(errsv, ==, ENOENT);
-
-        errno = ESRCH;
-        v     = nm_platform_sysctl_get(
-            PL,
-            NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/lo/not-existing"));
-        errsv = errno;
-        g_assert(!v);
-        g_assert_cmpint(errsv, ==, ENOENT);
-
-        errno = ESRCH;
-        i64   = nm_platform_sysctl_get_int_checked(
-            PL,
-            NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/lo/not-existing"),
-            10,
-            1,
-            G_MAXINT,
-            -1);
-        errsv = errno;
-        g_assert_cmpint(i64, ==, -1);
-        g_assert_cmpint(errsv, ==, ENOENT);
-    }
-
-    /* accessing the path directly, only succeeds iff the current namespace happens to be the namespace
-     * in which we created the link. */
-    {
-        gs_free char *c = NULL;
-
-        if (!nm_utils_file_get_contents(-1,
-                                        nm_sprintf_bufa(100, "/sys/class/net/%s/ifindex", IFNAME),
-                                        0,
-                                        NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
-                                        &c,
-                                        NULL,
-                                        NULL,
-                                        NULL))
-            ifindex_tmp = -1;
-        else
-            ifindex_tmp = _nm_utils_ascii_str_to_int64(c, 10, 0, G_MAXINT, -2);
-    }
-    if (nmp_netns_get_current() == nm_platform_netns_get(PL))
-        g_assert_cmpint(ifindex_tmp, ==, ifindex);
-    else
-        g_assert_cmpint(ifindex_tmp, ==, -1);
-
-    nmtstp_link_delete(PL, FALSE, ifindex, NULL, TRUE);
-}
-
-typedef struct {
-    GMainLoop * loop;
-    const char *path;
-    gboolean    expected_success;
-    gint32      expected_value;
-} SetAsyncData;
-
-static void
-sysctl_set_async_cb(GError *error, gpointer user_data)
-{
-    SetAsyncData *data = user_data;
-
-    if (data->expected_success) {
-        g_assert_no_error(error);
-        g_assert_cmpint(nm_platform_sysctl_get_int32(NM_PLATFORM_GET,
-                                                     NMP_SYSCTL_PATHID_ABSOLUTE(data->path),
-                                                     -1),
-                        ==,
-                        data->expected_value);
-    } else
-        g_assert(error);
-
-    g_main_loop_quit(data->loop);
-}
-
-static void
-test_sysctl_set_async(void)
-{
-    NMPlatform *const PL     = NM_PLATFORM_GET;
-    const char *const IFNAME = "nm-dummy-0";
-    const char *const PATH   = "/proc/sys/net/ipv4/conf/nm-dummy-0/rp_filter";
-    GMainLoop *       loop;
-    gs_unref_object GCancellable *cancellable = NULL;
-    gboolean                      proc_writable;
-    SetAsyncData                  data;
-    int                           ifindex;
-
-    ifindex       = nmtstp_link_dummy_add(PL, -1, IFNAME)->ifindex;
-    loop          = g_main_loop_new(NULL, FALSE);
-    cancellable   = g_cancellable_new();
-    proc_writable = access(PATH, W_OK) == 0;
-
-    data = (SetAsyncData){
-        .loop             = loop,
-        .path             = PATH,
-        .expected_success = proc_writable,
-        .expected_value   = 2,
-    };
-
-    nm_platform_sysctl_set_async(PL,
-                                 NMP_SYSCTL_PATHID_ABSOLUTE(PATH),
-                                 (const char *[]){"2", NULL},
-                                 sysctl_set_async_cb,
-                                 &data,
-                                 cancellable);
-
-    if (!nmtst_main_loop_run(loop, 1000))
-        g_assert_not_reached();
-
-    data = (SetAsyncData){
-        .loop             = loop,
-        .path             = PATH,
-        .expected_success = proc_writable,
-        .expected_value   = 1,
-    };
-
-    nm_platform_sysctl_set_async(PL,
-                                 NMP_SYSCTL_PATHID_ABSOLUTE(PATH),
-                                 (const char *[]){"2", "0", "1", "0", "1", NULL},
-                                 sysctl_set_async_cb,
-                                 &data,
-                                 cancellable);
-
-    if (!nmtst_main_loop_run(loop, 2000))
-        g_assert_not_reached();
-
-    nmtstp_link_delete(NULL, -1, ifindex, IFNAME, TRUE);
-    g_main_loop_unref(loop);
-}
-
-static void
-test_sysctl_set_async_fail(void)
-{
-    NMPlatform *const PL     = NM_PLATFORM_GET;
-    const char *const IFNAME = "nm-dummy-0";
-    const char *const PATH   = "/proc/sys/net/ipv4/conf/nm-dummy-0/does-not-exist";
-    GMainLoop *       loop;
-    gs_unref_object GCancellable *cancellable = NULL;
-    SetAsyncData                  data;
-    int                           ifindex;
-
-    ifindex     = nmtstp_link_dummy_add(PL, -1, IFNAME)->ifindex;
-    loop        = g_main_loop_new(NULL, FALSE);
-    cancellable = g_cancellable_new();
-
-    data = (SetAsyncData){
-        .loop             = loop,
-        .path             = PATH,
-        .expected_success = FALSE,
-    };
-
-    nm_platform_sysctl_set_async(PL,
-                                 NMP_SYSCTL_PATHID_ABSOLUTE(PATH),
-                                 (const char *[]){"2", NULL},
-                                 sysctl_set_async_cb,
-                                 &data,
-                                 cancellable);
-
-    if (!nmtst_main_loop_run(loop, 1000))
-        g_assert_not_reached();
-
-    nmtstp_link_delete(NULL, -1, ifindex, IFNAME, TRUE);
-    g_main_loop_unref(loop);
-}
-
-/*****************************************************************************/
-
-static gpointer
-_test_netns_mt_thread(gpointer data)
-{
-    NMPNetns *      netns1           = data;
-    gs_unref_object NMPNetns *netns2 = NULL;
-    NMPNetns *                netns_bottom;
-    NMPNetns *                initial;
-
-    netns_bottom = nmp_netns_get_initial();
-    g_assert(netns_bottom);
-
-    /* I don't know why, but we need to create a new netns here at least once.
-     * Otherwise, setns(, CLONE_NEWNS) below fails with EINVAL (???).
-     *
-     * Something is not right here, but what?  */
-    netns2 = nmp_netns_new();
-    nmp_netns_pop(netns2);
-    g_clear_object(&netns2);
-
-    nmp_netns_push(netns1);
-    nmp_netns_push_type(netns_bottom, CLONE_NEWNET);
-    nmp_netns_push_type(netns_bottom, CLONE_NEWNS);
-    nmp_netns_push_type(netns1, CLONE_NEWNS);
-    nmp_netns_pop(netns1);
-    nmp_netns_pop(netns_bottom);
-    nmp_netns_pop(netns_bottom);
-    nmp_netns_pop(netns1);
-
-    initial = nmp_netns_get_initial();
-    g_assert(NMP_IS_NETNS(initial));
-    return g_object_ref(initial);
-}
-
-static void
-test_netns_mt(void)
-{
-    gs_unref_object NMPNetns *netns1 = NULL;
-    NMPNetns *                initial_from_other_thread;
-    GThread *                 th;
-
-    if (_test_netns_check_skip())
-        return;
-
-    netns1 = nmp_netns_new();
-    g_assert(NMP_NETNS(netns1));
-    nmp_netns_pop(netns1);
-
-    th                        = g_thread_new("nm-test-netns-mt", _test_netns_mt_thread, netns1);
-    initial_from_other_thread = g_thread_join(th);
-    g_assert(NMP_IS_NETNS(initial_from_other_thread));
-
-    if (nmtst_get_rand_bool()) {
-        nmp_netns_push(initial_from_other_thread);
-        nmp_netns_pop(initial_from_other_thread);
-    }
-
-    g_object_add_weak_pointer(G_OBJECT(initial_from_other_thread),
-                              (gpointer *) &initial_from_other_thread);
-    g_object_unref(initial_from_other_thread);
-    g_assert(initial_from_other_thread == NULL);
-}
-
-/*****************************************************************************/
-
-static void
-ethtool_features_dump(const NMEthtoolFeatureStates *features)
-{
-    guint i, j;
-
-    g_assert(features);
-
-    _LOGT(">>> %u features (%u ss-features)", features->n_states, features->n_ss_features);
-
-    for (i = 0; i < features->n_states; i++) {
-        const NMEthtoolFeatureState *s = &features->states_list[i];
-
-        _LOGT(">>> feature-list[%3u]: %3d = %-32s (%3u) | %s %s %s %s",
-              i,
-              (int) s->info->ethtool_id,
-              s->info->kernel_names[s->idx_kernel_name],
-              s->idx_ss_features,
-              s->active ? "ACT" : "act",
-              s->available ? "AVA" : "ava",
-              s->never_changed ? "NCH" : "nch",
-              s->requested ? "REQ" : "req");
-    }
-    for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) {
-        _LOGT(">>> feature-idx [%3u]: %-32s = %u features",
-              i + (guint) _NM_ETHTOOL_ID_FEATURE_FIRST,
-              nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname,
-              (guint) NM_PTRARRAY_LEN(features->states_indexed[i]));
-        for (j = 0; features->states_indexed[i] && features->states_indexed[i][j]; j++) {
-            const NMEthtoolFeatureState *s = features->states_indexed[i][j];
-
-            _LOGT(">>>  %3u: %-32s | %s %s %s %s",
-                  j,
-                  s->info->kernel_names[s->idx_kernel_name],
-                  s->active ? "ACT" : "act",
-                  s->available ? "AVA" : "ava",
-                  s->never_changed ? "NCH" : "nch",
-                  s->requested ? "REQ" : "req");
-        }
-    }
-}
-
-static void
-test_ethtool_features_get(void)
-{
-    gs_unref_ptrarray GPtrArray *gfree_keeper = g_ptr_array_new_with_free_func(g_free);
-    const int                    IFINDEX      = 1;
-    guint                        i;
-    guint                        i_run;
-
-    for (i_run = 0; i_run < 5; i_run++) {
-        NMEthtoolFeatureStates *features;
-        NMTernary *             requested;
-        gboolean                do_set = TRUE;
-
-        requested = g_new(NMTernary, _NM_ETHTOOL_ID_FEATURE_NUM);
-        for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++)
-            requested[i] = NM_TERNARY_DEFAULT;
-        g_ptr_array_add(gfree_keeper, requested);
-
-        if (i_run == 0) {
-            requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_RX)]  = NM_TERNARY_FALSE;
-            requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE;
-            requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] =
-                NM_TERNARY_FALSE;
-        } else if (i_run == 1)
-            do_set = FALSE;
-        else if (i_run == 2) {
-            requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE;
-            requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] =
-                NM_TERNARY_TRUE;
-        } else if (i_run == 3)
-            do_set = FALSE;
-
-        _LOGT(">>> ethtool-features-get RUN %u (do-set=%s", i_run, do_set ? "set" : "reset");
-
-        features = nmp_utils_ethtool_get_features(IFINDEX);
-        g_ptr_array_add(gfree_keeper, features);
-
-        ethtool_features_dump(features);
-
-        if (_LOGT_ENABLED())
-            _system("ethtool -k lo");
-
-        if (!do_set) {
-            requested = gfree_keeper->pdata[i_run * 2 - 2];
-            features  = gfree_keeper->pdata[i_run * 2 - 1];
-        }
-
-        nmp_utils_ethtool_set_features(IFINDEX, features, requested, do_set);
-    }
-}
-
-/*****************************************************************************/
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
-    nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-void
-_nmtstp_setup_tests(void)
-{
-    nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE);
-    nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, SLAVE_NAME, FALSE);
-    nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, PARENT_NAME, FALSE);
-    g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME));
-    g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, SLAVE_NAME));
-    g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, PARENT_NAME));
-
-    g_test_add_func("/link/bogus", test_bogus);
-    g_test_add_func("/link/loopback", test_loopback);
-    g_test_add_func("/link/internal", test_internal);
-    g_test_add_func("/link/software/bridge", test_bridge);
-    g_test_add_func("/link/software/bond", test_bond);
-    g_test_add_func("/link/software/team", test_team);
-    g_test_add_func("/link/software/vlan", test_vlan);
-    g_test_add_func("/link/software/bridge/addr", test_bridge_addr);
-
-    if (nmtstp_is_root_test()) {
-        g_test_add_func("/link/external", test_external);
-
-        test_software_detect_add("/link/software/detect/bridge", NM_LINK_TYPE_BRIDGE, 0);
-        test_software_detect_add("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0);
-        test_software_detect_add("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0);
-        test_software_detect_add("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);
-        test_software_detect_add("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1);
-        test_software_detect_add("/link/software/detect/ip6gre", NM_LINK_TYPE_IP6GRE, 0);
-        test_software_detect_add("/link/software/detect/ip6gretap", NM_LINK_TYPE_IP6GRETAP, 0);
-        test_software_detect_add("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0);
-        test_software_detect_add("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0);
-        test_software_detect_add("/link/software/detect/macvtap", NM_LINK_TYPE_MACVTAP, 0);
-        test_software_detect_add("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0);
-        test_software_detect_add("/link/software/detect/tun", NM_LINK_TYPE_TUN, 0);
-        test_software_detect_add("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0);
-        test_software_detect_add("/link/software/detect/vrf", NM_LINK_TYPE_VRF, 0);
-        test_software_detect_add("/link/software/detect/vxlan/0", NM_LINK_TYPE_VXLAN, 0);
-        test_software_detect_add("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1);
-        test_software_detect_add("/link/software/detect/wireguard/0", NM_LINK_TYPE_WIREGUARD, 0);
-        test_software_detect_add("/link/software/detect/wireguard/1", NM_LINK_TYPE_WIREGUARD, 1);
-        test_software_detect_add("/link/software/detect/wireguard/2", NM_LINK_TYPE_WIREGUARD, 2);
-
-        g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress);
-
-        g_test_add_data_func("/link/create-many-links/20",
-                             GUINT_TO_POINTER(20),
-                             test_create_many_links);
-        g_test_add_data_func("/link/create-many-links/1000",
-                             GUINT_TO_POINTER(1000),
-                             test_create_many_links);
-
-        g_test_add_func("/link/nl-bugs/veth", test_nl_bugs_veth);
-        g_test_add_func("/link/nl-bugs/spurious-newlink", test_nl_bugs_spuroius_newlink);
-        g_test_add_func("/link/nl-bugs/spurious-dellink", test_nl_bugs_spuroius_dellink);
-
-        g_test_add_vtable("/general/netns/general",
-                          0,
-                          NULL,
-                          _test_netns_setup,
-                          test_netns_general,
-                          _test_netns_teardown);
-        g_test_add_vtable("/general/netns/set-netns",
-                          0,
-                          NULL,
-                          _test_netns_setup,
-                          test_netns_set_netns,
-                          _test_netns_teardown);
-        g_test_add_vtable("/general/netns/push",
-                          0,
-                          NULL,
-                          _test_netns_setup,
-                          test_netns_push,
-                          _test_netns_teardown);
-        g_test_add_vtable("/general/netns/bind-to-path",
-                          0,
-                          NULL,
-                          _test_netns_setup,
-                          test_netns_bind_to_path,
-                          _test_netns_teardown);
-
-        g_test_add_func("/general/netns/mt", test_netns_mt);
-
-        g_test_add_func("/general/sysctl/rename", test_sysctl_rename);
-        g_test_add_func("/general/sysctl/netns-switch", test_sysctl_netns_switch);
-        g_test_add_func("/general/sysctl/set-async", test_sysctl_set_async);
-        g_test_add_func("/general/sysctl/set-async-fail", test_sysctl_set_async_fail);
-
-        g_test_add_func("/link/ethtool/features/get", test_ethtool_features_get);
-    }
-}
diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c
deleted file mode 100644
index e61e6b09..00000000
--- a/src/platform/tests/test-nmp-object.c
+++ /dev/null
@@ -1,617 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2015 - 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include <libudev.h>
-#include <linux/pkt_sched.h>
-
-#include "platform/nmp-object.h"
-#include "nm-udev-aux/nm-udev-utils.h"
-
-#include "nm-test-utils-core.h"
-
-struct {
-    GList *udev_devices;
-} global;
-
-/*****************************************************************************/
-
-static void
-test_obj_base(void)
-{
-    static const union {
-        GObject   g;
-        NMPObject k;
-    } x = {};
-    static const union {
-        GTypeClass k;
-        NMPClass   c;
-    } l                        = {};
-    static const GObject *   g = &x.g;
-    static const GTypeClass *k = &l.k;
-    static const NMPObject * o = &x.k;
-    static const NMPClass *  c = &l.c;
-
-    NMObjBaseInst * obj;
-    gs_unref_object GCancellable *obj_cancellable = g_cancellable_new();
-    nm_auto_nmpobj NMPObject *obj_link            = nmp_object_new_link(10);
-
-    g_assert(&g->g_type_instance == (void *) &o->_class);
-    g_assert(&g->g_type_instance.g_class == (void *) &o->_class);
-
-    g_assert(sizeof(o->parent.parent) == sizeof(GTypeInstance));
-
-    g_assert(&c->parent == (void *) c);
-    g_assert(&c->parent.parent.g_type_class == (void *) c);
-    g_assert(&c->parent.parent.g_type == (void *) c);
-    g_assert(&c->parent.parent.g_type == &k->g_type);
-
-    g_assert(sizeof(c->parent.parent) == sizeof(GTypeClass));
-
-    g_assert(&o->parent == (void *) o);
-    g_assert(&o->parent.klass == (void *) &o->_class);
-
-    obj = (NMObjBaseInst *) obj_cancellable;
-    g_assert(!NMP_CLASS_IS_VALID((NMPClass *) obj->klass));
-    g_assert(G_TYPE_CHECK_INSTANCE_TYPE(obj, G_TYPE_CANCELLABLE));
-
-    obj = (NMObjBaseInst *) obj_link;
-    g_assert(NMP_CLASS_IS_VALID((NMPClass *) obj->klass));
-    g_assert(!G_TYPE_CHECK_INSTANCE_TYPE(obj, G_TYPE_CANCELLABLE));
-}
-
-/*****************************************************************************/
-
-static gboolean
-_nmp_object_id_equal(const NMPObject *a, const NMPObject *b)
-{
-    gboolean a_b = nmp_object_id_equal(a, b);
-
-    g_assert(NM_IN_SET(a_b, FALSE, TRUE) && a_b == nmp_object_id_equal(b, a));
-    return a_b;
-}
-#define nmp_object_id_equal _nmp_object_id_equal
-
-static gboolean
-_nmp_object_equal(const NMPObject *a, const NMPObject *b)
-{
-    gboolean a_b = nmp_object_equal(a, b);
-
-    g_assert(NM_IN_SET(a_b, FALSE, TRUE) && a_b == nmp_object_equal(b, a));
-    return a_b;
-}
-#define nmp_object_equal _nmp_object_equal
-
-/*****************************************************************************/
-
-static void
-_assert_cache_multi_lookup_contains(const NMPCache *             cache,
-                                    const NMDedupMultiHeadEntry *head_entry,
-                                    const NMPObject *            obj,
-                                    gboolean                     visible_only,
-                                    gboolean                     contains)
-{
-    NMDedupMultiIter iter;
-    gboolean         found;
-    guint            i, len;
-    const NMPObject *o;
-
-    g_assert(NMP_OBJECT_IS_VALID(obj));
-
-    g_assert(nmp_cache_lookup_obj(cache, obj) == obj);
-    g_assert(!head_entry
-             || (head_entry->len > 0
-                 && c_list_length(&head_entry->lst_entries_head) == head_entry->len));
-
-    len = head_entry ? head_entry->len : 0;
-
-    found = FALSE;
-    i     = 0;
-    nmp_cache_iter_for_each (&iter, head_entry, &o) {
-        g_assert(NMP_OBJECT_IS_VALID(o));
-        if (obj == o) {
-            if (!visible_only || nmp_object_is_visible(o)) {
-                g_assert(!found);
-                found = TRUE;
-            }
-        }
-        i++;
-    }
-
-    g_assert(len == i);
-    g_assert(!!contains == found);
-}
-
-static void
-_assert_cache_multi_lookup_contains_link(const NMPCache * cache,
-                                         gboolean         visible_only,
-                                         const NMPObject *obj,
-                                         gboolean         contains)
-{
-    const NMDedupMultiHeadEntry *head_entry;
-    NMPLookup                    lookup;
-
-    g_assert(cache);
-
-    nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK);
-    head_entry = nmp_cache_lookup(cache, &lookup);
-    _assert_cache_multi_lookup_contains(cache, head_entry, obj, visible_only, contains);
-}
-
-/*****************************************************************************/
-
-static void
-ops_post_check(NMPCache *       cache,
-               NMPCacheOpsType  ops_type,
-               const NMPObject *obj_old,
-               const NMPObject *obj_new,
-               const NMPObject *obj_new_expected,
-               NMPCacheOpsType  expected_ops_type)
-{
-    g_assert(cache);
-
-    g_assert_cmpint(expected_ops_type, ==, ops_type);
-
-    switch (ops_type) {
-    case NMP_CACHE_OPS_ADDED:
-        g_assert(!obj_old);
-        g_assert(NMP_OBJECT_IS_VALID(obj_new));
-        g_assert(nmp_object_is_alive(obj_new));
-        g_assert(nmp_object_id_equal(obj_new_expected, obj_new));
-        g_assert(nmp_object_equal(obj_new_expected, obj_new));
-        break;
-    case NMP_CACHE_OPS_UPDATED:
-        g_assert(obj_old != obj_new);
-        g_assert(NMP_OBJECT_IS_VALID(obj_old));
-        g_assert(NMP_OBJECT_IS_VALID(obj_new));
-        g_assert(nmp_object_is_alive(obj_old));
-        g_assert(nmp_object_is_alive(obj_new));
-        g_assert(nmp_object_id_equal(obj_new_expected, obj_new));
-        g_assert(nmp_object_id_equal(obj_new_expected, obj_old));
-        g_assert(nmp_object_id_equal(obj_old, obj_new));
-        g_assert(nmp_object_equal(obj_new_expected, obj_new));
-        g_assert(!nmp_object_equal(obj_new_expected, obj_old));
-        g_assert(!nmp_object_equal(obj_old, obj_new));
-        break;
-    case NMP_CACHE_OPS_REMOVED:
-        g_assert(!obj_new);
-        g_assert(NMP_OBJECT_IS_VALID(obj_old));
-        g_assert(nmp_object_is_alive(obj_old));
-        if (obj_new_expected)
-            g_assert(nmp_object_id_equal(obj_new_expected, obj_old));
-        break;
-    case NMP_CACHE_OPS_UNCHANGED:
-        g_assert(obj_old == obj_new);
-        if (obj_old) {
-            g_assert(NMP_OBJECT_IS_VALID(obj_old));
-            g_assert(nmp_object_is_alive(obj_old));
-            g_assert(nmp_object_equal(obj_old, obj_new));
-            g_assert(nmp_object_id_equal(obj_new_expected, obj_new));
-        } else
-            g_assert(!obj_new_expected);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-}
-
-static void
-_nmp_cache_update_netlink(NMPCache *        cache,
-                          NMPObject *       obj,
-                          const NMPObject **out_obj_old,
-                          const NMPObject **out_obj_new,
-                          NMPCacheOpsType   expected_ops_type)
-{
-    NMPCacheOpsType  ops_type;
-    const NMPObject *obj_prev;
-    const NMPObject *obj_old;
-    const NMPObject *obj_new;
-    nm_auto_nmpobj NMPObject *obj_new_expected = NULL;
-
-    g_assert(cache);
-    g_assert(NMP_OBJECT_IS_VALID(obj));
-
-    obj_prev         = nmp_cache_lookup_link(cache, NMP_OBJECT_CAST_LINK(obj)->ifindex);
-    obj_new_expected = nmp_object_clone(obj, FALSE);
-    if (obj_prev && obj_prev->_link.udev.device)
-        obj_new_expected->_link.udev.device = udev_device_ref(obj_prev->_link.udev.device);
-    _nmp_object_fixup_link_udev_fields(&obj_new_expected, NULL, nmp_cache_use_udev_get(cache));
-
-    ops_type = nmp_cache_update_netlink(cache, obj, FALSE, &obj_old, &obj_new);
-    ops_post_check(cache,
-                   ops_type,
-                   obj_old,
-                   obj_new,
-                   nmp_object_is_alive(obj_new_expected) ? obj_new_expected : NULL,
-                   expected_ops_type);
-
-    if (out_obj_new)
-        *out_obj_new = obj_new;
-    else
-        nmp_object_unref(obj_new);
-    if (out_obj_old)
-        *out_obj_old = obj_old;
-    else
-        nmp_object_unref(obj_old);
-}
-
-static const NMPlatformLink pl_link_2 = {
-    .ifindex = 2,
-    .name    = "eth0",
-    .type    = NM_LINK_TYPE_ETHERNET,
-};
-
-static const NMPlatformLink pl_link_3 = {
-    .ifindex = 3,
-    .name    = "wlan0",
-    .type    = NM_LINK_TYPE_WIFI,
-};
-
-static void
-test_cache_link(void)
-{
-    NMPCache *                      cache;
-    NMPObject *                     objm1;
-    const NMPObject *               obj_old, *obj_new;
-    NMPObject                       objs1;
-    struct udev_device *            udev_device_2 = g_list_nth_data(global.udev_devices, 0);
-    struct udev_device *            udev_device_3 = g_list_nth_data(global.udev_devices, 0);
-    NMPCacheOpsType                 ops_type;
-    nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL;
-    gboolean                                           use_udev  = nmtst_get_rand_uint32() % 2;
-
-    multi_idx = nm_dedup_multi_index_new();
-
-    cache = nmp_cache_new(multi_idx, use_udev);
-
-    /* if we have a link, and don't set is_in_netlink, adding it has no effect. */
-    objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
-    g_assert(NMP_OBJECT_UP_CAST(&objm1->object) == objm1);
-    g_assert(!nmp_object_is_alive(objm1));
-    _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED);
-    nmtst_assert_nmp_cache_is_consistent(cache);
-    g_assert(!obj_old);
-    g_assert(!obj_new);
-    g_assert(!nmp_cache_lookup_obj(cache, objm1));
-    g_assert(!nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)));
-    nmp_object_unref(objm1);
-
-    /* Only when setting @is_in_netlink the link is added. */
-    objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
-    objm1->_link.netlink.is_in_netlink = TRUE;
-    g_assert(nmp_object_is_alive(objm1));
-    _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_ADDED);
-    nmtst_assert_nmp_cache_is_consistent(cache);
-    g_assert(!obj_old);
-    g_assert(obj_new);
-    g_assert(objm1 == obj_new);
-    g_assert(nmp_object_equal(objm1, obj_new));
-    g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new);
-    g_assert(nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))
-             == obj_new);
-    g_assert(nmp_object_is_visible(obj_new));
-    _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-    _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE);
-    nmp_object_unref(objm1);
-    nmp_object_unref(obj_new);
-
-    /* updating the same link with identical value, has no effect. */
-    objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
-    objm1->_link.netlink.is_in_netlink = TRUE;
-    g_assert(nmp_object_is_alive(objm1));
-    _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED);
-    nmtst_assert_nmp_cache_is_consistent(cache);
-    g_assert(obj_old);
-    g_assert(obj_new);
-    g_assert(obj_new != objm1);
-    g_assert(nmp_object_equal(objm1, obj_new));
-    g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new);
-    g_assert(nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))
-             == obj_new);
-    nmp_object_unref(objm1);
-    nmp_object_unref(obj_new);
-    nmp_object_unref(obj_new);
-
-    /* remove the link from netlink */
-    objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
-    g_assert(!nmp_object_is_alive(objm1));
-    _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_REMOVED);
-    nmtst_assert_nmp_cache_is_consistent(cache);
-    g_assert(obj_old);
-    g_assert(!obj_new);
-    g_assert(!nmp_cache_lookup_obj(cache, objm1));
-    g_assert(!nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)));
-    nmp_object_unref(objm1);
-    nmp_object_unref(obj_old);
-    nmp_object_unref(obj_new);
-
-    if (udev_device_2) {
-        /* now add the link only with aspect UDEV. */
-        ops_type =
-            nmp_cache_update_link_udev(cache, pl_link_2.ifindex, udev_device_2, &obj_old, &obj_new);
-        nmtst_assert_nmp_cache_is_consistent(cache);
-        g_assert_cmpint(ops_type, ==, NMP_CACHE_OPS_ADDED);
-        g_assert(!obj_old);
-        g_assert(obj_new);
-        g_assert(
-            nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))
-            == obj_new);
-        g_assert(!nmp_object_is_visible(obj_new));
-        _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, FALSE);
-        _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-        nmp_object_unref(obj_new);
-    }
-
-    /* add it in netlink too. */
-    objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
-    objm1->_link.netlink.is_in_netlink = TRUE;
-    g_assert(nmp_object_is_alive(objm1));
-    _nmp_cache_update_netlink(cache,
-                              objm1,
-                              &obj_old,
-                              &obj_new,
-                              udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED);
-    nmtst_assert_nmp_cache_is_consistent(cache);
-    if (udev_device_2) {
-        g_assert(obj_old);
-        g_assert(!nmp_object_is_visible(obj_old));
-    } else
-        g_assert(!obj_old);
-    g_assert(nmp_object_equal(objm1, obj_new));
-    g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new);
-    g_assert(nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))
-             == obj_new);
-    g_assert(nmp_object_is_visible(obj_new));
-    _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE);
-    _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-    nmp_object_unref(objm1);
-    nmp_object_unref(obj_old);
-    nmp_object_unref(obj_new);
-
-    /* remove again from netlink. */
-    objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
-    objm1->_link.netlink.is_in_netlink = FALSE;
-    g_assert(!nmp_object_is_alive(objm1));
-    _nmp_cache_update_netlink(cache,
-                              objm1,
-                              &obj_old,
-                              &obj_new,
-                              udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED);
-    nmtst_assert_nmp_cache_is_consistent(cache);
-    if (udev_device_2)
-        g_assert(obj_new == objm1);
-    else
-        g_assert(!obj_new);
-    g_assert(obj_old);
-    g_assert(nmp_object_is_alive(obj_old));
-    if (udev_device_2) {
-        g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new);
-        g_assert(
-            nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))
-            == obj_new);
-        g_assert(!nmp_object_is_visible(obj_new));
-        _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, FALSE);
-        _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-    } else {
-        g_assert(nmp_cache_lookup_obj(cache, objm1) == NULL);
-        g_assert(
-            nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))
-            == NULL);
-        g_assert(!nmp_object_is_alive(obj_new));
-        g_assert(!nmp_object_is_visible(obj_new));
-    }
-    nmp_object_unref(objm1);
-    nmp_object_unref(obj_old);
-    nmp_object_unref(obj_new);
-
-    /* now another link only with aspect UDEV. */
-    if (udev_device_3) {
-        /* now add the link only with aspect UDEV. */
-        ops_type =
-            nmp_cache_update_link_udev(cache, pl_link_3.ifindex, udev_device_3, &obj_old, &obj_new);
-        g_assert_cmpint(ops_type, ==, NMP_CACHE_OPS_ADDED);
-        nmtst_assert_nmp_cache_is_consistent(cache);
-        g_assert(NMP_OBJECT_IS_VALID(obj_new));
-        g_assert(!obj_old);
-        g_assert(!nmp_object_is_visible(obj_new));
-        g_assert(
-            nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_3.ifindex))
-            == obj_new);
-        _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, FALSE);
-        _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-        g_assert_cmpint(obj_new->_link.netlink.is_in_netlink, ==, FALSE);
-        g_assert_cmpint(obj_new->link.initialized, ==, FALSE);
-        nmp_object_unref(obj_new);
-
-        /* add it in netlink too. */
-        objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3);
-        objm1->_link.netlink.is_in_netlink = TRUE;
-        g_assert(nmp_object_is_alive(objm1));
-        _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UPDATED);
-        nmtst_assert_nmp_cache_is_consistent(cache);
-        g_assert(obj_old);
-        g_assert(obj_new == objm1);
-        g_assert(nmp_object_equal(objm1, obj_new));
-        g_assert(!obj_old || !nmp_object_is_visible(obj_old));
-        g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new);
-        g_assert(
-            nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_3.ifindex))
-            == obj_new);
-        g_assert(nmp_object_is_visible(obj_new));
-        _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE);
-        _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-        g_assert_cmpint(obj_new->_link.netlink.is_in_netlink, ==, TRUE);
-        g_assert_cmpint(obj_new->link.initialized, ==, TRUE);
-        nmp_object_unref(objm1);
-        nmp_object_unref(obj_old);
-        nmp_object_unref(obj_new);
-
-        /* remove UDEV. */
-        ops_type = nmp_cache_update_link_udev(cache, pl_link_3.ifindex, NULL, &obj_old, &obj_new);
-        g_assert_cmpint(ops_type, ==, NMP_CACHE_OPS_UPDATED);
-        nmtst_assert_nmp_cache_is_consistent(cache);
-        g_assert(obj_old && nmp_object_is_visible(obj_old));
-        g_assert(
-            nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_3.ifindex))
-            == obj_new);
-        g_assert(nmp_object_is_visible(obj_new));
-        _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE);
-        _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE);
-        g_assert_cmpint(obj_new->_link.netlink.is_in_netlink, ==, TRUE);
-        g_assert_cmpint(obj_new->link.initialized, ==, !nmp_cache_use_udev_get(cache));
-        nmp_object_unref(obj_new);
-        nmp_object_unref(obj_old);
-    }
-
-    nmp_cache_free(cache);
-}
-
-const char noqueue[]  = "noqueue";
-const char fq_codel[] = "fq_codel";
-const char ingress[]  = "ingress";
-
-static const NMPlatformQdisc pl_qdisc_1a = {
-    .ifindex     = 1,
-    .kind        = noqueue,
-    .addr_family = AF_UNSPEC,
-    .handle      = 0,
-    .parent      = TC_H_ROOT,
-    .info        = 0,
-};
-
-static const NMPlatformQdisc pl_qdisc_1b = {
-    .ifindex     = 1,
-    .kind        = fq_codel,
-    .addr_family = AF_UNSPEC,
-    .handle      = 0,
-    .parent      = TC_H_ROOT,
-    .info        = 0,
-};
-
-static const NMPlatformQdisc pl_qdisc_1c = {
-    .ifindex     = 1,
-    .kind        = ingress,
-    .addr_family = AF_UNSPEC,
-    .handle      = TC_H_MAKE(TC_H_INGRESS, 0),
-    .parent      = TC_H_INGRESS,
-    .info        = 0,
-};
-
-static const NMPlatformQdisc pl_qdisc_2 = {
-    .ifindex     = 2,
-    .kind        = fq_codel,
-    .addr_family = AF_UNSPEC,
-    .handle      = 0,
-    .parent      = TC_H_ROOT,
-    .info        = 0,
-};
-
-static void
-test_cache_qdisc(void)
-{
-    NMPCache *                      cache;
-    nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL;
-    NMPLookup                                          lookup;
-    const NMDedupMultiHeadEntry *                      head_entry;
-    nm_auto_nmpobj NMPObject *obj1a =
-        nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1a);
-    nm_auto_nmpobj NMPObject *obj1b =
-        nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1b);
-    nm_auto_nmpobj NMPObject *obj1c =
-        nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1c);
-    nm_auto_nmpobj NMPObject *obj2 =
-        nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_2);
-
-    multi_idx = nm_dedup_multi_index_new();
-    cache     = nmp_cache_new(multi_idx, nmtst_get_rand_uint32() % 2);
-
-    g_assert(nmp_cache_lookup_obj(cache, obj1a) == NULL);
-
-    g_assert(nmp_cache_update_netlink(cache, obj1a, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED);
-    g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1a);
-    g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1a);
-    g_assert(nmp_cache_lookup_obj(cache, obj2) == NULL);
-
-    g_assert(nmp_cache_update_netlink(cache, obj1b, FALSE, NULL, NULL) == NMP_CACHE_OPS_UPDATED);
-    g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1b);
-    g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1b);
-    g_assert(nmp_cache_lookup_obj(cache, obj2) == NULL);
-
-    g_assert(nmp_cache_update_netlink(cache, obj1c, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED);
-    g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1b);
-    g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1b);
-    g_assert(nmp_cache_lookup_obj(cache, obj1c) == obj1c);
-    g_assert(nmp_cache_lookup_obj(cache, obj2) == NULL);
-
-    g_assert(nmp_cache_update_netlink(cache, obj2, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED);
-    g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1b);
-    g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1b);
-    g_assert(nmp_cache_lookup_obj(cache, obj2) == obj2);
-
-    head_entry = nmp_cache_lookup(cache, nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_QDISC, 1));
-    g_assert(head_entry->len == 2);
-
-    nmp_cache_free(cache);
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-int
-main(int argc, char **argv)
-{
-    int           result;
-    NMUdevClient *udev_client;
-
-    nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT");
-
-    udev_client = nm_udev_client_new((const char *[]){"net", NULL}, NULL, NULL);
-    {
-        struct udev_enumerate * enumerator;
-        struct udev_list_entry *devices, *l;
-
-        enumerator = nm_udev_client_enumerate_new(udev_client);
-
-        /* Demand that the device is initialized (udev rules ran,
-         * device has a stable name now) in case udev is running
-         * (not in a container). */
-        if (access("/sys", W_OK) == 0)
-            udev_enumerate_add_match_is_initialized(enumerator);
-
-        udev_enumerate_scan_devices(enumerator);
-
-        devices = udev_enumerate_get_list_entry(enumerator);
-        for (l = devices; l != NULL; l = udev_list_entry_get_next(l)) {
-            struct udev_device *udevice;
-
-            udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator),
-                                                   udev_list_entry_get_name(l));
-            if (udevice == NULL)
-                continue;
-
-            global.udev_devices = g_list_prepend(global.udev_devices, udevice);
-        }
-        global.udev_devices = g_list_reverse(global.udev_devices);
-
-        udev_enumerate_unref(enumerator);
-    }
-
-    g_test_add_func("/nmp-object/obj-base", test_obj_base);
-    g_test_add_func("/nmp-object/cache_link", test_cache_link);
-    g_test_add_func("/nmp-object/cache_qdisc", test_cache_qdisc);
-
-    result = g_test_run();
-
-    while (global.udev_devices) {
-        udev_device_unref(global.udev_devices->data);
-        global.udev_devices = g_list_delete_link(global.udev_devices, global.udev_devices);
-    }
-
-    nm_udev_client_unref(udev_client);
-
-    return result;
-}
diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c
deleted file mode 100644
index 703c886e..00000000
--- a/src/platform/tests/test-platform-general.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2015 - 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include <linux/rtnetlink.h>
-
-#include "platform/nm-platform-utils.h"
-#include "platform/nm-linux-platform.h"
-
-#include "nm-test-utils-core.h"
-
-/*****************************************************************************/
-
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr)
-                == G_STRUCT_OFFSET(NMPlatformIP4Address, address));
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr)
-                == G_STRUCT_OFFSET(NMPlatformIP6Address, address));
-
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr)
-                == G_STRUCT_OFFSET(NMPlatformIP4Route, network));
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr)
-                == G_STRUCT_OFFSET(NMPlatformIP6Route, network));
-
-/*****************************************************************************/
-
-static void
-test_init_linux_platform(void)
-{
-    gs_unref_object NMPlatform *platform = NULL;
-
-    platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
-}
-
-/*****************************************************************************/
-
-static void
-test_link_get_all(void)
-{
-    gs_unref_object NMPlatform *platform = NULL;
-    gs_unref_ptrarray GPtrArray *links   = NULL;
-
-    platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
-
-    links = nm_platform_link_get_all(platform, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_platform_link_flags2str(void)
-{
-    int i;
-
-    for (i = 0; i < 100; i++) {
-        char        buf[NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 100];
-        const char *s;
-        const guint flags = ((i == 0) ? ~0u : nmtst_get_rand_uint());
-        gsize       l;
-
-        s = nm_platform_link_flags2str(flags, buf, sizeof(buf));
-        g_assert(s);
-
-        l = strlen(s);
-        if (l > NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN)
-            g_error(
-                "nm_platform_link_flags2str(%x) produced a longer output than %zu chars: \"%s\"",
-                flags,
-                NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN,
-                s);
-        if (flags == ~0u && l != NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN)
-            g_error("nm_platform_link_flags2str(%x) is expected to produce %zu chars, but produced "
-                    "%zu: \"%s\"",
-                    flags,
-                    NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN,
-                    l,
-                    s);
-    }
-}
-
-/*****************************************************************************/
-
-static int
-_address_pretty_sort_cmp(gconstpointer a, gconstpointer b, gpointer test_data)
-{
-    const int                   TEST_DATA_I      = GPOINTER_TO_INT(test_data);
-    const int                   addr_family      = (TEST_DATA_I == 0 ? AF_INET : AF_INET6);
-    const int                   IPV6_PREFER_TEMP = (TEST_DATA_I == 2);
-    const NMPlatformIPXAddress *a_a              = a;
-    const NMPlatformIPXAddress *a_b              = b;
-
-    if (addr_family == AF_INET)
-        return nm_platform_ip4_address_pretty_sort_cmp(&a_a->a4, &a_b->a4);
-
-    return nm_platform_ip6_address_pretty_sort_cmp(&a_a->a6, &a_b->a6, IPV6_PREFER_TEMP);
-}
-
-static void
-test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data)
-{
-    static const char *const EXPECTED_BUFFER[3] = {
-        [0] = ("5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218424e48836dd1cb504e03d53e1124c5"
-               "0065aeb2e6fbf952902383028e3b47f280f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a"
-               "8982c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000"
-               "883b0f3fd6ed84d6c959e553b887edcd01c2f5d200000043b809d259e499db7d00f1853bdcb0e4bc"
-               "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c400368b6630000007a"
-               "034f43340d01683c0045097aea4a849f060ddf57b24a5be9636360d603000000ad7c499dd538d345"
-               "74c038404923e75d0209e2fc0000004acc807cdce682f80f00315c45ef817264c89a736ed55ed637"
-               "b96c200203000000faf1809becd2506315a6da29b2e94d3a031fe0e900000083a36035fb6297dfa7"
-               "00686b5efd0d53bb6215de4bb6f6f3d031a79028030000008bb836c0a25ea71f5daaed4d99eb2ebe"
-               "033c432f000000bf4ccf30d3aaaf02a4005d7308b67f91bf9d82c856ba942455e8d07c8403000000"
-               "f2abb982b001ec16901f55f960c55c22022099a80000002b4d4647f53b1921af0088e3759a08e7a5"
-               "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf1402d3481e00000060"
-               "e89f7abdb682380a00eae374835b4a49a2b980b6aba92da6409969aa03000000e00473755d31e5b2"
-               "de252167c1c91b3a02ba0c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4"
-               "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348b00c12ebd000000ab667224dae775e5cc"
-               "0041aca2ff0f576767d3648102b61886d149f07403000000153ece68ade15cec25a59273e7519f34"
-               "c4458d70000000f3819aa46fbe1439340033ae6dec0fb124f264af67eed7c9a8ecc8fb1103000000"
-               "fcebbaeb0c56535923f14874042a8aff021f8e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b"
-               "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0029c44770000004b"
-               "2e69220d6c0fc09c25d6534c809829af4a9df58dbfef186d416f3a1e030000002c932e655203d82a"
-               "3c84c4eb274ed18603780281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b"
-               "69e66142030000004fda8a3e0b841cf76391dd68269b53ec0244a831000000b78c54dda9ac3bb1b1"
-               "d43e6505621b9a7f0422ae3fc8979ee0416f95e70300000057d6249b652ba98c7dc7f17f666969e4"
-               "023baf7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000"
-               "cd897619f51f44e644d7cf1d06b2b1150082549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3"
-               "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1c03c2056c00000051"
-               "bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0e5fe7d360300000066a3ae3939762df3"
-               "3a2d55060c78d55100b110fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b"
-               "86ed271803000000a5edc511c1507a141e0f515638c7ba31027609450000003357ae79989870ccec"
-               "3def0ad92749e016663fe6ee0228c1da82d1595603000000348352d715cf9d411ea012e5307294b6"
-               "0146dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000"
-               "862573c2303dd1d65c7b2cffeca6d1adaccae11f0000000f855ebf3b772eb2b1c896c9a7304f6645"
-               "0a5f6abd850b06e3b10123e6030000001dff045298cfee0636674cdefb57b9ae54cfe8f400000038"
-               "1ba2c4396de60f032bc7f34de2959871c0d4c0d4eb720c4ab550c5db03000000f32f4af595d785d5"
-               "c1b5aad487c192f08bd7a09b00000043288cd9bf66ec305a225a0c71b2ce78bb16104c8eaf18c565"
-               "b16c7376030000005219061ab4c5c79489b2cc6a883c146972decb8b000000f5e6d66df46ea13910"
-               "7754dee62c36d2fc70ccc567df7a49b8585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e"
-               "75039fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000"
-               "895d5f24037d233302ad3b82d639272e0246eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c"
-               "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8ec7e4b89bf5a5d0"
-               "6776e66a9d80ab132e1ac921eb76adbb229df32e561fa80a0fc4676703000000a23eb66e720da9e0"
-               "7ac998b5690807d50217369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a"
-               "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed03bb58f0e9201f17bd99fcf72909ac9e"
-               "7a55299e9bb4fd53bc7417940fcffe3f81cafd6302000000d6732578acd14320aefd4503189f7630"
-               "038e501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000"
-               "891715df7fc6a902edae579e2e10c7f7022ba0340436242cbeb0248cee3fbc160032d4f28aa28c08"
-               "f80dd50c6712dfb4abba4a32020000008ffe423d01883918039249f398f9b37ea091465100000064"
-               "3722d9b707c0d8a400b7c8307f06b4b29088f20d9ac676d5e4bafc4e02000000fde69eec3af2e6d0"
-               "bd68ab722af14548b29572e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea"
-               "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd6011fa56dfdcfc1155f236c8b9c79a620"
-               "00660bbf024b03ff0a8e27c405e64244e36f90d402000000fd41fe47684b370b6ec6584d64496089"
-               "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a119c64ed0402000000"
-               "a660ac824b7fae389861419c50da49bf02092583000000259f9f0251becc987907879cca68fec7bb"
-               "bb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6078a806d329c9b0000bfc972000000f5"
-               "b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f641e447502000000b9b68c08a5e4351e"
-               "a349e1ccf662e058b879a45100000045fcb6a035339d504c9726d80d9c2d89df765b4d9a130257dc"
-               "d1e1b34902000000bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46da"
-               "fe7d6ec4ac1ea051010911915ddb05f2c43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0"
-               "032d2ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000"
-               "18238487a417f3da01d99dae5f19009601582cab0000005b2363d13edc5aa115005eb914d8fbe9a4"
-               "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40267c3d400000064"
-               "9da90bd2fff2f2560046870bd7d5f14870c6d18d6242b356b9ef1b2101000000f90adac616a31dc2"
-               "e46a234558817151008fc9c900000073e64b0bd761fdf274005dca8ce1bd1871ae17bb4515856092"
-               "b4d9e89b010000006855676c277cf1bd017c9148da5892bb0351c3a70000009f3391ce7d3fd48469"
-               "005f0c233dbdd2a97835df1f1782dee86c1de913010000003ee1d76fc1ea76e98c9dfc78997ab53e"
-               "00c21963f5b4cb2454830c68e44ea74b002b83f9b3bee14d861a4c9eeecc89f65408c1b701000000"
-               "d9e1825fa638e1af284a024b7f9e85ff00e050a2000000276e08cb887464b93400c3127c750fabdd"
-               "69121aec129cdc690d58fbcc01000000d0d44ff1e51c35157666c05348e6f50700a8e89800000012"
-               "b900b2061d0c334b009f2dd1cdf64b0f9a60e0e289f08db3fde6b0250100000039dd8f88152a5845"
-               "4d9ca9d20f45dfa702e78604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c"
-               "210aeb09010000007000b96d06992b6a58acd3995b9663d20248f333ef467092818aa77d6732b678"
-               "00844ef5a943825fcd743f59bd14c89b955e1a13010000007acbce3e3bcdf3824f1b134847ff26ba"
-               "009a774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000"
-               "5e0dfe491d1ba96742c7b5e02b2271220188b02a06d0dc5504b0595daf37deb499996bfb667f072d"
-               "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba80383f4c500000063"
-               "eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8ca0100000027335a25a364d101"
-               "5ffac03089f4553902b01784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507"
-               "f121014a01000000efc67bce716c856e3973dc42a1003be94f89d8ee0000009b5d5bbe6c10085f3d"
-               "6176f78a19bb8df1804c122fce5078c156e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807"
-               "cbad7645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000"
-               "da40d88d40a6d75bc404156225b7eedefc2b44574b15e2ae496ad01bf007eacb0a28aec868282510"
-               "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189018ee815000000a7"
-               "5c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a7a859db500000000362956cd46646a0e"
-               "222160e5f769bb290366ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d"
-               "8e47935e0000000034f0386a253c21d94064f6b021281e230094ae20000000d71fd050bf8d85055b"
-               "00e3756ccdb3455c60ca7b11c66af76e594f24a100000000e143fd52599364e13468f80fd514573f"
-               "b572671c0000006932d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c857ae81200000000"
-               "3e29535402e9b690c628d048eacce745ea213cb1000000b632ef3be6070dafa200187470e9da5570"
-               "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db4532545666937c22a3b000000dc"
-               "c405cbee5016c25200d8901d7a0165fe20744edb6ba04f14a4c73cf500000000a4bab14874afdf54"
-               "e6aae816430607ca0675e09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b"
-               "6e4c699300000000d9c1e67743efb54e54270e46042e911803894e38000000376feecb80ac245409"
-               "c0becc271d9c2f67179bff0644399ae7e3c9472e00000000c5cfd9f2343b21362c19a0921dce2f83"
-               "00defa45000000270b9977e166bee737fe73670c439a644c323b59b4cd20eb7dabea74f700000000"
-               "f6989d2d6a909e986ff7add5df2c93e05459507b0000000f466554d2ae4d52a8c67b2e48b47003c8"
-               "1785d3ffdbd9a617df6b3542000000004c5cf8107ba282f4f983821918f93e742d08f0550000006f"
-               "2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b5159747cf200000000ab2dadc5a39411fd"
-               "4ff1116d478987316a553fc2000000cfc6ebe434a7ae8ff040483e310819e3b10db116431ec6f769"
-               "438a72e1000000002495a609675344f7e2e3a5ebaec3c85f0a1742f70abe95c50345132a61eda239"
-               "d9d083c3bf085387046ef8a36f0e9e696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9"
-               "03dd01f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000"
-               "0d3c723b91adb0da7c4aa7e7eb5a15bc03015fb98b841fd84cc43c510385b9a4c2aac1d67a909b29"
-               "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a92409c0b7f0318a"
-               "575a4f8e061db3dd7fde25654a4059d565dbc8a91e3b4457b077ddad3108be69f9b97d05c917ad6b"
-               "10e693bb6e26f2ba90c8e909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38"
-               "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea01aafdc3a9fe1ec787bc45db7c52a52d"
-               "00bd39a44e8e8bc17c01ac63eca0c1cf5ff7f03a03000000c9a89192c1c8be55281a59d1fd338f35"
-               "0075f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000"
-               "24438387def0f4c6544e4b275d9b714600f810d2a9fec17647176b7c07d856e3b883efebc09dd9d6"
-               "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee018588ffa9fe6cae"
-               "426de59560fad65d67c624f285d7174177a47579dda0b6eaa9a84c820300000070b1646d8026e9f1"
-               "704f1b16286ba2da017ef082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82"
-               "fa40546c03000000df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea9fe3e7d75a2f42b50c6a363"
-               "40132378b95c59313bacba64dbe996206e6904f50200000047150b9b14010469823acb72bb89182f"
-               "00112196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000"
-               "e79c10acfce165e332a62384ec04e5ba009185ada9fe0070a36dd51323b2c54200154d12f86c260a"
-               "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98c0221c19ca9fe942f"
-               "460bcea75481f25e007d0de9a7afe283bd2f22ead05ff72006c83bc0020000004bdade862c224f6f"
-               "36506ebd455e679c00369bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f"
-               "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb120335256aa9fe6e5d58099ffc4a503a71"
-               "2350acbd48411f0dc15d2f0f49dad345d966279502000000e06302aba042aaa218dc091e9aa1477f"
-               "6fdc9830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000"
-               "98c39e7cc282208fefc57ff447036b9501adcb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13"
-               "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde5301b3ec71a9fe9f25"
-               "4ac95883195580410062ed564153e17478f8c3344d89c0bbfaa100fd01000000be184524a6bdc878"
-               "9cf851782d895bcc03a98489a9fe8c1287e6f7bb020ffdb00012098610e52bb2a16a4008aefd545b"
-               "0d80684e01000000ba8110fb9733cc24904f288262e6ea77032fa5f8a9feeefa701d120523bd98f2"
-               "00098b43cd68be6e3f81268193fd637e9037d7a701000000c47cf0f551e96770a754ac19ef820fe0"
-               "0031f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000"
-               "68cb3bc873b04d937a6ed8f7bc51e54066fed098a9fe048a92d3adc69a84eb47622400207799416a"
-               "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183600085d627a9feb1cb"
-               "e491cbbbf9443fd6007eb3c5bf64b671d6f18dbf463f9b83f512dc1c00000000fbab244735d67c61"
-               "283031667b2d74a102e0b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef"
-               "a9a89f8700000000fcdf6d9be94030b34774d1d7dddedd9802f0f627a9fe965a87041331b2834bcf"
-               "00b4e3ce848518c4e3f6cbf25e5e1b992231bb0200000000173c333cd03bc905b7b899afeb760e3f"
-               "024a2efca9fe96b89b1bc8f415bd4e77be46bae5a1b3cae76665a268abfe8a41a84e27c100000000"
-               "cb29efdf672d2fa57fc85ebbe276c5660364192da9fee7af5eb888e9eb37bb046686943b101e1f55"
-               "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82d03c74828a9fe1e37"
-               "1051852c972ea7954079884af257b044fd13a6826a4c619f3d136cac000000009402a4c216772167"
-               "3f2b02b3256ead1f03ea9bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c"),
-        [1] = ("54270e46020000006a894e387625da376feecb80ac245409c0becc271d9c2f67179bff0644399ae7"
-               "9c64ed0432d599eaa660ac824b7fae389861419c7a899f2d010000009bf5a5d06776e66a9d80ab13"
-               "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b"
-               "c4e1966800000000b3121cd5ef51e696c816290dbaee0e7726d082e1530ff5397c9125f59577d71c"
-               "4b258a005116d11354edff62ceaa458fc75a91c425a5927300000000c4458d70911714f1819aa46f"
-               "be143934c933ae6dec0fb124f264af67eed7c9a8c38b6b8ee2614344bea73223e59bf0193432e9fa"
-               "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44"
-               "64d210a256be75e0509c4477d19ac64b2e69220d12ea3b9501000000fb95e8332fdfff658483a2d0"
-               "39a7bf148ed3481e0bccc460e89f7abdb682380a62eae374835b4a49a2b980b6aba92da6409969aa"
-               "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359"
-               "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9bb0ec36f0000000064a2827b7cdd38d0314c178e"
-               "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13"
-               "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226"
-               "d324d9a086ed27184b443181a5edc511c1507a142fea9bc10300000062fb81e733cff620ca7feefe"
-               "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196"
-               "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911"
-               "4bdade862c224f6f36506ebd455e679cef369bb8d514573f03000000f6932f6932d1d5f5d0ce2cf6"
-               "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd"
-               "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d"
-               "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a41e0f515601000000f57609453df7803357ae7998"
-               "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7"
-               "ae8cb60b0300000038d856a40c67c3d4afa9c8649da90bd2fff2f256000000000000000000000000"
-               "00000001955e1a13d1111b067acbce3e3bcdf38200154d12010000009edfa7a74c1c83c18e47935e"
-               "8354846e34f0386a00000000000000000000000000000001ac26c7d41fd050bf8d85055bcfe3756c"
-               "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000"
-               "00000000020ffdb0e612098610e52bb2a16a40086f0e9e6903000000ec2e2924348352d715cf9d41"
-               "1ea012e5307294b600000000000000000000000000000000ccd2f50c30706cae3fdcc2f0ee3d5e26"
-               "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000"
-               "0000000000459582f4ef43c780908872746e39efaefd545b020000007ced4f8b362956cd46646a0e"
-               "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d"
-               "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000"
-               "0000000069d9942f460bcea75481f25e307d0de96e91b91501000000be5b534e0a6527f67485ab35"
-               "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b"
-               "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000"
-               "00000000b49185ad9b7d0070a36dd51323b2c542e5fe7d360100000066a3ae3939762df33a2d5506"
-               "0c78d551cbb110fd000000000000000000000000000000002c171ed15abbbe1cd911db7b56e8f3fe"
-               "9a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7246f13b2050424a2000000000000000000000000"
-               "00000000ffe9d6812231bb02f922259b173c333cbae87d60000000005d31e5b2de252167c1c91b3a"
-               "36ba0c700ee78477000000000000000000000000000000006ad0143a0554efb46b382ab0404cdf02"
-               "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000"
-               "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8"
-               "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec"
-               "7666c05303000000ffa8e89871fb9510b900b2061d0c334b819f2dd1000000000000000000000000"
-               "00000000095a3230fde69eec3af2e6d0bd68ab7210613fc90200000016a31dc2e46a234558817151"
-               "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2"
-               "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000"
-               "00000000b314f695bd82e9ea8891ed0a3d1b91cab56e03e0010000002f70249eefc67bce716c856e"
-               "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1"
-               "eecc89f601000000d635edea8ffe423d01883918039249f398f9b37e000000000000000000000000"
-               "000000001fb7c8307f06b4b29088f20d9ac676d5f90e54b501000000a779f37c30d2c5053c40ecae"
-               "210aeb0934cb2a2400000000000000000000000000000000df48f333ef467092818aa77d6732b678"
-               "bcd7be0700000000e45aaf61814f703b40125e6baf4648cbaaa37b86000000000000000000000000"
-               "000000005ddb05f2a84e27c18a06e2c9cb29efdf50da49bf00000000d94beb259f9f0251becc9879"
-               "07879cca68fec7bb000000000000000000000000000000009402a4c2167721673f2b02b3256ead1f"
-               "a349e1cc00000000b879a45176740744fcb6a035339d504c9726d80d000000000000000000000000"
-               "000000009518862bc9a89192c1c8be55281a59d1ebfdcec30000000067a982be8a934f852cc3d4d8"
-               "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a"
-               "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000"
-               "00000002e6fbf952902383028e3b47f2111d891d536c75bb01000000720da9e07ac998b5690807d5"
-               "2617369ee1af4ca500000000000000000000ffff47d7b351a36b178aabc78a4a0d80684ee5dbf45b"
-               "17a4763102000000f9119c40b468b66331bca67a034f43340d01683c00000000000000000000ffff"
-               "b24a5be9b10123e6e4f15ecd1dff045298cfee069c88b02a0300000004b0595daf37deb499996bfb"
-               "667f072dec1e5d9cdc8a11f4409bcfb3c167090e99d90a8543961b2ccd47724a3c460ba85183f4c5"
-               "a7afe28302000000d05ff720b16c73761a3fcb675219061ab4c5c79489b2cc6a883c146972decb8b"
-               "5adac8f5e6d66df46ea139107754dee62c36d2fcc7a4c65601000000cd625009a40aeb62a42b6a62"
-               "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb"
-               "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599"
-               "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b21cdb3455c00000000c66af76e80f062ea1a7e0b7b"
-               "e218d067530e1b0487b8c3b99f2b8a1a8982c42f53700a3437c5156e072b2f2fb337c9cfe07c34dd"
-               "c896c9a7000000000a5f6abd850b06e3d9662795ce2cc1cee06302aba042aaa218dc091e9aa1477f"
-               "6fdc9830d7fbc95829a8838314dff34d24c332214d4647f5000000000f88e3759a08e7a56663861e"
-               "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db"
-               "7625ca4a00000000e682f80f94315c45ef817264c89a736ed55ed637b077ddad3108be69f9b97d05"
-               "c917ad6b10e693bb6e26f2ba90c8e909e85e20e5b0916e5d030000004a503a712350acbd48411f0d"
-               "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8"
-               "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e"
-               "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c"
-               "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378"
-               "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620"
-               "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2"
-               "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034"
-               "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9"
-               "4d88189c471a1ff2f0ce3ff66e782110125ae2eddaae7d6300000000c0982b283aa9986700b2a2b3"
-               "ed257b8b0489f48f053ec8cac72105b327335a25a364d1015ffac03089f45539e1b0178462156cd6"
-               "6855676c00000000017c9148da5892bb4951c3a7ed55689d3391ce7d3fd48469845f0c233dbdd2a9"
-               "7835df1f1782dee88487fd0db5971b46b7a350f998c39e7c00000000efc57ff447036b9551adcb22"
-               "fd50793f797a3c7dadd1c86e759d0c90bc512e137dcef5e4a27985bd8d1e69c83dc21056b973972c"
-               "bc51e540030000006c3d048a92d3adc69a84eb47622400207799416afef0a086fbd7e2f7dea0077a"
-               "e9c0c0d9c386e9c6e6a2cbfa10ee58bdc75183600422ae3f03000000c43bd794c697895e5bfe47c6"
-               "f53a54e01b0c1d89fecd94d0e02d2ec587fc330003781b0f294a2b73c4421398f4de67e9cee64b38"
-               "69121aec010000000fcc00ac2daa755e5292cd32dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51"
-               "bbce426cfa4b861cc78592be7b14e7ba9c15acb836674cde0200000054cfe8f42bf0e9381ba2c439"
-               "6de60f032bc7f34dfe959871c0d4c0d4eb720c4ae3c9472e5f2da5d9c5cfd9f2343b21362c19a092"
-               "b2cd3dbd01000000e958e48d2ab8b0313e7f8933e315130fa9a84c82feb83f6e70b1646d8026e9f1"
-               "704f1b16286ba2dabc7ef0820c91ed33ef60a8b5bcfe97e1000000007ad742d3d7320a4f880cf47f"
-               "5dd0cf69cb22840ffeb3fe7749509cb6752b2cee30b7e7736a0afc9879ea40e69710fc9f6e8e99cd"
-               "1dce2f83020000003a3efc240b9977e166bee737fe73670c439a644c000000000000000000000000"
-               "000000015e0dfe491d1ba96742c7b5e02b227122cf844ef501000000cd743f59bd14c89b5cfd5ce6"
-               "e82e7854152f2b700000000000000000000000000000000127e19f254ac9588319558041fc62ed56"
-               "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000"
-               "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f"
-               "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e"
-               "0436242c03000000ee3fbc164632d4f28aa28c08f80dd50c6712dfb4000000000000000000000000"
-               "00000000078a806d329c9b008bbfc9723107f3f52af145480300000004265f6c72923e22594f3f79"
-               "e208ed2e2ebb07710000000000000000000000000000000039dd8f88152a58454d9ca9d20f45dfa7"
-               "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000"
-               "000000008ae21e371051852c972ea7954079884a9a1b163a030000000e2f4f911a0dd8c052ed6b13"
-               "e2815a1a37a52bdd00000000000000000000000000000000bd99fcf72909ac9e7a55299e9bb4fd53"
-               "9f3c2c8803000000f51f44e644d7cf1d06b2b115d882549e62c12fba000000000000000000000000"
-               "000000004fc812bd2f8a59d96d064126666befbbf257b044030000006a4c619f9037d7a754655354"
-               "c47cf0f551e967700000000000000000000000000000000050b8d10ab700cc3a7cf51be0403b654b"
-               "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000"
-               "00000000d538d34574c038404923e75d0e09e2fcfc1519de010000002545666937c22a3b6e9686dc"
-               "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e"
-               "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000"
-               "00000000b883efebc09dd9d61966b7ae7412041dd7ac5f9901000000822a272bec4501a1e27acfee"
-               "7a8588ffd5a06cae0000000000000000000000000000000077a47579dda0b6ead1e1b34901eaedd5"
-               "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000"
-               "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096"
-               "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f"
-               "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000"
-               "000000005b29a197b7b3cceaf5f1bb12c535256a74993ade03000000e62112898dab2dade2ab2fc9"
-               "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8"
-               "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000"
-               "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050"
-               "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f"
-               "bc74179403000000438a72e12ae0436a2495a609675344f7e2e3a5eb000000000000000000000000"
-               "0000000061eda239d9d083c3bf085387046ef8a34153e174020000004d89c0bb5408c1b7d17fb084"
-               "d9e1825fa638e1af000000000000000000000000000000006e08cb887464b9344ec3127c750fabdd"
-               "6c0fc09c02000000809829af4a9df58dbfef186d416f3a1ef170d10f000000000000000000000000"
-               "0000000087780281d47a32f2235376239daeaacba9a89f8701000000fcdf6d9be94030b34774d1d7"
-               "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767"
-               "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000"
-               "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc"
-               "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515"
-               "b7f0318a01000000061db3dd7fde25654a4059d565dbc8a91e3b4457000000000000000000000000"
-               "00000000c1b5aad487c192f08bd7a09bdd21444359747cf200000000ab2dadc5a39411fd4ff1116d"
-               "478987316a553fc2000000000000000000000000000000000819e3b10db116431ec6f7691539ce41"
-               "b95c593100000000dbe9962069e66142e22753344fda8a3e0b841cf7000000000000000000000000"
-               "000000008c54dda9ac3bb1b1d43e6505621b9a7f672d2fa501000000e276c5661a64192db44ce7af"
-               "5eb888e9eb37bb0400000000000000000000000000000002641e447514ca565fb9b68c08a5e4351e"
-               "9f3c39f201000000de745cb25851429b3bbfb50168dfd04edf6b3542000000000000000000000000"
-               "0000000218f93e742d08f0550b55726f2292362e70ccc56700000000a4c73cf5ffa4ffc8a4bab148"
-               "74afdf54e6aae8160000000000000000000000000000000268baf76ab08940f6fc3bbdc7f6090f75"
-               "4f1b134803000000449a774929e86716ec852d59f3d17232edd86ad6000000000000000000000000"
-               "000000027dba1ee7e143fd52599364e13468f80f40b26f6603000000badfad0fe8fa8f3c1aad2a82"
-               "530b7447d9c2f401000000000000000000000000000000028147507e1cd59ea1ae6da48b1eba6d16"
-               "dedea2030100000002a1f8e6f5657f3f9e3eb807cbad76451055edb8000000000000000000000000"
-               "00000002d9279fb2b8fcbac6abea74f7a6df7979f6989d2d000000006ff7add5df2c93e05459507b"
-               "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"),
-        [2] = ("4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44"
-               "64d210a256be75e0509c4477d19ac64b2e69220d54270e46020000006a894e387625da376feecb80"
-               "ac245409c0becc271d9c2f67179bff0644399ae79c64ed0432d599eaa660ac824b7fae389861419c"
-               "12ea3b9501000000fb95e8332fdfff658483a2d039a7bf148ed3481e0bccc460e89f7abdb682380a"
-               "62eae374835b4a49a2b980b6aba92da6409969aa7a899f2d010000009bf5a5d06776e66a9d80ab13"
-               "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b"
-               "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359"
-               "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9c4e1966800000000b3121cd5ef51e696c816290d"
-               "baee0e7726d082e1530ff5397c9125f59577d71c4b258a005116d11354edff62ceaa458fc75a91c4"
-               "25a5927300000000c4458d70911714f1819aa46fbe143934c933ae6dec0fb124f264af67eed7c9a8"
-               "c38b6b8ee2614344bea73223e59bf0193432e9fa2fea9bc10300000062fb81e733cff620ca7feefe"
-               "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196"
-               "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911"
-               "4bdade862c224f6f36506ebd455e679cef369bb8bb0ec36f0000000064a2827b7cdd38d0314c178e"
-               "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13"
-               "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226"
-               "d324d9a086ed27184b443181a5edc511c1507a14d514573f03000000f6932f6932d1d5f5d0ce2cf6"
-               "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd"
-               "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d"
-               "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a4ae8cb60b0300000038d856a40c67c3d4afa9c864"
-               "9da90bd2fff2f25600000000000000000000000000000001955e1a13d1111b067acbce3e3bcdf382"
-               "00154d12010000009edfa7a74c1c83c18e47935e8354846e34f0386a000000000000000000000000"
-               "00000001ac26c7d41fd050bf8d85055bcfe3756c1e0f515601000000f57609453df7803357ae7998"
-               "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7"
-               "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000"
-               "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8"
-               "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec"
-               "6f0e9e6903000000ec2e2924348352d715cf9d411ea012e5307294b6000000000000000000000000"
-               "00000000ccd2f50c30706cae3fdcc2f0ee3d5e267666c05303000000ffa8e89871fb9510b900b206"
-               "1d0c334b819f2dd100000000000000000000000000000000095a3230fde69eec3af2e6d0bd68ab72"
-               "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000"
-               "0000000000459582f4ef43c780908872746e39ef10613fc90200000016a31dc2e46a234558817151"
-               "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2"
-               "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000"
-               "00000000b314f695bd82e9ea8891ed0a3d1b91ca6e91b91501000000be5b534e0a6527f67485ab35"
-               "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b"
-               "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000"
-               "00000000b49185ad9b7d0070a36dd51323b2c542b56e03e0010000002f70249eefc67bce716c856e"
-               "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1"
-               "e5fe7d360100000066a3ae3939762df33a2d55060c78d551cbb110fd000000000000000000000000"
-               "000000002c171ed15abbbe1cd911db7b56e8f3feeecc89f601000000d635edea8ffe423d01883918"
-               "039249f398f9b37e000000000000000000000000000000001fb7c8307f06b4b29088f20d9ac676d5"
-               "f90e54b501000000a779f37c30d2c5053c40ecae210aeb0934cb2a24000000000000000000000000"
-               "00000000df48f333ef467092818aa77d6732b678bcd7be0700000000e45aaf61814f703b40125e6b"
-               "af4648cbaaa37b86000000000000000000000000000000005ddb05f2a84e27c18a06e2c9cb29efdf"
-               "50da49bf00000000d94beb259f9f0251becc987907879cca68fec7bb000000000000000000000000"
-               "000000009402a4c2167721673f2b02b3256ead1fa349e1cc00000000b879a45176740744fcb6a035"
-               "339d504c9726d80d000000000000000000000000000000009518862bc9a89192c1c8be55281a59d1"
-               "bae87d60000000005d31e5b2de252167c1c91b3a36ba0c700ee78477000000000000000000000000"
-               "000000006ad0143a0554efb46b382ab0404cdf02ebfdcec30000000067a982be8a934f852cc3d4d8"
-               "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a"
-               "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000"
-               "00000000020ffdb0e612098610e52bb2a16a4008aefd545b020000007ced4f8b362956cd46646a0e"
-               "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d"
-               "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000"
-               "0000000069d9942f460bcea75481f25e307d0de99a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7"
-               "246f13b2050424a200000000000000000000000000000000ffe9d6812231bb02f922259b173c333c"
-               "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000"
-               "00000002e6fbf952902383028e3b47f2111d891d17a4763102000000f9119c40b468b66331bca67a"
-               "034f43340d01683c00000000000000000000ffffb24a5be9b10123e6e4f15ecd1dff045298cfee06"
-               "536c75bb01000000720da9e07ac998b5690807d52617369ee1af4ca500000000000000000000ffff"
-               "47d7b351a36b178aabc78a4a0d80684ee5dbf45bb0916e5d030000004a503a712350acbd48411f0d"
-               "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8"
-               "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e"
-               "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c"
-               "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378"
-               "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620"
-               "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2"
-               "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034"
-               "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9"
-               "4d88189c471a1ff2f0ce3ff66e782110125ae2edc7a4c65601000000cd625009a40aeb62a42b6a62"
-               "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb"
-               "daae7d6300000000c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8cac72105b327335a25"
-               "a364d1015ffac03089f45539e1b0178462156cd66855676c00000000017c9148da5892bb4951c3a7"
-               "ed55689d3391ce7d3fd48469845f0c233dbdd2a97835df1f1782dee88487fd0db5971b46b7a350f9"
-               "cdb3455c00000000c66af76e80f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a8982c42f"
-               "53700a3437c5156e072b2f2fb337c9cfe07c34ddc896c9a7000000000a5f6abd850b06e3d9662795"
-               "ce2cc1cee06302aba042aaa218dc091e9aa1477f6fdc9830d7fbc95829a8838314dff34d24c33221"
-               "98c39e7c00000000efc57ff447036b9551adcb22fd50793f797a3c7dadd1c86e759d0c90bc512e13"
-               "7dcef5e4a27985bd8d1e69c83dc21056b973972c7625ca4a00000000e682f80f94315c45ef817264"
-               "c89a736ed55ed637b077ddad3108be69f9b97d05c917ad6b10e693bb6e26f2ba90c8e909e85e20e5"
-               "9c88b02a0300000004b0595daf37deb499996bfb667f072dec1e5d9cdc8a11f4409bcfb3c167090e"
-               "99d90a8543961b2ccd47724a3c460ba85183f4c5a7afe28302000000d05ff720b16c73761a3fcb67"
-               "5219061ab4c5c79489b2cc6a883c146972decb8b5adac8f5e6d66df46ea139107754dee62c36d2fc"
-               "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599"
-               "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b214d4647f5000000000f88e3759a08e7a56663861e"
-               "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db"
-               "0422ae3f03000000c43bd794c697895e5bfe47c6f53a54e01b0c1d89fecd94d0e02d2ec587fc3300"
-               "03781b0f294a2b73c4421398f4de67e9cee64b38bc51e540030000006c3d048a92d3adc69a84eb47"
-               "622400207799416afef0a086fbd7e2f7dea0077ae9c0c0d9c386e9c6e6a2cbfa10ee58bdc7518360"
-               "36674cde0200000054cfe8f42bf0e9381ba2c4396de60f032bc7f34dfe959871c0d4c0d4eb720c4a"
-               "e3c9472e5f2da5d9c5cfd9f2343b21362c19a092b2cd3dbd01000000e958e48d2ab8b0313e7f8933"
-               "e315130fa9a84c82feb83f6e70b1646d8026e9f1704f1b16286ba2dabc7ef0820c91ed33ef60a8b5"
-               "bcfe97e1000000007ad742d3d7320a4f880cf47f5dd0cf69cb22840ffeb3fe7749509cb6752b2cee"
-               "30b7e7736a0afc9879ea40e69710fc9f6e8e99cd69121aec010000000fcc00ac2daa755e5292cd32"
-               "dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51bbce426cfa4b861cc78592be7b14e7ba9c15acb8"
-               "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000"
-               "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f"
-               "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e"
-               "cf844ef501000000cd743f59bd14c89b5cfd5ce6e82e7854152f2b70000000000000000000000000"
-               "0000000127e19f254ac9588319558041fc62ed561dce2f83020000003a3efc240b9977e166bee737"
-               "fe73670c439a644c000000000000000000000000000000015e0dfe491d1ba96742c7b5e02b227122"
-               "2af145480300000004265f6c72923e22594f3f79e208ed2e2ebb0771000000000000000000000000"
-               "0000000039dd8f88152a58454d9ca9d20f45dfa774993ade03000000e62112898dab2dade2ab2fc9"
-               "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8"
-               "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000"
-               "000000008ae21e371051852c972ea7954079884a9f3c2c8803000000f51f44e644d7cf1d06b2b115"
-               "d882549e62c12fba000000000000000000000000000000004fc812bd2f8a59d96d064126666befbb"
-               "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000"
-               "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050"
-               "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f"
-               "f257b044030000006a4c619f9037d7a754655354c47cf0f551e96770000000000000000000000000"
-               "0000000050b8d10ab700cc3a7cf51be0403b654bbc74179403000000438a72e12ae0436a2495a609"
-               "675344f7e2e3a5eb0000000000000000000000000000000061eda239d9d083c3bf085387046ef8a3"
-               "4153e174020000004d89c0bb5408c1b7d17fb084d9e1825fa638e1af000000000000000000000000"
-               "000000006e08cb887464b9344ec3127c750fabdd6c0fc09c02000000809829af4a9df58dbfef186d"
-               "416f3a1ef170d10f0000000000000000000000000000000087780281d47a32f2235376239daeaacb"
-               "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000"
-               "00000000d538d34574c038404923e75d0e09e2fca9a89f8701000000fcdf6d9be94030b34774d1d7"
-               "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767"
-               "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000"
-               "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc"
-               "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515"
-               "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000"
-               "00000000b883efebc09dd9d61966b7ae7412041db7f0318a01000000061db3dd7fde25654a4059d5"
-               "65dbc8a91e3b445700000000000000000000000000000000c1b5aad487c192f08bd7a09bdd214443"
-               "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000"
-               "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096"
-               "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f"
-               "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a553fc2000000000000000000000000"
-               "000000000819e3b10db116431ec6f7691539ce41b95c593100000000dbe9962069e66142e2275334"
-               "4fda8a3e0b841cf7000000000000000000000000000000008c54dda9ac3bb1b1d43e6505621b9a7f"
-               "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000"
-               "000000005b29a197b7b3cceaf5f1bb12c535256a0436242c03000000ee3fbc164632d4f28aa28c08"
-               "f80dd50c6712dfb400000000000000000000000000000000078a806d329c9b008bbfc9723107f3f5"
-               "9a1b163a030000000e2f4f911a0dd8c052ed6b13e2815a1a37a52bdd000000000000000000000000"
-               "00000000bd99fcf72909ac9e7a55299e9bb4fd53fc1519de010000002545666937c22a3b6e9686dc"
-               "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e"
-               "d7ac5f9901000000822a272bec4501a1e27acfee7a8588ffd5a06cae000000000000000000000000"
-               "0000000077a47579dda0b6ead1e1b34901eaedd54f1b134803000000449a774929e86716ec852d59"
-               "f3d17232edd86ad6000000000000000000000000000000027dba1ee7e143fd52599364e13468f80f"
-               "40b26f6603000000badfad0fe8fa8f3c1aad2a82530b7447d9c2f401000000000000000000000000"
-               "000000028147507e1cd59ea1ae6da48b1eba6d16dedea2030100000002a1f8e6f5657f3f9e3eb807"
-               "cbad76451055edb800000000000000000000000000000002d9279fb2b8fcbac6abea74f7a6df7979"
-               "672d2fa501000000e276c5661a64192db44ce7af5eb888e9eb37bb04000000000000000000000000"
-               "00000002641e447514ca565fb9b68c08a5e4351e9f3c39f201000000de745cb25851429b3bbfb501"
-               "68dfd04edf6b35420000000000000000000000000000000218f93e742d08f0550b55726f2292362e"
-               "70ccc56700000000a4c73cf5ffa4ffc8a4bab14874afdf54e6aae816000000000000000000000000"
-               "0000000268baf76ab08940f6fc3bbdc7f6090f75f6989d2d000000006ff7add5df2c93e05459507b"
-               "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"),
-    };
-    const int   TEST_DATA_I      = GPOINTER_TO_INT(test_data);
-    const int   addr_family      = (TEST_DATA_I == 0 ? AF_INET : AF_INET6);
-    const int   IPV6_PREFER_TEMP = (TEST_DATA_I == 2);
-    const guint N_ADDRESSES      = 100;
-    const gsize ELM_SIZE =
-        addr_family == AF_INET ? sizeof(NMPlatformIP4Address) : sizeof(NMPlatformIP6Address);
-    const gboolean DO_REGENERATE = FALSE;
-    const gboolean PRINT_RESULT  = DO_REGENERATE;
-    const gboolean CHECK_RESULT  = !DO_REGENERATE;
-    gs_free guint8 *addresses    = NULL;
-    gs_free guint64 *rand_map    = NULL;
-    gsize            i, j;
-
-#if !defined(__amd64__)
-    /* The test generates a random array of NMPlatformIPXAddress (by crudely randomizing the memory,
-     * not the structures themself) and then compares the sorted result with the expected output.
-     * The sole purpose is to ensure that the sorting order stays stable.
-     *
-     * This only works on an architecture for which the test was made, otherwise
-     * the expected data does not match (due to different layout of the structures
-     * in memory).
-     *
-     * That's fine. Skip the test. */
-    g_test_skip("skip test on non-amd64 architecture");
-    return;
-#endif
-
-    /*
-     * First we create a list of addresses filled with (stable) random bytes.
-     * We tweak some fields explicitly (stable randomly), so that we cover all
-     * relevant cases.
-     *
-     * Then we sort the list of addresses, and compare that the result is
-     * as our EXPECTED_BUFFER.
-     */
-
-    addresses = g_malloc(ELM_SIZE * N_ADDRESSES);
-    rand_map  = g_malloc(sizeof(rand_map[0]) * N_ADDRESSES);
-    nmtst_stable_rand(258829693, addresses, ELM_SIZE * N_ADDRESSES);
-    nmtst_stable_rand(710086081, rand_map, sizeof(rand_map[0]) * N_ADDRESSES);
-
-    for (i = 0; i < N_ADDRESSES; i++) {
-        NMPlatformIPXAddress *a = (gpointer)(&addresses[i * ELM_SIZE]);
-        guint64               r = rand_map[i];
-        struct in6_addr *     a6;
-
-#define CONSUME_BITS(r, nbits)                        \
-    ({                                                \
-        guint64   _r     = (r);                       \
-        const int _nbits = (nbits);                   \
-                                                      \
-        r >>= (_nbits);                               \
-        (_r & (((((guint64) 1u) << (_nbits)) - 1u))); \
-    })
-
-        if (addr_family == AF_INET) {
-            if (CONSUME_BITS(r, 1)) {
-                /* randomly create a link-local address or not. */
-                g_assert((NM_IPV4LL_NETWORK & ~NM_IPV4LL_NETMASK) == 0);
-                a->a4.address = (a->a4.address & ~NM_IPV4LL_NETMASK) | NM_IPV4LL_NETWORK;
-            }
-        } else {
-            a6 = &a->a6.address;
-            switch (CONSUME_BITS(r, 4)) {
-            case 0:
-                a6->s6_addr32[0] = 0;
-                a6->s6_addr32[1] = 0;
-                a6->s6_addr32[2] = htonl(0xffff);
-                g_assert(IN6_IS_ADDR_V4MAPPED(a6));
-                break;
-            case 1:
-                a6->s6_addr32[0] = 0;
-                a6->s6_addr32[1] = 0;
-                a6->s6_addr32[2] = 0;
-                a6->s6_addr32[3] = htonl(2);
-                g_assert(IN6_IS_ADDR_V4COMPAT(a6));
-                break;
-            case 2:
-                a6->s6_addr32[0] = 0;
-                a6->s6_addr32[1] = 0;
-                a6->s6_addr32[2] = 0;
-                a6->s6_addr32[3] = 0;
-                g_assert(IN6_IS_ADDR_UNSPECIFIED(a6));
-                break;
-            case 3:
-                a6->s6_addr32[0] = 0;
-                a6->s6_addr32[1] = 0;
-                a6->s6_addr32[2] = 0;
-                a6->s6_addr32[3] = htonl(1);
-                g_assert(IN6_IS_ADDR_LOOPBACK(a6));
-                break;
-            case 4:
-                a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl(0xffc00000)) | htonl(0xfe800000);
-                g_assert(IN6_IS_ADDR_LINKLOCAL(a6));
-                break;
-            case 6:
-                a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl(0xffc00000)) | htonl(0xfec00000);
-                g_assert(IN6_IS_ADDR_SITELOCAL(a6));
-                break;
-            case 7:
-            case 8:
-            case 9:
-            case 10:
-                break;
-            default:
-                memset(a6, 0, sizeof(*a6));
-                break;
-            }
-        }
-
-        if (CONSUME_BITS(r, 5) != 0) {
-            /* randomly make addr-source the same (so that several addresses compare
-             * equal). */
-            a->a4.addr_source = CONSUME_BITS(r, 2);
-        }
-
-        if (addr_family == AF_INET) {
-            if (CONSUME_BITS(r, 1)) {
-                /* randomly make the label empty or not. */
-                a->a4.label[0] = '\0';
-            }
-        }
-        if (addr_family == AF_INET) {
-            if (CONSUME_BITS(r, 2) != 0) {
-                /* randomly make the label empty or not. */
-                a->a4.plen = CONSUME_BITS(r, 2);
-            }
-        }
-        if (addr_family == AF_INET) {
-            if (CONSUME_BITS(r, 1)) {
-                a->a4.address = (a->a4.address & ~0xFFFFFFu) | (CONSUME_BITS(r, 2) << 24);
-            }
-        }
-    }
-
-    g_qsort_with_data(addresses,
-                      N_ADDRESSES,
-                      ELM_SIZE,
-                      _address_pretty_sort_cmp,
-                      (gpointer) test_data);
-
-    for (i = 0; i < N_ADDRESSES; i++) {
-        const NMPlatformIPXAddress *a = (gconstpointer)(&addresses[i * ELM_SIZE]);
-
-        for (j = i + 1; j < N_ADDRESSES; j++) {
-            const NMPlatformIPXAddress *b = (gconstpointer)(&addresses[j * ELM_SIZE]);
-            int                         c1;
-            int                         c2;
-
-            if (addr_family == AF_INET) {
-                c1 = nm_platform_ip4_address_pretty_sort_cmp(&a->a4, &b->a4);
-                c2 = nm_platform_ip4_address_pretty_sort_cmp(&b->a4, &a->a4);
-            } else {
-                c1 = nm_platform_ip6_address_pretty_sort_cmp(&a->a6, &b->a6, IPV6_PREFER_TEMP);
-                c2 = nm_platform_ip6_address_pretty_sort_cmp(&b->a6, &a->a6, IPV6_PREFER_TEMP);
-            }
-
-            g_assert_cmpint(c1, >=, -1);
-            g_assert_cmpint(c1, <=, 1);
-            g_assert_cmpint(c1, ==, -c2);
-        }
-    }
-
-    if (PRINT_RESULT) {
-        g_print("\n        [%d] = (", TEST_DATA_I);
-        for (i = 0; i < ELM_SIZE * N_ADDRESSES;) {
-            if (i > 0)
-                g_print("\n               ");
-            g_print("\"");
-            for (j = 0; j < 40 && i < ELM_SIZE * N_ADDRESSES; j++, i++)
-                g_print("%02x", addresses[i]);
-            g_print("\"");
-        }
-        g_print("),\n");
-        return;
-    }
-
-    if (CHECK_RESULT) {
-        gs_free guint8 *bin_arr = NULL;
-        gsize           bin_len;
-
-        bin_arr = nm_utils_hexstr2bin_alloc(EXPECTED_BUFFER[TEST_DATA_I],
-                                            FALSE,
-                                            FALSE,
-                                            NULL,
-                                            0,
-                                            &bin_len);
-
-        if (bin_len != ELM_SIZE * N_ADDRESSES || memcmp(addresses, bin_arr, bin_len) != 0) {
-            char *addresses_str = nm_utils_bin2hexstr(addresses, ELM_SIZE * N_ADDRESSES, -1);
-
-            g_error(">>> test_platform_ip_address_pretty_sort_cmp() will fail:\n"
-                    ">>> addresses[%zu]: %s\n"
-                    ">>> expected [%zu]: %s\n",
-                    ELM_SIZE * N_ADDRESSES,
-                    addresses_str,
-                    bin_len,
-                    EXPECTED_BUFFER[TEST_DATA_I]);
-        }
-
-        g_assert_cmpmem(addresses, ELM_SIZE * N_ADDRESSES, bin_arr, bin_len);
-    }
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-int
-main(int argc, char **argv)
-{
-    nmtst_init_assert_logging(&argc, &argv, "WARN", "DEFAULT");
-
-    g_test_add_func("/general/init_linux_platform", test_init_linux_platform);
-    g_test_add_func("/general/link_get_all", test_link_get_all);
-    g_test_add_func("/general/nm_platform_link_flags2str", test_nm_platform_link_flags2str);
-    g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/4",
-                         GINT_TO_POINTER(0),
-                         test_platform_ip_address_pretty_sort_cmp);
-    g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/6/1",
-                         GINT_TO_POINTER(1),
-                         test_platform_ip_address_pretty_sort_cmp);
-    g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/6/2",
-                         GINT_TO_POINTER(2),
-                         test_platform_ip_address_pretty_sort_cmp);
-
-    return g_test_run();
-}
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
deleted file mode 100644
index 1305e586..00000000
--- a/src/platform/tests/test-route.c
+++ /dev/null
@@ -1,1926 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2016 - 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include <linux/rtnetlink.h>
-#include <linux/fib_rules.h>
-
-#include "nm-core-utils.h"
-#include "platform/nm-platform-utils.h"
-#include "platform/nmp-rules-manager.h"
-
-#include "test-common.h"
-
-#define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX
-#define EX             NMTSTP_ENV1_EX
-
-static void
-_wait_for_ipv4_addr_device_route(NMPlatform *platform,
-                                 gint64      timeout_msec,
-                                 int         ifindex,
-                                 in_addr_t   addr,
-                                 guint8      plen)
-{
-    /* Wait that the addresses gets a device-route. After adding a address,
-     * the device route is not added immediately. It takes a moment... */
-
-    addr = nm_utils_ip4_address_clear_host_address(addr, plen);
-    NMTST_WAIT_ASSERT(400, {
-        NMDedupMultiIter iter;
-        NMPLookup        lookup;
-        const NMPObject *o;
-
-        nmp_cache_iter_for_each (
-            &iter,
-            nm_platform_lookup(platform,
-                               nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex)),
-            &o) {
-            const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE(o);
-
-            if (r->plen == plen && addr == nm_utils_ip4_address_clear_host_address(r->network, plen)
-                && r->metric == 0 && r->scope_inv == nm_platform_route_scope_inv(RT_SCOPE_LINK)
-                && r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
-                return;
-        }
-        nmtstp_assert_wait_for_signal(platform,
-                                      (nmtst_wait_end_us - g_get_monotonic_time()) / 1000);
-    });
-}
-
-static void
-_wait_for_ipv6_addr_non_tentative(NMPlatform *           platform,
-                                  gint64                 timeout_msec,
-                                  int                    ifindex,
-                                  guint                  addr_n,
-                                  const struct in6_addr *addrs)
-{
-    guint i;
-
-    /* Wait that the addresses become non-tentative.  Dummy interfaces are NOARP
-     * and thus don't do DAD, but the kernel sets the address as tentative for a
-     * small amount of time, which prevents the immediate addition of the route
-     * with RTA_PREFSRC */
-
-    NMTST_WAIT_ASSERT(timeout_msec, {
-        gboolean                    should_wait = FALSE;
-        const NMPlatformIP6Address *plt_addr;
-
-        for (i = 0; i < addr_n; i++) {
-            plt_addr = nm_platform_ip6_address_get(platform, ifindex, &addrs[i]);
-            if (!plt_addr || NM_FLAGS_HAS(plt_addr->n_ifa_flags, IFA_F_TENTATIVE)) {
-                should_wait = TRUE;
-                break;
-            }
-        }
-        if (!should_wait)
-            return;
-        nmtstp_assert_wait_for_signal(platform,
-                                      (nmtst_wait_end_us - g_get_monotonic_time()) / 1000);
-    });
-}
-
-static void
-ip4_route_callback(NMPlatform *              platform,
-                   int                       obj_type_i,
-                   int                       ifindex,
-                   const NMPlatformIP4Route *received,
-                   int                       change_type_i,
-                   SignalData *              data)
-{
-    const NMPObjectType              obj_type    = obj_type_i;
-    const NMPlatformSignalChangeType change_type = change_type_i;
-    NMPObject                        o_id;
-    nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
-
-    g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_IP4_ROUTE);
-    g_assert(received);
-    g_assert_cmpint(received->ifindex, ==, ifindex);
-    g_assert(data && data->name);
-    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED);
-
-    /* run code for initializing the ID only */
-    nmp_object_stackinit_id(&o_id, NMP_OBJECT_UP_CAST(received));
-    nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), TRUE);
-    nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), FALSE);
-
-    if (data->ifindex && data->ifindex != received->ifindex)
-        return;
-    if (data->change_type != change_type)
-        return;
-
-    if (data->loop)
-        g_main_loop_quit(data->loop);
-
-    data->received_count++;
-    _LOGD("Received signal '%s' %dth time.", data->name, data->received_count);
-}
-
-static void
-ip6_route_callback(NMPlatform *              platform,
-                   int                       obj_type_i,
-                   int                       ifindex,
-                   const NMPlatformIP6Route *received,
-                   int                       change_type_i,
-                   SignalData *              data)
-{
-    const NMPObjectType              obj_type    = obj_type_i;
-    const NMPlatformSignalChangeType change_type = change_type_i;
-    NMPObject                        o_id;
-    nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
-
-    g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_IP6_ROUTE);
-    g_assert(received);
-    g_assert_cmpint(received->ifindex, ==, ifindex);
-    g_assert(data && data->name);
-    g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED);
-
-    /* run code for initializing the ID only */
-    nmp_object_stackinit_id(&o_id, NMP_OBJECT_UP_CAST(received));
-    nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), TRUE);
-    nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), FALSE);
-
-    if (data->ifindex && data->ifindex != received->ifindex)
-        return;
-    if (data->change_type != change_type)
-        return;
-
-    if (data->loop)
-        g_main_loop_quit(data->loop);
-
-    data->received_count++;
-    _LOGD("Received signal '%s' %dth time.", data->name, data->received_count);
-}
-
-static void
-test_ip4_route_metric0(void)
-{
-    int         ifindex       = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    SignalData *route_added   = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                         NM_PLATFORM_SIGNAL_ADDED,
-                                         ip4_route_callback);
-    SignalData *route_changed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                           NM_PLATFORM_SIGNAL_CHANGED,
-                                           ip4_route_callback);
-    SignalData *route_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                           NM_PLATFORM_SIGNAL_REMOVED,
-                                           ip4_route_callback);
-    in_addr_t   network =
-        nmtst_inet4_from_string("192.0.2.5"); /* from 192.0.2.0/24 (TEST-NET-1) (rfc5737) */
-    int plen   = 32;
-    int metric = 22987;
-    int mss    = 1000;
-
-    /* No routes initially */
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0);
-
-    /* add the first route */
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network,
-                         plen,
-                         INADDR_ANY,
-                         0,
-                         metric,
-                         mss);
-    accept_signal(route_added);
-
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0);
-
-    /* Deleting route with metric 0 does nothing */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, 0));
-    ensure_no_signal(route_removed);
-
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0);
-
-    /* add the second route */
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network,
-                         plen,
-                         INADDR_ANY,
-                         0,
-                         0,
-                         mss);
-    accept_signal(route_added);
-
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0);
-
-    /* Delete route with metric 0 */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, 0));
-    accept_signal(route_removed);
-
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0);
-
-    /* Delete route with metric 0 again (we expect nothing to happen) */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, 0));
-    ensure_no_signal(route_removed);
-
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0);
-
-    /* Delete the other route */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric));
-    accept_signal(route_removed);
-
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0);
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0);
-
-    free_signal(route_added);
-    free_signal(route_changed);
-    free_signal(route_removed);
-}
-
-static void
-test_ip4_route(void)
-{
-    int                ifindex       = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    SignalData *       route_added   = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                         NM_PLATFORM_SIGNAL_ADDED,
-                                         ip4_route_callback);
-    SignalData *       route_changed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                           NM_PLATFORM_SIGNAL_CHANGED,
-                                           ip4_route_callback);
-    SignalData *       route_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
-                                           NM_PLATFORM_SIGNAL_REMOVED,
-                                           ip4_route_callback);
-    GPtrArray *        routes;
-    NMPlatformIP4Route rts[3];
-    in_addr_t          network;
-    guint8             plen = 24;
-    in_addr_t          gateway;
-    /* Choose a high metric so that we hopefully don't conflict. */
-    int metric = 22986;
-    int mss    = 1000;
-
-    inet_pton(AF_INET, "192.0.3.0", &network);
-    inet_pton(AF_INET, "198.51.100.1", &gateway);
-
-    /* Add route to gateway */
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         gateway,
-                         32,
-                         INADDR_ANY,
-                         0,
-                         metric,
-                         mss);
-    accept_signal(route_added);
-
-    /* Add route */
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0);
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network,
-                         plen,
-                         gateway,
-                         0,
-                         metric,
-                         mss);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0);
-    accept_signal(route_added);
-
-    /* Add route again */
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network,
-                         plen,
-                         gateway,
-                         0,
-                         metric,
-                         mss);
-    accept_signals(route_changed, 0, 1);
-
-    /* Add default route */
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, 0, 0, metric, 0);
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         0,
-                         0,
-                         gateway,
-                         0,
-                         metric,
-                         mss);
-    nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, 0, 0, metric, 0);
-    accept_signal(route_added);
-
-    /* Add default route again */
-    nmtstp_ip4_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         0,
-                         0,
-                         gateway,
-                         0,
-                         metric,
-                         mss);
-    accept_signals(route_changed, 0, 1);
-
-    /* Test route listing */
-    routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex);
-    memset(rts, 0, sizeof(rts));
-    rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
-    rts[0].network   = gateway;
-    rts[0].plen      = 32;
-    rts[0].ifindex   = ifindex;
-    rts[0].gateway   = INADDR_ANY;
-    rts[0].metric    = metric;
-    rts[0].mss       = mss;
-    rts[0].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_LINK);
-    rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
-    rts[1].network   = network;
-    rts[1].plen      = plen;
-    rts[1].ifindex   = ifindex;
-    rts[1].gateway   = gateway;
-    rts[1].metric    = metric;
-    rts[1].mss       = mss;
-    rts[1].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
-    rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
-    rts[2].network   = 0;
-    rts[2].plen      = 0;
-    rts[2].ifindex   = ifindex;
-    rts[2].gateway   = gateway;
-    rts[2].metric    = metric;
-    rts[2].mss       = mss;
-    rts[2].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
-    g_assert_cmpint(routes->len, ==, 3);
-    nmtst_platform_ip4_routes_equal_aptr((const NMPObject *const *) routes->pdata,
-                                         rts,
-                                         routes->len,
-                                         TRUE);
-    g_ptr_array_unref(routes);
-
-    /* Remove route */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric));
-    nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0);
-    accept_signal(route_removed);
-
-    /* Remove route again */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric));
-
-    /* Remove default route */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, 0, 0, metric));
-    accept_signal(route_removed);
-
-    /* Remove route to gateway */
-    g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, gateway, 32, metric));
-    accept_signal(route_removed);
-
-    free_signal(route_added);
-    free_signal(route_changed);
-    free_signal(route_removed);
-}
-
-static void
-test_ip6_route(void)
-{
-    int                ifindex       = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    SignalData *       route_added   = add_signal(NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
-                                         NM_PLATFORM_SIGNAL_ADDED,
-                                         ip6_route_callback);
-    SignalData *       route_changed = add_signal(NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
-                                           NM_PLATFORM_SIGNAL_CHANGED,
-                                           ip6_route_callback);
-    SignalData *       route_removed = add_signal(NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
-                                           NM_PLATFORM_SIGNAL_REMOVED,
-                                           ip6_route_callback);
-    GPtrArray *        routes;
-    NMPlatformIP6Route rts[3];
-    struct in6_addr    network;
-    guint8             plen = 64;
-    struct in6_addr    gateway, pref_src;
-    /* Choose a high metric so that we hopefully don't conflict. */
-    const int metric = 22987;
-    int       mss    = 1000;
-
-    inet_pton(AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
-    inet_pton(AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway);
-    inet_pton(AF_INET6, "::42", &pref_src);
-
-    g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET,
-                                         ifindex,
-                                         pref_src,
-                                         128,
-                                         in6addr_any,
-                                         NM_PLATFORM_LIFETIME_PERMANENT,
-                                         NM_PLATFORM_LIFETIME_PERMANENT,
-                                         0));
-    accept_signals(route_added, 0, 3);
-
-    _wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 200, ifindex, 1, &pref_src);
-
-    /* Add route to gateway */
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         gateway,
-                         128,
-                         in6addr_any,
-                         in6addr_any,
-                         metric,
-                         mss);
-    accept_signals(route_added, 0, 3);
-
-    /* Add route */
-    g_assert(!nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0));
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network,
-                         plen,
-                         gateway,
-                         pref_src,
-                         metric,
-                         mss);
-    g_assert(nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0));
-    accept_signal(route_added);
-
-    /* Add route again */
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         network,
-                         plen,
-                         gateway,
-                         pref_src,
-                         metric,
-                         mss);
-    accept_signals(route_changed, 0, 1);
-
-    /* Add default route */
-    g_assert(!nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0));
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         in6addr_any,
-                         0,
-                         gateway,
-                         in6addr_any,
-                         metric,
-                         mss);
-    g_assert(nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0));
-    accept_signal(route_added);
-
-    /* Add default route again */
-    nmtstp_ip6_route_add(NM_PLATFORM_GET,
-                         ifindex,
-                         NM_IP_CONFIG_SOURCE_USER,
-                         in6addr_any,
-                         0,
-                         gateway,
-                         in6addr_any,
-                         metric,
-                         mss);
-    accept_signals(route_changed, 0, 1);
-
-    /* Test route listing */
-    routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex);
-    memset(rts, 0, sizeof(rts));
-    rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
-    rts[0].network   = gateway;
-    rts[0].plen      = 128;
-    rts[0].ifindex   = ifindex;
-    rts[0].gateway   = in6addr_any;
-    rts[0].pref_src  = in6addr_any;
-    rts[0].metric    = metric;
-    rts[0].mss       = mss;
-    rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
-    rts[1].network   = network;
-    rts[1].plen      = plen;
-    rts[1].ifindex   = ifindex;
-    rts[1].gateway   = gateway;
-    rts[1].pref_src  = pref_src;
-    rts[1].metric    = metric;
-    rts[1].mss       = mss;
-    rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
-    rts[2].network   = in6addr_any;
-    rts[2].plen      = 0;
-    rts[2].ifindex   = ifindex;
-    rts[2].gateway   = gateway;
-    rts[2].pref_src  = in6addr_any;
-    rts[2].metric    = metric;
-    rts[2].mss       = mss;
-    g_assert_cmpint(routes->len, ==, 3);
-    nmtst_platform_ip6_routes_equal_aptr((const NMPObject *const *) routes->pdata,
-                                         rts,
-                                         routes->len,
-                                         TRUE);
-    g_ptr_array_unref(routes);
-
-    /* Remove route */
-    g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric));
-    g_assert(!nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0));
-    accept_signal(route_removed);
-
-    /* Remove route again */
-    g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric));
-
-    /* Remove default route */
-    g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
-    accept_signal(route_removed);
-
-    /* Remove route to gateway */
-    g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, gateway, 128, metric));
-    accept_signal(route_removed);
-
-    free_signal(route_added);
-    free_signal(route_changed);
-    free_signal(route_removed);
-}
-
-/*****************************************************************************/
-
-static void
-test_ip4_route_get(void)
-{
-    int            ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    in_addr_t      a;
-    int            result;
-    nm_auto_nmpobj NMPObject *route = NULL;
-    const NMPlatformIP4Route *r;
-
-    nmtstp_run_command_check("ip route add 1.2.3.0/24 dev %s", DEVICE_NAME);
-
-    NMTST_WAIT_ASSERT(100, {
-        nmtstp_wait_for_signal(NM_PLATFORM_GET, 10);
-        if (nmtstp_ip4_route_get(NM_PLATFORM_GET,
-                                 ifindex,
-                                 nmtst_inet4_from_string("1.2.3.0"),
-                                 24,
-                                 0,
-                                 0))
-            break;
-    });
-
-    a      = nmtst_inet4_from_string("1.2.3.1");
-    result = nm_platform_ip_route_get(NM_PLATFORM_GET,
-                                      AF_INET,
-                                      &a,
-                                      nmtst_get_rand_uint32() % 2 ? 0 : ifindex,
-                                      &route);
-
-    g_assert(NMTST_NM_ERR_SUCCESS(result));
-    g_assert(NMP_OBJECT_GET_TYPE(route) == NMP_OBJECT_TYPE_IP4_ROUTE);
-    g_assert(!NMP_OBJECT_IS_STACKINIT(route));
-    g_assert(route->parent._ref_count == 1);
-    r = NMP_OBJECT_CAST_IP4_ROUTE(route);
-    g_assert(NM_FLAGS_HAS(r->r_rtm_flags, RTM_F_CLONED));
-    g_assert(r->ifindex == ifindex);
-    g_assert(r->network == a);
-    g_assert(r->plen == 32);
-
-    nmtstp_run_command_check("ip route flush dev %s", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-}
-
-static void
-test_ip4_zero_gateway(void)
-{
-    int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-
-    nmtstp_run_command_check("ip route add 1.2.3.1/32 via 0.0.0.0 dev %s", DEVICE_NAME);
-    nmtstp_run_command_check("ip route add 1.2.3.2/32 dev %s", DEVICE_NAME);
-
-    NMTST_WAIT_ASSERT(100, {
-        nmtstp_wait_for_signal(NM_PLATFORM_GET, 10);
-        if (nmtstp_ip4_route_get(NM_PLATFORM_GET,
-                                 ifindex,
-                                 nmtst_inet4_from_string("1.2.3.1"),
-                                 32,
-                                 0,
-                                 0)
-            && nmtstp_ip4_route_get(NM_PLATFORM_GET,
-                                    ifindex,
-                                    nmtst_inet4_from_string("1.2.3.2"),
-                                    32,
-                                    0,
-                                    0))
-            break;
-    });
-
-    nmtstp_run_command_check("ip route flush dev %s", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-}
-
-static void
-test_ip4_route_options(gconstpointer test_data)
-{
-    const int         TEST_IDX = GPOINTER_TO_INT(test_data);
-    const int         IFINDEX  = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    gs_unref_ptrarray GPtrArray *routes = NULL;
-#define RTS_MAX 3
-    NMPlatformIP4Route   rts_add[RTS_MAX] = {};
-    NMPlatformIP4Route   rts_cmp[RTS_MAX] = {};
-    NMPlatformIP4Address addr[1]          = {};
-    guint                i;
-    guint                rts_n  = 0;
-    guint                addr_n = 0;
-
-    switch (TEST_IDX) {
-    case 1:
-        rts_add[rts_n++] = ((NMPlatformIP4Route){
-            .ifindex   = IFINDEX,
-            .rt_source = NM_IP_CONFIG_SOURCE_USER,
-            .network   = nmtst_inet4_from_string("172.16.1.0"),
-            .plen      = 24,
-            .metric    = 20,
-            .tos       = 0x28,
-            .window    = 10000,
-            .cwnd      = 16,
-            .initcwnd  = 30,
-            .initrwnd  = 50,
-            .mtu       = 1350,
-            .lock_cwnd = TRUE,
-        });
-        break;
-    case 2:
-        addr[addr_n++]   = ((NMPlatformIP4Address){
-            .ifindex      = IFINDEX,
-            .address      = nmtst_inet4_from_string("172.16.1.5"),
-            .peer_address = nmtst_inet4_from_string("172.16.1.5"),
-            .plen         = 24,
-            .lifetime     = NM_PLATFORM_LIFETIME_PERMANENT,
-            .preferred    = NM_PLATFORM_LIFETIME_PERMANENT,
-            .n_ifa_flags  = 0,
-        });
-        rts_add[rts_n++] = ((NMPlatformIP4Route){
-            .ifindex   = IFINDEX,
-            .rt_source = NM_IP_CONFIG_SOURCE_USER,
-            .network   = nmtst_inet4_from_string("172.17.1.0"),
-            .gateway   = nmtst_inet4_from_string("172.16.1.1"),
-            .plen      = 24,
-            .metric    = 20,
-        });
-        rts_add[rts_n++] = ((NMPlatformIP4Route){
-            .ifindex     = IFINDEX,
-            .rt_source   = NM_IP_CONFIG_SOURCE_USER,
-            .network     = nmtst_inet4_from_string("172.19.1.0"),
-            .gateway     = nmtst_inet4_from_string("172.18.1.1"),
-            .r_rtm_flags = RTNH_F_ONLINK,
-            .plen        = 24,
-            .metric      = 20,
-        });
-        break;
-    default:
-        g_assert_not_reached();
-        break;
-    }
-    g_assert(rts_n <= G_N_ELEMENTS(rts_add));
-    g_assert(addr_n <= G_N_ELEMENTS(addr));
-
-    for (i = 0; i < addr_n; i++) {
-        const NMPlatformIP4Address *a = &addr[i];
-
-        g_assert(a->ifindex == IFINDEX);
-        g_assert(nm_platform_ip4_address_add(
-            NM_PLATFORM_GET,
-            a->ifindex,
-            a->address,
-            a->plen,
-            a->peer_address,
-            nm_platform_ip4_broadcast_address_create(a->address, a->plen),
-            a->lifetime,
-            a->preferred,
-            a->n_ifa_flags,
-            a->label));
-        if (a->peer_address == a->address)
-            _wait_for_ipv4_addr_device_route(NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen);
-    }
-
-    for (i = 0; i < rts_n; i++)
-        g_assert(NMTST_NM_ERR_SUCCESS(
-            nm_platform_ip4_route_add(NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i])));
-
-    for (i = 0; i < rts_n; i++) {
-        rts_cmp[i] = rts_add[i];
-        nm_platform_ip_route_normalize(AF_INET, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i]));
-    }
-
-    routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, IFINDEX);
-    g_assert_cmpint(routes->len, ==, rts_n);
-    nmtst_platform_ip4_routes_equal_aptr((const NMPObject *const *) routes->pdata,
-                                         rts_cmp,
-                                         routes->len,
-                                         TRUE);
-
-    for (i = 0; i < rts_n; i++) {
-        g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET,
-                                                  IFINDEX,
-                                                  rts_add[i].network,
-                                                  rts_add[i].plen,
-                                                  rts_add[i].metric));
-    }
-#undef RTS_MAX
-}
-
-static void
-test_ip6_route_get(void)
-{
-    int                    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    const struct in6_addr *a;
-    int                    result;
-    nm_auto_nmpobj NMPObject *route = NULL;
-    const NMPlatformIP6Route *r;
-
-    nmtstp_run_command_check("ip -6 route add fd01:abcd::/64 via fe80::99 dev %s", DEVICE_NAME);
-
-    NMTST_WAIT_ASSERT(100, {
-        nmtstp_wait_for_signal(NM_PLATFORM_GET, 10);
-        if (nmtstp_ip6_route_get(NM_PLATFORM_GET,
-                                 ifindex,
-                                 nmtst_inet6_from_string("fd01:abcd::"),
-                                 64,
-                                 NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
-                                 NULL,
-                                 0))
-            break;
-    });
-
-    a      = nmtst_inet6_from_string("fd01:abcd::42");
-    result = nm_platform_ip_route_get(NM_PLATFORM_GET,
-                                      AF_INET6,
-                                      a,
-                                      nmtst_get_rand_uint32() % 2 ? 0 : ifindex,
-                                      &route);
-
-    g_assert(NMTST_NM_ERR_SUCCESS(result));
-    g_assert(NMP_OBJECT_GET_TYPE(route) == NMP_OBJECT_TYPE_IP6_ROUTE);
-    g_assert(!NMP_OBJECT_IS_STACKINIT(route));
-    g_assert(route->parent._ref_count == 1);
-    r = NMP_OBJECT_CAST_IP6_ROUTE(route);
-    g_assert(r->ifindex == ifindex);
-    nmtst_assert_ip6_address(&r->network, "fd01:abcd::42");
-    g_assert_cmpint(r->plen, ==, 128);
-    nmtst_assert_ip6_address(&r->gateway, "fe80::99");
-
-    nmtstp_run_command_check("ip -6 route flush dev %s", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 50);
-}
-
-static void
-test_ip6_route_options(gconstpointer test_data)
-{
-    const int         TEST_IDX = GPOINTER_TO_INT(test_data);
-    const int         IFINDEX  = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    gs_unref_ptrarray GPtrArray *routes = NULL;
-#define RTS_MAX 3
-    NMPlatformIP6Route   rts_add[RTS_MAX]             = {};
-    NMPlatformIP6Route   rts_cmp[RTS_MAX]             = {};
-    NMPlatformIP6Address addr[1]                      = {};
-    struct in6_addr      addr_in6[G_N_ELEMENTS(addr)] = {};
-    guint                rts_n                        = 0;
-    guint                addr_n                       = 0;
-    guint                i;
-
-    switch (TEST_IDX) {
-    case 1:
-        rts_add[rts_n++] = ((NMPlatformIP6Route){
-            .ifindex   = IFINDEX,
-            .rt_source = NM_IP_CONFIG_SOURCE_USER,
-            .network   = *nmtst_inet6_from_string("2001:db8:a:b:0:0:0:0"),
-            .plen      = 64,
-            .gateway   = in6addr_any,
-            .metric    = 1024,
-            .window    = 20000,
-            .cwnd      = 8,
-            .initcwnd  = 22,
-            .initrwnd  = 33,
-            .mtu       = 1300,
-            .lock_mtu  = TRUE,
-        });
-        break;
-    case 2:
-        addr[addr_n++]   = ((NMPlatformIP6Address){
-            .ifindex      = IFINDEX,
-            .address      = *nmtst_inet6_from_string("2000::2"),
-            .plen         = 128,
-            .peer_address = in6addr_any,
-            .lifetime     = NM_PLATFORM_LIFETIME_PERMANENT,
-            .preferred    = NM_PLATFORM_LIFETIME_PERMANENT,
-            .n_ifa_flags  = 0,
-        });
-        rts_add[rts_n++] = ((NMPlatformIP6Route){
-            .ifindex   = IFINDEX,
-            .rt_source = NM_IP_CONFIG_SOURCE_USER,
-            .network   = *nmtst_inet6_from_string("1010::1"),
-            .plen      = 128,
-            .gateway   = in6addr_any,
-            .metric    = 256,
-            .pref_src  = *nmtst_inet6_from_string("2000::2"),
-        });
-        break;
-    case 3:
-        addr[addr_n++]   = ((NMPlatformIP6Address){
-            .ifindex      = IFINDEX,
-            .address      = *nmtst_inet6_from_string("2001:db8:8086::5"),
-            .plen         = 128,
-            .peer_address = in6addr_any,
-            .lifetime     = NM_PLATFORM_LIFETIME_PERMANENT,
-            .preferred    = NM_PLATFORM_LIFETIME_PERMANENT,
-            .n_ifa_flags  = 0,
-        });
-        rts_add[rts_n++] = ((NMPlatformIP6Route){
-            .ifindex   = IFINDEX,
-            .rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER),
-            .network   = *nmtst_inet6_from_string("2001:db8:8086::"),
-            .plen      = 110,
-            .metric    = 10021,
-            .mss       = 0,
-        });
-        rts_add[rts_n++] = ((NMPlatformIP6Route){
-            .ifindex   = IFINDEX,
-            .rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER),
-            .network   = *nmtst_inet6_from_string("2001:db8:abad:c0de::"),
-            .plen      = 64,
-            .gateway   = *nmtst_inet6_from_string("2001:db8:8086::1"),
-            .metric    = 21,
-            .mss       = 0,
-        });
-        break;
-    default:
-        g_assert_not_reached();
-    }
-    g_assert(rts_n <= G_N_ELEMENTS(rts_add));
-    g_assert(addr_n <= G_N_ELEMENTS(addr));
-
-    for (i = 0; i < addr_n; i++) {
-        g_assert(addr[i].ifindex == IFINDEX);
-        addr_in6[i] = addr[i].address;
-        g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET,
-                                             IFINDEX,
-                                             addr[i].address,
-                                             addr[i].plen,
-                                             addr[i].peer_address,
-                                             addr[i].lifetime,
-                                             addr[i].preferred,
-                                             addr[i].n_ifa_flags));
-    }
-    _wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6);
-
-    for (i = 0; i < rts_n; i++)
-        g_assert(NMTST_NM_ERR_SUCCESS(
-            nm_platform_ip6_route_add(NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i])));
-
-    for (i = 0; i < rts_n; i++) {
-        rts_cmp[i] = rts_add[i];
-        nm_platform_ip_route_normalize(AF_INET6, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i]));
-    }
-
-    routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, IFINDEX);
-    g_assert_cmpint(routes->len, ==, rts_n);
-    nmtst_platform_ip6_routes_equal_aptr((const NMPObject *const *) routes->pdata,
-                                         rts_cmp,
-                                         routes->len,
-                                         TRUE);
-
-    for (i = 0; i < rts_n; i++) {
-        g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET,
-                                                  IFINDEX,
-                                                  rts_add[i].network,
-                                                  rts_add[i].plen,
-                                                  rts_add[i].metric));
-    }
-
-    for (i = 0; i < addr_n; i++) {
-        nmtstp_ip6_address_del(NM_PLATFORM_GET, EX, IFINDEX, rts_add[i].network, rts_add[i].plen);
-    }
-#undef RTS_MAX
-}
-
-/*****************************************************************************/
-
-static void
-test_ip(gconstpointer test_data)
-{
-    const int             TEST_IDX = GPOINTER_TO_INT(test_data);
-    const int             IFINDEX  = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    guint                 i, j, k;
-    const NMPlatformLink *l;
-    char                  ifname[IFNAMSIZ];
-    char                  ifname2[IFNAMSIZ];
-    char                  s1[NM_UTILS_INET_ADDRSTRLEN];
-    NMPlatform *          platform = NM_PLATFORM_GET;
-    const int             EX_      = -1;
-    struct {
-        int ifindex;
-    } iface_data[10] = {
-        {0},
-    };
-    int   order_idx[G_N_ELEMENTS(iface_data)] = {0};
-    guint order_len;
-    guint try;
-
-    for (i = 0; i < G_N_ELEMENTS(iface_data); i++) {
-        nm_sprintf_buf(ifname, "v%02u", i);
-        nm_sprintf_buf(ifname2, "w%02u", i);
-
-        g_assert(!nm_platform_link_get_by_ifname(platform, ifname));
-        g_assert(!nm_platform_link_get_by_ifname(platform, ifname2));
-        l                     = nmtstp_link_veth_add(platform, EX_, ifname, ifname2);
-        iface_data[i].ifindex = l->ifindex;
-
-        nmtstp_link_set_updown(platform, EX_, iface_data[i].ifindex, TRUE);
-        nmtstp_link_set_updown(platform,
-                               EX_,
-                               nmtstp_link_get(platform, -1, ifname2)->ifindex,
-                               TRUE);
-
-        nm_sprintf_buf(s1, "192.168.7.%d", 100 + i);
-        nmtstp_ip4_address_add(platform,
-                               EX_,
-                               iface_data[i].ifindex,
-                               nmtst_inet4_from_string(s1),
-                               24,
-                               nmtst_inet4_from_string(s1),
-                               3600,
-                               3600,
-                               0,
-                               NULL);
-    }
-
-    order_len = 0;
-    for (try = 0; try < 5 * G_N_ELEMENTS(order_idx); try++) {
-        NMPObject                    o;
-        NMPlatformIP4Route *         r;
-        guint                        idx;
-        const NMDedupMultiHeadEntry *head_entry;
-        NMPLookup                    lookup;
-
-        nmp_object_stackinit(&o, NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
-        r          = NMP_OBJECT_CAST_IP4_ROUTE(&o);
-        r->network = nmtst_inet4_from_string("192.168.9.0");
-        r->plen    = 24;
-        r->metric  = 109;
-
-        if (order_len == 0
-            || (order_len < G_N_ELEMENTS(order_idx) && nmtst_get_rand_uint32() % 2)) {
-again_find_idx:
-            idx = nmtst_get_rand_uint32() % G_N_ELEMENTS(iface_data);
-            for (i = 0; i < order_len; i++) {
-                if (order_idx[i] == idx)
-                    goto again_find_idx;
-            }
-            order_idx[order_len++] = idx;
-
-            r->ifindex = iface_data[idx].ifindex;
-            g_assert(
-                NMTST_NM_ERR_SUCCESS(nm_platform_ip4_route_add(platform, NMP_NLM_FLAG_APPEND, r)));
-        } else {
-            i   = nmtst_get_rand_uint32() % order_len;
-            idx = order_idx[i];
-            for (i++; i < order_len; i++)
-                order_idx[i - 1] = order_idx[i];
-            order_len--;
-
-            r->ifindex = iface_data[idx].ifindex;
-            g_assert(nm_platform_object_delete(platform, &o));
-        }
-
-        head_entry =
-            nm_platform_lookup(platform,
-                               nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_IP4_ROUTE));
-        for (j = 0; j < G_N_ELEMENTS(iface_data); j++) {
-            gboolean         has;
-            NMDedupMultiIter iter;
-            const NMPObject *o_cached;
-
-            has = FALSE;
-            for (k = 0; k < order_len; k++) {
-                if (order_idx[k] == j) {
-                    g_assert(!has);
-                    has = TRUE;
-                }
-            }
-
-            nmp_cache_iter_for_each (&iter, head_entry, &o_cached) {
-                const NMPlatformIP4Route *r_cached = NMP_OBJECT_CAST_IP4_ROUTE(o_cached);
-
-                if (r_cached->ifindex != iface_data[j].ifindex || r_cached->metric != 109)
-                    continue;
-
-                g_assert(has);
-                has = FALSE;
-            }
-            g_assert(!has);
-        }
-    }
-
-    for (i = 0; i < G_N_ELEMENTS(iface_data); i++)
-        g_assert(nm_platform_link_delete(platform, iface_data[i].ifindex));
-
-    (void) TEST_IDX;
-    (void) IFINDEX;
-}
-
-/*****************************************************************************/
-
-#define FRA_SUPPRESS_IFGROUP   13
-#define FRA_SUPPRESS_PREFIXLEN 14
-#define FRA_L3MDEV             19
-#define FRA_UID_RANGE          20
-#define FRA_PROTOCOL           21
-#define FRA_IP_PROTO           22
-#define FRA_SPORT_RANGE        23
-#define FRA_DPORT_RANGE        24
-
-static const NMPObject *
-_rule_find_by_priority(NMPlatform *platform, guint32 priority)
-{
-    const NMDedupMultiHeadEntry *head_entry;
-    NMDedupMultiIter             iter;
-    const NMPObject *            o;
-    const NMPObject *            obj = NULL;
-    NMPLookup                    lookup;
-
-    nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
-    head_entry = nm_platform_lookup(platform, &lookup);
-    nmp_cache_iter_for_each (&iter, head_entry, &o) {
-        if (NMP_OBJECT_CAST_ROUTING_RULE(o)->priority != priority)
-            continue;
-        g_assert(!obj);
-        obj = o;
-    }
-    return obj;
-}
-
-static const NMPObject *
-_rule_check_kernel_support_one(NMPlatform *platform, const NMPlatformRoutingRule *rr)
-{
-    nm_auto_nmpobj const NMPObject *obj = NULL;
-    int                             r;
-
-    g_assert(!_rule_find_by_priority(platform, rr->priority));
-
-    r = nm_platform_routing_rule_add(platform, NMP_NLM_FLAG_ADD, rr);
-    g_assert_cmpint(r, ==, 0);
-
-    obj = nmp_object_ref(_rule_find_by_priority(platform, rr->priority));
-    g_assert(obj);
-
-    r = nm_platform_object_delete(platform, obj);
-    g_assert_cmpint(r, ==, TRUE);
-
-    g_assert(!_rule_find_by_priority(platform, rr->priority));
-
-    return g_steal_pointer(&obj);
-}
-
-static gboolean
-_rule_check_kernel_support(NMPlatform *platform, int attribute)
-{
-    static int support[] = {
-        [FRA_SUPPRESS_IFGROUP]   = 0,
-        [FRA_SUPPRESS_PREFIXLEN] = 0,
-        [FRA_L3MDEV]             = 0,
-        [FRA_UID_RANGE]          = 0,
-        [FRA_PROTOCOL]           = 0,
-        [FRA_IP_PROTO]           = 0,
-        [FRA_SPORT_RANGE]        = 0,
-        [FRA_DPORT_RANGE]        = 0,
-    };
-    const guint32 PROBE_PRORITY = 12033;
-    gboolean      sup;
-    int           i;
-
-    g_assert(NM_IS_PLATFORM(platform));
-
-    if (attribute == -1) {
-        for (i = 0; i < G_N_ELEMENTS(support); i++) {
-            if (support[i] < 0) {
-                /* indicate that some test was skipped. */
-                return FALSE;
-            }
-        }
-        return TRUE;
-    }
-
-    g_assert(attribute >= 0 && attribute < G_N_ELEMENTS(support));
-
-    if (support[attribute] != 0)
-        return support[attribute] >= 0;
-
-    switch (attribute) {
-    case FRA_SUPPRESS_IFGROUP:
-    {
-        nm_auto_nmpobj const NMPObject *obj = NULL;
-        const NMPlatformRoutingRule     rr  = {
-            .addr_family              = AF_INET,
-            .priority                 = PROBE_PRORITY,
-            .suppress_ifgroup_inverse = ~((guint32) 1245),
-        };
-
-        obj = _rule_check_kernel_support_one(platform, &rr);
-
-        sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->suppress_prefixlen_inverse
-              == rr.suppress_ifgroup_inverse;
-        break;
-    }
-    case FRA_SUPPRESS_PREFIXLEN:
-    {
-        nm_auto_nmpobj const NMPObject *obj = NULL;
-        const NMPlatformRoutingRule     rr  = {
-            .addr_family                = AF_INET,
-            .priority                   = PROBE_PRORITY,
-            .suppress_prefixlen_inverse = ~((guint32) 1245),
-        };
-
-        obj = _rule_check_kernel_support_one(platform, &rr);
-
-        sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->suppress_prefixlen_inverse
-              == rr.suppress_prefixlen_inverse;
-        break;
-    }
-    case FRA_L3MDEV:
-    {
-        nm_auto_nmpobj const NMPObject *obj = NULL;
-        const NMPlatformRoutingRule     rr  = {
-            .addr_family = AF_INET,
-            .priority    = PROBE_PRORITY,
-            .l3mdev      = TRUE,
-        };
-
-        obj = _rule_check_kernel_support_one(platform, &rr);
-
-        sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->l3mdev != 0;
-        break;
-    }
-    case FRA_UID_RANGE:
-    {
-        nm_auto_nmpobj const NMPObject *obj = NULL;
-        const NMPlatformRoutingRule     rr  = {
-            .addr_family = AF_INET,
-            .priority    = PROBE_PRORITY,
-            .uid_range =
-                {
-                    .start = 0,
-                    .end   = 0,
-                },
-            .uid_range_has = TRUE,
-        };
-
-        obj = _rule_check_kernel_support_one(platform, &rr);
-
-        sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->uid_range_has;
-        break;
-    }
-    case FRA_PROTOCOL:
-    {
-        nm_auto_nmpobj const NMPObject *obj = NULL;
-        const NMPlatformRoutingRule     rr  = {
-            .addr_family = AF_INET,
-            .priority    = PROBE_PRORITY,
-            .protocol    = 30,
-        };
-
-        obj = _rule_check_kernel_support_one(platform, &rr);
-
-        sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->protocol == 30;
-        break;
-    }
-    case FRA_IP_PROTO:
-    {
-        nm_auto_nmpobj const NMPObject *obj = NULL;
-        const NMPlatformRoutingRule     rr  = {
-            .addr_family = AF_INET,
-            .priority    = PROBE_PRORITY,
-            .ip_proto    = 30,
-        };
-
-        obj = _rule_check_kernel_support_one(platform, &rr);
-
-        sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->ip_proto == 30;
-        break;
-    }
-    case FRA_SPORT_RANGE:
-    case FRA_DPORT_RANGE:
-        /* these were added at the same time as FRA_IP_PROTO. */
-        sup = _rule_check_kernel_support(platform, FRA_IP_PROTO);
-        break;
-    default:
-        g_assert_not_reached();
-        return FALSE;
-    }
-
-    support[attribute] = sup ? 1 : -1;
-
-    _LOGD("kernel support for routing rule attribute #%d %s",
-          attribute,
-          sup ? "detected" : "not detected");
-    return sup;
-}
-
-static const NMPObject *
-_platform_has_routing_rule(NMPlatform *platform, const NMPObject *obj)
-{
-    const NMPObject *o;
-
-    g_assert(NM_IS_PLATFORM(platform));
-    g_assert(NMP_OBJECT_IS_VALID(obj));
-    g_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_ROUTING_RULE);
-
-    o = nm_platform_lookup_obj(platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj);
-    if (o)
-        g_assert(nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(obj),
-                                              NMP_OBJECT_CAST_ROUTING_RULE(o),
-                                              NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID)
-                 == 0);
-
-    return o;
-}
-
-static guint32
-_rr_rand_choose_u32(guint32 p)
-{
-    /* mostly, we just return zero. We want that each rule only has few
-     * fields set -- having most fields at zero. */
-    if ((p % 10000u) < 7500u)
-        return 0;
-
-    /* give 0xFFFFFFFFu extra probability. */
-    if ((p % 10000u) < 8250u)
-        return 0xFFFFFFFFu;
-
-    /* choose a small number. */
-    if ((p % 10000u) < 9125u)
-        return (~p) % 10;
-
-    /* finally, full random number. */
-    return ~p;
-}
-
-#define _rr_rand_choose_u8(p) ((guint8) _rr_rand_choose_u32((p)))
-
-static const NMPObject *
-_rule_create_random(NMPlatform *platform)
-{
-    NMPObject *            obj;
-    NMPlatformRoutingRule *rr;
-    guint32                p;
-    int                    addr_size;
-    guint                  i;
-    char                   saddr[NM_UTILS_INET_ADDRSTRLEN];
-    static struct {
-        guint32 uid;
-        guint32 euid;
-        bool    initialized;
-    } uids;
-
-    if (G_UNLIKELY(!uids.initialized)) {
-        uids.uid         = getuid();
-        uids.euid        = geteuid();
-        uids.initialized = TRUE;
-    }
-
-    obj = nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, NULL);
-    rr  = NMP_OBJECT_CAST_ROUTING_RULE(obj);
-
-    rr->addr_family = nmtst_rand_select(AF_INET, AF_INET6);
-
-    addr_size = nm_utils_addr_family_to_size(rr->addr_family);
-
-    p = nmtst_get_rand_uint32();
-    if ((p % 1000u) < 50)
-        rr->priority = 10000 + ((~p) % 20u);
-
-    p = nmtst_get_rand_uint32();
-    if ((p % 1000u) < 40)
-        nm_sprintf_buf(rr->iifname, "t-iif-%u", (~p) % 20);
-    else if ((p % 1000u) < 80)
-        nm_sprintf_buf(rr->iifname, "%s", DEVICE_NAME);
-
-    p = nmtst_get_rand_uint32();
-    if ((p % 1000u) < 40)
-        nm_sprintf_buf(rr->oifname, "t-oif-%d", (~p) % 20);
-    else if ((p % 1000u) < 80)
-        nm_sprintf_buf(rr->oifname, "%s", DEVICE_NAME);
-
-    for (i = 0; i < 2; i++) {
-        NMIPAddr *p_addr = i ? &rr->src : &rr->dst;
-        guint8 *  p_len  = i ? &rr->src_len : &rr->dst_len;
-
-        p = nmtst_get_rand_uint32();
-        if ((p % 1000u) < 100) {
-            /* if we set src_len/dst_len to zero, the src/dst is actually ignored.
-             *
-             * For fuzzying, still set the address. It shall have no further effect.
-             * */
-            *p_len = (~p) % (addr_size * 8 + 1);
-            p      = nmtst_get_rand_uint32();
-            if ((p % 3u) == 0) {
-                if (rr->addr_family == AF_INET)
-                    p_addr->addr4 =
-                        nmtst_inet4_from_string(nm_sprintf_buf(saddr, "192.192.5.%u", (~p) % 256u));
-                else
-                    p_addr->addr6 = *nmtst_inet6_from_string(
-                        nm_sprintf_buf(saddr, "1:2:3:4::f:%02x", (~p) % 256u));
-            } else if ((p % 3u) == 1)
-                nmtst_rand_buf(NULL, p_addr, addr_size);
-        }
-    }
-
-    p = nmtst_get_rand_uint32();
-    if ((p % 1000u) < 50)
-        rr->tun_id = 10000 + ((~p) % 20);
-
-again_action:
-    p = nmtst_get_rand_uint32();
-    if ((p % 1000u) < 500)
-        rr->action = FR_ACT_UNSPEC;
-    else if ((p % 1000u) < 750)
-        rr->action = (~p) % 12u;
-    else
-        rr->action = (~p) % 0x100u;
-
-    rr->priority = _rr_rand_choose_u32(nmtst_get_rand_uint32());
-
-    if (rr->action == FR_ACT_GOTO && rr->priority == G_MAXINT32)
-        goto again_action;
-
-    p = nmtst_get_rand_uint32();
-    if ((p % 10000u) < 100)
-        rr->goto_target = rr->priority + 1;
-    else
-        rr->goto_target = _rr_rand_choose_u32(nmtst_get_rand_uint32());
-    if (rr->action == FR_ACT_GOTO && rr->goto_target <= rr->priority)
-        goto again_action;
-
-    p = nmtst_get_rand_uint32();
-    if ((p % 1000u) < 25) {
-        if (_rule_check_kernel_support(platform, FRA_L3MDEV)) {
-            rr->l3mdev = TRUE;
-            rr->table  = RT_TABLE_UNSPEC;
-        }
-    }
-
-again_table:
-    if (!rr->l3mdev) {
-        p = nmtst_get_rand_uint32();
-        if ((p % 1000u) < 700)
-            rr->table = RT_TABLE_UNSPEC;
-        else if ((p % 1000u) < 850)
-            rr->table = RT_TABLE_MAIN;
-        else
-            rr->table = 10000 + ((~p) % 10);
-        if (rr->action == FR_ACT_TO_TBL && rr->table == RT_TABLE_UNSPEC)
-            goto again_table;
-    }
-
-    rr->fwmark = _rr_rand_choose_u32(nmtst_get_rand_uint32());
-    rr->fwmask = _rr_rand_choose_u32(nmtst_get_rand_uint32());
-
-    rr->flow = _rr_rand_choose_u32(nmtst_get_rand_uint32());
-
-    if (_rule_check_kernel_support(platform, FRA_PROTOCOL))
-        rr->protocol = _rr_rand_choose_u8(nmtst_get_rand_uint32());
-
-#define IPTOS_TOS_MASK 0x1E
-
-again_tos:
-    rr->tos = _rr_rand_choose_u8(nmtst_get_rand_uint32());
-    if (rr->addr_family == AF_INET && rr->tos & ~IPTOS_TOS_MASK)
-        goto again_tos;
-
-    if (_rule_check_kernel_support(platform, FRA_IP_PROTO))
-        rr->ip_proto = _rr_rand_choose_u8(nmtst_get_rand_uint32());
-
-    if (_rule_check_kernel_support(platform, FRA_SUPPRESS_PREFIXLEN))
-        rr->suppress_prefixlen_inverse = ~_rr_rand_choose_u32(nmtst_get_rand_uint32());
-
-    if (_rule_check_kernel_support(platform, FRA_SUPPRESS_IFGROUP))
-        rr->suppress_ifgroup_inverse = ~_rr_rand_choose_u32(nmtst_get_rand_uint32());
-
-    if (_rule_check_kernel_support(platform, FRA_UID_RANGE)) {
-        p                 = nmtst_get_rand_uint32();
-        rr->uid_range_has = (p % 10000u) < 200;
-    }
-
-again_uid_range:
-    rr->uid_range.start = nmtst_rand_select(0u, uids.uid, uids.euid);
-    rr->uid_range.end   = nmtst_rand_select(0u, uids.uid, uids.euid);
-    if (rr->uid_range_has) {
-        if (rr->uid_range.end < rr->uid_range.start)
-            NM_SWAP(&rr->uid_range.start, &rr->uid_range.end);
-        if (rr->uid_range.start == ((guint32) -1) || rr->uid_range.end == ((guint32) -1))
-            goto again_uid_range;
-    }
-
-    for (i = 0; i < 2; i++) {
-        NMFibRulePortRange *range     = i ? &rr->sport_range : &rr->dport_range;
-        int                 attribute = i ? FRA_SPORT_RANGE : FRA_DPORT_RANGE;
-
-        if (!_rule_check_kernel_support(platform, attribute))
-            continue;
-
-        p = nmtst_get_rand_uint32();
-        if ((p % 10000u) < 300) {
-            while (range->start == 0) {
-                p            = p ^ nmtst_get_rand_uint32();
-                range->start = nmtst_rand_select(1u, 0xFFFEu, ((p) % 0xFFFEu) + 1);
-                range->end =
-                    nmtst_rand_select(1u, 0xFFFEu, ((p >> 16) % 0xFFFEu) + 1, range->start);
-                if (range->end < range->start)
-                    NM_SWAP(&range->start, &range->end);
-            }
-        }
-    }
-
-    p = nmtst_get_rand_uint32() % 1000u;
-    if (p < 100)
-        rr->flags |= FIB_RULE_INVERT;
-
-    return obj;
-}
-
-static gboolean
-_rule_fuzzy_equal(const NMPObject *obj, const NMPObject *obj_comp, int op_type)
-{
-    const NMPlatformRoutingRule *rr    = NMP_OBJECT_CAST_ROUTING_RULE(obj);
-    NMPlatformRoutingRule        rr_co = *NMP_OBJECT_CAST_ROUTING_RULE(obj_comp);
-
-    switch (op_type) {
-    case RTM_NEWRULE:
-        /* when adding rules with RTM_NEWRULE, kernel checks whether an existing
-         * rule already exists and may fail with EEXIST. This check has issues
-         * and reject legitimate rules (rh#1686075).
-         *
-         * Work around that. */
-        if (rr->src_len == 0)
-            rr_co.src_len = 0;
-        if (rr->dst_len == 0)
-            rr_co.dst_len = 0;
-        if (rr->flow == 0)
-            rr_co.flow = 0;
-        if (rr->tos == 0)
-            rr_co.tos = 0;
-        rr_co.suppress_prefixlen_inverse = rr->suppress_prefixlen_inverse;
-        rr_co.suppress_ifgroup_inverse   = rr->suppress_ifgroup_inverse;
-        if (!NM_FLAGS_HAS(rr->flags, FIB_RULE_INVERT))
-            rr_co.flags &= ~((guint32) FIB_RULE_INVERT);
-        else
-            rr_co.flags |= ((guint32) FIB_RULE_INVERT);
-        break;
-    case RTM_DELRULE:
-        /* when deleting a rule with RTM_DELRULE, kernel tries to find the
-         * candidate to delete. It might delete the wrong rule (rh#1685816). */
-        if (rr->action == FR_ACT_UNSPEC)
-            rr_co.action = FR_ACT_UNSPEC;
-        if (rr->iifname[0] == '\0')
-            rr_co.iifname[0] = '\0';
-        if (rr->oifname[0] == '\0')
-            rr_co.oifname[0] = '\0';
-        if (rr->src_len == 0)
-            rr_co.src_len = 0;
-        if (rr->dst_len == 0)
-            rr_co.dst_len = 0;
-        if (rr->tun_id == 0)
-            rr_co.tun_id = 0;
-        if (rr->fwmark == 0)
-            rr_co.fwmark = 0;
-        if (rr->fwmask == 0)
-            rr_co.fwmask = 0;
-        if (rr->flow == 0)
-            rr_co.flow = 0;
-        if (rr->protocol == 0)
-            rr_co.protocol = 0;
-        if (rr->table == RT_TABLE_UNSPEC)
-            rr_co.table = RT_TABLE_UNSPEC;
-        if (rr->l3mdev == 0)
-            rr_co.l3mdev = 0;
-        if (rr->tos == 0)
-            rr_co.tos = 0;
-        if (rr->ip_proto == 0)
-            rr_co.ip_proto = 0;
-        rr_co.suppress_prefixlen_inverse = rr->suppress_prefixlen_inverse;
-        if (rr->suppress_ifgroup_inverse == 0)
-            rr_co.suppress_ifgroup_inverse = 0;
-        if (!rr->uid_range_has)
-            rr_co.uid_range_has = FALSE;
-        if (rr->sport_range.start == 0 && rr->sport_range.end == 0) {
-            rr_co.sport_range.start = 0;
-            rr_co.sport_range.end   = 0;
-        }
-        if (rr->dport_range.start == 0 && rr->dport_range.end == 0) {
-            rr_co.dport_range.start = 0;
-            rr_co.dport_range.end   = 0;
-        }
-        if (!NM_FLAGS_HAS(rr->flags, FIB_RULE_INVERT))
-            rr_co.flags &= ~((guint32) FIB_RULE_INVERT);
-        else
-            rr_co.flags |= ((guint32) FIB_RULE_INVERT);
-        break;
-    default:
-        g_assert_not_reached();
-        break;
-    }
-
-    return nm_platform_routing_rule_cmp(rr, &rr_co, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0;
-}
-
-static void
-test_rule(gconstpointer test_data)
-{
-    const int         TEST_IDX                = GPOINTER_TO_INT(test_data);
-    const gboolean    TEST_SYNC               = (TEST_IDX == 4);
-    gs_unref_ptrarray GPtrArray *objs         = NULL;
-    gs_unref_ptrarray GPtrArray *objs_initial = NULL;
-    NMPlatform *                 platform     = NM_PLATFORM_GET;
-    guint                        i, j, n;
-    int                          r;
-    gboolean                     had_an_issue_exist = FALSE;
-
-    nm_platform_process_events(platform);
-
-    objs_initial = nmtstp_platform_routing_rules_get_all(platform, AF_UNSPEC);
-    g_assert(objs_initial);
-    g_assert_cmpint(objs_initial->len, ==, 5);
-
-    nmtstp_run_command_check("ip rule add table 766");
-    nm_platform_process_events(platform);
-
-    for (i = 6; i > 0; i--) {
-        gs_unref_ptrarray GPtrArray *objs_extern = NULL;
-        const NMPObject *            obj;
-
-        objs_extern = nmtstp_platform_routing_rules_get_all(platform, AF_UNSPEC);
-
-        g_assert(objs_extern);
-        g_assert_cmpint(objs_extern->len, ==, i);
-
-        if (TEST_IDX != 1)
-            nmtst_rand_perm(NULL, objs_extern->pdata, NULL, sizeof(gpointer), objs_extern->len);
-
-        obj = objs_extern->pdata[0];
-
-        r = nm_platform_object_delete(platform, obj);
-        g_assert_cmpint(r, ==, TRUE);
-
-        g_assert(!_platform_has_routing_rule(platform, obj));
-    }
-
-    g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), ==, 0);
-
-#define RR(...)                                  \
-    nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, \
-                   (const NMPlatformObject *) &((NMPlatformRoutingRule){__VA_ARGS__}))
-
-    objs = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET, .priority = 10, ));
-
-    g_ptr_array_add(
-        objs,
-        RR(.addr_family = AF_INET, .priority = 400, .action = FR_ACT_GOTO, .goto_target = 10000, ));
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET6, ));
-
-    g_ptr_array_add(objs,
-                    RR(.addr_family = AF_INET6, .action = FR_ACT_TO_TBL, .table = RT_TABLE_MAIN, ));
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET6, .priority = 30, ));
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET6, .priority = 50, .iifname = "t-iif-1", ));
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET6, .priority = 50, .iifname = "t-oif-1", ));
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET, .priority = 50, .iifname = "t-oif-2", ));
-
-    g_ptr_array_add(objs, RR(.addr_family = AF_INET, .priority = 51, .iifname = DEVICE_NAME, ));
-
-    if (TEST_IDX == 1) {
-        g_ptr_array_add(objs, RR(.addr_family = AF_INET, .table = 10000, ));
-    }
-
-    if (TEST_IDX != 1) {
-        nmtst_rand_perm(NULL, objs->pdata, NULL, sizeof(gpointer), objs->len);
-        g_ptr_array_set_size(objs, nmtst_get_rand_uint32() % (objs->len + 1));
-    }
-
-    n = (TEST_IDX != 1) ? nmtst_get_rand_uint32() % 50u : 0u;
-    for (i = 0; i < n; i++) {
-        nm_auto_nmpobj const NMPObject *o   = NULL;
-        guint                           try = 0;
-
-again:
-        o = _rule_create_random(platform);
-        for (j = 0; j < objs->len; j++) {
-            if (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(o),
-                                             NMP_OBJECT_CAST_ROUTING_RULE(objs->pdata[j]),
-                                             NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID)
-                == 0) {
-                try++;
-                g_assert(try < 200);
-                nm_clear_pointer(&o, nmp_object_unref);
-                goto again;
-            }
-        }
-        g_ptr_array_add(objs, (gpointer) g_steal_pointer(&o));
-    }
-
-    if (TEST_IDX != 1)
-        nmtst_rand_perm(NULL, objs->pdata, NULL, sizeof(gpointer), objs->len);
-
-    if (TEST_SYNC) {
-        gs_unref_hashtable GHashTable *unique_priorities = g_hash_table_new(NULL, NULL);
-        nm_auto_unref_rules_manager NMPRulesManager *rules_manager =
-            nmp_rules_manager_new(platform);
-        gs_unref_ptrarray GPtrArray *objs_sync  = NULL;
-        gconstpointer                USER_TAG_1 = &platform;
-        gconstpointer                USER_TAG_2 = &unique_priorities;
-
-        objs_sync = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-
-        /* ensure that priorities are unique. Otherwise, it confuses the test, because
-         * kernel may wrongly be unable to add/delete routes based on a wrong match
-         * (rh#1685816, rh#1685816). */
-        for (i = 0; i < objs->len; i++) {
-            const NMPObject *obj  = objs->pdata[i];
-            guint32          prio = NMP_OBJECT_CAST_ROUTING_RULE(obj)->priority;
-
-            if (!NM_IN_SET(prio, 0, 32766, 32767)
-                && !g_hash_table_contains(unique_priorities, GUINT_TO_POINTER(prio))) {
-                g_hash_table_add(unique_priorities, GUINT_TO_POINTER(prio));
-                g_ptr_array_add(objs_sync, (gpointer) nmp_object_ref(obj));
-            }
-        }
-
-        for (i = 0; i < objs_sync->len; i++) {
-            nmp_rules_manager_track(rules_manager,
-                                    NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]),
-                                    1,
-                                    USER_TAG_1,
-                                    NULL);
-            if (nmtst_get_rand_bool()) {
-                /* this has no effect, because a negative priority (of same absolute value)
-                 * has lower priority than the positive priority above. */
-                nmp_rules_manager_track(rules_manager,
-                                        NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]),
-                                        -1,
-                                        USER_TAG_2,
-                                        NULL);
-            }
-            if (nmtst_get_rand_uint32() % objs_sync->len == 0) {
-                nmp_rules_manager_sync(rules_manager, FALSE);
-                g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
-                                ==,
-                                i + 1);
-            }
-        }
-
-        nmp_rules_manager_sync(rules_manager, FALSE);
-        g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
-                        ==,
-                        objs_sync->len);
-
-        for (i = 0; i < objs_sync->len; i++) {
-            switch (nmtst_get_rand_uint32() % 3) {
-            case 0:
-                nmp_rules_manager_untrack(rules_manager,
-                                          NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]),
-                                          USER_TAG_1);
-                nmp_rules_manager_untrack(rules_manager,
-                                          NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]),
-                                          USER_TAG_1);
-                break;
-            case 1:
-                nmp_rules_manager_track(rules_manager,
-                                        NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]),
-                                        -1,
-                                        USER_TAG_1,
-                                        NULL);
-                break;
-            case 2:
-                nmp_rules_manager_track(rules_manager,
-                                        NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]),
-                                        -2,
-                                        USER_TAG_2,
-                                        NULL);
-                break;
-            }
-            if (nmtst_get_rand_uint32() % objs_sync->len == 0) {
-                nmp_rules_manager_sync(rules_manager, FALSE);
-                g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
-                                ==,
-                                objs_sync->len - i - 1);
-            }
-        }
-
-        nmp_rules_manager_sync(rules_manager, FALSE);
-
-    } else {
-        for (i = 0; i < objs->len;) {
-            const NMPObject *obj = objs->pdata[i];
-
-            for (j = 0; j < objs->len; j++)
-                g_assert((j < i) == (!!_platform_has_routing_rule(platform, objs->pdata[j])));
-
-            r = nm_platform_routing_rule_add(platform,
-                                             NMP_NLM_FLAG_ADD,
-                                             NMP_OBJECT_CAST_ROUTING_RULE(obj));
-
-            if (r == -EEXIST) {
-                g_assert(!_platform_has_routing_rule(platform, obj));
-                /* this should not happen, but there are bugs in kernel (rh#1686075). */
-                for (j = 0; j < i; j++) {
-                    const NMPObject *obj2 = objs->pdata[j];
-
-                    g_assert(_platform_has_routing_rule(platform, obj2));
-
-                    if (_rule_fuzzy_equal(obj, obj2, RTM_NEWRULE)) {
-                        r = 0;
-                        break;
-                    }
-                }
-                if (r == 0) {
-                    /* OK, the rule is shadowed by another rule, and kernel does not allow
-                     * us to add this one (rh#1686075). Drop this from the test. */
-                    g_ptr_array_remove_index(objs, i);
-                    had_an_issue_exist = TRUE;
-                    continue;
-                }
-            }
-
-            if (r != 0) {
-                NMPLookup                    lookup;
-                const NMDedupMultiHeadEntry *head_entry;
-                NMDedupMultiIter             iter;
-                const NMPObject *            o;
-
-                g_print(">>> failing... errno=%d, rule=%s\n",
-                        r,
-                        nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
-
-                nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
-                head_entry = nm_platform_lookup(platform, &lookup);
-                nmp_cache_iter_for_each (&iter, head_entry, &o) {
-                    char ch = ' ';
-
-                    if (NMP_OBJECT_CAST_ROUTING_RULE(o)->addr_family
-                            == NMP_OBJECT_CAST_ROUTING_RULE(obj)->addr_family
-                        && NMP_OBJECT_CAST_ROUTING_RULE(o)->priority
-                               == NMP_OBJECT_CAST_ROUTING_RULE(obj)->priority)
-                        ch = '*';
-                    g_print(">>> existing rule: %c %s\n",
-                            ch,
-                            nmp_object_to_string(o, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
-                }
-
-                nmtstp_run_command_check("ip rule");
-                nmtstp_run_command_check("ip -6 rule");
-                g_assert_cmpint(r, ==, 0);
-            }
-
-            g_assert(_platform_has_routing_rule(platform, obj));
-
-            g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
-                            ==,
-                            i + 1);
-
-            i++;
-        }
-
-        if (TEST_IDX != 1)
-            nmtst_rand_perm(NULL, objs->pdata, NULL, sizeof(gpointer), objs->len);
-
-        if (_LOGD_ENABLED()) {
-            nmtstp_run_command_check("ip rule");
-            nmtstp_run_command_check("ip -6 rule");
-        }
-
-        for (i = 0; i < objs->len; i++) {
-            const NMPObject *obj = objs->pdata[i];
-            const NMPObject *obj2;
-
-            for (j = 0; j < objs->len; j++)
-                g_assert((j < i) == (!_platform_has_routing_rule(platform, objs->pdata[j])));
-
-            g_assert(_platform_has_routing_rule(platform, obj));
-
-            r = nm_platform_object_delete(platform, obj);
-            g_assert_cmpint(r, ==, TRUE);
-
-            obj2 = _platform_has_routing_rule(platform, obj);
-
-            if (obj2) {
-                guint k;
-
-                /* When deleting a rule, kernel does a fuzzy match, ignoring for example:
-                 *  - action, if it is FR_ACT_UNSPEC
-                 *  - iifname,oifname if it is unspecified
-                 * rh#1685816
-                 *
-                 * That means, we may have deleted the wrong rule. Which one? */
-                k = i;
-                for (j = i + 1; j < objs->len; j++) {
-                    if (!_platform_has_routing_rule(platform, objs->pdata[j])) {
-                        g_assert_cmpint(k, ==, i);
-                        k = j;
-                    }
-                }
-                g_assert_cmpint(k, >, i);
-
-                if (!_rule_fuzzy_equal(obj, objs->pdata[k], RTM_DELRULE)) {
-                    g_print(">>> failing...\n");
-                    g_print(">>> no fuzzy match between: %s\n",
-                            nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
-                    g_print(
-                        ">>>                    and: %s\n",
-                        nmp_object_to_string(objs->pdata[k], NMP_OBJECT_TO_STRING_ALL, NULL, 0));
-                    g_assert_not_reached();
-                }
-
-                objs->pdata[i] = objs->pdata[k];
-                objs->pdata[k] = (gpointer) obj;
-                obj2           = NULL;
-            }
-
-            g_assert(!obj2);
-
-            g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
-                            ==,
-                            objs->len - i - 1);
-        }
-    }
-
-    g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), ==, 0);
-
-    for (i = 0; i < objs_initial->len; i++) {
-        const NMPObject *obj = objs_initial->pdata[i];
-
-        for (j = 0; j < objs_initial->len; j++)
-            g_assert((j < i) == (!!_platform_has_routing_rule(platform, objs_initial->pdata[j])));
-
-        r = nm_platform_routing_rule_add(platform,
-                                         NMP_NLM_FLAG_ADD,
-                                         NMP_OBJECT_CAST_ROUTING_RULE(obj));
-        g_assert_cmpint(r, ==, 0);
-    }
-    for (j = 0; j < objs_initial->len; j++)
-        g_assert(_platform_has_routing_rule(platform, objs_initial->pdata[j]));
-    g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC),
-                    ==,
-                    objs_initial->len);
-
-    /* the tests passed as good as we could (as good as we implemented workarounds for them).
-     * Still, with this kernel, not all features were fully tested. Mark the test as skipped. */
-    if (had_an_issue_exist)
-        g_test_skip("adding a rule failed with EEXIST although it should not (rh#1686075)");
-    else if (!_rule_check_kernel_support(platform, -1))
-        g_test_skip("some kernel features were not available and skipped for the test");
-}
-
-/*****************************************************************************/
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
-    nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-void
-_nmtstp_setup_tests(void)
-{
-#define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, TRUE)
-#define add_test_func_data(testpath, test_func, arg) \
-    nmtstp_env1_add_test_func_data(testpath, test_func, arg, TRUE)
-    add_test_func("/route/ip4", test_ip4_route);
-    add_test_func("/route/ip6", test_ip6_route);
-    add_test_func("/route/ip4_metric0", test_ip4_route_metric0);
-    add_test_func_data("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER(1));
-    if (nmtstp_is_root_test())
-        add_test_func_data("/route/ip4_options/2", test_ip4_route_options, GINT_TO_POINTER(2));
-    add_test_func_data("/route/ip6_options/1", test_ip6_route_options, GINT_TO_POINTER(1));
-    add_test_func_data("/route/ip6_options/2", test_ip6_route_options, GINT_TO_POINTER(2));
-    add_test_func_data("/route/ip6_options/3", test_ip6_route_options, GINT_TO_POINTER(3));
-
-    if (nmtstp_is_root_test()) {
-        add_test_func_data("/route/ip/1", test_ip, GINT_TO_POINTER(1));
-        add_test_func("/route/ip4_route_get", test_ip4_route_get);
-        add_test_func("/route/ip6_route_get", test_ip6_route_get);
-        add_test_func("/route/ip4_zero_gateway", test_ip4_zero_gateway);
-    }
-
-    if (nmtstp_is_root_test()) {
-        add_test_func_data("/route/rule/1", test_rule, GINT_TO_POINTER(1));
-        add_test_func_data("/route/rule/2", test_rule, GINT_TO_POINTER(2));
-        add_test_func_data("/route/rule/3", test_rule, GINT_TO_POINTER(3));
-        add_test_func_data("/route/rule/4", test_rule, GINT_TO_POINTER(4));
-    }
-}
diff --git a/src/platform/tests/test-tc.c b/src/platform/tests/test-tc.c
deleted file mode 100644
index 4cbe4f5d..00000000
--- a/src/platform/tests/test-tc.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-
-#include "nm-default.h"
-
-#include <linux/pkt_sched.h>
-
-#include "nm-test-utils-core.h"
-#include "platform/nmp-object.h"
-#include "platform/nmp-netns.h"
-#include "platform/nm-platform-utils.h"
-#include "test-common.h"
-
-static NMPObject *
-qdisc_new(int ifindex, const char *kind, guint32 parent)
-{
-    NMPObject *obj;
-
-    obj        = nmp_object_new(NMP_OBJECT_TYPE_QDISC, NULL);
-    obj->qdisc = (NMPlatformQdisc){
-        .ifindex = ifindex,
-        .kind    = kind,
-        .parent  = parent,
-    };
-
-    return obj;
-}
-
-static GPtrArray *
-qdiscs_lookup(int ifindex)
-{
-    NMPLookup lookup;
-
-    return nm_platform_lookup_clone(NM_PLATFORM_GET,
-                                    nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_QDISC, ifindex),
-                                    NULL,
-                                    NULL);
-}
-
-static void
-test_qdisc1(void)
-{
-    int               ifindex;
-    gs_unref_ptrarray GPtrArray *known = NULL;
-    gs_unref_ptrarray GPtrArray *plat  = NULL;
-    NMPObject *                  obj;
-    NMPlatformQdisc *            qdisc;
-
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert_cmpint(ifindex, >, 0);
-
-    nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME);
-    nmtstp_run_command_check("tc qdisc add dev %s root sfq", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 0);
-
-    known = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-    g_ptr_array_add(known, qdisc_new(ifindex, "fq_codel", TC_H_ROOT));
-    g_ptr_array_add(known, qdisc_new(ifindex, "ingress", TC_H_INGRESS));
-
-    g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known));
-    plat = qdiscs_lookup(ifindex);
-    g_assert(plat);
-    g_assert_cmpint(plat->len, ==, 2);
-
-    obj   = plat->pdata[0];
-    qdisc = NMP_OBJECT_CAST_QDISC(obj);
-    g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT);
-    g_assert_cmpstr(qdisc->kind, ==, "fq_codel");
-
-    obj   = plat->pdata[1];
-    qdisc = NMP_OBJECT_CAST_QDISC(obj);
-    g_assert_cmpint(qdisc->parent, ==, TC_H_INGRESS);
-    g_assert_cmpstr(qdisc->kind, ==, "ingress");
-}
-
-static void
-test_qdisc_fq_codel(void)
-{
-    int               ifindex;
-    gs_unref_ptrarray GPtrArray *known = NULL;
-    gs_unref_ptrarray GPtrArray *plat  = NULL;
-    NMPObject *                  obj;
-    NMPlatformQdisc *            qdisc;
-
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert_cmpint(ifindex, >, 0);
-
-    nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 0);
-
-    known                       = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-    obj                         = qdisc_new(ifindex, "fq_codel", TC_H_ROOT);
-    obj->qdisc.handle           = TC_H_MAKE(0x8142 << 16, 0);
-    obj->qdisc.fq_codel.limit   = 2048;
-    obj->qdisc.fq_codel.flows   = 64;
-    obj->qdisc.fq_codel.quantum = 1000;
-    g_ptr_array_add(known, obj);
-
-    g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known));
-    plat = qdiscs_lookup(ifindex);
-    g_assert(plat);
-    g_assert_cmpint(plat->len, ==, 1);
-
-    obj   = plat->pdata[0];
-    qdisc = NMP_OBJECT_CAST_QDISC(obj);
-    g_assert_cmpstr(qdisc->kind, ==, "fq_codel");
-    g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8142 << 16, 0));
-    g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT);
-    g_assert_cmpint(qdisc->fq_codel.limit, ==, 2048);
-    g_assert_cmpint(qdisc->fq_codel.flows, ==, 64);
-    g_assert_cmpint(qdisc->fq_codel.quantum, ==, 1000);
-}
-
-static void
-test_qdisc_sfq(void)
-{
-    int               ifindex;
-    gs_unref_ptrarray GPtrArray *known = NULL;
-    gs_unref_ptrarray GPtrArray *plat  = NULL;
-    NMPObject *                  obj;
-    NMPlatformQdisc *            qdisc;
-
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert_cmpint(ifindex, >, 0);
-
-    nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 0);
-
-    known             = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-    obj               = qdisc_new(ifindex, "sfq", TC_H_ROOT);
-    obj->qdisc.handle = TC_H_MAKE(0x8143 << 16, 0);
-    obj->qdisc.sfq.perturb_period = 10;
-    obj->qdisc.sfq.quantum        = 1540;
-    obj->qdisc.sfq.flows          = 256;
-    g_ptr_array_add(known, obj);
-
-    g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known));
-    plat = qdiscs_lookup(ifindex);
-    g_assert(plat);
-    g_assert_cmpint(plat->len, ==, 1);
-
-    obj   = plat->pdata[0];
-    qdisc = NMP_OBJECT_CAST_QDISC(obj);
-    g_assert_cmpstr(qdisc->kind, ==, "sfq");
-    g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8143 << 16, 0));
-    g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT);
-    g_assert_cmpint(qdisc->sfq.perturb_period, ==, 10);
-    g_assert_cmpint(qdisc->sfq.quantum, ==, 1540);
-    g_assert_cmpint(qdisc->sfq.flows, ==, 256);
-}
-
-static void
-test_qdisc_tbf(void)
-{
-    int               ifindex;
-    gs_unref_ptrarray GPtrArray *known = NULL;
-    gs_unref_ptrarray GPtrArray *plat  = NULL;
-    NMPObject *                  obj;
-    NMPlatformQdisc *            qdisc;
-
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME);
-    g_assert_cmpint(ifindex, >, 0);
-
-    nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME);
-
-    nmtstp_wait_for_signal(NM_PLATFORM_GET, 0);
-
-    known                = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-    obj                  = qdisc_new(ifindex, "tbf", TC_H_ROOT);
-    obj->qdisc.handle    = TC_H_MAKE(0x8143 << 16, 0);
-    obj->qdisc.tbf.rate  = 1000000;
-    obj->qdisc.tbf.burst = 2000;
-    obj->qdisc.tbf.limit = 3000;
-    g_ptr_array_add(known, obj);
-
-    obj               = qdisc_new(ifindex, "sfq", TC_H_MAKE(0x8143 << 16, 0));
-    obj->qdisc.handle = TC_H_MAKE(0x8005 << 16, 0);
-    g_ptr_array_add(known, obj);
-
-    g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known));
-    plat = qdiscs_lookup(ifindex);
-    g_assert(plat);
-    g_assert_cmpint(plat->len, ==, 2);
-
-    obj   = plat->pdata[0];
-    qdisc = NMP_OBJECT_CAST_QDISC(obj);
-    g_assert_cmpstr(qdisc->kind, ==, "tbf");
-    g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8143 << 16, 0));
-    g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT);
-    g_assert_cmpint(qdisc->tbf.rate, ==, 1000000);
-    g_assert_cmpint(qdisc->tbf.burst, ==, 2000);
-    g_assert_cmpint(qdisc->tbf.limit, ==, 3000);
-
-    obj   = plat->pdata[1];
-    qdisc = NMP_OBJECT_CAST_QDISC(obj);
-    g_assert_cmpstr(qdisc->kind, ==, "sfq");
-    g_assert_cmpint(qdisc->parent, ==, TC_H_MAKE(0x8143 << 16, 0));
-    g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8005 << 16, 0));
-}
-
-/*****************************************************************************/
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
-    nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-void
-_nmtstp_setup_tests(void)
-{
-    if (nmtstp_is_root_test()) {
-        nmtstp_env1_add_test_func("/link/qdisc/1", test_qdisc1, TRUE);
-        nmtstp_env1_add_test_func("/link/qdisc/fq_codel", test_qdisc_fq_codel, TRUE);
-        nmtstp_env1_add_test_func("/link/qdisc/sfq", test_qdisc_sfq, TRUE);
-        nmtstp_env1_add_test_func("/link/qdisc/tbf", test_qdisc_tbf, TRUE);
-    }
-}