]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
aaa5b4ce YW |
2 | |
3 | #include <stdbool.h> | |
4 | #include <unistd.h> | |
5 | ||
6 | #include "sd-device.h" | |
7 | #include "sd-event.h" | |
8 | ||
9 | #include "device-monitor-private.h" | |
10 | #include "device-private.h" | |
11 | #include "device-util.h" | |
12 | #include "macro.h" | |
81649574 | 13 | #include "path-util.h" |
42672c80 | 14 | #include "stat-util.h" |
aaa5b4ce YW |
15 | #include "string-util.h" |
16 | #include "tests.h" | |
17 | #include "util.h" | |
18 | #include "virt.h" | |
19 | ||
20 | static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) { | |
21 | const char *s, *syspath = userdata; | |
22 | ||
23 | assert_se(sd_device_get_syspath(d, &s) >= 0); | |
24 | assert_se(streq(s, syspath)); | |
25 | ||
aa6c83e6 | 26 | return sd_event_exit(sd_device_monitor_get_event(m), 100); |
aaa5b4ce YW |
27 | } |
28 | ||
42672c80 | 29 | static void test_receive_device_fail(void) { |
aaa5b4ce | 30 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; |
4fe0caad YW |
31 | _cleanup_(sd_device_unrefp) sd_device *loopback = NULL; |
32 | const char *syspath; | |
aaa5b4ce | 33 | |
4fe0caad YW |
34 | log_info("/* %s */", __func__); |
35 | ||
36 | /* Try to send device with invalid action and without seqnum. */ | |
37 | assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); | |
38 | assert_se(device_add_property(loopback, "ACTION", "hoge") >= 0); | |
39 | ||
40 | assert_se(sd_device_get_syspath(loopback, &syspath) >= 0); | |
41 | ||
42 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 43 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
4fe0caad | 44 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
4fe0caad YW |
45 | |
46 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 47 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
4fe0caad YW |
48 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
49 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); | |
4fe0caad | 50 | |
42672c80 | 51 | assert_se(device_monitor_send_device(monitor_server, monitor_client, loopback) >= 0); |
4fe0caad | 52 | assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0); |
4fe0caad YW |
53 | } |
54 | ||
55 | static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) { | |
56 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; | |
57 | const char *syspath, *subsystem, *tag, *devtype = NULL; | |
58 | ||
a5a59a24 YW |
59 | log_device_info(device, "/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__, |
60 | true_false(subsystem_filter), true_false(tag_filter), true_false(use_bpf)); | |
aaa5b4ce | 61 | |
a5a59a24 | 62 | assert_se(sd_device_get_syspath(device, &syspath) >= 0); |
aaa5b4ce YW |
63 | |
64 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 65 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
deb2b734 | 66 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
aaa5b4ce YW |
67 | |
68 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 69 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
aaa5b4ce | 70 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
deb2b734 | 71 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); |
aaa5b4ce YW |
72 | |
73 | if (subsystem_filter) { | |
a5a59a24 YW |
74 | assert_se(sd_device_get_subsystem(device, &subsystem) >= 0); |
75 | (void) sd_device_get_devtype(device, &devtype); | |
76 | assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, devtype) >= 0); | |
aaa5b4ce YW |
77 | } |
78 | ||
79 | if (tag_filter) | |
a5a59a24 | 80 | FOREACH_DEVICE_TAG(device, tag) |
aaa5b4ce YW |
81 | assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, tag) >= 0); |
82 | ||
83 | if ((subsystem_filter || tag_filter) && use_bpf) | |
84 | assert_se(sd_device_monitor_filter_update(monitor_client) >= 0); | |
85 | ||
4fe0caad | 86 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); |
aa6c83e6 | 87 | assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); |
aaa5b4ce YW |
88 | } |
89 | ||
a5a59a24 | 90 | static void test_subsystem_filter(sd_device *device) { |
aaa5b4ce YW |
91 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; |
92 | _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; | |
def36693 | 93 | const char *syspath, *subsystem; |
aaa5b4ce YW |
94 | sd_device *d; |
95 | ||
def36693 | 96 | log_device_info(device, "/* %s */", __func__); |
aaa5b4ce | 97 | |
a5a59a24 YW |
98 | assert_se(sd_device_get_syspath(device, &syspath) >= 0); |
99 | assert_se(sd_device_get_subsystem(device, &subsystem) >= 0); | |
aaa5b4ce YW |
100 | |
101 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 102 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
deb2b734 | 103 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
aaa5b4ce YW |
104 | |
105 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 106 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
aaa5b4ce YW |
107 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
108 | assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0); | |
deb2b734 | 109 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); |
aaa5b4ce YW |
110 | |
111 | assert_se(sd_device_enumerator_new(&e) >= 0); | |
112 | assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, false) >= 0); | |
113 | FOREACH_DEVICE(e, d) { | |
def36693 YW |
114 | const char *p, *s; |
115 | ||
aaa5b4ce YW |
116 | assert_se(sd_device_get_syspath(d, &p) >= 0); |
117 | assert_se(sd_device_get_subsystem(d, &s) >= 0); | |
118 | ||
46c1223b YW |
119 | assert_se(device_add_property(d, "ACTION", "add") >= 0); |
120 | assert_se(device_add_property(d, "SEQNUM", "10") >= 0); | |
121 | ||
def36693 YW |
122 | log_device_debug(d, "Sending device subsystem:%s syspath:%s", s, p); |
123 | assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0); | |
124 | } | |
125 | ||
126 | log_device_info(device, "Sending device subsystem:%s syspath:%s", subsystem, syspath); | |
127 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); | |
128 | assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); | |
129 | } | |
130 | ||
131 | static void test_tag_filter(sd_device *device) { | |
132 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; | |
133 | _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; | |
134 | const char *syspath; | |
135 | sd_device *d; | |
136 | ||
137 | log_device_info(device, "/* %s */", __func__); | |
138 | ||
139 | assert_se(sd_device_get_syspath(device, &syspath) >= 0); | |
140 | ||
141 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 142 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
def36693 | 143 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
def36693 YW |
144 | |
145 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 146 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
def36693 YW |
147 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
148 | assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, "TEST_SD_DEVICE_MONITOR") >= 0); | |
149 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); | |
def36693 YW |
150 | |
151 | assert_se(sd_device_enumerator_new(&e) >= 0); | |
152 | FOREACH_DEVICE(e, d) { | |
153 | const char *p; | |
154 | ||
155 | assert_se(sd_device_get_syspath(d, &p) >= 0); | |
156 | ||
46c1223b YW |
157 | assert_se(device_add_property(d, "ACTION", "add") >= 0); |
158 | assert_se(device_add_property(d, "SEQNUM", "10") >= 0); | |
159 | ||
def36693 | 160 | log_device_debug(d, "Sending device syspath:%s", p); |
aaa5b4ce YW |
161 | assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0); |
162 | } | |
163 | ||
def36693 | 164 | log_device_info(device, "Sending device syspath:%s", syspath); |
a5a59a24 | 165 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); |
aa6c83e6 | 166 | assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); |
def36693 YW |
167 | |
168 | } | |
169 | ||
170 | static void test_sysattr_filter(sd_device *device, const char *sysattr) { | |
171 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; | |
172 | _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; | |
81649574 | 173 | const char *syspath, *sysattr_value; |
def36693 YW |
174 | sd_device *d; |
175 | ||
176 | log_device_info(device, "/* %s(%s) */", __func__, sysattr); | |
177 | ||
178 | assert_se(sd_device_get_syspath(device, &syspath) >= 0); | |
def36693 YW |
179 | assert_se(sd_device_get_sysattr_value(device, sysattr, &sysattr_value) >= 0); |
180 | ||
181 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 182 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
def36693 | 183 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
def36693 YW |
184 | |
185 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 186 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
def36693 | 187 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
def36693 YW |
188 | assert_se(sd_device_monitor_filter_add_match_sysattr(monitor_client, sysattr, sysattr_value, true) >= 0); |
189 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); | |
def36693 YW |
190 | |
191 | assert_se(sd_device_enumerator_new(&e) >= 0); | |
192 | assert_se(sd_device_enumerator_add_match_sysattr(e, sysattr, sysattr_value, false) >= 0); | |
193 | FOREACH_DEVICE(e, d) { | |
194 | const char *p; | |
195 | ||
196 | assert_se(sd_device_get_syspath(d, &p) >= 0); | |
197 | ||
46c1223b YW |
198 | assert_se(device_add_property(d, "ACTION", "add") >= 0); |
199 | assert_se(device_add_property(d, "SEQNUM", "10") >= 0); | |
200 | ||
def36693 YW |
201 | log_device_debug(d, "Sending device syspath:%s", p); |
202 | assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0); | |
81649574 YW |
203 | |
204 | /* The sysattr filter is not implemented in BPF yet. So, sending multiple devices may fills up | |
205 | * buffer and device_monitor_send_device() may return EAGAIN. Let's send one device here, | |
206 | * which should be filtered out by the receiver. */ | |
207 | break; | |
def36693 YW |
208 | } |
209 | ||
210 | log_device_info(device, "Sending device syspath:%s", syspath); | |
211 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); | |
212 | assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); | |
213 | ||
214 | } | |
215 | ||
216 | static void test_parent_filter(sd_device *device) { | |
217 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; | |
218 | _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; | |
81649574 | 219 | const char *syspath, *parent_syspath; |
def36693 YW |
220 | sd_device *parent, *d; |
221 | int r; | |
222 | ||
223 | log_device_info(device, "/* %s */", __func__); | |
224 | ||
225 | assert_se(sd_device_get_syspath(device, &syspath) >= 0); | |
def36693 YW |
226 | r = sd_device_get_parent(device, &parent); |
227 | if (r < 0) | |
228 | return (void) log_device_info(device, "Device does not have parent, skipping."); | |
81649574 | 229 | assert_se(sd_device_get_syspath(parent, &parent_syspath) >= 0); |
def36693 YW |
230 | |
231 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 232 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
def36693 | 233 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
def36693 YW |
234 | |
235 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 236 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
def36693 | 237 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
def36693 YW |
238 | assert_se(sd_device_monitor_filter_add_match_parent(monitor_client, parent, true) >= 0); |
239 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); | |
def36693 YW |
240 | |
241 | assert_se(sd_device_enumerator_new(&e) >= 0); | |
242 | FOREACH_DEVICE(e, d) { | |
243 | const char *p; | |
244 | ||
245 | assert_se(sd_device_get_syspath(d, &p) >= 0); | |
81649574 YW |
246 | if (path_startswith(p, parent_syspath)) |
247 | continue; | |
def36693 | 248 | |
46c1223b YW |
249 | assert_se(device_add_property(d, "ACTION", "add") >= 0); |
250 | assert_se(device_add_property(d, "SEQNUM", "10") >= 0); | |
251 | ||
def36693 YW |
252 | log_device_debug(d, "Sending device syspath:%s", p); |
253 | assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0); | |
81649574 YW |
254 | |
255 | /* The parent filter is not implemented in BPF yet. So, sending multiple devices may fills up | |
256 | * buffer and device_monitor_send_device() may return EAGAIN. Let's send one device here, | |
257 | * which should be filtered out by the receiver. */ | |
258 | break; | |
def36693 YW |
259 | } |
260 | ||
261 | log_device_info(device, "Sending device syspath:%s", syspath); | |
262 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); | |
263 | assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); | |
264 | ||
aa6c83e6 YW |
265 | } |
266 | ||
267 | static void test_sd_device_monitor_filter_remove(sd_device *device) { | |
268 | _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; | |
269 | const char *syspath; | |
270 | ||
271 | log_device_info(device, "/* %s */", __func__); | |
272 | ||
273 | assert_se(sd_device_get_syspath(device, &syspath) >= 0); | |
274 | ||
275 | assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 276 | assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0); |
aa6c83e6 | 277 | assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); |
aa6c83e6 YW |
278 | |
279 | assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); | |
cbdf6a1f | 280 | assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0); |
aa6c83e6 YW |
281 | assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); |
282 | assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); | |
aa6c83e6 YW |
283 | |
284 | assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, "hoge", NULL) >= 0); | |
285 | assert_se(sd_device_monitor_filter_update(monitor_client) >= 0); | |
286 | ||
287 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); | |
288 | assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0); | |
289 | ||
290 | assert_se(sd_device_monitor_filter_remove(monitor_client) >= 0); | |
291 | ||
292 | assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); | |
293 | assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); | |
aaa5b4ce YW |
294 | } |
295 | ||
296 | int main(int argc, char *argv[]) { | |
a5a59a24 | 297 | _cleanup_(sd_device_unrefp) sd_device *loopback = NULL, *sda = NULL; |
aaa5b4ce YW |
298 | int r; |
299 | ||
300 | test_setup_logging(LOG_INFO); | |
301 | ||
302 | if (getuid() != 0) | |
303 | return log_tests_skipped("not root"); | |
304 | ||
42672c80 | 305 | if (path_is_read_only_fs("/sys") > 0) |
4a55ce8f | 306 | return log_tests_skipped("Running in container"); |
42672c80 YW |
307 | |
308 | test_receive_device_fail(); | |
aaa5b4ce | 309 | |
4fe0caad YW |
310 | assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); |
311 | assert_se(device_add_property(loopback, "ACTION", "add") >= 0); | |
312 | assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0); | |
def36693 | 313 | assert_se(device_add_tag(loopback, "TEST_SD_DEVICE_MONITOR", true) >= 0); |
4fe0caad YW |
314 | |
315 | test_send_receive_one(loopback, false, false, false); | |
316 | test_send_receive_one(loopback, true, false, false); | |
317 | test_send_receive_one(loopback, false, true, false); | |
318 | test_send_receive_one(loopback, true, true, false); | |
319 | test_send_receive_one(loopback, true, false, true); | |
320 | test_send_receive_one(loopback, false, true, true); | |
321 | test_send_receive_one(loopback, true, true, true); | |
a5a59a24 YW |
322 | |
323 | test_subsystem_filter(loopback); | |
def36693 YW |
324 | test_tag_filter(loopback); |
325 | test_sysattr_filter(loopback, "ifindex"); | |
aa6c83e6 | 326 | test_sd_device_monitor_filter_remove(loopback); |
a5a59a24 YW |
327 | |
328 | r = sd_device_new_from_subsystem_sysname(&sda, "block", "sda"); | |
329 | if (r < 0) { | |
330 | log_info_errno(r, "Failed to create sd_device for sda, skipping remaining tests: %m"); | |
331 | return 0; | |
332 | } | |
333 | ||
334 | assert_se(device_add_property(sda, "ACTION", "change") >= 0); | |
335 | assert_se(device_add_property(sda, "SEQNUM", "11") >= 0); | |
aaa5b4ce | 336 | |
4fe0caad YW |
337 | test_send_receive_one(sda, false, false, false); |
338 | test_send_receive_one(sda, true, false, false); | |
339 | test_send_receive_one(sda, false, true, false); | |
340 | test_send_receive_one(sda, true, true, false); | |
341 | test_send_receive_one(sda, true, false, true); | |
342 | test_send_receive_one(sda, false, true, true); | |
343 | test_send_receive_one(sda, true, true, true); | |
aaa5b4ce | 344 | |
def36693 YW |
345 | test_parent_filter(sda); |
346 | ||
aaa5b4ce YW |
347 | return 0; |
348 | } |