12a8682a8SVincenzo Maffione /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
32a8682a8SVincenzo Maffione *
42a8682a8SVincenzo Maffione * Copyright (C) 2018 Vincenzo Maffione
52a8682a8SVincenzo Maffione *
62a8682a8SVincenzo Maffione * Redistribution and use in source and binary forms, with or without
72a8682a8SVincenzo Maffione * modification, are permitted provided that the following conditions
82a8682a8SVincenzo Maffione * are met:
92a8682a8SVincenzo Maffione * 1. Redistributions of source code must retain the above copyright
102a8682a8SVincenzo Maffione * notice, this list of conditions and the following disclaimer.
112a8682a8SVincenzo Maffione * 2. Redistributions in binary form must reproduce the above copyright
122a8682a8SVincenzo Maffione * notice, this list of conditions and the following disclaimer in the
132a8682a8SVincenzo Maffione * documentation and/or other materials provided with the distribution.
142a8682a8SVincenzo Maffione *
152a8682a8SVincenzo Maffione * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162a8682a8SVincenzo Maffione * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172a8682a8SVincenzo Maffione * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182a8682a8SVincenzo Maffione * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192a8682a8SVincenzo Maffione * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202a8682a8SVincenzo Maffione * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212a8682a8SVincenzo Maffione * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222a8682a8SVincenzo Maffione * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232a8682a8SVincenzo Maffione * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242a8682a8SVincenzo Maffione * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252a8682a8SVincenzo Maffione * SUCH DAMAGE.
262a8682a8SVincenzo Maffione */
272a8682a8SVincenzo Maffione
2845c67e8fSVincenzo Maffione /*
2945c67e8fSVincenzo Maffione * This program contains a suite of unit tests for the netmap control device.
3045c67e8fSVincenzo Maffione *
3145c67e8fSVincenzo Maffione * On FreeBSD, you can run these tests with Kyua once installed in the system:
3245c67e8fSVincenzo Maffione * # kyua test -k /usr/tests/sys/netmap/Kyuafile
3345c67e8fSVincenzo Maffione *
3445c67e8fSVincenzo Maffione * On Linux, you can run them directly:
3545c67e8fSVincenzo Maffione * # ./ctrl-api-test
3645c67e8fSVincenzo Maffione */
3745c67e8fSVincenzo Maffione
382a8682a8SVincenzo Maffione #include <sys/ioctl.h>
392a8682a8SVincenzo Maffione #include <sys/mman.h>
402a8682a8SVincenzo Maffione #include <sys/wait.h>
412a8682a8SVincenzo Maffione
422a8682a8SVincenzo Maffione #include <assert.h>
432a8682a8SVincenzo Maffione #include <ctype.h>
442a8682a8SVincenzo Maffione #include <errno.h>
452a8682a8SVincenzo Maffione #include <fcntl.h>
462a8682a8SVincenzo Maffione #include <inttypes.h>
4736d6e657SVincenzo Maffione #include <libnetmap.h>
482a8682a8SVincenzo Maffione #include <net/if.h>
492a8682a8SVincenzo Maffione #include <net/netmap.h>
502a8682a8SVincenzo Maffione #include <pthread.h>
512a8682a8SVincenzo Maffione #include <semaphore.h>
522a8682a8SVincenzo Maffione #include <stdint.h>
532a8682a8SVincenzo Maffione #include <stdio.h>
542a8682a8SVincenzo Maffione #include <stdlib.h>
552a8682a8SVincenzo Maffione #include <string.h>
562a8682a8SVincenzo Maffione #include <time.h>
572a8682a8SVincenzo Maffione #include <unistd.h>
582a8682a8SVincenzo Maffione #include <signal.h>
5936d6e657SVincenzo Maffione #include <stddef.h>
602a8682a8SVincenzo Maffione
617d757b71SOlivier Cochard #ifdef __FreeBSD__
627d757b71SOlivier Cochard #include "freebsd_test_suite/macros.h"
637d757b71SOlivier Cochard
642a8682a8SVincenzo Maffione static int
eventfd(int x __unused,int y __unused)652a8682a8SVincenzo Maffione eventfd(int x __unused, int y __unused)
662a8682a8SVincenzo Maffione {
672a8682a8SVincenzo Maffione errno = ENODEV;
682a8682a8SVincenzo Maffione return -1;
692a8682a8SVincenzo Maffione }
704f6858e8SVincenzo Maffione #else /* __linux__ */
714f6858e8SVincenzo Maffione #include <sys/eventfd.h>
724f6858e8SVincenzo Maffione #endif
732a8682a8SVincenzo Maffione
7436d6e657SVincenzo Maffione #define NM_IFNAMSZ 64
7536d6e657SVincenzo Maffione
762a8682a8SVincenzo Maffione static int
exec_command(int argc,const char * const argv[])772a8682a8SVincenzo Maffione exec_command(int argc, const char *const argv[])
782a8682a8SVincenzo Maffione {
792a8682a8SVincenzo Maffione pid_t child_pid;
802a8682a8SVincenzo Maffione pid_t wret;
812a8682a8SVincenzo Maffione int child_status;
822a8682a8SVincenzo Maffione int i;
832a8682a8SVincenzo Maffione
842a8682a8SVincenzo Maffione printf("Executing command: ");
852a8682a8SVincenzo Maffione for (i = 0; i < argc - 1; i++) {
862a8682a8SVincenzo Maffione if (!argv[i]) {
872a8682a8SVincenzo Maffione /* Invalid argument. */
882a8682a8SVincenzo Maffione return -1;
892a8682a8SVincenzo Maffione }
902a8682a8SVincenzo Maffione if (i > 0) {
912a8682a8SVincenzo Maffione putchar(' ');
922a8682a8SVincenzo Maffione }
932a8682a8SVincenzo Maffione printf("%s", argv[i]);
942a8682a8SVincenzo Maffione }
952a8682a8SVincenzo Maffione putchar('\n');
962a8682a8SVincenzo Maffione
972a8682a8SVincenzo Maffione child_pid = fork();
982a8682a8SVincenzo Maffione if (child_pid == 0) {
992a8682a8SVincenzo Maffione char **av;
10008f34ad9SVincenzo Maffione int fds[3];
1012a8682a8SVincenzo Maffione
1022a8682a8SVincenzo Maffione /* Child process. Redirect stdin, stdout
1032a8682a8SVincenzo Maffione * and stderr. */
10408f34ad9SVincenzo Maffione for (i = 0; i < 3; i++) {
10508f34ad9SVincenzo Maffione close(i);
10608f34ad9SVincenzo Maffione fds[i] = open("/dev/null", O_RDONLY);
10708f34ad9SVincenzo Maffione if (fds[i] < 0) {
10808f34ad9SVincenzo Maffione for (i--; i >= 0; i--) {
10908f34ad9SVincenzo Maffione close(fds[i]);
11008f34ad9SVincenzo Maffione }
1112a8682a8SVincenzo Maffione return -1;
1122a8682a8SVincenzo Maffione }
11308f34ad9SVincenzo Maffione }
1142a8682a8SVincenzo Maffione
1152a8682a8SVincenzo Maffione /* Make a copy of the arguments, passing them to execvp. */
1162a8682a8SVincenzo Maffione av = calloc(argc, sizeof(av[0]));
1172a8682a8SVincenzo Maffione if (!av) {
1182a8682a8SVincenzo Maffione exit(EXIT_FAILURE);
1192a8682a8SVincenzo Maffione }
1202a8682a8SVincenzo Maffione for (i = 0; i < argc - 1; i++) {
1212a8682a8SVincenzo Maffione av[i] = strdup(argv[i]);
1222a8682a8SVincenzo Maffione if (!av[i]) {
1232a8682a8SVincenzo Maffione exit(EXIT_FAILURE);
1242a8682a8SVincenzo Maffione }
1252a8682a8SVincenzo Maffione }
1262a8682a8SVincenzo Maffione execvp(av[0], av);
1272a8682a8SVincenzo Maffione perror("execvp()");
1282a8682a8SVincenzo Maffione exit(EXIT_FAILURE);
1292a8682a8SVincenzo Maffione }
1302a8682a8SVincenzo Maffione
1312a8682a8SVincenzo Maffione wret = waitpid(child_pid, &child_status, 0);
1322a8682a8SVincenzo Maffione if (wret < 0) {
1332a8682a8SVincenzo Maffione fprintf(stderr, "waitpid() failed: %s\n", strerror(errno));
1342a8682a8SVincenzo Maffione return wret;
1352a8682a8SVincenzo Maffione }
1362a8682a8SVincenzo Maffione if (WIFEXITED(child_status)) {
1372a8682a8SVincenzo Maffione return WEXITSTATUS(child_status);
1382a8682a8SVincenzo Maffione }
1392a8682a8SVincenzo Maffione
1402a8682a8SVincenzo Maffione return -1;
1412a8682a8SVincenzo Maffione }
1422a8682a8SVincenzo Maffione
1432a8682a8SVincenzo Maffione
1442a8682a8SVincenzo Maffione #define THRET_SUCCESS ((void *)128)
1452a8682a8SVincenzo Maffione #define THRET_FAILURE ((void *)0)
1462a8682a8SVincenzo Maffione
1472a8682a8SVincenzo Maffione struct TestContext {
14836d6e657SVincenzo Maffione char ifname[NM_IFNAMSZ];
14936d6e657SVincenzo Maffione char ifname_ext[NM_IFNAMSZ];
15036d6e657SVincenzo Maffione char bdgname[NM_IFNAMSZ];
1512a8682a8SVincenzo Maffione uint32_t nr_tx_slots; /* slots in tx rings */
1522a8682a8SVincenzo Maffione uint32_t nr_rx_slots; /* slots in rx rings */
1532a8682a8SVincenzo Maffione uint16_t nr_tx_rings; /* number of tx rings */
1542a8682a8SVincenzo Maffione uint16_t nr_rx_rings; /* number of rx rings */
1554f6858e8SVincenzo Maffione uint16_t nr_host_tx_rings; /* number of host tx rings */
1564f6858e8SVincenzo Maffione uint16_t nr_host_rx_rings; /* number of host rx rings */
1572a8682a8SVincenzo Maffione uint16_t nr_mem_id; /* id of the memory allocator */
1582a8682a8SVincenzo Maffione uint16_t nr_ringid; /* ring(s) we care about */
1592a8682a8SVincenzo Maffione uint32_t nr_mode; /* specify NR_REG_* modes */
1602a8682a8SVincenzo Maffione uint32_t nr_extra_bufs; /* number of requested extra buffers */
1612a8682a8SVincenzo Maffione uint64_t nr_flags; /* additional flags (see below) */
1622a8682a8SVincenzo Maffione uint32_t nr_hdr_len; /* for PORT_HDR_SET and PORT_HDR_GET */
1632a8682a8SVincenzo Maffione uint32_t nr_first_cpu_id; /* vale polling */
1642a8682a8SVincenzo Maffione uint32_t nr_num_polling_cpus; /* vale polling */
1655e874d26SVincenzo Maffione uint32_t sync_kloop_mode; /* sync-kloop */
1662a8682a8SVincenzo Maffione int fd; /* netmap file descriptor */
1672a8682a8SVincenzo Maffione
1682a8682a8SVincenzo Maffione void *csb; /* CSB entries (atok and ktoa) */
1692a8682a8SVincenzo Maffione struct nmreq_option *nr_opt; /* list of options */
1702a8682a8SVincenzo Maffione sem_t *sem; /* for thread synchronization */
17136d6e657SVincenzo Maffione
17236d6e657SVincenzo Maffione struct nmctx *nmctx;
17336d6e657SVincenzo Maffione const char *ifparse;
17436d6e657SVincenzo Maffione struct nmport_d *nmport; /* nmport descriptor from libnetmap */
1752a8682a8SVincenzo Maffione };
1762a8682a8SVincenzo Maffione
1772a8682a8SVincenzo Maffione static struct TestContext ctx_;
1782a8682a8SVincenzo Maffione
1792a8682a8SVincenzo Maffione typedef int (*testfunc_t)(struct TestContext *ctx);
1802a8682a8SVincenzo Maffione
1812a8682a8SVincenzo Maffione static void
nmreq_hdr_init(struct nmreq_header * hdr,const char * ifname)1822a8682a8SVincenzo Maffione nmreq_hdr_init(struct nmreq_header *hdr, const char *ifname)
1832a8682a8SVincenzo Maffione {
1842a8682a8SVincenzo Maffione memset(hdr, 0, sizeof(*hdr));
1852a8682a8SVincenzo Maffione hdr->nr_version = NETMAP_API;
18636d6e657SVincenzo Maffione assert(strlen(ifname) < NM_IFNAMSZ);
18736d6e657SVincenzo Maffione strncpy(hdr->nr_name, ifname, sizeof(hdr->nr_name));
1882a8682a8SVincenzo Maffione }
1892a8682a8SVincenzo Maffione
1902a8682a8SVincenzo Maffione /* Single NETMAP_REQ_PORT_INFO_GET. */
1912a8682a8SVincenzo Maffione static int
port_info_get(struct TestContext * ctx)1922a8682a8SVincenzo Maffione port_info_get(struct TestContext *ctx)
1932a8682a8SVincenzo Maffione {
1942a8682a8SVincenzo Maffione struct nmreq_port_info_get req;
1952a8682a8SVincenzo Maffione struct nmreq_header hdr;
1962a8682a8SVincenzo Maffione int success;
1972a8682a8SVincenzo Maffione int ret;
1982a8682a8SVincenzo Maffione
19908f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_PORT_INFO_GET on '%s'\n", ctx->ifname_ext);
2002a8682a8SVincenzo Maffione
20108f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
2022a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_PORT_INFO_GET;
2032a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
2042a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
2052a8682a8SVincenzo Maffione req.nr_mem_id = ctx->nr_mem_id;
2062a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
2072a8682a8SVincenzo Maffione if (ret != 0) {
2082a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, PORT_INFO_GET)");
2092a8682a8SVincenzo Maffione return ret;
2102a8682a8SVincenzo Maffione }
2115854d718SVincenzo Maffione printf("nr_memsize %llu\n", (unsigned long long)req.nr_memsize);
2122a8682a8SVincenzo Maffione printf("nr_tx_slots %u\n", req.nr_tx_slots);
2132a8682a8SVincenzo Maffione printf("nr_rx_slots %u\n", req.nr_rx_slots);
2142a8682a8SVincenzo Maffione printf("nr_tx_rings %u\n", req.nr_tx_rings);
2152a8682a8SVincenzo Maffione printf("nr_rx_rings %u\n", req.nr_rx_rings);
2162a8682a8SVincenzo Maffione printf("nr_mem_id %u\n", req.nr_mem_id);
2172a8682a8SVincenzo Maffione
2182a8682a8SVincenzo Maffione success = req.nr_memsize && req.nr_tx_slots && req.nr_rx_slots &&
2192a8682a8SVincenzo Maffione req.nr_tx_rings && req.nr_rx_rings && req.nr_tx_rings;
2202a8682a8SVincenzo Maffione if (!success) {
2212a8682a8SVincenzo Maffione return -1;
2222a8682a8SVincenzo Maffione }
2232a8682a8SVincenzo Maffione
2242a8682a8SVincenzo Maffione /* Write back results to the context structure. */
2252a8682a8SVincenzo Maffione ctx->nr_tx_slots = req.nr_tx_slots;
2262a8682a8SVincenzo Maffione ctx->nr_rx_slots = req.nr_rx_slots;
2272a8682a8SVincenzo Maffione ctx->nr_tx_rings = req.nr_tx_rings;
2282a8682a8SVincenzo Maffione ctx->nr_rx_rings = req.nr_rx_rings;
2292a8682a8SVincenzo Maffione ctx->nr_mem_id = req.nr_mem_id;
2302a8682a8SVincenzo Maffione
2312a8682a8SVincenzo Maffione return 0;
2322a8682a8SVincenzo Maffione }
2332a8682a8SVincenzo Maffione
2342a8682a8SVincenzo Maffione /* Single NETMAP_REQ_REGISTER, no use. */
2352a8682a8SVincenzo Maffione static int
port_register(struct TestContext * ctx)2362a8682a8SVincenzo Maffione port_register(struct TestContext *ctx)
2372a8682a8SVincenzo Maffione {
2382a8682a8SVincenzo Maffione struct nmreq_register req;
2392a8682a8SVincenzo Maffione struct nmreq_header hdr;
2402a8682a8SVincenzo Maffione int success;
2412a8682a8SVincenzo Maffione int ret;
2422a8682a8SVincenzo Maffione
2432a8682a8SVincenzo Maffione printf("Testing NETMAP_REQ_REGISTER(mode=%d,ringid=%d,"
2445854d718SVincenzo Maffione "flags=0x%llx) on '%s'\n",
2455854d718SVincenzo Maffione ctx->nr_mode, ctx->nr_ringid, (unsigned long long)ctx->nr_flags,
24608f34ad9SVincenzo Maffione ctx->ifname_ext);
2472a8682a8SVincenzo Maffione
24808f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
2492a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_REGISTER;
2502a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
2512a8682a8SVincenzo Maffione hdr.nr_options = (uintptr_t)ctx->nr_opt;
2522a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
2532a8682a8SVincenzo Maffione req.nr_mem_id = ctx->nr_mem_id;
2542a8682a8SVincenzo Maffione req.nr_mode = ctx->nr_mode;
2552a8682a8SVincenzo Maffione req.nr_ringid = ctx->nr_ringid;
2562a8682a8SVincenzo Maffione req.nr_flags = ctx->nr_flags;
2572a8682a8SVincenzo Maffione req.nr_tx_slots = ctx->nr_tx_slots;
2582a8682a8SVincenzo Maffione req.nr_rx_slots = ctx->nr_rx_slots;
2592a8682a8SVincenzo Maffione req.nr_tx_rings = ctx->nr_tx_rings;
2604f6858e8SVincenzo Maffione req.nr_host_tx_rings = ctx->nr_host_tx_rings;
2614f6858e8SVincenzo Maffione req.nr_host_rx_rings = ctx->nr_host_rx_rings;
2622a8682a8SVincenzo Maffione req.nr_rx_rings = ctx->nr_rx_rings;
2632a8682a8SVincenzo Maffione req.nr_extra_bufs = ctx->nr_extra_bufs;
2642a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
2652a8682a8SVincenzo Maffione if (ret != 0) {
2662a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, REGISTER)");
2672a8682a8SVincenzo Maffione return ret;
2682a8682a8SVincenzo Maffione }
2695854d718SVincenzo Maffione printf("nr_offset 0x%llx\n", (unsigned long long)req.nr_offset);
2705854d718SVincenzo Maffione printf("nr_memsize %llu\n", (unsigned long long)req.nr_memsize);
2712a8682a8SVincenzo Maffione printf("nr_tx_slots %u\n", req.nr_tx_slots);
2722a8682a8SVincenzo Maffione printf("nr_rx_slots %u\n", req.nr_rx_slots);
2732a8682a8SVincenzo Maffione printf("nr_tx_rings %u\n", req.nr_tx_rings);
2742a8682a8SVincenzo Maffione printf("nr_rx_rings %u\n", req.nr_rx_rings);
2754f6858e8SVincenzo Maffione printf("nr_host_tx_rings %u\n", req.nr_host_tx_rings);
2764f6858e8SVincenzo Maffione printf("nr_host_rx_rings %u\n", req.nr_host_rx_rings);
2772a8682a8SVincenzo Maffione printf("nr_mem_id %u\n", req.nr_mem_id);
2782a8682a8SVincenzo Maffione printf("nr_extra_bufs %u\n", req.nr_extra_bufs);
2792a8682a8SVincenzo Maffione
2802a8682a8SVincenzo Maffione success = req.nr_memsize && (ctx->nr_mode == req.nr_mode) &&
2812a8682a8SVincenzo Maffione (ctx->nr_ringid == req.nr_ringid) &&
2822a8682a8SVincenzo Maffione (ctx->nr_flags == req.nr_flags) &&
2832a8682a8SVincenzo Maffione ((!ctx->nr_tx_slots && req.nr_tx_slots) ||
2842a8682a8SVincenzo Maffione (ctx->nr_tx_slots == req.nr_tx_slots)) &&
2852a8682a8SVincenzo Maffione ((!ctx->nr_rx_slots && req.nr_rx_slots) ||
2862a8682a8SVincenzo Maffione (ctx->nr_rx_slots == req.nr_rx_slots)) &&
2872a8682a8SVincenzo Maffione ((!ctx->nr_tx_rings && req.nr_tx_rings) ||
2882a8682a8SVincenzo Maffione (ctx->nr_tx_rings == req.nr_tx_rings)) &&
2892a8682a8SVincenzo Maffione ((!ctx->nr_rx_rings && req.nr_rx_rings) ||
2902a8682a8SVincenzo Maffione (ctx->nr_rx_rings == req.nr_rx_rings)) &&
2914f6858e8SVincenzo Maffione ((!ctx->nr_host_tx_rings && req.nr_host_tx_rings) ||
2924f6858e8SVincenzo Maffione (ctx->nr_host_tx_rings == req.nr_host_tx_rings)) &&
2934f6858e8SVincenzo Maffione ((!ctx->nr_host_rx_rings && req.nr_host_rx_rings) ||
2944f6858e8SVincenzo Maffione (ctx->nr_host_rx_rings == req.nr_host_rx_rings)) &&
2952a8682a8SVincenzo Maffione ((!ctx->nr_mem_id && req.nr_mem_id) ||
2962a8682a8SVincenzo Maffione (ctx->nr_mem_id == req.nr_mem_id)) &&
2972a8682a8SVincenzo Maffione (ctx->nr_extra_bufs == req.nr_extra_bufs);
2982a8682a8SVincenzo Maffione if (!success) {
2992a8682a8SVincenzo Maffione return -1;
3002a8682a8SVincenzo Maffione }
3012a8682a8SVincenzo Maffione
3022a8682a8SVincenzo Maffione /* Write back results to the context structure.*/
3032a8682a8SVincenzo Maffione ctx->nr_tx_slots = req.nr_tx_slots;
3042a8682a8SVincenzo Maffione ctx->nr_rx_slots = req.nr_rx_slots;
3052a8682a8SVincenzo Maffione ctx->nr_tx_rings = req.nr_tx_rings;
3062a8682a8SVincenzo Maffione ctx->nr_rx_rings = req.nr_rx_rings;
3074f6858e8SVincenzo Maffione ctx->nr_host_tx_rings = req.nr_host_tx_rings;
3084f6858e8SVincenzo Maffione ctx->nr_host_rx_rings = req.nr_host_rx_rings;
3092a8682a8SVincenzo Maffione ctx->nr_mem_id = req.nr_mem_id;
3102a8682a8SVincenzo Maffione ctx->nr_extra_bufs = req.nr_extra_bufs;
3112a8682a8SVincenzo Maffione
3122a8682a8SVincenzo Maffione return 0;
3132a8682a8SVincenzo Maffione }
3142a8682a8SVincenzo Maffione
3152a8682a8SVincenzo Maffione static int
niocregif(struct TestContext * ctx,int netmap_api)3162a8682a8SVincenzo Maffione niocregif(struct TestContext *ctx, int netmap_api)
3172a8682a8SVincenzo Maffione {
3182a8682a8SVincenzo Maffione struct nmreq req;
3192a8682a8SVincenzo Maffione int success;
3202a8682a8SVincenzo Maffione int ret;
3212a8682a8SVincenzo Maffione
32208f34ad9SVincenzo Maffione printf("Testing legacy NIOCREGIF on '%s'\n", ctx->ifname_ext);
3232a8682a8SVincenzo Maffione
3242a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
32508f34ad9SVincenzo Maffione memcpy(req.nr_name, ctx->ifname_ext, sizeof(req.nr_name));
3262a8682a8SVincenzo Maffione req.nr_name[sizeof(req.nr_name) - 1] = '\0';
3272a8682a8SVincenzo Maffione req.nr_version = netmap_api;
3282a8682a8SVincenzo Maffione req.nr_ringid = ctx->nr_ringid;
3292a8682a8SVincenzo Maffione req.nr_flags = ctx->nr_mode | ctx->nr_flags;
3302a8682a8SVincenzo Maffione req.nr_tx_slots = ctx->nr_tx_slots;
3312a8682a8SVincenzo Maffione req.nr_rx_slots = ctx->nr_rx_slots;
3322a8682a8SVincenzo Maffione req.nr_tx_rings = ctx->nr_tx_rings;
3332a8682a8SVincenzo Maffione req.nr_rx_rings = ctx->nr_rx_rings;
3342a8682a8SVincenzo Maffione req.nr_arg2 = ctx->nr_mem_id;
3352a8682a8SVincenzo Maffione req.nr_arg3 = ctx->nr_extra_bufs;
3362a8682a8SVincenzo Maffione
3372a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCREGIF, &req);
3382a8682a8SVincenzo Maffione if (ret != 0) {
3392a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCREGIF)");
3402a8682a8SVincenzo Maffione return ret;
3412a8682a8SVincenzo Maffione }
3422a8682a8SVincenzo Maffione
3432a8682a8SVincenzo Maffione printf("nr_offset 0x%x\n", req.nr_offset);
3442a8682a8SVincenzo Maffione printf("nr_memsize %u\n", req.nr_memsize);
3452a8682a8SVincenzo Maffione printf("nr_tx_slots %u\n", req.nr_tx_slots);
3462a8682a8SVincenzo Maffione printf("nr_rx_slots %u\n", req.nr_rx_slots);
3472a8682a8SVincenzo Maffione printf("nr_tx_rings %u\n", req.nr_tx_rings);
3482a8682a8SVincenzo Maffione printf("nr_rx_rings %u\n", req.nr_rx_rings);
3492a8682a8SVincenzo Maffione printf("nr_version %d\n", req.nr_version);
3502a8682a8SVincenzo Maffione printf("nr_ringid %x\n", req.nr_ringid);
3512a8682a8SVincenzo Maffione printf("nr_flags %x\n", req.nr_flags);
3522a8682a8SVincenzo Maffione printf("nr_arg2 %u\n", req.nr_arg2);
3532a8682a8SVincenzo Maffione printf("nr_arg3 %u\n", req.nr_arg3);
3542a8682a8SVincenzo Maffione
3552a8682a8SVincenzo Maffione success = req.nr_memsize &&
3562a8682a8SVincenzo Maffione (ctx->nr_ringid == req.nr_ringid) &&
3572a8682a8SVincenzo Maffione ((ctx->nr_mode | ctx->nr_flags) == req.nr_flags) &&
3582a8682a8SVincenzo Maffione ((!ctx->nr_tx_slots && req.nr_tx_slots) ||
3592a8682a8SVincenzo Maffione (ctx->nr_tx_slots == req.nr_tx_slots)) &&
3602a8682a8SVincenzo Maffione ((!ctx->nr_rx_slots && req.nr_rx_slots) ||
3612a8682a8SVincenzo Maffione (ctx->nr_rx_slots == req.nr_rx_slots)) &&
3622a8682a8SVincenzo Maffione ((!ctx->nr_tx_rings && req.nr_tx_rings) ||
3632a8682a8SVincenzo Maffione (ctx->nr_tx_rings == req.nr_tx_rings)) &&
3642a8682a8SVincenzo Maffione ((!ctx->nr_rx_rings && req.nr_rx_rings) ||
3652a8682a8SVincenzo Maffione (ctx->nr_rx_rings == req.nr_rx_rings)) &&
3662a8682a8SVincenzo Maffione ((!ctx->nr_mem_id && req.nr_arg2) ||
3672a8682a8SVincenzo Maffione (ctx->nr_mem_id == req.nr_arg2)) &&
3682a8682a8SVincenzo Maffione (ctx->nr_extra_bufs == req.nr_arg3);
3692a8682a8SVincenzo Maffione if (!success) {
3702a8682a8SVincenzo Maffione return -1;
3712a8682a8SVincenzo Maffione }
3722a8682a8SVincenzo Maffione
3732a8682a8SVincenzo Maffione /* Write back results to the context structure.*/
3742a8682a8SVincenzo Maffione ctx->nr_tx_slots = req.nr_tx_slots;
3752a8682a8SVincenzo Maffione ctx->nr_rx_slots = req.nr_rx_slots;
3762a8682a8SVincenzo Maffione ctx->nr_tx_rings = req.nr_tx_rings;
3772a8682a8SVincenzo Maffione ctx->nr_rx_rings = req.nr_rx_rings;
3782a8682a8SVincenzo Maffione ctx->nr_mem_id = req.nr_arg2;
3792a8682a8SVincenzo Maffione ctx->nr_extra_bufs = req.nr_arg3;
3802a8682a8SVincenzo Maffione
3812a8682a8SVincenzo Maffione return ret;
3822a8682a8SVincenzo Maffione }
3832a8682a8SVincenzo Maffione
3842a8682a8SVincenzo Maffione /* The 11 ABI is the one right before the introduction of the new NIOCCTRL
3852a8682a8SVincenzo Maffione * ABI. The 11 ABI is useful to perform tests with legacy applications
3865e874d26SVincenzo Maffione * (which use the 11 ABI) and new kernel (which uses 12, or higher).
3875e874d26SVincenzo Maffione * However, version 14 introduced a change in the layout of struct netmap_if,
3885e874d26SVincenzo Maffione * so that binary backward compatibility to 11 is not supported anymore.
3895e874d26SVincenzo Maffione */
3905e874d26SVincenzo Maffione #define NETMAP_API_NIOCREGIF 14
3912a8682a8SVincenzo Maffione
3922a8682a8SVincenzo Maffione static int
legacy_regif_default(struct TestContext * ctx)3932a8682a8SVincenzo Maffione legacy_regif_default(struct TestContext *ctx)
3942a8682a8SVincenzo Maffione {
3952a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API_NIOCREGIF);
3962a8682a8SVincenzo Maffione }
3972a8682a8SVincenzo Maffione
3982a8682a8SVincenzo Maffione static int
legacy_regif_all_nic(struct TestContext * ctx)3992a8682a8SVincenzo Maffione legacy_regif_all_nic(struct TestContext *ctx)
4002a8682a8SVincenzo Maffione {
4012a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
4022a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API);
4032a8682a8SVincenzo Maffione }
4042a8682a8SVincenzo Maffione
4052a8682a8SVincenzo Maffione static int
legacy_regif_12(struct TestContext * ctx)4062a8682a8SVincenzo Maffione legacy_regif_12(struct TestContext *ctx)
4072a8682a8SVincenzo Maffione {
4082a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
4092a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API_NIOCREGIF+1);
4102a8682a8SVincenzo Maffione }
4112a8682a8SVincenzo Maffione
4122a8682a8SVincenzo Maffione static int
legacy_regif_sw(struct TestContext * ctx)4132a8682a8SVincenzo Maffione legacy_regif_sw(struct TestContext *ctx)
4142a8682a8SVincenzo Maffione {
4152a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_SW;
4162a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API_NIOCREGIF);
4172a8682a8SVincenzo Maffione }
4182a8682a8SVincenzo Maffione
4192a8682a8SVincenzo Maffione static int
legacy_regif_future(struct TestContext * ctx)4202a8682a8SVincenzo Maffione legacy_regif_future(struct TestContext *ctx)
4212a8682a8SVincenzo Maffione {
4222a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NIC_SW;
4232a8682a8SVincenzo Maffione /* Test forward compatibility for the legacy ABI. This means
4242a8682a8SVincenzo Maffione * using an older kernel (with ABI 12 or higher) and a newer
4252a8682a8SVincenzo Maffione * application (with ABI greater than NETMAP_API). */
4262a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API+2);
4272a8682a8SVincenzo Maffione }
4282a8682a8SVincenzo Maffione
4292a8682a8SVincenzo Maffione static int
legacy_regif_extra_bufs(struct TestContext * ctx)4302a8682a8SVincenzo Maffione legacy_regif_extra_bufs(struct TestContext *ctx)
4312a8682a8SVincenzo Maffione {
4322a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
4332a8682a8SVincenzo Maffione ctx->nr_extra_bufs = 20; /* arbitrary number of extra bufs */
4342a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API_NIOCREGIF);
4352a8682a8SVincenzo Maffione }
4362a8682a8SVincenzo Maffione
4372a8682a8SVincenzo Maffione static int
legacy_regif_extra_bufs_pipe(struct TestContext * ctx)4382a8682a8SVincenzo Maffione legacy_regif_extra_bufs_pipe(struct TestContext *ctx)
4392a8682a8SVincenzo Maffione {
44008f34ad9SVincenzo Maffione strncat(ctx->ifname_ext, "{pipeexbuf", sizeof(ctx->ifname_ext));
4412a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
4422a8682a8SVincenzo Maffione ctx->nr_extra_bufs = 58; /* arbitrary number of extra bufs */
4432a8682a8SVincenzo Maffione
4442a8682a8SVincenzo Maffione return niocregif(ctx, NETMAP_API_NIOCREGIF);
4452a8682a8SVincenzo Maffione }
4462a8682a8SVincenzo Maffione
4472a8682a8SVincenzo Maffione static int
legacy_regif_extra_bufs_pipe_vale(struct TestContext * ctx)4482a8682a8SVincenzo Maffione legacy_regif_extra_bufs_pipe_vale(struct TestContext *ctx)
4492a8682a8SVincenzo Maffione {
45008f34ad9SVincenzo Maffione strncpy(ctx->ifname_ext, "valeX1:Y4", sizeof(ctx->ifname_ext));
4512a8682a8SVincenzo Maffione return legacy_regif_extra_bufs_pipe(ctx);
4522a8682a8SVincenzo Maffione }
4532a8682a8SVincenzo Maffione
4542a8682a8SVincenzo Maffione /* Only valid after a successful port_register(). */
4552a8682a8SVincenzo Maffione static int
num_registered_rings(struct TestContext * ctx)4562a8682a8SVincenzo Maffione num_registered_rings(struct TestContext *ctx)
4572a8682a8SVincenzo Maffione {
4582a8682a8SVincenzo Maffione if (ctx->nr_flags & NR_TX_RINGS_ONLY) {
4592a8682a8SVincenzo Maffione return ctx->nr_tx_rings;
4602a8682a8SVincenzo Maffione }
4612a8682a8SVincenzo Maffione if (ctx->nr_flags & NR_RX_RINGS_ONLY) {
4622a8682a8SVincenzo Maffione return ctx->nr_rx_rings;
4632a8682a8SVincenzo Maffione }
4642a8682a8SVincenzo Maffione
4652a8682a8SVincenzo Maffione return ctx->nr_tx_rings + ctx->nr_rx_rings;
4662a8682a8SVincenzo Maffione }
4672a8682a8SVincenzo Maffione
4682a8682a8SVincenzo Maffione static int
port_register_hwall_host(struct TestContext * ctx)4692a8682a8SVincenzo Maffione port_register_hwall_host(struct TestContext *ctx)
4702a8682a8SVincenzo Maffione {
4712a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NIC_SW;
4722a8682a8SVincenzo Maffione return port_register(ctx);
4732a8682a8SVincenzo Maffione }
4742a8682a8SVincenzo Maffione
4752a8682a8SVincenzo Maffione static int
port_register_hostall(struct TestContext * ctx)4764f6858e8SVincenzo Maffione port_register_hostall(struct TestContext *ctx)
4772a8682a8SVincenzo Maffione {
4782a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_SW;
4792a8682a8SVincenzo Maffione return port_register(ctx);
4802a8682a8SVincenzo Maffione }
4812a8682a8SVincenzo Maffione
4822a8682a8SVincenzo Maffione static int
port_register_hwall(struct TestContext * ctx)4832a8682a8SVincenzo Maffione port_register_hwall(struct TestContext *ctx)
4842a8682a8SVincenzo Maffione {
4852a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
4862a8682a8SVincenzo Maffione return port_register(ctx);
4872a8682a8SVincenzo Maffione }
4882a8682a8SVincenzo Maffione
4892a8682a8SVincenzo Maffione static int
port_register_single_hw_pair(struct TestContext * ctx)4904f6858e8SVincenzo Maffione port_register_single_hw_pair(struct TestContext *ctx)
4912a8682a8SVincenzo Maffione {
4922a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ONE_NIC;
4932a8682a8SVincenzo Maffione ctx->nr_ringid = 0;
4942a8682a8SVincenzo Maffione return port_register(ctx);
4952a8682a8SVincenzo Maffione }
4962a8682a8SVincenzo Maffione
4972a8682a8SVincenzo Maffione static int
port_register_single_host_pair(struct TestContext * ctx)4984f6858e8SVincenzo Maffione port_register_single_host_pair(struct TestContext *ctx)
4994f6858e8SVincenzo Maffione {
5004f6858e8SVincenzo Maffione ctx->nr_mode = NR_REG_ONE_SW;
5014f6858e8SVincenzo Maffione ctx->nr_host_tx_rings = 2;
5024f6858e8SVincenzo Maffione ctx->nr_host_rx_rings = 2;
5034f6858e8SVincenzo Maffione ctx->nr_ringid = 1;
5044f6858e8SVincenzo Maffione return port_register(ctx);
5054f6858e8SVincenzo Maffione }
5064f6858e8SVincenzo Maffione
5074f6858e8SVincenzo Maffione static int
port_register_hostall_many(struct TestContext * ctx)5084f6858e8SVincenzo Maffione port_register_hostall_many(struct TestContext *ctx)
5094f6858e8SVincenzo Maffione {
5104f6858e8SVincenzo Maffione ctx->nr_mode = NR_REG_SW;
5114f6858e8SVincenzo Maffione ctx->nr_host_tx_rings = 5;
5124f6858e8SVincenzo Maffione ctx->nr_host_rx_rings = 4;
5134f6858e8SVincenzo Maffione return port_register(ctx);
5144f6858e8SVincenzo Maffione }
5154f6858e8SVincenzo Maffione
5164f6858e8SVincenzo Maffione static int
port_register_hwall_tx(struct TestContext * ctx)5172a8682a8SVincenzo Maffione port_register_hwall_tx(struct TestContext *ctx)
5182a8682a8SVincenzo Maffione {
5192a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
5202a8682a8SVincenzo Maffione ctx->nr_flags |= NR_TX_RINGS_ONLY;
5212a8682a8SVincenzo Maffione return port_register(ctx);
5222a8682a8SVincenzo Maffione }
5232a8682a8SVincenzo Maffione
5242a8682a8SVincenzo Maffione static int
port_register_hwall_rx(struct TestContext * ctx)5252a8682a8SVincenzo Maffione port_register_hwall_rx(struct TestContext *ctx)
5262a8682a8SVincenzo Maffione {
5272a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
5282a8682a8SVincenzo Maffione ctx->nr_flags |= NR_RX_RINGS_ONLY;
5292a8682a8SVincenzo Maffione return port_register(ctx);
5302a8682a8SVincenzo Maffione }
5312a8682a8SVincenzo Maffione
53236d6e657SVincenzo Maffione
53336d6e657SVincenzo Maffione static int
vale_mkname(char * vpname,struct TestContext * ctx)53436d6e657SVincenzo Maffione vale_mkname(char *vpname, struct TestContext *ctx)
53536d6e657SVincenzo Maffione {
53636d6e657SVincenzo Maffione if (snprintf(vpname, NM_IFNAMSZ, "%s:%s", ctx->bdgname, ctx->ifname_ext) >= NM_IFNAMSZ) {
53736d6e657SVincenzo Maffione fprintf(stderr, "%s:%s too long (max %d chars)\n", ctx->bdgname, ctx->ifname_ext,
53836d6e657SVincenzo Maffione NM_IFNAMSZ - 1);
53936d6e657SVincenzo Maffione return -1;
54036d6e657SVincenzo Maffione }
54136d6e657SVincenzo Maffione return 0;
54236d6e657SVincenzo Maffione }
54336d6e657SVincenzo Maffione
54436d6e657SVincenzo Maffione
5452a8682a8SVincenzo Maffione /* NETMAP_REQ_VALE_ATTACH */
5462a8682a8SVincenzo Maffione static int
vale_attach(struct TestContext * ctx)5472a8682a8SVincenzo Maffione vale_attach(struct TestContext *ctx)
5482a8682a8SVincenzo Maffione {
5492a8682a8SVincenzo Maffione struct nmreq_vale_attach req;
5502a8682a8SVincenzo Maffione struct nmreq_header hdr;
55136d6e657SVincenzo Maffione char vpname[NM_IFNAMSZ];
5522a8682a8SVincenzo Maffione int ret;
5532a8682a8SVincenzo Maffione
55436d6e657SVincenzo Maffione if (vale_mkname(vpname, ctx) < 0)
55536d6e657SVincenzo Maffione return -1;
5562a8682a8SVincenzo Maffione
5572a8682a8SVincenzo Maffione printf("Testing NETMAP_REQ_VALE_ATTACH on '%s'\n", vpname);
5582a8682a8SVincenzo Maffione nmreq_hdr_init(&hdr, vpname);
5592a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_VALE_ATTACH;
5602a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
5612a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
5622a8682a8SVincenzo Maffione req.reg.nr_mem_id = ctx->nr_mem_id;
5632a8682a8SVincenzo Maffione if (ctx->nr_mode == 0) {
5642a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC; /* default */
5652a8682a8SVincenzo Maffione }
5662a8682a8SVincenzo Maffione req.reg.nr_mode = ctx->nr_mode;
5672a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
5682a8682a8SVincenzo Maffione if (ret != 0) {
5692a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, VALE_ATTACH)");
5702a8682a8SVincenzo Maffione return ret;
5712a8682a8SVincenzo Maffione }
5722a8682a8SVincenzo Maffione printf("nr_mem_id %u\n", req.reg.nr_mem_id);
5732a8682a8SVincenzo Maffione
5742a8682a8SVincenzo Maffione return ((!ctx->nr_mem_id && req.reg.nr_mem_id > 1) ||
5752a8682a8SVincenzo Maffione (ctx->nr_mem_id == req.reg.nr_mem_id)) &&
5762a8682a8SVincenzo Maffione (ctx->nr_flags == req.reg.nr_flags)
5772a8682a8SVincenzo Maffione ? 0
5782a8682a8SVincenzo Maffione : -1;
5792a8682a8SVincenzo Maffione }
5802a8682a8SVincenzo Maffione
5812a8682a8SVincenzo Maffione /* NETMAP_REQ_VALE_DETACH */
5822a8682a8SVincenzo Maffione static int
vale_detach(struct TestContext * ctx)5832a8682a8SVincenzo Maffione vale_detach(struct TestContext *ctx)
5842a8682a8SVincenzo Maffione {
5852a8682a8SVincenzo Maffione struct nmreq_header hdr;
5862a8682a8SVincenzo Maffione struct nmreq_vale_detach req;
58736d6e657SVincenzo Maffione char vpname[NM_IFNAMSZ];
5882a8682a8SVincenzo Maffione int ret;
5892a8682a8SVincenzo Maffione
59036d6e657SVincenzo Maffione if (vale_mkname(vpname, ctx) < 0)
59136d6e657SVincenzo Maffione return -1;
5922a8682a8SVincenzo Maffione
5932a8682a8SVincenzo Maffione printf("Testing NETMAP_REQ_VALE_DETACH on '%s'\n", vpname);
5942a8682a8SVincenzo Maffione nmreq_hdr_init(&hdr, vpname);
5952a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_VALE_DETACH;
5962a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
5972a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
5982a8682a8SVincenzo Maffione if (ret != 0) {
5992a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, VALE_DETACH)");
6002a8682a8SVincenzo Maffione return ret;
6012a8682a8SVincenzo Maffione }
6022a8682a8SVincenzo Maffione
6032a8682a8SVincenzo Maffione return 0;
6042a8682a8SVincenzo Maffione }
6052a8682a8SVincenzo Maffione
6062a8682a8SVincenzo Maffione /* First NETMAP_REQ_VALE_ATTACH, then NETMAP_REQ_VALE_DETACH. */
6072a8682a8SVincenzo Maffione static int
vale_attach_detach(struct TestContext * ctx)6082a8682a8SVincenzo Maffione vale_attach_detach(struct TestContext *ctx)
6092a8682a8SVincenzo Maffione {
6102a8682a8SVincenzo Maffione int ret;
6112a8682a8SVincenzo Maffione
6122a8682a8SVincenzo Maffione if ((ret = vale_attach(ctx)) != 0) {
6132a8682a8SVincenzo Maffione return ret;
6142a8682a8SVincenzo Maffione }
6152a8682a8SVincenzo Maffione
6162a8682a8SVincenzo Maffione return vale_detach(ctx);
6172a8682a8SVincenzo Maffione }
6182a8682a8SVincenzo Maffione
6192a8682a8SVincenzo Maffione static int
vale_attach_detach_host_rings(struct TestContext * ctx)6202a8682a8SVincenzo Maffione vale_attach_detach_host_rings(struct TestContext *ctx)
6212a8682a8SVincenzo Maffione {
6222a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NIC_SW;
6232a8682a8SVincenzo Maffione return vale_attach_detach(ctx);
6242a8682a8SVincenzo Maffione }
6252a8682a8SVincenzo Maffione
6262a8682a8SVincenzo Maffione /* First NETMAP_REQ_PORT_HDR_SET and the NETMAP_REQ_PORT_HDR_GET
6272a8682a8SVincenzo Maffione * to check that we get the same value. */
6282a8682a8SVincenzo Maffione static int
port_hdr_set_and_get(struct TestContext * ctx)6292a8682a8SVincenzo Maffione port_hdr_set_and_get(struct TestContext *ctx)
6302a8682a8SVincenzo Maffione {
6312a8682a8SVincenzo Maffione struct nmreq_port_hdr req;
6322a8682a8SVincenzo Maffione struct nmreq_header hdr;
6332a8682a8SVincenzo Maffione int ret;
6342a8682a8SVincenzo Maffione
63508f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_PORT_HDR_SET on '%s'\n", ctx->ifname_ext);
6362a8682a8SVincenzo Maffione
63708f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
6382a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_PORT_HDR_SET;
6392a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
6402a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
6412a8682a8SVincenzo Maffione req.nr_hdr_len = ctx->nr_hdr_len;
6422a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
6432a8682a8SVincenzo Maffione if (ret != 0) {
6442a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, PORT_HDR_SET)");
6452a8682a8SVincenzo Maffione return ret;
6462a8682a8SVincenzo Maffione }
6472a8682a8SVincenzo Maffione
6482a8682a8SVincenzo Maffione if (req.nr_hdr_len != ctx->nr_hdr_len) {
6492a8682a8SVincenzo Maffione return -1;
6502a8682a8SVincenzo Maffione }
6512a8682a8SVincenzo Maffione
65208f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_PORT_HDR_GET on '%s'\n", ctx->ifname_ext);
6532a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_PORT_HDR_GET;
6542a8682a8SVincenzo Maffione req.nr_hdr_len = 0;
6552a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
6562a8682a8SVincenzo Maffione if (ret != 0) {
6572a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, PORT_HDR_SET)");
6582a8682a8SVincenzo Maffione return ret;
6592a8682a8SVincenzo Maffione }
6602a8682a8SVincenzo Maffione printf("nr_hdr_len %u\n", req.nr_hdr_len);
6612a8682a8SVincenzo Maffione
6622a8682a8SVincenzo Maffione return (req.nr_hdr_len == ctx->nr_hdr_len) ? 0 : -1;
6632a8682a8SVincenzo Maffione }
6642a8682a8SVincenzo Maffione
6652a8682a8SVincenzo Maffione /*
6662a8682a8SVincenzo Maffione * Possible lengths for the VirtIO network header, as specified by
6672a8682a8SVincenzo Maffione * the standard:
6682a8682a8SVincenzo Maffione * http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html
6692a8682a8SVincenzo Maffione */
6702a8682a8SVincenzo Maffione #define VIRTIO_NET_HDR_LEN 10
6712a8682a8SVincenzo Maffione #define VIRTIO_NET_HDR_LEN_WITH_MERGEABLE_RXBUFS 12
6722a8682a8SVincenzo Maffione
6732a8682a8SVincenzo Maffione static int
vale_ephemeral_port_hdr_manipulation(struct TestContext * ctx)6742a8682a8SVincenzo Maffione vale_ephemeral_port_hdr_manipulation(struct TestContext *ctx)
6752a8682a8SVincenzo Maffione {
6762a8682a8SVincenzo Maffione int ret;
6772a8682a8SVincenzo Maffione
67808f34ad9SVincenzo Maffione strncpy(ctx->ifname_ext, "vale:eph0", sizeof(ctx->ifname_ext));
6792a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
6802a8682a8SVincenzo Maffione if ((ret = port_register(ctx))) {
6812a8682a8SVincenzo Maffione return ret;
6822a8682a8SVincenzo Maffione }
6832a8682a8SVincenzo Maffione /* Try to set and get all the acceptable values. */
6842a8682a8SVincenzo Maffione ctx->nr_hdr_len = VIRTIO_NET_HDR_LEN_WITH_MERGEABLE_RXBUFS;
6852a8682a8SVincenzo Maffione if ((ret = port_hdr_set_and_get(ctx))) {
6862a8682a8SVincenzo Maffione return ret;
6872a8682a8SVincenzo Maffione }
6882a8682a8SVincenzo Maffione ctx->nr_hdr_len = 0;
6892a8682a8SVincenzo Maffione if ((ret = port_hdr_set_and_get(ctx))) {
6902a8682a8SVincenzo Maffione return ret;
6912a8682a8SVincenzo Maffione }
6922a8682a8SVincenzo Maffione ctx->nr_hdr_len = VIRTIO_NET_HDR_LEN;
6932a8682a8SVincenzo Maffione if ((ret = port_hdr_set_and_get(ctx))) {
6942a8682a8SVincenzo Maffione return ret;
6952a8682a8SVincenzo Maffione }
6962a8682a8SVincenzo Maffione return 0;
6972a8682a8SVincenzo Maffione }
6982a8682a8SVincenzo Maffione
6992a8682a8SVincenzo Maffione static int
vale_persistent_port(struct TestContext * ctx)7002a8682a8SVincenzo Maffione vale_persistent_port(struct TestContext *ctx)
7012a8682a8SVincenzo Maffione {
7022a8682a8SVincenzo Maffione struct nmreq_vale_newif req;
7032a8682a8SVincenzo Maffione struct nmreq_header hdr;
7042a8682a8SVincenzo Maffione int result;
7052a8682a8SVincenzo Maffione int ret;
7062a8682a8SVincenzo Maffione
70708f34ad9SVincenzo Maffione strncpy(ctx->ifname_ext, "per4", sizeof(ctx->ifname_ext));
7082a8682a8SVincenzo Maffione
70908f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_VALE_NEWIF on '%s'\n", ctx->ifname_ext);
7102a8682a8SVincenzo Maffione
71108f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
7122a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_VALE_NEWIF;
7132a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
7142a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
7152a8682a8SVincenzo Maffione req.nr_mem_id = ctx->nr_mem_id;
7162a8682a8SVincenzo Maffione req.nr_tx_slots = ctx->nr_tx_slots;
7172a8682a8SVincenzo Maffione req.nr_rx_slots = ctx->nr_rx_slots;
7182a8682a8SVincenzo Maffione req.nr_tx_rings = ctx->nr_tx_rings;
7192a8682a8SVincenzo Maffione req.nr_rx_rings = ctx->nr_rx_rings;
7202a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
7212a8682a8SVincenzo Maffione if (ret != 0) {
7222a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, VALE_NEWIF)");
7232a8682a8SVincenzo Maffione return ret;
7242a8682a8SVincenzo Maffione }
7252a8682a8SVincenzo Maffione
7262a8682a8SVincenzo Maffione /* Attach the persistent VALE port to a switch and then detach. */
7272a8682a8SVincenzo Maffione result = vale_attach_detach(ctx);
7282a8682a8SVincenzo Maffione
72908f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_VALE_DELIF on '%s'\n", ctx->ifname_ext);
7302a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_VALE_DELIF;
7312a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)NULL;
7322a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
7332a8682a8SVincenzo Maffione if (ret != 0) {
7342a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, VALE_NEWIF)");
7352a8682a8SVincenzo Maffione if (result == 0) {
7362a8682a8SVincenzo Maffione result = ret;
7372a8682a8SVincenzo Maffione }
7382a8682a8SVincenzo Maffione }
7392a8682a8SVincenzo Maffione
7402a8682a8SVincenzo Maffione return result;
7412a8682a8SVincenzo Maffione }
7422a8682a8SVincenzo Maffione
7432a8682a8SVincenzo Maffione /* Single NETMAP_REQ_POOLS_INFO_GET. */
7442a8682a8SVincenzo Maffione static int
pools_info_get(struct TestContext * ctx)7452a8682a8SVincenzo Maffione pools_info_get(struct TestContext *ctx)
7462a8682a8SVincenzo Maffione {
7472a8682a8SVincenzo Maffione struct nmreq_pools_info req;
7482a8682a8SVincenzo Maffione struct nmreq_header hdr;
7492a8682a8SVincenzo Maffione int ret;
7502a8682a8SVincenzo Maffione
75108f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_POOLS_INFO_GET on '%s'\n", ctx->ifname_ext);
7522a8682a8SVincenzo Maffione
75308f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
7542a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_POOLS_INFO_GET;
7552a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
7562a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
7572a8682a8SVincenzo Maffione req.nr_mem_id = ctx->nr_mem_id;
7582a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
7592a8682a8SVincenzo Maffione if (ret != 0) {
7602a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, POOLS_INFO_GET)");
7612a8682a8SVincenzo Maffione return ret;
7622a8682a8SVincenzo Maffione }
7635854d718SVincenzo Maffione printf("nr_memsize %llu\n", (unsigned long long)req.nr_memsize);
7642a8682a8SVincenzo Maffione printf("nr_mem_id %u\n", req.nr_mem_id);
7655854d718SVincenzo Maffione printf("nr_if_pool_offset 0x%llx\n",
7665854d718SVincenzo Maffione (unsigned long long)req.nr_if_pool_offset);
7672a8682a8SVincenzo Maffione printf("nr_if_pool_objtotal %u\n", req.nr_if_pool_objtotal);
7682a8682a8SVincenzo Maffione printf("nr_if_pool_objsize %u\n", req.nr_if_pool_objsize);
7695854d718SVincenzo Maffione printf("nr_ring_pool_offset 0x%llx\n",
7705854d718SVincenzo Maffione (unsigned long long)req.nr_if_pool_offset);
7712a8682a8SVincenzo Maffione printf("nr_ring_pool_objtotal %u\n", req.nr_ring_pool_objtotal);
7722a8682a8SVincenzo Maffione printf("nr_ring_pool_objsize %u\n", req.nr_ring_pool_objsize);
7735854d718SVincenzo Maffione printf("nr_buf_pool_offset 0x%llx\n",
7745854d718SVincenzo Maffione (unsigned long long)req.nr_buf_pool_offset);
7752a8682a8SVincenzo Maffione printf("nr_buf_pool_objtotal %u\n", req.nr_buf_pool_objtotal);
7762a8682a8SVincenzo Maffione printf("nr_buf_pool_objsize %u\n", req.nr_buf_pool_objsize);
7772a8682a8SVincenzo Maffione
7782a8682a8SVincenzo Maffione return req.nr_memsize && req.nr_if_pool_objtotal &&
7792a8682a8SVincenzo Maffione req.nr_if_pool_objsize &&
7802a8682a8SVincenzo Maffione req.nr_ring_pool_objtotal &&
7812a8682a8SVincenzo Maffione req.nr_ring_pool_objsize &&
7822a8682a8SVincenzo Maffione req.nr_buf_pool_objtotal &&
7832a8682a8SVincenzo Maffione req.nr_buf_pool_objsize
7842a8682a8SVincenzo Maffione ? 0
7852a8682a8SVincenzo Maffione : -1;
7862a8682a8SVincenzo Maffione }
7872a8682a8SVincenzo Maffione
7882a8682a8SVincenzo Maffione static int
pools_info_get_and_register(struct TestContext * ctx)7892a8682a8SVincenzo Maffione pools_info_get_and_register(struct TestContext *ctx)
7902a8682a8SVincenzo Maffione {
7912a8682a8SVincenzo Maffione int ret;
7922a8682a8SVincenzo Maffione
7932a8682a8SVincenzo Maffione /* Check that we can get pools info before we register
7942a8682a8SVincenzo Maffione * a netmap interface. */
7952a8682a8SVincenzo Maffione ret = pools_info_get(ctx);
7962a8682a8SVincenzo Maffione if (ret != 0) {
7972a8682a8SVincenzo Maffione return ret;
7982a8682a8SVincenzo Maffione }
7992a8682a8SVincenzo Maffione
8002a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ONE_NIC;
8012a8682a8SVincenzo Maffione ret = port_register(ctx);
8022a8682a8SVincenzo Maffione if (ret != 0) {
8032a8682a8SVincenzo Maffione return ret;
8042a8682a8SVincenzo Maffione }
8052a8682a8SVincenzo Maffione ctx->nr_mem_id = 1;
8062a8682a8SVincenzo Maffione
8072a8682a8SVincenzo Maffione /* Check that we can get pools info also after we register. */
8082a8682a8SVincenzo Maffione return pools_info_get(ctx);
8092a8682a8SVincenzo Maffione }
8102a8682a8SVincenzo Maffione
8112a8682a8SVincenzo Maffione static int
pools_info_get_empty_ifname(struct TestContext * ctx)8122a8682a8SVincenzo Maffione pools_info_get_empty_ifname(struct TestContext *ctx)
8132a8682a8SVincenzo Maffione {
81408f34ad9SVincenzo Maffione strncpy(ctx->ifname_ext, "", sizeof(ctx->ifname_ext));
8152a8682a8SVincenzo Maffione return pools_info_get(ctx) != 0 ? 0 : -1;
8162a8682a8SVincenzo Maffione }
8172a8682a8SVincenzo Maffione
8182a8682a8SVincenzo Maffione static int
pipe_master(struct TestContext * ctx)8192a8682a8SVincenzo Maffione pipe_master(struct TestContext *ctx)
8202a8682a8SVincenzo Maffione {
82108f34ad9SVincenzo Maffione strncat(ctx->ifname_ext, "{pipeid1", sizeof(ctx->ifname_ext));
8222a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NIC_SW;
8232a8682a8SVincenzo Maffione
8242a8682a8SVincenzo Maffione if (port_register(ctx) == 0) {
8252a8682a8SVincenzo Maffione printf("pipes should not accept NR_REG_NIC_SW\n");
8262a8682a8SVincenzo Maffione return -1;
8272a8682a8SVincenzo Maffione }
8282a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
8292a8682a8SVincenzo Maffione
8302a8682a8SVincenzo Maffione return port_register(ctx);
8312a8682a8SVincenzo Maffione }
8322a8682a8SVincenzo Maffione
8332a8682a8SVincenzo Maffione static int
pipe_slave(struct TestContext * ctx)8342a8682a8SVincenzo Maffione pipe_slave(struct TestContext *ctx)
8352a8682a8SVincenzo Maffione {
83608f34ad9SVincenzo Maffione strncat(ctx->ifname_ext, "}pipeid2", sizeof(ctx->ifname_ext));
8372a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_ALL_NIC;
8382a8682a8SVincenzo Maffione
8392a8682a8SVincenzo Maffione return port_register(ctx);
8402a8682a8SVincenzo Maffione }
8412a8682a8SVincenzo Maffione
8422a8682a8SVincenzo Maffione /* Test PORT_INFO_GET and POOLS_INFO_GET on a pipe. This is useful to test the
84336d6e657SVincenzo Maffione * registration request used internally by netmap. */
8442a8682a8SVincenzo Maffione static int
pipe_port_info_get(struct TestContext * ctx)8452a8682a8SVincenzo Maffione pipe_port_info_get(struct TestContext *ctx)
8462a8682a8SVincenzo Maffione {
84708f34ad9SVincenzo Maffione strncat(ctx->ifname_ext, "}pipeid3", sizeof(ctx->ifname_ext));
8482a8682a8SVincenzo Maffione
8492a8682a8SVincenzo Maffione return port_info_get(ctx);
8502a8682a8SVincenzo Maffione }
8512a8682a8SVincenzo Maffione
8522a8682a8SVincenzo Maffione static int
pipe_pools_info_get(struct TestContext * ctx)8532a8682a8SVincenzo Maffione pipe_pools_info_get(struct TestContext *ctx)
8542a8682a8SVincenzo Maffione {
85508f34ad9SVincenzo Maffione strncat(ctx->ifname_ext, "{xid", sizeof(ctx->ifname_ext));
8562a8682a8SVincenzo Maffione
8572a8682a8SVincenzo Maffione return pools_info_get(ctx);
8582a8682a8SVincenzo Maffione }
8592a8682a8SVincenzo Maffione
8602a8682a8SVincenzo Maffione /* NETMAP_REQ_VALE_POLLING_ENABLE */
8612a8682a8SVincenzo Maffione static int
vale_polling_enable(struct TestContext * ctx)8622a8682a8SVincenzo Maffione vale_polling_enable(struct TestContext *ctx)
8632a8682a8SVincenzo Maffione {
8642a8682a8SVincenzo Maffione struct nmreq_vale_polling req;
8652a8682a8SVincenzo Maffione struct nmreq_header hdr;
86636d6e657SVincenzo Maffione char vpname[NM_IFNAMSZ];
8672a8682a8SVincenzo Maffione int ret;
8682a8682a8SVincenzo Maffione
86936d6e657SVincenzo Maffione if (vale_mkname(vpname, ctx) < 0)
87036d6e657SVincenzo Maffione return -1;
87136d6e657SVincenzo Maffione
8722a8682a8SVincenzo Maffione printf("Testing NETMAP_REQ_VALE_POLLING_ENABLE on '%s'\n", vpname);
8732a8682a8SVincenzo Maffione
8742a8682a8SVincenzo Maffione nmreq_hdr_init(&hdr, vpname);
8752a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_VALE_POLLING_ENABLE;
8762a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
8772a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
8782a8682a8SVincenzo Maffione req.nr_mode = ctx->nr_mode;
8792a8682a8SVincenzo Maffione req.nr_first_cpu_id = ctx->nr_first_cpu_id;
8802a8682a8SVincenzo Maffione req.nr_num_polling_cpus = ctx->nr_num_polling_cpus;
8812a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
8822a8682a8SVincenzo Maffione if (ret != 0) {
8832a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, VALE_POLLING_ENABLE)");
8842a8682a8SVincenzo Maffione return ret;
8852a8682a8SVincenzo Maffione }
8862a8682a8SVincenzo Maffione
8872a8682a8SVincenzo Maffione return (req.nr_mode == ctx->nr_mode &&
8882a8682a8SVincenzo Maffione req.nr_first_cpu_id == ctx->nr_first_cpu_id &&
8892a8682a8SVincenzo Maffione req.nr_num_polling_cpus == ctx->nr_num_polling_cpus)
8902a8682a8SVincenzo Maffione ? 0
8912a8682a8SVincenzo Maffione : -1;
8922a8682a8SVincenzo Maffione }
8932a8682a8SVincenzo Maffione
8942a8682a8SVincenzo Maffione /* NETMAP_REQ_VALE_POLLING_DISABLE */
8952a8682a8SVincenzo Maffione static int
vale_polling_disable(struct TestContext * ctx)8962a8682a8SVincenzo Maffione vale_polling_disable(struct TestContext *ctx)
8972a8682a8SVincenzo Maffione {
8982a8682a8SVincenzo Maffione struct nmreq_vale_polling req;
8992a8682a8SVincenzo Maffione struct nmreq_header hdr;
90036d6e657SVincenzo Maffione char vpname[NM_IFNAMSZ];
9012a8682a8SVincenzo Maffione int ret;
9022a8682a8SVincenzo Maffione
90336d6e657SVincenzo Maffione if (vale_mkname(vpname, ctx) < 0)
90436d6e657SVincenzo Maffione return -1;
90536d6e657SVincenzo Maffione
9062a8682a8SVincenzo Maffione printf("Testing NETMAP_REQ_VALE_POLLING_DISABLE on '%s'\n", vpname);
9072a8682a8SVincenzo Maffione
9082a8682a8SVincenzo Maffione nmreq_hdr_init(&hdr, vpname);
9092a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_VALE_POLLING_DISABLE;
9102a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
9112a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
9122a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
9132a8682a8SVincenzo Maffione if (ret != 0) {
9142a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, VALE_POLLING_DISABLE)");
9152a8682a8SVincenzo Maffione return ret;
9162a8682a8SVincenzo Maffione }
9172a8682a8SVincenzo Maffione
9182a8682a8SVincenzo Maffione return 0;
9192a8682a8SVincenzo Maffione }
9202a8682a8SVincenzo Maffione
9212a8682a8SVincenzo Maffione static int
vale_polling_enable_disable(struct TestContext * ctx)9222a8682a8SVincenzo Maffione vale_polling_enable_disable(struct TestContext *ctx)
9232a8682a8SVincenzo Maffione {
9242a8682a8SVincenzo Maffione int ret = 0;
9252a8682a8SVincenzo Maffione
9262a8682a8SVincenzo Maffione if ((ret = vale_attach(ctx)) != 0) {
9272a8682a8SVincenzo Maffione return ret;
9282a8682a8SVincenzo Maffione }
9292a8682a8SVincenzo Maffione
9302a8682a8SVincenzo Maffione ctx->nr_mode = NETMAP_POLLING_MODE_SINGLE_CPU;
9312a8682a8SVincenzo Maffione ctx->nr_num_polling_cpus = 1;
9322a8682a8SVincenzo Maffione ctx->nr_first_cpu_id = 0;
9332a8682a8SVincenzo Maffione if ((ret = vale_polling_enable(ctx))) {
9342a8682a8SVincenzo Maffione vale_detach(ctx);
9352a8682a8SVincenzo Maffione #ifdef __FreeBSD__
9362a8682a8SVincenzo Maffione /* NETMAP_REQ_VALE_POLLING_DISABLE is disabled on FreeBSD,
9372a8682a8SVincenzo Maffione * because it is currently broken. We are happy to see that
9382a8682a8SVincenzo Maffione * it fails. */
9392a8682a8SVincenzo Maffione return 0;
94008f34ad9SVincenzo Maffione #else
9412a8682a8SVincenzo Maffione return ret;
94208f34ad9SVincenzo Maffione #endif
9432a8682a8SVincenzo Maffione }
9442a8682a8SVincenzo Maffione
9452a8682a8SVincenzo Maffione if ((ret = vale_polling_disable(ctx))) {
9462a8682a8SVincenzo Maffione vale_detach(ctx);
9472a8682a8SVincenzo Maffione return ret;
9482a8682a8SVincenzo Maffione }
9492a8682a8SVincenzo Maffione
9502a8682a8SVincenzo Maffione return vale_detach(ctx);
9512a8682a8SVincenzo Maffione }
9522a8682a8SVincenzo Maffione
9532a8682a8SVincenzo Maffione static void
push_option(struct nmreq_option * opt,struct TestContext * ctx)9542a8682a8SVincenzo Maffione push_option(struct nmreq_option *opt, struct TestContext *ctx)
9552a8682a8SVincenzo Maffione {
9562a8682a8SVincenzo Maffione opt->nro_next = (uintptr_t)ctx->nr_opt;
9572a8682a8SVincenzo Maffione ctx->nr_opt = opt;
9582a8682a8SVincenzo Maffione }
9592a8682a8SVincenzo Maffione
9602a8682a8SVincenzo Maffione static void
clear_options(struct TestContext * ctx)9612a8682a8SVincenzo Maffione clear_options(struct TestContext *ctx)
9622a8682a8SVincenzo Maffione {
9632a8682a8SVincenzo Maffione ctx->nr_opt = NULL;
9642a8682a8SVincenzo Maffione }
9652a8682a8SVincenzo Maffione
9662a8682a8SVincenzo Maffione static int
checkoption(struct nmreq_option * opt,struct nmreq_option * exp)9672a8682a8SVincenzo Maffione checkoption(struct nmreq_option *opt, struct nmreq_option *exp)
9682a8682a8SVincenzo Maffione {
9692a8682a8SVincenzo Maffione if (opt->nro_next != exp->nro_next) {
9702a8682a8SVincenzo Maffione printf("nro_next %p expected %p\n",
9712a8682a8SVincenzo Maffione (void *)(uintptr_t)opt->nro_next,
9722a8682a8SVincenzo Maffione (void *)(uintptr_t)exp->nro_next);
9732a8682a8SVincenzo Maffione return -1;
9742a8682a8SVincenzo Maffione }
9752a8682a8SVincenzo Maffione if (opt->nro_reqtype != exp->nro_reqtype) {
9762a8682a8SVincenzo Maffione printf("nro_reqtype %u expected %u\n", opt->nro_reqtype,
9772a8682a8SVincenzo Maffione exp->nro_reqtype);
9782a8682a8SVincenzo Maffione return -1;
9792a8682a8SVincenzo Maffione }
9802a8682a8SVincenzo Maffione if (opt->nro_status != exp->nro_status) {
9812a8682a8SVincenzo Maffione printf("nro_status %u expected %u\n", opt->nro_status,
9822a8682a8SVincenzo Maffione exp->nro_status);
9832a8682a8SVincenzo Maffione return -1;
9842a8682a8SVincenzo Maffione }
9852a8682a8SVincenzo Maffione return 0;
9862a8682a8SVincenzo Maffione }
9872a8682a8SVincenzo Maffione
9882a8682a8SVincenzo Maffione static int
unsupported_option(struct TestContext * ctx)9892a8682a8SVincenzo Maffione unsupported_option(struct TestContext *ctx)
9902a8682a8SVincenzo Maffione {
9912a8682a8SVincenzo Maffione struct nmreq_option opt, save;
9922a8682a8SVincenzo Maffione
99308f34ad9SVincenzo Maffione printf("Testing unsupported option on %s\n", ctx->ifname_ext);
9942a8682a8SVincenzo Maffione
9952a8682a8SVincenzo Maffione memset(&opt, 0, sizeof(opt));
9962a8682a8SVincenzo Maffione opt.nro_reqtype = 1234;
9972a8682a8SVincenzo Maffione push_option(&opt, ctx);
9982a8682a8SVincenzo Maffione save = opt;
9992a8682a8SVincenzo Maffione
10002a8682a8SVincenzo Maffione if (port_register_hwall(ctx) >= 0)
10012a8682a8SVincenzo Maffione return -1;
10022a8682a8SVincenzo Maffione
10032a8682a8SVincenzo Maffione clear_options(ctx);
10042a8682a8SVincenzo Maffione save.nro_status = EOPNOTSUPP;
10052a8682a8SVincenzo Maffione return checkoption(&opt, &save);
10062a8682a8SVincenzo Maffione }
10072a8682a8SVincenzo Maffione
10082a8682a8SVincenzo Maffione static int
infinite_options(struct TestContext * ctx)10092a8682a8SVincenzo Maffione infinite_options(struct TestContext *ctx)
10102a8682a8SVincenzo Maffione {
10112a8682a8SVincenzo Maffione struct nmreq_option opt;
10122a8682a8SVincenzo Maffione
1013e2a431a0SVincenzo Maffione printf("Testing infinite list of options on %s (invalid options)\n", ctx->ifname_ext);
10142a8682a8SVincenzo Maffione
1015e2a431a0SVincenzo Maffione memset(&opt, 0, sizeof(opt));
1016e2a431a0SVincenzo Maffione opt.nro_reqtype = NETMAP_REQ_OPT_MAX + 1;
10172a8682a8SVincenzo Maffione push_option(&opt, ctx);
10182a8682a8SVincenzo Maffione opt.nro_next = (uintptr_t)&opt;
10192a8682a8SVincenzo Maffione if (port_register_hwall(ctx) >= 0)
10202a8682a8SVincenzo Maffione return -1;
10212a8682a8SVincenzo Maffione clear_options(ctx);
10222a8682a8SVincenzo Maffione return (errno == EMSGSIZE ? 0 : -1);
10232a8682a8SVincenzo Maffione }
10242a8682a8SVincenzo Maffione
1025e2a431a0SVincenzo Maffione static int
infinite_options2(struct TestContext * ctx)1026e2a431a0SVincenzo Maffione infinite_options2(struct TestContext *ctx)
1027e2a431a0SVincenzo Maffione {
1028e2a431a0SVincenzo Maffione struct nmreq_option opt;
1029e2a431a0SVincenzo Maffione
1030e2a431a0SVincenzo Maffione printf("Testing infinite list of options on %s (valid options)\n", ctx->ifname_ext);
1031e2a431a0SVincenzo Maffione
1032e2a431a0SVincenzo Maffione memset(&opt, 0, sizeof(opt));
1033e2a431a0SVincenzo Maffione opt.nro_reqtype = NETMAP_REQ_OPT_OFFSETS;
1034e2a431a0SVincenzo Maffione push_option(&opt, ctx);
1035e2a431a0SVincenzo Maffione opt.nro_next = (uintptr_t)&opt;
1036e2a431a0SVincenzo Maffione if (port_register_hwall(ctx) >= 0)
1037e2a431a0SVincenzo Maffione return -1;
1038e2a431a0SVincenzo Maffione clear_options(ctx);
1039e2a431a0SVincenzo Maffione return (errno == EINVAL ? 0 : -1);
1040e2a431a0SVincenzo Maffione }
1041e2a431a0SVincenzo Maffione
10422a8682a8SVincenzo Maffione #ifdef CONFIG_NETMAP_EXTMEM
10432a8682a8SVincenzo Maffione int
change_param(const char * pname,unsigned long newv,unsigned long * poldv)10442a8682a8SVincenzo Maffione change_param(const char *pname, unsigned long newv, unsigned long *poldv)
10452a8682a8SVincenzo Maffione {
10462a8682a8SVincenzo Maffione #ifdef __linux__
10472a8682a8SVincenzo Maffione char param[256] = "/sys/module/netmap/parameters/";
10482a8682a8SVincenzo Maffione unsigned long oldv;
10492a8682a8SVincenzo Maffione FILE *f;
10502a8682a8SVincenzo Maffione
10512a8682a8SVincenzo Maffione strncat(param, pname, sizeof(param) - 1);
10522a8682a8SVincenzo Maffione
10532a8682a8SVincenzo Maffione f = fopen(param, "r+");
10542a8682a8SVincenzo Maffione if (f == NULL) {
10552a8682a8SVincenzo Maffione perror(param);
10562a8682a8SVincenzo Maffione return -1;
10572a8682a8SVincenzo Maffione }
10582a8682a8SVincenzo Maffione if (fscanf(f, "%ld", &oldv) != 1) {
10592a8682a8SVincenzo Maffione perror(param);
10602a8682a8SVincenzo Maffione fclose(f);
10612a8682a8SVincenzo Maffione return -1;
10622a8682a8SVincenzo Maffione }
10632a8682a8SVincenzo Maffione if (poldv)
10642a8682a8SVincenzo Maffione *poldv = oldv;
10652a8682a8SVincenzo Maffione rewind(f);
10662a8682a8SVincenzo Maffione if (fprintf(f, "%ld\n", newv) < 0) {
10672a8682a8SVincenzo Maffione perror(param);
10682a8682a8SVincenzo Maffione fclose(f);
10692a8682a8SVincenzo Maffione return -1;
10702a8682a8SVincenzo Maffione }
10712a8682a8SVincenzo Maffione fclose(f);
10722a8682a8SVincenzo Maffione printf("change_param: %s: %ld -> %ld\n", pname, oldv, newv);
10732a8682a8SVincenzo Maffione #endif /* __linux__ */
10742a8682a8SVincenzo Maffione return 0;
10752a8682a8SVincenzo Maffione }
10762a8682a8SVincenzo Maffione
10772a8682a8SVincenzo Maffione static int
push_extmem_option(struct TestContext * ctx,const struct nmreq_pools_info * pi,struct nmreq_opt_extmem * e)10782a8682a8SVincenzo Maffione push_extmem_option(struct TestContext *ctx, const struct nmreq_pools_info *pi,
10792a8682a8SVincenzo Maffione struct nmreq_opt_extmem *e)
10802a8682a8SVincenzo Maffione {
10812a8682a8SVincenzo Maffione void *addr;
10822a8682a8SVincenzo Maffione
10832a8682a8SVincenzo Maffione addr = mmap(NULL, pi->nr_memsize, PROT_READ | PROT_WRITE,
10842a8682a8SVincenzo Maffione MAP_ANONYMOUS | MAP_SHARED, -1, 0);
10852a8682a8SVincenzo Maffione if (addr == MAP_FAILED) {
10862a8682a8SVincenzo Maffione perror("mmap");
10872a8682a8SVincenzo Maffione return -1;
10882a8682a8SVincenzo Maffione }
10892a8682a8SVincenzo Maffione
10902a8682a8SVincenzo Maffione memset(e, 0, sizeof(*e));
10912a8682a8SVincenzo Maffione e->nro_opt.nro_reqtype = NETMAP_REQ_OPT_EXTMEM;
10922a8682a8SVincenzo Maffione e->nro_info = *pi;
10932a8682a8SVincenzo Maffione e->nro_usrptr = (uintptr_t)addr;
10942a8682a8SVincenzo Maffione
10952a8682a8SVincenzo Maffione push_option(&e->nro_opt, ctx);
10962a8682a8SVincenzo Maffione
10972a8682a8SVincenzo Maffione return 0;
10982a8682a8SVincenzo Maffione }
10992a8682a8SVincenzo Maffione
11002a8682a8SVincenzo Maffione static int
pop_extmem_option(struct TestContext * ctx,struct nmreq_opt_extmem * exp)11012a8682a8SVincenzo Maffione pop_extmem_option(struct TestContext *ctx, struct nmreq_opt_extmem *exp)
11022a8682a8SVincenzo Maffione {
11032a8682a8SVincenzo Maffione struct nmreq_opt_extmem *e;
11042a8682a8SVincenzo Maffione int ret;
11052a8682a8SVincenzo Maffione
11062a8682a8SVincenzo Maffione e = (struct nmreq_opt_extmem *)(uintptr_t)ctx->nr_opt;
11072a8682a8SVincenzo Maffione ctx->nr_opt = (struct nmreq_option *)(uintptr_t)ctx->nr_opt->nro_next;
11082a8682a8SVincenzo Maffione
11092a8682a8SVincenzo Maffione if ((ret = checkoption(&e->nro_opt, &exp->nro_opt))) {
11102a8682a8SVincenzo Maffione return ret;
11112a8682a8SVincenzo Maffione }
11122a8682a8SVincenzo Maffione
11132a8682a8SVincenzo Maffione if (e->nro_usrptr != exp->nro_usrptr) {
11142a8682a8SVincenzo Maffione printf("usrptr %" PRIu64 " expected %" PRIu64 "\n",
11152a8682a8SVincenzo Maffione e->nro_usrptr, exp->nro_usrptr);
11162a8682a8SVincenzo Maffione return -1;
11172a8682a8SVincenzo Maffione }
11182a8682a8SVincenzo Maffione if (e->nro_info.nr_memsize != exp->nro_info.nr_memsize) {
11192a8682a8SVincenzo Maffione printf("memsize %" PRIu64 " expected %" PRIu64 "\n",
11202a8682a8SVincenzo Maffione e->nro_info.nr_memsize, exp->nro_info.nr_memsize);
11212a8682a8SVincenzo Maffione return -1;
11222a8682a8SVincenzo Maffione }
11232a8682a8SVincenzo Maffione
11242a8682a8SVincenzo Maffione if ((ret = munmap((void *)(uintptr_t)e->nro_usrptr,
11252a8682a8SVincenzo Maffione e->nro_info.nr_memsize)))
11262a8682a8SVincenzo Maffione return ret;
11272a8682a8SVincenzo Maffione
11282a8682a8SVincenzo Maffione return 0;
11292a8682a8SVincenzo Maffione }
11302a8682a8SVincenzo Maffione
11312a8682a8SVincenzo Maffione static int
_extmem_option(struct TestContext * ctx,const struct nmreq_pools_info * pi)11322a8682a8SVincenzo Maffione _extmem_option(struct TestContext *ctx,
11332a8682a8SVincenzo Maffione const struct nmreq_pools_info *pi)
11342a8682a8SVincenzo Maffione {
11352a8682a8SVincenzo Maffione struct nmreq_opt_extmem e, save;
11362a8682a8SVincenzo Maffione int ret;
11372a8682a8SVincenzo Maffione
11382a8682a8SVincenzo Maffione if ((ret = push_extmem_option(ctx, pi, &e)) < 0)
11392a8682a8SVincenzo Maffione return ret;
11402a8682a8SVincenzo Maffione
11412a8682a8SVincenzo Maffione save = e;
11422a8682a8SVincenzo Maffione
114308f34ad9SVincenzo Maffione strncpy(ctx->ifname_ext, "vale0:0", sizeof(ctx->ifname_ext));
11442a8682a8SVincenzo Maffione ctx->nr_tx_slots = 16;
11452a8682a8SVincenzo Maffione ctx->nr_rx_slots = 16;
11462a8682a8SVincenzo Maffione
11472a8682a8SVincenzo Maffione if ((ret = port_register_hwall(ctx)))
11482a8682a8SVincenzo Maffione return ret;
11492a8682a8SVincenzo Maffione
11502a8682a8SVincenzo Maffione ret = pop_extmem_option(ctx, &save);
11512a8682a8SVincenzo Maffione
11522a8682a8SVincenzo Maffione return ret;
11532a8682a8SVincenzo Maffione }
11542a8682a8SVincenzo Maffione
11552a8682a8SVincenzo Maffione static size_t
pools_info_min_memsize(const struct nmreq_pools_info * pi)11562a8682a8SVincenzo Maffione pools_info_min_memsize(const struct nmreq_pools_info *pi)
11572a8682a8SVincenzo Maffione {
11582a8682a8SVincenzo Maffione size_t tot = 0;
11592a8682a8SVincenzo Maffione
11602a8682a8SVincenzo Maffione tot += pi->nr_if_pool_objtotal * pi->nr_if_pool_objsize;
11612a8682a8SVincenzo Maffione tot += pi->nr_ring_pool_objtotal * pi->nr_ring_pool_objsize;
11622a8682a8SVincenzo Maffione tot += pi->nr_buf_pool_objtotal * pi->nr_buf_pool_objsize;
11632a8682a8SVincenzo Maffione
11642a8682a8SVincenzo Maffione return tot;
11652a8682a8SVincenzo Maffione }
11662a8682a8SVincenzo Maffione
11672a8682a8SVincenzo Maffione /*
11682a8682a8SVincenzo Maffione * Fill the specification of a netmap memory allocator to be
11692a8682a8SVincenzo Maffione * used with the 'struct nmreq_opt_extmem' option. Arbitrary
11702a8682a8SVincenzo Maffione * values are used for the parameters, but with enough netmap
11712a8682a8SVincenzo Maffione * rings, netmap ifs, and buffers to support a VALE port.
11722a8682a8SVincenzo Maffione */
11732a8682a8SVincenzo Maffione static void
pools_info_fill(struct nmreq_pools_info * pi)11742a8682a8SVincenzo Maffione pools_info_fill(struct nmreq_pools_info *pi)
11752a8682a8SVincenzo Maffione {
11762a8682a8SVincenzo Maffione pi->nr_if_pool_objtotal = 2;
11772a8682a8SVincenzo Maffione pi->nr_if_pool_objsize = 1024;
11782a8682a8SVincenzo Maffione pi->nr_ring_pool_objtotal = 64;
11792a8682a8SVincenzo Maffione pi->nr_ring_pool_objsize = 512;
11802a8682a8SVincenzo Maffione pi->nr_buf_pool_objtotal = 4096;
11812a8682a8SVincenzo Maffione pi->nr_buf_pool_objsize = 2048;
11822a8682a8SVincenzo Maffione pi->nr_memsize = pools_info_min_memsize(pi);
11832a8682a8SVincenzo Maffione }
11842a8682a8SVincenzo Maffione
11852a8682a8SVincenzo Maffione static int
extmem_option(struct TestContext * ctx)11862a8682a8SVincenzo Maffione extmem_option(struct TestContext *ctx)
11872a8682a8SVincenzo Maffione {
11882a8682a8SVincenzo Maffione struct nmreq_pools_info pools_info;
11892a8682a8SVincenzo Maffione
11902a8682a8SVincenzo Maffione pools_info_fill(&pools_info);
11912a8682a8SVincenzo Maffione
11922a8682a8SVincenzo Maffione printf("Testing extmem option on vale0:0\n");
11932a8682a8SVincenzo Maffione return _extmem_option(ctx, &pools_info);
11942a8682a8SVincenzo Maffione }
11952a8682a8SVincenzo Maffione
11962a8682a8SVincenzo Maffione static int
bad_extmem_option(struct TestContext * ctx)11972a8682a8SVincenzo Maffione bad_extmem_option(struct TestContext *ctx)
11982a8682a8SVincenzo Maffione {
11992a8682a8SVincenzo Maffione struct nmreq_pools_info pools_info;
12002a8682a8SVincenzo Maffione
12012a8682a8SVincenzo Maffione printf("Testing bad extmem option on vale0:0\n");
12022a8682a8SVincenzo Maffione
12032a8682a8SVincenzo Maffione pools_info_fill(&pools_info);
12042a8682a8SVincenzo Maffione /* Request a large ring size, to make sure that the kernel
12052a8682a8SVincenzo Maffione * rejects our request. */
12065e874d26SVincenzo Maffione pools_info.nr_ring_pool_objsize = (1 << 20);
12072a8682a8SVincenzo Maffione
12082a8682a8SVincenzo Maffione return _extmem_option(ctx, &pools_info) < 0 ? 0 : -1;
12092a8682a8SVincenzo Maffione }
12102a8682a8SVincenzo Maffione
12112a8682a8SVincenzo Maffione static int
duplicate_extmem_options(struct TestContext * ctx)12122a8682a8SVincenzo Maffione duplicate_extmem_options(struct TestContext *ctx)
12132a8682a8SVincenzo Maffione {
12142a8682a8SVincenzo Maffione struct nmreq_opt_extmem e1, save1, e2, save2;
12152a8682a8SVincenzo Maffione struct nmreq_pools_info pools_info;
12162a8682a8SVincenzo Maffione int ret;
12172a8682a8SVincenzo Maffione
12182a8682a8SVincenzo Maffione printf("Testing duplicate extmem option on vale0:0\n");
12192a8682a8SVincenzo Maffione
12202a8682a8SVincenzo Maffione pools_info_fill(&pools_info);
12212a8682a8SVincenzo Maffione
12222a8682a8SVincenzo Maffione if ((ret = push_extmem_option(ctx, &pools_info, &e1)) < 0)
12232a8682a8SVincenzo Maffione return ret;
12242a8682a8SVincenzo Maffione
12252a8682a8SVincenzo Maffione if ((ret = push_extmem_option(ctx, &pools_info, &e2)) < 0) {
12262a8682a8SVincenzo Maffione clear_options(ctx);
12272a8682a8SVincenzo Maffione return ret;
12282a8682a8SVincenzo Maffione }
12292a8682a8SVincenzo Maffione
12302a8682a8SVincenzo Maffione save1 = e1;
12312a8682a8SVincenzo Maffione save2 = e2;
12322a8682a8SVincenzo Maffione
12335e874d26SVincenzo Maffione strncpy(ctx->ifname_ext, "vale0:0", sizeof(ctx->ifname_ext));
12345e874d26SVincenzo Maffione ctx->nr_tx_slots = 16;
12355e874d26SVincenzo Maffione ctx->nr_rx_slots = 16;
12365e874d26SVincenzo Maffione
12372a8682a8SVincenzo Maffione ret = port_register_hwall(ctx);
12382a8682a8SVincenzo Maffione if (ret >= 0) {
12392a8682a8SVincenzo Maffione printf("duplicate option not detected\n");
12402a8682a8SVincenzo Maffione return -1;
12412a8682a8SVincenzo Maffione }
12422a8682a8SVincenzo Maffione
12432a8682a8SVincenzo Maffione save2.nro_opt.nro_status = EINVAL;
12442a8682a8SVincenzo Maffione if ((ret = pop_extmem_option(ctx, &save2)))
12452a8682a8SVincenzo Maffione return ret;
12462a8682a8SVincenzo Maffione
12472a8682a8SVincenzo Maffione save1.nro_opt.nro_status = EINVAL;
12482a8682a8SVincenzo Maffione if ((ret = pop_extmem_option(ctx, &save1)))
12492a8682a8SVincenzo Maffione return ret;
12502a8682a8SVincenzo Maffione
12512a8682a8SVincenzo Maffione return 0;
12522a8682a8SVincenzo Maffione }
12532a8682a8SVincenzo Maffione #endif /* CONFIG_NETMAP_EXTMEM */
12542a8682a8SVincenzo Maffione
12552a8682a8SVincenzo Maffione static int
push_csb_option(struct TestContext * ctx,struct nmreq_opt_csb * opt)12562a8682a8SVincenzo Maffione push_csb_option(struct TestContext *ctx, struct nmreq_opt_csb *opt)
12572a8682a8SVincenzo Maffione {
12582a8682a8SVincenzo Maffione size_t csb_size;
12592a8682a8SVincenzo Maffione int num_entries;
12602a8682a8SVincenzo Maffione int ret;
12612a8682a8SVincenzo Maffione
12622a8682a8SVincenzo Maffione ctx->nr_flags |= NR_EXCLUSIVE;
12632a8682a8SVincenzo Maffione
12642a8682a8SVincenzo Maffione /* Get port info in order to use num_registered_rings(). */
12652a8682a8SVincenzo Maffione ret = port_info_get(ctx);
12662a8682a8SVincenzo Maffione if (ret != 0) {
12672a8682a8SVincenzo Maffione return ret;
12682a8682a8SVincenzo Maffione }
12692a8682a8SVincenzo Maffione num_entries = num_registered_rings(ctx);
12702a8682a8SVincenzo Maffione
12712a8682a8SVincenzo Maffione csb_size = (sizeof(struct nm_csb_atok) + sizeof(struct nm_csb_ktoa)) *
12722a8682a8SVincenzo Maffione num_entries;
12732a8682a8SVincenzo Maffione assert(csb_size > 0);
12742a8682a8SVincenzo Maffione if (ctx->csb) {
12752a8682a8SVincenzo Maffione free(ctx->csb);
12762a8682a8SVincenzo Maffione }
12772a8682a8SVincenzo Maffione ret = posix_memalign(&ctx->csb, sizeof(struct nm_csb_atok), csb_size);
12782a8682a8SVincenzo Maffione if (ret != 0) {
12792a8682a8SVincenzo Maffione printf("Failed to allocate CSB memory\n");
12802a8682a8SVincenzo Maffione exit(EXIT_FAILURE);
12812a8682a8SVincenzo Maffione }
12822a8682a8SVincenzo Maffione
12832a8682a8SVincenzo Maffione memset(opt, 0, sizeof(*opt));
12842a8682a8SVincenzo Maffione opt->nro_opt.nro_reqtype = NETMAP_REQ_OPT_CSB;
12852a8682a8SVincenzo Maffione opt->csb_atok = (uintptr_t)ctx->csb;
12862a8682a8SVincenzo Maffione opt->csb_ktoa = (uintptr_t)(((uint8_t *)ctx->csb) +
12872a8682a8SVincenzo Maffione sizeof(struct nm_csb_atok) * num_entries);
12882a8682a8SVincenzo Maffione
12892a8682a8SVincenzo Maffione printf("Pushing option NETMAP_REQ_OPT_CSB\n");
12902a8682a8SVincenzo Maffione push_option(&opt->nro_opt, ctx);
12912a8682a8SVincenzo Maffione
12922a8682a8SVincenzo Maffione return 0;
12932a8682a8SVincenzo Maffione }
12942a8682a8SVincenzo Maffione
12952a8682a8SVincenzo Maffione static int
csb_mode(struct TestContext * ctx)12962a8682a8SVincenzo Maffione csb_mode(struct TestContext *ctx)
12972a8682a8SVincenzo Maffione {
12982a8682a8SVincenzo Maffione struct nmreq_opt_csb opt;
12992a8682a8SVincenzo Maffione int ret;
13002a8682a8SVincenzo Maffione
13012a8682a8SVincenzo Maffione ret = push_csb_option(ctx, &opt);
13022a8682a8SVincenzo Maffione if (ret != 0) {
13032a8682a8SVincenzo Maffione return ret;
13042a8682a8SVincenzo Maffione }
13052a8682a8SVincenzo Maffione
13062a8682a8SVincenzo Maffione ret = port_register_hwall(ctx);
13072a8682a8SVincenzo Maffione clear_options(ctx);
13082a8682a8SVincenzo Maffione
13092a8682a8SVincenzo Maffione return ret;
13102a8682a8SVincenzo Maffione }
13112a8682a8SVincenzo Maffione
13122a8682a8SVincenzo Maffione static int
csb_mode_invalid_memory(struct TestContext * ctx)13132a8682a8SVincenzo Maffione csb_mode_invalid_memory(struct TestContext *ctx)
13142a8682a8SVincenzo Maffione {
13152a8682a8SVincenzo Maffione struct nmreq_opt_csb opt;
13162a8682a8SVincenzo Maffione int ret;
13172a8682a8SVincenzo Maffione
13182a8682a8SVincenzo Maffione memset(&opt, 0, sizeof(opt));
13192a8682a8SVincenzo Maffione opt.nro_opt.nro_reqtype = NETMAP_REQ_OPT_CSB;
13202a8682a8SVincenzo Maffione opt.csb_atok = (uintptr_t)0x10;
13212a8682a8SVincenzo Maffione opt.csb_ktoa = (uintptr_t)0x800;
13222a8682a8SVincenzo Maffione push_option(&opt.nro_opt, ctx);
13232a8682a8SVincenzo Maffione
13242a8682a8SVincenzo Maffione ctx->nr_flags = NR_EXCLUSIVE;
13252a8682a8SVincenzo Maffione ret = port_register_hwall(ctx);
13262a8682a8SVincenzo Maffione clear_options(ctx);
13272a8682a8SVincenzo Maffione
13282a8682a8SVincenzo Maffione return (ret < 0) ? 0 : -1;
13292a8682a8SVincenzo Maffione }
13302a8682a8SVincenzo Maffione
13312a8682a8SVincenzo Maffione static int
sync_kloop_stop(struct TestContext * ctx)13322a8682a8SVincenzo Maffione sync_kloop_stop(struct TestContext *ctx)
13332a8682a8SVincenzo Maffione {
13342a8682a8SVincenzo Maffione struct nmreq_header hdr;
13352a8682a8SVincenzo Maffione int ret;
13362a8682a8SVincenzo Maffione
133708f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_SYNC_KLOOP_STOP on '%s'\n", ctx->ifname_ext);
13382a8682a8SVincenzo Maffione
133908f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
13402a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_SYNC_KLOOP_STOP;
13412a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
13422a8682a8SVincenzo Maffione if (ret != 0) {
13432a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, SYNC_KLOOP_STOP)");
13442a8682a8SVincenzo Maffione }
13452a8682a8SVincenzo Maffione
13462a8682a8SVincenzo Maffione return ret;
13472a8682a8SVincenzo Maffione }
13482a8682a8SVincenzo Maffione
13492a8682a8SVincenzo Maffione static void *
sync_kloop_worker(void * opaque)13502a8682a8SVincenzo Maffione sync_kloop_worker(void *opaque)
13512a8682a8SVincenzo Maffione {
13522a8682a8SVincenzo Maffione struct TestContext *ctx = opaque;
13532a8682a8SVincenzo Maffione struct nmreq_sync_kloop_start req;
13542a8682a8SVincenzo Maffione struct nmreq_header hdr;
13552a8682a8SVincenzo Maffione int ret;
13562a8682a8SVincenzo Maffione
135708f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_SYNC_KLOOP_START on '%s'\n", ctx->ifname_ext);
13582a8682a8SVincenzo Maffione
135908f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
13602a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_SYNC_KLOOP_START;
13612a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)&req;
13622a8682a8SVincenzo Maffione hdr.nr_options = (uintptr_t)ctx->nr_opt;
13632a8682a8SVincenzo Maffione memset(&req, 0, sizeof(req));
13642a8682a8SVincenzo Maffione req.sleep_us = 500;
13652a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
13662a8682a8SVincenzo Maffione if (ret != 0) {
13672a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, SYNC_KLOOP_START)");
13682a8682a8SVincenzo Maffione }
13692a8682a8SVincenzo Maffione
13702a8682a8SVincenzo Maffione if (ctx->sem) {
13712a8682a8SVincenzo Maffione sem_post(ctx->sem);
13722a8682a8SVincenzo Maffione }
13732a8682a8SVincenzo Maffione
13742a8682a8SVincenzo Maffione pthread_exit(ret ? (void *)THRET_FAILURE : (void *)THRET_SUCCESS);
13752a8682a8SVincenzo Maffione }
13762a8682a8SVincenzo Maffione
13772a8682a8SVincenzo Maffione static int
sync_kloop_start_stop(struct TestContext * ctx)13782a8682a8SVincenzo Maffione sync_kloop_start_stop(struct TestContext *ctx)
13792a8682a8SVincenzo Maffione {
13802a8682a8SVincenzo Maffione pthread_t th;
13812a8682a8SVincenzo Maffione void *thret = THRET_FAILURE;
13822a8682a8SVincenzo Maffione int ret;
13832a8682a8SVincenzo Maffione
13842a8682a8SVincenzo Maffione ret = pthread_create(&th, NULL, sync_kloop_worker, ctx);
13852a8682a8SVincenzo Maffione if (ret != 0) {
13862a8682a8SVincenzo Maffione printf("pthread_create(kloop): %s\n", strerror(ret));
13872a8682a8SVincenzo Maffione return -1;
13882a8682a8SVincenzo Maffione }
13892a8682a8SVincenzo Maffione
13902a8682a8SVincenzo Maffione ret = sync_kloop_stop(ctx);
13912a8682a8SVincenzo Maffione if (ret != 0) {
13922a8682a8SVincenzo Maffione return ret;
13932a8682a8SVincenzo Maffione }
13942a8682a8SVincenzo Maffione
13952a8682a8SVincenzo Maffione ret = pthread_join(th, &thret);
13962a8682a8SVincenzo Maffione if (ret != 0) {
13972a8682a8SVincenzo Maffione printf("pthread_join(kloop): %s\n", strerror(ret));
13982a8682a8SVincenzo Maffione }
13992a8682a8SVincenzo Maffione
14002a8682a8SVincenzo Maffione return thret == THRET_SUCCESS ? 0 : -1;
14012a8682a8SVincenzo Maffione }
14022a8682a8SVincenzo Maffione
14032a8682a8SVincenzo Maffione static int
sync_kloop(struct TestContext * ctx)14042a8682a8SVincenzo Maffione sync_kloop(struct TestContext *ctx)
14052a8682a8SVincenzo Maffione {
14062a8682a8SVincenzo Maffione int ret;
14072a8682a8SVincenzo Maffione
14082a8682a8SVincenzo Maffione ret = csb_mode(ctx);
14092a8682a8SVincenzo Maffione if (ret != 0) {
14102a8682a8SVincenzo Maffione return ret;
14112a8682a8SVincenzo Maffione }
14122a8682a8SVincenzo Maffione
14132a8682a8SVincenzo Maffione return sync_kloop_start_stop(ctx);
14142a8682a8SVincenzo Maffione }
14152a8682a8SVincenzo Maffione
14162a8682a8SVincenzo Maffione static int
sync_kloop_eventfds(struct TestContext * ctx)14172a8682a8SVincenzo Maffione sync_kloop_eventfds(struct TestContext *ctx)
14182a8682a8SVincenzo Maffione {
14195e874d26SVincenzo Maffione struct nmreq_opt_sync_kloop_eventfds *evopt = NULL;
14205e874d26SVincenzo Maffione struct nmreq_opt_sync_kloop_mode modeopt;
14215e874d26SVincenzo Maffione struct nmreq_option evsave;
14222a8682a8SVincenzo Maffione int num_entries;
14232a8682a8SVincenzo Maffione size_t opt_size;
14242a8682a8SVincenzo Maffione int ret, i;
14252a8682a8SVincenzo Maffione
14265e874d26SVincenzo Maffione memset(&modeopt, 0, sizeof(modeopt));
14275e874d26SVincenzo Maffione modeopt.nro_opt.nro_reqtype = NETMAP_REQ_OPT_SYNC_KLOOP_MODE;
14285e874d26SVincenzo Maffione modeopt.mode = ctx->sync_kloop_mode;
14295e874d26SVincenzo Maffione push_option(&modeopt.nro_opt, ctx);
14305e874d26SVincenzo Maffione
14312a8682a8SVincenzo Maffione num_entries = num_registered_rings(ctx);
14325e874d26SVincenzo Maffione opt_size = sizeof(*evopt) + num_entries * sizeof(evopt->eventfds[0]);
14335e874d26SVincenzo Maffione evopt = calloc(1, opt_size);
14345e874d26SVincenzo Maffione evopt->nro_opt.nro_next = 0;
14355e874d26SVincenzo Maffione evopt->nro_opt.nro_reqtype = NETMAP_REQ_OPT_SYNC_KLOOP_EVENTFDS;
14365e874d26SVincenzo Maffione evopt->nro_opt.nro_status = 0;
14375e874d26SVincenzo Maffione evopt->nro_opt.nro_size = opt_size;
14382a8682a8SVincenzo Maffione for (i = 0; i < num_entries; i++) {
14392a8682a8SVincenzo Maffione int efd = eventfd(0, 0);
14402a8682a8SVincenzo Maffione
14415e874d26SVincenzo Maffione evopt->eventfds[i].ioeventfd = efd;
14422a8682a8SVincenzo Maffione efd = eventfd(0, 0);
14435e874d26SVincenzo Maffione evopt->eventfds[i].irqfd = efd;
14442a8682a8SVincenzo Maffione }
14452a8682a8SVincenzo Maffione
14465e874d26SVincenzo Maffione push_option(&evopt->nro_opt, ctx);
14475e874d26SVincenzo Maffione evsave = evopt->nro_opt;
14482a8682a8SVincenzo Maffione
14492a8682a8SVincenzo Maffione ret = sync_kloop_start_stop(ctx);
14502a8682a8SVincenzo Maffione if (ret != 0) {
14515e874d26SVincenzo Maffione free(evopt);
14522a8682a8SVincenzo Maffione clear_options(ctx);
14532a8682a8SVincenzo Maffione return ret;
14542a8682a8SVincenzo Maffione }
14552a8682a8SVincenzo Maffione #ifdef __linux__
14565e874d26SVincenzo Maffione evsave.nro_status = 0;
14572a8682a8SVincenzo Maffione #else /* !__linux__ */
14585e874d26SVincenzo Maffione evsave.nro_status = EOPNOTSUPP;
14592a8682a8SVincenzo Maffione #endif /* !__linux__ */
14602a8682a8SVincenzo Maffione
14615e874d26SVincenzo Maffione ret = checkoption(&evopt->nro_opt, &evsave);
14625e874d26SVincenzo Maffione free(evopt);
14632a8682a8SVincenzo Maffione clear_options(ctx);
14642a8682a8SVincenzo Maffione
14652a8682a8SVincenzo Maffione return ret;
14662a8682a8SVincenzo Maffione }
14672a8682a8SVincenzo Maffione
14682a8682a8SVincenzo Maffione static int
sync_kloop_eventfds_all_mode(struct TestContext * ctx,uint32_t sync_kloop_mode)14695e874d26SVincenzo Maffione sync_kloop_eventfds_all_mode(struct TestContext *ctx,
14705e874d26SVincenzo Maffione uint32_t sync_kloop_mode)
14712a8682a8SVincenzo Maffione {
14722a8682a8SVincenzo Maffione int ret;
14732a8682a8SVincenzo Maffione
14742a8682a8SVincenzo Maffione ret = csb_mode(ctx);
14752a8682a8SVincenzo Maffione if (ret != 0) {
14762a8682a8SVincenzo Maffione return ret;
14772a8682a8SVincenzo Maffione }
14782a8682a8SVincenzo Maffione
14795e874d26SVincenzo Maffione ctx->sync_kloop_mode = sync_kloop_mode;
14805e874d26SVincenzo Maffione
14812a8682a8SVincenzo Maffione return sync_kloop_eventfds(ctx);
14822a8682a8SVincenzo Maffione }
14832a8682a8SVincenzo Maffione
14842a8682a8SVincenzo Maffione static int
sync_kloop_eventfds_all(struct TestContext * ctx)14855e874d26SVincenzo Maffione sync_kloop_eventfds_all(struct TestContext *ctx)
14865e874d26SVincenzo Maffione {
14875e874d26SVincenzo Maffione return sync_kloop_eventfds_all_mode(ctx, 0);
14885e874d26SVincenzo Maffione }
14895e874d26SVincenzo Maffione
14905e874d26SVincenzo Maffione static int
sync_kloop_eventfds_all_tx(struct TestContext * ctx)14912a8682a8SVincenzo Maffione sync_kloop_eventfds_all_tx(struct TestContext *ctx)
14922a8682a8SVincenzo Maffione {
14932a8682a8SVincenzo Maffione struct nmreq_opt_csb opt;
14942a8682a8SVincenzo Maffione int ret;
14952a8682a8SVincenzo Maffione
14962a8682a8SVincenzo Maffione ret = push_csb_option(ctx, &opt);
14972a8682a8SVincenzo Maffione if (ret != 0) {
14982a8682a8SVincenzo Maffione return ret;
14992a8682a8SVincenzo Maffione }
15002a8682a8SVincenzo Maffione
15012a8682a8SVincenzo Maffione ret = port_register_hwall_tx(ctx);
15022a8682a8SVincenzo Maffione if (ret != 0) {
15032a8682a8SVincenzo Maffione return ret;
15042a8682a8SVincenzo Maffione }
15052a8682a8SVincenzo Maffione clear_options(ctx);
15062a8682a8SVincenzo Maffione
15072a8682a8SVincenzo Maffione return sync_kloop_eventfds(ctx);
15082a8682a8SVincenzo Maffione }
15092a8682a8SVincenzo Maffione
15102a8682a8SVincenzo Maffione static int
sync_kloop_eventfds_all_direct(struct TestContext * ctx)15115e874d26SVincenzo Maffione sync_kloop_eventfds_all_direct(struct TestContext *ctx)
15125e874d26SVincenzo Maffione {
15135e874d26SVincenzo Maffione return sync_kloop_eventfds_all_mode(ctx,
15145e874d26SVincenzo Maffione NM_OPT_SYNC_KLOOP_DIRECT_TX | NM_OPT_SYNC_KLOOP_DIRECT_RX);
15155e874d26SVincenzo Maffione }
15165e874d26SVincenzo Maffione
15175e874d26SVincenzo Maffione static int
sync_kloop_eventfds_all_direct_tx(struct TestContext * ctx)15185e874d26SVincenzo Maffione sync_kloop_eventfds_all_direct_tx(struct TestContext *ctx)
15195e874d26SVincenzo Maffione {
15205e874d26SVincenzo Maffione return sync_kloop_eventfds_all_mode(ctx,
15215e874d26SVincenzo Maffione NM_OPT_SYNC_KLOOP_DIRECT_TX);
15225e874d26SVincenzo Maffione }
15235e874d26SVincenzo Maffione
15245e874d26SVincenzo Maffione static int
sync_kloop_eventfds_all_direct_rx(struct TestContext * ctx)15255e874d26SVincenzo Maffione sync_kloop_eventfds_all_direct_rx(struct TestContext *ctx)
15265e874d26SVincenzo Maffione {
15275e874d26SVincenzo Maffione return sync_kloop_eventfds_all_mode(ctx,
15285e874d26SVincenzo Maffione NM_OPT_SYNC_KLOOP_DIRECT_RX);
15295e874d26SVincenzo Maffione }
15305e874d26SVincenzo Maffione
15315e874d26SVincenzo Maffione static int
sync_kloop_nocsb(struct TestContext * ctx)15322a8682a8SVincenzo Maffione sync_kloop_nocsb(struct TestContext *ctx)
15332a8682a8SVincenzo Maffione {
15342a8682a8SVincenzo Maffione int ret;
15352a8682a8SVincenzo Maffione
15362a8682a8SVincenzo Maffione ret = port_register_hwall(ctx);
15372a8682a8SVincenzo Maffione if (ret != 0) {
15382a8682a8SVincenzo Maffione return ret;
15392a8682a8SVincenzo Maffione }
15402a8682a8SVincenzo Maffione
15412a8682a8SVincenzo Maffione /* Sync kloop must fail because we did not use
15422a8682a8SVincenzo Maffione * NETMAP_REQ_CSB_ENABLE. */
15432a8682a8SVincenzo Maffione return sync_kloop_start_stop(ctx) != 0 ? 0 : -1;
15442a8682a8SVincenzo Maffione }
15452a8682a8SVincenzo Maffione
15462a8682a8SVincenzo Maffione static int
csb_enable(struct TestContext * ctx)15472a8682a8SVincenzo Maffione csb_enable(struct TestContext *ctx)
15482a8682a8SVincenzo Maffione {
15492a8682a8SVincenzo Maffione struct nmreq_option saveopt;
15502a8682a8SVincenzo Maffione struct nmreq_opt_csb opt;
15512a8682a8SVincenzo Maffione struct nmreq_header hdr;
15522a8682a8SVincenzo Maffione int ret;
15532a8682a8SVincenzo Maffione
15542a8682a8SVincenzo Maffione ret = push_csb_option(ctx, &opt);
15552a8682a8SVincenzo Maffione if (ret != 0) {
15562a8682a8SVincenzo Maffione return ret;
15572a8682a8SVincenzo Maffione }
15582a8682a8SVincenzo Maffione saveopt = opt.nro_opt;
15592a8682a8SVincenzo Maffione saveopt.nro_status = 0;
15602a8682a8SVincenzo Maffione
156108f34ad9SVincenzo Maffione nmreq_hdr_init(&hdr, ctx->ifname_ext);
15622a8682a8SVincenzo Maffione hdr.nr_reqtype = NETMAP_REQ_CSB_ENABLE;
15632a8682a8SVincenzo Maffione hdr.nr_options = (uintptr_t)ctx->nr_opt;
15642a8682a8SVincenzo Maffione hdr.nr_body = (uintptr_t)NULL;
15652a8682a8SVincenzo Maffione
156608f34ad9SVincenzo Maffione printf("Testing NETMAP_REQ_CSB_ENABLE on '%s'\n", ctx->ifname_ext);
15672a8682a8SVincenzo Maffione
15682a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
15692a8682a8SVincenzo Maffione if (ret != 0) {
15702a8682a8SVincenzo Maffione perror("ioctl(/dev/netmap, NIOCCTRL, CSB_ENABLE)");
15712a8682a8SVincenzo Maffione return ret;
15722a8682a8SVincenzo Maffione }
15732a8682a8SVincenzo Maffione
15742a8682a8SVincenzo Maffione ret = checkoption(&opt.nro_opt, &saveopt);
15752a8682a8SVincenzo Maffione clear_options(ctx);
15762a8682a8SVincenzo Maffione
15772a8682a8SVincenzo Maffione return ret;
15782a8682a8SVincenzo Maffione }
15792a8682a8SVincenzo Maffione
15802a8682a8SVincenzo Maffione static int
sync_kloop_csb_enable(struct TestContext * ctx)15812a8682a8SVincenzo Maffione sync_kloop_csb_enable(struct TestContext *ctx)
15822a8682a8SVincenzo Maffione {
15832a8682a8SVincenzo Maffione int ret;
15842a8682a8SVincenzo Maffione
15852a8682a8SVincenzo Maffione ctx->nr_flags |= NR_EXCLUSIVE;
15862a8682a8SVincenzo Maffione ret = port_register_hwall(ctx);
15872a8682a8SVincenzo Maffione if (ret != 0) {
15882a8682a8SVincenzo Maffione return ret;
15892a8682a8SVincenzo Maffione }
15902a8682a8SVincenzo Maffione
15912a8682a8SVincenzo Maffione ret = csb_enable(ctx);
15922a8682a8SVincenzo Maffione if (ret != 0) {
15932a8682a8SVincenzo Maffione return ret;
15942a8682a8SVincenzo Maffione }
15952a8682a8SVincenzo Maffione
15962a8682a8SVincenzo Maffione return sync_kloop_start_stop(ctx);
15972a8682a8SVincenzo Maffione }
15982a8682a8SVincenzo Maffione
15992a8682a8SVincenzo Maffione static int
sync_kloop_conflict(struct TestContext * ctx)16002a8682a8SVincenzo Maffione sync_kloop_conflict(struct TestContext *ctx)
16012a8682a8SVincenzo Maffione {
16022a8682a8SVincenzo Maffione struct nmreq_opt_csb opt;
16032a8682a8SVincenzo Maffione pthread_t th1, th2;
16042a8682a8SVincenzo Maffione void *thret1 = THRET_FAILURE, *thret2 = THRET_FAILURE;
16052a8682a8SVincenzo Maffione struct timespec to;
16062a8682a8SVincenzo Maffione sem_t sem;
16072a8682a8SVincenzo Maffione int err = 0;
16082a8682a8SVincenzo Maffione int ret;
16092a8682a8SVincenzo Maffione
16102a8682a8SVincenzo Maffione ret = push_csb_option(ctx, &opt);
16112a8682a8SVincenzo Maffione if (ret != 0) {
16122a8682a8SVincenzo Maffione return ret;
16132a8682a8SVincenzo Maffione }
16142a8682a8SVincenzo Maffione
16152a8682a8SVincenzo Maffione ret = port_register_hwall(ctx);
16162a8682a8SVincenzo Maffione if (ret != 0) {
16172a8682a8SVincenzo Maffione return ret;
16182a8682a8SVincenzo Maffione }
16192a8682a8SVincenzo Maffione clear_options(ctx);
16202a8682a8SVincenzo Maffione
16212a8682a8SVincenzo Maffione ret = sem_init(&sem, 0, 0);
16222a8682a8SVincenzo Maffione if (ret != 0) {
16232a8682a8SVincenzo Maffione printf("sem_init() failed: %s\n", strerror(ret));
16242a8682a8SVincenzo Maffione return ret;
16252a8682a8SVincenzo Maffione }
16262a8682a8SVincenzo Maffione ctx->sem = &sem;
16272a8682a8SVincenzo Maffione
16282a8682a8SVincenzo Maffione ret = pthread_create(&th1, NULL, sync_kloop_worker, ctx);
16292a8682a8SVincenzo Maffione err |= ret;
16302a8682a8SVincenzo Maffione if (ret != 0) {
16312a8682a8SVincenzo Maffione printf("pthread_create(kloop1): %s\n", strerror(ret));
16322a8682a8SVincenzo Maffione }
16332a8682a8SVincenzo Maffione
16342a8682a8SVincenzo Maffione ret = pthread_create(&th2, NULL, sync_kloop_worker, ctx);
16352a8682a8SVincenzo Maffione err |= ret;
16362a8682a8SVincenzo Maffione if (ret != 0) {
16372a8682a8SVincenzo Maffione printf("pthread_create(kloop2): %s\n", strerror(ret));
16382a8682a8SVincenzo Maffione }
16392a8682a8SVincenzo Maffione
16402a8682a8SVincenzo Maffione /* Wait for one of the two threads to fail to start the kloop, to
16412a8682a8SVincenzo Maffione * avoid a race condition where th1 starts the loop and stops,
16422a8682a8SVincenzo Maffione * and after that th2 starts the loop successfully. */
16432a8682a8SVincenzo Maffione clock_gettime(CLOCK_REALTIME, &to);
16442a8682a8SVincenzo Maffione to.tv_sec += 2;
16452a8682a8SVincenzo Maffione ret = sem_timedwait(&sem, &to);
16462a8682a8SVincenzo Maffione err |= ret;
16472a8682a8SVincenzo Maffione if (ret != 0) {
16482a8682a8SVincenzo Maffione printf("sem_timedwait() failed: %s\n", strerror(errno));
16492a8682a8SVincenzo Maffione }
16502a8682a8SVincenzo Maffione
16512a8682a8SVincenzo Maffione err |= sync_kloop_stop(ctx);
16522a8682a8SVincenzo Maffione
16532a8682a8SVincenzo Maffione ret = pthread_join(th1, &thret1);
16542a8682a8SVincenzo Maffione err |= ret;
16552a8682a8SVincenzo Maffione if (ret != 0) {
16562a8682a8SVincenzo Maffione printf("pthread_join(kloop1): %s\n", strerror(ret));
16572a8682a8SVincenzo Maffione }
16582a8682a8SVincenzo Maffione
16592a8682a8SVincenzo Maffione ret = pthread_join(th2, &thret2);
16602a8682a8SVincenzo Maffione err |= ret;
16612a8682a8SVincenzo Maffione if (ret != 0) {
16622a8682a8SVincenzo Maffione printf("pthread_join(kloop2): %s %d\n", strerror(ret), ret);
16632a8682a8SVincenzo Maffione }
16642a8682a8SVincenzo Maffione
16652a8682a8SVincenzo Maffione sem_destroy(&sem);
16662a8682a8SVincenzo Maffione ctx->sem = NULL;
16672a8682a8SVincenzo Maffione if (err) {
16682a8682a8SVincenzo Maffione return err;
16692a8682a8SVincenzo Maffione }
16702a8682a8SVincenzo Maffione
16712a8682a8SVincenzo Maffione /* Check that one of the two failed, while the other one succeeded. */
16722a8682a8SVincenzo Maffione return ((thret1 == THRET_SUCCESS && thret2 == THRET_FAILURE) ||
16732a8682a8SVincenzo Maffione (thret1 == THRET_FAILURE && thret2 == THRET_SUCCESS))
16742a8682a8SVincenzo Maffione ? 0
16752a8682a8SVincenzo Maffione : -1;
16762a8682a8SVincenzo Maffione }
16772a8682a8SVincenzo Maffione
16782a8682a8SVincenzo Maffione static int
sync_kloop_eventfds_mismatch(struct TestContext * ctx)16792a8682a8SVincenzo Maffione sync_kloop_eventfds_mismatch(struct TestContext *ctx)
16802a8682a8SVincenzo Maffione {
16812a8682a8SVincenzo Maffione struct nmreq_opt_csb opt;
16822a8682a8SVincenzo Maffione int ret;
16832a8682a8SVincenzo Maffione
16842a8682a8SVincenzo Maffione ret = push_csb_option(ctx, &opt);
16852a8682a8SVincenzo Maffione if (ret != 0) {
16862a8682a8SVincenzo Maffione return ret;
16872a8682a8SVincenzo Maffione }
16882a8682a8SVincenzo Maffione
16892a8682a8SVincenzo Maffione ret = port_register_hwall_rx(ctx);
16902a8682a8SVincenzo Maffione if (ret != 0) {
16912a8682a8SVincenzo Maffione return ret;
16922a8682a8SVincenzo Maffione }
16932a8682a8SVincenzo Maffione clear_options(ctx);
16942a8682a8SVincenzo Maffione
16952a8682a8SVincenzo Maffione /* Deceive num_registered_rings() to trigger a failure of
16962a8682a8SVincenzo Maffione * sync_kloop_eventfds(). The latter will think that all the
16972a8682a8SVincenzo Maffione * rings were registered, and allocate the wrong number of
16982a8682a8SVincenzo Maffione * eventfds. */
16992a8682a8SVincenzo Maffione ctx->nr_flags &= ~NR_RX_RINGS_ONLY;
17002a8682a8SVincenzo Maffione
17012a8682a8SVincenzo Maffione return (sync_kloop_eventfds(ctx) != 0) ? 0 : -1;
17022a8682a8SVincenzo Maffione }
17032a8682a8SVincenzo Maffione
17042a8682a8SVincenzo Maffione static int
null_port(struct TestContext * ctx)17052a8682a8SVincenzo Maffione null_port(struct TestContext *ctx)
17062a8682a8SVincenzo Maffione {
17072a8682a8SVincenzo Maffione int ret;
17082a8682a8SVincenzo Maffione
17092a8682a8SVincenzo Maffione ctx->nr_mem_id = 1;
17102a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NULL;
17112a8682a8SVincenzo Maffione ctx->nr_tx_rings = 10;
17122a8682a8SVincenzo Maffione ctx->nr_rx_rings = 5;
17132a8682a8SVincenzo Maffione ctx->nr_tx_slots = 256;
17142a8682a8SVincenzo Maffione ctx->nr_rx_slots = 100;
17152a8682a8SVincenzo Maffione ret = port_register(ctx);
17162a8682a8SVincenzo Maffione if (ret != 0) {
17172a8682a8SVincenzo Maffione return ret;
17182a8682a8SVincenzo Maffione }
17192a8682a8SVincenzo Maffione return 0;
17202a8682a8SVincenzo Maffione }
17212a8682a8SVincenzo Maffione
17222a8682a8SVincenzo Maffione static int
null_port_all_zero(struct TestContext * ctx)17232a8682a8SVincenzo Maffione null_port_all_zero(struct TestContext *ctx)
17242a8682a8SVincenzo Maffione {
17252a8682a8SVincenzo Maffione int ret;
17262a8682a8SVincenzo Maffione
17272a8682a8SVincenzo Maffione ctx->nr_mem_id = 1;
17282a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NULL;
17292a8682a8SVincenzo Maffione ctx->nr_tx_rings = 0;
17302a8682a8SVincenzo Maffione ctx->nr_rx_rings = 0;
17312a8682a8SVincenzo Maffione ctx->nr_tx_slots = 0;
17322a8682a8SVincenzo Maffione ctx->nr_rx_slots = 0;
17332a8682a8SVincenzo Maffione ret = port_register(ctx);
17342a8682a8SVincenzo Maffione if (ret != 0) {
17352a8682a8SVincenzo Maffione return ret;
17362a8682a8SVincenzo Maffione }
17372a8682a8SVincenzo Maffione return 0;
17382a8682a8SVincenzo Maffione }
17392a8682a8SVincenzo Maffione
17402a8682a8SVincenzo Maffione static int
null_port_sync(struct TestContext * ctx)17412a8682a8SVincenzo Maffione null_port_sync(struct TestContext *ctx)
17422a8682a8SVincenzo Maffione {
17432a8682a8SVincenzo Maffione int ret;
17442a8682a8SVincenzo Maffione
17452a8682a8SVincenzo Maffione ctx->nr_mem_id = 1;
17462a8682a8SVincenzo Maffione ctx->nr_mode = NR_REG_NULL;
17472a8682a8SVincenzo Maffione ctx->nr_tx_rings = 10;
17482a8682a8SVincenzo Maffione ctx->nr_rx_rings = 5;
17492a8682a8SVincenzo Maffione ctx->nr_tx_slots = 256;
17502a8682a8SVincenzo Maffione ctx->nr_rx_slots = 100;
17512a8682a8SVincenzo Maffione ret = port_register(ctx);
17522a8682a8SVincenzo Maffione if (ret != 0) {
17532a8682a8SVincenzo Maffione return ret;
17542a8682a8SVincenzo Maffione }
17552a8682a8SVincenzo Maffione ret = ioctl(ctx->fd, NIOCTXSYNC, 0);
17562a8682a8SVincenzo Maffione if (ret != 0) {
17572a8682a8SVincenzo Maffione return ret;
17582a8682a8SVincenzo Maffione }
17592a8682a8SVincenzo Maffione return 0;
17602a8682a8SVincenzo Maffione }
17612a8682a8SVincenzo Maffione
176236d6e657SVincenzo Maffione struct nmreq_parse_test {
176336d6e657SVincenzo Maffione const char *ifname;
176436d6e657SVincenzo Maffione const char *exp_port;
176536d6e657SVincenzo Maffione const char *exp_suff;
176636d6e657SVincenzo Maffione int exp_error;
176736d6e657SVincenzo Maffione uint32_t exp_mode;
176836d6e657SVincenzo Maffione uint16_t exp_ringid;
176936d6e657SVincenzo Maffione uint64_t exp_flags;
177036d6e657SVincenzo Maffione };
177136d6e657SVincenzo Maffione
177236d6e657SVincenzo Maffione static struct nmreq_parse_test nmreq_parse_tests[] = {
177336d6e657SVincenzo Maffione /* port spec is the input. The expected results are as follows:
177436d6e657SVincenzo Maffione * - port: what should go into hdr.nr_name
177536d6e657SVincenzo Maffione * - suff: the trailing part of the input after parsing (NULL means equal to port spec)
177636d6e657SVincenzo Maffione * - err: the expected return value, interpreted as follows
177736d6e657SVincenzo Maffione * err > 0 => nmreq_header_parse should fail with the given error
177836d6e657SVincenzo Maffione * err < 0 => nrmeq_header_parse should succeed, but nmreq_register_decode should
177936d6e657SVincenzo Maffione * fail with error |err|
178036d6e657SVincenzo Maffione * err = 0 => should succeed
178136d6e657SVincenzo Maffione * - mode, ringid flags: what should go into the corresponding nr_* fields in the
178236d6e657SVincenzo Maffione * nmreq_register struct in case of success
178336d6e657SVincenzo Maffione */
178436d6e657SVincenzo Maffione
178536d6e657SVincenzo Maffione /*port spec*/ /*port*/ /*suff*/ /*err*/ /*mode*/ /*ringid*/ /*flags*/
178636d6e657SVincenzo Maffione { "netmap:eth0", "eth0", "", 0, NR_REG_ALL_NIC, 0, 0 },
178736d6e657SVincenzo Maffione { "netmap:eth0-1", "eth0", "", 0, NR_REG_ONE_NIC, 1, 0 },
178836d6e657SVincenzo Maffione { "netmap:eth0-", "eth0", "-", -EINVAL,0, 0, 0 },
178936d6e657SVincenzo Maffione { "netmap:eth0/x", "eth0", "", 0, NR_REG_ALL_NIC, 0, NR_EXCLUSIVE },
179036d6e657SVincenzo Maffione { "netmap:eth0/z", "eth0", "", 0, NR_REG_ALL_NIC, 0, NR_ZCOPY_MON },
179136d6e657SVincenzo Maffione { "netmap:eth0/r", "eth0", "", 0, NR_REG_ALL_NIC, 0, NR_MONITOR_RX },
179236d6e657SVincenzo Maffione { "netmap:eth0/t", "eth0", "", 0, NR_REG_ALL_NIC, 0, NR_MONITOR_TX },
179336d6e657SVincenzo Maffione { "netmap:eth0-2/Tx", "eth0", "", 0, NR_REG_ONE_NIC, 2, NR_TX_RINGS_ONLY|NR_EXCLUSIVE },
179436d6e657SVincenzo Maffione { "netmap:eth0*", "eth0", "", 0, NR_REG_NIC_SW, 0, 0 },
179536d6e657SVincenzo Maffione { "netmap:eth0^", "eth0", "", 0, NR_REG_SW, 0, 0 },
179636d6e657SVincenzo Maffione { "netmap:eth0@2", "eth0", "", 0, NR_REG_ALL_NIC, 0, 0 },
179736d6e657SVincenzo Maffione { "netmap:eth0@2/R", "eth0", "", 0, NR_REG_ALL_NIC, 0, NR_RX_RINGS_ONLY },
179836d6e657SVincenzo Maffione { "netmap:eth0@netmap:lo/R", "eth0", "@netmap:lo/R", 0, NR_REG_ALL_NIC, 0, 0 },
179936d6e657SVincenzo Maffione { "netmap:eth0/R@xxx", "eth0", "@xxx", 0, NR_REG_ALL_NIC, 0, NR_RX_RINGS_ONLY },
180036d6e657SVincenzo Maffione { "netmap:eth0@2/R@2", "eth0", "", 0, NR_REG_ALL_NIC, 0, NR_RX_RINGS_ONLY },
180136d6e657SVincenzo Maffione { "netmap:eth0@2/R@3", "eth0", "@2/R@3", -EINVAL,0, 0, 0 },
180236d6e657SVincenzo Maffione { "netmap:eth0@", "eth0", "@", -EINVAL,0, 0, 0 },
180336d6e657SVincenzo Maffione { "netmap:", "", NULL, EINVAL, 0, 0, 0 },
180436d6e657SVincenzo Maffione { "netmap:^", "", NULL, EINVAL, 0, 0, 0 },
180536d6e657SVincenzo Maffione { "netmap:{", "", NULL, EINVAL, 0, 0, 0 },
180636d6e657SVincenzo Maffione { "eth0", NULL, NULL, EINVAL, 0, 0, 0 },
180736d6e657SVincenzo Maffione { "vale0:0", "vale0:0", "", 0, NR_REG_ALL_NIC, 0, 0 },
180836d6e657SVincenzo Maffione { "vale:0", "vale:0", "", 0, NR_REG_ALL_NIC, 0, 0 },
180936d6e657SVincenzo Maffione { "valeXXX:YYY", "valeXXX:YYY", "", 0, NR_REG_ALL_NIC, 0, 0 },
181036d6e657SVincenzo Maffione { "valeXXX:YYY-4", "valeXXX:YYY", "", 0, NR_REG_ONE_NIC, 4, 0 },
181136d6e657SVincenzo Maffione { "netmapXXX:eth0", NULL, NULL, EINVAL, 0, 0, 0 },
181236d6e657SVincenzo Maffione { "netmap:14", "14", "", 0, NR_REG_ALL_NIC, 0, 0 },
181336d6e657SVincenzo Maffione { "netmap:pipe{0", "pipe{0", "", 0, NR_REG_ALL_NIC, 0, 0 },
181436d6e657SVincenzo Maffione { "netmap:pipe{in", "pipe{in", "", 0, NR_REG_ALL_NIC, 0, 0 },
181536d6e657SVincenzo Maffione { "netmap:pipe{in-7", "pipe{in", "", 0, NR_REG_ONE_NIC, 7, 0 },
181636d6e657SVincenzo Maffione { "vale0:0{0", "vale0:0{0", "", 0, NR_REG_ALL_NIC, 0, 0 },
181736d6e657SVincenzo Maffione { "netmap:pipe{1}2", NULL, NULL, EINVAL, 0, 0, 0 },
181836d6e657SVincenzo Maffione { "vale0:0@opt", "vale0:0", "@opt", 0, NR_REG_ALL_NIC, 0, 0 },
181936d6e657SVincenzo Maffione { "vale0:0/Tx@opt", "vale0:0", "@opt", 0, NR_REG_ALL_NIC, 0, NR_TX_RINGS_ONLY|NR_EXCLUSIVE },
182036d6e657SVincenzo Maffione { "vale0:0-3@opt", "vale0:0", "@opt", 0, NR_REG_ONE_NIC, 3, 0 },
182136d6e657SVincenzo Maffione { "vale0:0@", "vale0:0", "@", -EINVAL,0, 0, 0 },
182236d6e657SVincenzo Maffione { "", NULL, NULL, EINVAL, 0, 0, 0 },
182336d6e657SVincenzo Maffione { NULL, NULL, NULL, 0, 0, 0, 0 },
182436d6e657SVincenzo Maffione };
182536d6e657SVincenzo Maffione
182636d6e657SVincenzo Maffione static void
randomize(void * dst,size_t n)182736d6e657SVincenzo Maffione randomize(void *dst, size_t n)
182836d6e657SVincenzo Maffione {
182936d6e657SVincenzo Maffione size_t i;
183036d6e657SVincenzo Maffione char *dst_ = dst;
183136d6e657SVincenzo Maffione
183236d6e657SVincenzo Maffione for (i = 0; i < n; i++)
183336d6e657SVincenzo Maffione dst_[i] = (char)random();
183436d6e657SVincenzo Maffione }
183536d6e657SVincenzo Maffione
183636d6e657SVincenzo Maffione static int
nmreq_hdr_parsing(struct TestContext * ctx,struct nmreq_parse_test * t,struct nmreq_header * hdr)183736d6e657SVincenzo Maffione nmreq_hdr_parsing(struct TestContext *ctx,
183836d6e657SVincenzo Maffione struct nmreq_parse_test *t,
183936d6e657SVincenzo Maffione struct nmreq_header *hdr)
184036d6e657SVincenzo Maffione {
184136d6e657SVincenzo Maffione const char *save;
184236d6e657SVincenzo Maffione struct nmreq_header orig_hdr;
184336d6e657SVincenzo Maffione
184436d6e657SVincenzo Maffione save = ctx->ifparse = t->ifname;
184536d6e657SVincenzo Maffione orig_hdr = *hdr;
184636d6e657SVincenzo Maffione
184736d6e657SVincenzo Maffione printf("nmreq_header: \"%s\"\n", ctx->ifparse);
184836d6e657SVincenzo Maffione if (nmreq_header_decode(&ctx->ifparse, hdr, ctx->nmctx) < 0) {
184936d6e657SVincenzo Maffione if (t->exp_error > 0) {
185036d6e657SVincenzo Maffione if (errno != t->exp_error) {
185136d6e657SVincenzo Maffione printf("!!! got errno=%d, want %d\n",
185236d6e657SVincenzo Maffione errno, t->exp_error);
185336d6e657SVincenzo Maffione return -1;
185436d6e657SVincenzo Maffione }
185536d6e657SVincenzo Maffione if (ctx->ifparse != save) {
185636d6e657SVincenzo Maffione printf("!!! parse error, but first arg changed\n");
185736d6e657SVincenzo Maffione return -1;
185836d6e657SVincenzo Maffione }
185936d6e657SVincenzo Maffione if (memcmp(&orig_hdr, hdr, sizeof(*hdr))) {
186036d6e657SVincenzo Maffione printf("!!! parse error, but header changed\n");
186136d6e657SVincenzo Maffione return -1;
186236d6e657SVincenzo Maffione }
186336d6e657SVincenzo Maffione return 0;
186436d6e657SVincenzo Maffione }
186536d6e657SVincenzo Maffione printf ("!!! nmreq_header_decode was expected to succeed, but it failed with error %d\n", errno);
186636d6e657SVincenzo Maffione return -1;
186736d6e657SVincenzo Maffione }
186836d6e657SVincenzo Maffione if (t->exp_error > 0) {
186936d6e657SVincenzo Maffione printf("!!! nmreq_header_decode returns 0, but error %d was expected\n", t->exp_error);
187036d6e657SVincenzo Maffione return -1;
187136d6e657SVincenzo Maffione }
187236d6e657SVincenzo Maffione if (strcmp(t->exp_port, hdr->nr_name) != 0) {
187336d6e657SVincenzo Maffione printf("!!! got '%s', want '%s'\n", hdr->nr_name, t->exp_port);
187436d6e657SVincenzo Maffione return -1;
187536d6e657SVincenzo Maffione }
187636d6e657SVincenzo Maffione if (hdr->nr_reqtype != orig_hdr.nr_reqtype ||
187736d6e657SVincenzo Maffione hdr->nr_options != orig_hdr.nr_options ||
187836d6e657SVincenzo Maffione hdr->nr_body != orig_hdr.nr_body) {
187936d6e657SVincenzo Maffione printf("!!! some fields of the nmreq_header where changed unexpectedly\n");
188036d6e657SVincenzo Maffione return -1;
188136d6e657SVincenzo Maffione }
188236d6e657SVincenzo Maffione return 0;
188336d6e657SVincenzo Maffione }
188436d6e657SVincenzo Maffione
188536d6e657SVincenzo Maffione static int
nmreq_reg_parsing(struct TestContext * ctx,struct nmreq_parse_test * t,struct nmreq_register * reg)188636d6e657SVincenzo Maffione nmreq_reg_parsing(struct TestContext *ctx,
188736d6e657SVincenzo Maffione struct nmreq_parse_test *t,
188836d6e657SVincenzo Maffione struct nmreq_register *reg)
188936d6e657SVincenzo Maffione {
189036d6e657SVincenzo Maffione const char *save;
189136d6e657SVincenzo Maffione struct nmreq_register orig_reg;
189236d6e657SVincenzo Maffione
189336d6e657SVincenzo Maffione
189436d6e657SVincenzo Maffione save = ctx->ifparse;
189536d6e657SVincenzo Maffione orig_reg = *reg;
189636d6e657SVincenzo Maffione
189736d6e657SVincenzo Maffione printf("nmreq_register: \"%s\"\n", ctx->ifparse);
189836d6e657SVincenzo Maffione if (nmreq_register_decode(&ctx->ifparse, reg, ctx->nmctx) < 0) {
189936d6e657SVincenzo Maffione if (t->exp_error < 0) {
190036d6e657SVincenzo Maffione if (errno != -t->exp_error) {
190136d6e657SVincenzo Maffione printf("!!! got errno=%d, want %d\n",
190236d6e657SVincenzo Maffione errno, -t->exp_error);
190336d6e657SVincenzo Maffione return -1;
190436d6e657SVincenzo Maffione }
190536d6e657SVincenzo Maffione if (ctx->ifparse != save) {
190636d6e657SVincenzo Maffione printf("!!! parse error, but first arg changed\n");
190736d6e657SVincenzo Maffione return -1;
190836d6e657SVincenzo Maffione }
190936d6e657SVincenzo Maffione if (memcmp(&orig_reg, reg, sizeof(*reg))) {
191036d6e657SVincenzo Maffione printf("!!! parse error, but nmreq_register changed\n");
191136d6e657SVincenzo Maffione return -1;
191236d6e657SVincenzo Maffione }
191336d6e657SVincenzo Maffione return 0;
191436d6e657SVincenzo Maffione }
191536d6e657SVincenzo Maffione printf ("!!! parse failed but it should have succeeded\n");
191636d6e657SVincenzo Maffione return -1;
191736d6e657SVincenzo Maffione }
191836d6e657SVincenzo Maffione if (t->exp_error < 0) {
191936d6e657SVincenzo Maffione printf("!!! nmreq_register_decode returns 0, but error %d was expected\n", -t->exp_error);
192036d6e657SVincenzo Maffione return -1;
192136d6e657SVincenzo Maffione }
192236d6e657SVincenzo Maffione if (reg->nr_mode != t->exp_mode) {
192336d6e657SVincenzo Maffione printf("!!! got nr_mode '%d', want '%d'\n", reg->nr_mode, t->exp_mode);
192436d6e657SVincenzo Maffione return -1;
192536d6e657SVincenzo Maffione }
192636d6e657SVincenzo Maffione if (reg->nr_ringid != t->exp_ringid) {
192736d6e657SVincenzo Maffione printf("!!! got nr_ringid '%d', want '%d'\n", reg->nr_ringid, t->exp_ringid);
192836d6e657SVincenzo Maffione return -1;
192936d6e657SVincenzo Maffione }
193036d6e657SVincenzo Maffione if (reg->nr_flags != t->exp_flags) {
193136d6e657SVincenzo Maffione printf("!!! got nm_flags '%llx', want '%llx\n", (unsigned long long)reg->nr_flags,
193236d6e657SVincenzo Maffione (unsigned long long)t->exp_flags);
193336d6e657SVincenzo Maffione return -1;
193436d6e657SVincenzo Maffione }
193536d6e657SVincenzo Maffione if (reg->nr_offset != orig_reg.nr_offset ||
193636d6e657SVincenzo Maffione reg->nr_memsize != orig_reg.nr_memsize ||
193736d6e657SVincenzo Maffione reg->nr_tx_slots != orig_reg.nr_tx_slots ||
193836d6e657SVincenzo Maffione reg->nr_rx_slots != orig_reg.nr_rx_slots ||
193936d6e657SVincenzo Maffione reg->nr_tx_rings != orig_reg.nr_tx_rings ||
194036d6e657SVincenzo Maffione reg->nr_rx_rings != orig_reg.nr_rx_rings ||
194136d6e657SVincenzo Maffione reg->nr_extra_bufs != orig_reg.nr_extra_bufs)
194236d6e657SVincenzo Maffione {
194336d6e657SVincenzo Maffione printf("!!! some fields of the nmreq_register where changed unexpectedly\n");
194436d6e657SVincenzo Maffione return -1;
194536d6e657SVincenzo Maffione }
194636d6e657SVincenzo Maffione return 0;
194736d6e657SVincenzo Maffione }
194836d6e657SVincenzo Maffione
194936d6e657SVincenzo Maffione static void
nmctx_parsing_error(struct nmctx * ctx,const char * msg)195036d6e657SVincenzo Maffione nmctx_parsing_error(struct nmctx *ctx, const char *msg)
195136d6e657SVincenzo Maffione {
195236d6e657SVincenzo Maffione (void)ctx;
195336d6e657SVincenzo Maffione printf(" got message: %s\n", msg);
195436d6e657SVincenzo Maffione }
195536d6e657SVincenzo Maffione
195636d6e657SVincenzo Maffione static int
nmreq_parsing(struct TestContext * ctx)195736d6e657SVincenzo Maffione nmreq_parsing(struct TestContext *ctx)
195836d6e657SVincenzo Maffione {
195936d6e657SVincenzo Maffione struct nmreq_parse_test *t;
196036d6e657SVincenzo Maffione struct nmreq_header hdr;
196136d6e657SVincenzo Maffione struct nmreq_register reg;
196236d6e657SVincenzo Maffione struct nmctx test_nmctx, *nmctx;
196336d6e657SVincenzo Maffione int ret = 0;
196436d6e657SVincenzo Maffione
196536d6e657SVincenzo Maffione nmctx = nmctx_get();
196636d6e657SVincenzo Maffione if (nmctx == NULL) {
196736d6e657SVincenzo Maffione printf("Failed to acquire nmctx: %s", strerror(errno));
196836d6e657SVincenzo Maffione return -1;
196936d6e657SVincenzo Maffione }
197036d6e657SVincenzo Maffione test_nmctx = *nmctx;
197136d6e657SVincenzo Maffione test_nmctx.error = nmctx_parsing_error;
197236d6e657SVincenzo Maffione ctx->nmctx = &test_nmctx;
197336d6e657SVincenzo Maffione for (t = nmreq_parse_tests; t->ifname != NULL; t++) {
197436d6e657SVincenzo Maffione const char *exp_suff = t->exp_suff != NULL ?
197536d6e657SVincenzo Maffione t->exp_suff : t->ifname;
197636d6e657SVincenzo Maffione
197736d6e657SVincenzo Maffione randomize(&hdr, sizeof(hdr));
197836d6e657SVincenzo Maffione randomize(®, sizeof(reg));
197936d6e657SVincenzo Maffione reg.nr_mem_id = 0;
198036d6e657SVincenzo Maffione if (nmreq_hdr_parsing(ctx, t, &hdr) < 0) {
198136d6e657SVincenzo Maffione ret = -1;
198236d6e657SVincenzo Maffione } else if (t->exp_error <= 0 && nmreq_reg_parsing(ctx, t, ®) < 0) {
198336d6e657SVincenzo Maffione ret = -1;
198436d6e657SVincenzo Maffione }
198536d6e657SVincenzo Maffione if (strcmp(ctx->ifparse, exp_suff) != 0) {
198636d6e657SVincenzo Maffione printf("!!! string suffix after parse is '%s', but it should be '%s'\n",
198736d6e657SVincenzo Maffione ctx->ifparse, exp_suff);
198836d6e657SVincenzo Maffione ret = -1;
198936d6e657SVincenzo Maffione }
199036d6e657SVincenzo Maffione }
1991f4db3905SJohn Baldwin ctx->nmctx = NULL;
199236d6e657SVincenzo Maffione return ret;
199336d6e657SVincenzo Maffione }
199436d6e657SVincenzo Maffione
199536d6e657SVincenzo Maffione static int
binarycomp(struct TestContext * ctx)199636d6e657SVincenzo Maffione binarycomp(struct TestContext *ctx)
199736d6e657SVincenzo Maffione {
199836d6e657SVincenzo Maffione #define ckroff(f, o) do {\
199936d6e657SVincenzo Maffione if (offsetof(struct netmap_ring, f) != (o)) {\
200036d6e657SVincenzo Maffione printf("offset of netmap_ring.%s is %zd, but it should be %d",\
200136d6e657SVincenzo Maffione #f, offsetof(struct netmap_ring, f), (o));\
200236d6e657SVincenzo Maffione return -1;\
200336d6e657SVincenzo Maffione }\
200436d6e657SVincenzo Maffione } while (0)
200536d6e657SVincenzo Maffione
200636d6e657SVincenzo Maffione (void)ctx;
200736d6e657SVincenzo Maffione
200836d6e657SVincenzo Maffione ckroff(buf_ofs, 0);
200936d6e657SVincenzo Maffione ckroff(num_slots, 8);
201036d6e657SVincenzo Maffione ckroff(nr_buf_size, 12);
201136d6e657SVincenzo Maffione ckroff(ringid, 16);
201236d6e657SVincenzo Maffione ckroff(dir, 18);
201336d6e657SVincenzo Maffione ckroff(head, 20);
201436d6e657SVincenzo Maffione ckroff(cur, 24);
201536d6e657SVincenzo Maffione ckroff(tail, 28);
201636d6e657SVincenzo Maffione ckroff(flags, 32);
201736d6e657SVincenzo Maffione ckroff(ts, 40);
201836d6e657SVincenzo Maffione ckroff(offset_mask, 56);
201936d6e657SVincenzo Maffione ckroff(buf_align, 64);
202036d6e657SVincenzo Maffione ckroff(sem, 128);
202136d6e657SVincenzo Maffione ckroff(slot, 256);
202236d6e657SVincenzo Maffione
202336d6e657SVincenzo Maffione return 0;
202436d6e657SVincenzo Maffione }
202536d6e657SVincenzo Maffione
20262a8682a8SVincenzo Maffione static void
usage(const char * prog)20272a8682a8SVincenzo Maffione usage(const char *prog)
20282a8682a8SVincenzo Maffione {
20292a8682a8SVincenzo Maffione printf("%s -i IFNAME\n"
20302a8682a8SVincenzo Maffione "[-j TEST_NUM1[-[TEST_NUM2]] | -[TEST_NUM_2]]\n"
20312a8682a8SVincenzo Maffione "[-l (list test cases)]\n",
20322a8682a8SVincenzo Maffione prog);
20332a8682a8SVincenzo Maffione }
20342a8682a8SVincenzo Maffione
20352a8682a8SVincenzo Maffione struct mytest {
20362a8682a8SVincenzo Maffione testfunc_t test;
20372a8682a8SVincenzo Maffione const char *name;
20382a8682a8SVincenzo Maffione };
20392a8682a8SVincenzo Maffione
20402a8682a8SVincenzo Maffione #define decltest(f) \
20412a8682a8SVincenzo Maffione { \
20422a8682a8SVincenzo Maffione .test = f, .name = #f \
20432a8682a8SVincenzo Maffione }
20442a8682a8SVincenzo Maffione
20452a8682a8SVincenzo Maffione static struct mytest tests[] = {
20462a8682a8SVincenzo Maffione decltest(port_info_get),
20472a8682a8SVincenzo Maffione decltest(port_register_hwall_host),
20482a8682a8SVincenzo Maffione decltest(port_register_hwall),
20494f6858e8SVincenzo Maffione decltest(port_register_hostall),
20504f6858e8SVincenzo Maffione decltest(port_register_single_hw_pair),
20514f6858e8SVincenzo Maffione decltest(port_register_single_host_pair),
20524f6858e8SVincenzo Maffione decltest(port_register_hostall_many),
20532a8682a8SVincenzo Maffione decltest(vale_attach_detach),
20542a8682a8SVincenzo Maffione decltest(vale_attach_detach_host_rings),
20552a8682a8SVincenzo Maffione decltest(vale_ephemeral_port_hdr_manipulation),
20562a8682a8SVincenzo Maffione decltest(vale_persistent_port),
20572a8682a8SVincenzo Maffione decltest(pools_info_get_and_register),
20582a8682a8SVincenzo Maffione decltest(pools_info_get_empty_ifname),
20592a8682a8SVincenzo Maffione decltest(pipe_master),
20602a8682a8SVincenzo Maffione decltest(pipe_slave),
20612a8682a8SVincenzo Maffione decltest(pipe_port_info_get),
20622a8682a8SVincenzo Maffione decltest(pipe_pools_info_get),
20632a8682a8SVincenzo Maffione decltest(vale_polling_enable_disable),
20642a8682a8SVincenzo Maffione decltest(unsupported_option),
20652a8682a8SVincenzo Maffione decltest(infinite_options),
2066e2a431a0SVincenzo Maffione decltest(infinite_options2),
20672a8682a8SVincenzo Maffione #ifdef CONFIG_NETMAP_EXTMEM
20682a8682a8SVincenzo Maffione decltest(extmem_option),
20692a8682a8SVincenzo Maffione decltest(bad_extmem_option),
20702a8682a8SVincenzo Maffione decltest(duplicate_extmem_options),
20712a8682a8SVincenzo Maffione #endif /* CONFIG_NETMAP_EXTMEM */
20722a8682a8SVincenzo Maffione decltest(csb_mode),
20732a8682a8SVincenzo Maffione decltest(csb_mode_invalid_memory),
20742a8682a8SVincenzo Maffione decltest(sync_kloop),
20752a8682a8SVincenzo Maffione decltest(sync_kloop_eventfds_all),
20762a8682a8SVincenzo Maffione decltest(sync_kloop_eventfds_all_tx),
20775e874d26SVincenzo Maffione decltest(sync_kloop_eventfds_all_direct),
20785e874d26SVincenzo Maffione decltest(sync_kloop_eventfds_all_direct_tx),
20795e874d26SVincenzo Maffione decltest(sync_kloop_eventfds_all_direct_rx),
20802a8682a8SVincenzo Maffione decltest(sync_kloop_nocsb),
20812a8682a8SVincenzo Maffione decltest(sync_kloop_csb_enable),
20822a8682a8SVincenzo Maffione decltest(sync_kloop_conflict),
20832a8682a8SVincenzo Maffione decltest(sync_kloop_eventfds_mismatch),
20842a8682a8SVincenzo Maffione decltest(null_port),
20852a8682a8SVincenzo Maffione decltest(null_port_all_zero),
20862a8682a8SVincenzo Maffione decltest(null_port_sync),
20872a8682a8SVincenzo Maffione decltest(legacy_regif_default),
20882a8682a8SVincenzo Maffione decltest(legacy_regif_all_nic),
20892a8682a8SVincenzo Maffione decltest(legacy_regif_12),
20902a8682a8SVincenzo Maffione decltest(legacy_regif_sw),
20912a8682a8SVincenzo Maffione decltest(legacy_regif_future),
20922a8682a8SVincenzo Maffione decltest(legacy_regif_extra_bufs),
20932a8682a8SVincenzo Maffione decltest(legacy_regif_extra_bufs_pipe),
20942a8682a8SVincenzo Maffione decltest(legacy_regif_extra_bufs_pipe_vale),
209536d6e657SVincenzo Maffione decltest(nmreq_parsing),
209636d6e657SVincenzo Maffione decltest(binarycomp),
20972a8682a8SVincenzo Maffione };
20982a8682a8SVincenzo Maffione
20992a8682a8SVincenzo Maffione static void
context_cleanup(struct TestContext * ctx)21002a8682a8SVincenzo Maffione context_cleanup(struct TestContext *ctx)
21012a8682a8SVincenzo Maffione {
21022a8682a8SVincenzo Maffione if (ctx->csb) {
21032a8682a8SVincenzo Maffione free(ctx->csb);
21042a8682a8SVincenzo Maffione ctx->csb = NULL;
21052a8682a8SVincenzo Maffione }
21062a8682a8SVincenzo Maffione
21072a8682a8SVincenzo Maffione close(ctx->fd);
21082a8682a8SVincenzo Maffione ctx->fd = -1;
21092a8682a8SVincenzo Maffione }
21102a8682a8SVincenzo Maffione
21112a8682a8SVincenzo Maffione static int
parse_interval(const char * arg,int * j,int * k)21122a8682a8SVincenzo Maffione parse_interval(const char *arg, int *j, int *k)
21132a8682a8SVincenzo Maffione {
21142a8682a8SVincenzo Maffione const char *scan = arg;
21152a8682a8SVincenzo Maffione char *rest;
21162a8682a8SVincenzo Maffione
21172a8682a8SVincenzo Maffione *j = 0;
21182a8682a8SVincenzo Maffione *k = -1;
21192a8682a8SVincenzo Maffione if (*scan == '-') {
21202a8682a8SVincenzo Maffione scan++;
21212a8682a8SVincenzo Maffione goto get_k;
21222a8682a8SVincenzo Maffione }
21232a8682a8SVincenzo Maffione if (!isdigit(*scan))
21242a8682a8SVincenzo Maffione goto err;
21252a8682a8SVincenzo Maffione *k = strtol(scan, &rest, 10);
21262a8682a8SVincenzo Maffione *j = *k - 1;
21272a8682a8SVincenzo Maffione scan = rest;
21282a8682a8SVincenzo Maffione if (*scan == '-') {
21292a8682a8SVincenzo Maffione *k = -1;
21302a8682a8SVincenzo Maffione scan++;
21312a8682a8SVincenzo Maffione }
21322a8682a8SVincenzo Maffione get_k:
21332a8682a8SVincenzo Maffione if (*scan == '\0')
21342a8682a8SVincenzo Maffione return 0;
21352a8682a8SVincenzo Maffione if (!isdigit(*scan))
21362a8682a8SVincenzo Maffione goto err;
21372a8682a8SVincenzo Maffione *k = strtol(scan, &rest, 10);
21382a8682a8SVincenzo Maffione scan = rest;
21392a8682a8SVincenzo Maffione if (!(*scan == '\0'))
21402a8682a8SVincenzo Maffione goto err;
21412a8682a8SVincenzo Maffione
21422a8682a8SVincenzo Maffione return 0;
21432a8682a8SVincenzo Maffione
21442a8682a8SVincenzo Maffione err:
21452a8682a8SVincenzo Maffione fprintf(stderr, "syntax error in '%s', must be num[-[num]] or -[num]\n", arg);
21462a8682a8SVincenzo Maffione return -1;
21472a8682a8SVincenzo Maffione }
21482a8682a8SVincenzo Maffione
21492a8682a8SVincenzo Maffione #define ARGV_APPEND(_av, _ac, _x)\
21502a8682a8SVincenzo Maffione do {\
21512a8682a8SVincenzo Maffione assert((int)(_ac) < (int)(sizeof(_av)/sizeof((_av)[0])));\
21522a8682a8SVincenzo Maffione (_av)[(_ac)++] = _x;\
21532a8682a8SVincenzo Maffione } while (0)
21542a8682a8SVincenzo Maffione
21552a8682a8SVincenzo Maffione static void
tap_cleanup(int signo)21562a8682a8SVincenzo Maffione tap_cleanup(int signo)
21572a8682a8SVincenzo Maffione {
21582a8682a8SVincenzo Maffione const char *av[8];
21592a8682a8SVincenzo Maffione int ac = 0;
21602a8682a8SVincenzo Maffione
21612a8682a8SVincenzo Maffione (void)signo;
21622a8682a8SVincenzo Maffione #ifdef __FreeBSD__
21632a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "ifconfig");
21642a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, ctx_.ifname);
21652a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "destroy");
21662a8682a8SVincenzo Maffione #else
21672a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "ip");
21682a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "link");
21692a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "del");
21702a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, ctx_.ifname);
21712a8682a8SVincenzo Maffione #endif
21722a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, NULL);
21732a8682a8SVincenzo Maffione if (exec_command(ac, av)) {
21742a8682a8SVincenzo Maffione printf("Failed to destroy tap interface\n");
21752a8682a8SVincenzo Maffione }
21762a8682a8SVincenzo Maffione }
21772a8682a8SVincenzo Maffione
21782a8682a8SVincenzo Maffione int
main(int argc,char ** argv)21792a8682a8SVincenzo Maffione main(int argc, char **argv)
21802a8682a8SVincenzo Maffione {
21812a8682a8SVincenzo Maffione int create_tap = 1;
21822a8682a8SVincenzo Maffione int num_tests;
21832a8682a8SVincenzo Maffione int ret = 0;
21842a8682a8SVincenzo Maffione int j = 0;
21852a8682a8SVincenzo Maffione int k = -1;
21862a8682a8SVincenzo Maffione int list = 0;
21872a8682a8SVincenzo Maffione int opt;
21882a8682a8SVincenzo Maffione int i;
21892a8682a8SVincenzo Maffione
21907d757b71SOlivier Cochard #ifdef __FreeBSD__
21917d757b71SOlivier Cochard PLAIN_REQUIRE_KERNEL_MODULE("if_tap", 0);
2192c9c9de93SEnji Cooper PLAIN_REQUIRE_KERNEL_MODULE("netmap", 0);
21937d757b71SOlivier Cochard #endif
21947d757b71SOlivier Cochard
21952a8682a8SVincenzo Maffione memset(&ctx_, 0, sizeof(ctx_));
21962a8682a8SVincenzo Maffione
21972a8682a8SVincenzo Maffione {
21982a8682a8SVincenzo Maffione struct timespec t;
21992a8682a8SVincenzo Maffione int idx;
22002a8682a8SVincenzo Maffione
22012a8682a8SVincenzo Maffione clock_gettime(CLOCK_REALTIME, &t);
22022a8682a8SVincenzo Maffione srand((unsigned int)t.tv_nsec);
22032a8682a8SVincenzo Maffione idx = rand() % 8000 + 100;
22042a8682a8SVincenzo Maffione snprintf(ctx_.ifname, sizeof(ctx_.ifname), "tap%d", idx);
22052a8682a8SVincenzo Maffione idx = rand() % 800 + 100;
22062a8682a8SVincenzo Maffione snprintf(ctx_.bdgname, sizeof(ctx_.bdgname), "vale%d", idx);
22072a8682a8SVincenzo Maffione }
22082a8682a8SVincenzo Maffione
22092a8682a8SVincenzo Maffione while ((opt = getopt(argc, argv, "hi:j:l")) != -1) {
22102a8682a8SVincenzo Maffione switch (opt) {
22112a8682a8SVincenzo Maffione case 'h':
22122a8682a8SVincenzo Maffione usage(argv[0]);
22132a8682a8SVincenzo Maffione return 0;
22142a8682a8SVincenzo Maffione
22152a8682a8SVincenzo Maffione case 'i':
22162a8682a8SVincenzo Maffione strncpy(ctx_.ifname, optarg, sizeof(ctx_.ifname) - 1);
22172a8682a8SVincenzo Maffione create_tap = 0;
22182a8682a8SVincenzo Maffione break;
22192a8682a8SVincenzo Maffione
22202a8682a8SVincenzo Maffione case 'j':
22212a8682a8SVincenzo Maffione if (parse_interval(optarg, &j, &k) < 0) {
22222a8682a8SVincenzo Maffione usage(argv[0]);
22232a8682a8SVincenzo Maffione return -1;
22242a8682a8SVincenzo Maffione }
22252a8682a8SVincenzo Maffione break;
22262a8682a8SVincenzo Maffione
22272a8682a8SVincenzo Maffione case 'l':
22282a8682a8SVincenzo Maffione list = 1;
22292a8682a8SVincenzo Maffione create_tap = 0;
22302a8682a8SVincenzo Maffione break;
22312a8682a8SVincenzo Maffione
22322a8682a8SVincenzo Maffione default:
22332a8682a8SVincenzo Maffione printf(" Unrecognized option %c\n", opt);
22342a8682a8SVincenzo Maffione usage(argv[0]);
22352a8682a8SVincenzo Maffione return -1;
22362a8682a8SVincenzo Maffione }
22372a8682a8SVincenzo Maffione }
22382a8682a8SVincenzo Maffione
22392a8682a8SVincenzo Maffione num_tests = sizeof(tests) / sizeof(tests[0]);
22402a8682a8SVincenzo Maffione
22412a8682a8SVincenzo Maffione if (j < 0 || j >= num_tests || k > num_tests) {
22422a8682a8SVincenzo Maffione fprintf(stderr, "Test interval %d-%d out of range (%d-%d)\n",
22432a8682a8SVincenzo Maffione j + 1, k, 1, num_tests + 1);
22442a8682a8SVincenzo Maffione return -1;
22452a8682a8SVincenzo Maffione }
22462a8682a8SVincenzo Maffione
22472a8682a8SVincenzo Maffione if (k < 0)
22482a8682a8SVincenzo Maffione k = num_tests;
22492a8682a8SVincenzo Maffione
22502a8682a8SVincenzo Maffione if (list) {
22512a8682a8SVincenzo Maffione printf("Available tests:\n");
22522a8682a8SVincenzo Maffione for (i = 0; i < num_tests; i++) {
22532a8682a8SVincenzo Maffione printf("#%03d: %s\n", i + 1, tests[i].name);
22542a8682a8SVincenzo Maffione }
22552a8682a8SVincenzo Maffione return 0;
22562a8682a8SVincenzo Maffione }
22572a8682a8SVincenzo Maffione
22582a8682a8SVincenzo Maffione if (create_tap) {
22592a8682a8SVincenzo Maffione struct sigaction sa;
22602a8682a8SVincenzo Maffione const char *av[8];
22612a8682a8SVincenzo Maffione int ac = 0;
22622a8682a8SVincenzo Maffione #ifdef __FreeBSD__
22632a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "ifconfig");
22642a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, ctx_.ifname);
22652a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "create");
22662a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "up");
22672a8682a8SVincenzo Maffione #else
22682a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "ip");
22692a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "tuntap");
22702a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "add");
22712a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "mode");
22722a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "tap");
22732a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, "name");
22742a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, ctx_.ifname);
22752a8682a8SVincenzo Maffione #endif
22762a8682a8SVincenzo Maffione ARGV_APPEND(av, ac, NULL);
22772a8682a8SVincenzo Maffione if (exec_command(ac, av)) {
22782a8682a8SVincenzo Maffione printf("Failed to create tap interface\n");
22792a8682a8SVincenzo Maffione return -1;
22802a8682a8SVincenzo Maffione }
22812a8682a8SVincenzo Maffione
22822a8682a8SVincenzo Maffione sa.sa_handler = tap_cleanup;
22832a8682a8SVincenzo Maffione sigemptyset(&sa.sa_mask);
22842a8682a8SVincenzo Maffione sa.sa_flags = SA_RESTART;
22852a8682a8SVincenzo Maffione ret = sigaction(SIGINT, &sa, NULL);
22862a8682a8SVincenzo Maffione if (ret) {
22872a8682a8SVincenzo Maffione perror("sigaction(SIGINT)");
22882a8682a8SVincenzo Maffione goto out;
22892a8682a8SVincenzo Maffione }
22902a8682a8SVincenzo Maffione ret = sigaction(SIGTERM, &sa, NULL);
22912a8682a8SVincenzo Maffione if (ret) {
22922a8682a8SVincenzo Maffione perror("sigaction(SIGTERM)");
22932a8682a8SVincenzo Maffione goto out;
22942a8682a8SVincenzo Maffione }
22952a8682a8SVincenzo Maffione }
22962a8682a8SVincenzo Maffione
22972a8682a8SVincenzo Maffione for (i = j; i < k; i++) {
22982a8682a8SVincenzo Maffione struct TestContext ctxcopy;
22992a8682a8SVincenzo Maffione int fd;
23002a8682a8SVincenzo Maffione printf("==> Start of Test #%d [%s]\n", i + 1, tests[i].name);
23012a8682a8SVincenzo Maffione fd = open("/dev/netmap", O_RDWR);
23022a8682a8SVincenzo Maffione if (fd < 0) {
23032a8682a8SVincenzo Maffione perror("open(/dev/netmap)");
23042a8682a8SVincenzo Maffione ret = fd;
23052a8682a8SVincenzo Maffione goto out;
23062a8682a8SVincenzo Maffione }
23072a8682a8SVincenzo Maffione memcpy(&ctxcopy, &ctx_, sizeof(ctxcopy));
23082a8682a8SVincenzo Maffione ctxcopy.fd = fd;
230908f34ad9SVincenzo Maffione memcpy(ctxcopy.ifname_ext, ctxcopy.ifname,
231008f34ad9SVincenzo Maffione sizeof(ctxcopy.ifname));
23112a8682a8SVincenzo Maffione ret = tests[i].test(&ctxcopy);
23122a8682a8SVincenzo Maffione if (ret != 0) {
23132a8682a8SVincenzo Maffione printf("Test #%d [%s] failed\n", i + 1, tests[i].name);
23142a8682a8SVincenzo Maffione goto out;
23152a8682a8SVincenzo Maffione }
23162a8682a8SVincenzo Maffione printf("==> Test #%d [%s] successful\n", i + 1, tests[i].name);
23172a8682a8SVincenzo Maffione context_cleanup(&ctxcopy);
23182a8682a8SVincenzo Maffione }
23192a8682a8SVincenzo Maffione out:
23202a8682a8SVincenzo Maffione tap_cleanup(0);
23212a8682a8SVincenzo Maffione
23222a8682a8SVincenzo Maffione return ret;
23232a8682a8SVincenzo Maffione }
2324