[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250912195339.20635-11-yana2bsh@gmail.com>
Date: Fri, 12 Sep 2025 22:53:33 +0300
From: Yana Bashlykova <yana2bsh@...il.com>
To: "David S. Miller" <davem@...emloft.net>
Cc: Yana Bashlykova <yana2bsh@...il.com>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Shuah Khan <shuah@...nel.org>,
Paul Walmsley <paul.walmsley@...ive.com>,
Palmer Dabbelt <palmer@...belt.com>,
Albert Ou <aou@...s.berkeley.edu>,
Nathan Chancellor <nathan@...nel.org>,
Nick Desaulniers <ndesaulniers@...gle.com>,
Tom Rix <trix@...hat.com>,
linux-kernel@...r.kernel.org,
netdev@...r.kernel.org,
linux-kselftest@...r.kernel.org,
linux-riscv@...ts.infradead.org,
bpf@...r.kernel.org,
llvm@...ts.linux.dev,
lvc-project@...uxtesting.org
Subject: [PATCH 6.1 10/15] selftests: net: genetlink: add packet capture test infrastructure
Add test cases for monitoring Netlink traffic during test execution
Require CONFIG_NLMON.
Signed-off-by: Yana Bashlykova <yana2bsh@...il.com>
---
tools/testing/selftests/net/Makefile | 6 +
tools/testing/selftests/net/genetlink.c | 234 ++++++++++++++++++++++++
2 files changed, 240 insertions(+)
create mode 100644 tools/testing/selftests/net/genetlink.c
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 69c58362c0ed..0c325ccc5f03 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -71,6 +71,7 @@ TEST_GEN_FILES += bind_bhash
TEST_GEN_PROGS += sk_bind_sendto_listen
TEST_GEN_PROGS += sk_connect_zero_addr
TEST_PROGS += test_ingress_egress_chaining.sh
+TEST_GEN_PROGS += genetlink
TEST_FILES := settings
@@ -82,3 +83,8 @@ $(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
$(OUTPUT)/tcp_mmap: LDLIBS += -lpthread
$(OUTPUT)/tcp_inq: LDLIBS += -lpthread
$(OUTPUT)/bind_bhash: LDLIBS += -lpthread
+
+$(OUTPUT)/genetlink: LDLIBS += -lnl-3 -lnl-genl-3
+$(OUTPUT)/genetlink: CFLAGS += $(shell pkg-config --cflags libnl-3.0 libnl-genl-3.0)
+
+EXTRA_CLEAN := $(SCRATCH_DIR) $(OUTPUT)/genetlink.pcap
diff --git a/tools/testing/selftests/net/genetlink.c b/tools/testing/selftests/net/genetlink.c
new file mode 100644
index 000000000000..5be9ca68accd
--- /dev/null
+++ b/tools/testing/selftests/net/genetlink.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic Netlink and Netlink test cases
+ *
+ * This test suite validates various aspects of Generic Netlink and Netlink communication
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/mngt.h>
+#include <linux/genetlink.h>
+
+#include "../kselftest_harness.h"
+
+#define MY_GENL_FAMILY_NAME "TEST_GENL"
+#define MY_GENL_CMD_UNSPEC 0
+#define MY_GENL_CMD_ECHO 1
+#define MY_GENL_CMD_SET_VALUE 2
+#define MY_GENL_CMD_GET_VALUE 3
+#define MY_GENL_CMD_EVENT 4
+#define MY_GENL_CMD_NO_ATTRS 5
+
+#define MY_GENL_SMALL_CMD_GET 0
+
+#define MY_GENL_ATTR_UNSPEC 0
+#define MY_GENL_ATTR_DATA 1
+#define MY_GENL_ATTR_VALUE 2
+#define MY_GENL_ATTR_PATH 3
+#define MY_GENL_ATTR_NESTED 4
+#define MY_GENL_ATTR_MAX 4
+
+#define THIRD_GENL_FAMILY_NAME "THIRD_GENL"
+
+#define THIRD_GENL_CMD_ECHO 1
+
+#define THIRD_GENL_ATTR_UNSPEC 0
+#define THIRD_GENL_ATTR_DATA 1
+#define THIRD_GENL_ATTR_FLAG 2
+#define THIRD_GENL_ATTR_MAX 2
+
+#define PATH_GENL_TEST_NUM "/sys/kernel/genl_test/value"
+#define PATH_GENL_TEST_MES "/sys/kernel/genl_test/message"
+#define PATH_GENL_TEST_DEV "/sys/kernel/genl_test/some_info"
+#define PATH_PARALLEL_GENL_MES "/sys/kernel/parallel_genl/message"
+#define PATH_THIRD_GENL_MES "/sys/kernel/third_genl/message"
+
+#define MY_MCGRP_NAME "MY_MCGRP_GENL"
+
+#define GENL_CTRL "nlctrl"
+#define CTRL_ATTR_POLICY_MAX (__CTRL_ATTR_POLICY_DUMP_MAX - 1)
+
+#define PARALLEL_GENL_FAMILY_NAME "PARALLEL_GENL"
+#define PARALLEL_GENL_ATTR_UNSPEC 0
+#define PARALLEL_GENL_CMD_SEND 1
+#define PARALLEL_GENL_CMD_DUMP_INFO 2
+#define PARALLEL_GENL_CMD_SET_VALUE 3
+#define PARALLEL_GENL_CMD_GET_VALUE 4
+
+#define PARALLEL_GENL_ATTR_DATA 1
+#define PARALLEL_GENL_ATTR_BINARY 2
+#define PARALLEL_GENL_ATTR_NAME 3
+#define PARALLEL_GENL_ATTR_DESC 4
+#define PARALLEL_GENL_ATTR_FLAG_NONBLOCK 9
+#define PARALLEL_GENL_ATTR_FLAG_BLOCK 10
+#define PARALLEL_GENL_ATTR_PATH 12
+#define PARALLEL_GENL_ATTR_MAX 12
+
+#define LARGE_GENL_FAMILY_NAME "LARGE_GENL"
+
+/*
+ * Test cases
+ */
+
+/**
+ * TEST(capture_start) - Starts Netlink traffic capture using nlmon interface
+ *
+ * Creates a virtual nlmon interface, enables it and starts packet capture
+ * with tcpdump. Captured packets are saved to 'genetlink.pcap' file.
+ *
+ * Note:
+ * - Requires root privileges
+ * - Creates temporary interface 'nlmon0'
+ * - Runs tcpdump in background
+ * - Adds small delay to ensure capture starts
+ */
+
+TEST(capture_start)
+{
+ printf("Running Test: starting Netlink traffic capture...\n");
+
+ // Only root can monitor Netlink traffic
+ if (geteuid()) {
+ SKIP(return, "test requires root");
+ return;
+ }
+
+ char command[256];
+ int result;
+
+ snprintf(command, sizeof(command), "ip link add nlmon0 type nlmon");
+ result = system(command);
+ ASSERT_EQ(WEXITSTATUS(result), 0);
+ if (result == -1) {
+ perror("system");
+ return;
+ }
+
+ snprintf(command, sizeof(command), "ip link set nlmon0 up");
+ result = system(command);
+ ASSERT_EQ(WEXITSTATUS(result), 0);
+ if (result == -1) {
+ perror("system");
+ return;
+ }
+
+ snprintf(command, sizeof(command),
+ "tcpdump -i nlmon0 -w genetlink.pcap &");
+ result = system(command);
+ ASSERT_EQ(WEXITSTATUS(result), 0);
+ if (result == -1) {
+ perror("system");
+ return;
+ }
+
+ printf("nlmon is up. Starting netlink process...\n");
+
+ sleep(2);
+
+ printf("Starting Netlink tests...\n");
+}
+
+/**
+ * TEST(capture_end) - Terminates Netlink traffic monitoring session
+ *
+ * Performs controlled shutdown of nlmon capture interface by:
+ * 1. Stopping tcpdump capture process
+ * 2. Bringing down nlmon interface
+ * 3. Deleting nlmon interface
+ *
+ * Test Procedure:
+ * 1. Privilege Check:
+ * - Verifies root privileges (required for nlmon operations)
+ * - Gracefully skips if not root
+ *
+ * 2. Capture Termination:
+ * - Stops tcpdump process (2-second delay for cleanup)
+ * - Brings nlmon0 interface down
+ * - Deletes nlmon0 interface
+ * - Validates each operation succeeds
+ *
+ * 3. Cleanup Verification:
+ * - Checks system command exit statuses
+ * - Provides detailed error reporting
+ *
+ * Key Validations:
+ * - Proper termination of monitoring session
+ * - Correct interface teardown
+ * - Root privilege enforcement
+ * - System command error handling
+ *
+ * Expected Behavior:
+ * - tcpdump process should terminate successfully
+ * - nlmon0 interface should deactivate cleanly
+ * - Interface should be removable
+ * - Non-root execution should skip gracefully
+ *
+ * Security Considerations:
+ * - Requires root for network interface control
+ * - Ensures complete capture session cleanup
+ * - Verifies proper resource release
+ *
+ * Note:
+ * - Should be paired with capture_start test
+ * - Includes 2-second delay for process stabilization
+ * - Provides status feedback through printf
+ */
+
+TEST(capture_end)
+{
+ printf("Running Test: stopping Netlink traffic capture...\n");
+
+ // Only root can monitor Netlink traffic
+ if (geteuid()) {
+ SKIP(return, "test requires root");
+ return;
+ }
+
+ char command[256];
+ int result;
+
+ sleep(2);
+
+ snprintf(command, sizeof(command), "pkill tcpdump");
+ result = system(command);
+ ASSERT_EQ(WEXITSTATUS(result), 0);
+ if (result == -1) {
+ perror("system");
+ return;
+ }
+
+ snprintf(command, sizeof(command), "ip link set nlmon0 down");
+ result = system(command);
+ ASSERT_EQ(WEXITSTATUS(result), 0);
+ if (result == -1) {
+ perror("system");
+ return;
+ }
+
+ snprintf(command, sizeof(command), "ip link delete nlmon0 type nlmon");
+ result = system(command);
+ ASSERT_EQ(WEXITSTATUS(result), 0);
+ if (result == -1) {
+ perror("system");
+ return;
+ }
+
+ printf("The capturing is over\n");
+}
+
+TEST_HARNESS_MAIN
--
2.34.1
Powered by blists - more mailing lists