#include "tst_test.h" #include "tst_safe_macros.h" #include "lapi/sched.h" #define MAX_TRIES 1000 static void child_func(void) { int fd, len, event_found, tries; struct sockaddr_nl sa; char buffer[4096]; struct nlmsghdr *nlh; /* child will listen to a network interface create/delete/up/down events */ memset(&sa, 0, sizeof(sa)); sa.nl_family = AF_NETLINK; sa.nl_groups = RTMGRP_LINK; fd = SAFE_SOCKET(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); SAFE_BIND(fd, (struct sockaddr *) &sa, sizeof(sa)); /* waits for parent to create an interface */ TST_CHECKPOINT_WAKE_AND_WAIT(0); /* * To get rid of "resource temporarily unavailable" errors * when testing with -i option */ tries = 0; event_found = 0; nlh = (struct nlmsghdr *) buffer; while (tries < MAX_TRIES) { len = recv(fd, nlh, sizeof(buffer), MSG_DONTWAIT); if (len > 0) { /* stop receiving only on interface create/delete event */ if (nlh->nlmsg_type == RTM_NEWLINK || nlh->nlmsg_type == RTM_DELLINK) { event_found++; break; } } usleep(10000); tries++; } SAFE_CLOSE(fd); if (event_found) tst_res(TPASS, "interface changes detected"); else tst_res(TFAIL, "failed to detect interface changes"); exit(0); } static void test_netns_netlink(void) { /* unshares the network namespace */ SAFE_UNSHARE(CLONE_NEWNET); if (SAFE_FORK() == 0) child_func(); /* wait until child opens netlink socket */ TST_CHECKPOINT_WAIT(0); /* creates TAP network interface dummy0 */ if (WEXITSTATUS(system("ip tuntap add dev dummy0 mode tap"))) tst_brk(TBROK, "adding interface failed"); /* removes previously created dummy0 device */ if (WEXITSTATUS(system("ip tuntap del mode tap dummy0"))) tst_brk(TBROK, "removing interface failed"); /* allow child to continue */ TST_CHECKPOINT_WAKE(0); tst_reap_children(); } static struct tst_test test = { .test_all = test_netns_netlink, .needs_checkpoints = 1, .needs_root = 1, .forks_child = 1, .needs_kconfigs = (const char *[]) { "CONFIG_NET_NS=y", "CONFIG_TUN", NULL }, };
时间: 2024-04-18 17:32:07 浏览: 163
这段代码是一个测试用例,用于测试网络命名空间(netns)中的网络接口事件。它包含了一些头文件和相关的函数调用。
在`child_func`函数中,首先创建一个网络套接字,并绑定到一个特定的地址和端口上。然后使用`tst_checkpoint_wake_and_wait`函数等待父进程创建一个网络接口。接着使用循环来接收网络事件消息,如果接收到创建或删除网络接口的消息,则跳出循环。最后关闭套接字,并根据是否接收到事件消息来输出相应的测试结果。
在`test_netns_netlink`函数中,首先使用`safe_unshare`函数创建一个新的网络命名空间。然后使用`safe_fork`函数创建一个子进程,在子进程中调用`child_func`函数。接着使用`tst_checkpoint_wait`函数等待子进程打开网络套接字。然后使用系统命令创建一个TAP网络接口(dummy0),并使用系统命令删除之前创建的dummy0设备。最后使用`tst_checkpoint_wake`函数允许子进程继续执行。
最后定义了一个`tst_test`结构体,指定了测试运行的函数为`test_netns_netlink`,需要使用检查点功能(needs_checkpoints),需要以root权限运行,需要在内核配置中启用网络命名空间(CONFIG_NET_NS)和TUN设备驱动(CONFIG_TUN)。
这段代码的目的是测试在网络命名空间中创建和删除网络接口时是否能够正确检测到事件。
相关问题
请解释这段代码:#include "uart_test.h" #include "rbfd_uart_impls.h" #include "cmsis_os.h" #include "logger.h" #include "stm32f4xx_hal.h" #include "ff.h" extern UART_HandleTypeDef huart1; #define URT1 (&RBFD_UART_GET_UART(urt1)) #define URT_TST_BUF_LEN 8192U #define U_MB(x) (x*1024u*1024u) #define TEST_DATA_LEN U_MB(768) #define TEST_LOOPS (TEST_DATA_LEN / URT_TST_BUF_LEN)
这段代码包含了一些头文件的引用,并定义了一些宏和变量。下面是代码的解释:
1. `#include` 是一个预处理指令,用于包含其他头文件。这段代码中包含了 `uart_test.h`、`rbfd_uart_impls.h`、`cmsis_os.h`、`logger.h`、`stm32f4xx_hal.h` 和 `ff.h` 这些头文件。
2. `extern UART_HandleTypeDef huart1` 是一个外部变量的声明,表示 `huart1` 是一个 UART_HandleTypeDef 类型的变量,这个变量在其他地方定义。
3. `#define` 是一个预处理指令,用于定义宏。这段代码中定义了以下几个宏:
- `URT1` 定义为 `&RBFD_UART_GET_UART(urt1)`,表示一个指向 `urt1` UART 的指针。
- `URT_TST_BUF_LEN` 定义为 `8192U`,表示一个缓冲区的长度。
- `U_MB(x)` 是一个宏函数,用于将以兆字节为单位的值转换为字节。在这里,它将 `x` 乘以 1024*1024 来得到字节的值。
- `TEST_DATA_LEN` 定义为 `U_MB(768)`,表示测试数据的长度为 768 兆字节。
- `TEST_LOOPS` 定义为 `(TEST_DATA_LEN / URT_TST_BUF_LEN)`,表示测试循环的次数,即测试数据长度除以缓冲区长度的结果。
这段代码主要是为了引用头文件,并定义了一些宏和变量,用于后续的代码使用。
#include "tst_test.h" #include "lapi/sched.h" static void child_func(void) { TST_EXP_EQ_LI(getsid(0), 0); TST_EXP_EQ_LI(getpgid(0), 0); tst_res(TINFO, "setsid()"); SAFE_SETSID(); TST_EXP_EQ_LI(getsid(0), 1); TST_EXP_EQ_LI(getpgid(0), 1); } static void run(void) { const struct tst_clone_args args = { CLONE_NEWPID, SIGCHLD }; if (!SAFE_CLONE(&args)) { child_func(); return; } } static struct tst_test test = { .test_all = run, .needs_root = 1, .forks_child = 1, .needs_kconfigs = (const char *[]) { "CONFIG_PID_NS", NULL, }, };
这段代码是一个测试用例,用于测试进程命名空间(pidns)。它包含了一些头文件和相关的函数调用。
在`child_func`函数中,首先使用`tst_exp_eq_li`函数来验证`getsid`和`getpgid`函数的返回值是否符合预期。然后调用`tst_res`函数打印一条信息,然后使用`safe_setsid`函数设置新会话ID。再次调用`getsid`和`getpgid`函数来验证设置后的值。
在`run`函数中,首先定义了一个`tst_clone_args`结构体,指定了需要创建新的进程命名空间(CLONE_NEWPID)和信号处理(SIGCHLD)。然后使用`safe_clone`函数来创建子进程,在子进程中调用`child_func`函数。
最后定义了一个`tst_test`结构体,指定了测试运行的函数为`run`,需要以root权限运行,需要在内核配置中启用进程命名空间(CONFIG_PID_NS)。
这段代码的目的是测试在进程命名空间中使用`setsid`函数的功能。
阅读全文