1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/* 7f08c3bdfSopenharmony_ci * Very simple uevent netlink socket test. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * We fork a child that listens for a kernel events while parents creates and 10f08c3bdfSopenharmony_ci * removes a tun network device which should produce two several add and remove 11f08c3bdfSopenharmony_ci * events. 12f08c3bdfSopenharmony_ci */ 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include <stdio.h> 15f08c3bdfSopenharmony_ci#include <stdlib.h> 16f08c3bdfSopenharmony_ci#include <sys/wait.h> 17f08c3bdfSopenharmony_ci#include <sys/socket.h> 18f08c3bdfSopenharmony_ci#include <linux/if.h> 19f08c3bdfSopenharmony_ci#include <linux/if_tun.h> 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#include "tst_kconfig.h" 22f08c3bdfSopenharmony_ci#include "tst_test.h" 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_ci#include "uevent.h" 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#define TUN_PATH "/dev/net/tun" 27f08c3bdfSopenharmony_ci#define CONFIG_RPS "CONFIG_RPS" 28f08c3bdfSopenharmony_ci#define MAX_UEVENTS 7 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic struct uevent_desc add = { 31f08c3bdfSopenharmony_ci .msg = "add@/devices/virtual/net/ltp-tun0", 32f08c3bdfSopenharmony_ci .value_cnt = 4, 33f08c3bdfSopenharmony_ci .values = (const char*[]) { 34f08c3bdfSopenharmony_ci "ACTION=add", 35f08c3bdfSopenharmony_ci "DEVPATH=/devices/virtual/net/ltp-tun0", 36f08c3bdfSopenharmony_ci "SUBSYSTEM=net", 37f08c3bdfSopenharmony_ci "INTERFACE=ltp-tun0", 38f08c3bdfSopenharmony_ci } 39f08c3bdfSopenharmony_ci}; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_cistatic struct uevent_desc add_rx = { 42f08c3bdfSopenharmony_ci .msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-0", 43f08c3bdfSopenharmony_ci .value_cnt = 3, 44f08c3bdfSopenharmony_ci .values = (const char*[]) { 45f08c3bdfSopenharmony_ci "ACTION=add", 46f08c3bdfSopenharmony_ci "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0", 47f08c3bdfSopenharmony_ci "SUBSYSTEM=queues", 48f08c3bdfSopenharmony_ci } 49f08c3bdfSopenharmony_ci}; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistatic struct uevent_desc add_tx = { 52f08c3bdfSopenharmony_ci .msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-0", 53f08c3bdfSopenharmony_ci .value_cnt = 3, 54f08c3bdfSopenharmony_ci .values = (const char*[]) { 55f08c3bdfSopenharmony_ci "ACTION=add", 56f08c3bdfSopenharmony_ci "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0", 57f08c3bdfSopenharmony_ci "SUBSYSTEM=queues", 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci}; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic struct uevent_desc rem_rx = { 62f08c3bdfSopenharmony_ci .msg = "remove@/devices/virtual/net/ltp-tun0/queues/rx-0", 63f08c3bdfSopenharmony_ci .value_cnt = 3, 64f08c3bdfSopenharmony_ci .values = (const char*[]) { 65f08c3bdfSopenharmony_ci "ACTION=remove", 66f08c3bdfSopenharmony_ci "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0", 67f08c3bdfSopenharmony_ci "SUBSYSTEM=queues", 68f08c3bdfSopenharmony_ci } 69f08c3bdfSopenharmony_ci}; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistatic struct uevent_desc rem_tx = { 72f08c3bdfSopenharmony_ci .msg = "remove@/devices/virtual/net/ltp-tun0/queues/tx-0", 73f08c3bdfSopenharmony_ci .value_cnt = 3, 74f08c3bdfSopenharmony_ci .values = (const char*[]) { 75f08c3bdfSopenharmony_ci "ACTION=remove", 76f08c3bdfSopenharmony_ci "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0", 77f08c3bdfSopenharmony_ci "SUBSYSTEM=queues", 78f08c3bdfSopenharmony_ci } 79f08c3bdfSopenharmony_ci}; 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_cistatic struct uevent_desc rem = { 82f08c3bdfSopenharmony_ci .msg = "remove@/devices/virtual/net/ltp-tun0", 83f08c3bdfSopenharmony_ci .value_cnt = 4, 84f08c3bdfSopenharmony_ci .values = (const char*[]) { 85f08c3bdfSopenharmony_ci "ACTION=remove", 86f08c3bdfSopenharmony_ci "DEVPATH=/devices/virtual/net/ltp-tun0", 87f08c3bdfSopenharmony_ci "SUBSYSTEM=net", 88f08c3bdfSopenharmony_ci "INTERFACE=ltp-tun0", 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci}; 91f08c3bdfSopenharmony_cistatic const struct uevent_desc *uevents[MAX_UEVENTS]; 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_cistatic void generate_tun_uevents(void) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci int fd = SAFE_OPEN(TUN_PATH, O_RDWR); 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci struct ifreq ifr = { 98f08c3bdfSopenharmony_ci .ifr_flags = IFF_TUN, 99f08c3bdfSopenharmony_ci .ifr_name = "ltp-tun0", 100f08c3bdfSopenharmony_ci }; 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr); 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci SAFE_IOCTL(fd, TUNSETPERSIST, 0); 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 107f08c3bdfSopenharmony_ci} 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_cistatic void verify_uevent(void) 110f08c3bdfSopenharmony_ci{ 111f08c3bdfSopenharmony_ci int pid, fd; 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 114f08c3bdfSopenharmony_ci if (!pid) { 115f08c3bdfSopenharmony_ci fd = open_uevent_netlink(); 116f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 117f08c3bdfSopenharmony_ci wait_for_uevents(fd, uevents); 118f08c3bdfSopenharmony_ci exit(0); 119f08c3bdfSopenharmony_ci } 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(0); 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci generate_tun_uevents(); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci wait_for_pid(pid); 126f08c3bdfSopenharmony_ci} 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_cistatic void setup(void) 129f08c3bdfSopenharmony_ci{ 130f08c3bdfSopenharmony_ci struct tst_kconfig_var kconfig = { 131f08c3bdfSopenharmony_ci .id = CONFIG_RPS, 132f08c3bdfSopenharmony_ci .id_len = sizeof(CONFIG_RPS) - 1, 133f08c3bdfSopenharmony_ci }; 134f08c3bdfSopenharmony_ci int i = 0; 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci tst_kconfig_read(&kconfig, 1); 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci uevents[i++] = &add; 139f08c3bdfSopenharmony_ci if (kconfig.choice == 'y') 140f08c3bdfSopenharmony_ci uevents[i++] = &add_rx; 141f08c3bdfSopenharmony_ci uevents[i++] = &add_tx; 142f08c3bdfSopenharmony_ci if (kconfig.choice == 'y') 143f08c3bdfSopenharmony_ci uevents[i++] = &rem_rx; 144f08c3bdfSopenharmony_ci uevents[i++] = &rem_tx; 145f08c3bdfSopenharmony_ci uevents[i++] = &rem; 146f08c3bdfSopenharmony_ci uevents[i++] = NULL; 147f08c3bdfSopenharmony_ci} 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_cistatic struct tst_test test = { 150f08c3bdfSopenharmony_ci .setup = setup, 151f08c3bdfSopenharmony_ci .test_all = verify_uevent, 152f08c3bdfSopenharmony_ci .forks_child = 1, 153f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 154f08c3bdfSopenharmony_ci .needs_drivers = (const char *const []) { 155f08c3bdfSopenharmony_ci "tun", 156f08c3bdfSopenharmony_ci NULL 157f08c3bdfSopenharmony_ci }, 158f08c3bdfSopenharmony_ci .needs_root = 1 159f08c3bdfSopenharmony_ci}; 160