14c067f38SVincenzo Maffione /*- 24c067f38SVincenzo Maffione * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c067f38SVincenzo Maffione * 44c067f38SVincenzo Maffione * Copyright (C) 2018 Universita` di Pisa 54c067f38SVincenzo Maffione * All rights reserved. 64c067f38SVincenzo Maffione * 74c067f38SVincenzo Maffione * Redistribution and use in source and binary forms, with or without 84c067f38SVincenzo Maffione * modification, are permitted provided that the following conditions 94c067f38SVincenzo Maffione * are met: 104c067f38SVincenzo Maffione * 114c067f38SVincenzo Maffione * 1. Redistributions of source code must retain the above copyright 124c067f38SVincenzo Maffione * notice, this list of conditions and the following disclaimer. 134c067f38SVincenzo Maffione * 2. Redistributions in binary form must reproduce the above copyright 144c067f38SVincenzo Maffione * notice, this list of conditions and the following disclaimer in the 154c067f38SVincenzo Maffione * documentation and/or other materials provided with the distribution. 164c067f38SVincenzo Maffione * 174c067f38SVincenzo Maffione * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 184c067f38SVincenzo Maffione * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194c067f38SVincenzo Maffione * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 204c067f38SVincenzo Maffione * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 214c067f38SVincenzo Maffione * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 224c067f38SVincenzo Maffione * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 234c067f38SVincenzo Maffione * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 244c067f38SVincenzo Maffione * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 254c067f38SVincenzo Maffione * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 264c067f38SVincenzo Maffione * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 274c067f38SVincenzo Maffione * SUCH DAMAGE. 284c067f38SVincenzo Maffione * 294c067f38SVincenzo Maffione * $FreeBSD$ 304c067f38SVincenzo Maffione */ 314c067f38SVincenzo Maffione 325c4f8d80SVincenzo Maffione #include <sys/types.h> 335c4f8d80SVincenzo Maffione #include <sys/stat.h> 345c4f8d80SVincenzo Maffione #include <sys/ioctl.h> 355c4f8d80SVincenzo Maffione #include <sys/mman.h> 365c4f8d80SVincenzo Maffione #include <ctype.h> 375c4f8d80SVincenzo Maffione #include <fcntl.h> 385c4f8d80SVincenzo Maffione #include <inttypes.h> 395c4f8d80SVincenzo Maffione #include <stdlib.h> 405c4f8d80SVincenzo Maffione #include <stdio.h> 415c4f8d80SVincenzo Maffione #include <stdarg.h> 425c4f8d80SVincenzo Maffione #include <string.h> 435c4f8d80SVincenzo Maffione #include <unistd.h> 445c4f8d80SVincenzo Maffione #include <errno.h> 455c4f8d80SVincenzo Maffione 465c4f8d80SVincenzo Maffione //#define NMREQ_DEBUG 475c4f8d80SVincenzo Maffione #ifdef NMREQ_DEBUG 485c4f8d80SVincenzo Maffione #define NETMAP_WITH_LIBS 495c4f8d80SVincenzo Maffione #define ED(...) D(__VA_ARGS__) 505c4f8d80SVincenzo Maffione #else 515c4f8d80SVincenzo Maffione #define ED(...) 525c4f8d80SVincenzo Maffione /* an identifier is a possibly empty sequence of alphanum characters and 535c4f8d80SVincenzo Maffione * underscores 545c4f8d80SVincenzo Maffione */ 555c4f8d80SVincenzo Maffione static int 565c4f8d80SVincenzo Maffione nm_is_identifier(const char *s, const char *e) 575c4f8d80SVincenzo Maffione { 585c4f8d80SVincenzo Maffione for (; s != e; s++) { 595c4f8d80SVincenzo Maffione if (!isalnum(*s) && *s != '_') { 605c4f8d80SVincenzo Maffione return 0; 615c4f8d80SVincenzo Maffione } 625c4f8d80SVincenzo Maffione } 635c4f8d80SVincenzo Maffione 645c4f8d80SVincenzo Maffione return 1; 655c4f8d80SVincenzo Maffione } 665c4f8d80SVincenzo Maffione #endif /* NMREQ_DEBUG */ 675c4f8d80SVincenzo Maffione 685c4f8d80SVincenzo Maffione #include <net/netmap_user.h> 695c4f8d80SVincenzo Maffione #define LIBNETMAP_NOTHREADSAFE 705c4f8d80SVincenzo Maffione #include "libnetmap.h" 715c4f8d80SVincenzo Maffione 725c4f8d80SVincenzo Maffione void 735c4f8d80SVincenzo Maffione nmreq_push_option(struct nmreq_header *h, struct nmreq_option *o) 745c4f8d80SVincenzo Maffione { 755c4f8d80SVincenzo Maffione o->nro_next = h->nr_options; 765c4f8d80SVincenzo Maffione h->nr_options = (uintptr_t)o; 775c4f8d80SVincenzo Maffione } 785c4f8d80SVincenzo Maffione 795c4f8d80SVincenzo Maffione struct nmreq_prefix { 805c4f8d80SVincenzo Maffione const char *prefix; /* the constant part of the prefix */ 815c4f8d80SVincenzo Maffione size_t len; /* its strlen() */ 825c4f8d80SVincenzo Maffione uint32_t flags; 835c4f8d80SVincenzo Maffione #define NR_P_ID (1U << 0) /* whether an identifier is needed */ 845c4f8d80SVincenzo Maffione #define NR_P_SKIP (1U << 1) /* whether the scope must be passed to netmap */ 855c4f8d80SVincenzo Maffione #define NR_P_EMPTYID (1U << 2) /* whether an empty identifier is allowed */ 865c4f8d80SVincenzo Maffione }; 875c4f8d80SVincenzo Maffione 885c4f8d80SVincenzo Maffione #define declprefix(prefix, flags) { (prefix), (sizeof(prefix) - 1), (flags) } 895c4f8d80SVincenzo Maffione 905c4f8d80SVincenzo Maffione static struct nmreq_prefix nmreq_prefixes[] = { 915c4f8d80SVincenzo Maffione declprefix("netmap", NR_P_SKIP), 925c4f8d80SVincenzo Maffione declprefix(NM_BDG_NAME, NR_P_ID|NR_P_EMPTYID), 935c4f8d80SVincenzo Maffione { NULL } /* terminate the list */ 945c4f8d80SVincenzo Maffione }; 955c4f8d80SVincenzo Maffione 965c4f8d80SVincenzo Maffione void 975c4f8d80SVincenzo Maffione nmreq_header_init(struct nmreq_header *h, uint16_t reqtype, void *body) 985c4f8d80SVincenzo Maffione { 995c4f8d80SVincenzo Maffione memset(h, 0, sizeof(*h)); 1005c4f8d80SVincenzo Maffione h->nr_version = NETMAP_API; 1015c4f8d80SVincenzo Maffione h->nr_reqtype = reqtype; 1025c4f8d80SVincenzo Maffione h->nr_body = (uintptr_t)body; 1035c4f8d80SVincenzo Maffione } 1045c4f8d80SVincenzo Maffione 1055c4f8d80SVincenzo Maffione int 1065c4f8d80SVincenzo Maffione nmreq_header_decode(const char **pifname, struct nmreq_header *h, struct nmctx *ctx) 1075c4f8d80SVincenzo Maffione { 1085c4f8d80SVincenzo Maffione const char *scan = NULL; 1095c4f8d80SVincenzo Maffione const char *vpname = NULL; 1105c4f8d80SVincenzo Maffione const char *pipesep = NULL; 1115c4f8d80SVincenzo Maffione u_int namelen; 1125c4f8d80SVincenzo Maffione const char *ifname = *pifname; 1135c4f8d80SVincenzo Maffione struct nmreq_prefix *p; 1145c4f8d80SVincenzo Maffione 1155c4f8d80SVincenzo Maffione scan = ifname; 1165c4f8d80SVincenzo Maffione for (p = nmreq_prefixes; p->prefix != NULL; p++) { 1175c4f8d80SVincenzo Maffione if (!strncmp(scan, p->prefix, p->len)) 1185c4f8d80SVincenzo Maffione break; 1195c4f8d80SVincenzo Maffione } 1205c4f8d80SVincenzo Maffione if (p->prefix == NULL) { 1215c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid request, prefix unknown or missing", *pifname); 1225c4f8d80SVincenzo Maffione goto fail; 1235c4f8d80SVincenzo Maffione } 1245c4f8d80SVincenzo Maffione scan += p->len; 1255c4f8d80SVincenzo Maffione 1265c4f8d80SVincenzo Maffione vpname = index(scan, ':'); 1275c4f8d80SVincenzo Maffione if (vpname == NULL) { 1285c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: missing ':'", ifname); 1295c4f8d80SVincenzo Maffione goto fail; 1305c4f8d80SVincenzo Maffione } 1315c4f8d80SVincenzo Maffione if (vpname != scan) { 1325c4f8d80SVincenzo Maffione /* there is an identifier, can we accept it? */ 1335c4f8d80SVincenzo Maffione if (!(p->flags & NR_P_ID)) { 1345c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: no identifier allowed between '%s' and ':'", *pifname, p->prefix); 1355c4f8d80SVincenzo Maffione goto fail; 1365c4f8d80SVincenzo Maffione } 1375c4f8d80SVincenzo Maffione 1385c4f8d80SVincenzo Maffione if (!nm_is_identifier(scan, vpname)) { 1395c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid identifier '%.*s'", *pifname, vpname - scan, scan); 1405c4f8d80SVincenzo Maffione goto fail; 1415c4f8d80SVincenzo Maffione } 1425c4f8d80SVincenzo Maffione } else { 1435c4f8d80SVincenzo Maffione if ((p->flags & NR_P_ID) && !(p->flags & NR_P_EMPTYID)) { 1445c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: identifier is missing between '%s' and ':'", *pifname, p->prefix); 1455c4f8d80SVincenzo Maffione goto fail; 1465c4f8d80SVincenzo Maffione } 1475c4f8d80SVincenzo Maffione } 1485c4f8d80SVincenzo Maffione ++vpname; /* skip the colon */ 1495c4f8d80SVincenzo Maffione if (p->flags & NR_P_SKIP) 1505c4f8d80SVincenzo Maffione ifname = vpname; 1515c4f8d80SVincenzo Maffione scan = vpname; 1525c4f8d80SVincenzo Maffione 1535c4f8d80SVincenzo Maffione /* scan for a separator */ 1545c4f8d80SVincenzo Maffione for (; *scan && !index("-*^/@", *scan); scan++) 1555c4f8d80SVincenzo Maffione ; 1565c4f8d80SVincenzo Maffione 1575c4f8d80SVincenzo Maffione /* search for possible pipe indicators */ 1585c4f8d80SVincenzo Maffione for (pipesep = vpname; pipesep != scan && !index("{}", *pipesep); pipesep++) 1595c4f8d80SVincenzo Maffione ; 1605c4f8d80SVincenzo Maffione 1615c4f8d80SVincenzo Maffione if (!nm_is_identifier(vpname, pipesep)) { 1625c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid port name '%.*s'", *pifname, 1635c4f8d80SVincenzo Maffione pipesep - vpname, vpname); 1645c4f8d80SVincenzo Maffione goto fail; 1655c4f8d80SVincenzo Maffione } 1665c4f8d80SVincenzo Maffione if (pipesep != scan) { 1675c4f8d80SVincenzo Maffione pipesep++; 1685c4f8d80SVincenzo Maffione if (*pipesep == '\0') { 1695c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid empty pipe name", *pifname); 1705c4f8d80SVincenzo Maffione goto fail; 1715c4f8d80SVincenzo Maffione } 1725c4f8d80SVincenzo Maffione if (!nm_is_identifier(pipesep, scan)) { 1735c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid pipe name '%.*s'", *pifname, scan - pipesep, pipesep); 1745c4f8d80SVincenzo Maffione goto fail; 1755c4f8d80SVincenzo Maffione } 1765c4f8d80SVincenzo Maffione } 1775c4f8d80SVincenzo Maffione 1785c4f8d80SVincenzo Maffione namelen = scan - ifname; 1795c4f8d80SVincenzo Maffione if (namelen >= sizeof(h->nr_name)) { 1805c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "name '%.*s' too long", namelen, ifname); 1815c4f8d80SVincenzo Maffione goto fail; 1825c4f8d80SVincenzo Maffione } 1835c4f8d80SVincenzo Maffione if (namelen == 0) { 1845c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid empty port name", *pifname); 1855c4f8d80SVincenzo Maffione goto fail; 1865c4f8d80SVincenzo Maffione } 1875c4f8d80SVincenzo Maffione 1885c4f8d80SVincenzo Maffione /* fill the header */ 1895c4f8d80SVincenzo Maffione memcpy(h->nr_name, ifname, namelen); 1905c4f8d80SVincenzo Maffione h->nr_name[namelen] = '\0'; 1915c4f8d80SVincenzo Maffione ED("name %s", h->nr_name); 1925c4f8d80SVincenzo Maffione 1935c4f8d80SVincenzo Maffione *pifname = scan; 1945c4f8d80SVincenzo Maffione 1955c4f8d80SVincenzo Maffione return 0; 1965c4f8d80SVincenzo Maffione fail: 1975c4f8d80SVincenzo Maffione errno = EINVAL; 1985c4f8d80SVincenzo Maffione return -1; 1995c4f8d80SVincenzo Maffione } 2005c4f8d80SVincenzo Maffione 2015c4f8d80SVincenzo Maffione 2025c4f8d80SVincenzo Maffione /* 2035c4f8d80SVincenzo Maffione * 0 not recognized 2045c4f8d80SVincenzo Maffione * -1 error 2055c4f8d80SVincenzo Maffione * >= 0 mem_id 2065c4f8d80SVincenzo Maffione */ 2075c4f8d80SVincenzo Maffione int32_t 2085c4f8d80SVincenzo Maffione nmreq_get_mem_id(const char **pifname, struct nmctx *ctx) 2095c4f8d80SVincenzo Maffione { 2105c4f8d80SVincenzo Maffione int fd = -1; 2115c4f8d80SVincenzo Maffione struct nmreq_header gh; 2125c4f8d80SVincenzo Maffione struct nmreq_port_info_get gb; 2135c4f8d80SVincenzo Maffione const char *ifname; 2145c4f8d80SVincenzo Maffione 2155c4f8d80SVincenzo Maffione errno = 0; 2165c4f8d80SVincenzo Maffione ifname = *pifname; 2175c4f8d80SVincenzo Maffione 2185c4f8d80SVincenzo Maffione if (ifname == NULL) 2195c4f8d80SVincenzo Maffione goto fail; 2205c4f8d80SVincenzo Maffione 2215c4f8d80SVincenzo Maffione /* try to look for a netmap port with this name */ 2225c4f8d80SVincenzo Maffione fd = open("/dev/netmap", O_RDWR); 2235c4f8d80SVincenzo Maffione if (fd < 0) { 2245c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "cannot open /dev/netmap: %s", strerror(errno)); 2255c4f8d80SVincenzo Maffione goto fail; 2265c4f8d80SVincenzo Maffione } 2275c4f8d80SVincenzo Maffione nmreq_header_init(&gh, NETMAP_REQ_PORT_INFO_GET, &gb); 2285c4f8d80SVincenzo Maffione if (nmreq_header_decode(&ifname, &gh, ctx) < 0) { 2295c4f8d80SVincenzo Maffione goto fail; 2305c4f8d80SVincenzo Maffione } 2315c4f8d80SVincenzo Maffione memset(&gb, 0, sizeof(gb)); 2325c4f8d80SVincenzo Maffione if (ioctl(fd, NIOCCTRL, &gh) < 0) { 2335c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "cannot get info for '%s': %s", *pifname, strerror(errno)); 2345c4f8d80SVincenzo Maffione goto fail; 2355c4f8d80SVincenzo Maffione } 2365c4f8d80SVincenzo Maffione *pifname = ifname; 2375c4f8d80SVincenzo Maffione close(fd); 2385c4f8d80SVincenzo Maffione return gb.nr_mem_id; 2395c4f8d80SVincenzo Maffione 2405c4f8d80SVincenzo Maffione fail: 2415c4f8d80SVincenzo Maffione if (fd >= 0) 2425c4f8d80SVincenzo Maffione close(fd); 2435c4f8d80SVincenzo Maffione if (!errno) 2445c4f8d80SVincenzo Maffione errno = EINVAL; 2455c4f8d80SVincenzo Maffione return -1; 2465c4f8d80SVincenzo Maffione } 2475c4f8d80SVincenzo Maffione 2485c4f8d80SVincenzo Maffione 2495c4f8d80SVincenzo Maffione int 2505c4f8d80SVincenzo Maffione nmreq_register_decode(const char **pifname, struct nmreq_register *r, struct nmctx *ctx) 2515c4f8d80SVincenzo Maffione { 2525c4f8d80SVincenzo Maffione enum { P_START, P_RNGSFXOK, P_GETNUM, P_FLAGS, P_FLAGSOK, P_MEMID, P_ONESW } p_state; 2535c4f8d80SVincenzo Maffione long num; 2545c4f8d80SVincenzo Maffione const char *scan = *pifname; 2555c4f8d80SVincenzo Maffione uint32_t nr_mode; 2565c4f8d80SVincenzo Maffione uint16_t nr_mem_id; 2575c4f8d80SVincenzo Maffione uint16_t nr_ringid; 2585c4f8d80SVincenzo Maffione uint64_t nr_flags; 2595c4f8d80SVincenzo Maffione 260*ab639bb2SVincenzo Maffione errno = 0; 261*ab639bb2SVincenzo Maffione 2625c4f8d80SVincenzo Maffione /* fill the request */ 2635c4f8d80SVincenzo Maffione 2645c4f8d80SVincenzo Maffione p_state = P_START; 2655c4f8d80SVincenzo Maffione /* defaults */ 2665c4f8d80SVincenzo Maffione nr_mode = NR_REG_ALL_NIC; /* default for no suffix */ 2675c4f8d80SVincenzo Maffione nr_mem_id = r->nr_mem_id; /* if non-zero, further updates are disabled */ 2685c4f8d80SVincenzo Maffione nr_ringid = 0; 2695c4f8d80SVincenzo Maffione nr_flags = 0; 2705c4f8d80SVincenzo Maffione while (*scan) { 2715c4f8d80SVincenzo Maffione switch (p_state) { 2725c4f8d80SVincenzo Maffione case P_START: 2735c4f8d80SVincenzo Maffione switch (*scan) { 2745c4f8d80SVincenzo Maffione case '^': /* only SW ring */ 2755c4f8d80SVincenzo Maffione nr_mode = NR_REG_SW; 2765c4f8d80SVincenzo Maffione p_state = P_ONESW; 2775c4f8d80SVincenzo Maffione break; 2785c4f8d80SVincenzo Maffione case '*': /* NIC and SW */ 2795c4f8d80SVincenzo Maffione nr_mode = NR_REG_NIC_SW; 2805c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 2815c4f8d80SVincenzo Maffione break; 2825c4f8d80SVincenzo Maffione case '-': /* one NIC ring pair */ 2835c4f8d80SVincenzo Maffione nr_mode = NR_REG_ONE_NIC; 2845c4f8d80SVincenzo Maffione p_state = P_GETNUM; 2855c4f8d80SVincenzo Maffione break; 2865c4f8d80SVincenzo Maffione case '/': /* start of flags */ 2875c4f8d80SVincenzo Maffione p_state = P_FLAGS; 2885c4f8d80SVincenzo Maffione break; 2895c4f8d80SVincenzo Maffione case '@': /* start of memid */ 2905c4f8d80SVincenzo Maffione p_state = P_MEMID; 2915c4f8d80SVincenzo Maffione break; 2925c4f8d80SVincenzo Maffione default: 2935c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unknown modifier: '%c'", *scan); 2945c4f8d80SVincenzo Maffione goto fail; 2955c4f8d80SVincenzo Maffione } 2965c4f8d80SVincenzo Maffione scan++; 2975c4f8d80SVincenzo Maffione break; 2985c4f8d80SVincenzo Maffione case P_RNGSFXOK: 2995c4f8d80SVincenzo Maffione switch (*scan) { 3005c4f8d80SVincenzo Maffione case '/': 3015c4f8d80SVincenzo Maffione p_state = P_FLAGS; 3025c4f8d80SVincenzo Maffione break; 3035c4f8d80SVincenzo Maffione case '@': 3045c4f8d80SVincenzo Maffione p_state = P_MEMID; 3055c4f8d80SVincenzo Maffione break; 3065c4f8d80SVincenzo Maffione default: 3075c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unexpected character: '%c'", *scan); 3085c4f8d80SVincenzo Maffione goto fail; 3095c4f8d80SVincenzo Maffione } 3105c4f8d80SVincenzo Maffione scan++; 3115c4f8d80SVincenzo Maffione break; 3125c4f8d80SVincenzo Maffione case P_GETNUM: 3135c4f8d80SVincenzo Maffione if (!isdigit(*scan)) { 3145c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "got '%s' while expecting a number", scan); 3155c4f8d80SVincenzo Maffione goto fail; 3165c4f8d80SVincenzo Maffione } 3175c4f8d80SVincenzo Maffione num = strtol(scan, (char **)&scan, 10); 3185c4f8d80SVincenzo Maffione if (num < 0 || num >= NETMAP_RING_MASK) { 3195c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "'%ld' out of range [0, %d)", 3205c4f8d80SVincenzo Maffione num, NETMAP_RING_MASK); 3215c4f8d80SVincenzo Maffione goto fail; 3225c4f8d80SVincenzo Maffione } 3235c4f8d80SVincenzo Maffione nr_ringid = num & NETMAP_RING_MASK; 3245c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 3255c4f8d80SVincenzo Maffione break; 3265c4f8d80SVincenzo Maffione case P_FLAGS: 3275c4f8d80SVincenzo Maffione case P_FLAGSOK: 3285c4f8d80SVincenzo Maffione switch (*scan) { 3295c4f8d80SVincenzo Maffione case '@': 3305c4f8d80SVincenzo Maffione p_state = P_MEMID; 3315c4f8d80SVincenzo Maffione scan++; 3325c4f8d80SVincenzo Maffione continue; 3335c4f8d80SVincenzo Maffione case 'x': 3345c4f8d80SVincenzo Maffione nr_flags |= NR_EXCLUSIVE; 3355c4f8d80SVincenzo Maffione break; 3365c4f8d80SVincenzo Maffione case 'z': 3375c4f8d80SVincenzo Maffione nr_flags |= NR_ZCOPY_MON; 3385c4f8d80SVincenzo Maffione break; 3395c4f8d80SVincenzo Maffione case 't': 3405c4f8d80SVincenzo Maffione nr_flags |= NR_MONITOR_TX; 3415c4f8d80SVincenzo Maffione break; 3425c4f8d80SVincenzo Maffione case 'r': 3435c4f8d80SVincenzo Maffione nr_flags |= NR_MONITOR_RX; 3445c4f8d80SVincenzo Maffione break; 3455c4f8d80SVincenzo Maffione case 'R': 3465c4f8d80SVincenzo Maffione nr_flags |= NR_RX_RINGS_ONLY; 3475c4f8d80SVincenzo Maffione break; 3485c4f8d80SVincenzo Maffione case 'T': 3495c4f8d80SVincenzo Maffione nr_flags |= NR_TX_RINGS_ONLY; 3505c4f8d80SVincenzo Maffione break; 3515c4f8d80SVincenzo Maffione default: 3525c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unrecognized flag: '%c'", *scan); 3535c4f8d80SVincenzo Maffione goto fail; 3545c4f8d80SVincenzo Maffione } 3555c4f8d80SVincenzo Maffione scan++; 3565c4f8d80SVincenzo Maffione p_state = P_FLAGSOK; 3575c4f8d80SVincenzo Maffione break; 3585c4f8d80SVincenzo Maffione case P_MEMID: 3595c4f8d80SVincenzo Maffione if (!isdigit(*scan)) { 3605c4f8d80SVincenzo Maffione scan--; /* escape to options */ 3615c4f8d80SVincenzo Maffione goto out; 3625c4f8d80SVincenzo Maffione } 3635c4f8d80SVincenzo Maffione num = strtol(scan, (char **)&scan, 10); 3645c4f8d80SVincenzo Maffione if (num <= 0) { 3655c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid mem_id: '%ld'", num); 3665c4f8d80SVincenzo Maffione goto fail; 3675c4f8d80SVincenzo Maffione } 3685c4f8d80SVincenzo Maffione if (nr_mem_id && nr_mem_id != num) { 3695c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid setting of mem_id to %ld (already set to %"PRIu16")", num, nr_mem_id); 3705c4f8d80SVincenzo Maffione goto fail; 3715c4f8d80SVincenzo Maffione } 3725c4f8d80SVincenzo Maffione nr_mem_id = num; 3735c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 3745c4f8d80SVincenzo Maffione break; 3755c4f8d80SVincenzo Maffione case P_ONESW: 3765c4f8d80SVincenzo Maffione if (!isdigit(*scan)) { 3775c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 3785c4f8d80SVincenzo Maffione } else { 3795c4f8d80SVincenzo Maffione nr_mode = NR_REG_ONE_SW; 3805c4f8d80SVincenzo Maffione p_state = P_GETNUM; 3815c4f8d80SVincenzo Maffione } 3825c4f8d80SVincenzo Maffione break; 3835c4f8d80SVincenzo Maffione } 3845c4f8d80SVincenzo Maffione } 3855c4f8d80SVincenzo Maffione if (p_state == P_MEMID && !*scan) { 3865c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid empty mem_id"); 3875c4f8d80SVincenzo Maffione goto fail; 3885c4f8d80SVincenzo Maffione } 3895c4f8d80SVincenzo Maffione if (p_state != P_START && p_state != P_RNGSFXOK && 3905c4f8d80SVincenzo Maffione p_state != P_FLAGSOK && p_state != P_MEMID && p_state != P_ONESW) { 3915c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unexpected end of request"); 3925c4f8d80SVincenzo Maffione goto fail; 3935c4f8d80SVincenzo Maffione } 3945c4f8d80SVincenzo Maffione out: 3955c4f8d80SVincenzo Maffione ED("flags: %s %s %s %s %s %s", 3965c4f8d80SVincenzo Maffione (nr_flags & NR_EXCLUSIVE) ? "EXCLUSIVE" : "", 3975c4f8d80SVincenzo Maffione (nr_flags & NR_ZCOPY_MON) ? "ZCOPY_MON" : "", 3985c4f8d80SVincenzo Maffione (nr_flags & NR_MONITOR_TX) ? "MONITOR_TX" : "", 3995c4f8d80SVincenzo Maffione (nr_flags & NR_MONITOR_RX) ? "MONITOR_RX" : "", 4005c4f8d80SVincenzo Maffione (nr_flags & NR_RX_RINGS_ONLY) ? "RX_RINGS_ONLY" : "", 4015c4f8d80SVincenzo Maffione (nr_flags & NR_TX_RINGS_ONLY) ? "TX_RINGS_ONLY" : ""); 4025c4f8d80SVincenzo Maffione r->nr_mode = nr_mode; 4035c4f8d80SVincenzo Maffione r->nr_ringid = nr_ringid; 4045c4f8d80SVincenzo Maffione r->nr_flags = nr_flags; 4055c4f8d80SVincenzo Maffione r->nr_mem_id = nr_mem_id; 4065c4f8d80SVincenzo Maffione *pifname = scan; 4075c4f8d80SVincenzo Maffione return 0; 4085c4f8d80SVincenzo Maffione 4095c4f8d80SVincenzo Maffione fail: 4105c4f8d80SVincenzo Maffione if (!errno) 4115c4f8d80SVincenzo Maffione errno = EINVAL; 4125c4f8d80SVincenzo Maffione return -1; 4135c4f8d80SVincenzo Maffione } 4145c4f8d80SVincenzo Maffione 4155c4f8d80SVincenzo Maffione 4165c4f8d80SVincenzo Maffione static int 4175c4f8d80SVincenzo Maffione nmreq_option_parsekeys(const char *prefix, char *body, struct nmreq_opt_parser *p, 4185c4f8d80SVincenzo Maffione struct nmreq_parse_ctx *pctx) 4195c4f8d80SVincenzo Maffione { 4205c4f8d80SVincenzo Maffione char *scan; 4215c4f8d80SVincenzo Maffione char delim1; 4225c4f8d80SVincenzo Maffione struct nmreq_opt_key *k; 4235c4f8d80SVincenzo Maffione 4245c4f8d80SVincenzo Maffione scan = body; 4255c4f8d80SVincenzo Maffione delim1 = *scan; 4265c4f8d80SVincenzo Maffione while (delim1 != '\0') { 4275c4f8d80SVincenzo Maffione char *key, *value; 4285c4f8d80SVincenzo Maffione char delim; 4295c4f8d80SVincenzo Maffione size_t vlen; 4305c4f8d80SVincenzo Maffione 4315c4f8d80SVincenzo Maffione key = scan; 4325c4f8d80SVincenzo Maffione for ( scan++; *scan != '\0' && *scan != '=' && *scan != ','; scan++) { 4335c4f8d80SVincenzo Maffione if (*scan == '-') 4345c4f8d80SVincenzo Maffione *scan = '_'; 4355c4f8d80SVincenzo Maffione } 4365c4f8d80SVincenzo Maffione delim = *scan; 4375c4f8d80SVincenzo Maffione *scan = '\0'; 4385c4f8d80SVincenzo Maffione scan++; 4395c4f8d80SVincenzo Maffione for (k = p->keys; (k - p->keys) < NMREQ_OPT_MAXKEYS && k->key != NULL; 4405c4f8d80SVincenzo Maffione k++) { 4415c4f8d80SVincenzo Maffione if (!strcmp(k->key, key)) 4425c4f8d80SVincenzo Maffione goto found; 4435c4f8d80SVincenzo Maffione 4445c4f8d80SVincenzo Maffione } 4455c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "unknown key: '%s'", key); 4465c4f8d80SVincenzo Maffione errno = EINVAL; 4475c4f8d80SVincenzo Maffione return -1; 4485c4f8d80SVincenzo Maffione found: 4495c4f8d80SVincenzo Maffione if (pctx->keys[k->id] != NULL) { 4505c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "option '%s': duplicate key '%s', already set to '%s'", 4515c4f8d80SVincenzo Maffione prefix, key, pctx->keys[k->id]); 4525c4f8d80SVincenzo Maffione errno = EINVAL; 4535c4f8d80SVincenzo Maffione return -1; 4545c4f8d80SVincenzo Maffione } 4555c4f8d80SVincenzo Maffione value = scan; 4565c4f8d80SVincenzo Maffione for ( ; *scan != '\0' && *scan != ','; scan++) 4575c4f8d80SVincenzo Maffione ; 4585c4f8d80SVincenzo Maffione delim1 = *scan; 4595c4f8d80SVincenzo Maffione *scan = '\0'; 4605c4f8d80SVincenzo Maffione vlen = scan - value; 4615c4f8d80SVincenzo Maffione scan++; 4625c4f8d80SVincenzo Maffione if (delim == '=') { 4635c4f8d80SVincenzo Maffione pctx->keys[k->id] = (vlen ? value : NULL); 4645c4f8d80SVincenzo Maffione } else { 4655c4f8d80SVincenzo Maffione if (!(k->flags & NMREQ_OPTK_ALLOWEMPTY)) { 4665c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "option '%s': missing '=value' for key '%s'", 4675c4f8d80SVincenzo Maffione prefix, key); 4685c4f8d80SVincenzo Maffione errno = EINVAL; 4695c4f8d80SVincenzo Maffione return -1; 4705c4f8d80SVincenzo Maffione } 4715c4f8d80SVincenzo Maffione pctx->keys[k->id] = key; 4725c4f8d80SVincenzo Maffione } 4735c4f8d80SVincenzo Maffione } 4745c4f8d80SVincenzo Maffione /* now check that all no-default keys have been assigned */ 4755c4f8d80SVincenzo Maffione for (k = p->keys; (k - p->keys) < NMREQ_OPT_MAXKEYS && k->key != NULL; k++) { 4765c4f8d80SVincenzo Maffione if ((k->flags & NMREQ_OPTK_MUSTSET) && pctx->keys[k->id] == NULL) { 4775c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "option '%s': mandatory key '%s' not assigned", 4785c4f8d80SVincenzo Maffione prefix, k->key); 4795c4f8d80SVincenzo Maffione errno = EINVAL; 4805c4f8d80SVincenzo Maffione return -1; 4815c4f8d80SVincenzo Maffione } 4825c4f8d80SVincenzo Maffione } 4835c4f8d80SVincenzo Maffione return 0; 4845c4f8d80SVincenzo Maffione } 4855c4f8d80SVincenzo Maffione 4865c4f8d80SVincenzo Maffione 4875c4f8d80SVincenzo Maffione static int 4885c4f8d80SVincenzo Maffione nmreq_option_decode1(char *opt, struct nmreq_opt_parser *parsers, 4895c4f8d80SVincenzo Maffione void *token, struct nmctx *ctx) 4905c4f8d80SVincenzo Maffione { 4915c4f8d80SVincenzo Maffione struct nmreq_opt_parser *p; 4925c4f8d80SVincenzo Maffione const char *prefix; 4935c4f8d80SVincenzo Maffione char *scan; 4945c4f8d80SVincenzo Maffione char delim; 4955c4f8d80SVincenzo Maffione struct nmreq_parse_ctx pctx; 4965c4f8d80SVincenzo Maffione int i; 4975c4f8d80SVincenzo Maffione 4985c4f8d80SVincenzo Maffione prefix = opt; 4995c4f8d80SVincenzo Maffione /* find the delimiter */ 5005c4f8d80SVincenzo Maffione for (scan = opt; *scan != '\0' && *scan != ':' && *scan != '='; scan++) 5015c4f8d80SVincenzo Maffione ; 5025c4f8d80SVincenzo Maffione delim = *scan; 5035c4f8d80SVincenzo Maffione *scan = '\0'; 5045c4f8d80SVincenzo Maffione scan++; 5055c4f8d80SVincenzo Maffione /* find the prefix */ 5065c4f8d80SVincenzo Maffione for (p = parsers; p != NULL; p = p->next) { 5075c4f8d80SVincenzo Maffione if (!strcmp(prefix, p->prefix)) 5085c4f8d80SVincenzo Maffione break; 5095c4f8d80SVincenzo Maffione } 5105c4f8d80SVincenzo Maffione if (p == NULL) { 5115c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unknown option: '%s'", prefix); 5125c4f8d80SVincenzo Maffione errno = EINVAL; 5135c4f8d80SVincenzo Maffione return -1; 5145c4f8d80SVincenzo Maffione } 5155c4f8d80SVincenzo Maffione if (p->flags & NMREQ_OPTF_DISABLED) { 5165c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "option '%s' is not supported", prefix); 5175c4f8d80SVincenzo Maffione errno = EOPNOTSUPP; 5185c4f8d80SVincenzo Maffione return -1; 5195c4f8d80SVincenzo Maffione } 5205c4f8d80SVincenzo Maffione /* prepare the parse context */ 5215c4f8d80SVincenzo Maffione pctx.ctx = ctx; 5225c4f8d80SVincenzo Maffione pctx.token = token; 5235c4f8d80SVincenzo Maffione for (i = 0; i < NMREQ_OPT_MAXKEYS; i++) 5245c4f8d80SVincenzo Maffione pctx.keys[i] = NULL; 5255c4f8d80SVincenzo Maffione switch (delim) { 5265c4f8d80SVincenzo Maffione case '\0': 5275c4f8d80SVincenzo Maffione /* no body */ 5285c4f8d80SVincenzo Maffione if (!(p->flags & NMREQ_OPTF_ALLOWEMPTY)) { 5295c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "syntax error: missing body after '%s'", 5305c4f8d80SVincenzo Maffione prefix); 5315c4f8d80SVincenzo Maffione errno = EINVAL; 5325c4f8d80SVincenzo Maffione return -1; 5335c4f8d80SVincenzo Maffione } 5345c4f8d80SVincenzo Maffione break; 5355c4f8d80SVincenzo Maffione case '=': /* the body goes to the default option key, if any */ 5365c4f8d80SVincenzo Maffione if (p->default_key < 0 || p->default_key >= NMREQ_OPT_MAXKEYS) { 5375c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "syntax error: '=' not valid after '%s'", 5385c4f8d80SVincenzo Maffione prefix); 5395c4f8d80SVincenzo Maffione errno = EINVAL; 5405c4f8d80SVincenzo Maffione return -1; 5415c4f8d80SVincenzo Maffione } 5425c4f8d80SVincenzo Maffione if (*scan == '\0') { 5435c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "missing value for option '%s'", prefix); 5445c4f8d80SVincenzo Maffione errno = EINVAL; 5455c4f8d80SVincenzo Maffione return -1; 5465c4f8d80SVincenzo Maffione } 5475c4f8d80SVincenzo Maffione pctx.keys[p->default_key] = scan; 5485c4f8d80SVincenzo Maffione break; 5495c4f8d80SVincenzo Maffione case ':': /* parse 'key=value' strings */ 5505c4f8d80SVincenzo Maffione if (nmreq_option_parsekeys(prefix, scan, p, &pctx) < 0) 5515c4f8d80SVincenzo Maffione return -1; 5525c4f8d80SVincenzo Maffione break; 5535c4f8d80SVincenzo Maffione } 5545c4f8d80SVincenzo Maffione return p->parse(&pctx); 5555c4f8d80SVincenzo Maffione } 5565c4f8d80SVincenzo Maffione 5575c4f8d80SVincenzo Maffione int 5585c4f8d80SVincenzo Maffione nmreq_options_decode(const char *opt, struct nmreq_opt_parser parsers[], 5595c4f8d80SVincenzo Maffione void *token, struct nmctx *ctx) 5605c4f8d80SVincenzo Maffione { 5615c4f8d80SVincenzo Maffione const char *scan, *opt1; 5625c4f8d80SVincenzo Maffione char *w; 5635c4f8d80SVincenzo Maffione size_t len; 5645c4f8d80SVincenzo Maffione int ret; 5655c4f8d80SVincenzo Maffione 5665c4f8d80SVincenzo Maffione if (*opt == '\0') 5675c4f8d80SVincenzo Maffione return 0; /* empty list, OK */ 5685c4f8d80SVincenzo Maffione 5695c4f8d80SVincenzo Maffione if (*opt != '@') { 5705c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "option list does not start with '@'"); 5715c4f8d80SVincenzo Maffione errno = EINVAL; 5725c4f8d80SVincenzo Maffione return -1; 5735c4f8d80SVincenzo Maffione } 5745c4f8d80SVincenzo Maffione 5755c4f8d80SVincenzo Maffione scan = opt; 5765c4f8d80SVincenzo Maffione do { 5775c4f8d80SVincenzo Maffione scan++; /* skip the plus */ 5785c4f8d80SVincenzo Maffione opt1 = scan; /* start of option */ 5795c4f8d80SVincenzo Maffione /* find the end of the option */ 5805c4f8d80SVincenzo Maffione for ( ; *scan != '\0' && *scan != '@'; scan++) 5815c4f8d80SVincenzo Maffione ; 5825c4f8d80SVincenzo Maffione len = scan - opt1; 5835c4f8d80SVincenzo Maffione if (len == 0) { 5845c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid empty option"); 5855c4f8d80SVincenzo Maffione errno = EINVAL; 5865c4f8d80SVincenzo Maffione return -1; 5875c4f8d80SVincenzo Maffione } 5885c4f8d80SVincenzo Maffione w = nmctx_malloc(ctx, len + 1); 5895c4f8d80SVincenzo Maffione if (w == NULL) { 5905c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "out of memory"); 5915c4f8d80SVincenzo Maffione errno = ENOMEM; 5925c4f8d80SVincenzo Maffione return -1; 5935c4f8d80SVincenzo Maffione } 5945c4f8d80SVincenzo Maffione memcpy(w, opt1, len); 5955c4f8d80SVincenzo Maffione w[len] = '\0'; 5965c4f8d80SVincenzo Maffione ret = nmreq_option_decode1(w, parsers, token, ctx); 5975c4f8d80SVincenzo Maffione nmctx_free(ctx, w); 5985c4f8d80SVincenzo Maffione if (ret < 0) 5995c4f8d80SVincenzo Maffione return -1; 6005c4f8d80SVincenzo Maffione } while (*scan != '\0'); 6015c4f8d80SVincenzo Maffione 6025c4f8d80SVincenzo Maffione return 0; 6035c4f8d80SVincenzo Maffione } 6045c4f8d80SVincenzo Maffione 6055c4f8d80SVincenzo Maffione struct nmreq_option * 6065c4f8d80SVincenzo Maffione nmreq_find_option(struct nmreq_header *h, uint32_t t) 6075c4f8d80SVincenzo Maffione { 60888024c4aSVincenzo Maffione struct nmreq_option *o = NULL; 6095c4f8d80SVincenzo Maffione 61088024c4aSVincenzo Maffione nmreq_foreach_option(h, o) { 6115c4f8d80SVincenzo Maffione if (o->nro_reqtype == t) 6125c4f8d80SVincenzo Maffione break; 6135c4f8d80SVincenzo Maffione } 6145c4f8d80SVincenzo Maffione return o; 6155c4f8d80SVincenzo Maffione } 6165c4f8d80SVincenzo Maffione 6175c4f8d80SVincenzo Maffione void 6185c4f8d80SVincenzo Maffione nmreq_remove_option(struct nmreq_header *h, struct nmreq_option *o) 6195c4f8d80SVincenzo Maffione { 6205c4f8d80SVincenzo Maffione struct nmreq_option **nmo; 6215c4f8d80SVincenzo Maffione 6225c4f8d80SVincenzo Maffione for (nmo = (struct nmreq_option **)&h->nr_options; *nmo != NULL; 6235c4f8d80SVincenzo Maffione nmo = (struct nmreq_option **)&(*nmo)->nro_next) { 6245c4f8d80SVincenzo Maffione if (*nmo == o) { 6255c4f8d80SVincenzo Maffione *((uint64_t *)(*nmo)) = o->nro_next; 6265c4f8d80SVincenzo Maffione o->nro_next = (uint64_t)(uintptr_t)NULL; 6275c4f8d80SVincenzo Maffione break; 6285c4f8d80SVincenzo Maffione } 6295c4f8d80SVincenzo Maffione } 6305c4f8d80SVincenzo Maffione } 6315c4f8d80SVincenzo Maffione 6325c4f8d80SVincenzo Maffione void 6335c4f8d80SVincenzo Maffione nmreq_free_options(struct nmreq_header *h) 6345c4f8d80SVincenzo Maffione { 6355c4f8d80SVincenzo Maffione struct nmreq_option *o, *next; 6365c4f8d80SVincenzo Maffione 63788024c4aSVincenzo Maffione /* 63888024c4aSVincenzo Maffione * Note: can't use nmreq_foreach_option() here; it frees the 63988024c4aSVincenzo Maffione * list as it's walking and nmreq_foreach_option() isn't 64088024c4aSVincenzo Maffione * modification-safe. 64188024c4aSVincenzo Maffione */ 64288024c4aSVincenzo Maffione for (o = (struct nmreq_option *)(uintptr_t)h->nr_options; o != NULL; 64388024c4aSVincenzo Maffione o = next) { 64488024c4aSVincenzo Maffione next = (struct nmreq_option *)(uintptr_t)o->nro_next; 6455c4f8d80SVincenzo Maffione free(o); 6465c4f8d80SVincenzo Maffione } 6475c4f8d80SVincenzo Maffione } 6485c4f8d80SVincenzo Maffione 6495c4f8d80SVincenzo Maffione const char* 6505c4f8d80SVincenzo Maffione nmreq_option_name(uint32_t nro_reqtype) 6515c4f8d80SVincenzo Maffione { 6525c4f8d80SVincenzo Maffione switch (nro_reqtype) { 6535c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_EXTMEM: 6545c4f8d80SVincenzo Maffione return "extmem"; 6555c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_SYNC_KLOOP_EVENTFDS: 6565c4f8d80SVincenzo Maffione return "sync-kloop-eventfds"; 6575c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_CSB: 6585c4f8d80SVincenzo Maffione return "csb"; 6595c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_SYNC_KLOOP_MODE: 6605c4f8d80SVincenzo Maffione return "sync-kloop-mode"; 661f8113f0aSVincenzo Maffione case NETMAP_REQ_OPT_OFFSETS: 662f8113f0aSVincenzo Maffione return "offsets"; 6635c4f8d80SVincenzo Maffione default: 6645c4f8d80SVincenzo Maffione return "unknown"; 6655c4f8d80SVincenzo Maffione } 6665c4f8d80SVincenzo Maffione } 6675c4f8d80SVincenzo Maffione 6685c4f8d80SVincenzo Maffione #if 0 6695c4f8d80SVincenzo Maffione #include <inttypes.h> 6705c4f8d80SVincenzo Maffione static void 6715c4f8d80SVincenzo Maffione nmreq_dump(struct nmport_d *d) 6725c4f8d80SVincenzo Maffione { 6735c4f8d80SVincenzo Maffione printf("header:\n"); 6745c4f8d80SVincenzo Maffione printf(" nr_version: %"PRIu16"\n", d->hdr.nr_version); 6755c4f8d80SVincenzo Maffione printf(" nr_reqtype: %"PRIu16"\n", d->hdr.nr_reqtype); 6765c4f8d80SVincenzo Maffione printf(" nr_reserved: %"PRIu32"\n", d->hdr.nr_reserved); 6775c4f8d80SVincenzo Maffione printf(" nr_name: %s\n", d->hdr.nr_name); 6785c4f8d80SVincenzo Maffione printf(" nr_options: %lx\n", (unsigned long)d->hdr.nr_options); 6795c4f8d80SVincenzo Maffione printf(" nr_body: %lx\n", (unsigned long)d->hdr.nr_body); 6805c4f8d80SVincenzo Maffione printf("\n"); 6815c4f8d80SVincenzo Maffione printf("register (%p):\n", (void *)d->hdr.nr_body); 6825c4f8d80SVincenzo Maffione printf(" nr_mem_id: %"PRIu16"\n", d->reg.nr_mem_id); 6835c4f8d80SVincenzo Maffione printf(" nr_ringid: %"PRIu16"\n", d->reg.nr_ringid); 6845c4f8d80SVincenzo Maffione printf(" nr_mode: %lx\n", (unsigned long)d->reg.nr_mode); 6855c4f8d80SVincenzo Maffione printf(" nr_flags: %lx\n", (unsigned long)d->reg.nr_flags); 6865c4f8d80SVincenzo Maffione printf("\n"); 6875c4f8d80SVincenzo Maffione if (d->hdr.nr_options) { 6885c4f8d80SVincenzo Maffione struct nmreq_opt_extmem *e = (struct nmreq_opt_extmem *)d->hdr.nr_options; 6895c4f8d80SVincenzo Maffione printf("opt_extmem (%p):\n", e); 6905c4f8d80SVincenzo Maffione printf(" nro_opt.nro_next: %lx\n", (unsigned long)e->nro_opt.nro_next); 6915c4f8d80SVincenzo Maffione printf(" nro_opt.nro_reqtype: %"PRIu32"\n", e->nro_opt.nro_reqtype); 6925c4f8d80SVincenzo Maffione printf(" nro_usrptr: %lx\n", (unsigned long)e->nro_usrptr); 6935c4f8d80SVincenzo Maffione printf(" nro_info.nr_memsize %"PRIu64"\n", e->nro_info.nr_memsize); 6945c4f8d80SVincenzo Maffione } 6955c4f8d80SVincenzo Maffione printf("\n"); 6965c4f8d80SVincenzo Maffione printf("mem (%p):\n", d->mem); 6975c4f8d80SVincenzo Maffione printf(" refcount: %d\n", d->mem->refcount); 6985c4f8d80SVincenzo Maffione printf(" mem: %p\n", d->mem->mem); 6995c4f8d80SVincenzo Maffione printf(" size: %zu\n", d->mem->size); 7005c4f8d80SVincenzo Maffione printf("\n"); 7015c4f8d80SVincenzo Maffione printf("rings:\n"); 7025c4f8d80SVincenzo Maffione printf(" tx: [%d, %d]\n", d->first_tx_ring, d->last_tx_ring); 7035c4f8d80SVincenzo Maffione printf(" rx: [%d, %d]\n", d->first_rx_ring, d->last_rx_ring); 7045c4f8d80SVincenzo Maffione } 7055c4f8d80SVincenzo Maffione int 7065c4f8d80SVincenzo Maffione main(int argc, char *argv[]) 7075c4f8d80SVincenzo Maffione { 7085c4f8d80SVincenzo Maffione struct nmport_d *d; 7095c4f8d80SVincenzo Maffione 7105c4f8d80SVincenzo Maffione if (argc < 2) { 7115c4f8d80SVincenzo Maffione fprintf(stderr, "usage: %s netmap-expr\n", argv[0]); 7125c4f8d80SVincenzo Maffione return 1; 7135c4f8d80SVincenzo Maffione } 7145c4f8d80SVincenzo Maffione 7155c4f8d80SVincenzo Maffione d = nmport_open(argv[1]); 7165c4f8d80SVincenzo Maffione if (d != NULL) { 7175c4f8d80SVincenzo Maffione nmreq_dump(d); 7185c4f8d80SVincenzo Maffione nmport_close(d); 7195c4f8d80SVincenzo Maffione } 7205c4f8d80SVincenzo Maffione 7215c4f8d80SVincenzo Maffione return 0; 7225c4f8d80SVincenzo Maffione } 7235c4f8d80SVincenzo Maffione #endif 724