2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (C) 2018 Vincenzo Maffione
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/ioctl.h>
40 #include <net/netmap.h>
42 #include <semaphore.h>
52 #include "freebsd_test_suite/macros.h"
55 eventfd(int x __unused, int y __unused)
61 #include <sys/eventfd.h>
65 exec_command(int argc, const char *const argv[])
72 printf("Executing command: ");
73 for (i = 0; i < argc - 1; i++) {
75 /* Invalid argument. */
81 printf("%s", argv[i]);
90 /* Child process. Redirect stdin, stdout
92 for (i = 0; i < 3; i++) {
94 fds[i] = open("/dev/null", O_RDONLY);
96 for (i--; i >= 0; i--) {
103 /* Make a copy of the arguments, passing them to execvp. */
104 av = calloc(argc, sizeof(av[0]));
108 for (i = 0; i < argc - 1; i++) {
109 av[i] = strdup(argv[i]);
119 wret = waitpid(child_pid, &child_status, 0);
121 fprintf(stderr, "waitpid() failed: %s\n", strerror(errno));
124 if (WIFEXITED(child_status)) {
125 return WEXITSTATUS(child_status);
132 #define THRET_SUCCESS ((void *)128)
133 #define THRET_FAILURE ((void *)0)
137 char ifname_ext[128];
139 uint32_t nr_tx_slots; /* slots in tx rings */
140 uint32_t nr_rx_slots; /* slots in rx rings */
141 uint16_t nr_tx_rings; /* number of tx rings */
142 uint16_t nr_rx_rings; /* number of rx rings */
143 uint16_t nr_host_tx_rings; /* number of host tx rings */
144 uint16_t nr_host_rx_rings; /* number of host rx rings */
145 uint16_t nr_mem_id; /* id of the memory allocator */
146 uint16_t nr_ringid; /* ring(s) we care about */
147 uint32_t nr_mode; /* specify NR_REG_* modes */
148 uint32_t nr_extra_bufs; /* number of requested extra buffers */
149 uint64_t nr_flags; /* additional flags (see below) */
150 uint32_t nr_hdr_len; /* for PORT_HDR_SET and PORT_HDR_GET */
151 uint32_t nr_first_cpu_id; /* vale polling */
152 uint32_t nr_num_polling_cpus; /* vale polling */
153 uint32_t sync_kloop_mode; /* sync-kloop */
154 int fd; /* netmap file descriptor */
156 void *csb; /* CSB entries (atok and ktoa) */
157 struct nmreq_option *nr_opt; /* list of options */
158 sem_t *sem; /* for thread synchronization */
161 static struct TestContext ctx_;
163 typedef int (*testfunc_t)(struct TestContext *ctx);
166 nmreq_hdr_init(struct nmreq_header *hdr, const char *ifname)
168 memset(hdr, 0, sizeof(*hdr));
169 hdr->nr_version = NETMAP_API;
170 strncpy(hdr->nr_name, ifname, sizeof(hdr->nr_name) - 1);
173 /* Single NETMAP_REQ_PORT_INFO_GET. */
175 port_info_get(struct TestContext *ctx)
177 struct nmreq_port_info_get req;
178 struct nmreq_header hdr;
182 printf("Testing NETMAP_REQ_PORT_INFO_GET on '%s'\n", ctx->ifname_ext);
184 nmreq_hdr_init(&hdr, ctx->ifname_ext);
185 hdr.nr_reqtype = NETMAP_REQ_PORT_INFO_GET;
186 hdr.nr_body = (uintptr_t)&req;
187 memset(&req, 0, sizeof(req));
188 req.nr_mem_id = ctx->nr_mem_id;
189 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
191 perror("ioctl(/dev/netmap, NIOCCTRL, PORT_INFO_GET)");
194 printf("nr_memsize %llu\n", (unsigned long long)req.nr_memsize);
195 printf("nr_tx_slots %u\n", req.nr_tx_slots);
196 printf("nr_rx_slots %u\n", req.nr_rx_slots);
197 printf("nr_tx_rings %u\n", req.nr_tx_rings);
198 printf("nr_rx_rings %u\n", req.nr_rx_rings);
199 printf("nr_mem_id %u\n", req.nr_mem_id);
201 success = req.nr_memsize && req.nr_tx_slots && req.nr_rx_slots &&
202 req.nr_tx_rings && req.nr_rx_rings && req.nr_tx_rings;
207 /* Write back results to the context structure. */
208 ctx->nr_tx_slots = req.nr_tx_slots;
209 ctx->nr_rx_slots = req.nr_rx_slots;
210 ctx->nr_tx_rings = req.nr_tx_rings;
211 ctx->nr_rx_rings = req.nr_rx_rings;
212 ctx->nr_mem_id = req.nr_mem_id;
217 /* Single NETMAP_REQ_REGISTER, no use. */
219 port_register(struct TestContext *ctx)
221 struct nmreq_register req;
222 struct nmreq_header hdr;
226 printf("Testing NETMAP_REQ_REGISTER(mode=%d,ringid=%d,"
227 "flags=0x%llx) on '%s'\n",
228 ctx->nr_mode, ctx->nr_ringid, (unsigned long long)ctx->nr_flags,
231 nmreq_hdr_init(&hdr, ctx->ifname_ext);
232 hdr.nr_reqtype = NETMAP_REQ_REGISTER;
233 hdr.nr_body = (uintptr_t)&req;
234 hdr.nr_options = (uintptr_t)ctx->nr_opt;
235 memset(&req, 0, sizeof(req));
236 req.nr_mem_id = ctx->nr_mem_id;
237 req.nr_mode = ctx->nr_mode;
238 req.nr_ringid = ctx->nr_ringid;
239 req.nr_flags = ctx->nr_flags;
240 req.nr_tx_slots = ctx->nr_tx_slots;
241 req.nr_rx_slots = ctx->nr_rx_slots;
242 req.nr_tx_rings = ctx->nr_tx_rings;
243 req.nr_host_tx_rings = ctx->nr_host_tx_rings;
244 req.nr_host_rx_rings = ctx->nr_host_rx_rings;
245 req.nr_rx_rings = ctx->nr_rx_rings;
246 req.nr_extra_bufs = ctx->nr_extra_bufs;
247 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
249 perror("ioctl(/dev/netmap, NIOCCTRL, REGISTER)");
252 printf("nr_offset 0x%llx\n", (unsigned long long)req.nr_offset);
253 printf("nr_memsize %llu\n", (unsigned long long)req.nr_memsize);
254 printf("nr_tx_slots %u\n", req.nr_tx_slots);
255 printf("nr_rx_slots %u\n", req.nr_rx_slots);
256 printf("nr_tx_rings %u\n", req.nr_tx_rings);
257 printf("nr_rx_rings %u\n", req.nr_rx_rings);
258 printf("nr_host_tx_rings %u\n", req.nr_host_tx_rings);
259 printf("nr_host_rx_rings %u\n", req.nr_host_rx_rings);
260 printf("nr_mem_id %u\n", req.nr_mem_id);
261 printf("nr_extra_bufs %u\n", req.nr_extra_bufs);
263 success = req.nr_memsize && (ctx->nr_mode == req.nr_mode) &&
264 (ctx->nr_ringid == req.nr_ringid) &&
265 (ctx->nr_flags == req.nr_flags) &&
266 ((!ctx->nr_tx_slots && req.nr_tx_slots) ||
267 (ctx->nr_tx_slots == req.nr_tx_slots)) &&
268 ((!ctx->nr_rx_slots && req.nr_rx_slots) ||
269 (ctx->nr_rx_slots == req.nr_rx_slots)) &&
270 ((!ctx->nr_tx_rings && req.nr_tx_rings) ||
271 (ctx->nr_tx_rings == req.nr_tx_rings)) &&
272 ((!ctx->nr_rx_rings && req.nr_rx_rings) ||
273 (ctx->nr_rx_rings == req.nr_rx_rings)) &&
274 ((!ctx->nr_host_tx_rings && req.nr_host_tx_rings) ||
275 (ctx->nr_host_tx_rings == req.nr_host_tx_rings)) &&
276 ((!ctx->nr_host_rx_rings && req.nr_host_rx_rings) ||
277 (ctx->nr_host_rx_rings == req.nr_host_rx_rings)) &&
278 ((!ctx->nr_mem_id && req.nr_mem_id) ||
279 (ctx->nr_mem_id == req.nr_mem_id)) &&
280 (ctx->nr_extra_bufs == req.nr_extra_bufs);
285 /* Write back results to the context structure.*/
286 ctx->nr_tx_slots = req.nr_tx_slots;
287 ctx->nr_rx_slots = req.nr_rx_slots;
288 ctx->nr_tx_rings = req.nr_tx_rings;
289 ctx->nr_rx_rings = req.nr_rx_rings;
290 ctx->nr_host_tx_rings = req.nr_host_tx_rings;
291 ctx->nr_host_rx_rings = req.nr_host_rx_rings;
292 ctx->nr_mem_id = req.nr_mem_id;
293 ctx->nr_extra_bufs = req.nr_extra_bufs;
299 niocregif(struct TestContext *ctx, int netmap_api)
305 printf("Testing legacy NIOCREGIF on '%s'\n", ctx->ifname_ext);
307 memset(&req, 0, sizeof(req));
308 memcpy(req.nr_name, ctx->ifname_ext, sizeof(req.nr_name));
309 req.nr_name[sizeof(req.nr_name) - 1] = '\0';
310 req.nr_version = netmap_api;
311 req.nr_ringid = ctx->nr_ringid;
312 req.nr_flags = ctx->nr_mode | ctx->nr_flags;
313 req.nr_tx_slots = ctx->nr_tx_slots;
314 req.nr_rx_slots = ctx->nr_rx_slots;
315 req.nr_tx_rings = ctx->nr_tx_rings;
316 req.nr_rx_rings = ctx->nr_rx_rings;
317 req.nr_arg2 = ctx->nr_mem_id;
318 req.nr_arg3 = ctx->nr_extra_bufs;
320 ret = ioctl(ctx->fd, NIOCREGIF, &req);
322 perror("ioctl(/dev/netmap, NIOCREGIF)");
326 printf("nr_offset 0x%x\n", req.nr_offset);
327 printf("nr_memsize %u\n", req.nr_memsize);
328 printf("nr_tx_slots %u\n", req.nr_tx_slots);
329 printf("nr_rx_slots %u\n", req.nr_rx_slots);
330 printf("nr_tx_rings %u\n", req.nr_tx_rings);
331 printf("nr_rx_rings %u\n", req.nr_rx_rings);
332 printf("nr_version %d\n", req.nr_version);
333 printf("nr_ringid %x\n", req.nr_ringid);
334 printf("nr_flags %x\n", req.nr_flags);
335 printf("nr_arg2 %u\n", req.nr_arg2);
336 printf("nr_arg3 %u\n", req.nr_arg3);
338 success = req.nr_memsize &&
339 (ctx->nr_ringid == req.nr_ringid) &&
340 ((ctx->nr_mode | ctx->nr_flags) == req.nr_flags) &&
341 ((!ctx->nr_tx_slots && req.nr_tx_slots) ||
342 (ctx->nr_tx_slots == req.nr_tx_slots)) &&
343 ((!ctx->nr_rx_slots && req.nr_rx_slots) ||
344 (ctx->nr_rx_slots == req.nr_rx_slots)) &&
345 ((!ctx->nr_tx_rings && req.nr_tx_rings) ||
346 (ctx->nr_tx_rings == req.nr_tx_rings)) &&
347 ((!ctx->nr_rx_rings && req.nr_rx_rings) ||
348 (ctx->nr_rx_rings == req.nr_rx_rings)) &&
349 ((!ctx->nr_mem_id && req.nr_arg2) ||
350 (ctx->nr_mem_id == req.nr_arg2)) &&
351 (ctx->nr_extra_bufs == req.nr_arg3);
356 /* Write back results to the context structure.*/
357 ctx->nr_tx_slots = req.nr_tx_slots;
358 ctx->nr_rx_slots = req.nr_rx_slots;
359 ctx->nr_tx_rings = req.nr_tx_rings;
360 ctx->nr_rx_rings = req.nr_rx_rings;
361 ctx->nr_mem_id = req.nr_arg2;
362 ctx->nr_extra_bufs = req.nr_arg3;
367 /* The 11 ABI is the one right before the introduction of the new NIOCCTRL
368 * ABI. The 11 ABI is useful to perform tests with legacy applications
369 * (which use the 11 ABI) and new kernel (which uses 12, or higher).
370 * However, version 14 introduced a change in the layout of struct netmap_if,
371 * so that binary backward compatibility to 11 is not supported anymore.
373 #define NETMAP_API_NIOCREGIF 14
376 legacy_regif_default(struct TestContext *ctx)
378 return niocregif(ctx, NETMAP_API_NIOCREGIF);
382 legacy_regif_all_nic(struct TestContext *ctx)
384 ctx->nr_mode = NR_REG_ALL_NIC;
385 return niocregif(ctx, NETMAP_API);
389 legacy_regif_12(struct TestContext *ctx)
391 ctx->nr_mode = NR_REG_ALL_NIC;
392 return niocregif(ctx, NETMAP_API_NIOCREGIF+1);
396 legacy_regif_sw(struct TestContext *ctx)
398 ctx->nr_mode = NR_REG_SW;
399 return niocregif(ctx, NETMAP_API_NIOCREGIF);
403 legacy_regif_future(struct TestContext *ctx)
405 ctx->nr_mode = NR_REG_NIC_SW;
406 /* Test forward compatibility for the legacy ABI. This means
407 * using an older kernel (with ABI 12 or higher) and a newer
408 * application (with ABI greater than NETMAP_API). */
409 return niocregif(ctx, NETMAP_API+2);
413 legacy_regif_extra_bufs(struct TestContext *ctx)
415 ctx->nr_mode = NR_REG_ALL_NIC;
416 ctx->nr_extra_bufs = 20; /* arbitrary number of extra bufs */
417 return niocregif(ctx, NETMAP_API_NIOCREGIF);
421 legacy_regif_extra_bufs_pipe(struct TestContext *ctx)
423 strncat(ctx->ifname_ext, "{pipeexbuf", sizeof(ctx->ifname_ext));
424 ctx->nr_mode = NR_REG_ALL_NIC;
425 ctx->nr_extra_bufs = 58; /* arbitrary number of extra bufs */
427 return niocregif(ctx, NETMAP_API_NIOCREGIF);
431 legacy_regif_extra_bufs_pipe_vale(struct TestContext *ctx)
433 strncpy(ctx->ifname_ext, "valeX1:Y4", sizeof(ctx->ifname_ext));
434 return legacy_regif_extra_bufs_pipe(ctx);
437 /* Only valid after a successful port_register(). */
439 num_registered_rings(struct TestContext *ctx)
441 if (ctx->nr_flags & NR_TX_RINGS_ONLY) {
442 return ctx->nr_tx_rings;
444 if (ctx->nr_flags & NR_RX_RINGS_ONLY) {
445 return ctx->nr_rx_rings;
448 return ctx->nr_tx_rings + ctx->nr_rx_rings;
452 port_register_hwall_host(struct TestContext *ctx)
454 ctx->nr_mode = NR_REG_NIC_SW;
455 return port_register(ctx);
459 port_register_hostall(struct TestContext *ctx)
461 ctx->nr_mode = NR_REG_SW;
462 return port_register(ctx);
466 port_register_hwall(struct TestContext *ctx)
468 ctx->nr_mode = NR_REG_ALL_NIC;
469 return port_register(ctx);
473 port_register_single_hw_pair(struct TestContext *ctx)
475 ctx->nr_mode = NR_REG_ONE_NIC;
477 return port_register(ctx);
481 port_register_single_host_pair(struct TestContext *ctx)
483 ctx->nr_mode = NR_REG_ONE_SW;
484 ctx->nr_host_tx_rings = 2;
485 ctx->nr_host_rx_rings = 2;
487 return port_register(ctx);
491 port_register_hostall_many(struct TestContext *ctx)
493 ctx->nr_mode = NR_REG_SW;
494 ctx->nr_host_tx_rings = 5;
495 ctx->nr_host_rx_rings = 4;
496 return port_register(ctx);
500 port_register_hwall_tx(struct TestContext *ctx)
502 ctx->nr_mode = NR_REG_ALL_NIC;
503 ctx->nr_flags |= NR_TX_RINGS_ONLY;
504 return port_register(ctx);
508 port_register_hwall_rx(struct TestContext *ctx)
510 ctx->nr_mode = NR_REG_ALL_NIC;
511 ctx->nr_flags |= NR_RX_RINGS_ONLY;
512 return port_register(ctx);
515 /* NETMAP_REQ_VALE_ATTACH */
517 vale_attach(struct TestContext *ctx)
519 struct nmreq_vale_attach req;
520 struct nmreq_header hdr;
521 char vpname[sizeof(ctx->bdgname) + 1 + sizeof(ctx->ifname_ext)];
524 snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, ctx->ifname_ext);
526 printf("Testing NETMAP_REQ_VALE_ATTACH on '%s'\n", vpname);
527 nmreq_hdr_init(&hdr, vpname);
528 hdr.nr_reqtype = NETMAP_REQ_VALE_ATTACH;
529 hdr.nr_body = (uintptr_t)&req;
530 memset(&req, 0, sizeof(req));
531 req.reg.nr_mem_id = ctx->nr_mem_id;
532 if (ctx->nr_mode == 0) {
533 ctx->nr_mode = NR_REG_ALL_NIC; /* default */
535 req.reg.nr_mode = ctx->nr_mode;
536 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
538 perror("ioctl(/dev/netmap, NIOCCTRL, VALE_ATTACH)");
541 printf("nr_mem_id %u\n", req.reg.nr_mem_id);
543 return ((!ctx->nr_mem_id && req.reg.nr_mem_id > 1) ||
544 (ctx->nr_mem_id == req.reg.nr_mem_id)) &&
545 (ctx->nr_flags == req.reg.nr_flags)
550 /* NETMAP_REQ_VALE_DETACH */
552 vale_detach(struct TestContext *ctx)
554 struct nmreq_header hdr;
555 struct nmreq_vale_detach req;
559 snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, ctx->ifname_ext);
561 printf("Testing NETMAP_REQ_VALE_DETACH on '%s'\n", vpname);
562 nmreq_hdr_init(&hdr, vpname);
563 hdr.nr_reqtype = NETMAP_REQ_VALE_DETACH;
564 hdr.nr_body = (uintptr_t)&req;
565 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
567 perror("ioctl(/dev/netmap, NIOCCTRL, VALE_DETACH)");
574 /* First NETMAP_REQ_VALE_ATTACH, then NETMAP_REQ_VALE_DETACH. */
576 vale_attach_detach(struct TestContext *ctx)
580 if ((ret = vale_attach(ctx)) != 0) {
584 return vale_detach(ctx);
588 vale_attach_detach_host_rings(struct TestContext *ctx)
590 ctx->nr_mode = NR_REG_NIC_SW;
591 return vale_attach_detach(ctx);
594 /* First NETMAP_REQ_PORT_HDR_SET and the NETMAP_REQ_PORT_HDR_GET
595 * to check that we get the same value. */
597 port_hdr_set_and_get(struct TestContext *ctx)
599 struct nmreq_port_hdr req;
600 struct nmreq_header hdr;
603 printf("Testing NETMAP_REQ_PORT_HDR_SET on '%s'\n", ctx->ifname_ext);
605 nmreq_hdr_init(&hdr, ctx->ifname_ext);
606 hdr.nr_reqtype = NETMAP_REQ_PORT_HDR_SET;
607 hdr.nr_body = (uintptr_t)&req;
608 memset(&req, 0, sizeof(req));
609 req.nr_hdr_len = ctx->nr_hdr_len;
610 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
612 perror("ioctl(/dev/netmap, NIOCCTRL, PORT_HDR_SET)");
616 if (req.nr_hdr_len != ctx->nr_hdr_len) {
620 printf("Testing NETMAP_REQ_PORT_HDR_GET on '%s'\n", ctx->ifname_ext);
621 hdr.nr_reqtype = NETMAP_REQ_PORT_HDR_GET;
623 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
625 perror("ioctl(/dev/netmap, NIOCCTRL, PORT_HDR_SET)");
628 printf("nr_hdr_len %u\n", req.nr_hdr_len);
630 return (req.nr_hdr_len == ctx->nr_hdr_len) ? 0 : -1;
634 * Possible lengths for the VirtIO network header, as specified by
636 * http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html
638 #define VIRTIO_NET_HDR_LEN 10
639 #define VIRTIO_NET_HDR_LEN_WITH_MERGEABLE_RXBUFS 12
642 vale_ephemeral_port_hdr_manipulation(struct TestContext *ctx)
646 strncpy(ctx->ifname_ext, "vale:eph0", sizeof(ctx->ifname_ext));
647 ctx->nr_mode = NR_REG_ALL_NIC;
648 if ((ret = port_register(ctx))) {
651 /* Try to set and get all the acceptable values. */
652 ctx->nr_hdr_len = VIRTIO_NET_HDR_LEN_WITH_MERGEABLE_RXBUFS;
653 if ((ret = port_hdr_set_and_get(ctx))) {
657 if ((ret = port_hdr_set_and_get(ctx))) {
660 ctx->nr_hdr_len = VIRTIO_NET_HDR_LEN;
661 if ((ret = port_hdr_set_and_get(ctx))) {
668 vale_persistent_port(struct TestContext *ctx)
670 struct nmreq_vale_newif req;
671 struct nmreq_header hdr;
675 strncpy(ctx->ifname_ext, "per4", sizeof(ctx->ifname_ext));
677 printf("Testing NETMAP_REQ_VALE_NEWIF on '%s'\n", ctx->ifname_ext);
679 nmreq_hdr_init(&hdr, ctx->ifname_ext);
680 hdr.nr_reqtype = NETMAP_REQ_VALE_NEWIF;
681 hdr.nr_body = (uintptr_t)&req;
682 memset(&req, 0, sizeof(req));
683 req.nr_mem_id = ctx->nr_mem_id;
684 req.nr_tx_slots = ctx->nr_tx_slots;
685 req.nr_rx_slots = ctx->nr_rx_slots;
686 req.nr_tx_rings = ctx->nr_tx_rings;
687 req.nr_rx_rings = ctx->nr_rx_rings;
688 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
690 perror("ioctl(/dev/netmap, NIOCCTRL, VALE_NEWIF)");
694 /* Attach the persistent VALE port to a switch and then detach. */
695 result = vale_attach_detach(ctx);
697 printf("Testing NETMAP_REQ_VALE_DELIF on '%s'\n", ctx->ifname_ext);
698 hdr.nr_reqtype = NETMAP_REQ_VALE_DELIF;
699 hdr.nr_body = (uintptr_t)NULL;
700 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
702 perror("ioctl(/dev/netmap, NIOCCTRL, VALE_NEWIF)");
711 /* Single NETMAP_REQ_POOLS_INFO_GET. */
713 pools_info_get(struct TestContext *ctx)
715 struct nmreq_pools_info req;
716 struct nmreq_header hdr;
719 printf("Testing NETMAP_REQ_POOLS_INFO_GET on '%s'\n", ctx->ifname_ext);
721 nmreq_hdr_init(&hdr, ctx->ifname_ext);
722 hdr.nr_reqtype = NETMAP_REQ_POOLS_INFO_GET;
723 hdr.nr_body = (uintptr_t)&req;
724 memset(&req, 0, sizeof(req));
725 req.nr_mem_id = ctx->nr_mem_id;
726 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
728 perror("ioctl(/dev/netmap, NIOCCTRL, POOLS_INFO_GET)");
731 printf("nr_memsize %llu\n", (unsigned long long)req.nr_memsize);
732 printf("nr_mem_id %u\n", req.nr_mem_id);
733 printf("nr_if_pool_offset 0x%llx\n",
734 (unsigned long long)req.nr_if_pool_offset);
735 printf("nr_if_pool_objtotal %u\n", req.nr_if_pool_objtotal);
736 printf("nr_if_pool_objsize %u\n", req.nr_if_pool_objsize);
737 printf("nr_ring_pool_offset 0x%llx\n",
738 (unsigned long long)req.nr_if_pool_offset);
739 printf("nr_ring_pool_objtotal %u\n", req.nr_ring_pool_objtotal);
740 printf("nr_ring_pool_objsize %u\n", req.nr_ring_pool_objsize);
741 printf("nr_buf_pool_offset 0x%llx\n",
742 (unsigned long long)req.nr_buf_pool_offset);
743 printf("nr_buf_pool_objtotal %u\n", req.nr_buf_pool_objtotal);
744 printf("nr_buf_pool_objsize %u\n", req.nr_buf_pool_objsize);
746 return req.nr_memsize && req.nr_if_pool_objtotal &&
747 req.nr_if_pool_objsize &&
748 req.nr_ring_pool_objtotal &&
749 req.nr_ring_pool_objsize &&
750 req.nr_buf_pool_objtotal &&
751 req.nr_buf_pool_objsize
757 pools_info_get_and_register(struct TestContext *ctx)
761 /* Check that we can get pools info before we register
762 * a netmap interface. */
763 ret = pools_info_get(ctx);
768 ctx->nr_mode = NR_REG_ONE_NIC;
769 ret = port_register(ctx);
775 /* Check that we can get pools info also after we register. */
776 return pools_info_get(ctx);
780 pools_info_get_empty_ifname(struct TestContext *ctx)
782 strncpy(ctx->ifname_ext, "", sizeof(ctx->ifname_ext));
783 return pools_info_get(ctx) != 0 ? 0 : -1;
787 pipe_master(struct TestContext *ctx)
789 strncat(ctx->ifname_ext, "{pipeid1", sizeof(ctx->ifname_ext));
790 ctx->nr_mode = NR_REG_NIC_SW;
792 if (port_register(ctx) == 0) {
793 printf("pipes should not accept NR_REG_NIC_SW\n");
796 ctx->nr_mode = NR_REG_ALL_NIC;
798 return port_register(ctx);
802 pipe_slave(struct TestContext *ctx)
804 strncat(ctx->ifname_ext, "}pipeid2", sizeof(ctx->ifname_ext));
805 ctx->nr_mode = NR_REG_ALL_NIC;
807 return port_register(ctx);
810 /* Test PORT_INFO_GET and POOLS_INFO_GET on a pipe. This is useful to test the
811 * registration request used internall by netmap. */
813 pipe_port_info_get(struct TestContext *ctx)
815 strncat(ctx->ifname_ext, "}pipeid3", sizeof(ctx->ifname_ext));
817 return port_info_get(ctx);
821 pipe_pools_info_get(struct TestContext *ctx)
823 strncat(ctx->ifname_ext, "{xid", sizeof(ctx->ifname_ext));
825 return pools_info_get(ctx);
828 /* NETMAP_REQ_VALE_POLLING_ENABLE */
830 vale_polling_enable(struct TestContext *ctx)
832 struct nmreq_vale_polling req;
833 struct nmreq_header hdr;
837 snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, ctx->ifname_ext);
838 printf("Testing NETMAP_REQ_VALE_POLLING_ENABLE on '%s'\n", vpname);
840 nmreq_hdr_init(&hdr, vpname);
841 hdr.nr_reqtype = NETMAP_REQ_VALE_POLLING_ENABLE;
842 hdr.nr_body = (uintptr_t)&req;
843 memset(&req, 0, sizeof(req));
844 req.nr_mode = ctx->nr_mode;
845 req.nr_first_cpu_id = ctx->nr_first_cpu_id;
846 req.nr_num_polling_cpus = ctx->nr_num_polling_cpus;
847 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
849 perror("ioctl(/dev/netmap, NIOCCTRL, VALE_POLLING_ENABLE)");
853 return (req.nr_mode == ctx->nr_mode &&
854 req.nr_first_cpu_id == ctx->nr_first_cpu_id &&
855 req.nr_num_polling_cpus == ctx->nr_num_polling_cpus)
860 /* NETMAP_REQ_VALE_POLLING_DISABLE */
862 vale_polling_disable(struct TestContext *ctx)
864 struct nmreq_vale_polling req;
865 struct nmreq_header hdr;
869 snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, ctx->ifname_ext);
870 printf("Testing NETMAP_REQ_VALE_POLLING_DISABLE on '%s'\n", vpname);
872 nmreq_hdr_init(&hdr, vpname);
873 hdr.nr_reqtype = NETMAP_REQ_VALE_POLLING_DISABLE;
874 hdr.nr_body = (uintptr_t)&req;
875 memset(&req, 0, sizeof(req));
876 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
878 perror("ioctl(/dev/netmap, NIOCCTRL, VALE_POLLING_DISABLE)");
886 vale_polling_enable_disable(struct TestContext *ctx)
890 if ((ret = vale_attach(ctx)) != 0) {
894 ctx->nr_mode = NETMAP_POLLING_MODE_SINGLE_CPU;
895 ctx->nr_num_polling_cpus = 1;
896 ctx->nr_first_cpu_id = 0;
897 if ((ret = vale_polling_enable(ctx))) {
900 /* NETMAP_REQ_VALE_POLLING_DISABLE is disabled on FreeBSD,
901 * because it is currently broken. We are happy to see that
909 if ((ret = vale_polling_disable(ctx))) {
914 return vale_detach(ctx);
918 push_option(struct nmreq_option *opt, struct TestContext *ctx)
920 opt->nro_next = (uintptr_t)ctx->nr_opt;
925 clear_options(struct TestContext *ctx)
931 checkoption(struct nmreq_option *opt, struct nmreq_option *exp)
933 if (opt->nro_next != exp->nro_next) {
934 printf("nro_next %p expected %p\n",
935 (void *)(uintptr_t)opt->nro_next,
936 (void *)(uintptr_t)exp->nro_next);
939 if (opt->nro_reqtype != exp->nro_reqtype) {
940 printf("nro_reqtype %u expected %u\n", opt->nro_reqtype,
944 if (opt->nro_status != exp->nro_status) {
945 printf("nro_status %u expected %u\n", opt->nro_status,
953 unsupported_option(struct TestContext *ctx)
955 struct nmreq_option opt, save;
957 printf("Testing unsupported option on %s\n", ctx->ifname_ext);
959 memset(&opt, 0, sizeof(opt));
960 opt.nro_reqtype = 1234;
961 push_option(&opt, ctx);
964 if (port_register_hwall(ctx) >= 0)
968 save.nro_status = EOPNOTSUPP;
969 return checkoption(&opt, &save);
973 infinite_options(struct TestContext *ctx)
975 struct nmreq_option opt;
977 printf("Testing infinite list of options on %s\n", ctx->ifname_ext);
979 opt.nro_reqtype = 1234;
980 push_option(&opt, ctx);
981 opt.nro_next = (uintptr_t)&opt;
982 if (port_register_hwall(ctx) >= 0)
985 return (errno == EMSGSIZE ? 0 : -1);
988 #ifdef CONFIG_NETMAP_EXTMEM
990 change_param(const char *pname, unsigned long newv, unsigned long *poldv)
993 char param[256] = "/sys/module/netmap/parameters/";
997 strncat(param, pname, sizeof(param) - 1);
999 f = fopen(param, "r+");
1004 if (fscanf(f, "%ld", &oldv) != 1) {
1012 if (fprintf(f, "%ld\n", newv) < 0) {
1018 printf("change_param: %s: %ld -> %ld\n", pname, oldv, newv);
1019 #endif /* __linux__ */
1024 push_extmem_option(struct TestContext *ctx, const struct nmreq_pools_info *pi,
1025 struct nmreq_opt_extmem *e)
1029 addr = mmap(NULL, pi->nr_memsize, PROT_READ | PROT_WRITE,
1030 MAP_ANONYMOUS | MAP_SHARED, -1, 0);
1031 if (addr == MAP_FAILED) {
1036 memset(e, 0, sizeof(*e));
1037 e->nro_opt.nro_reqtype = NETMAP_REQ_OPT_EXTMEM;
1039 e->nro_usrptr = (uintptr_t)addr;
1041 push_option(&e->nro_opt, ctx);
1047 pop_extmem_option(struct TestContext *ctx, struct nmreq_opt_extmem *exp)
1049 struct nmreq_opt_extmem *e;
1052 e = (struct nmreq_opt_extmem *)(uintptr_t)ctx->nr_opt;
1053 ctx->nr_opt = (struct nmreq_option *)(uintptr_t)ctx->nr_opt->nro_next;
1055 if ((ret = checkoption(&e->nro_opt, &exp->nro_opt))) {
1059 if (e->nro_usrptr != exp->nro_usrptr) {
1060 printf("usrptr %" PRIu64 " expected %" PRIu64 "\n",
1061 e->nro_usrptr, exp->nro_usrptr);
1064 if (e->nro_info.nr_memsize != exp->nro_info.nr_memsize) {
1065 printf("memsize %" PRIu64 " expected %" PRIu64 "\n",
1066 e->nro_info.nr_memsize, exp->nro_info.nr_memsize);
1070 if ((ret = munmap((void *)(uintptr_t)e->nro_usrptr,
1071 e->nro_info.nr_memsize)))
1078 _extmem_option(struct TestContext *ctx,
1079 const struct nmreq_pools_info *pi)
1081 struct nmreq_opt_extmem e, save;
1084 if ((ret = push_extmem_option(ctx, pi, &e)) < 0)
1089 strncpy(ctx->ifname_ext, "vale0:0", sizeof(ctx->ifname_ext));
1090 ctx->nr_tx_slots = 16;
1091 ctx->nr_rx_slots = 16;
1093 if ((ret = port_register_hwall(ctx)))
1096 ret = pop_extmem_option(ctx, &save);
1102 pools_info_min_memsize(const struct nmreq_pools_info *pi)
1106 tot += pi->nr_if_pool_objtotal * pi->nr_if_pool_objsize;
1107 tot += pi->nr_ring_pool_objtotal * pi->nr_ring_pool_objsize;
1108 tot += pi->nr_buf_pool_objtotal * pi->nr_buf_pool_objsize;
1114 * Fill the specification of a netmap memory allocator to be
1115 * used with the 'struct nmreq_opt_extmem' option. Arbitrary
1116 * values are used for the parameters, but with enough netmap
1117 * rings, netmap ifs, and buffers to support a VALE port.
1120 pools_info_fill(struct nmreq_pools_info *pi)
1122 pi->nr_if_pool_objtotal = 2;
1123 pi->nr_if_pool_objsize = 1024;
1124 pi->nr_ring_pool_objtotal = 64;
1125 pi->nr_ring_pool_objsize = 512;
1126 pi->nr_buf_pool_objtotal = 4096;
1127 pi->nr_buf_pool_objsize = 2048;
1128 pi->nr_memsize = pools_info_min_memsize(pi);
1132 extmem_option(struct TestContext *ctx)
1134 struct nmreq_pools_info pools_info;
1136 pools_info_fill(&pools_info);
1138 printf("Testing extmem option on vale0:0\n");
1139 return _extmem_option(ctx, &pools_info);
1143 bad_extmem_option(struct TestContext *ctx)
1145 struct nmreq_pools_info pools_info;
1147 printf("Testing bad extmem option on vale0:0\n");
1149 pools_info_fill(&pools_info);
1150 /* Request a large ring size, to make sure that the kernel
1151 * rejects our request. */
1152 pools_info.nr_ring_pool_objsize = (1 << 20);
1154 return _extmem_option(ctx, &pools_info) < 0 ? 0 : -1;
1158 duplicate_extmem_options(struct TestContext *ctx)
1160 struct nmreq_opt_extmem e1, save1, e2, save2;
1161 struct nmreq_pools_info pools_info;
1164 printf("Testing duplicate extmem option on vale0:0\n");
1166 pools_info_fill(&pools_info);
1168 if ((ret = push_extmem_option(ctx, &pools_info, &e1)) < 0)
1171 if ((ret = push_extmem_option(ctx, &pools_info, &e2)) < 0) {
1179 strncpy(ctx->ifname_ext, "vale0:0", sizeof(ctx->ifname_ext));
1180 ctx->nr_tx_slots = 16;
1181 ctx->nr_rx_slots = 16;
1183 ret = port_register_hwall(ctx);
1185 printf("duplicate option not detected\n");
1189 save2.nro_opt.nro_status = EINVAL;
1190 if ((ret = pop_extmem_option(ctx, &save2)))
1193 save1.nro_opt.nro_status = EINVAL;
1194 if ((ret = pop_extmem_option(ctx, &save1)))
1199 #endif /* CONFIG_NETMAP_EXTMEM */
1202 push_csb_option(struct TestContext *ctx, struct nmreq_opt_csb *opt)
1208 ctx->nr_flags |= NR_EXCLUSIVE;
1210 /* Get port info in order to use num_registered_rings(). */
1211 ret = port_info_get(ctx);
1215 num_entries = num_registered_rings(ctx);
1217 csb_size = (sizeof(struct nm_csb_atok) + sizeof(struct nm_csb_ktoa)) *
1219 assert(csb_size > 0);
1223 ret = posix_memalign(&ctx->csb, sizeof(struct nm_csb_atok), csb_size);
1225 printf("Failed to allocate CSB memory\n");
1229 memset(opt, 0, sizeof(*opt));
1230 opt->nro_opt.nro_reqtype = NETMAP_REQ_OPT_CSB;
1231 opt->csb_atok = (uintptr_t)ctx->csb;
1232 opt->csb_ktoa = (uintptr_t)(((uint8_t *)ctx->csb) +
1233 sizeof(struct nm_csb_atok) * num_entries);
1235 printf("Pushing option NETMAP_REQ_OPT_CSB\n");
1236 push_option(&opt->nro_opt, ctx);
1242 csb_mode(struct TestContext *ctx)
1244 struct nmreq_opt_csb opt;
1247 ret = push_csb_option(ctx, &opt);
1252 ret = port_register_hwall(ctx);
1259 csb_mode_invalid_memory(struct TestContext *ctx)
1261 struct nmreq_opt_csb opt;
1264 memset(&opt, 0, sizeof(opt));
1265 opt.nro_opt.nro_reqtype = NETMAP_REQ_OPT_CSB;
1266 opt.csb_atok = (uintptr_t)0x10;
1267 opt.csb_ktoa = (uintptr_t)0x800;
1268 push_option(&opt.nro_opt, ctx);
1270 ctx->nr_flags = NR_EXCLUSIVE;
1271 ret = port_register_hwall(ctx);
1274 return (ret < 0) ? 0 : -1;
1278 sync_kloop_stop(struct TestContext *ctx)
1280 struct nmreq_header hdr;
1283 printf("Testing NETMAP_REQ_SYNC_KLOOP_STOP on '%s'\n", ctx->ifname_ext);
1285 nmreq_hdr_init(&hdr, ctx->ifname_ext);
1286 hdr.nr_reqtype = NETMAP_REQ_SYNC_KLOOP_STOP;
1287 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
1289 perror("ioctl(/dev/netmap, NIOCCTRL, SYNC_KLOOP_STOP)");
1296 sync_kloop_worker(void *opaque)
1298 struct TestContext *ctx = opaque;
1299 struct nmreq_sync_kloop_start req;
1300 struct nmreq_header hdr;
1303 printf("Testing NETMAP_REQ_SYNC_KLOOP_START on '%s'\n", ctx->ifname_ext);
1305 nmreq_hdr_init(&hdr, ctx->ifname_ext);
1306 hdr.nr_reqtype = NETMAP_REQ_SYNC_KLOOP_START;
1307 hdr.nr_body = (uintptr_t)&req;
1308 hdr.nr_options = (uintptr_t)ctx->nr_opt;
1309 memset(&req, 0, sizeof(req));
1311 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
1313 perror("ioctl(/dev/netmap, NIOCCTRL, SYNC_KLOOP_START)");
1320 pthread_exit(ret ? (void *)THRET_FAILURE : (void *)THRET_SUCCESS);
1324 sync_kloop_start_stop(struct TestContext *ctx)
1327 void *thret = THRET_FAILURE;
1330 ret = pthread_create(&th, NULL, sync_kloop_worker, ctx);
1332 printf("pthread_create(kloop): %s\n", strerror(ret));
1336 ret = sync_kloop_stop(ctx);
1341 ret = pthread_join(th, &thret);
1343 printf("pthread_join(kloop): %s\n", strerror(ret));
1346 return thret == THRET_SUCCESS ? 0 : -1;
1350 sync_kloop(struct TestContext *ctx)
1354 ret = csb_mode(ctx);
1359 return sync_kloop_start_stop(ctx);
1363 sync_kloop_eventfds(struct TestContext *ctx)
1365 struct nmreq_opt_sync_kloop_eventfds *evopt = NULL;
1366 struct nmreq_opt_sync_kloop_mode modeopt;
1367 struct nmreq_option evsave;
1372 memset(&modeopt, 0, sizeof(modeopt));
1373 modeopt.nro_opt.nro_reqtype = NETMAP_REQ_OPT_SYNC_KLOOP_MODE;
1374 modeopt.mode = ctx->sync_kloop_mode;
1375 push_option(&modeopt.nro_opt, ctx);
1377 num_entries = num_registered_rings(ctx);
1378 opt_size = sizeof(*evopt) + num_entries * sizeof(evopt->eventfds[0]);
1379 evopt = calloc(1, opt_size);
1380 evopt->nro_opt.nro_next = 0;
1381 evopt->nro_opt.nro_reqtype = NETMAP_REQ_OPT_SYNC_KLOOP_EVENTFDS;
1382 evopt->nro_opt.nro_status = 0;
1383 evopt->nro_opt.nro_size = opt_size;
1384 for (i = 0; i < num_entries; i++) {
1385 int efd = eventfd(0, 0);
1387 evopt->eventfds[i].ioeventfd = efd;
1388 efd = eventfd(0, 0);
1389 evopt->eventfds[i].irqfd = efd;
1392 push_option(&evopt->nro_opt, ctx);
1393 evsave = evopt->nro_opt;
1395 ret = sync_kloop_start_stop(ctx);
1402 evsave.nro_status = 0;
1403 #else /* !__linux__ */
1404 evsave.nro_status = EOPNOTSUPP;
1405 #endif /* !__linux__ */
1407 ret = checkoption(&evopt->nro_opt, &evsave);
1415 sync_kloop_eventfds_all_mode(struct TestContext *ctx,
1416 uint32_t sync_kloop_mode)
1420 ret = csb_mode(ctx);
1425 ctx->sync_kloop_mode = sync_kloop_mode;
1427 return sync_kloop_eventfds(ctx);
1431 sync_kloop_eventfds_all(struct TestContext *ctx)
1433 return sync_kloop_eventfds_all_mode(ctx, 0);
1437 sync_kloop_eventfds_all_tx(struct TestContext *ctx)
1439 struct nmreq_opt_csb opt;
1442 ret = push_csb_option(ctx, &opt);
1447 ret = port_register_hwall_tx(ctx);
1453 return sync_kloop_eventfds(ctx);
1457 sync_kloop_eventfds_all_direct(struct TestContext *ctx)
1459 return sync_kloop_eventfds_all_mode(ctx,
1460 NM_OPT_SYNC_KLOOP_DIRECT_TX | NM_OPT_SYNC_KLOOP_DIRECT_RX);
1464 sync_kloop_eventfds_all_direct_tx(struct TestContext *ctx)
1466 return sync_kloop_eventfds_all_mode(ctx,
1467 NM_OPT_SYNC_KLOOP_DIRECT_TX);
1471 sync_kloop_eventfds_all_direct_rx(struct TestContext *ctx)
1473 return sync_kloop_eventfds_all_mode(ctx,
1474 NM_OPT_SYNC_KLOOP_DIRECT_RX);
1478 sync_kloop_nocsb(struct TestContext *ctx)
1482 ret = port_register_hwall(ctx);
1487 /* Sync kloop must fail because we did not use
1488 * NETMAP_REQ_CSB_ENABLE. */
1489 return sync_kloop_start_stop(ctx) != 0 ? 0 : -1;
1493 csb_enable(struct TestContext *ctx)
1495 struct nmreq_option saveopt;
1496 struct nmreq_opt_csb opt;
1497 struct nmreq_header hdr;
1500 ret = push_csb_option(ctx, &opt);
1504 saveopt = opt.nro_opt;
1505 saveopt.nro_status = 0;
1507 nmreq_hdr_init(&hdr, ctx->ifname_ext);
1508 hdr.nr_reqtype = NETMAP_REQ_CSB_ENABLE;
1509 hdr.nr_options = (uintptr_t)ctx->nr_opt;
1510 hdr.nr_body = (uintptr_t)NULL;
1512 printf("Testing NETMAP_REQ_CSB_ENABLE on '%s'\n", ctx->ifname_ext);
1514 ret = ioctl(ctx->fd, NIOCCTRL, &hdr);
1516 perror("ioctl(/dev/netmap, NIOCCTRL, CSB_ENABLE)");
1520 ret = checkoption(&opt.nro_opt, &saveopt);
1527 sync_kloop_csb_enable(struct TestContext *ctx)
1531 ctx->nr_flags |= NR_EXCLUSIVE;
1532 ret = port_register_hwall(ctx);
1537 ret = csb_enable(ctx);
1542 return sync_kloop_start_stop(ctx);
1546 sync_kloop_conflict(struct TestContext *ctx)
1548 struct nmreq_opt_csb opt;
1550 void *thret1 = THRET_FAILURE, *thret2 = THRET_FAILURE;
1556 ret = push_csb_option(ctx, &opt);
1561 ret = port_register_hwall(ctx);
1567 ret = sem_init(&sem, 0, 0);
1569 printf("sem_init() failed: %s\n", strerror(ret));
1574 ret = pthread_create(&th1, NULL, sync_kloop_worker, ctx);
1577 printf("pthread_create(kloop1): %s\n", strerror(ret));
1580 ret = pthread_create(&th2, NULL, sync_kloop_worker, ctx);
1583 printf("pthread_create(kloop2): %s\n", strerror(ret));
1586 /* Wait for one of the two threads to fail to start the kloop, to
1587 * avoid a race condition where th1 starts the loop and stops,
1588 * and after that th2 starts the loop successfully. */
1589 clock_gettime(CLOCK_REALTIME, &to);
1591 ret = sem_timedwait(&sem, &to);
1594 printf("sem_timedwait() failed: %s\n", strerror(errno));
1597 err |= sync_kloop_stop(ctx);
1599 ret = pthread_join(th1, &thret1);
1602 printf("pthread_join(kloop1): %s\n", strerror(ret));
1605 ret = pthread_join(th2, &thret2);
1608 printf("pthread_join(kloop2): %s %d\n", strerror(ret), ret);
1617 /* Check that one of the two failed, while the other one succeeded. */
1618 return ((thret1 == THRET_SUCCESS && thret2 == THRET_FAILURE) ||
1619 (thret1 == THRET_FAILURE && thret2 == THRET_SUCCESS))
1625 sync_kloop_eventfds_mismatch(struct TestContext *ctx)
1627 struct nmreq_opt_csb opt;
1630 ret = push_csb_option(ctx, &opt);
1635 ret = port_register_hwall_rx(ctx);
1641 /* Deceive num_registered_rings() to trigger a failure of
1642 * sync_kloop_eventfds(). The latter will think that all the
1643 * rings were registered, and allocate the wrong number of
1645 ctx->nr_flags &= ~NR_RX_RINGS_ONLY;
1647 return (sync_kloop_eventfds(ctx) != 0) ? 0 : -1;
1651 null_port(struct TestContext *ctx)
1656 ctx->nr_mode = NR_REG_NULL;
1657 ctx->nr_tx_rings = 10;
1658 ctx->nr_rx_rings = 5;
1659 ctx->nr_tx_slots = 256;
1660 ctx->nr_rx_slots = 100;
1661 ret = port_register(ctx);
1669 null_port_all_zero(struct TestContext *ctx)
1674 ctx->nr_mode = NR_REG_NULL;
1675 ctx->nr_tx_rings = 0;
1676 ctx->nr_rx_rings = 0;
1677 ctx->nr_tx_slots = 0;
1678 ctx->nr_rx_slots = 0;
1679 ret = port_register(ctx);
1687 null_port_sync(struct TestContext *ctx)
1692 ctx->nr_mode = NR_REG_NULL;
1693 ctx->nr_tx_rings = 10;
1694 ctx->nr_rx_rings = 5;
1695 ctx->nr_tx_slots = 256;
1696 ctx->nr_rx_slots = 100;
1697 ret = port_register(ctx);
1701 ret = ioctl(ctx->fd, NIOCTXSYNC, 0);
1709 usage(const char *prog)
1711 printf("%s -i IFNAME\n"
1712 "[-j TEST_NUM1[-[TEST_NUM2]] | -[TEST_NUM_2]]\n"
1713 "[-l (list test cases)]\n",
1722 #define decltest(f) \
1724 .test = f, .name = #f \
1727 static struct mytest tests[] = {
1728 decltest(port_info_get),
1729 decltest(port_register_hwall_host),
1730 decltest(port_register_hwall),
1731 decltest(port_register_hostall),
1732 decltest(port_register_single_hw_pair),
1733 decltest(port_register_single_host_pair),
1734 decltest(port_register_hostall_many),
1735 decltest(vale_attach_detach),
1736 decltest(vale_attach_detach_host_rings),
1737 decltest(vale_ephemeral_port_hdr_manipulation),
1738 decltest(vale_persistent_port),
1739 decltest(pools_info_get_and_register),
1740 decltest(pools_info_get_empty_ifname),
1741 decltest(pipe_master),
1742 decltest(pipe_slave),
1743 decltest(pipe_port_info_get),
1744 decltest(pipe_pools_info_get),
1745 decltest(vale_polling_enable_disable),
1746 decltest(unsupported_option),
1747 decltest(infinite_options),
1748 #ifdef CONFIG_NETMAP_EXTMEM
1749 decltest(extmem_option),
1750 decltest(bad_extmem_option),
1751 decltest(duplicate_extmem_options),
1752 #endif /* CONFIG_NETMAP_EXTMEM */
1754 decltest(csb_mode_invalid_memory),
1755 decltest(sync_kloop),
1756 decltest(sync_kloop_eventfds_all),
1757 decltest(sync_kloop_eventfds_all_tx),
1758 decltest(sync_kloop_eventfds_all_direct),
1759 decltest(sync_kloop_eventfds_all_direct_tx),
1760 decltest(sync_kloop_eventfds_all_direct_rx),
1761 decltest(sync_kloop_nocsb),
1762 decltest(sync_kloop_csb_enable),
1763 decltest(sync_kloop_conflict),
1764 decltest(sync_kloop_eventfds_mismatch),
1765 decltest(null_port),
1766 decltest(null_port_all_zero),
1767 decltest(null_port_sync),
1768 decltest(legacy_regif_default),
1769 decltest(legacy_regif_all_nic),
1770 decltest(legacy_regif_12),
1771 decltest(legacy_regif_sw),
1772 decltest(legacy_regif_future),
1773 decltest(legacy_regif_extra_bufs),
1774 decltest(legacy_regif_extra_bufs_pipe),
1775 decltest(legacy_regif_extra_bufs_pipe_vale),
1779 context_cleanup(struct TestContext *ctx)
1791 parse_interval(const char *arg, int *j, int *k)
1793 const char *scan = arg;
1802 if (!isdigit(*scan))
1804 *k = strtol(scan, &rest, 10);
1814 if (!isdigit(*scan))
1816 *k = strtol(scan, &rest, 10);
1818 if (!(*scan == '\0'))
1824 fprintf(stderr, "syntax error in '%s', must be num[-[num]] or -[num]\n", arg);
1828 #define ARGV_APPEND(_av, _ac, _x)\
1830 assert((int)(_ac) < (int)(sizeof(_av)/sizeof((_av)[0])));\
1831 (_av)[(_ac)++] = _x;\
1835 tap_cleanup(int signo)
1842 ARGV_APPEND(av, ac, "ifconfig");
1843 ARGV_APPEND(av, ac, ctx_.ifname);
1844 ARGV_APPEND(av, ac, "destroy");
1846 ARGV_APPEND(av, ac, "ip");
1847 ARGV_APPEND(av, ac, "link");
1848 ARGV_APPEND(av, ac, "del");
1849 ARGV_APPEND(av, ac, ctx_.ifname);
1851 ARGV_APPEND(av, ac, NULL);
1852 if (exec_command(ac, av)) {
1853 printf("Failed to destroy tap interface\n");
1858 main(int argc, char **argv)
1870 PLAIN_REQUIRE_KERNEL_MODULE("if_tap", 0);
1871 PLAIN_REQUIRE_KERNEL_MODULE("netmap", 0);
1874 memset(&ctx_, 0, sizeof(ctx_));
1880 clock_gettime(CLOCK_REALTIME, &t);
1881 srand((unsigned int)t.tv_nsec);
1882 idx = rand() % 8000 + 100;
1883 snprintf(ctx_.ifname, sizeof(ctx_.ifname), "tap%d", idx);
1884 idx = rand() % 800 + 100;
1885 snprintf(ctx_.bdgname, sizeof(ctx_.bdgname), "vale%d", idx);
1888 while ((opt = getopt(argc, argv, "hi:j:l")) != -1) {
1895 strncpy(ctx_.ifname, optarg, sizeof(ctx_.ifname) - 1);
1900 if (parse_interval(optarg, &j, &k) < 0) {
1912 printf(" Unrecognized option %c\n", opt);
1918 num_tests = sizeof(tests) / sizeof(tests[0]);
1920 if (j < 0 || j >= num_tests || k > num_tests) {
1921 fprintf(stderr, "Test interval %d-%d out of range (%d-%d)\n",
1922 j + 1, k, 1, num_tests + 1);
1930 printf("Available tests:\n");
1931 for (i = 0; i < num_tests; i++) {
1932 printf("#%03d: %s\n", i + 1, tests[i].name);
1938 struct sigaction sa;
1942 ARGV_APPEND(av, ac, "ifconfig");
1943 ARGV_APPEND(av, ac, ctx_.ifname);
1944 ARGV_APPEND(av, ac, "create");
1945 ARGV_APPEND(av, ac, "up");
1947 ARGV_APPEND(av, ac, "ip");
1948 ARGV_APPEND(av, ac, "tuntap");
1949 ARGV_APPEND(av, ac, "add");
1950 ARGV_APPEND(av, ac, "mode");
1951 ARGV_APPEND(av, ac, "tap");
1952 ARGV_APPEND(av, ac, "name");
1953 ARGV_APPEND(av, ac, ctx_.ifname);
1955 ARGV_APPEND(av, ac, NULL);
1956 if (exec_command(ac, av)) {
1957 printf("Failed to create tap interface\n");
1961 sa.sa_handler = tap_cleanup;
1962 sigemptyset(&sa.sa_mask);
1963 sa.sa_flags = SA_RESTART;
1964 ret = sigaction(SIGINT, &sa, NULL);
1966 perror("sigaction(SIGINT)");
1969 ret = sigaction(SIGTERM, &sa, NULL);
1971 perror("sigaction(SIGTERM)");
1976 for (i = j; i < k; i++) {
1977 struct TestContext ctxcopy;
1979 printf("==> Start of Test #%d [%s]\n", i + 1, tests[i].name);
1980 fd = open("/dev/netmap", O_RDWR);
1982 perror("open(/dev/netmap)");
1986 memcpy(&ctxcopy, &ctx_, sizeof(ctxcopy));
1988 memcpy(ctxcopy.ifname_ext, ctxcopy.ifname,
1989 sizeof(ctxcopy.ifname));
1990 ret = tests[i].test(&ctxcopy);
1992 printf("Test #%d [%s] failed\n", i + 1, tests[i].name);
1995 printf("==> Test #%d [%s] successful\n", i + 1, tests[i].name);
1996 context_cleanup(&ctxcopy);