netmap_user.h (251138) | netmap_user.h (259412) |
---|---|
1/* 2 * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. | 1/* 2 * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. |
3 * | 3 * Copyright (C) 2013 Universita` di Pisa 4 * |
4 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are 6 * met: 7 * | 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * |
8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. | 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. |
10 * | |
11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the | 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 14 * distribution. 15 * 16 * 3. Neither the name of the authors nor the names of their contributors 17 * may be used to endorse or promote products derived from this 18 * software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI AND CONTRIBUTORS "AS IS" AND | 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTEO LANDI OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. | 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 25 * SUCH DAMAGE. |
31 */ 32 33/* | 26 */ 27 28/* |
34 * $FreeBSD: head/sys/net/netmap_user.h 251138 2013-05-30 13:41:19Z luigi $ | 29 * $FreeBSD: head/sys/net/netmap_user.h 259412 2013-12-15 08:37:24Z luigi $ |
35 * 36 * This header contains the macros used to manipulate netmap structures 37 * and packets in userspace. See netmap(4) for more information. 38 * 39 * The address of the struct netmap_if, say nifp, is computed from the 40 * value returned from ioctl(.., NIOCREG, ...) and the mmap region: 41 * ioctl(fd, NIOCREG, &req); 42 * mem = mmap(0, ... ); --- 8 unchanged lines hidden (view full) --- 51 * ring->slot[i] gives us the i-th slot (we can access 52 * directly plen, flags, bufindex) 53 * 54 * char *buf = NETMAP_BUF(ring, x) returns a pointer to 55 * the buffer numbered x 56 * 57 * Since rings are circular, we have macros to compute the next index 58 * i = NETMAP_RING_NEXT(ring, i); | 30 * 31 * This header contains the macros used to manipulate netmap structures 32 * and packets in userspace. See netmap(4) for more information. 33 * 34 * The address of the struct netmap_if, say nifp, is computed from the 35 * value returned from ioctl(.., NIOCREG, ...) and the mmap region: 36 * ioctl(fd, NIOCREG, &req); 37 * mem = mmap(0, ... ); --- 8 unchanged lines hidden (view full) --- 46 * ring->slot[i] gives us the i-th slot (we can access 47 * directly plen, flags, bufindex) 48 * 49 * char *buf = NETMAP_BUF(ring, x) returns a pointer to 50 * the buffer numbered x 51 * 52 * Since rings are circular, we have macros to compute the next index 53 * i = NETMAP_RING_NEXT(ring, i); |
54 * 55 * To ease porting apps from pcap to netmap we supply a few fuctions 56 * that can be called to open, close and read from netmap in a way 57 * similar to libpcap. 58 * 59 * In order to use these, include #define NETMAP_WITH_LIBS 60 * in the source file that invokes these functions. |
|
59 */ 60 61#ifndef _NET_NETMAP_USER_H_ 62#define _NET_NETMAP_USER_H_ 63 | 61 */ 62 63#ifndef _NET_NETMAP_USER_H_ 64#define _NET_NETMAP_USER_H_ 65 |
66#include <stdint.h> 67#include <net/if.h> /* IFNAMSIZ */ 68#include <net/netmap.h> 69 |
|
64#define _NETMAP_OFFSET(type, ptr, offset) \ 65 ((type)(void *)((char *)(ptr) + (offset))) 66 67#define NETMAP_IF(b, o) _NETMAP_OFFSET(struct netmap_if *, b, o) 68 69#define NETMAP_TXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring *, \ 70 nifp, (nifp)->ring_ofs[index] ) 71 72#define NETMAP_RXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring *, \ 73 nifp, (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] ) 74 75#define NETMAP_BUF(ring, index) \ 76 ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size)) 77 78#define NETMAP_BUF_IDX(ring, buf) \ 79 ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \ | 70#define _NETMAP_OFFSET(type, ptr, offset) \ 71 ((type)(void *)((char *)(ptr) + (offset))) 72 73#define NETMAP_IF(b, o) _NETMAP_OFFSET(struct netmap_if *, b, o) 74 75#define NETMAP_TXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring *, \ 76 nifp, (nifp)->ring_ofs[index] ) 77 78#define NETMAP_RXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring *, \ 79 nifp, (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] ) 80 81#define NETMAP_BUF(ring, index) \ 82 ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size)) 83 84#define NETMAP_BUF_IDX(ring, buf) \ 85 ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \ |
80 (ring)->nr_buf_size ) | 86 (ring)->nr_buf_size ) |
81 82#define NETMAP_RING_NEXT(r, i) \ 83 ((i)+1 == (r)->num_slots ? 0 : (i) + 1 ) 84 85#define NETMAP_RING_FIRST_RESERVED(r) \ 86 ( (r)->cur < (r)->reserved ? \ 87 (r)->cur + (r)->num_slots - (r)->reserved : \ 88 (r)->cur - (r)->reserved ) 89 90/* 91 * Return 1 if the given tx ring is empty. 92 */ 93#define NETMAP_TX_RING_EMPTY(r) ((r)->avail >= (r)->num_slots - 1) 94 | 87 88#define NETMAP_RING_NEXT(r, i) \ 89 ((i)+1 == (r)->num_slots ? 0 : (i) + 1 ) 90 91#define NETMAP_RING_FIRST_RESERVED(r) \ 92 ( (r)->cur < (r)->reserved ? \ 93 (r)->cur + (r)->num_slots - (r)->reserved : \ 94 (r)->cur - (r)->reserved ) 95 96/* 97 * Return 1 if the given tx ring is empty. 98 */ 99#define NETMAP_TX_RING_EMPTY(r) ((r)->avail >= (r)->num_slots - 1) 100 |
101#ifdef NETMAP_WITH_LIBS 102/* 103 * Support for simple I/O libraries. 104 * Include other system headers required for compiling this. 105 */ 106 107#ifndef HAVE_NETMAP_WITH_LIBS 108#define HAVE_NETMAP_WITH_LIBS 109 110#include <sys/time.h> 111#include <sys/mman.h> 112#include <string.h> /* memset */ 113#include <sys/ioctl.h> 114#include <sys/errno.h> /* EINVAL */ 115#include <fcntl.h> /* O_RDWR */ 116#include <malloc.h> 117 118struct nm_hdr_t { /* same as pcap_pkthdr */ 119 struct timeval ts; 120 uint32_t caplen; 121 uint32_t len; 122}; 123 124struct nm_desc_t { 125 struct nm_desc_t *self; 126 int fd; 127 void *mem; 128 int memsize; 129 struct netmap_if *nifp; 130 uint16_t first_ring, last_ring, cur_ring; 131 struct nmreq req; 132 struct nm_hdr_t hdr; 133}; 134 135/* 136 * when the descriptor is open correctly, d->self == d 137 */ 138#define P2NMD(p) ((struct nm_desc_t *)(p)) 139#define IS_NETMAP_DESC(d) (P2NMD(d)->self == P2NMD(d)) 140#define NETMAP_FD(d) (P2NMD(d)->fd) 141 142/* 143 * The callback, invoked on each received packet. Same as libpcap 144 */ 145typedef void (*nm_cb_t)(u_char *, const struct nm_hdr_t *, const u_char *d); 146 147/* 148 * The open routine accepts an ifname (netmap:foo or vale:foo) and 149 * optionally a second (string) argument indicating the ring number 150 * to open. If successful, t opens the fd and maps the memory. 151 */ 152static struct nm_desc_t *nm_open(const char *ifname, 153 const char *ring_no, int flags, int ring_flags); 154 155/* 156 * nm_dispatch() is the same as pcap_dispatch() 157 * nm_next() is the same as pcap_next() 158 */ 159static int nm_dispatch(struct nm_desc_t *, int, nm_cb_t, u_char *); 160static u_char *nm_next(struct nm_desc_t *, struct nm_hdr_t *); 161 162/* 163 * unmap memory, close file descriptor and free the descriptor. 164 */ 165static int nm_close(struct nm_desc_t *); 166 167 168/* 169 * Try to open, return descriptor if successful, NULL otherwise. 170 * An invalid netmap name will return errno = 0; 171 */ 172static struct nm_desc_t * 173nm_open(const char *ifname, const char *ring_name, int flags, int ring_flags) 174{ 175 struct nm_desc_t *d; 176 u_int n; 177 178 if (strncmp(ifname, "netmap:", 7) && strncmp(ifname, "vale", 4)) { 179 errno = 0; /* name not recognised */ 180 return NULL; 181 } 182 if (ifname[0] == 'n') 183 ifname += 7; 184 d = (struct nm_desc_t *)calloc(1, sizeof(*d)); 185 if (d == NULL) { 186 errno = ENOMEM; 187 return NULL; 188 } 189 d->self = d; /* set this early so nm_close() works */ 190 d->fd = open("/dev/netmap", O_RDWR); 191 if (d->fd < 0) 192 goto fail; 193 194 if (flags & NETMAP_SW_RING) { 195 d->req.nr_ringid = NETMAP_SW_RING; 196 } else { 197 u_int r; 198 if (flags & NETMAP_HW_RING) /* interpret ring as int */ 199 r = (uintptr_t)ring_name; 200 else /* interpret ring as numeric string */ 201 r = ring_name ? atoi(ring_name) : ~0; 202 r = (r < NETMAP_RING_MASK) ? (r | NETMAP_HW_RING) : 0; 203 d->req.nr_ringid = r; /* set the ring */ 204 } 205 d->req.nr_ringid |= (flags & ~NETMAP_RING_MASK); 206 d->req.nr_version = NETMAP_API; 207 strncpy(d->req.nr_name, ifname, sizeof(d->req.nr_name)); 208 if (ioctl(d->fd, NIOCREGIF, &d->req)) 209 goto fail; 210 211 d->memsize = d->req.nr_memsize; 212 d->mem = mmap(0, d->memsize, PROT_WRITE | PROT_READ, MAP_SHARED, 213 d->fd, 0); 214 if (d->mem == NULL) 215 goto fail; 216 d->nifp = NETMAP_IF(d->mem, d->req.nr_offset); 217 if (d->req.nr_ringid & NETMAP_SW_RING) { 218 d->first_ring = d->last_ring = d->req.nr_rx_rings; 219 } else if (d->req.nr_ringid & NETMAP_HW_RING) { 220 d->first_ring = d->last_ring = 221 d->req.nr_ringid & NETMAP_RING_MASK; 222 } else { 223 d->first_ring = 0; 224 d->last_ring = d->req.nr_rx_rings - 1; 225 } 226 d->cur_ring = d->first_ring; 227 for (n = d->first_ring; n <= d->last_ring; n++) { 228 struct netmap_ring *ring = NETMAP_RXRING(d->nifp, n); 229 ring->flags |= ring_flags; 230 } 231 return d; 232 233fail: 234 nm_close(d); 235 errno = EINVAL; 236 return NULL; 237} 238 239 240static int 241nm_close(struct nm_desc_t *d) 242{ 243 if (d == NULL || d->self != d) 244 return EINVAL; 245 if (d->mem) 246 munmap(d->mem, d->memsize); 247 if (d->fd != -1) 248 close(d->fd); 249 bzero(d, sizeof(*d)); 250 free(d); 251 return 0; 252} 253 254 255/* 256 * Same prototype as pcap_dispatch(), only need to cast. 257 */ 258inline /* not really, but disable unused warnings */ 259static int 260nm_dispatch(struct nm_desc_t *d, int cnt, nm_cb_t cb, u_char *arg) 261{ 262 int n = d->last_ring - d->first_ring + 1; 263 int c, got = 0, ri = d->cur_ring; 264 265 if (cnt == 0) 266 cnt = -1; 267 /* cnt == -1 means infinite, but rings have a finite amount 268 * of buffers and the int is large enough that we never wrap, 269 * so we can omit checking for -1 270 */ 271 for (c=0; c < n && cnt != got; c++) { 272 /* compute current ring to use */ 273 struct netmap_ring *ring; 274 275 ri = d->cur_ring + c; 276 if (ri > d->last_ring) 277 ri = d->first_ring; 278 ring = NETMAP_RXRING(d->nifp, ri); 279 for ( ; ring->avail > 0 && cnt != got; got++) { 280 u_int i = ring->cur; 281 u_int idx = ring->slot[i].buf_idx; 282 u_char *buf = (u_char *)NETMAP_BUF(ring, idx); 283 // XXX should check valid buf 284 // prefetch(buf); 285 d->hdr.len = d->hdr.caplen = ring->slot[i].len; 286 d->hdr.ts = ring->ts; 287 cb(arg, &d->hdr, buf); 288 ring->cur = NETMAP_RING_NEXT(ring, i); 289 ring->avail--; 290 } 291 } 292 d->cur_ring = ri; 293 return got; 294} 295 296inline /* not really, but disable unused warnings */ 297static u_char * 298nm_next(struct nm_desc_t *d, struct nm_hdr_t *hdr) 299{ 300 int ri = d->cur_ring; 301 302 do { 303 /* compute current ring to use */ 304 struct netmap_ring *ring = NETMAP_RXRING(d->nifp, ri); 305 if (ring->avail > 0) { 306 u_int i = ring->cur; 307 u_int idx = ring->slot[i].buf_idx; 308 u_char *buf = (u_char *)NETMAP_BUF(ring, idx); 309 // XXX should check valid buf 310 // prefetch(buf); 311 hdr->ts = ring->ts; 312 hdr->len = hdr->caplen = ring->slot[i].len; 313 ring->cur = NETMAP_RING_NEXT(ring, i); 314 ring->avail--; 315 d->cur_ring = ri; 316 return buf; 317 } 318 ri++; 319 if (ri > d->last_ring) 320 ri = d->first_ring; 321 } while (ri != d->cur_ring); 322 return NULL; /* nothing found */ 323} 324 325#endif /* !HAVE_NETMAP_WITH_LIBS */ 326 327#endif /* NETMAP_WITH_LIBS */ 328 |
|
95#endif /* _NET_NETMAP_USER_H_ */ | 329#endif /* _NET_NETMAP_USER_H_ */ |