/
githubmirror
/
liburing
Обзор
Документация
Войти
/
githubmirror
/
liburing
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/zcrx.c
928 строк
20 KB
Haiyue Wang
test/zcrx: use uring_ptr_to_u64() helper to convert ptr to u64
18 июн 2025, 19:02
18 июн 2025, 19:02
c2b3a10
Код
Авторство
О чём код?
/* SPDX-License-Identifier: MIT */ /* * Simple test case showing using send and recv through io_uring */ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/mman.h> #include <sys/socket.h> #include <sys/types.h> #include <pthread.h> #include <net/if.h> #include "liburing.h" #include "helpers.h" static unsigned int ifidx, rxq; static long page_size; /* the hw rxq must consume 128 of these pages, leaving 4 left */ #define AREA_PAGES 132 #define AREA_SZ (AREA_PAGES * page_size) #define RQ_ENTRIES 128 /* this is one more than the # of free pages after filling hw rxq */ #define LOOP_COUNT 5 #define DEV_ENV_VAR "NETIF" #define RXQ_ENV_VAR "NETRXQ" #define RING_FLAGS (IORING_SETUP_DEFER_TASKRUN | \ IORING_SETUP_CQE32 | \ IORING_SETUP_SINGLE_ISSUER) static char str[] = "iv5t4dl500w7wsrf14fsuq8thptto0z7i2q62z1p8dwrv5u4kaxpqhm2rb7bapddi5gfkh7f9695eh46t2o5yap2y43gstbsq3n90bg1i7zx1m4wojoqbuxhsrw4s4y3sh9qp57ovbaa2o9yaqa7d4to2vak1otvgkoxs5t0ovjbe6roginrjeh906kmjn1289jlho9a1bud02ex4xr3cvfcybpl6axnr117p0aesb3070wlvj91en7tpf8nyb1e"; #define MSG_SIZE 512 #define PORT 10202 #define HOST "127.0.0.1" static int probe_zcrx(void *area) { struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; struct io_uring ring; int ret; ret = t_create_ring(8, &ring, RING_FLAGS); if (ret == T_SETUP_SKIP) { fprintf(stderr, "required ring flags are not supported, skip\n"); return T_EXIT_SKIP; } if (ret) { fprintf(stderr, "probe ring setup failure\n"); return T_EXIT_FAIL; } ret = io_uring_register_ifq(&ring, ®); if (ret == -EINVAL) { fprintf(stderr, "zcrx is not supported, skip\n"); return T_EXIT_SKIP; } if (ret) { fprintf(stderr, "probe zcrx register fail %i\n", ret); return T_EXIT_FAIL; } io_uring_queue_exit(&ring); return T_EXIT_PASS; } static int try_register_ifq(struct io_uring_zcrx_ifq_reg *reg) { struct io_uring ring; int ret; ret = t_create_ring(8, &ring, RING_FLAGS); if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); exit(T_EXIT_FAIL); } ret = io_uring_register_ifq(&ring, reg); io_uring_queue_exit(&ring); return ret; } static int test_invalid_if(void *area) { int ret; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = -1, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; ret = try_register_ifq(®); if (ret != -EINVAL && ret != -ENODEV) { fprintf(stderr, "registered invalid IF %i\n", ret); return T_EXIT_FAIL; } reg.if_idx = ifidx; reg.if_rxq = -1; ret = try_register_ifq(®); if (ret != -EINVAL) { fprintf(stderr, "registered invalid IFQ %i\n", ret); return T_EXIT_FAIL; } return T_EXIT_PASS; } static int test_invalid_ifq_collision(void *area) { struct io_uring ring, ring2; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; int ret; ret = t_create_ring(8, &ring, RING_FLAGS); if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); return T_EXIT_FAIL; } ret = t_create_ring(8, &ring2, RING_FLAGS); if (ret != T_SETUP_OK) { fprintf(stderr, "ring2 create failed: %d\n", ret); return T_EXIT_FAIL; } ret = io_uring_register_ifq(&ring, ®); if (ret) { fprintf(stderr, "initial registration failed %i\n", ret); return T_EXIT_FAIL; } /* register taken ifq */ ret = io_uring_register_ifq(&ring, ®); if (!ret) { fprintf(stderr, "registered taken queue\n"); return T_EXIT_FAIL; } ret = io_uring_register_ifq(&ring2, ®); if (!ret) { fprintf(stderr, "registered taken queue ring2\n"); return T_EXIT_FAIL; } io_uring_queue_exit(&ring); io_uring_queue_exit(&ring2); return T_EXIT_PASS; } static int test_rq_setup(void *area) { int ret; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = 0, .area_ptr = uring_ptr_to_u64(&area_reg), }; ret = try_register_ifq(®); if (ret != -EINVAL) { fprintf(stderr, "registered 0 rq entries\n"); return T_EXIT_FAIL; } reg.rq_entries = (__u32)-1; ret = try_register_ifq(®); if (ret != -EINVAL) { fprintf(stderr, "registered unlimited nr of rq entries\n"); return T_EXIT_FAIL; } reg.rq_entries = RQ_ENTRIES - 1; ret = try_register_ifq(®); if (ret != 0) { fprintf(stderr, "ifq registration failed %i\n", ret); return T_EXIT_FAIL; } if (reg.rq_entries == RQ_ENTRIES - 1) { fprintf(stderr, "registered non pow2 refill entries %i\n", reg.rq_entries); return T_EXIT_FAIL; } return T_EXIT_PASS; } static int test_null_area_reg_struct(void) { int ret; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(0), }; ret = try_register_ifq(®); return ret ? T_EXIT_PASS : T_EXIT_FAIL; } static int test_null_area(void) { int ret; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(0), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; ret = try_register_ifq(®); return ret ? T_EXIT_PASS : T_EXIT_FAIL; } static int test_misaligned_area(void *area) { int ret; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area + 1), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; if (!try_register_ifq(®)) return T_EXIT_FAIL; area_reg.addr = uring_ptr_to_u64(area); area_reg.len = AREA_SZ - 1; ret = try_register_ifq(®); return ret ? T_EXIT_PASS : T_EXIT_FAIL; } static int test_larger_than_alloc_area(void *area) { int ret; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area), .len = AREA_SZ + 4096, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; ret = try_register_ifq(®); return ret ? T_EXIT_PASS : T_EXIT_FAIL; } static int test_area_access(void) { struct io_uring_zcrx_area_reg area_reg = { .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; int i, ret; void *area; for (i = 0; i < 2; i++) { int ro = i & 1; int prot = ro ? PROT_READ : PROT_WRITE; area = mmap(NULL, AREA_SZ, prot, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); if (area == MAP_FAILED) { perror("mmap"); return T_EXIT_FAIL; } area_reg.addr = uring_ptr_to_u64(area); ret = try_register_ifq(®); if (ret != -EFAULT) { fprintf(stderr, "registered unaccessible memory\n"); return T_EXIT_FAIL; } munmap(area, AREA_SZ); } return T_EXIT_PASS; } static int create_ring_with_ifq(struct io_uring *ring, void *area, __u32 *id) { struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(area), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; int ret; ret = t_create_ring(128, ring, RING_FLAGS); if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); return T_EXIT_FAIL; } ret = io_uring_register_ifq(ring, ®); if (ret) { io_uring_queue_exit(ring); fprintf(stderr, "ifq register failed %d\n", ret); return T_EXIT_FAIL; } *id = reg.zcrx_id; return 0; } static void test_io_uring_prep_zcrx(struct io_uring_sqe *sqe, int fd, int ifq) { io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, fd, NULL, 0, 0); sqe->zcrx_ifq_idx = ifq; sqe->ioprio |= IORING_RECV_MULTISHOT; } static struct io_uring_cqe *submit_and_wait_one(struct io_uring *ring) { struct io_uring_cqe *cqe; int ret; ret = io_uring_submit(ring); if (ret != 1) { fprintf(stderr, "sqe submit failed: %d\n", ret); return NULL; } ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { fprintf(stderr, "wait completion %d\n", ret); return NULL; } return cqe; } static int test_invalid_zcrx_request(void *area) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; struct io_uring ring; __u32 zcrx_id; int ret, fds[2]; ret = create_ring_with_ifq(&ring, area, &zcrx_id); if (ret != T_SETUP_OK) { fprintf(stderr, "ifq-ring create failed: %d\n", ret); return T_EXIT_FAIL; } ret = t_create_socket_pair(fds, true); if (ret) { fprintf(stderr, "t_create_socket_pair failed: %d\n", ret); return ret; } /* invalid file */ sqe = io_uring_get_sqe(&ring); test_io_uring_prep_zcrx(sqe, ring.ring_fd, zcrx_id); cqe = submit_and_wait_one(&ring); if (!cqe) { fprintf(stderr, "submit_and_wait_one failed\n"); return T_EXIT_FAIL; } if (cqe->flags & IORING_CQE_F_MORE) { fprintf(stderr, "unexpected F_MORE for invalid fd\n"); return T_EXIT_FAIL; } if (cqe->res != -ENOTSOCK) { fprintf(stderr, "zcrx for non-socket file\n"); return T_EXIT_FAIL; } io_uring_cqe_seen(&ring, cqe); /* invalid ifq idx */ sqe = io_uring_get_sqe(&ring); test_io_uring_prep_zcrx(sqe, fds[0], zcrx_id + 1); cqe = submit_and_wait_one(&ring); if (!cqe) { fprintf(stderr, "submit_and_wait_one failed\n"); return T_EXIT_FAIL; } if (cqe->flags & IORING_CQE_F_MORE) { fprintf(stderr, "unexpected F_MORE for invalid fd\n"); return T_EXIT_FAIL; } if (cqe->res != -EINVAL) { fprintf(stderr, "zcrx recv with non-existent zcrx ifq\n"); return T_EXIT_FAIL; } io_uring_cqe_seen(&ring, cqe); close(fds[0]); close(fds[1]); io_uring_queue_exit(&ring); return 0; } struct recv_data { pthread_barrier_t connect; pthread_barrier_t startup; pthread_barrier_t barrier; pthread_barrier_t finish; int accept_fd; char buf[MSG_SIZE]; void *area; void *ring_ptr; unsigned int ring_sz; struct io_uring_zcrx_rq rq_ring; }; static int recv_prep(struct io_uring *ring, struct recv_data *rd, int *sock, __u32 zcrx_id) { struct sockaddr_in saddr; struct io_uring_sqe *sqe; int sockfd, ret, val, use_fd; socklen_t socklen; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(PORT); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); return 1; } val = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("bind"); goto err; } ret = listen(sockfd, 1); if (ret < 0) { perror("listen"); goto err; } pthread_barrier_wait(&rd->connect); socklen = sizeof(saddr); use_fd = accept(sockfd, (struct sockaddr *)&saddr, &socklen); if (use_fd < 0) { perror("accept"); goto err; } rd->accept_fd = use_fd; pthread_barrier_wait(&rd->startup); pthread_barrier_wait(&rd->barrier); sqe = io_uring_get_sqe(ring); io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, use_fd, NULL, 0, 0); sqe->zcrx_ifq_idx = zcrx_id; sqe->ioprio |= IORING_RECV_MULTISHOT; sqe->user_data = 2; ret = io_uring_submit(ring); if (ret <= 0) { fprintf(stderr, "submit failed: %d\n", ret); goto err; } *sock = sockfd; return 0; err: close(sockfd); return 1; } static struct io_uring_zcrx_rqe* get_refill_entry(struct io_uring_zcrx_rq *rq_ring) { unsigned mask = rq_ring->ring_entries - 1; struct io_uring_zcrx_rqe* rqe; rqe = &rq_ring->rqes[rq_ring->rq_tail & mask]; rq_ring->rq_tail++; return rqe; } static void refill_garbage(struct recv_data *rd, uint64_t area_token) { struct io_uring_zcrx_rq *rq_ring = &rd->rq_ring; struct io_uring_zcrx_rqe* rqe; int i = 0; /* invalid area */ rqe = get_refill_entry(rq_ring); rqe->off = (area_token + 1) << IORING_ZCRX_AREA_SHIFT; i++; /* invalid area offset */ rqe = get_refill_entry(rq_ring); rqe->off = AREA_SZ | (area_token << IORING_ZCRX_AREA_SHIFT); rqe->off += AREA_SZ; i++; for (; i < rq_ring->ring_entries; i++) { rqe = get_refill_entry(rq_ring); rqe->off = ((uint64_t)1 << IORING_ZCRX_AREA_SHIFT) - 1; } io_uring_smp_store_release(rq_ring->ktail, rq_ring->rq_tail); } static int do_recv(struct io_uring *ring, struct recv_data *rd, uint64_t refill_area_token) { struct io_uring_cqe *cqe; struct io_uring_zcrx_cqe *zcqe; int i, ret; refill_garbage(rd, refill_area_token); for (i = 0; i < LOOP_COUNT - 1; i++) { uint64_t off, mask = (1ULL << IORING_ZCRX_AREA_SHIFT) - 1; void *addr; ret = io_uring_wait_cqe(ring, &cqe); if (ret) { fprintf(stdout, "wait_cqe: %d\n", ret); return 1; } if (cqe->res == -EINVAL) { fprintf(stdout, "recv not supported, skipping\n"); goto out; } if (cqe->res < 0) { fprintf(stderr, "failed recv cqe: %d\n", cqe->res); goto err; } if (cqe->res - 1 != strlen(str)) { fprintf(stderr, "got wrong length: %d/%d\n", cqe->res, (int) strlen(str) + 1); goto err; } zcqe = (struct io_uring_zcrx_cqe *)(cqe + 1); off = zcqe->off & mask; addr = (char *) rd->area + off; ret = strncmp(str, addr, sizeof(str)); if (ret != 0) { fprintf(stderr, "recv incorrect payload: %s\n", (const char *)addr); goto err; } io_uring_cqe_seen(ring, cqe); } ret = io_uring_wait_cqe(ring, &cqe); if (ret) { fprintf(stdout, "wait_cqe: %d\n", ret); return 1; } if (cqe->res != -ENOMEM) { fprintf(stdout, "final recv cqe did not return ENOMEM\n"); goto err; } out: io_uring_cqe_seen(ring, cqe); pthread_barrier_wait(&rd->finish); return 0; err: io_uring_cqe_seen(ring, cqe); pthread_barrier_wait(&rd->finish); return 1; } static void *recv_fn(void *data) { struct recv_data *rd = data; struct io_uring_params p = { }; struct io_uring ring; int ret, sock; struct io_uring_zcrx_area_reg area_reg = { .addr = uring_ptr_to_u64(rd->area), .len = AREA_SZ, .flags = 0, }; struct io_uring_zcrx_ifq_reg reg = { .if_idx = ifidx, .if_rxq = rxq, .rq_entries = RQ_ENTRIES, .area_ptr = uring_ptr_to_u64(&area_reg), }; p.flags = RING_FLAGS; ret = t_create_ring_params(8, &ring, &p); if (ret == T_SETUP_SKIP) { ret = 0; goto err; } else if (ret < 0) { goto err; } ret = io_uring_register_ifq(&ring, ®); if (ret != 0) { fprintf(stderr, "register_ifq failed: %d\n", ret); goto err_ring_exit; } /* rd->ring_ptr = mmap( 0, reg.offsets.mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, ring.enter_ring_fd, IORING_OFF_RQ_RING ); rd->ring_sz = reg.offsets.mmap_sz; */ rd->rq_ring.khead = (__u32*)((char*)rd->ring_ptr + reg.offsets.head); rd->rq_ring.ktail = (__u32*)((char*)rd->ring_ptr + reg.offsets.tail); rd->rq_ring.rqes = (struct io_uring_zcrx_rqe*)((char*)rd->ring_ptr + reg.offsets.rqes); rd->rq_ring.rq_tail = 0; rd->rq_ring.ring_entries = reg.rq_entries; ret = recv_prep(&ring, rd, &sock, reg.zcrx_id); if (ret) { fprintf(stderr, "recv_prep failed: %d\n", ret); goto err; } ret = do_recv(&ring, rd, area_reg.rq_area_token); close(sock); close(rd->accept_fd); err_ring_exit: io_uring_queue_exit(&ring); err: return (void *)(intptr_t)ret; } static int do_send(struct recv_data *rd) { struct sockaddr_in saddr; struct iovec iov = { .iov_base = str, .iov_len = sizeof(str), }; struct io_uring ring; struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int i, sockfd, ret; ret = io_uring_queue_init(8, &ring, 0); if (ret) { fprintf(stderr, "queue init failed: %d\n", ret); return 1; } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(PORT); inet_pton(AF_INET, HOST, &saddr.sin_addr); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); goto err2; } pthread_barrier_wait(&rd->connect); ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("connect"); goto err; } pthread_barrier_wait(&rd->startup); for (i = 0; i < LOOP_COUNT; i++) { sqe = io_uring_get_sqe(&ring); io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0); sqe->user_data = 1; } ret = io_uring_submit(&ring); if (ret <= 0) { fprintf(stderr, "submit failed: %d\n", ret); goto err; } pthread_barrier_wait(&rd->barrier); ret = io_uring_wait_cqe(&ring, &cqe); if (cqe->res == -EINVAL) { fprintf(stdout, "send not supported, skipping\n"); goto err; } if (cqe->res != iov.iov_len) { fprintf(stderr, "failed cqe: %d\n", cqe->res); goto err; } pthread_barrier_wait(&rd->finish); close(sockfd); io_uring_queue_exit(&ring); return 0; err: close(sockfd); err2: io_uring_queue_exit(&ring); pthread_barrier_wait(&rd->finish); return 1; } static int test_recv(void *area) { pthread_t recv_thread; struct recv_data rd; int ret; void *retval; memset(&rd, 0, sizeof(rd)); pthread_barrier_init(&rd.connect, NULL, 2); pthread_barrier_init(&rd.startup, NULL, 2); pthread_barrier_init(&rd.barrier, NULL, 2); pthread_barrier_init(&rd.finish, NULL, 2); rd.area = area; ret = pthread_create(&recv_thread, NULL, recv_fn, &rd); if (ret) { fprintf(stderr, "Thread create failed: %d\n", ret); return 1; } do_send(&rd); pthread_join(recv_thread, &retval); return (intptr_t)retval; } int main(int argc, char *argv[]) { char *dev, *rxq_str, *rxq_end; void *area_outer, *area; int ret; if (argc > 1) return T_EXIT_SKIP; page_size = sysconf(_SC_PAGESIZE); if (page_size < 0) { perror("sysconf(_SC_PAGESIZE)"); return T_EXIT_FAIL; } area_outer = mmap(NULL, AREA_SZ + 8192, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); if (area_outer == MAP_FAILED) { perror("mmap"); return T_EXIT_FAIL; } area = mmap(area_outer, AREA_SZ, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); if (area == MAP_FAILED) { perror("mmap"); return T_EXIT_FAIL; } dev = getenv(DEV_ENV_VAR); if (!dev) return T_EXIT_SKIP; ifidx = if_nametoindex(dev); if (!ifidx) return T_EXIT_SKIP; rxq_str = getenv(RXQ_ENV_VAR); if (!rxq_str) return T_EXIT_SKIP; rxq = strtol(rxq_str, &rxq_end, 10); if (rxq_end == rxq_str || *rxq_end != '\0') return T_EXIT_SKIP; ret = probe_zcrx(area); if (ret != T_EXIT_PASS) return ret; ret = test_rq_setup(area); if (ret) { fprintf(stderr, "test_invalid_reg_struct failed\n"); return ret; } ret = test_null_area_reg_struct(); if (ret) { fprintf(stderr, "test_null_area_reg_struct failed\n"); return ret; } ret = test_null_area(); if (ret) { fprintf(stderr, "test_null_area failed\n"); return ret; } ret = test_misaligned_area(area); if (ret) { fprintf(stderr, "test_misaligned_area failed\n"); return ret; } ret = test_larger_than_alloc_area(area); if (ret) { fprintf(stderr, "test_larger_than_alloc_area failed\n"); return ret; } ret = test_area_access(); if (ret) { fprintf(stderr, "test_area_access failed\n"); return ret; } ret = test_invalid_if(area); if (ret) { fprintf(stderr, "test_invalid_if failed\n"); return ret; } ret = test_invalid_ifq_collision(area); if (ret) { fprintf(stderr, "test_invalid_ifq_collision failed\n"); return ret; } ret = test_invalid_zcrx_request(area); if (ret) { fprintf(stderr, "test_invalid_ifq_collision failed\n"); return ret; } ret = test_recv(area); if (ret) { fprintf(stderr, "test_recv failed\n"); return ret; } munmap(area, AREA_SZ); return T_EXIT_PASS; }