diff options
author | Thomas Haller <thaller@redhat.com> | 2018-04-09 20:29:13 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-04-09 20:29:13 +0200 |
commit | 69e80d6c51d9447445c8ef2696c8f3ef8c4d1dc9 (patch) | |
tree | 833709ce514cc580e216d9ddf2cbcb1fb07263b0 | |
parent | 7a063a91c7f8db8f78cab124bf9ba80a242be233 (diff) | |
parent | ef93f6caad0552b8bd73057caed52147dac5eda0 (diff) | |
download | NetworkManager-69e80d6c51d9447445c8ef2696c8f3ef8c4d1dc9.tar.gz |
platform: merge branch 'th/platform-tun'
https://github.com/NetworkManager/NetworkManager/pull/87
-rw-r--r-- | shared/nm-utils/nm-test-utils.h | 14 | ||||
-rw-r--r-- | src/devices/nm-device-tun.c | 3 | ||||
-rw-r--r-- | src/devices/tests/test-lldp.c | 52 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 87 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 29 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 6 | ||||
-rw-r--r-- | src/platform/tests/test-common.c | 103 | ||||
-rw-r--r-- | src/platform/tests/test-common.h | 12 | ||||
-rw-r--r-- | src/platform/tests/test-link.c | 65 | ||||
-rwxr-xr-x | tools/run-nm-test.sh | 8 |
10 files changed, 296 insertions, 83 deletions
diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index d7233de20f..f44f49d835 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -162,6 +162,14 @@ g_assert_not_reached (); \ } G_STMT_END +#define nmtst_assert_nonnull(command) \ + ({ \ + typeof (*(command)) *_ptr = (command); \ + \ + g_assert (_ptr && (TRUE || (command))); \ + _ptr; \ + }) + #define nmtst_assert_success(success, error) \ G_STMT_START { \ g_assert_no_error (error); \ @@ -808,6 +816,12 @@ nmtst_get_rand_int (void) return g_rand_int (nmtst_get_rand ()); } +static inline gboolean +nmtst_get_rand_bool (void) +{ + return nmtst_get_rand_int () % 2; +} + static inline gpointer nmtst_rand_buf (GRand *rand, gpointer buffer, gsize buffer_length) { diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index 123455f16d..c3ce4b7357 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -264,7 +264,8 @@ create_and_realize (NMDevice *device, plerr = nm_platform_link_tun_add (nm_device_get_platform (device), iface, &props, - out_plink); + out_plink, + NULL); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create TUN/TAP interface '%s' for '%s': %s", diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 655f26ecad..5d0625f80a 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -347,8 +347,7 @@ static void _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { const NMPlatformLink *link; - struct ifreq ifr = { }; - int fd, s; + nm_auto_close int fd = -1; fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); if (fd == -1) { @@ -357,20 +356,45 @@ _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) return; } - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); - g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); - - /* Bring the interface up */ - s = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - g_assert (s >= 0); - ifr.ifr_flags |= IFF_UP; - g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); - nm_close (s); + if (nmtst_get_rand_bool ()) { + const NMPlatformLnkTun lnk = { + .type = IFF_TAP, + .pi = FALSE, + .vnet_hdr = FALSE, + .multi_queue = FALSE, + .persist = FALSE, + }; + + nm_close (nm_steal_fd (&fd)); + + link = nmtstp_link_tun_add (NM_PLATFORM_GET, + FALSE, + TEST_IFNAME, + &lnk, + &fd); + g_assert (link); + nmtstp_link_set_updown (NM_PLATFORM_GET, -1, link->ifindex, TRUE); + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 0); + } else { + int s; + struct ifreq ifr = { }; + + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); + g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); + + /* Bring the interface up */ + s = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + g_assert (s >= 0); + ifr.ifr_flags |= IFF_UP; + g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); + nm_close (s); + + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 100); + } - link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 100); fixture->ifindex = link->ifindex; - fixture->fd = fd; + fixture->fd = nm_steal_fd (&fd); memcpy (fixture->mac, link->addr.data, ETH_ALEN); } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index b8d252070e..0ed8fa06fb 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1396,10 +1396,6 @@ _parse_lnk_tun (const char *kind, struct nlattr *info_data) NMPObject *obj; NMPlatformLnkTun *props; - /* FIXME: the netlink API is not yet part of a released kernel version - * Disable it for now, until we are sure it is stable. */ - return NULL; - if (!info_data || !nm_streq0 (kind, "tun")) return NULL; @@ -3934,40 +3930,46 @@ cache_on_change (NMPlatform *platform, && (obj_new && obj_new->_link.netlink.is_in_netlink) && (!obj_old || !obj_old->_link.netlink.is_in_netlink)) { - if (!obj_new->_link.netlink.lnk) { + gboolean re_request_link = FALSE; + const NMPlatformLnkTun *lnk_tun; + + if ( !obj_new->_link.netlink.lnk + && NM_IN_SET (obj_new->link.type, NM_LINK_TYPE_GRE, + NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_INFINIBAND, + NM_LINK_TYPE_MACVLAN, + NM_LINK_TYPE_MACVLAN, + NM_LINK_TYPE_SIT, + NM_LINK_TYPE_TUN, + NM_LINK_TYPE_VLAN, + NM_LINK_TYPE_VXLAN)) { /* certain link-types also come with a IFLA_INFO_DATA/lnk_data. It may happen that * kernel didn't send this notification, thus when we first learn about a link * that lacks an lnk_data we re-request it again. * * For example https://bugzilla.redhat.com/show_bug.cgi?id=1284001 */ - switch (obj_new->link.type) { - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_IP6TNL: - case NM_LINK_TYPE_INFINIBAND: - case NM_LINK_TYPE_MACVLAN: - case NM_LINK_TYPE_MACVTAP: - case NM_LINK_TYPE_SIT: - case NM_LINK_TYPE_VLAN: - case NM_LINK_TYPE_VXLAN: - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER (obj_new->link.ifindex)); - break; - default: - break; - } - } - if ( obj_new->link.type == NM_LINK_TYPE_VETH - && obj_new->link.parent == 0) { + re_request_link = TRUE; + } else if ( obj_new->link.type == NM_LINK_TYPE_TUN + && obj_new->_link.netlink.lnk + && (lnk_tun = &(obj_new->_link.netlink.lnk)->lnk_tun) + && !lnk_tun->persist + && lnk_tun->pi + && !lnk_tun->vnet_hdr + && !lnk_tun->multi_queue + && !lnk_tun->owner_valid + && !lnk_tun->group_valid) { + /* kernel has/had a know issue that the first notification for TUN device would + * be sent with invalid parameters. The message looks like that kind, so refetch + * it. */ + re_request_link = TRUE; + } else if ( obj_new->link.type == NM_LINK_TYPE_VETH + && obj_new->link.parent == 0) { /* the initial notification when adding a veth pair can lack the parent/IFLA_LINK * (https://bugzilla.redhat.com/show_bug.cgi?id=1285827). * Request it again. */ - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER (obj_new->link.ifindex)); - } - if ( obj_new->link.type == NM_LINK_TYPE_ETHERNET - && obj_new->link.addr.len == 0) { + re_request_link = TRUE; + } else if ( obj_new->link.type == NM_LINK_TYPE_ETHERNET + && obj_new->link.addr.len == 0) { /* Due to a kernel bug, we sometimes receive spurious NEWLINK * messages after a wifi interface has disappeared. Since the * link is not present anymore we can't determine its type and @@ -3975,6 +3977,9 @@ cache_on_change (NMPlatform *platform, * specified. Request the link again to check if it really * exists. https://bugzilla.redhat.com/show_bug.cgi?id=1302037 */ + re_request_link = TRUE; + } + if (re_request_link) { delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (obj_new->link.ifindex)); @@ -5591,14 +5596,15 @@ static gboolean link_tun_add (NMPlatform *platform, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link) + const NMPlatformLink **out_link, + int *out_fd) { const NMPObject *obj; struct ifreq ifr = { }; nm_auto_close int fd = -1; - if (!NM_IN_SET (props->type, IFF_TAP, IFF_TUN)) - return FALSE; + nm_assert (NM_IN_SET (props->type, IFF_TAP, IFF_TUN)); + nm_assert (props->persist || out_fd); fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); if (fd < 0) @@ -5623,18 +5629,23 @@ link_tun_add (NMPlatform *platform, return FALSE; } - if (ioctl (fd, TUNSETPERSIST, (int) !!props->persist)) - return FALSE; + if (props->persist) { + if (ioctl (fd, TUNSETPERSIST, 1)) + return FALSE; + } do_request_link (platform, 0, name); obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform), 0, name, FALSE, NM_LINK_TYPE_TUN, NULL, NULL); - if (out_link) - *out_link = obj ? &obj->link : NULL; - return !!obj; + if (!obj) + return FALSE; + + NM_SET_OUT (out_link, &obj->link); + NM_SET_OUT (out_fd, nm_steal_fd (&fd)); + return TRUE; } static gboolean diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index a645da2ee6..976039def4 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -2046,6 +2046,11 @@ nm_platform_link_vxlan_add (NMPlatform *self, * @vnet_hdr: whether to set the IFF_VNET_HDR flag * @multi_queue: whether to set the IFF_MULTI_QUEUE flag * @out_link: on success, the link object + * @out_fd: (allow-none): if give, return the file descriptor for the + * created device. Note that when creating a non-persistent device, + * this argument is mandatory, otherwise it makes no sense + * to create such an interface. + * The caller is responsible for closing this file descriptor. * * Create a TUN or TAP interface. */ @@ -2053,7 +2058,8 @@ NMPlatformError nm_platform_link_tun_add (NMPlatform *self, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link) + const NMPlatformLink **out_link, + int *out_fd) { char b[255]; NMPlatformError plerr; @@ -2062,6 +2068,13 @@ nm_platform_link_tun_add (NMPlatform *self, g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (NM_IN_SET (props->type, IFF_TUN, IFF_TAP), NM_PLATFORM_ERROR_BUG); + + /* creating a non-persistant device requires that the caller handles + * the file descriptor. */ + g_return_val_if_fail (props->persist || out_fd, NM_PLATFORM_ERROR_BUG); + + NM_SET_OUT (out_fd, -1); plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_TUN, out_link); if (plerr != NM_PLATFORM_ERROR_SUCCESS) @@ -2069,7 +2082,7 @@ nm_platform_link_tun_add (NMPlatform *self, _LOGD ("link: adding tun '%s' %s", name, nm_platform_lnk_tun_to_string (props, b, sizeof (b))); - if (!klass->link_tun_add (self, name, props, out_link)) + if (!klass->link_tun_add (self, name, props, out_link, out_fd)) return NM_PLATFORM_ERROR_UNSPECIFIED; return NM_PLATFORM_ERROR_SUCCESS; } @@ -5120,17 +5133,19 @@ nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len type = nm_sprintf_buf (str_type, "tun type %u", (guint) lnk->type); g_snprintf (buf, len, - "%s " /* type */ - " pi %s" /* pi */ - " vnet_hdr %s" /* vnet_hdr */ + "%s" /* type */ + "%s" /* pi */ + "%s" /* vnet_hdr */ "%s" /* multi_queue */ + "%s" /* persist */ "%s" /* owner */ "%s" /* group */ "", type, - lnk->pi ? "on" : "off", - lnk->vnet_hdr ? "on" : "off", + lnk->pi ? " pi" : "", + lnk->vnet_hdr ? " vnet_hdr" : "", lnk->multi_queue ? " multi_queue" : "", + lnk->persist ? " persist" : "", lnk->owner_valid ? nm_sprintf_buf (str_owner, " owner %u", (guint) lnk->owner) : "", lnk->group_valid ? nm_sprintf_buf (str_group, " group %u", (guint) lnk->group) : ""); return buf; diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 824735083a..e6cef63bae 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -853,7 +853,8 @@ typedef struct { gboolean (*link_tun_add) (NMPlatform *platform, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link); + const NMPlatformLink **out_link, + int *out_fd); gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, const NMPlatformLink **out_link); gboolean (*infiniband_partition_delete) (NMPlatform *, int parent, int p_key); @@ -1286,7 +1287,8 @@ NMPlatformError nm_platform_link_sit_add (NMPlatform *self, NMPlatformError nm_platform_link_tun_add (NMPlatform *self, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link); + const NMPlatformLink **out_link, + int *out_fd); const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 67e74c13f2..8724fedc86 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -23,6 +23,7 @@ #include <sched.h> #include <sys/wait.h> #include <fcntl.h> +#include <linux/if_tun.h> #include "test-common.h" @@ -627,7 +628,10 @@ 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_ms) { - return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); + return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, + timeout_ms + ? nm_utils_get_monotonic_timestamp_ms () + timeout_ms + : 0); } const NMPlatformLink * @@ -635,6 +639,7 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType { const NMPlatformLink *plink; gint64 now; + gboolean waited_once = FALSE; _init_platform (&platform, FALSE); @@ -646,29 +651,24 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type)) return plink; - if (until_ms < now) + 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); } } -const NMPlatformLink * -nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms) -{ - return nmtstp_assert_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); -} - -const NMPlatformLink * -nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms) -{ - const NMPlatformLink *plink; - - plink = nmtstp_wait_for_link_until (platform, ifname, expected_link_type, until_ms); - g_assert (plink); - return plink; -} - /*****************************************************************************/ int @@ -1469,6 +1469,73 @@ nmtstp_link_sit_add (NMPlatform *platform, } const NMPlatformLink * +nmtstp_link_tun_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkTun *lnk, + int *out_fd) +{ + const NMPlatformLink *pllink = NULL; + NMPlatformError plerr; + int err; + + g_assert (nm_utils_is_valid_iface_name (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) { + gs_free char *dev = NULL; + gs_free char *local = NULL, *remote = NULL; + + 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); + plerr = nm_platform_link_tun_add (platform, name, lnk, &pllink, out_fd); + g_assert_cmpint (plerr, ==, NM_PLATFORM_ERROR_SUCCESS); + } + + g_assert (pllink); + g_assert_cmpint (pllink->type, ==, NM_LINK_TYPE_TUN); + g_assert_cmpstr (pllink->name, ==, name); + return pllink; +} + +const NMPlatformLink * nmtstp_link_vxlan_add (NMPlatform *platform, gboolean external_command, const char *name, diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 2b830cf196..bd02b0d7d3 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -129,8 +129,11 @@ const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const ch g_assert_not_reached (); \ } G_STMT_END -const NMPlatformLink *nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms); -const NMPlatformLink *nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms); +#define nmtstp_assert_wait_for_link(platform, ifname, expected_link_type, timeout_ms) \ + nmtst_assert_nonnull (nmtstp_wait_for_link (platform, ifname, expected_link_type, timeout_ms)) + +#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)) /*****************************************************************************/ @@ -307,6 +310,11 @@ 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_vxlan_add (NMPlatform *platform, gboolean external_command, const char *name, diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 90bb823ddb..dcd600ee64 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -23,6 +23,7 @@ #include <sys/mount.h> #include <sys/stat.h> #include <sys/types.h> +#include <linux/if_tun.h> #include "platform/nmp-object.h" #include "platform/nmp-netns.h" @@ -697,6 +698,8 @@ test_software_detect (gconstpointer user_data) const NMPObject *lnk; guint i_step; const gboolean ext = test_data->external_command; + NMPlatformLnkTun lnk_tun; + 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; @@ -892,6 +895,38 @@ test_software_detect (gconstpointer user_data) 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; + } default: g_assert_not_reached (); } @@ -922,7 +957,13 @@ test_software_detect (gconstpointer user_data) lnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, test_data->link_type, &plink); g_assert (plink); g_assert_cmpint (plink->ifindex, ==, ifindex); - g_assert (lnk); + + 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_GRE: { @@ -1011,6 +1052,27 @@ test_software_detect (gconstpointer user_data) 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); + + g_assert (nm_platform_lnk_tun_cmp (plnk, &lnk_tun) == 0); + break; + } case NM_LINK_TYPE_VLAN: { const NMPlatformLnkVlan *plnk = &lnk->lnk_vlan; @@ -2581,6 +2643,7 @@ _nmtstp_setup_tests (void) 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/vxlan/0", NM_LINK_TYPE_VXLAN, 0); test_software_detect_add ("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1); diff --git a/tools/run-nm-test.sh b/tools/run-nm-test.sh index 5848d0a061..2c23e7175f 100755 --- a/tools/run-nm-test.sh +++ b/tools/run-nm-test.sh @@ -121,6 +121,10 @@ else NMTST_USE_VALGRIND=0 shift; ;; + "-d") + NMTST_SET_DEBUG=1 + shift; + ;; "--test"|-t) shift TEST="$1" @@ -146,6 +150,10 @@ else fi +if [ "$NMTST_SET_DEBUG" == 1 -a -z "${NMTST_DEBUG+x}" ]; then + export NMTST_DEBUG=d +fi + if _is_true "$NMTST_MAKE_FIRST" 0; then git_dir="$(readlink -f "$(git rev-parse --show-toplevel)")" rel_path="$(realpath --relative-to="$git_dir" -m "$TEST" 2>/dev/null)" || die "cannot resolve test-name \"$TEST\". Did you call the script properly?" |