Deleted Added
full compact
netmap_generic.c (341477) netmap_generic.c (342033)
1/*
2 * Copyright (C) 2013-2016 Vincenzo Maffione
3 * Copyright (C) 2013-2016 Luigi Rizzo
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

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

60 *
61 * RX:
62 *
63 */
64
65#ifdef __FreeBSD__
66
67#include <sys/cdefs.h> /* prerequisite */
1/*
2 * Copyright (C) 2013-2016 Vincenzo Maffione
3 * Copyright (C) 2013-2016 Luigi Rizzo
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

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

60 *
61 * RX:
62 *
63 */
64
65#ifdef __FreeBSD__
66
67#include <sys/cdefs.h> /* prerequisite */
68__FBSDID("$FreeBSD: stable/11/sys/dev/netmap/netmap_generic.c 341477 2018-12-04 17:40:56Z vmaffione $");
68__FBSDID("$FreeBSD: stable/11/sys/dev/netmap/netmap_generic.c 342033 2018-12-13 10:13:29Z vmaffione $");
69
70#include <sys/types.h>
71#include <sys/errno.h>
72#include <sys/malloc.h>
73#include <sys/lock.h> /* PROT_EXEC */
74#include <sys/rwlock.h>
75#include <sys/socket.h> /* sockaddrs */
76#include <sys/selinfo.h>
77#include <net/if.h>
78#include <net/if_types.h>
79#include <net/if_var.h>
80#include <machine/bus.h> /* bus_dmamap_* in netmap_kern.h */
81
69
70#include <sys/types.h>
71#include <sys/errno.h>
72#include <sys/malloc.h>
73#include <sys/lock.h> /* PROT_EXEC */
74#include <sys/rwlock.h>
75#include <sys/socket.h> /* sockaddrs */
76#include <sys/selinfo.h>
77#include <net/if.h>
78#include <net/if_types.h>
79#include <net/if_var.h>
80#include <machine/bus.h> /* bus_dmamap_* in netmap_kern.h */
81
82// XXX temporary - D() defined here
83#include <net/netmap.h>
84#include <dev/netmap/netmap_kern.h>
85#include <dev/netmap/netmap_mem2.h>
86
87#define MBUF_RXQ(m) ((m)->m_pkthdr.flowid)
88#define smp_mb()
89
90#elif defined _WIN32

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

172 RATE_PRINTK(rxsync);
173 RATE_PRINTK(rxirq);
174 printk("\n");
175
176 ctx->old = cur;
177 r = mod_timer(&ctx->timer, jiffies +
178 msecs_to_jiffies(RATE_PERIOD * 1000));
179 if (unlikely(r))
82#include <net/netmap.h>
83#include <dev/netmap/netmap_kern.h>
84#include <dev/netmap/netmap_mem2.h>
85
86#define MBUF_RXQ(m) ((m)->m_pkthdr.flowid)
87#define smp_mb()
88
89#elif defined _WIN32

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

