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