Deleted Added
full compact
netmap_user.h (259412) netmap_user.h (260368)
1/*
1/*
2 * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved.
3 * Copyright (C) 2013 Universita` di Pisa
2 * Copyright (C) 2011-2014 Universita` di Pisa. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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

--- 9 unchanged lines hidden (view full) ---

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.
26 */
27
28/*
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 9 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
29 * $FreeBSD: head/sys/net/netmap_user.h 259412 2013-12-15 08:37:24Z luigi $
28 * $FreeBSD: head/sys/net/netmap_user.h 260368 2014-01-06 12:53:15Z luigi $
30 *
29 *
31 * This header contains the macros used to manipulate netmap structures
32 * and packets in userspace. See netmap(4) for more information.
30 * Functions and macros to manipulate netmap structures and packets
31 * 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, ... );
38 * nifp = NETMAP_IF(mem, req.nr_nifp);
39 * (so simple, we could just do it manually)
40 *
41 * From there:
42 * struct netmap_ring *NETMAP_TXRING(nifp, index)
43 * struct netmap_ring *NETMAP_RXRING(nifp, index)
44 * we can access ring->nr_cur, ring->nr_avail, ring->nr_flags
45 *
46 * ring->slot[i] gives us the i-th slot (we can access
32 *
33 * The address of the struct netmap_if, say nifp, is computed from the
34 * value returned from ioctl(.., NIOCREG, ...) and the mmap region:
35 * ioctl(fd, NIOCREG, &req);
36 * mem = mmap(0, ... );
37 * nifp = NETMAP_IF(mem, req.nr_nifp);
38 * (so simple, we could just do it manually)
39 *
40 * From there:
41 * struct netmap_ring *NETMAP_TXRING(nifp, index)
42 * struct netmap_ring *NETMAP_RXRING(nifp, index)
43 * we can access ring->nr_cur, ring->nr_avail, ring->nr_flags
44 *
45 * ring->slot[i] gives us the i-th slot (we can access
47 * directly plen, flags, bufindex)
46 * directly len, flags, buf_idx)
48 *
49 * char *buf = NETMAP_BUF(ring, x) returns a pointer to
50 * the buffer numbered x
51 *
47 *
48 * char *buf = NETMAP_BUF(ring, x) returns a pointer to
49 * the buffer numbered x
50 *
52 * Since rings are circular, we have macros to compute the next index
53 * i = NETMAP_RING_NEXT(ring, i);
51 * All ring indexes (head, cur, tail) should always move forward.
52 * To compute the next index in a circular ring you can use
53 * i = nm_ring_next(ring, i);
54 *
55 * To ease porting apps from pcap to netmap we supply a few fuctions
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.
56 * that can be called to open, close, read and write on netmap in a way
57 * similar to libpcap. Note that the read/write function depend on
58 * an ioctl()/select()/poll() being issued to refill rings or push
59 * packets out.
58 *
59 * In order to use these, include #define NETMAP_WITH_LIBS
60 * in the source file that invokes these functions.
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 */
60 *
61 * In order to use these, include #define NETMAP_WITH_LIBS
62 * in the source file that invokes these functions.
63 */
64
65#ifndef _NET_NETMAP_USER_H_
66#define _NET_NETMAP_USER_H_
67
68#include <stdint.h>
69#include <net/if.h> /* IFNAMSIZ */
70
71#ifndef likely
72#define likely(x) __builtin_expect(!!(x), 1)
73#define unlikely(x) __builtin_expect(!!(x), 0)
74#endif /* likely and unlikely */
75
68#include <net/netmap.h>
69
76#include <net/netmap.h>
77
78/* helper macro */
70#define _NETMAP_OFFSET(type, ptr, offset) \
71 ((type)(void *)((char *)(ptr) + (offset)))
72
79#define _NETMAP_OFFSET(type, ptr, offset) \
80 ((type)(void *)((char *)(ptr) + (offset)))
81
73#define NETMAP_IF(b, o) _NETMAP_OFFSET(struct netmap_if *, b, o)
82#define NETMAP_IF(_base, _ofs) _NETMAP_OFFSET(struct netmap_if *, _base, _ofs)
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) ) / \
86 (ring)->nr_buf_size )
87
83
84#define NETMAP_TXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring *, \
85 nifp, (nifp)->ring_ofs[index] )
86
87#define NETMAP_RXRING(nifp, index) _NETMAP_OFFSET(struct netmap_ring *, \
88 nifp, (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] )
89
90#define NETMAP_BUF(ring, index) \
91 ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size))
92
93#define NETMAP_BUF_IDX(ring, buf) \
94 ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \
95 (ring)->nr_buf_size )
96
88#define NETMAP_RING_NEXT(r, i) \
89 ((i)+1 == (r)->num_slots ? 0 : (i) + 1 )
90
97
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 )
98static inline uint32_t
99nm_ring_next(struct netmap_ring *r, uint32_t i)
100{
101 return ( unlikely(i + 1 == r->num_slots) ? 0 : i + 1);
102}
95
103
104
96/*
105/*
97 * Return 1 if the given tx ring is empty.
106 * Return 1 if we have pending transmissions in the tx ring.
107 * When everything is complete ring->cur = ring->tail + 1 (modulo ring size)
98 */
108 */
99#define NETMAP_TX_RING_EMPTY(r) ((r)->avail >= (r)->num_slots - 1)
109static inline int
110nm_tx_pending(struct netmap_ring *r)
111{
112 return nm_ring_next(r, r->tail) != r->cur;
113}
100
114
115
116static inline uint32_t
117nm_ring_space(struct netmap_ring *ring)
118{
119 int ret = ring->tail - ring->cur;
120 if (ret < 0)
121 ret += ring->num_slots;
122 return ret;
123}
124
125
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 */
126#ifdef NETMAP_WITH_LIBS
127/*
128 * Support for simple I/O libraries.
129 * Include other system headers required for compiling this.
130 */
131
132#ifndef HAVE_NETMAP_WITH_LIBS
133#define HAVE_NETMAP_WITH_LIBS
134
135#include <sys/time.h>
136#include <sys/mman.h>
137#include <string.h> /* memset */
138#include <sys/ioctl.h>
139#include <sys/errno.h> /* EINVAL */
140#include <fcntl.h> /* O_RDWR */
116#include <malloc.h>
141#include <unistd.h> /* close() */
142#ifdef __FreeBSD__
143#include <stdlib.h>
144#else
145#include <malloc.h> /* on FreeBSD it is stdlib.h */
146#endif
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 {

--- 9 unchanged lines hidden (view full) ---

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
147
148struct nm_hdr_t { /* same as pcap_pkthdr */
149 struct timeval ts;
150 uint32_t caplen;
151 uint32_t len;
152};
153
154struct nm_desc_t {

--- 9 unchanged lines hidden (view full) ---

164
165/*
166 * when the descriptor is open correctly, d->self == d
167 */
168#define P2NMD(p) ((struct nm_desc_t *)(p))
169#define IS_NETMAP_DESC(d) (P2NMD(d)->self == P2NMD(d))
170#define NETMAP_FD(d) (P2NMD(d)->fd)
171
172
142/*
173/*
174 * this is a slightly optimized copy routine which rounds
175 * to multiple of 64 bytes and is often faster than dealing
176 * with other odd sizes. We assume there is enough room
177 * in the source and destination buffers.
178 *
179 * XXX only for multiples of 64 bytes, non overlapped.
180 */
181static inline void
182pkt_copy(const void *_src, void *_dst, int l)
183{
184 const uint64_t *src = _src;
185 uint64_t *dst = _dst;
186 if (unlikely(l >= 1024)) {
187 memcpy(dst, src, l);
188 return;
189 }
190 for (; likely(l > 0); l-=64) {
191 *dst++ = *src++;
192 *dst++ = *src++;
193 *dst++ = *src++;
194 *dst++ = *src++;
195 *dst++ = *src++;
196 *dst++ = *src++;
197 *dst++ = *src++;
198 *dst++ = *src++;
199 }
200}
201
202
203/*
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/*
204 * The callback, invoked on each received packet. Same as libpcap
205 */
206typedef void (*nm_cb_t)(u_char *, const struct nm_hdr_t *, const u_char *d);
207
208/*
148 * The open routine accepts an ifname (netmap:foo or vale:foo) and
149 * optionally a second (string) argument indicating the ring number
209 *--- the pcap-like API ---
210 *
211 * nm_open() opens a file descriptor, binds to a port and maps memory.
212 *
213 * ifname (netmap:foo or vale:foo) is the port name
214 * flags can be NETMAP_SW_RING or NETMAP_HW_RING etc.
215 * ring_no only used if NETMAP_HW_RING is specified, is interpreted
216 * as a string or integer indicating the ring number
217 * ring_flags is stored in all ring flags (e.g. for transparent mode)
150 * to open. If successful, t opens the fd and maps the memory.
151 */
218 * to open. If successful, t opens the fd and maps the memory.
219 */
220
152static struct nm_desc_t *nm_open(const char *ifname,
153 const char *ring_no, int flags, int ring_flags);
154
155/*
221static struct nm_desc_t *nm_open(const char *ifname,
222 const char *ring_no, int flags, int ring_flags);
223
224/*
156 * nm_dispatch() is the same as pcap_dispatch()
157 * nm_next() is the same as pcap_next()
225 * nm_close() closes and restores the port to its previous state
158 */
226 */
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
227
228static int nm_close(struct nm_desc_t *);
229
162/*
230/*
163 * unmap memory, close file descriptor and free the descriptor.
231 * nm_inject() is the same as pcap_inject()
232 * nm_dispatch() is the same as pcap_dispatch()
233 * nm_nextpkt() is the same as pcap_next()
164 */
234 */
165static int nm_close(struct nm_desc_t *);
166
235
236static int nm_inject(struct nm_desc_t *, const void *, size_t);
237static int nm_dispatch(struct nm_desc_t *, int, nm_cb_t, u_char *);
238static u_char *nm_nextpkt(struct nm_desc_t *, struct nm_hdr_t *);
167
239
240
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;

--- 59 unchanged lines hidden (view full) ---

235 errno = EINVAL;
236 return NULL;
237}
238
239
240static int
241nm_close(struct nm_desc_t *d)
242{
241/*
242 * Try to open, return descriptor if successful, NULL otherwise.
243 * An invalid netmap name will return errno = 0;
244 */
245static struct nm_desc_t *
246nm_open(const char *ifname, const char *ring_name, int flags, int ring_flags)
247{
248 struct nm_desc_t *d;

--- 59 unchanged lines hidden (view full) ---

308 errno = EINVAL;
309 return NULL;
310}
311
312
313static int
314nm_close(struct nm_desc_t *d)
315{
316 /*
317 * ugly trick to avoid unused warnings
318 */
319 static void *__xxzt[] __attribute__ ((unused)) =
320 { nm_open, nm_inject, nm_dispatch, nm_nextpkt } ;
321
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/*
322 if (d == NULL || d->self != d)
323 return EINVAL;
324 if (d->mem)
325 munmap(d->mem, d->memsize);
326 if (d->fd != -1)
327 close(d->fd);
328 bzero(d, sizeof(*d));
329 free(d);
330 return 0;
331}
332
333
334/*
335 * Same prototype as pcap_inject(), only need to cast.
336 */
337static int
338nm_inject(struct nm_desc_t *d, const void *buf, size_t size)
339{
340 u_int c, n = d->last_ring - d->first_ring + 1;
341
342 if (0) fprintf(stderr, "%s rings %d %d %d\n", __FUNCTION__,
343 d->first_ring, d->cur_ring, d->last_ring);
344 for (c = 0; c < n ; c++) {
345 /* compute current ring to use */
346 struct netmap_ring *ring;
347 uint32_t i, idx;
348 uint32_t ri = d->cur_ring + c;
349
350 if (ri > d->last_ring)
351 ri = d->first_ring;
352 ring = NETMAP_TXRING(d->nifp, ri);
353 if (nm_ring_empty(ring)) {
354 if (0) fprintf(stderr, "%s ring %d cur %d tail %d\n",
355 __FUNCTION__,
356 ri, ring->cur, ring->tail);
357 continue;
358 }
359 i = ring->cur;
360 idx = ring->slot[i].buf_idx;
361 ring->slot[i].len = size;
362 pkt_copy(buf, NETMAP_BUF(ring, idx), size);
363 d->cur_ring = ri;
364 ring->head = ring->cur = nm_ring_next(ring, i);
365 return size;
366 }
367 return 0; /* fail */
368}
369
370
371/*
256 * Same prototype as pcap_dispatch(), only need to cast.
257 */
372 * Same prototype as pcap_dispatch(), only need to cast.
373 */
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;

--- 4 unchanged lines hidden (view full) ---

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);
374static int
375nm_dispatch(struct nm_desc_t *d, int cnt, nm_cb_t cb, u_char *arg)
376{
377 int n = d->last_ring - d->first_ring + 1;
378 int c, got = 0, ri = d->cur_ring;
379
380 if (cnt == 0)
381 cnt = -1;

--- 4 unchanged lines hidden (view full) ---

386 for (c=0; c < n && cnt != got; c++) {
387 /* compute current ring to use */
388 struct netmap_ring *ring;
389
390 ri = d->cur_ring + c;
391 if (ri > d->last_ring)
392 ri = d->first_ring;
393 ring = NETMAP_RXRING(d->nifp, ri);
279 for ( ; ring->avail > 0 && cnt != got; got++) {
394 for ( ; !nm_ring_empty(ring) && 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);
395 u_int i = ring->cur;
396 u_int idx = ring->slot[i].buf_idx;
397 u_char *buf = (u_char *)NETMAP_BUF(ring, idx);
398 // XXX should check valid buf
399 // prefetch(buf);
400 d->hdr.len = d->hdr.caplen = ring->slot[i].len;
401 d->hdr.ts = ring->ts;
402 cb(arg, &d->hdr, buf);
288 ring->cur = NETMAP_RING_NEXT(ring, i);
289 ring->avail--;
403 ring->head = ring->cur = nm_ring_next(ring, i);
290 }
291 }
292 d->cur_ring = ri;
293 return got;
294}
295
404 }
405 }
406 d->cur_ring = ri;
407 return got;
408}
409
296inline /* not really, but disable unused warnings */
297static u_char *
410static u_char *
298nm_next(struct nm_desc_t *d, struct nm_hdr_t *hdr)
411nm_nextpkt(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);
412{
413 int ri = d->cur_ring;
414
415 do {
416 /* compute current ring to use */
417 struct netmap_ring *ring = NETMAP_RXRING(d->nifp, ri);
305 if (ring->avail > 0) {
418 if (!nm_ring_empty(ring)) {
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;
419 u_int i = ring->cur;
420 u_int idx = ring->slot[i].buf_idx;
421 u_char *buf = (u_char *)NETMAP_BUF(ring, idx);
422 // XXX should check valid buf
423 // prefetch(buf);
424 hdr->ts = ring->ts;
425 hdr->len = hdr->caplen = ring->slot[i].len;
313 ring->cur = NETMAP_RING_NEXT(ring, i);
314 ring->avail--;
426 ring->cur = nm_ring_next(ring, i);
427 /* we could postpone advancing head if we want
428 * to hold the buffer. This can be supported in
429 * the future.
430 */
431 ring->head = ring->cur;
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
329#endif /* _NET_NETMAP_USER_H_ */
432 d->cur_ring = ri;
433 return buf;
434 }
435 ri++;
436 if (ri > d->last_ring)
437 ri = d->first_ring;
438 } while (ri != d->cur_ring);
439 return NULL; /* nothing found */
440}
441
442#endif /* !HAVE_NETMAP_WITH_LIBS */
443
444#endif /* NETMAP_WITH_LIBS */
445
446#endif /* _NET_NETMAP_USER_H_ */