171 RATE_PRINTK(rxsync);
172 RATE_PRINTK(rxirq);
173 printk("\n");
174
175 ctx->old = cur;
176 r = mod_timer(&ctx->timer, jiffies +
177 msecs_to_jiffies(RATE_PERIOD * 1000));
178 if (unlikely(r))
180 D("[v1000] Error: mod_timer()");
179 nm_prerr("mod_timer() failed");
181}
182
183static struct rate_context rate_ctx;
184
185void generic_rate(int txp, int txs, int txi, int rxp, int rxs, int rxi)
186{
187 if (txp) rate_ctx.new.txpkt++;
188 if (txs) rate_ctx.new.txsync++;

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

233 nm_os_catch_rx(gna, 0);
234
235 /* Release packet steering control. */
236 nm_os_catch_tx(gna, 0);
237 }
238
239 for_each_rx_kring_h(r, kring, na) {
240 if (nm_kring_pending_off(kring)) {
180}
181
182static struct rate_context rate_ctx;
183
184void generic_rate(int txp, int txs, int txi, int rxp, int rxs, int rxi)
185{
186 if (txp) rate_ctx.new.txpkt++;
187 if (txs) rate_ctx.new.txsync++;

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

232 nm_os_catch_rx(gna, 0);
233
234 /* Release packet steering control. */
235 nm_os_catch_tx(gna, 0);
236 }
237
238 for_each_rx_kring_h(r, kring, na) {
239 if (nm_kring_pending_off(kring)) {
241 D("Emulated adapter: ring '%s' deactivated", kring->name);
240 nm_prinf("Emulated adapter: ring '%s' deactivated", kring->name);
242 kring->nr_mode = NKR_NETMAP_OFF;
243 }
244 }
245 for_each_tx_kring_h(r, kring, na) {
246 if (nm_kring_pending_off(kring)) {
247 kring->nr_mode = NKR_NETMAP_OFF;
241 kring->nr_mode = NKR_NETMAP_OFF;
242 }
243 }
244 for_each_tx_kring_h(r, kring, na) {
245 if (nm_kring_pending_off(kring)) {
246 kring->nr_mode = NKR_NETMAP_OFF;
248 D("Emulated adapter: ring '%s' deactivated", kring->name);
247 nm_prinf("Emulated adapter: ring '%s' deactivated", kring->name);
249 }
250 }
251
252 for_each_rx_kring(r, kring, na) {
253 /* Free the mbufs still pending in the RX queues,
254 * that did not end up into the corresponding netmap
255 * RX rings. */
256 mbq_safe_purge(&kring->rx_queue);

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

293 }
294 }
295 nm_os_free(kring->tx_pool);
296 kring->tx_pool = NULL;
297 }
298
299#ifdef RATE_GENERIC
300 if (--rate_ctx.refcount == 0) {
248 }
249 }
250
251 for_each_rx_kring(r, kring, na) {
252 /* Free the mbufs still pending in the RX queues,
253 * that did not end up into the corresponding netmap
254 * RX rings. */
255 mbq_safe_purge(&kring->rx_queue);

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

292 }
293 }
294 nm_os_free(kring->tx_pool);
295 kring->tx_pool = NULL;
296 }
297
298#ifdef RATE_GENERIC
299 if (--rate_ctx.refcount == 0) {
301 D("del_timer()");
300 nm_prinf("del_timer()");
302 del_timer(&rate_ctx.timer);
303 }
304#endif
301 del_timer(&rate_ctx.timer);
302 }
303#endif
305 D("Emulated adapter for %s deactivated", na->name);
304 nm_prinf("Emulated adapter for %s deactivated", na->name);
306 }
307
308 return 0;
309}
310
311/* Enable/disable netmap mode for a generic network interface. */
312static int
313generic_netmap_register(struct netmap_adapter *na, int enable)

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

322 }
323
324 if (!enable) {
325 /* This is actually an unregif. */
326 return generic_netmap_unregister(na);
327 }
328
329 if (na->active_fds == 0) {
305 }
306
307 return 0;
308}
309
310/* Enable/disable netmap mode for a generic network interface. */
311static int
312generic_netmap_register(struct netmap_adapter *na, int enable)

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

