1*5c4f8d80SVincenzo Maffione /* $FreeBSD$ */ 2*5c4f8d80SVincenzo Maffione #include <sys/types.h> 3*5c4f8d80SVincenzo Maffione #include <sys/stat.h> 4*5c4f8d80SVincenzo Maffione #include <sys/ioctl.h> 5*5c4f8d80SVincenzo Maffione #include <sys/mman.h> 6*5c4f8d80SVincenzo Maffione #include <ctype.h> 7*5c4f8d80SVincenzo Maffione #include <fcntl.h> 8*5c4f8d80SVincenzo Maffione #include <inttypes.h> 9*5c4f8d80SVincenzo Maffione #include <stdlib.h> 10*5c4f8d80SVincenzo Maffione #include <stdio.h> 11*5c4f8d80SVincenzo Maffione #include <stdarg.h> 12*5c4f8d80SVincenzo Maffione #include <string.h> 13*5c4f8d80SVincenzo Maffione #include <unistd.h> 14*5c4f8d80SVincenzo Maffione #include <errno.h> 15*5c4f8d80SVincenzo Maffione 16*5c4f8d80SVincenzo Maffione //#define NMREQ_DEBUG 17*5c4f8d80SVincenzo Maffione #ifdef NMREQ_DEBUG 18*5c4f8d80SVincenzo Maffione #define NETMAP_WITH_LIBS 19*5c4f8d80SVincenzo Maffione #define ED(...) D(__VA_ARGS__) 20*5c4f8d80SVincenzo Maffione #else 21*5c4f8d80SVincenzo Maffione #define ED(...) 22*5c4f8d80SVincenzo Maffione /* an identifier is a possibly empty sequence of alphanum characters and 23*5c4f8d80SVincenzo Maffione * underscores 24*5c4f8d80SVincenzo Maffione */ 25*5c4f8d80SVincenzo Maffione static int 26*5c4f8d80SVincenzo Maffione nm_is_identifier(const char *s, const char *e) 27*5c4f8d80SVincenzo Maffione { 28*5c4f8d80SVincenzo Maffione for (; s != e; s++) { 29*5c4f8d80SVincenzo Maffione if (!isalnum(*s) && *s != '_') { 30*5c4f8d80SVincenzo Maffione return 0; 31*5c4f8d80SVincenzo Maffione } 32*5c4f8d80SVincenzo Maffione } 33*5c4f8d80SVincenzo Maffione 34*5c4f8d80SVincenzo Maffione return 1; 35*5c4f8d80SVincenzo Maffione } 36*5c4f8d80SVincenzo Maffione #endif /* NMREQ_DEBUG */ 37*5c4f8d80SVincenzo Maffione 38*5c4f8d80SVincenzo Maffione #include <net/netmap_user.h> 39*5c4f8d80SVincenzo Maffione #define LIBNETMAP_NOTHREADSAFE 40*5c4f8d80SVincenzo Maffione #include "libnetmap.h" 41*5c4f8d80SVincenzo Maffione 42*5c4f8d80SVincenzo Maffione void 43*5c4f8d80SVincenzo Maffione nmreq_push_option(struct nmreq_header *h, struct nmreq_option *o) 44*5c4f8d80SVincenzo Maffione { 45*5c4f8d80SVincenzo Maffione o->nro_next = h->nr_options; 46*5c4f8d80SVincenzo Maffione h->nr_options = (uintptr_t)o; 47*5c4f8d80SVincenzo Maffione } 48*5c4f8d80SVincenzo Maffione 49*5c4f8d80SVincenzo Maffione struct nmreq_prefix { 50*5c4f8d80SVincenzo Maffione const char *prefix; /* the constant part of the prefix */ 51*5c4f8d80SVincenzo Maffione size_t len; /* its strlen() */ 52*5c4f8d80SVincenzo Maffione uint32_t flags; 53*5c4f8d80SVincenzo Maffione #define NR_P_ID (1U << 0) /* whether an identifier is needed */ 54*5c4f8d80SVincenzo Maffione #define NR_P_SKIP (1U << 1) /* whether the scope must be passed to netmap */ 55*5c4f8d80SVincenzo Maffione #define NR_P_EMPTYID (1U << 2) /* whether an empty identifier is allowed */ 56*5c4f8d80SVincenzo Maffione }; 57*5c4f8d80SVincenzo Maffione 58*5c4f8d80SVincenzo Maffione #define declprefix(prefix, flags) { (prefix), (sizeof(prefix) - 1), (flags) } 59*5c4f8d80SVincenzo Maffione 60*5c4f8d80SVincenzo Maffione static struct nmreq_prefix nmreq_prefixes[] = { 61*5c4f8d80SVincenzo Maffione declprefix("netmap", NR_P_SKIP), 62*5c4f8d80SVincenzo Maffione declprefix(NM_BDG_NAME, NR_P_ID|NR_P_EMPTYID), 63*5c4f8d80SVincenzo Maffione { NULL } /* terminate the list */ 64*5c4f8d80SVincenzo Maffione }; 65*5c4f8d80SVincenzo Maffione 66*5c4f8d80SVincenzo Maffione void 67*5c4f8d80SVincenzo Maffione nmreq_header_init(struct nmreq_header *h, uint16_t reqtype, void *body) 68*5c4f8d80SVincenzo Maffione { 69*5c4f8d80SVincenzo Maffione memset(h, 0, sizeof(*h)); 70*5c4f8d80SVincenzo Maffione h->nr_version = NETMAP_API; 71*5c4f8d80SVincenzo Maffione h->nr_reqtype = reqtype; 72*5c4f8d80SVincenzo Maffione h->nr_body = (uintptr_t)body; 73*5c4f8d80SVincenzo Maffione } 74*5c4f8d80SVincenzo Maffione 75*5c4f8d80SVincenzo Maffione int 76*5c4f8d80SVincenzo Maffione nmreq_header_decode(const char **pifname, struct nmreq_header *h, struct nmctx *ctx) 77*5c4f8d80SVincenzo Maffione { 78*5c4f8d80SVincenzo Maffione const char *scan = NULL; 79*5c4f8d80SVincenzo Maffione const char *vpname = NULL; 80*5c4f8d80SVincenzo Maffione const char *pipesep = NULL; 81*5c4f8d80SVincenzo Maffione u_int namelen; 82*5c4f8d80SVincenzo Maffione const char *ifname = *pifname; 83*5c4f8d80SVincenzo Maffione struct nmreq_prefix *p; 84*5c4f8d80SVincenzo Maffione 85*5c4f8d80SVincenzo Maffione scan = ifname; 86*5c4f8d80SVincenzo Maffione for (p = nmreq_prefixes; p->prefix != NULL; p++) { 87*5c4f8d80SVincenzo Maffione if (!strncmp(scan, p->prefix, p->len)) 88*5c4f8d80SVincenzo Maffione break; 89*5c4f8d80SVincenzo Maffione } 90*5c4f8d80SVincenzo Maffione if (p->prefix == NULL) { 91*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid request, prefix unknown or missing", *pifname); 92*5c4f8d80SVincenzo Maffione goto fail; 93*5c4f8d80SVincenzo Maffione } 94*5c4f8d80SVincenzo Maffione scan += p->len; 95*5c4f8d80SVincenzo Maffione 96*5c4f8d80SVincenzo Maffione vpname = index(scan, ':'); 97*5c4f8d80SVincenzo Maffione if (vpname == NULL) { 98*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: missing ':'", ifname); 99*5c4f8d80SVincenzo Maffione goto fail; 100*5c4f8d80SVincenzo Maffione } 101*5c4f8d80SVincenzo Maffione if (vpname != scan) { 102*5c4f8d80SVincenzo Maffione /* there is an identifier, can we accept it? */ 103*5c4f8d80SVincenzo Maffione if (!(p->flags & NR_P_ID)) { 104*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: no identifier allowed between '%s' and ':'", *pifname, p->prefix); 105*5c4f8d80SVincenzo Maffione goto fail; 106*5c4f8d80SVincenzo Maffione } 107*5c4f8d80SVincenzo Maffione 108*5c4f8d80SVincenzo Maffione if (!nm_is_identifier(scan, vpname)) { 109*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid identifier '%.*s'", *pifname, vpname - scan, scan); 110*5c4f8d80SVincenzo Maffione goto fail; 111*5c4f8d80SVincenzo Maffione } 112*5c4f8d80SVincenzo Maffione } else { 113*5c4f8d80SVincenzo Maffione if ((p->flags & NR_P_ID) && !(p->flags & NR_P_EMPTYID)) { 114*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: identifier is missing between '%s' and ':'", *pifname, p->prefix); 115*5c4f8d80SVincenzo Maffione goto fail; 116*5c4f8d80SVincenzo Maffione } 117*5c4f8d80SVincenzo Maffione } 118*5c4f8d80SVincenzo Maffione ++vpname; /* skip the colon */ 119*5c4f8d80SVincenzo Maffione if (p->flags & NR_P_SKIP) 120*5c4f8d80SVincenzo Maffione ifname = vpname; 121*5c4f8d80SVincenzo Maffione scan = vpname; 122*5c4f8d80SVincenzo Maffione 123*5c4f8d80SVincenzo Maffione /* scan for a separator */ 124*5c4f8d80SVincenzo Maffione for (; *scan && !index("-*^/@", *scan); scan++) 125*5c4f8d80SVincenzo Maffione ; 126*5c4f8d80SVincenzo Maffione 127*5c4f8d80SVincenzo Maffione /* search for possible pipe indicators */ 128*5c4f8d80SVincenzo Maffione for (pipesep = vpname; pipesep != scan && !index("{}", *pipesep); pipesep++) 129*5c4f8d80SVincenzo Maffione ; 130*5c4f8d80SVincenzo Maffione 131*5c4f8d80SVincenzo Maffione if (!nm_is_identifier(vpname, pipesep)) { 132*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid port name '%.*s'", *pifname, 133*5c4f8d80SVincenzo Maffione pipesep - vpname, vpname); 134*5c4f8d80SVincenzo Maffione goto fail; 135*5c4f8d80SVincenzo Maffione } 136*5c4f8d80SVincenzo Maffione if (pipesep != scan) { 137*5c4f8d80SVincenzo Maffione pipesep++; 138*5c4f8d80SVincenzo Maffione if (*pipesep == '\0') { 139*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid empty pipe name", *pifname); 140*5c4f8d80SVincenzo Maffione goto fail; 141*5c4f8d80SVincenzo Maffione } 142*5c4f8d80SVincenzo Maffione if (!nm_is_identifier(pipesep, scan)) { 143*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid pipe name '%.*s'", *pifname, scan - pipesep, pipesep); 144*5c4f8d80SVincenzo Maffione goto fail; 145*5c4f8d80SVincenzo Maffione } 146*5c4f8d80SVincenzo Maffione } 147*5c4f8d80SVincenzo Maffione 148*5c4f8d80SVincenzo Maffione namelen = scan - ifname; 149*5c4f8d80SVincenzo Maffione if (namelen >= sizeof(h->nr_name)) { 150*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "name '%.*s' too long", namelen, ifname); 151*5c4f8d80SVincenzo Maffione goto fail; 152*5c4f8d80SVincenzo Maffione } 153*5c4f8d80SVincenzo Maffione if (namelen == 0) { 154*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "%s: invalid empty port name", *pifname); 155*5c4f8d80SVincenzo Maffione goto fail; 156*5c4f8d80SVincenzo Maffione } 157*5c4f8d80SVincenzo Maffione 158*5c4f8d80SVincenzo Maffione /* fill the header */ 159*5c4f8d80SVincenzo Maffione memcpy(h->nr_name, ifname, namelen); 160*5c4f8d80SVincenzo Maffione h->nr_name[namelen] = '\0'; 161*5c4f8d80SVincenzo Maffione ED("name %s", h->nr_name); 162*5c4f8d80SVincenzo Maffione 163*5c4f8d80SVincenzo Maffione *pifname = scan; 164*5c4f8d80SVincenzo Maffione 165*5c4f8d80SVincenzo Maffione return 0; 166*5c4f8d80SVincenzo Maffione fail: 167*5c4f8d80SVincenzo Maffione errno = EINVAL; 168*5c4f8d80SVincenzo Maffione return -1; 169*5c4f8d80SVincenzo Maffione } 170*5c4f8d80SVincenzo Maffione 171*5c4f8d80SVincenzo Maffione 172*5c4f8d80SVincenzo Maffione /* 173*5c4f8d80SVincenzo Maffione * 0 not recognized 174*5c4f8d80SVincenzo Maffione * -1 error 175*5c4f8d80SVincenzo Maffione * >= 0 mem_id 176*5c4f8d80SVincenzo Maffione */ 177*5c4f8d80SVincenzo Maffione int32_t 178*5c4f8d80SVincenzo Maffione nmreq_get_mem_id(const char **pifname, struct nmctx *ctx) 179*5c4f8d80SVincenzo Maffione { 180*5c4f8d80SVincenzo Maffione int fd = -1; 181*5c4f8d80SVincenzo Maffione struct nmreq_header gh; 182*5c4f8d80SVincenzo Maffione struct nmreq_port_info_get gb; 183*5c4f8d80SVincenzo Maffione const char *ifname; 184*5c4f8d80SVincenzo Maffione 185*5c4f8d80SVincenzo Maffione errno = 0; 186*5c4f8d80SVincenzo Maffione ifname = *pifname; 187*5c4f8d80SVincenzo Maffione 188*5c4f8d80SVincenzo Maffione if (ifname == NULL) 189*5c4f8d80SVincenzo Maffione goto fail; 190*5c4f8d80SVincenzo Maffione 191*5c4f8d80SVincenzo Maffione /* try to look for a netmap port with this name */ 192*5c4f8d80SVincenzo Maffione fd = open("/dev/netmap", O_RDWR); 193*5c4f8d80SVincenzo Maffione if (fd < 0) { 194*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "cannot open /dev/netmap: %s", strerror(errno)); 195*5c4f8d80SVincenzo Maffione goto fail; 196*5c4f8d80SVincenzo Maffione } 197*5c4f8d80SVincenzo Maffione nmreq_header_init(&gh, NETMAP_REQ_PORT_INFO_GET, &gb); 198*5c4f8d80SVincenzo Maffione if (nmreq_header_decode(&ifname, &gh, ctx) < 0) { 199*5c4f8d80SVincenzo Maffione goto fail; 200*5c4f8d80SVincenzo Maffione } 201*5c4f8d80SVincenzo Maffione memset(&gb, 0, sizeof(gb)); 202*5c4f8d80SVincenzo Maffione if (ioctl(fd, NIOCCTRL, &gh) < 0) { 203*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "cannot get info for '%s': %s", *pifname, strerror(errno)); 204*5c4f8d80SVincenzo Maffione goto fail; 205*5c4f8d80SVincenzo Maffione } 206*5c4f8d80SVincenzo Maffione *pifname = ifname; 207*5c4f8d80SVincenzo Maffione close(fd); 208*5c4f8d80SVincenzo Maffione return gb.nr_mem_id; 209*5c4f8d80SVincenzo Maffione 210*5c4f8d80SVincenzo Maffione fail: 211*5c4f8d80SVincenzo Maffione if (fd >= 0) 212*5c4f8d80SVincenzo Maffione close(fd); 213*5c4f8d80SVincenzo Maffione if (!errno) 214*5c4f8d80SVincenzo Maffione errno = EINVAL; 215*5c4f8d80SVincenzo Maffione return -1; 216*5c4f8d80SVincenzo Maffione } 217*5c4f8d80SVincenzo Maffione 218*5c4f8d80SVincenzo Maffione 219*5c4f8d80SVincenzo Maffione int 220*5c4f8d80SVincenzo Maffione nmreq_register_decode(const char **pifname, struct nmreq_register *r, struct nmctx *ctx) 221*5c4f8d80SVincenzo Maffione { 222*5c4f8d80SVincenzo Maffione enum { P_START, P_RNGSFXOK, P_GETNUM, P_FLAGS, P_FLAGSOK, P_MEMID, P_ONESW } p_state; 223*5c4f8d80SVincenzo Maffione long num; 224*5c4f8d80SVincenzo Maffione const char *scan = *pifname; 225*5c4f8d80SVincenzo Maffione uint32_t nr_mode; 226*5c4f8d80SVincenzo Maffione uint16_t nr_mem_id; 227*5c4f8d80SVincenzo Maffione uint16_t nr_ringid; 228*5c4f8d80SVincenzo Maffione uint64_t nr_flags; 229*5c4f8d80SVincenzo Maffione 230*5c4f8d80SVincenzo Maffione /* fill the request */ 231*5c4f8d80SVincenzo Maffione 232*5c4f8d80SVincenzo Maffione p_state = P_START; 233*5c4f8d80SVincenzo Maffione /* defaults */ 234*5c4f8d80SVincenzo Maffione nr_mode = NR_REG_ALL_NIC; /* default for no suffix */ 235*5c4f8d80SVincenzo Maffione nr_mem_id = r->nr_mem_id; /* if non-zero, further updates are disabled */ 236*5c4f8d80SVincenzo Maffione nr_ringid = 0; 237*5c4f8d80SVincenzo Maffione nr_flags = 0; 238*5c4f8d80SVincenzo Maffione while (*scan) { 239*5c4f8d80SVincenzo Maffione switch (p_state) { 240*5c4f8d80SVincenzo Maffione case P_START: 241*5c4f8d80SVincenzo Maffione switch (*scan) { 242*5c4f8d80SVincenzo Maffione case '^': /* only SW ring */ 243*5c4f8d80SVincenzo Maffione nr_mode = NR_REG_SW; 244*5c4f8d80SVincenzo Maffione p_state = P_ONESW; 245*5c4f8d80SVincenzo Maffione break; 246*5c4f8d80SVincenzo Maffione case '*': /* NIC and SW */ 247*5c4f8d80SVincenzo Maffione nr_mode = NR_REG_NIC_SW; 248*5c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 249*5c4f8d80SVincenzo Maffione break; 250*5c4f8d80SVincenzo Maffione case '-': /* one NIC ring pair */ 251*5c4f8d80SVincenzo Maffione nr_mode = NR_REG_ONE_NIC; 252*5c4f8d80SVincenzo Maffione p_state = P_GETNUM; 253*5c4f8d80SVincenzo Maffione break; 254*5c4f8d80SVincenzo Maffione case '/': /* start of flags */ 255*5c4f8d80SVincenzo Maffione p_state = P_FLAGS; 256*5c4f8d80SVincenzo Maffione break; 257*5c4f8d80SVincenzo Maffione case '@': /* start of memid */ 258*5c4f8d80SVincenzo Maffione p_state = P_MEMID; 259*5c4f8d80SVincenzo Maffione break; 260*5c4f8d80SVincenzo Maffione default: 261*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unknown modifier: '%c'", *scan); 262*5c4f8d80SVincenzo Maffione goto fail; 263*5c4f8d80SVincenzo Maffione } 264*5c4f8d80SVincenzo Maffione scan++; 265*5c4f8d80SVincenzo Maffione break; 266*5c4f8d80SVincenzo Maffione case P_RNGSFXOK: 267*5c4f8d80SVincenzo Maffione switch (*scan) { 268*5c4f8d80SVincenzo Maffione case '/': 269*5c4f8d80SVincenzo Maffione p_state = P_FLAGS; 270*5c4f8d80SVincenzo Maffione break; 271*5c4f8d80SVincenzo Maffione case '@': 272*5c4f8d80SVincenzo Maffione p_state = P_MEMID; 273*5c4f8d80SVincenzo Maffione break; 274*5c4f8d80SVincenzo Maffione default: 275*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unexpected character: '%c'", *scan); 276*5c4f8d80SVincenzo Maffione goto fail; 277*5c4f8d80SVincenzo Maffione } 278*5c4f8d80SVincenzo Maffione scan++; 279*5c4f8d80SVincenzo Maffione break; 280*5c4f8d80SVincenzo Maffione case P_GETNUM: 281*5c4f8d80SVincenzo Maffione if (!isdigit(*scan)) { 282*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "got '%s' while expecting a number", scan); 283*5c4f8d80SVincenzo Maffione goto fail; 284*5c4f8d80SVincenzo Maffione } 285*5c4f8d80SVincenzo Maffione num = strtol(scan, (char **)&scan, 10); 286*5c4f8d80SVincenzo Maffione if (num < 0 || num >= NETMAP_RING_MASK) { 287*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "'%ld' out of range [0, %d)", 288*5c4f8d80SVincenzo Maffione num, NETMAP_RING_MASK); 289*5c4f8d80SVincenzo Maffione goto fail; 290*5c4f8d80SVincenzo Maffione } 291*5c4f8d80SVincenzo Maffione nr_ringid = num & NETMAP_RING_MASK; 292*5c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 293*5c4f8d80SVincenzo Maffione break; 294*5c4f8d80SVincenzo Maffione case P_FLAGS: 295*5c4f8d80SVincenzo Maffione case P_FLAGSOK: 296*5c4f8d80SVincenzo Maffione switch (*scan) { 297*5c4f8d80SVincenzo Maffione case '@': 298*5c4f8d80SVincenzo Maffione p_state = P_MEMID; 299*5c4f8d80SVincenzo Maffione scan++; 300*5c4f8d80SVincenzo Maffione continue; 301*5c4f8d80SVincenzo Maffione case 'x': 302*5c4f8d80SVincenzo Maffione nr_flags |= NR_EXCLUSIVE; 303*5c4f8d80SVincenzo Maffione break; 304*5c4f8d80SVincenzo Maffione case 'z': 305*5c4f8d80SVincenzo Maffione nr_flags |= NR_ZCOPY_MON; 306*5c4f8d80SVincenzo Maffione break; 307*5c4f8d80SVincenzo Maffione case 't': 308*5c4f8d80SVincenzo Maffione nr_flags |= NR_MONITOR_TX; 309*5c4f8d80SVincenzo Maffione break; 310*5c4f8d80SVincenzo Maffione case 'r': 311*5c4f8d80SVincenzo Maffione nr_flags |= NR_MONITOR_RX; 312*5c4f8d80SVincenzo Maffione break; 313*5c4f8d80SVincenzo Maffione case 'R': 314*5c4f8d80SVincenzo Maffione nr_flags |= NR_RX_RINGS_ONLY; 315*5c4f8d80SVincenzo Maffione break; 316*5c4f8d80SVincenzo Maffione case 'T': 317*5c4f8d80SVincenzo Maffione nr_flags |= NR_TX_RINGS_ONLY; 318*5c4f8d80SVincenzo Maffione break; 319*5c4f8d80SVincenzo Maffione default: 320*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unrecognized flag: '%c'", *scan); 321*5c4f8d80SVincenzo Maffione goto fail; 322*5c4f8d80SVincenzo Maffione } 323*5c4f8d80SVincenzo Maffione scan++; 324*5c4f8d80SVincenzo Maffione p_state = P_FLAGSOK; 325*5c4f8d80SVincenzo Maffione break; 326*5c4f8d80SVincenzo Maffione case P_MEMID: 327*5c4f8d80SVincenzo Maffione if (!isdigit(*scan)) { 328*5c4f8d80SVincenzo Maffione scan--; /* escape to options */ 329*5c4f8d80SVincenzo Maffione goto out; 330*5c4f8d80SVincenzo Maffione } 331*5c4f8d80SVincenzo Maffione num = strtol(scan, (char **)&scan, 10); 332*5c4f8d80SVincenzo Maffione if (num <= 0) { 333*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid mem_id: '%ld'", num); 334*5c4f8d80SVincenzo Maffione goto fail; 335*5c4f8d80SVincenzo Maffione } 336*5c4f8d80SVincenzo Maffione if (nr_mem_id && nr_mem_id != num) { 337*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid setting of mem_id to %ld (already set to %"PRIu16")", num, nr_mem_id); 338*5c4f8d80SVincenzo Maffione goto fail; 339*5c4f8d80SVincenzo Maffione } 340*5c4f8d80SVincenzo Maffione nr_mem_id = num; 341*5c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 342*5c4f8d80SVincenzo Maffione break; 343*5c4f8d80SVincenzo Maffione case P_ONESW: 344*5c4f8d80SVincenzo Maffione if (!isdigit(*scan)) { 345*5c4f8d80SVincenzo Maffione p_state = P_RNGSFXOK; 346*5c4f8d80SVincenzo Maffione } else { 347*5c4f8d80SVincenzo Maffione nr_mode = NR_REG_ONE_SW; 348*5c4f8d80SVincenzo Maffione p_state = P_GETNUM; 349*5c4f8d80SVincenzo Maffione } 350*5c4f8d80SVincenzo Maffione break; 351*5c4f8d80SVincenzo Maffione } 352*5c4f8d80SVincenzo Maffione } 353*5c4f8d80SVincenzo Maffione if (p_state == P_MEMID && !*scan) { 354*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid empty mem_id"); 355*5c4f8d80SVincenzo Maffione goto fail; 356*5c4f8d80SVincenzo Maffione } 357*5c4f8d80SVincenzo Maffione if (p_state != P_START && p_state != P_RNGSFXOK && 358*5c4f8d80SVincenzo Maffione p_state != P_FLAGSOK && p_state != P_MEMID && p_state != P_ONESW) { 359*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unexpected end of request"); 360*5c4f8d80SVincenzo Maffione goto fail; 361*5c4f8d80SVincenzo Maffione } 362*5c4f8d80SVincenzo Maffione out: 363*5c4f8d80SVincenzo Maffione ED("flags: %s %s %s %s %s %s", 364*5c4f8d80SVincenzo Maffione (nr_flags & NR_EXCLUSIVE) ? "EXCLUSIVE" : "", 365*5c4f8d80SVincenzo Maffione (nr_flags & NR_ZCOPY_MON) ? "ZCOPY_MON" : "", 366*5c4f8d80SVincenzo Maffione (nr_flags & NR_MONITOR_TX) ? "MONITOR_TX" : "", 367*5c4f8d80SVincenzo Maffione (nr_flags & NR_MONITOR_RX) ? "MONITOR_RX" : "", 368*5c4f8d80SVincenzo Maffione (nr_flags & NR_RX_RINGS_ONLY) ? "RX_RINGS_ONLY" : "", 369*5c4f8d80SVincenzo Maffione (nr_flags & NR_TX_RINGS_ONLY) ? "TX_RINGS_ONLY" : ""); 370*5c4f8d80SVincenzo Maffione r->nr_mode = nr_mode; 371*5c4f8d80SVincenzo Maffione r->nr_ringid = nr_ringid; 372*5c4f8d80SVincenzo Maffione r->nr_flags = nr_flags; 373*5c4f8d80SVincenzo Maffione r->nr_mem_id = nr_mem_id; 374*5c4f8d80SVincenzo Maffione *pifname = scan; 375*5c4f8d80SVincenzo Maffione return 0; 376*5c4f8d80SVincenzo Maffione 377*5c4f8d80SVincenzo Maffione fail: 378*5c4f8d80SVincenzo Maffione if (!errno) 379*5c4f8d80SVincenzo Maffione errno = EINVAL; 380*5c4f8d80SVincenzo Maffione return -1; 381*5c4f8d80SVincenzo Maffione } 382*5c4f8d80SVincenzo Maffione 383*5c4f8d80SVincenzo Maffione 384*5c4f8d80SVincenzo Maffione static int 385*5c4f8d80SVincenzo Maffione nmreq_option_parsekeys(const char *prefix, char *body, struct nmreq_opt_parser *p, 386*5c4f8d80SVincenzo Maffione struct nmreq_parse_ctx *pctx) 387*5c4f8d80SVincenzo Maffione { 388*5c4f8d80SVincenzo Maffione char *scan; 389*5c4f8d80SVincenzo Maffione char delim1; 390*5c4f8d80SVincenzo Maffione struct nmreq_opt_key *k; 391*5c4f8d80SVincenzo Maffione 392*5c4f8d80SVincenzo Maffione scan = body; 393*5c4f8d80SVincenzo Maffione delim1 = *scan; 394*5c4f8d80SVincenzo Maffione while (delim1 != '\0') { 395*5c4f8d80SVincenzo Maffione char *key, *value; 396*5c4f8d80SVincenzo Maffione char delim; 397*5c4f8d80SVincenzo Maffione size_t vlen; 398*5c4f8d80SVincenzo Maffione 399*5c4f8d80SVincenzo Maffione key = scan; 400*5c4f8d80SVincenzo Maffione for ( scan++; *scan != '\0' && *scan != '=' && *scan != ','; scan++) { 401*5c4f8d80SVincenzo Maffione if (*scan == '-') 402*5c4f8d80SVincenzo Maffione *scan = '_'; 403*5c4f8d80SVincenzo Maffione } 404*5c4f8d80SVincenzo Maffione delim = *scan; 405*5c4f8d80SVincenzo Maffione *scan = '\0'; 406*5c4f8d80SVincenzo Maffione scan++; 407*5c4f8d80SVincenzo Maffione for (k = p->keys; (k - p->keys) < NMREQ_OPT_MAXKEYS && k->key != NULL; 408*5c4f8d80SVincenzo Maffione k++) { 409*5c4f8d80SVincenzo Maffione if (!strcmp(k->key, key)) 410*5c4f8d80SVincenzo Maffione goto found; 411*5c4f8d80SVincenzo Maffione 412*5c4f8d80SVincenzo Maffione } 413*5c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "unknown key: '%s'", key); 414*5c4f8d80SVincenzo Maffione errno = EINVAL; 415*5c4f8d80SVincenzo Maffione return -1; 416*5c4f8d80SVincenzo Maffione found: 417*5c4f8d80SVincenzo Maffione if (pctx->keys[k->id] != NULL) { 418*5c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "option '%s': duplicate key '%s', already set to '%s'", 419*5c4f8d80SVincenzo Maffione prefix, key, pctx->keys[k->id]); 420*5c4f8d80SVincenzo Maffione errno = EINVAL; 421*5c4f8d80SVincenzo Maffione return -1; 422*5c4f8d80SVincenzo Maffione } 423*5c4f8d80SVincenzo Maffione value = scan; 424*5c4f8d80SVincenzo Maffione for ( ; *scan != '\0' && *scan != ','; scan++) 425*5c4f8d80SVincenzo Maffione ; 426*5c4f8d80SVincenzo Maffione delim1 = *scan; 427*5c4f8d80SVincenzo Maffione *scan = '\0'; 428*5c4f8d80SVincenzo Maffione vlen = scan - value; 429*5c4f8d80SVincenzo Maffione scan++; 430*5c4f8d80SVincenzo Maffione if (delim == '=') { 431*5c4f8d80SVincenzo Maffione pctx->keys[k->id] = (vlen ? value : NULL); 432*5c4f8d80SVincenzo Maffione } else { 433*5c4f8d80SVincenzo Maffione if (!(k->flags & NMREQ_OPTK_ALLOWEMPTY)) { 434*5c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "option '%s': missing '=value' for key '%s'", 435*5c4f8d80SVincenzo Maffione prefix, key); 436*5c4f8d80SVincenzo Maffione errno = EINVAL; 437*5c4f8d80SVincenzo Maffione return -1; 438*5c4f8d80SVincenzo Maffione } 439*5c4f8d80SVincenzo Maffione pctx->keys[k->id] = key; 440*5c4f8d80SVincenzo Maffione } 441*5c4f8d80SVincenzo Maffione } 442*5c4f8d80SVincenzo Maffione /* now check that all no-default keys have been assigned */ 443*5c4f8d80SVincenzo Maffione for (k = p->keys; (k - p->keys) < NMREQ_OPT_MAXKEYS && k->key != NULL; k++) { 444*5c4f8d80SVincenzo Maffione if ((k->flags & NMREQ_OPTK_MUSTSET) && pctx->keys[k->id] == NULL) { 445*5c4f8d80SVincenzo Maffione nmctx_ferror(pctx->ctx, "option '%s': mandatory key '%s' not assigned", 446*5c4f8d80SVincenzo Maffione prefix, k->key); 447*5c4f8d80SVincenzo Maffione errno = EINVAL; 448*5c4f8d80SVincenzo Maffione return -1; 449*5c4f8d80SVincenzo Maffione } 450*5c4f8d80SVincenzo Maffione } 451*5c4f8d80SVincenzo Maffione return 0; 452*5c4f8d80SVincenzo Maffione } 453*5c4f8d80SVincenzo Maffione 454*5c4f8d80SVincenzo Maffione 455*5c4f8d80SVincenzo Maffione static int 456*5c4f8d80SVincenzo Maffione nmreq_option_decode1(char *opt, struct nmreq_opt_parser *parsers, 457*5c4f8d80SVincenzo Maffione void *token, struct nmctx *ctx) 458*5c4f8d80SVincenzo Maffione { 459*5c4f8d80SVincenzo Maffione struct nmreq_opt_parser *p; 460*5c4f8d80SVincenzo Maffione const char *prefix; 461*5c4f8d80SVincenzo Maffione char *scan; 462*5c4f8d80SVincenzo Maffione char delim; 463*5c4f8d80SVincenzo Maffione struct nmreq_parse_ctx pctx; 464*5c4f8d80SVincenzo Maffione int i; 465*5c4f8d80SVincenzo Maffione 466*5c4f8d80SVincenzo Maffione prefix = opt; 467*5c4f8d80SVincenzo Maffione /* find the delimiter */ 468*5c4f8d80SVincenzo Maffione for (scan = opt; *scan != '\0' && *scan != ':' && *scan != '='; scan++) 469*5c4f8d80SVincenzo Maffione ; 470*5c4f8d80SVincenzo Maffione delim = *scan; 471*5c4f8d80SVincenzo Maffione *scan = '\0'; 472*5c4f8d80SVincenzo Maffione scan++; 473*5c4f8d80SVincenzo Maffione /* find the prefix */ 474*5c4f8d80SVincenzo Maffione for (p = parsers; p != NULL; p = p->next) { 475*5c4f8d80SVincenzo Maffione if (!strcmp(prefix, p->prefix)) 476*5c4f8d80SVincenzo Maffione break; 477*5c4f8d80SVincenzo Maffione } 478*5c4f8d80SVincenzo Maffione if (p == NULL) { 479*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "unknown option: '%s'", prefix); 480*5c4f8d80SVincenzo Maffione errno = EINVAL; 481*5c4f8d80SVincenzo Maffione return -1; 482*5c4f8d80SVincenzo Maffione } 483*5c4f8d80SVincenzo Maffione if (p->flags & NMREQ_OPTF_DISABLED) { 484*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "option '%s' is not supported", prefix); 485*5c4f8d80SVincenzo Maffione errno = EOPNOTSUPP; 486*5c4f8d80SVincenzo Maffione return -1; 487*5c4f8d80SVincenzo Maffione } 488*5c4f8d80SVincenzo Maffione /* prepare the parse context */ 489*5c4f8d80SVincenzo Maffione pctx.ctx = ctx; 490*5c4f8d80SVincenzo Maffione pctx.token = token; 491*5c4f8d80SVincenzo Maffione for (i = 0; i < NMREQ_OPT_MAXKEYS; i++) 492*5c4f8d80SVincenzo Maffione pctx.keys[i] = NULL; 493*5c4f8d80SVincenzo Maffione switch (delim) { 494*5c4f8d80SVincenzo Maffione case '\0': 495*5c4f8d80SVincenzo Maffione /* no body */ 496*5c4f8d80SVincenzo Maffione if (!(p->flags & NMREQ_OPTF_ALLOWEMPTY)) { 497*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "syntax error: missing body after '%s'", 498*5c4f8d80SVincenzo Maffione prefix); 499*5c4f8d80SVincenzo Maffione errno = EINVAL; 500*5c4f8d80SVincenzo Maffione return -1; 501*5c4f8d80SVincenzo Maffione } 502*5c4f8d80SVincenzo Maffione break; 503*5c4f8d80SVincenzo Maffione case '=': /* the body goes to the default option key, if any */ 504*5c4f8d80SVincenzo Maffione if (p->default_key < 0 || p->default_key >= NMREQ_OPT_MAXKEYS) { 505*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "syntax error: '=' not valid after '%s'", 506*5c4f8d80SVincenzo Maffione prefix); 507*5c4f8d80SVincenzo Maffione errno = EINVAL; 508*5c4f8d80SVincenzo Maffione return -1; 509*5c4f8d80SVincenzo Maffione } 510*5c4f8d80SVincenzo Maffione if (*scan == '\0') { 511*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "missing value for option '%s'", prefix); 512*5c4f8d80SVincenzo Maffione errno = EINVAL; 513*5c4f8d80SVincenzo Maffione return -1; 514*5c4f8d80SVincenzo Maffione } 515*5c4f8d80SVincenzo Maffione pctx.keys[p->default_key] = scan; 516*5c4f8d80SVincenzo Maffione break; 517*5c4f8d80SVincenzo Maffione case ':': /* parse 'key=value' strings */ 518*5c4f8d80SVincenzo Maffione if (nmreq_option_parsekeys(prefix, scan, p, &pctx) < 0) 519*5c4f8d80SVincenzo Maffione return -1; 520*5c4f8d80SVincenzo Maffione break; 521*5c4f8d80SVincenzo Maffione } 522*5c4f8d80SVincenzo Maffione return p->parse(&pctx); 523*5c4f8d80SVincenzo Maffione } 524*5c4f8d80SVincenzo Maffione 525*5c4f8d80SVincenzo Maffione int 526*5c4f8d80SVincenzo Maffione nmreq_options_decode(const char *opt, struct nmreq_opt_parser parsers[], 527*5c4f8d80SVincenzo Maffione void *token, struct nmctx *ctx) 528*5c4f8d80SVincenzo Maffione { 529*5c4f8d80SVincenzo Maffione const char *scan, *opt1; 530*5c4f8d80SVincenzo Maffione char *w; 531*5c4f8d80SVincenzo Maffione size_t len; 532*5c4f8d80SVincenzo Maffione int ret; 533*5c4f8d80SVincenzo Maffione 534*5c4f8d80SVincenzo Maffione if (*opt == '\0') 535*5c4f8d80SVincenzo Maffione return 0; /* empty list, OK */ 536*5c4f8d80SVincenzo Maffione 537*5c4f8d80SVincenzo Maffione if (*opt != '@') { 538*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "option list does not start with '@'"); 539*5c4f8d80SVincenzo Maffione errno = EINVAL; 540*5c4f8d80SVincenzo Maffione return -1; 541*5c4f8d80SVincenzo Maffione } 542*5c4f8d80SVincenzo Maffione 543*5c4f8d80SVincenzo Maffione scan = opt; 544*5c4f8d80SVincenzo Maffione do { 545*5c4f8d80SVincenzo Maffione scan++; /* skip the plus */ 546*5c4f8d80SVincenzo Maffione opt1 = scan; /* start of option */ 547*5c4f8d80SVincenzo Maffione /* find the end of the option */ 548*5c4f8d80SVincenzo Maffione for ( ; *scan != '\0' && *scan != '@'; scan++) 549*5c4f8d80SVincenzo Maffione ; 550*5c4f8d80SVincenzo Maffione len = scan - opt1; 551*5c4f8d80SVincenzo Maffione if (len == 0) { 552*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "invalid empty option"); 553*5c4f8d80SVincenzo Maffione errno = EINVAL; 554*5c4f8d80SVincenzo Maffione return -1; 555*5c4f8d80SVincenzo Maffione } 556*5c4f8d80SVincenzo Maffione w = nmctx_malloc(ctx, len + 1); 557*5c4f8d80SVincenzo Maffione if (w == NULL) { 558*5c4f8d80SVincenzo Maffione nmctx_ferror(ctx, "out of memory"); 559*5c4f8d80SVincenzo Maffione errno = ENOMEM; 560*5c4f8d80SVincenzo Maffione return -1; 561*5c4f8d80SVincenzo Maffione } 562*5c4f8d80SVincenzo Maffione memcpy(w, opt1, len); 563*5c4f8d80SVincenzo Maffione w[len] = '\0'; 564*5c4f8d80SVincenzo Maffione ret = nmreq_option_decode1(w, parsers, token, ctx); 565*5c4f8d80SVincenzo Maffione nmctx_free(ctx, w); 566*5c4f8d80SVincenzo Maffione if (ret < 0) 567*5c4f8d80SVincenzo Maffione return -1; 568*5c4f8d80SVincenzo Maffione } while (*scan != '\0'); 569*5c4f8d80SVincenzo Maffione 570*5c4f8d80SVincenzo Maffione return 0; 571*5c4f8d80SVincenzo Maffione } 572*5c4f8d80SVincenzo Maffione 573*5c4f8d80SVincenzo Maffione struct nmreq_option * 574*5c4f8d80SVincenzo Maffione nmreq_find_option(struct nmreq_header *h, uint32_t t) 575*5c4f8d80SVincenzo Maffione { 576*5c4f8d80SVincenzo Maffione struct nmreq_option *o; 577*5c4f8d80SVincenzo Maffione 578*5c4f8d80SVincenzo Maffione for (o = (struct nmreq_option *)h->nr_options; o != NULL; 579*5c4f8d80SVincenzo Maffione o = (struct nmreq_option *)o->nro_next) { 580*5c4f8d80SVincenzo Maffione if (o->nro_reqtype == t) 581*5c4f8d80SVincenzo Maffione break; 582*5c4f8d80SVincenzo Maffione } 583*5c4f8d80SVincenzo Maffione return o; 584*5c4f8d80SVincenzo Maffione } 585*5c4f8d80SVincenzo Maffione 586*5c4f8d80SVincenzo Maffione void 587*5c4f8d80SVincenzo Maffione nmreq_remove_option(struct nmreq_header *h, struct nmreq_option *o) 588*5c4f8d80SVincenzo Maffione { 589*5c4f8d80SVincenzo Maffione struct nmreq_option **nmo; 590*5c4f8d80SVincenzo Maffione 591*5c4f8d80SVincenzo Maffione for (nmo = (struct nmreq_option **)&h->nr_options; *nmo != NULL; 592*5c4f8d80SVincenzo Maffione nmo = (struct nmreq_option **)&(*nmo)->nro_next) { 593*5c4f8d80SVincenzo Maffione if (*nmo == o) { 594*5c4f8d80SVincenzo Maffione *((uint64_t *)(*nmo)) = o->nro_next; 595*5c4f8d80SVincenzo Maffione o->nro_next = (uint64_t)(uintptr_t)NULL; 596*5c4f8d80SVincenzo Maffione break; 597*5c4f8d80SVincenzo Maffione } 598*5c4f8d80SVincenzo Maffione } 599*5c4f8d80SVincenzo Maffione } 600*5c4f8d80SVincenzo Maffione 601*5c4f8d80SVincenzo Maffione void 602*5c4f8d80SVincenzo Maffione nmreq_free_options(struct nmreq_header *h) 603*5c4f8d80SVincenzo Maffione { 604*5c4f8d80SVincenzo Maffione struct nmreq_option *o, *next; 605*5c4f8d80SVincenzo Maffione 606*5c4f8d80SVincenzo Maffione for (o = (struct nmreq_option *)h->nr_options; o != NULL; o = next) { 607*5c4f8d80SVincenzo Maffione next = (struct nmreq_option *)o->nro_next; 608*5c4f8d80SVincenzo Maffione free(o); 609*5c4f8d80SVincenzo Maffione } 610*5c4f8d80SVincenzo Maffione } 611*5c4f8d80SVincenzo Maffione 612*5c4f8d80SVincenzo Maffione const char* 613*5c4f8d80SVincenzo Maffione nmreq_option_name(uint32_t nro_reqtype) 614*5c4f8d80SVincenzo Maffione { 615*5c4f8d80SVincenzo Maffione switch (nro_reqtype) { 616*5c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_EXTMEM: 617*5c4f8d80SVincenzo Maffione return "extmem"; 618*5c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_SYNC_KLOOP_EVENTFDS: 619*5c4f8d80SVincenzo Maffione return "sync-kloop-eventfds"; 620*5c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_CSB: 621*5c4f8d80SVincenzo Maffione return "csb"; 622*5c4f8d80SVincenzo Maffione case NETMAP_REQ_OPT_SYNC_KLOOP_MODE: 623*5c4f8d80SVincenzo Maffione return "sync-kloop-mode"; 624*5c4f8d80SVincenzo Maffione default: 625*5c4f8d80SVincenzo Maffione return "unknown"; 626*5c4f8d80SVincenzo Maffione } 627*5c4f8d80SVincenzo Maffione } 628*5c4f8d80SVincenzo Maffione 629*5c4f8d80SVincenzo Maffione #if 0 630*5c4f8d80SVincenzo Maffione #include <inttypes.h> 631*5c4f8d80SVincenzo Maffione static void 632*5c4f8d80SVincenzo Maffione nmreq_dump(struct nmport_d *d) 633*5c4f8d80SVincenzo Maffione { 634*5c4f8d80SVincenzo Maffione printf("header:\n"); 635*5c4f8d80SVincenzo Maffione printf(" nr_version: %"PRIu16"\n", d->hdr.nr_version); 636*5c4f8d80SVincenzo Maffione printf(" nr_reqtype: %"PRIu16"\n", d->hdr.nr_reqtype); 637*5c4f8d80SVincenzo Maffione printf(" nr_reserved: %"PRIu32"\n", d->hdr.nr_reserved); 638*5c4f8d80SVincenzo Maffione printf(" nr_name: %s\n", d->hdr.nr_name); 639*5c4f8d80SVincenzo Maffione printf(" nr_options: %lx\n", (unsigned long)d->hdr.nr_options); 640*5c4f8d80SVincenzo Maffione printf(" nr_body: %lx\n", (unsigned long)d->hdr.nr_body); 641*5c4f8d80SVincenzo Maffione printf("\n"); 642*5c4f8d80SVincenzo Maffione printf("register (%p):\n", (void *)d->hdr.nr_body); 643*5c4f8d80SVincenzo Maffione printf(" nr_mem_id: %"PRIu16"\n", d->reg.nr_mem_id); 644*5c4f8d80SVincenzo Maffione printf(" nr_ringid: %"PRIu16"\n", d->reg.nr_ringid); 645*5c4f8d80SVincenzo Maffione printf(" nr_mode: %lx\n", (unsigned long)d->reg.nr_mode); 646*5c4f8d80SVincenzo Maffione printf(" nr_flags: %lx\n", (unsigned long)d->reg.nr_flags); 647*5c4f8d80SVincenzo Maffione printf("\n"); 648*5c4f8d80SVincenzo Maffione if (d->hdr.nr_options) { 649*5c4f8d80SVincenzo Maffione struct nmreq_opt_extmem *e = (struct nmreq_opt_extmem *)d->hdr.nr_options; 650*5c4f8d80SVincenzo Maffione printf("opt_extmem (%p):\n", e); 651*5c4f8d80SVincenzo Maffione printf(" nro_opt.nro_next: %lx\n", (unsigned long)e->nro_opt.nro_next); 652*5c4f8d80SVincenzo Maffione printf(" nro_opt.nro_reqtype: %"PRIu32"\n", e->nro_opt.nro_reqtype); 653*5c4f8d80SVincenzo Maffione printf(" nro_usrptr: %lx\n", (unsigned long)e->nro_usrptr); 654*5c4f8d80SVincenzo Maffione printf(" nro_info.nr_memsize %"PRIu64"\n", e->nro_info.nr_memsize); 655*5c4f8d80SVincenzo Maffione } 656*5c4f8d80SVincenzo Maffione printf("\n"); 657*5c4f8d80SVincenzo Maffione printf("mem (%p):\n", d->mem); 658*5c4f8d80SVincenzo Maffione printf(" refcount: %d\n", d->mem->refcount); 659*5c4f8d80SVincenzo Maffione printf(" mem: %p\n", d->mem->mem); 660*5c4f8d80SVincenzo Maffione printf(" size: %zu\n", d->mem->size); 661*5c4f8d80SVincenzo Maffione printf("\n"); 662*5c4f8d80SVincenzo Maffione printf("rings:\n"); 663*5c4f8d80SVincenzo Maffione printf(" tx: [%d, %d]\n", d->first_tx_ring, d->last_tx_ring); 664*5c4f8d80SVincenzo Maffione printf(" rx: [%d, %d]\n", d->first_rx_ring, d->last_rx_ring); 665*5c4f8d80SVincenzo Maffione } 666*5c4f8d80SVincenzo Maffione int 667*5c4f8d80SVincenzo Maffione main(int argc, char *argv[]) 668*5c4f8d80SVincenzo Maffione { 669*5c4f8d80SVincenzo Maffione struct nmport_d *d; 670*5c4f8d80SVincenzo Maffione 671*5c4f8d80SVincenzo Maffione if (argc < 2) { 672*5c4f8d80SVincenzo Maffione fprintf(stderr, "usage: %s netmap-expr\n", argv[0]); 673*5c4f8d80SVincenzo Maffione return 1; 674*5c4f8d80SVincenzo Maffione } 675*5c4f8d80SVincenzo Maffione 676*5c4f8d80SVincenzo Maffione d = nmport_open(argv[1]); 677*5c4f8d80SVincenzo Maffione if (d != NULL) { 678*5c4f8d80SVincenzo Maffione nmreq_dump(d); 679*5c4f8d80SVincenzo Maffione nmport_close(d); 680*5c4f8d80SVincenzo Maffione } 681*5c4f8d80SVincenzo Maffione 682*5c4f8d80SVincenzo Maffione return 0; 683*5c4f8d80SVincenzo Maffione } 684*5c4f8d80SVincenzo Maffione #endif 685