[LTP] [PATCH v2 22/31] testcases: sysfs: Add sys_net03

Cyril Hrubis <[email protected]>
Newsgroups it.linux.lists.ltp
Message-ID <[email protected]>
A test for /sys/class/net/*/* files.

Similar to sys_net02 but checks bridge related files after briding a
virtual ethernet interface.

Signed-off-by: Cyril Hrubis <[email protected]>
---
 runtest/sysfs                                |   1 +
 testcases/kernel/sysfs/class/net/.gitignore  |   1 +
 testcases/kernel/sysfs/class/net/sys_net03.c | 144 +++++++++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 testcases/kernel/sysfs/class/net/sys_net03.c

diff --git a/runtest/sysfs b/runtest/sysfs
index fee8a0b2b..b2cc0005c 100644
--- a/runtest/sysfs
+++ b/runtest/sysfs
@@ -17,3 +17,4 @@ sys_rtc01 sys_rtc01
 sys_thermal01 sys_thermal01
 sys_net01 sys_net01
 sys_net02 sys_net02
+sys_net03 sys_net03
diff --git a/testcases/kernel/sysfs/class/net/.gitignore b/testcases/kernel/sysfs/class/net/.gitignore
index b70d02158..8c3782a3b 100644
--- a/testcases/kernel/sysfs/class/net/.gitignore
+++ b/testcases/kernel/sysfs/class/net/.gitignore
@@ -1,2 +1,3 @@
 /sys_net01
 /sys_net02
+/sys_net03
diff --git a/testcases/kernel/sysfs/class/net/sys_net03.c b/testcases/kernel/sysfs/class/net/sys_net03.c
new file mode 100644
index 000000000..fcc5c5451
--- /dev/null
+++ b/testcases/kernel/sysfs/class/net/sys_net03.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Cyril Hrubis <[email protected]>
+ */
+
+/*\
+ * Verifies that bridge port sysfs attributes correctly appear, hold sane
+ * values, and disappear again as a network device is enslaved to and
+ * released from a bridge.
+ *
+ * The test creates a bridge and a veth pair, then:
+ *
+ * - verifies /sys/class/net/<bridge>/brif/ is empty and
+ *   /sys/class/net/<port>/brport does not exist before enslaving
+ * - enslaves one end of the veth pair to the bridge
+ * - verifies /sys/class/net/<bridge>/brif/<port> appears and
+ *   /sys/class/net/<port>/brport/{state,priority,path_cost} hold sane values
+ * - verifies /sys/class/net/<bridge>/bridge/{stp_state,forward_delay} hold
+ *   sane values
+ * - releases the port from the bridge
+ * - verifies /sys/class/net/<bridge>/brif/ is empty and
+ *   /sys/class/net/<port>/brport does not exist again
+ *
+ * This needs root to create the bridge and veth devices.
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include "tst_test.h"
+#include "tst_netdevice.h"
+#include "tst_sysfs_assert.h"
+
+#define BRNAME "ltp_br0"
+#define IFNAME1 "ltp_vethb1"
+#define IFNAME2 "ltp_vethb2"
+
+#define BR_PATH "/sys/class/net/" BRNAME
+#define PORT_PATH "/sys/class/net/" IFNAME1
+
+static int bridge_created;
+static int veth_created;
+
+static int count_dir_entries(const char *path)
+{
+	DIR *d;
+	struct dirent *ent;
+	int count = 0;
+
+	d = SAFE_OPENDIR(path);
+
+	while ((ent = SAFE_READDIR(d))) {
+		if (ent->d_name[0] == '.')
+			continue;
+
+		count++;
+	}
+
+	SAFE_CLOSEDIR(d);
+
+	return count;
+}
+
+static void setup(void)
+{
+	NETDEV_ADD_DEVICE(BRNAME, "bridge");
+	bridge_created = 1;
+
+	CREATE_VETH_PAIR(IFNAME1, IFNAME2);
+	veth_created = 1;
+
+	NETDEV_SET_STATE(BRNAME, 1);
+	NETDEV_SET_STATE(IFNAME1, 1);
+	NETDEV_SET_STATE(IFNAME2, 1);
+}
+
+static void check_not_enslaved(const char *desc)
+{
+	int nports = count_dir_entries(BR_PATH "/brif");
+
+	tst_res(TINFO, "%s", desc);
+
+	TST_EXP_EQ_LI(nports, 0);
+
+	if (access(PORT_PATH "/brport", F_OK))
+		tst_res(TPASS, PORT_PATH "/brport does not exist");
+	else
+		tst_res(TFAIL, PORT_PATH "/brport unexpectedly exists");
+}
+
+static void check_enslaved(void)
+{
+	int nports = count_dir_entries(BR_PATH "/brif");
+
+	tst_res(TINFO, "port enslaved to bridge");
+
+	TST_EXP_EQ_LI(nports, 1);
+
+	if (!access(BR_PATH "/brif/" IFNAME1, F_OK))
+		tst_res(TPASS, BR_PATH "/brif/" IFNAME1 " exists");
+	else
+		tst_res(TFAIL, BR_PATH "/brif/" IFNAME1 " does not exist");
+
+	TST_SYSFS_ASSERT_RANGELL(0, 4, PORT_PATH "/brport/state");
+	TST_SYSFS_ASSERT_RANGELL(0, 255, PORT_PATH "/brport/priority");
+	TST_SYSFS_ASSERT_RANGELL(1, LONG_MAX, PORT_PATH "/brport/path_cost");
+
+	TST_SYSFS_ASSERT_RANGELL(0, 2, BR_PATH "/bridge/stp_state");
+	TST_SYSFS_ASSERT_RANGELL(1, LONG_MAX, BR_PATH "/bridge/forward_delay");
+}
+
+static void run(void)
+{
+	check_not_enslaved("before enslaving");
+
+	NETDEV_SET_MASTER(IFNAME1, BRNAME);
+	check_enslaved();
+
+	NETDEV_SET_MASTER(IFNAME1, NULL);
+	check_not_enslaved("after releasing");
+}
+
+static void cleanup(void)
+{
+	if (veth_created)
+		NETDEV_REMOVE_DEVICE(IFNAME1);
+
+	if (bridge_created)
+		NETDEV_REMOVE_DEVICE(BRNAME);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.needs_kconfigs = (const char *const[]){
+		"CONFIG_VETH",
+		"CONFIG_BRIDGE",
+		NULL
+	},
+};
-- 
2.54.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.