321 }
322
323 if (!enable) {
324 /* This is actually an unregif. */
325 return generic_netmap_unregister(na);
326 }
327
328 if (na->active_fds == 0) {
330 D("Emulated adapter for %s activated", na->name);
329 nm_prinf("Emulated adapter for %s activated", na->name);
331 /* Do all memory allocations when (na->active_fds == 0), to
332 * simplify error management. */
333
334 /* Allocate memory for mitigation support on all the rx queues. */
335 gna->mit = nm_os_malloc(na->num_rx_rings * sizeof(struct nm_generic_mit));
336 if (!gna->mit) {
330 /* Do all memory allocations when (na->active_fds == 0), to
331 * simplify error management. */
332
333 /* Allocate memory for mitigation support on all the rx queues. */
334 gna->mit = nm_os_malloc(na->num_rx_rings * sizeof(struct nm_generic_mit));
335 if (!gna->mit) {
337 D("mitigation allocation failed");
336 nm_prerr("mitigation allocation failed");
338 error = ENOMEM;
339 goto out;
340 }
341
342 for_each_rx_kring(r, kring, na) {
343 /* Init mitigation support. */
344 nm_os_mitigation_init(&gna->mit[r], r, na);
345

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

356 */
357 for_each_tx_kring(r, kring, na) {
358 kring->tx_pool = NULL;
359 }
360 for_each_tx_kring(r, kring, na) {
361 kring->tx_pool =
362 nm_os_malloc(na->num_tx_desc * sizeof(struct mbuf *));
363 if (!kring->tx_pool) {
337 error = ENOMEM;
338 goto out;
339 }
340
341 for_each_rx_kring(r, kring, na) {
342 /* Init mitigation support. */
343 nm_os_mitigation_init(&gna->mit[r], r, na);
344

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

355 */
356 for_each_tx_kring(r, kring, na) {
357 kring->tx_pool = NULL;
358 }
359 for_each_tx_kring(r, kring, na) {
360 kring->tx_pool =
361 nm_os_malloc(na->num_tx_desc * sizeof(struct mbuf *));
362 if (!kring->tx_pool) {
364 D("tx_pool allocation failed");
363 nm_prerr("tx_pool allocation failed");
365 error = ENOMEM;
366 goto free_tx_pools;
367 }
368 mtx_init(&kring->tx_event_lock, "tx_event_lock",
369 NULL, MTX_SPIN);
370 }
371 }
372
373 for_each_rx_kring_h(r, kring, na) {
374 if (nm_kring_pending_on(kring)) {
364 error = ENOMEM;
365 goto free_tx_pools;
366 }
367 mtx_init(&kring->tx_event_lock, "tx_event_lock",
368 NULL, MTX_SPIN);
369 }
370 }
371
372 for_each_rx_kring_h(r, kring, na) {
373 if (nm_kring_pending_on(kring)) {
375 D("Emulated adapter: ring '%s' activated", kring->name);
374 nm_prinf("Emulated adapter: ring '%s' activated", kring->name);
376 kring->nr_mode = NKR_NETMAP_ON;
377 }
378
379 }
380 for_each_tx_kring_h(r, kring, na) {
381 if (nm_kring_pending_on(kring)) {
375 kring->nr_mode = NKR_NETMAP_ON;
376 }
377
378 }
379 for_each_tx_kring_h(r, kring, na) {
380 if (nm_kring_pending_on(kring)) {
382 D("Emulated adapter: ring '%s' activated", kring->name);
381 nm_prinf("Emulated adapter: ring '%s' activated", kring->name);
383 kring->nr_mode = NKR_NETMAP_ON;
384 }
385 }
386
387 for_each_tx_kring(r, kring, na) {
388 /* Initialize tx_pool and tx_event. */
389 for (i=0; i<na->num_tx_desc; i++) {
390 kring->tx_pool[i] = NULL;
391 }
392
393 kring->tx_event = NULL;
394 }
395
396 if (na->active_fds == 0) {
397 /* Prepare to intercept incoming traffic. */
398 error = nm_os_catch_rx(gna, 1);
399 if (error) {
382 kring->nr_mode = NKR_NETMAP_ON;
383 }
384 }
385
386 for_each_tx_kring(r, kring, na) {
387 /* Initialize tx_pool and tx_event. */
388 for (i=0; i<na->num_tx_desc; i++) {
389 kring->tx_pool[i] = NULL;
390 }
391
392 kring->tx_event = NULL;
393 }
394
395 if (na->active_fds == 0) {
396 /* Prepare to intercept incoming traffic. */
397 error = nm_os_catch_rx(gna, 1);
398 if (error) {
400 D("nm_os_catch_rx(1) failed (%d)", error);
399 nm_prerr("nm_os_catch_rx(1) failed (%d)", error);
401 goto free_tx_pools;
402 }
403
404 /* Let netmap control the packet steering. */
405 error = nm_os_catch_tx(gna, 1);
406 if (error) {
400 goto free_tx_pools;
401 }
402
403 /* Let netmap control the packet steering. */
404 error = nm_os_catch_tx(gna, 1);
405 if (error) {
407 D("nm_os_catch_tx(1) failed (%d)", error);
406 nm_prerr("nm_os_catch_tx(1) failed (%d)", error);
408 goto catch_rx;
409 }
410
411 na->na_flags |= NAF_NETMAP_ON;
412
413#ifdef RATE_GENERIC
414 if (rate_ctx.refcount == 0) {
407 goto catch_rx;
408 }
409
410 na->na_flags |= NAF_NETMAP_ON;
411
412#ifdef RATE_GENERIC
413 if (rate_ctx.refcount == 0) {
415 D("setup_timer()");
414 nm_prinf("setup_timer()");
416 memset(&rate_ctx, 0, sizeof(rate_ctx));
417 setup_timer(&rate_ctx.timer, &rate_callback, (unsigned long)&rate_ctx);
418 if (mod_timer(&rate_ctx.timer, jiffies + msecs_to_jiffies(1500))) {
415 memset(&rate_ctx, 0, sizeof(rate_ctx));
416 setup_timer(&rate_ctx.timer, &rate_callback, (unsigned long)&rate_ctx);
417 if (mod_timer(&rate_ctx.timer, jiffies + msecs_to_jiffies(1500))) {
419 D("Error: mod_timer()");
418 nm_prerr("Error: mod_timer()");
420 }
421 }
422 rate_ctx.refcount++;
423#endif /* RATE */
424 }
425
426 return 0;
427

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

455generic_mbuf_destructor(struct mbuf *m)
456{
457 struct netmap_adapter *na = NA(GEN_TX_MBUF_IFP(m));
458 struct netmap_kring *kring;
459 unsigned int r = MBUF_TXQ(m);
460 unsigned int r_orig = r;
461
462 if (unlikely(!nm_netmap_on(na) || r >= na->num_tx_rings)) {
419 }
420 }
421 rate_ctx.refcount++;
422#endif /* RATE */
423 }
424
425 return 0;
426

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

454generic_mbuf_destructor(struct mbuf *m)
455{
456 struct netmap_adapter *na = NA(GEN_TX_MBUF_IFP(m));
457 struct netmap_kring *kring;
458 unsigned int r = MBUF_TXQ(m);
459 unsigned int r_orig = r;
460
461 if (unlikely(!nm_netmap_on(na) || r >= na->num_tx_rings)) {
463 D("Error: no netmap adapter on device %p",
462 nm_prerr("Error: no netmap adapter on device %p",
464 GEN_TX_MBUF_IFP(m));
465 return;
466 }
467
468 /*
469 * First, clear the event mbuf.
470 * In principle, the event 'm' should match the one stored
471 * on ring 'r'. However we check it explicitely to stay

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

481 if (kring->tx_event == m) {
482 kring->tx_event = NULL;
483 match = true;
484 }
485 mtx_unlock_spin(&kring->tx_event_lock);
486
487 if (match) {
488 if (r != r_orig) {
463 GEN_TX_MBUF_IFP(m));
464 return;
465 }
466
467 /*
468 * First, clear the event mbuf.
469 * In principle, the event 'm' should match the one stored
470 * on ring 'r'. However we check it explicitely to stay

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

480 if (kring->tx_event == m) {
481 kring->tx_event = NULL;
482 match = true;
483 }
484 mtx_unlock_spin(&kring->tx_event_lock);
485
486 if (match) {
487 if (r != r_orig) {
489 RD(1, "event %p migrated: ring %u --> %u",
488 nm_prlim(1, "event %p migrated: ring %u --> %u",
490 m, r_orig, r);
491 }
492 break;
493 }
494
495 if (++r == na->num_tx_rings) r = 0;
496
497 if (r == r_orig) {
489 m, r_orig, r);
490 }
491 break;
492 }
493
494 if (++r == na->num_tx_rings) r = 0;
495
496 if (r == r_orig) {
498 RD(1, "Cannot match event %p", m);
497 nm_prlim(1, "Cannot match event %p", m);
499 return;
500 }
501 }
502
503 /* Second, wake up clients. They will reclaim the event through
504 * txsync. */
505 netmap_generic_irq(na, r, NULL);
506#ifdef __FreeBSD__

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

521generic_netmap_tx_clean(struct netmap_kring *kring, int txqdisc)
522{
523 u_int const lim = kring->nkr_num_slots - 1;
524 u_int nm_i = nm_next(kring->nr_hwtail, lim);
525 u_int hwcur = kring->nr_hwcur;
526 u_int n = 0;
527 struct mbuf **tx_pool = kring->tx_pool;
528
498 return;
499 }
500 }
501
502 /* Second, wake up clients. They will reclaim the event through
503 * txsync. */
504 netmap_generic_irq(na, r, NULL);
505#ifdef __FreeBSD__

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

520generic_netmap_tx_clean(struct netmap_kring *kring, int txqdisc)
521{
522 u_int const lim = kring->nkr_num_slots - 1;
523 u_int nm_i = nm_next(kring->nr_hwtail, lim);
524 u_int hwcur = kring->nr_hwcur;
525 u_int n = 0;
526 struct mbuf **tx_pool = kring->tx_pool;
527
529 ND("hwcur = %d, hwtail = %d", kring->nr_hwcur, kring->nr_hwtail);
528 nm_prdis("hwcur = %d, hwtail = %d", kring->nr_hwcur, kring->nr_hwtail);
530
531 while (nm_i != hwcur) { /* buffers not completed */
532 struct mbuf *m = tx_pool[nm_i];
533
534 if (txqdisc) {
535 if (m == NULL) {
536 /* Nothing to do, this is going
537 * to be replenished. */
529
530 while (nm_i != hwcur) { /* buffers not completed */
531 struct mbuf *m = tx_pool[nm_i];
532
533 if (txqdisc) {
534 if (m == NULL) {
535 /* Nothing to do, this is going
536 * to be replenished. */
538 RD(3, "Is this happening?");
537 nm_prlim(3, "Is this happening?");
539
540 } else if (MBUF_QUEUED(m)) {
541 break; /* Not dequeued yet. */
542
543 } else if (MBUF_REFCNT(m) != 1) {
544 /* This mbuf has been dequeued but is still busy
545 * (refcount is 2).
546 * Leave it to the driver and replenish. */

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

569 break;
570 }
571 }
572
573 n++;
574 nm_i = nm_next(nm_i, lim);
575 }
576 kring->nr_hwtail = nm_prev(nm_i, lim);
538
539 } else if (MBUF_QUEUED(m)) {
540 break; /* Not dequeued yet. */
541
542 } else if (MBUF_REFCNT(m) != 1) {
543 /* This mbuf has been dequeued but is still busy
544 * (refcount is 2).
545 * Leave it to the driver and replenish. */

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

568 break;
569 }
570 }
571
572 n++;
573 nm_i = nm_next(nm_i, lim);
574 }
575 kring->nr_hwtail = nm_prev(nm_i, lim);
577 ND("tx completed [%d] -> hwtail %d", n, kring->nr_hwtail);
576 nm_prdis("tx completed [%d] -> hwtail %d", n, kring->nr_hwtail);
578
579 return n;
580}
581
582/* Compute a slot index in the middle between inf and sup. */
583static inline u_int
584ring_middle(u_int inf, u_int sup, u_int lim)
585{

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

591 } else { /* wrap around */
592 e = (sup + n + inf) / 2;
593 if (e >= n) {
594 e -= n;
595 }
596 }
597
598 if (unlikely(e >= n)) {
577
578 return n;
579}
580
581/* Compute a slot index in the middle between inf and sup. */
582static inline u_int
583ring_middle(u_int inf, u_int sup, u_int lim)
584{

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

590 } else { /* wrap around */
591 e = (sup + n + inf) / 2;
592 if (e >= n) {
593 e -= n;
594 }
595 }
596
597 if (unlikely(e >= n)) {
599 D("This cannot happen");
598 nm_prerr("This cannot happen");
600 e = 0;
601 }
602
603 return e;
604}
605
606static void
607generic_set_tx_event(struct netmap_kring *kring, u_int hwcur)

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

647 }
648
649 SET_MBUF_DESTRUCTOR(m, generic_mbuf_destructor);
650 kring->tx_event = m;
651 mtx_unlock_spin(&kring->tx_event_lock);
652
653 kring->tx_pool[e] = NULL;
654
599 e = 0;
600 }
601
602 return e;
603}
604
605static void
606generic_set_tx_event(struct netmap_kring *kring, u_int hwcur)

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

