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_test.h"
22
23 #include "uevent.h"
24
25 #define TUN_PATH "/dev/net/tun"
26
generate_tun_uevents(void)27 static void generate_tun_uevents(void)
28 {
29 int fd = SAFE_OPEN(TUN_PATH, O_RDWR);
30
31 struct ifreq ifr = {
32 .ifr_flags = IFF_TUN,
33 .ifr_name = "ltp-tun0",
34 };
35
36 SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr);
37
38 SAFE_IOCTL(fd, TUNSETPERSIST, 0);
39
40 SAFE_CLOSE(fd);
41 }
42
verify_uevent(void)43 static void verify_uevent(void)
44 {
45 int pid, fd;
46
47 struct uevent_desc add = {
48 .msg = "add@/devices/virtual/net/ltp-tun0",
49 .value_cnt = 4,
50 .values = (const char*[]) {
51 "ACTION=add",
52 "DEVPATH=/devices/virtual/net/ltp-tun0",
53 "SUBSYSTEM=net",
54 "INTERFACE=ltp-tun0",
55 }
56 };
57
58 struct uevent_desc add_rx = {
59 .msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-0",
60 .value_cnt = 3,
61 .values = (const char*[]) {
62 "ACTION=add",
63 "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0",
64 "SUBSYSTEM=queues",
65 }
66 };
67
68 struct uevent_desc add_tx = {
69 .msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-0",
70 .value_cnt = 3,
71 .values = (const char*[]) {
72 "ACTION=add",
73 "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0",
74 "SUBSYSTEM=queues",
75 }
76 };
77
78 struct uevent_desc rem_rx = {
79 .msg = "remove@/devices/virtual/net/ltp-tun0/queues/rx-0",
80 .value_cnt = 3,
81 .values = (const char*[]) {
82 "ACTION=remove",
83 "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0",
84 "SUBSYSTEM=queues",
85 }
86 };
87
88 struct uevent_desc rem_tx = {
89 .msg = "remove@/devices/virtual/net/ltp-tun0/queues/tx-0",
90 .value_cnt = 3,
91 .values = (const char*[]) {
92 "ACTION=remove",
93 "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0",
94 "SUBSYSTEM=queues",
95 }
96 };
97
98 struct uevent_desc rem = {
99 .msg = "remove@/devices/virtual/net/ltp-tun0",
100 .value_cnt = 4,
101 .values = (const char*[]) {
102 "ACTION=remove",
103 "DEVPATH=/devices/virtual/net/ltp-tun0",
104 "SUBSYSTEM=net",
105 "INTERFACE=ltp-tun0",
106 }
107 };
108
109 const struct uevent_desc *const uevents[] = {
110 &add,
111 &add_rx,
112 &add_tx,
113 &rem_rx,
114 &rem_tx,
115 &rem,
116 NULL
117 };
118
119 pid = SAFE_FORK();
120 if (!pid) {
121 fd = open_uevent_netlink();
122 TST_CHECKPOINT_WAKE(0);
123 wait_for_uevents(fd, uevents);
124 exit(0);
125 }
126
127 TST_CHECKPOINT_WAIT(0);
128
129 generate_tun_uevents();
130
131 wait_for_pid(pid);
132 }
133
134 static struct tst_test test = {
135 .test_all = verify_uevent,
136 .forks_child = 1,
137 .needs_checkpoints = 1,
138 .needs_drivers = (const char *const []) {
139 "tun",
140 NULL
141 },
142 .needs_root = 1
143 };
144