platform/tests: add tests for TUN/TAP handling

This commit is contained in:
Thomas Haller 2018-04-05 14:02:22 +02:00
parent 722f79c9c5
commit bd8ab54b8e
3 changed files with 129 additions and 1 deletions

View file

@ -23,6 +23,7 @@
#include <sched.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <linux/if_tun.h>
#include "test-common.h"
@ -1468,6 +1469,70 @@ nmtstp_link_sit_add (NMPlatform *platform,
return pllink;
}
const NMPlatformLink *
nmtstp_link_tun_add (NMPlatform *platform,
gboolean external_command,
const char *name,
const NMPlatformLnkTun *lnk)
{
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));
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 {
plerr = nm_platform_link_tun_add (platform, name, lnk, &pllink);
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,

View file

@ -307,6 +307,10 @@ 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);
const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform,
gboolean external_command,
const char *name,

View file

@ -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,7 @@ test_software_detect (gconstpointer user_data)
const NMPObject *lnk;
guint i_step;
const gboolean ext = test_data->external_command;
NMPlatformLnkTun lnk_tun;
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 +894,35 @@ 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 (),
/* arguably, adding non-persistant devices from within NetworkManager makes
* no sense. */
.persist = TRUE,
};
break;
default:
g_assert_not_reached ();
break;
}
g_assert (nmtstp_link_tun_add (NULL, ext, DEVICE_NAME, &lnk_tun));
break;
}
default:
g_assert_not_reached ();
}
@ -922,7 +953,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 +1048,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 +2639,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);