646 }
647
648 SET_MBUF_DESTRUCTOR(m, generic_mbuf_destructor);
649 kring->tx_event = m;
650 mtx_unlock_spin(&kring->tx_event_lock);
651
652 kring->tx_pool[e] = NULL;
653
655 ND(5, "Request Event at %d mbuf %p refcnt %d", e, m, m ? MBUF_REFCNT(m) : -2 );
654 nm_prdis("Request Event at %d mbuf %p refcnt %d", e, m, m ? MBUF_REFCNT(m) : -2 );
656
657 /* Decrement the refcount. This will free it if we lose the race
658 * with the driver. */
659 m_freem(m);
660 smp_mb();
661}
662
663

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

692 struct nm_os_gen_arg a;
693 u_int event = -1;
694
695 if (gna->txqdisc && nm_kr_txempty(kring)) {
696 /* In txqdisc mode, we ask for a delayed notification,
697 * but only when cur == hwtail, which means that the
698 * client is going to block. */
699 event = ring_middle(nm_i, head, lim);
655
656 /* Decrement the refcount. This will free it if we lose the race
657 * with the driver. */
658 m_freem(m);
659 smp_mb();
660}
661
662

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

691 struct nm_os_gen_arg a;
692 u_int event = -1;
693
694 if (gna->txqdisc && nm_kr_txempty(kring)) {
695 /* In txqdisc mode, we ask for a delayed notification,
696 * but only when cur == hwtail, which means that the
697 * client is going to block. */
698 event = ring_middle(nm_i, head, lim);
700 ND(3, "Place txqdisc event (hwcur=%u,event=%u,"
699 nm_prdis("Place txqdisc event (hwcur=%u,event=%u,"
701 "head=%u,hwtail=%u)", nm_i, event, head,
702 kring->nr_hwtail);
703 }
704
705 a.ifp = ifp;
706 a.ring_nr = ring_nr;
707 a.head = a.tail = NULL;
708

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

718
719 /* Tale a mbuf from the tx pool (replenishing the pool
720 * entry if necessary) and copy in the user packet. */
721 m = kring->tx_pool[nm_i];
722 if (unlikely(m == NULL)) {
723 kring->tx_pool[nm_i] = m =
724 nm_os_get_mbuf(ifp, NETMAP_BUF_SIZE(na));
725 if (m == NULL) {
700 "head=%u,hwtail=%u)", nm_i, event, head,
701 kring->nr_hwtail);
702 }
703
704 a.ifp = ifp;
705 a.ring_nr = ring_nr;
706 a.head = a.tail = NULL;
707

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

717
718 /* Tale a mbuf from the tx pool (replenishing the pool
719 * entry if necessary) and copy in the user packet. */
720 m = kring->tx_pool[nm_i];
721 if (unlikely(m == NULL)) {
722 kring->tx_pool[nm_i] = m =
723 nm_os_get_mbuf(ifp, NETMAP_BUF_SIZE(na));
724 if (m == NULL) {
726 RD(2, "Failed to replenish mbuf");
725 nm_prlim(2, "Failed to replenish mbuf");
727 /* Here we could schedule a timer which
728 * retries to replenish after a while,
729 * and notifies the client when it
730 * manages to replenish some slots. In
731 * any case we break early to avoid
732 * crashes. */
733 break;
734 }

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

847 return 0;
848 }
849
850 /* limit the size of the queue */
851 if (unlikely(!gna->rxsg && MBUF_LEN(m) > NETMAP_BUF_SIZE(na))) {
852 /* This may happen when GRO/LRO features are enabled for
853 * the NIC driver when the generic adapter does not
854 * support RX scatter-gather. */
726 /* Here we could schedule a timer which
727 * retries to replenish after a while,
728 * and notifies the client when it
729 * manages to replenish some slots. In
730 * any case we break early to avoid
731 * crashes. */
732 break;
733 }

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

846 return 0;
847 }
848
849 /* limit the size of the queue */
850 if (unlikely(!gna->rxsg && MBUF_LEN(m) > NETMAP_BUF_SIZE(na))) {
851 /* This may happen when GRO/LRO features are enabled for
852 * the NIC driver when the generic adapter does not
853 * support RX scatter-gather. */
855 RD(2, "Warning: driver pushed up big packet "
854 nm_prlim(2, "Warning: driver pushed up big packet "
856 "(size=%d)", (int)MBUF_LEN(m));
857 m_freem(m);
858 } else if (unlikely(mbq_len(&kring->rx_queue) > 1024)) {
859 m_freem(m);
860 } else {
861 mbq_safe_enqueue(&kring->rx_queue, m);
862 }
863

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

1041 netmap_adapter_put(prev_na);
1042 if (nm_iszombie(na)) {
1043 /*
1044 * The driver has been removed without releasing
1045 * the reference so we need to do it here.
1046 */
1047 netmap_adapter_put(prev_na);
1048 }
855 "(size=%d)", (int)MBUF_LEN(m));
856 m_freem(m);
857 } else if (unlikely(mbq_len(&kring->rx_queue) > 1024)) {
858 m_freem(m);
859 } else {
860 mbq_safe_enqueue(&kring->rx_queue, m);
861 }
862

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

