diff options
Diffstat (limited to 'src/platform/tests')
| -rw-r--r-- | src/platform/tests/meson.build | 43 | ||||
| -rw-r--r-- | src/platform/tests/monitor.c | 78 | ||||
| -rw-r--r-- | src/platform/tests/test-address.c | 465 | ||||
| -rw-r--r-- | src/platform/tests/test-cleanup.c | 188 | ||||
| -rw-r--r-- | src/platform/tests/test-common.c | 2569 | ||||
| -rw-r--r-- | src/platform/tests/test-common.h | 610 | ||||
| -rw-r--r-- | src/platform/tests/test-link.c | 3819 | ||||
| -rw-r--r-- | src/platform/tests/test-nmp-object.c | 617 | ||||
| -rw-r--r-- | src/platform/tests/test-platform-general.c | 772 | ||||
| -rw-r--r-- | src/platform/tests/test-route.c | 1926 | ||||
| -rw-r--r-- | src/platform/tests/test-tc.c | 222 |
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, ¬_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); - } -} |