Commit a3033884 authored by Toke Høiland-Jørgensen's avatar Toke Høiland-Jørgensen Committed by Alexei Starovoitov
Browse files

selftests/bpf: Move open_netns() and close_netns() into network_helpers.c



These will also be used by the xdp_do_redirect test being added in the next
commit.

Signed-off-by: default avatarToke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20220309105346.100053-5-toke@redhat.com
parent 24592ad1
Loading
Loading
Loading
Loading
+86 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
#define _GNU_SOURCE

#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>

#include <arpa/inet.h>
#include <sys/mount.h>
#include <sys/stat.h>

#include <linux/err.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/limits.h>

#include "bpf_util.h"
#include "network_helpers.h"
#include "test_progs.h"

#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(MSG, ...) ({						\
@@ -356,3 +363,82 @@ char *ping_command(int family)
	}
	return "ping";
}

struct nstoken {
	int orig_netns_fd;
};

static int setns_by_fd(int nsfd)
{
	int err;

	err = setns(nsfd, CLONE_NEWNET);
	close(nsfd);

	if (!ASSERT_OK(err, "setns"))
		return err;

	/* Switch /sys to the new namespace so that e.g. /sys/class/net
	 * reflects the devices in the new namespace.
	 */
	err = unshare(CLONE_NEWNS);
	if (!ASSERT_OK(err, "unshare"))
		return err;

	/* Make our /sys mount private, so the following umount won't
	 * trigger the global umount in case it's shared.
	 */
	err = mount("none", "/sys", NULL, MS_PRIVATE, NULL);
	if (!ASSERT_OK(err, "remount private /sys"))
		return err;

	err = umount2("/sys", MNT_DETACH);
	if (!ASSERT_OK(err, "umount2 /sys"))
		return err;

	err = mount("sysfs", "/sys", "sysfs", 0, NULL);
	if (!ASSERT_OK(err, "mount /sys"))
		return err;

	err = mount("bpffs", "/sys/fs/bpf", "bpf", 0, NULL);
	if (!ASSERT_OK(err, "mount /sys/fs/bpf"))
		return err;

	return 0;
}

struct nstoken *open_netns(const char *name)
{
	int nsfd;
	char nspath[PATH_MAX];
	int err;
	struct nstoken *token;

	token = malloc(sizeof(struct nstoken));
	if (!ASSERT_OK_PTR(token, "malloc token"))
		return NULL;

	token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
	if (!ASSERT_GE(token->orig_netns_fd, 0, "open /proc/self/ns/net"))
		goto fail;

	snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
	nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
	if (!ASSERT_GE(nsfd, 0, "open netns fd"))
		goto fail;

	err = setns_by_fd(nsfd);
	if (!ASSERT_OK(err, "setns_by_fd"))
		goto fail;

	return token;
fail:
	free(token);
	return NULL;
}

void close_netns(struct nstoken *token)
{
	ASSERT_OK(setns_by_fd(token->orig_netns_fd), "setns_by_fd");
	free(token);
}
+9 −0
Original line number Diff line number Diff line
@@ -55,4 +55,13 @@ int make_sockaddr(int family, const char *addr_str, __u16 port,
		  struct sockaddr_storage *addr, socklen_t *len);
char *ping_command(int family);

struct nstoken;
/**
 * open_netns() - Switch to specified network namespace by name.
 *
 * Returns token with which to restore the original namespace
 * using close_netns().
 */
struct nstoken *open_netns(const char *name);
void close_netns(struct nstoken *token);
#endif
+0 −89
Original line number Diff line number Diff line
@@ -10,8 +10,6 @@
 * to drop unexpected traffic.
 */

#define _GNU_SOURCE

#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/if_tun.h>
@@ -19,10 +17,8 @@
#include <linux/sysctl.h>
#include <linux/time_types.h>
#include <linux/net_tstamp.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <unistd.h>

@@ -92,91 +88,6 @@ static int write_file(const char *path, const char *newval)
	return 0;
}

struct nstoken {
	int orig_netns_fd;
};

static int setns_by_fd(int nsfd)
{
	int err;

	err = setns(nsfd, CLONE_NEWNET);
	close(nsfd);

	if (!ASSERT_OK(err, "setns"))
		return err;

	/* Switch /sys to the new namespace so that e.g. /sys/class/net
	 * reflects the devices in the new namespace.
	 */
	err = unshare(CLONE_NEWNS);
	if (!ASSERT_OK(err, "unshare"))
		return err;

	/* Make our /sys mount private, so the following umount won't
	 * trigger the global umount in case it's shared.
	 */
	err = mount("none", "/sys", NULL, MS_PRIVATE, NULL);
	if (!ASSERT_OK(err, "remount private /sys"))
		return err;

	err = umount2("/sys", MNT_DETACH);
	if (!ASSERT_OK(err, "umount2 /sys"))
		return err;

	err = mount("sysfs", "/sys", "sysfs", 0, NULL);
	if (!ASSERT_OK(err, "mount /sys"))
		return err;

	err = mount("bpffs", "/sys/fs/bpf", "bpf", 0, NULL);
	if (!ASSERT_OK(err, "mount /sys/fs/bpf"))
		return err;

	return 0;
}

/**
 * open_netns() - Switch to specified network namespace by name.
 *
 * Returns token with which to restore the original namespace
 * using close_netns().
 */
static struct nstoken *open_netns(const char *name)
{
	int nsfd;
	char nspath[PATH_MAX];
	int err;
	struct nstoken *token;

	token = calloc(1, sizeof(struct nstoken));
	if (!ASSERT_OK_PTR(token, "malloc token"))
		return NULL;

	token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
	if (!ASSERT_GE(token->orig_netns_fd, 0, "open /proc/self/ns/net"))
		goto fail;

	snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
	nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
	if (!ASSERT_GE(nsfd, 0, "open netns fd"))
		goto fail;

	err = setns_by_fd(nsfd);
	if (!ASSERT_OK(err, "setns_by_fd"))
		goto fail;

	return token;
fail:
	free(token);
	return NULL;
}

static void close_netns(struct nstoken *token)
{
	ASSERT_OK(setns_by_fd(token->orig_netns_fd), "setns_by_fd");
	free(token);
}

static int netns_setup_namespaces(const char *verb)
{
	const char * const *ns = namespaces;