59799066b68f50121944770b38f7510b94f91667
[dragonfly.git] / sys / net / netmap / netmap_generic.c
1 /*
2  * Copyright (C) 2013 Universita` di Pisa. All rights reserved.
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  *   1. Redistributions of source code must retain the above copyright
8  *      notice, this list of conditions and the following disclaimer.
9  *   2. Redistributions in binary form must reproduce the above copyright
10  *      notice, this list of conditions and the following disclaimer in the
11  *      documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /*
27  * This module implements netmap support on top of standard,
28  * unmodified device drivers.
29  *
30  * A NIOCREGIF request is handled here if the device does not
31  * have native support. TX and RX rings are emulated as follows:
32  *
33  * NIOCREGIF
34  *      We preallocate a block of TX mbufs (roughly as many as
35  *      tx descriptors; the number is not critical) to speed up
36  *      operation during transmissions. The refcount on most of
37  *      these buffers is artificially bumped up so we can recycle
38  *      them more easily. Also, the destructor is intercepted
39  *      so we use it as an interrupt notification to wake up
40  *      processes blocked on a poll().
41  *
42  *      For each receive ring we allocate one "struct mbq"
43  *      (an mbuf tailq plus a spinlock). We intercept packets
44  *      (through if_input)
45  *      on the receive path and put them in the mbq from which
46  *      netmap receive routines can grab them.
47  *
48  * TX:
49  *      in the generic_txsync() routine, netmap buffers are copied
50  *      (or linked, in a future) to the preallocated mbufs
51  *      and pushed to the transmit queue. Some of these mbufs
52  *      (those with NS_REPORT, or otherwise every half ring)
53  *      have the refcount=1, others have refcount=2.
54  *      When the destructor is invoked, we take that as
55  *      a notification that all mbufs up to that one in
56  *      the specific ring have been completed, and generate
57  *      the equivalent of a transmit interrupt.
58  *
59  * RX:
60  *
61  */
62
63 /* __FBSDID("$FreeBSD: head/sys/dev/netmap/netmap.c 257666 2013-11-05 01:06:22Z luigi $"); */
64
65 #include <sys/types.h>
66 #include <sys/errno.h>
67 #include <sys/malloc.h>
68 #include <sys/event.h>
69 #include <sys/lock.h>   /* PROT_EXEC */
70 #include <sys/socket.h> /* sockaddrs */
71 #include <net/if.h>
72 #include <net/if_var.h>
73 #include <sys/bus.h>        /* bus_dmamap_* in netmap_kern.h */
74
75 // XXX temporary - D() defined here
76 #include <net/netmap.h>
77
78 #include "netmap_kern.h"
79 #include "netmap_mem2.h"
80
81 #define rtnl_lock() D("rtnl_lock called");
82 #define rtnl_unlock() D("rtnl_lock called");
83 #define MBUF_TXQ(m)     ((m)->m_pkthdr.hash)
84 #define smp_mb()
85
86 /*
87  * mbuf wrappers
88  */
89
90 /*
91  * we allocate an EXT_PACKET
92  */
93 #define netmap_get_mbuf(len) m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR)
94
95 /* mbuf destructor, also need to change the type to EXT_EXTREF,
96  * add an M_NOFREE flag, and then clear the flag and
97  * chain into uma_zfree(zone_pack, mf)
98  * (or reinstall the buffer ?)
99  */
100 #define SET_MBUF_DESTRUCTOR(m, fn)      do {            \
101                 (m)->m_ext.ext_free = (void *)fn;       \
102                 /* (m)->m_ext.ext_type = EXT_EXTREF; */ \
103         } while (0)
104
105
106 #define GET_MBUF_REFCNT(m)      ((m)->m_ext.ref_cnt ? *(m)->m_ext.ref_cnt : -1)
107
108 /* ======================== usage stats =========================== */
109
110 #ifdef RATE
111 #define IFRATE(x) x
112 struct rate_stats {
113     unsigned long txpkt;
114     unsigned long txsync;
115     unsigned long txirq;
116     unsigned long rxpkt;
117     unsigned long rxirq;
118     unsigned long rxsync;
119 };
120
121 struct rate_context {
122     unsigned refcount;
123     struct timer_list timer;
124     struct rate_stats new;
125     struct rate_stats old;
126 };
127
128 #define RATE_PRINTK(_NAME_) \
129     printk( #_NAME_ " = %lu Hz\n", (cur._NAME_ - ctx->old._NAME_)/RATE_PERIOD);
130 #define RATE_PERIOD  2
131 static void rate_callback(unsigned long arg)
132 {
133     struct rate_context * ctx = (struct rate_context *)arg;
134     struct rate_stats cur = ctx->new;
135     int r;
136
137     RATE_PRINTK(txpkt);
138     RATE_PRINTK(txsync);
139     RATE_PRINTK(txirq);
140     RATE_PRINTK(rxpkt);
141     RATE_PRINTK(rxsync);
142     RATE_PRINTK(rxirq);
143     printk("\n");
144
145     ctx->old = cur;
146     r = mod_timer(&ctx->timer, jiffies +
147                                 msecs_to_jiffies(RATE_PERIOD * 1000));
148     if (unlikely(r))
149         D("[v1000] Error: mod_timer()");
150 }
151
152 static struct rate_context rate_ctx;
153
154 #else /* !RATE */
155 #define IFRATE(x)
156 #endif /* !RATE */
157
158
159 /* =============== GENERIC NETMAP ADAPTER SUPPORT ================= */
160 #define GENERIC_BUF_SIZE        netmap_buf_size    /* Size of the mbufs in the Tx pool. */
161
162 /*
163  * Wrapper used by the generic adapter layer to notify
164  * the poller threads. Differently from netmap_rx_irq(), we check
165  * only IFCAP_NETMAP instead of NAF_NATIVE_ON to enable the irq.
166  */
167 static int
168 netmap_generic_irq(struct ifnet *ifp, u_int q, u_int *work_done)
169 {
170         if (unlikely(!(ifp->if_capenable & IFCAP_NETMAP)))
171                 return 0;
172
173         return netmap_common_irq(ifp, q, work_done);
174 }
175
176
177 /* Enable/disable netmap mode for a generic network interface. */
178 int generic_netmap_register(struct netmap_adapter *na, int enable)
179 {
180     struct ifnet *ifp = na->ifp;
181     struct netmap_generic_adapter *gna = (struct netmap_generic_adapter *)na;
182     struct mbuf *m;
183     int error;
184     int i, r;
185
186     if (!na)
187         return EINVAL;
188
189 #ifdef REG_RESET
190     error = ifp->netdev_ops->ndo_stop(ifp);
191     if (error) {
192         return error;
193     }
194 #endif /* REG_RESET */
195
196     if (enable) { /* Enable netmap mode. */
197         /* Initialize the rx queue, as generic_rx_handler() can
198          * be called as soon as netmap_catch_rx() returns.
199          */
200         for (r=0; r<na->num_rx_rings; r++) {
201             mbq_safe_init(&na->rx_rings[r].rx_queue);
202             na->rx_rings[r].nr_ntc = 0;
203         }
204
205         /* Init the mitigation timer. */
206         netmap_mitigation_init(gna);
207
208         /*
209          * Preallocate packet buffers for the tx rings.
210          */
211         for (r=0; r<na->num_tx_rings; r++) {
212             na->tx_rings[r].nr_ntc = 0;
213             na->tx_rings[r].tx_pool = kmalloc(na->num_tx_desc * sizeof(struct mbuf *),
214                                     M_DEVBUF, M_NOWAIT | M_ZERO);
215             if (!na->tx_rings[r].tx_pool) {
216                 D("tx_pool allocation failed");
217                 error = ENOMEM;
218                 goto free_tx_pool;
219             }
220             for (i=0; i<na->num_tx_desc; i++) {
221                 m = netmap_get_mbuf(GENERIC_BUF_SIZE);
222                 if (!m) {
223                     D("tx_pool[%d] allocation failed", i);
224                     error = ENOMEM;
225                     goto free_mbufs;
226                 }
227                 na->tx_rings[r].tx_pool[i] = m;
228             }
229         }
230         rtnl_lock();
231         /* Prepare to intercept incoming traffic. */
232         error = netmap_catch_rx(na, 1);
233         if (error) {
234             D("netdev_rx_handler_register() failed");
235             goto register_handler;
236         }
237         ifp->if_capenable |= IFCAP_NETMAP;
238
239         /* Make netmap control the packet steering. */
240         netmap_catch_packet_steering(gna, 1);
241
242         rtnl_unlock();
243
244 #ifdef RATE
245         if (rate_ctx.refcount == 0) {
246             D("setup_timer()");
247             memset(&rate_ctx, 0, sizeof(rate_ctx));
248             setup_timer(&rate_ctx.timer, &rate_callback, (unsigned long)&rate_ctx);
249             if (mod_timer(&rate_ctx.timer, jiffies + msecs_to_jiffies(1500))) {
250                 D("Error: mod_timer()");
251             }
252         }
253         rate_ctx.refcount++;
254 #endif /* RATE */
255
256     } else { /* Disable netmap mode. */
257         rtnl_lock();
258
259         ifp->if_capenable &= ~IFCAP_NETMAP;
260
261         /* Release packet steering control. */
262         netmap_catch_packet_steering(gna, 0);
263
264         /* Do not intercept packets on the rx path. */
265         netmap_catch_rx(na, 0);
266
267         rtnl_unlock();
268
269         /* Free the mbufs going to the netmap rings */
270         for (r=0; r<na->num_rx_rings; r++) {
271             mbq_safe_purge(&na->rx_rings[r].rx_queue);
272             mbq_safe_destroy(&na->rx_rings[r].rx_queue);
273         }
274
275         netmap_mitigation_cleanup(gna);
276
277         for (r=0; r<na->num_tx_rings; r++) {
278             for (i=0; i<na->num_tx_desc; i++) {
279                 m_freem(na->tx_rings[r].tx_pool[i]);
280             }
281             kfree(na->tx_rings[r].tx_pool, M_DEVBUF);
282         }
283
284 #ifdef RATE
285         if (--rate_ctx.refcount == 0) {
286             D("del_timer()");
287             del_timer(&rate_ctx.timer);
288         }
289 #endif
290     }
291
292 #ifdef REG_RESET
293     error = ifp->netdev_ops->ndo_open(ifp);
294     if (error) {
295         goto alloc_tx_pool;
296     }
297 #endif
298
299     return 0;
300
301 register_handler:
302     rtnl_unlock();
303 free_tx_pool:
304     r--;
305     i = na->num_tx_desc;  /* Useless, but just to stay safe. */
306 free_mbufs:
307     i--;
308     for (; r>=0; r--) {
309         for (; i>=0; i--) {
310             m_freem(na->tx_rings[r].tx_pool[i]);
311         }
312         kfree(na->tx_rings[r].tx_pool, M_DEVBUF);
313         i = na->num_tx_desc - 1;
314     }
315
316     return error;
317 }
318
319 /*
320  * Callback invoked when the device driver frees an mbuf used
321  * by netmap to transmit a packet. This usually happens when
322  * the NIC notifies the driver that transmission is completed.
323  */
324 static void
325 generic_mbuf_destructor(struct mbuf *m)
326 {
327     if (netmap_verbose)
328             D("Tx irq (%p) queue %d", m, MBUF_TXQ(m));
329     netmap_generic_irq(MBUF_IFP(m), MBUF_TXQ(m), NULL);
330 #if 0
331     m->m_ext.ext_type = EXT_PACKET;
332 #endif
333     m->m_ext.ext_free = NULL;
334 #if 0
335     if (*(m->m_ext.ref_cnt) == 0)
336         *(m->m_ext.ref_cnt) = 1;
337     uma_zfree(zone_pack, m);
338 #endif
339     IFRATE(rate_ctx.new.txirq++);
340 }
341
342 /* Record completed transmissions and update hwavail.
343  *
344  * nr_ntc is the oldest tx buffer not yet completed
345  * (same as nr_hwavail + nr_hwcur + 1),
346  * nr_hwcur is the first unsent buffer.
347  * When cleaning, we try to recover buffers between nr_ntc and nr_hwcur.
348  */
349 static int
350 generic_netmap_tx_clean(struct netmap_kring *kring)
351 {
352     u_int num_slots = kring->nkr_num_slots;
353     u_int ntc = kring->nr_ntc;
354     u_int hwcur = kring->nr_hwcur;
355     u_int n = 0;
356     struct mbuf **tx_pool = kring->tx_pool;
357
358     while (ntc != hwcur) { /* buffers not completed */
359         struct mbuf *m = tx_pool[ntc];
360
361         if (unlikely(m == NULL)) {
362             /* try to replenish the entry */
363             tx_pool[ntc] = m = netmap_get_mbuf(GENERIC_BUF_SIZE);
364             if (unlikely(m == NULL)) {
365                 D("mbuf allocation failed, XXX error");
366                 // XXX how do we proceed ? break ?
367                 return -ENOMEM;
368             }
369 #if 0
370         } else if (GET_MBUF_REFCNT(m) != 1) {
371             break; /* This mbuf is still busy: its refcnt is 2. */
372 #endif
373         }
374         if (unlikely(++ntc == num_slots)) {
375             ntc = 0;
376         }
377         n++;
378     }
379     kring->nr_ntc = ntc;
380     kring->nr_hwavail += n;
381     ND("tx completed [%d] -> hwavail %d", n, kring->nr_hwavail);
382
383     return n;
384 }
385
386
387 /*
388  * We have pending packets in the driver between nr_ntc and j.
389  * Compute a position in the middle, to be used to generate
390  * a notification.
391  */
392 static inline u_int
393 generic_tx_event_middle(struct netmap_kring *kring, u_int hwcur)
394 {
395     u_int n = kring->nkr_num_slots;
396     u_int ntc = kring->nr_ntc;
397     u_int e;
398
399     if (hwcur >= ntc) {
400         e = (hwcur + ntc) / 2;
401     } else { /* wrap around */
402         e = (hwcur + n + ntc) / 2;
403         if (e >= n) {
404             e -= n;
405         }
406     }
407
408     if (unlikely(e >= n)) {
409         D("This cannot happen");
410         e = 0;
411     }
412
413     return e;
414 }
415
416 /*
417  * We have pending packets in the driver between nr_ntc and hwcur.
418  * Schedule a notification approximately in the middle of the two.
419  * There is a race but this is only called within txsync which does
420  * a double check.
421  */
422 static void
423 generic_set_tx_event(struct netmap_kring *kring, u_int hwcur)
424 {
425     struct mbuf *m;
426     u_int e;
427
428     if (kring->nr_ntc == hwcur) {
429         return;
430     }
431     e = generic_tx_event_middle(kring, hwcur);
432
433     m = kring->tx_pool[e];
434     if (m == NULL) {
435         /* This can happen if there is already an event on the netmap
436            slot 'e': There is nothing to do. */
437         return;
438     }
439     ND("Event at %d mbuf %p refcnt %d", e, m, GET_MBUF_REFCNT(m));
440     kring->tx_pool[e] = NULL;
441     SET_MBUF_DESTRUCTOR(m, generic_mbuf_destructor);
442
443     // XXX wmb() ?
444     /* Decrement the refcount an free it if we have the last one. */
445     m_freem(m);
446     smp_mb();
447 }
448
449
450 /*
451  * generic_netmap_txsync() transforms netmap buffers into mbufs
452  * and passes them to the standard device driver
453  * (ndo_start_xmit() or ifp->if_transmit() ).
454  * On linux this is not done directly, but using dev_queue_xmit(),
455  * since it implements the TX flow control (and takes some locks).
456  */
457 static int
458 generic_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags)
459 {
460     struct ifnet *ifp = na->ifp;
461     struct netmap_kring *kring = &na->tx_rings[ring_nr];
462     struct netmap_ring *ring = kring->ring;
463     u_int j, k, num_slots = kring->nkr_num_slots;
464     int new_slots, ntx;
465
466     IFRATE(rate_ctx.new.txsync++);
467
468     // TODO: handle the case of mbuf allocation failure
469     /* first, reclaim completed buffers */
470     generic_netmap_tx_clean(kring);
471
472     /* Take a copy of ring->cur now, and never read it again. */
473     k = ring->cur;
474     if (unlikely(k >= num_slots)) {
475         return netmap_ring_reinit(kring);
476     }
477
478     rmb();
479     j = kring->nr_hwcur;
480     /*
481     * 'new_slots' counts how many new slots have been added:
482      * everything from hwcur to cur, excluding reserved ones, if any.
483      * nr_hwreserved start from hwcur and counts how many slots were
484      * not sent to the NIC from the previous round.
485      */
486     new_slots = k - j - kring->nr_hwreserved;
487     if (new_slots < 0) {
488         new_slots += num_slots;
489     }
490     ntx = 0;
491     if (j != k) {
492         /* Process new packets to send:
493          * j is the current index in the netmap ring.
494          */
495         while (j != k) {
496             struct netmap_slot *slot = &ring->slot[j]; /* Current slot in the netmap ring */
497             void *addr = NMB(slot);
498             u_int len = slot->len;
499             struct mbuf *m;
500             int tx_ret;
501
502             if (unlikely(addr == netmap_buffer_base || len > NETMAP_BUF_SIZE)) {
503                 return netmap_ring_reinit(kring);
504             }
505             /* Tale a mbuf from the tx pool and copy in the user packet. */
506             m = kring->tx_pool[j];
507             if (unlikely(!m)) {
508                 RD(5, "This should never happen");
509                 kring->tx_pool[j] = m = netmap_get_mbuf(GENERIC_BUF_SIZE);
510                 if (unlikely(m == NULL)) {
511                     D("mbuf allocation failed");
512                     break;
513                 }
514             }
515             /* XXX we should ask notifications when NS_REPORT is set,
516              * or roughly every half frame. We can optimize this
517              * by lazily requesting notifications only when a
518              * transmission fails. Probably the best way is to
519              * break on failures and set notifications when
520              * ring->avail == 0 || j != k
521              */
522             tx_ret = generic_xmit_frame(ifp, m, addr, len, ring_nr);
523             if (unlikely(tx_ret)) {
524                 RD(5, "start_xmit failed: err %d [%u,%u,%u,%u]",
525                         tx_ret, kring->nr_ntc, j, k, kring->nr_hwavail);
526                 /*
527                  * No room for this mbuf in the device driver.
528                  * Request a notification FOR A PREVIOUS MBUF,
529                  * then call generic_netmap_tx_clean(kring) to do the
530                  * double check and see if we can free more buffers.
531                  * If there is space continue, else break;
532                  * NOTE: the double check is necessary if the problem
533                  * occurs in the txsync call after selrecord().
534                  * Also, we need some way to tell the caller that not
535                  * all buffers were queued onto the device (this was
536                  * not a problem with native netmap driver where space
537                  * is preallocated). The bridge has a similar problem
538                  * and we solve it there by dropping the excess packets.
539                  */
540                 generic_set_tx_event(kring, j);
541                 if (generic_netmap_tx_clean(kring)) { /* space now available */
542                     continue;
543                 } else {
544                     break;
545                 }
546             }
547             slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
548             if (unlikely(++j == num_slots))
549                 j = 0;
550             ntx++;
551         }
552
553         /* Update hwcur to the next slot to transmit. */
554         kring->nr_hwcur = j;
555
556         /*
557          * Report all new slots as unavailable, even those not sent.
558          * We account for them with with hwreserved, so that
559          * nr_hwreserved =:= cur - nr_hwcur
560          */
561         kring->nr_hwavail -= new_slots;
562         kring->nr_hwreserved = k - j;
563         if (kring->nr_hwreserved < 0) {
564             kring->nr_hwreserved += num_slots;
565         }
566
567         IFRATE(rate_ctx.new.txpkt += ntx);
568
569         if (!kring->nr_hwavail) {
570             /* No more available slots? Set a notification event
571              * on a netmap slot that will be cleaned in the future.
572              * No doublecheck is performed, since txsync() will be
573              * called twice by netmap_poll().
574              */
575             generic_set_tx_event(kring, j);
576         }
577         ND("tx #%d, hwavail = %d", n, kring->nr_hwavail);
578     }
579
580     /* Synchronize the user's view to the kernel view. */
581     ring->avail = kring->nr_hwavail;
582     ring->reserved = kring->nr_hwreserved;
583
584     return 0;
585 }
586
587 /*
588  * This handler is registered (through netmap_catch_rx())
589  * within the attached network interface
590  * in the RX subsystem, so that every mbuf passed up by
591  * the driver can be stolen to the network stack.
592  * Stolen packets are put in a queue where the
593  * generic_netmap_rxsync() callback can extract them.
594  */
595 void generic_rx_handler(struct ifnet *ifp, struct mbuf *m)
596 {
597     struct netmap_adapter *na = NA(ifp);
598     struct netmap_generic_adapter *gna = (struct netmap_generic_adapter *)na;
599     u_int work_done;
600     u_int rr = 0; // receive ring number
601
602     ND("called");
603     /* limit the size of the queue */
604     if (unlikely(mbq_len(&na->rx_rings[rr].rx_queue) > 1024)) {
605         m_freem(m);
606     } else {
607         mbq_safe_enqueue(&na->rx_rings[rr].rx_queue, m);
608     }
609
610     if (netmap_generic_mit < 32768) {
611         /* no rx mitigation, pass notification up */
612         netmap_generic_irq(na->ifp, rr, &work_done);
613         IFRATE(rate_ctx.new.rxirq++);
614     } else {
615         /* same as send combining, filter notification if there is a
616          * pending timer, otherwise pass it up and start a timer.
617          */
618         if (likely(netmap_mitigation_active(gna))) {
619             /* Record that there is some pending work. */
620             gna->mit_pending = 1;
621         } else {
622             netmap_generic_irq(na->ifp, rr, &work_done);
623             IFRATE(rate_ctx.new.rxirq++);
624             netmap_mitigation_start(gna);
625         }
626     }
627 }
628
629 /*
630  * generic_netmap_rxsync() extracts mbufs from the queue filled by
631  * generic_netmap_rx_handler() and puts their content in the netmap
632  * receive ring.
633  * Access must be protected because the rx handler is asynchronous,
634  */
635 static int
636 generic_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags)
637 {
638     struct netmap_kring *kring = &na->rx_rings[ring_nr];
639     struct netmap_ring *ring = kring->ring;
640     u_int j, n, lim = kring->nkr_num_slots - 1;
641     int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
642     u_int k, resvd = ring->reserved;
643
644     if (ring->cur > lim)
645         return netmap_ring_reinit(kring);
646
647     /* Import newly received packets into the netmap ring. */
648     if (netmap_no_pendintr || force_update) {
649         uint16_t slot_flags = kring->nkr_slot_flags;
650         struct mbuf *m;
651
652         n = 0;
653         j = kring->nr_ntc; /* first empty slot in the receive ring */
654         /* extract buffers from the rx queue, stop at most one
655          * slot before nr_hwcur (index k)
656          */
657         k = (kring->nr_hwcur) ? kring->nr_hwcur-1 : lim;
658         while (j != k) {
659             int len;
660             void *addr = NMB(&ring->slot[j]);
661
662             if (addr == netmap_buffer_base) { /* Bad buffer */
663                 return netmap_ring_reinit(kring);
664             }
665             /*
666              * Call the locked version of the function.
667              *  XXX Ideally we could grab a batch of mbufs at once,
668              * by changing rx_queue into a ring.
669              */
670             m = mbq_safe_dequeue(&kring->rx_queue);
671             if (!m)
672                 break;
673             len = MBUF_LEN(m);
674             m_copydata(m, 0, len, addr);
675             ring->slot[j].len = len;
676             ring->slot[j].flags = slot_flags;
677             m_freem(m);
678             if (unlikely(j++ == lim))
679                 j = 0;
680             n++;
681         }
682         if (n) {
683             kring->nr_ntc = j;
684             kring->nr_hwavail += n;
685             IFRATE(rate_ctx.new.rxpkt += n);
686         }
687         kring->nr_kflags &= ~NKR_PENDINTR;
688     }
689
690     // XXX should we invert the order ?
691     /* Skip past packets that userspace has released */
692     j = kring->nr_hwcur;
693     k = ring->cur;
694     if (resvd > 0) {
695         if (resvd + ring->avail >= lim + 1) {
696             D("XXX invalid reserve/avail %d %d", resvd, ring->avail);
697             ring->reserved = resvd = 0; // XXX panic...
698         }
699         k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd;
700     }
701     if (j != k) {
702         /* Userspace has released some packets. */
703         for (n = 0; j != k; n++) {
704             struct netmap_slot *slot = &ring->slot[j];
705
706             slot->flags &= ~NS_BUF_CHANGED;
707             if (unlikely(j++ == lim))
708                 j = 0;
709         }
710         kring->nr_hwavail -= n;
711         kring->nr_hwcur = k;
712     }
713     /* Tell userspace that there are new packets. */
714     ring->avail = kring->nr_hwavail - resvd;
715     IFRATE(rate_ctx.new.rxsync++);
716
717     return 0;
718 }
719
720 static void
721 generic_netmap_dtor(struct netmap_adapter *na)
722 {
723     struct ifnet *ifp = na->ifp;
724     struct netmap_generic_adapter *gna = (struct netmap_generic_adapter*)na;
725     struct netmap_adapter *prev_na = gna->prev;
726
727     if (prev_na != NULL) {
728         D("Released generic NA %p", gna);
729 #if 0
730         if_rele(na->ifp);
731 #endif
732         netmap_adapter_put(prev_na);
733     }
734     if (ifp != NULL) {
735         WNA(ifp) = prev_na;
736         D("Restored native NA %p", prev_na);
737         na->ifp = NULL;
738     }
739 }
740
741 /*
742  * generic_netmap_attach() makes it possible to use netmap on
743  * a device without native netmap support.
744  * This is less performant than native support but potentially
745  * faster than raw sockets or similar schemes.
746  *
747  * In this "emulated" mode, netmap rings do not necessarily
748  * have the same size as those in the NIC. We use a default
749  * value and possibly override it if the OS has ways to fetch the
750  * actual configuration.
751  */
752 int
753 generic_netmap_attach(struct ifnet *ifp)
754 {
755     struct netmap_adapter *na;
756     struct netmap_generic_adapter *gna;
757     int retval;
758     u_int num_tx_desc, num_rx_desc;
759
760     num_tx_desc = num_rx_desc = netmap_generic_ringsize; /* starting point */
761
762     generic_find_num_desc(ifp, &num_tx_desc, &num_rx_desc);
763     ND("Netmap ring size: TX = %d, RX = %d", num_tx_desc, num_rx_desc);
764
765     gna = kmalloc(sizeof(*gna), M_DEVBUF, M_NOWAIT | M_ZERO);
766     if (gna == NULL) {
767         D("no memory on attach, give up");
768         return ENOMEM;
769     }
770     na = (struct netmap_adapter *)gna;
771     na->ifp = ifp;
772     na->num_tx_desc = num_tx_desc;
773     na->num_rx_desc = num_rx_desc;
774     na->nm_register = &generic_netmap_register;
775     na->nm_txsync = &generic_netmap_txsync;
776     na->nm_rxsync = &generic_netmap_rxsync;
777     na->nm_dtor = &generic_netmap_dtor;
778     /* when using generic, IFCAP_NETMAP is set so we force
779      * NAF_SKIP_INTR to use the regular interrupt handler
780      */
781     na->na_flags = NAF_SKIP_INTR;
782
783     ND("[GNA] num_tx_queues(%d), real_num_tx_queues(%d), len(%lu)",
784                 ifp->num_tx_queues, ifp->real_num_tx_queues,
785                 ifp->tx_queue_len);
786     ND("[GNA] num_rx_queues(%d), real_num_rx_queues(%d)",
787                 ifp->num_rx_queues, ifp->real_num_rx_queues);
788
789     generic_find_num_queues(ifp, &na->num_tx_rings, &na->num_rx_rings);
790
791     retval = netmap_attach_common(na);
792     if (retval) {
793         kfree(gna, M_DEVBUF);
794     }
795
796     return retval;
797 }