Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/netmap/netmap_generic.c
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
// XXX temporary - D() defined here | // XXX temporary - D() defined here | ||||
#include <net/netmap.h> | #include <net/netmap.h> | ||||
#include <dev/netmap/netmap_kern.h> | #include <dev/netmap/netmap_kern.h> | ||||
#include <dev/netmap/netmap_mem2.h> | #include <dev/netmap/netmap_mem2.h> | ||||
#define MBUF_RXQ(m) ((m)->m_pkthdr.flowid) | #define MBUF_RXQ(m) ((m)->m_pkthdr.flowid) | ||||
#define smp_mb() | #define smp_mb() | ||||
/* | |||||
* FreeBSD mbuf allocator/deallocator in emulation mode: | |||||
*/ | |||||
#if __FreeBSD_version < 1100000 | |||||
/* | |||||
* For older versions of FreeBSD: | |||||
* | |||||
* We allocate EXT_PACKET mbuf+clusters, but need to set M_NOFREE | |||||
* so that the destructor, if invoked, will not free the packet. | |||||
* In principle we should set the destructor only on demand, | |||||
* but since there might be a race we better do it on allocation. | |||||
* As a consequence, we also need to set the destructor or we | |||||
* would leak buffers. | |||||
*/ | |||||
/* mbuf destructor, also need to change the type to EXT_EXTREF, | |||||
* add an M_NOFREE flag, and then clear the flag and | |||||
* chain into uma_zfree(zone_pack, mf) | |||||
* (or reinstall the buffer ?) | |||||
*/ | |||||
#define SET_MBUF_DESTRUCTOR(m, fn) do { \ | |||||
(m)->m_ext.ext_free = (void *)fn; \ | |||||
(m)->m_ext.ext_type = EXT_EXTREF; \ | |||||
} while (0) | |||||
static int | |||||
void_mbuf_dtor(struct mbuf *m, void *arg1, void *arg2) | |||||
{ | |||||
/* restore original mbuf */ | |||||
m->m_ext.ext_buf = m->m_data = m->m_ext.ext_arg1; | |||||
m->m_ext.ext_arg1 = NULL; | |||||
m->m_ext.ext_type = EXT_PACKET; | |||||
m->m_ext.ext_free = NULL; | |||||
if (MBUF_REFCNT(m) == 0) | |||||
SET_MBUF_REFCNT(m, 1); | |||||
uma_zfree(zone_pack, m); | |||||
return 0; | |||||
} | |||||
static inline struct mbuf * | |||||
nm_os_get_mbuf(struct ifnet *ifp, int len) | |||||
{ | |||||
struct mbuf *m; | |||||
(void)ifp; | |||||
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | |||||
if (m) { | |||||
/* m_getcl() (mb_ctor_mbuf) has an assert that checks that | |||||
* M_NOFREE flag is not specified as third argument, | |||||
* so we have to set M_NOFREE after m_getcl(). */ | |||||
m->m_flags |= M_NOFREE; | |||||
m->m_ext.ext_arg1 = m->m_ext.ext_buf; // XXX save | |||||
m->m_ext.ext_free = (void *)void_mbuf_dtor; | |||||
m->m_ext.ext_type = EXT_EXTREF; | |||||
ND(5, "create m %p refcnt %d", m, MBUF_REFCNT(m)); | |||||
} | |||||
return m; | |||||
} | |||||
#else /* __FreeBSD_version >= 1100000 */ | |||||
/* | |||||
* Newer versions of FreeBSD, using a straightforward scheme. | |||||
* | |||||
* We allocate mbufs with m_gethdr(), since the mbuf header is needed | |||||
* by the driver. We also attach a customly-provided external storage, | |||||
* which in this case is a netmap buffer. When calling m_extadd(), however | |||||
* we pass a NULL address, since the real address (and length) will be | |||||
* filled in by nm_os_generic_xmit_frame() right before calling | |||||
* if_transmit(). | |||||
* | |||||
* The dtor function does nothing, however we need it since mb_free_ext() | |||||
* has a KASSERT(), checking that the mbuf dtor function is not NULL. | |||||
*/ | |||||
#if __FreeBSD_version <= 1200050 | |||||
static void void_mbuf_dtor(struct mbuf *m, void *arg1, void *arg2) { } | |||||
#else /* __FreeBSD_version >= 1200051 */ | |||||
/* The arg1 and arg2 pointers argument were removed by r324446, which | |||||
* in included since version 1200051. */ | |||||
static void void_mbuf_dtor(struct mbuf *m) { } | |||||
#endif /* __FreeBSD_version >= 1200051 */ | |||||
#define SET_MBUF_DESTRUCTOR(m, fn) do { \ | |||||
(m)->m_ext.ext_free = (fn != NULL) ? \ | |||||
(void *)fn : (void *)void_mbuf_dtor; \ | |||||
} while (0) | |||||
static inline struct mbuf * | |||||
nm_os_get_mbuf(struct ifnet *ifp, int len) | |||||
{ | |||||
struct mbuf *m; | |||||
(void)ifp; | |||||
(void)len; | |||||
m = m_gethdr(M_NOWAIT, MT_DATA); | |||||
if (m == NULL) { | |||||
return m; | |||||
} | |||||
m_extadd(m, NULL /* buf */, 0 /* size */, void_mbuf_dtor, | |||||
NULL, NULL, 0, EXT_NET_DRV); | |||||
return m; | |||||
} | |||||
#endif /* __FreeBSD_version >= 1100000 */ | |||||
#elif defined _WIN32 | #elif defined _WIN32 | ||||
#include "win_glue.h" | #include "win_glue.h" | ||||
#define MBUF_TXQ(m) 0//((m)->m_pkthdr.flowid) | #define MBUF_TXQ(m) 0//((m)->m_pkthdr.flowid) | ||||
#define MBUF_RXQ(m) 0//((m)->m_pkthdr.flowid) | #define MBUF_RXQ(m) 0//((m)->m_pkthdr.flowid) | ||||
#define smp_mb() //XXX: to be correctly defined | #define smp_mb() //XXX: to be correctly defined | ||||
▲ Show 20 Lines • Show All 945 Lines • ▼ Show 20 Lines | if (nm_iszombie(na)) { | ||||
/* | /* | ||||
* The driver has been removed without releasing | * The driver has been removed without releasing | ||||
* the reference so we need to do it here. | * the reference so we need to do it here. | ||||
*/ | */ | ||||
netmap_adapter_put(prev_na); | netmap_adapter_put(prev_na); | ||||
} | } | ||||
D("Native netmap adapter %p restored", prev_na); | D("Native netmap adapter %p restored", prev_na); | ||||
} | } | ||||
NM_ATTACH_NA(ifp, prev_na); | NM_RESTORE_NA(ifp, prev_na); | ||||
/* | /* | ||||
* netmap_detach_common(), that it's called after this function, | * netmap_detach_common(), that it's called after this function, | ||||
* overrides WNA(ifp) if na->ifp is not NULL. | * overrides WNA(ifp) if na->ifp is not NULL. | ||||
*/ | */ | ||||
na->ifp = NULL; | na->ifp = NULL; | ||||
D("Emulated netmap adapter for %s destroyed", na->name); | D("Emulated netmap adapter for %s destroyed", na->name); | ||||
} | } | ||||
Show All 24 Lines | |||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
if (ifp->if_type == IFT_LOOP) { | if (ifp->if_type == IFT_LOOP) { | ||||
D("if_loop is not supported by %s", __func__); | D("if_loop is not supported by %s", __func__); | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
#endif | #endif | ||||
if (NA(ifp) && !NM_NA_VALID(ifp)) { | if (NM_NA_CLASH(ifp)) { | ||||
/* If NA(ifp) is not null but there is no valid netmap | /* If NA(ifp) is not null but there is no valid netmap | ||||
* adapter it means that someone else is using the same | * adapter it means that someone else is using the same | ||||
* pointer (e.g. ax25_ptr on linux). This happens for | * pointer (e.g. ax25_ptr on linux). This happens for | ||||
* instance when also PF_RING is in use. */ | * instance when also PF_RING is in use. */ | ||||
D("Error: netmap adapter hook is busy"); | D("Error: netmap adapter hook is busy"); | ||||
return EBUSY; | return EBUSY; | ||||
} | } | ||||
Show All 11 Lines | if (gna == NULL) { | ||||
D("no memory on attach, give up"); | D("no memory on attach, give up"); | ||||
return ENOMEM; | return ENOMEM; | ||||
} | } | ||||
na = (struct netmap_adapter *)gna; | na = (struct netmap_adapter *)gna; | ||||
strncpy(na->name, ifp->if_xname, sizeof(na->name)); | strncpy(na->name, ifp->if_xname, sizeof(na->name)); | ||||
na->ifp = ifp; | na->ifp = ifp; | ||||
na->num_tx_desc = num_tx_desc; | na->num_tx_desc = num_tx_desc; | ||||
na->num_rx_desc = num_rx_desc; | na->num_rx_desc = num_rx_desc; | ||||
na->rx_buf_maxsize = 32768; | |||||
na->nm_register = &generic_netmap_register; | na->nm_register = &generic_netmap_register; | ||||
na->nm_txsync = &generic_netmap_txsync; | na->nm_txsync = &generic_netmap_txsync; | ||||
na->nm_rxsync = &generic_netmap_rxsync; | na->nm_rxsync = &generic_netmap_rxsync; | ||||
na->nm_dtor = &generic_netmap_dtor; | na->nm_dtor = &generic_netmap_dtor; | ||||
/* when using generic, NAF_NETMAP_ON is set so we force | /* when using generic, NAF_NETMAP_ON is set so we force | ||||
* NAF_SKIP_INTR to use the regular interrupt handler | * NAF_SKIP_INTR to use the regular interrupt handler | ||||
*/ | */ | ||||
na->na_flags = NAF_SKIP_INTR | NAF_HOST_RINGS; | na->na_flags = NAF_SKIP_INTR | NAF_HOST_RINGS; | ||||
ND("[GNA] num_tx_queues(%d), real_num_tx_queues(%d), len(%lu)", | ND("[GNA] num_tx_queues(%d), real_num_tx_queues(%d), len(%lu)", | ||||
ifp->num_tx_queues, ifp->real_num_tx_queues, | ifp->num_tx_queues, ifp->real_num_tx_queues, | ||||
ifp->tx_queue_len); | ifp->tx_queue_len); | ||||
ND("[GNA] num_rx_queues(%d), real_num_rx_queues(%d)", | ND("[GNA] num_rx_queues(%d), real_num_rx_queues(%d)", | ||||
ifp->num_rx_queues, ifp->real_num_rx_queues); | ifp->num_rx_queues, ifp->real_num_rx_queues); | ||||
nm_os_generic_find_num_queues(ifp, &na->num_tx_rings, &na->num_rx_rings); | nm_os_generic_find_num_queues(ifp, &na->num_tx_rings, &na->num_rx_rings); | ||||
retval = netmap_attach_common(na); | retval = netmap_attach_common(na); | ||||
if (retval) { | if (retval) { | ||||
nm_os_free(gna); | nm_os_free(gna); | ||||
return retval; | return retval; | ||||
} | } | ||||
if (NM_NA_VALID(ifp)) { | |||||
gna->prev = NA(ifp); /* save old na */ | gna->prev = NA(ifp); /* save old na */ | ||||
if (gna->prev != NULL) { | |||||
netmap_adapter_get(gna->prev); | netmap_adapter_get(gna->prev); | ||||
} | } | ||||
NM_ATTACH_NA(ifp, na); | NM_ATTACH_NA(ifp, na); | ||||
nm_os_generic_set_features(gna); | nm_os_generic_set_features(gna); | ||||
D("Emulated adapter for %s created (prev was %p)", na->name, gna->prev); | D("Emulated adapter for %s created (prev was %p)", na->name, gna->prev); | ||||
return retval; | return retval; | ||||
} | } |