All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anton Protopopov <a.s.protopopov@gmail.com>
To: bpf <bpf@vger.kernel.org>,
	lsm <linux-security-module@vger.kernel.org>,
	netdev <netdev@vger.kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>,
	KP Singh <kpsingh@kernel.org>,
	Matt Bobrowski <matt@bobrowski.net>,
	John Fastabend <john.fastabend@gmail.com>,
	Christian Brauner <brauner@kernel.org>,
	Paul Moore <paul@paul-moore.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: Anton Protopopov <a.s.protopopov@gmail.com>
Subject: [PATCH bpf-next 5/7] selftests/bpf: Add netdevsim helper library
Date: Mon, 31 Aug 2026 11:09:30 +0000	[thread overview]
Message-ID: <20260831110934.241898-6-a.s.protopopov@gmail.com> (raw)
In-Reply-To: <20260831110934.241898-1-a.s.protopopov@gmail.com>

Add a minimal netdevsim helper library for the BPF selftests.  This
covers basics: netdevsim creation with one port and one queue, which
we need for the upcoming BPF selftests.

Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
---
 tools/testing/selftests/bpf/Makefile          |   1 +
 .../testing/selftests/bpf/netdevsim_helpers.c | 176 ++++++++++++++++++
 .../testing/selftests/bpf/netdevsim_helpers.h |   9 +
 3 files changed, 186 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/netdevsim_helpers.c
 create mode 100644 tools/testing/selftests/bpf/netdevsim_helpers.h

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index b481b867f372..c21f89dbe70c 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -862,6 +862,7 @@ TRUNNER_EXTRA_SOURCES := test_progs.c		\
 			 unpriv_helpers.c 	\
 			 sysctl_helpers.c	\
 			 netlink_helpers.c	\
+			 netdevsim_helpers.c	\
 			 jit_disasm_helpers.c	\
 			 io_helpers.c		\
 			 test_loader.c		\
diff --git a/tools/testing/selftests/bpf/netdevsim_helpers.c b/tools/testing/selftests/bpf/netdevsim_helpers.c
new file mode 100644
index 000000000000..fbed7442b2e8
--- /dev/null
+++ b/tools/testing/selftests/bpf/netdevsim_helpers.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/rtnetlink.h>
+#include <poll.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "netdevsim_helpers.h"
+
+static int echo(const char *path, const char *fmt, ...)
+{
+	char buf[64];
+	va_list ap;
+	int fd, len, err = 0;
+
+	va_start(ap, fmt);
+	len = vsnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+
+	fd = open(path, O_WRONLY);
+	if (fd < 0)
+		return -errno;
+	if (write(fd, buf, len) != len)
+		err = -errno;
+	close(fd);
+
+	return err;
+}
+
+void netdevsim_destroy(unsigned int id)
+{
+	echo("/sys/bus/netdevsim/del_device", "%u", id);
+}
+
+static int create_new_device(void)
+{
+	unsigned int id;
+	int err;
+
+	/* if 10K is not enough, then something is clearly not right */
+	for (id = 0; id < 10000; id++) {
+		err = echo("/sys/bus/netdevsim/new_device", "%u", id);
+		if (!err)
+			return id;
+		if (err != -ENOSPC)
+			return err;
+	}
+
+	return -ENOSPC;
+}
+
+static int open_link_socket(void)
+{
+	struct sockaddr_nl addr = {
+		.nl_family = AF_NETLINK,
+		.nl_groups = RTMGRP_LINK,
+	};
+	int fd;
+
+	fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
+	if (fd < 0)
+		return -errno;
+	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {
+		int err = -errno;
+
+		close(fd);
+		return err;
+	}
+
+	return fd;
+}
+
+static int remaining_timeout_ms(const struct timespec *deadline)
+{
+	struct timespec now;
+	long long remaining;
+
+	if (clock_gettime(CLOCK_MONOTONIC, &now))
+		return -errno;
+
+	remaining = (deadline->tv_sec - now.tv_sec) * 1000 +
+		    (deadline->tv_nsec - now.tv_nsec) / 1000000;
+
+	return remaining > 0 ? remaining : 0;
+}
+
+static int recv_device_ifindex(int fd, unsigned int id, unsigned int *ifindex)
+{
+	char parent_name[32], buf[16 * 1024];
+	struct pollfd pfd = {
+		.fd = fd,
+		.events = POLLIN,
+	};
+	struct timespec deadline;
+	struct nlmsghdr *nlh;
+	int len, ret, timeout;
+
+	snprintf(parent_name, sizeof(parent_name), "netdevsim%u", id);
+	if (clock_gettime(CLOCK_MONOTONIC, &deadline))
+		return -errno;
+	deadline.tv_sec += 5;
+
+	for (timeout = remaining_timeout_ms(&deadline); timeout > 0;
+	     timeout = remaining_timeout_ms(&deadline)) {
+		ret = poll(&pfd, 1, timeout);
+		if (ret < 0) {
+			if (errno == EINTR)
+				continue;
+			return -errno;
+		}
+		if (!ret)
+			return -ETIMEDOUT;
+		if (!(pfd.revents & POLLIN))
+			return -EIO;
+
+		len = recv(fd, buf, sizeof(buf), 0);
+		if (len < 0)
+			return -errno;
+
+		for (nlh = (struct nlmsghdr *)buf; NLMSG_OK(nlh, len);
+		     nlh = NLMSG_NEXT(nlh, len)) {
+			struct ifinfomsg *ifm;
+			struct rtattr *attr;
+			int attr_len;
+
+			if (nlh->nlmsg_type != RTM_NEWLINK)
+				continue;
+
+			ifm = NLMSG_DATA(nlh);
+			attr = IFLA_RTA(ifm);
+			attr_len = IFLA_PAYLOAD(nlh);
+			for (; RTA_OK(attr, attr_len);
+			     attr = RTA_NEXT(attr, attr_len)) {
+				if (attr->rta_type != IFLA_PARENT_DEV_NAME)
+					continue;
+				if (strcmp(RTA_DATA(attr), parent_name))
+					continue;
+
+				*ifindex = ifm->ifi_index;
+				return 0;
+			}
+		}
+	}
+
+	return timeout < 0 ? timeout : -ETIMEDOUT;
+}
+
+int netdevsim_create(unsigned int *ifindex)
+{
+	int fd, id, err;
+
+	fd = open_link_socket();
+	if (fd < 0)
+		return fd;
+
+	id = create_new_device();
+	if (id < 0) {
+		close(fd);
+		return id;
+	}
+
+	err = recv_device_ifindex(fd, id, ifindex);
+	close(fd);
+	if (err) {
+		netdevsim_destroy(id);
+		return err;
+	}
+
+	return id;
+}
diff --git a/tools/testing/selftests/bpf/netdevsim_helpers.h b/tools/testing/selftests/bpf/netdevsim_helpers.h
new file mode 100644
index 000000000000..0a37d564a2c8
--- /dev/null
+++ b/tools/testing/selftests/bpf/netdevsim_helpers.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef NETDEVSIM_HELPERS_H
+#define NETDEVSIM_HELPERS_H
+
+int netdevsim_create(unsigned int *ifindex);
+void netdevsim_destroy(unsigned int id);
+
+#endif /* NETDEVSIM_HELPERS_H */
-- 
2.43.0


  parent reply	other threads:[~2026-08-31 10:59 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 11:09 [PATCH bpf-next 0/7] Add new way to add BPF LSM hooks Anton Protopopov
2026-08-31 11:09 ` [PATCH bpf-next 1/7] bpf: Allow BPF LSM programs to attach to more hooks Anton Protopopov
2026-08-31 11:50   ` bot+bpf-ci
2026-08-31 12:48     ` Anton Protopopov
2026-08-31 22:42   ` Paul Moore
2026-09-01 13:36     ` Anton Protopopov
2026-09-01 22:15       ` Paul Moore
2026-09-02 15:31         ` Anton Protopopov
2026-09-02 19:43           ` Paul Moore
2026-08-31 11:09 ` [PATCH bpf-next 2/7] net, bpf: Add a generic netlink hook on msg_rcv Anton Protopopov
2026-08-31 12:07   ` bot+bpf-ci
2026-08-31 13:22     ` Anton Protopopov
2026-08-31 11:09 ` [PATCH bpf-next 3/7] net, bpf: Add bpf hooks for ethtool control path Anton Protopopov
2026-09-01 10:59   ` sashiko-bot
2026-08-31 11:09 ` [PATCH bpf-next 4/7] selftests/bpf: Extract some helpers from tests to the netlink library Anton Protopopov
2026-08-31 11:09 ` Anton Protopopov [this message]
2026-08-31 12:07   ` [PATCH bpf-next 5/7] selftests/bpf: Add netdevsim helper library bot+bpf-ci
2026-08-31 12:55     ` Anton Protopopov
2026-09-01 10:59   ` sashiko-bot
2026-08-31 11:09 ` [PATCH bpf-next 6/7] selftests/bpf: Add tests for the generic netlink BPF hook Anton Protopopov
2026-08-31 12:07   ` bot+bpf-ci
2026-08-31 13:01     ` Anton Protopopov
2026-08-31 11:09 ` [PATCH bpf-next 7/7] selftests/bpf: Add tests for BPF ethtool hooks Anton Protopopov
2026-08-31 12:07   ` bot+bpf-ci
2026-08-31 13:12     ` Anton Protopopov
2026-08-31 22:34 ` [PATCH bpf-next 0/7] Add new way to add BPF LSM hooks Jakub Kicinski
2026-09-01 12:29   ` Anton Protopopov
2026-09-02  0:49     ` Jakub Kicinski
2026-09-02 15:11       ` Anton Protopopov
2026-09-02 18:07 ` Alexei Starovoitov
2026-09-02 19:31   ` Anton Protopopov
2026-09-03 12:16     ` Justin Suess
2026-09-03 13:23       ` Anton Protopopov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260831110934.241898-6-a.s.protopopov@gmail.com \
    --to=a.s.protopopov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brauner@kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=edumazet@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=kpsingh@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=matt@bobrowski.net \
    --cc=memxor@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.