xref: /aosp_15_r20/external/ltp/testcases/kernel/uevents/uevent02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2019 Cyril Hrubis <[email protected]>
4  * Copyright (c) Linux Test Project, 2019-2023
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Very simple uevent netlink socket test.
11  *
12  * We fork a child that listens for a kernel events while parents creates and
13  * removes a tun network device which should produce two several add and remove
14  * events.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/wait.h>
20 #include <sys/socket.h>
21 #include <linux/if.h>
22 #include <linux/if_tun.h>
23 
24 #include "tst_kconfig.h"
25 #include "tst_test.h"
26 
27 #include "uevent.h"
28 
29 #define TUN_PATH "/dev/net/tun"
30 #define MAX_UEVENTS 7
31 
32 static struct uevent_desc add = {
33 	.msg = "add@/devices/virtual/net/ltp-tun0",
34 	.value_cnt = 4,
35 	.values = (const char*[]) {
36 		"ACTION=add",
37 		"DEVPATH=/devices/virtual/net/ltp-tun0",
38 		"SUBSYSTEM=net",
39 		"INTERFACE=ltp-tun0",
40 	}
41 };
42 
43 static struct uevent_desc add_rx = {
44 	.msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-0",
45 	.value_cnt = 3,
46 	.values = (const char*[]) {
47 		"ACTION=add",
48 		"DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0",
49 		"SUBSYSTEM=queues",
50 	}
51 };
52 
53 static struct uevent_desc add_tx = {
54 	.msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-0",
55 	.value_cnt = 3,
56 	.values = (const char*[]) {
57 		"ACTION=add",
58 		"DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0",
59 		"SUBSYSTEM=queues",
60 	}
61 };
62 
63 static struct uevent_desc rem_rx = {
64 	.msg = "remove@/devices/virtual/net/ltp-tun0/queues/rx-0",
65 	.value_cnt = 3,
66 	.values = (const char*[]) {
67 		"ACTION=remove",
68 		"DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0",
69 		"SUBSYSTEM=queues",
70 	}
71 };
72 
73 static struct uevent_desc rem_tx = {
74 	.msg = "remove@/devices/virtual/net/ltp-tun0/queues/tx-0",
75 	.value_cnt = 3,
76 	.values = (const char*[]) {
77 		"ACTION=remove",
78 		"DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0",
79 		"SUBSYSTEM=queues",
80 	}
81 };
82 
83 static struct uevent_desc rem = {
84 	.msg = "remove@/devices/virtual/net/ltp-tun0",
85 	.value_cnt = 4,
86 	.values = (const char*[]) {
87 		"ACTION=remove",
88 		"DEVPATH=/devices/virtual/net/ltp-tun0",
89 		"SUBSYSTEM=net",
90 		"INTERFACE=ltp-tun0",
91 	}
92 };
93 static const struct uevent_desc *uevents[MAX_UEVENTS];
94 
generate_tun_uevents(void)95 static void generate_tun_uevents(void)
96 {
97 	int fd = SAFE_OPEN(TUN_PATH, O_RDWR);
98 
99 	struct ifreq ifr = {
100 		.ifr_flags = IFF_TUN,
101 		.ifr_name = "ltp-tun0",
102 	};
103 
104 	SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr);
105 
106 	SAFE_IOCTL(fd, TUNSETPERSIST, 0);
107 
108 	SAFE_CLOSE(fd);
109 }
110 
verify_uevent(void)111 static void verify_uevent(void)
112 {
113 	int pid, fd;
114 
115 	pid = SAFE_FORK();
116 	if (!pid) {
117 		fd = open_uevent_netlink();
118 		TST_CHECKPOINT_WAKE(0);
119 		wait_for_uevents(fd, uevents);
120 		exit(0);
121 	}
122 
123 	TST_CHECKPOINT_WAIT(0);
124 
125 	generate_tun_uevents();
126 
127 	wait_for_pid(pid);
128 }
129 
setup(void)130 static void setup(void)
131 {
132 	struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_RPS");
133 	int i = 0;
134 
135 	tst_kconfig_read(&kconfig, 1);
136 
137 	uevents[i++] = &add;
138 	if (kconfig.choice == 'y')
139 		uevents[i++] = &add_rx;
140 	uevents[i++] = &add_tx;
141 	if (kconfig.choice == 'y')
142 		uevents[i++] = &rem_rx;
143 	uevents[i++] = &rem_tx;
144 	uevents[i++] = &rem;
145 	uevents[i++] = NULL;
146 }
147 
148 static struct tst_test test = {
149 	.setup = setup,
150 	.test_all = verify_uevent,
151 	.forks_child = 1,
152 	.needs_checkpoints = 1,
153 	.needs_drivers = (const char *const []) {
154 		"tun",
155 		NULL
156 	},
157 	.needs_root = 1
158 };
159