1040 netmap_adapter_put(prev_na);
1041 if (nm_iszombie(na)) {
1042 /*
1043 * The driver has been removed without releasing
1044 * the reference so we need to do it here.
1045 */
1046 netmap_adapter_put(prev_na);
1047 }
1049 D("Native netmap adapter %p restored", prev_na);
1048 nm_prinf("Native netmap adapter %p restored", prev_na);
1050 }
1051 NM_RESTORE_NA(ifp, prev_na);
1052 /*
1053 * netmap_detach_common(), that it's called after this function,
1054 * overrides WNA(ifp) if na->ifp is not NULL.
1055 */
1056 na->ifp = NULL;
1049 }
1050 NM_RESTORE_NA(ifp, prev_na);
1051 /*
1052 * netmap_detach_common(), that it's called after this function,
1053 * overrides WNA(ifp) if na->ifp is not NULL.
1054 */
1055 na->ifp = NULL;
1057 D("Emulated netmap adapter for %s destroyed", na->name);
1056 nm_prinf("Emulated netmap adapter for %s destroyed", na->name);
1058}
1059
1060int
1061na_is_generic(struct netmap_adapter *na)
1062{
1063 return na->nm_register == generic_netmap_register;
1064}
1065

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

1079{
1080 struct netmap_adapter *na;
1081 struct netmap_generic_adapter *gna;
1082 int retval;
1083 u_int num_tx_desc, num_rx_desc;
1084
1085#ifdef __FreeBSD__
1086 if (ifp->if_type == IFT_LOOP) {
1057}
1058
1059int
1060na_is_generic(struct netmap_adapter *na)
1061{
1062 return na->nm_register == generic_netmap_register;
1063}
1064

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

1078{
1079 struct netmap_adapter *na;
1080 struct netmap_generic_adapter *gna;
1081 int retval;
1082 u_int num_tx_desc, num_rx_desc;
1083
1084#ifdef __FreeBSD__
1085 if (ifp->if_type == IFT_LOOP) {
1087 D("if_loop is not supported by %s", __func__);
1086 nm_prerr("if_loop is not supported by %s", __func__);
1088 return EINVAL;
1089 }
1090#endif
1091
1092 if (NM_NA_CLASH(ifp)) {
1093 /* If NA(ifp) is not null but there is no valid netmap
1094 * adapter it means that someone else is using the same
1095 * pointer (e.g. ax25_ptr on linux). This happens for
1096 * instance when also PF_RING is in use. */
1087 return EINVAL;
1088 }
1089#endif
1090
1091 if (NM_NA_CLASH(ifp)) {
1092 /* If NA(ifp) is not null but there is no valid netmap
1093 * adapter it means that someone else is using the same
1094 * pointer (e.g. ax25_ptr on linux). This happens for
1095 * instance when also PF_RING is in use. */
1097 D("Error: netmap adapter hook is busy");
1096 nm_prerr("Error: netmap adapter hook is busy");
1098 return EBUSY;
1099 }
1100
1101 num_tx_desc = num_rx_desc = netmap_generic_ringsize; /* starting point */
1102
1103 nm_os_generic_find_num_desc(ifp, &num_tx_desc, &num_rx_desc); /* ignore errors */
1097 return EBUSY;
1098 }
1099
1100 num_tx_desc = num_rx_desc = netmap_generic_ringsize; /* starting point */
1101
1102 nm_os_generic_find_num_desc(ifp, &num_tx_desc, &num_rx_desc); /* ignore errors */
1104 ND("Netmap ring size: TX = %d, RX = %d", num_tx_desc, num_rx_desc);
1105 if (num_tx_desc == 0 || num_rx_desc == 0) {
1103 if (num_tx_desc == 0 || num_rx_desc == 0) {
1106 D("Device has no hw slots (tx %u, rx %u)", num_tx_desc, num_rx_desc);
1104 nm_prerr("Device has no hw slots (tx %u, rx %u)", num_tx_desc, num_rx_desc);
1107 return EINVAL;
1108 }
1109
1110 gna = nm_os_malloc(sizeof(*gna));
1111 if (gna == NULL) {
1105 return EINVAL;
1106 }
1107
1108 gna = nm_os_malloc(sizeof(*gna));
1109 if (gna == NULL) {
1112 D("no memory on attach, give up");
1110 nm_prerr("no memory on attach, give up");
1113 return ENOMEM;
1114 }
1115 na = (struct netmap_adapter *)gna;
1111 return ENOMEM;
1112 }
1113 na = (struct netmap_adapter *)gna;
1116 strncpy(na->name, ifp->if_xname, sizeof(na->name));
1114 strlcpy(na->name, ifp->if_xname, sizeof(na->name));
1117 na->ifp = ifp;
1118 na->num_tx_desc = num_tx_desc;
1119 na->num_rx_desc = num_rx_desc;
1120 na->rx_buf_maxsize = 32768;
1121 na->nm_register = &generic_netmap_register;
1122 na->nm_txsync = &generic_netmap_txsync;
1123 na->nm_rxsync = &generic_netmap_rxsync;
1124 na->nm_dtor = &generic_netmap_dtor;
1125 /* when using generic, NAF_NETMAP_ON is set so we force
1126 * NAF_SKIP_INTR to use the regular interrupt handler
1127 */
1128 na->na_flags = NAF_SKIP_INTR | NAF_HOST_RINGS;
1129
1115 na->ifp = ifp;
1116 na->num_tx_desc = num_tx_desc;
1117 na->num_rx_desc = num_rx_desc;
1118 na->rx_buf_maxsize = 32768;
1119 na->nm_register = &generic_netmap_register;
1120 na->nm_txsync = &generic_netmap_txsync;
1121 na->nm_rxsync = &generic_netmap_rxsync;
1122 na->nm_dtor = &generic_netmap_dtor;
1123 /* when using generic, NAF_NETMAP_ON is set so we force
1124 * NAF_SKIP_INTR to use the regular interrupt handler
1125 */
1126 na->na_flags = NAF_SKIP_INTR | NAF_HOST_RINGS;
1127
1130 ND("[GNA] num_tx_queues(%d), real_num_tx_queues(%d), len(%lu)",
1128 nm_prdis("[GNA] num_tx_queues(%d), real_num_tx_queues(%d), len(%lu)",
1131 ifp->num_tx_queues, ifp->real_num_tx_queues,
1132 ifp->tx_queue_len);
1129 ifp->num_tx_queues, ifp->real_num_tx_queues,
1130 ifp->tx_queue_len);
1133 ND("[GNA] num_rx_queues(%d), real_num_rx_queues(%d)",
1131 nm_prdis("[GNA] num_rx_queues(%d), real_num_rx_queues(%d)",
1134 ifp->num_rx_queues, ifp->real_num_rx_queues);
1135
1136 nm_os_generic_find_num_queues(ifp, &na->num_tx_rings, &na->num_rx_rings);
1137
1138 retval = netmap_attach_common(na);
1139 if (retval) {
1140 nm_os_free(gna);
1141 return retval;
1142 }
1143
1144 if (NM_NA_VALID(ifp)) {
1145 gna->prev = NA(ifp); /* save old na */
1146 netmap_adapter_get(gna->prev);
1147 }
1148 NM_ATTACH_NA(ifp, na);
1149
1150 nm_os_generic_set_features(gna);
1151
1132 ifp->num_rx_queues, ifp->real_num_rx_queues);
1133
1134 nm_os_generic_find_num_queues(ifp, &na->num_tx_rings, &na->num_rx_rings);
1135
1136 retval = netmap_attach_common(na);
1137 if (retval) {
1138 nm_os_free(gna);
1139 return retval;
1140 }
1141
1142 if (NM_NA_VALID(ifp)) {
1143 gna->prev = NA(ifp); /* save old na */
1144 netmap_adapter_get(gna->prev);
1145 }
1146 NM_ATTACH_NA(ifp, na);
1147
1148 nm_os_generic_set_features(gna);
1149
1152 D("Emulated adapter for %s created (prev was %p)", na->name, gna->prev);
1150 nm_prinf("Emulated adapter for %s created (prev was %p)", na->name, gna->prev);
1153
1154 return retval;
1155}
1151
1152 return retval;
1153}