// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2019 Cyril Hrubis */ /* * Very simple uevent netlink socket test. * * We fork a child that listens for a kernel events while parents creates and * removes a tun network device which should produce two several add and remove * events. */ #include #include #include #include #include #include #include "tst_test.h" #include "uevent.h" #define TUN_PATH "/dev/net/tun" static void generate_tun_uevents(void) { int fd = SAFE_OPEN(TUN_PATH, O_RDWR); struct ifreq ifr = { .ifr_flags = IFF_TUN, .ifr_name = "ltp-tun0", }; SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr); SAFE_IOCTL(fd, TUNSETPERSIST, 0); SAFE_CLOSE(fd); } static void verify_uevent(void) { int pid, fd; struct uevent_desc add = { .msg = "add@/devices/virtual/net/ltp-tun0", .value_cnt = 4, .values = (const char*[]) { "ACTION=add", "DEVPATH=/devices/virtual/net/ltp-tun0", "SUBSYSTEM=net", "INTERFACE=ltp-tun0", } }; struct uevent_desc add_rx = { .msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-0", .value_cnt = 3, .values = (const char*[]) { "ACTION=add", "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0", "SUBSYSTEM=queues", } }; struct uevent_desc add_tx = { .msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-0", .value_cnt = 3, .values = (const char*[]) { "ACTION=add", "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0", "SUBSYSTEM=queues", } }; struct uevent_desc rem_rx = { .msg = "remove@/devices/virtual/net/ltp-tun0/queues/rx-0", .value_cnt = 3, .values = (const char*[]) { "ACTION=remove", "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0", "SUBSYSTEM=queues", } }; struct uevent_desc rem_tx = { .msg = "remove@/devices/virtual/net/ltp-tun0/queues/tx-0", .value_cnt = 3, .values = (const char*[]) { "ACTION=remove", "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0", "SUBSYSTEM=queues", } }; struct uevent_desc rem = { .msg = "remove@/devices/virtual/net/ltp-tun0", .value_cnt = 4, .values = (const char*[]) { "ACTION=remove", "DEVPATH=/devices/virtual/net/ltp-tun0", "SUBSYSTEM=net", "INTERFACE=ltp-tun0", } }; const struct uevent_desc *const uevents[] = { &add, &add_rx, &add_tx, &rem_rx, &rem_tx, &rem, NULL }; pid = SAFE_FORK(); if (!pid) { fd = open_uevent_netlink(); TST_CHECKPOINT_WAKE(0); wait_for_uevents(fd, uevents); exit(0); } TST_CHECKPOINT_WAIT(0); generate_tun_uevents(); wait_for_pid(pid); } static struct tst_test test = { .test_all = verify_uevent, .forks_child = 1, .needs_checkpoints = 1, .needs_drivers = (const char *const []) { "tun", NULL }, .needs_root = 1 };