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