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