mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-10 00:00:21 +01:00
platform: merge branch 'th/platform-tun'
https://github.com/NetworkManager/NetworkManager/pull/87
This commit is contained in:
commit
69e80d6c51
10 changed files with 295 additions and 82 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
if (nmtst_get_rand_bool ()) {
|
||||
const NMPlatformLnkTun lnk = {
|
||||
.type = IFF_TAP,
|
||||
.pi = FALSE,
|
||||
.vnet_hdr = FALSE,
|
||||
.multi_queue = FALSE,
|
||||
.persist = FALSE,
|
||||
};
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1468,6 +1468,73 @@ 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,
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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?"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue