Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/netmap/netmap_kern.h
Show First 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | do { \ | ||||
if (__cnt++ < lps) \ | if (__cnt++ < lps) \ | ||||
D(format, ##__VA_ARGS__); \ | D(format, ##__VA_ARGS__); \ | ||||
} while (0) | } while (0) | ||||
struct netmap_adapter; | struct netmap_adapter; | ||||
struct nm_bdg_fwd; | struct nm_bdg_fwd; | ||||
struct nm_bridge; | struct nm_bridge; | ||||
struct netmap_priv_d; | struct netmap_priv_d; | ||||
struct nm_bdg_args; | |||||
/* os-specific NM_SELINFO_T initialzation/destruction functions */ | /* os-specific NM_SELINFO_T initialzation/destruction functions */ | ||||
void nm_os_selinfo_init(NM_SELINFO_T *); | void nm_os_selinfo_init(NM_SELINFO_T *); | ||||
void nm_os_selinfo_uninit(NM_SELINFO_T *); | void nm_os_selinfo_uninit(NM_SELINFO_T *); | ||||
const char *nm_dump_buf(char *p, int len, int lim, char *dst); | const char *nm_dump_buf(char *p, int len, int lim, char *dst); | ||||
void nm_os_selwakeup(NM_SELINFO_T *si); | void nm_os_selwakeup(NM_SELINFO_T *si); | ||||
Show All 14 Lines | |||||
/* os independent alloc/realloc/free */ | /* os independent alloc/realloc/free */ | ||||
void *nm_os_malloc(size_t); | void *nm_os_malloc(size_t); | ||||
void *nm_os_vmalloc(size_t); | void *nm_os_vmalloc(size_t); | ||||
void *nm_os_realloc(void *, size_t new_size, size_t old_size); | void *nm_os_realloc(void *, size_t new_size, size_t old_size); | ||||
void nm_os_free(void *); | void nm_os_free(void *); | ||||
void nm_os_vfree(void *); | void nm_os_vfree(void *); | ||||
/* os specific attach/detach enter/exit-netmap-mode routines */ | |||||
void nm_os_onattach(struct ifnet *); | |||||
void nm_os_ondetach(struct ifnet *); | |||||
void nm_os_onenter(struct ifnet *); | |||||
void nm_os_onexit(struct ifnet *); | |||||
/* passes a packet up to the host stack. | /* passes a packet up to the host stack. | ||||
* If the packet is sent (or dropped) immediately it returns NULL, | * If the packet is sent (or dropped) immediately it returns NULL, | ||||
* otherwise it links the packet to prev and returns m. | * otherwise it links the packet to prev and returns m. | ||||
* In this case, a final call with m=NULL and prev != NULL will send up | * In this case, a final call with m=NULL and prev != NULL will send up | ||||
* the entire chain to the host stack. | * the entire chain to the host stack. | ||||
*/ | */ | ||||
void *nm_os_send_up(struct ifnet *, struct mbuf *m, struct mbuf *prev); | void *nm_os_send_up(struct ifnet *, struct mbuf *m, struct mbuf *prev); | ||||
int nm_os_mbuf_has_offld(struct mbuf *m); | int nm_os_mbuf_has_seg_offld(struct mbuf *m); | ||||
int nm_os_mbuf_has_csum_offld(struct mbuf *m); | |||||
#include "netmap_mbq.h" | #include "netmap_mbq.h" | ||||
extern NMG_LOCK_T netmap_global_lock; | extern NMG_LOCK_T netmap_global_lock; | ||||
enum txrx { NR_RX = 0, NR_TX = 1, NR_TXRX }; | enum txrx { NR_RX = 0, NR_TX = 1, NR_TXRX }; | ||||
static __inline const char* | static __inline const char* | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | #define NR_NOSLOT ((uint32_t)~0) /* used in nkr_*lease* */ | ||||
*/ | */ | ||||
int (*nm_sync)(struct netmap_kring *kring, int flags); | int (*nm_sync)(struct netmap_kring *kring, int flags); | ||||
int (*nm_notify)(struct netmap_kring *kring, int flags); | int (*nm_notify)(struct netmap_kring *kring, int flags); | ||||
#ifdef WITH_PIPES | #ifdef WITH_PIPES | ||||
struct netmap_kring *pipe; /* if this is a pipe ring, | struct netmap_kring *pipe; /* if this is a pipe ring, | ||||
* pointer to the other end | * pointer to the other end | ||||
*/ | */ | ||||
uint32_t pipe_tail; /* hwtail updated by the other end */ | |||||
#endif /* WITH_PIPES */ | #endif /* WITH_PIPES */ | ||||
#ifdef WITH_VALE | |||||
int (*save_notify)(struct netmap_kring *kring, int flags); | int (*save_notify)(struct netmap_kring *kring, int flags); | ||||
#endif | |||||
#ifdef WITH_MONITOR | #ifdef WITH_MONITOR | ||||
/* array of krings that are monitoring this kring */ | /* array of krings that are monitoring this kring */ | ||||
struct netmap_kring **monitors; | struct netmap_kring **monitors; | ||||
uint32_t max_monitors; /* current size of the monitors array */ | uint32_t max_monitors; /* current size of the monitors array */ | ||||
uint32_t n_monitors; /* next unused entry in the monitor array */ | uint32_t n_monitors; /* next unused entry in the monitor array */ | ||||
uint32_t mon_pos[NR_TXRX]; /* index of this ring in the monitored ring array */ | uint32_t mon_pos[NR_TXRX]; /* index of this ring in the monitored ring array */ | ||||
uint32_t mon_tail; /* last seen slot on rx */ | uint32_t mon_tail; /* last seen slot on rx */ | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
struct netmap_lut { | struct netmap_lut { | ||||
struct lut_entry *lut; | struct lut_entry *lut; | ||||
struct plut_entry *plut; | struct plut_entry *plut; | ||||
uint32_t objtotal; /* max buffer index */ | uint32_t objtotal; /* max buffer index */ | ||||
uint32_t objsize; /* buffer size */ | uint32_t objsize; /* buffer size */ | ||||
}; | }; | ||||
struct netmap_vp_adapter; // forward | struct netmap_vp_adapter; // forward | ||||
struct nm_bridge; | |||||
/* Struct to be filled by nm_config callbacks. */ | /* Struct to be filled by nm_config callbacks. */ | ||||
struct nm_config_info { | struct nm_config_info { | ||||
unsigned num_tx_rings; | unsigned num_tx_rings; | ||||
unsigned num_rx_rings; | unsigned num_rx_rings; | ||||
unsigned num_tx_descs; | unsigned num_tx_descs; | ||||
unsigned num_rx_descs; | unsigned num_rx_descs; | ||||
unsigned rx_buf_maxsize; | unsigned rx_buf_maxsize; | ||||
}; | }; | ||||
/* | /* | ||||
* default type for the magic field. | |||||
* May be overriden in glue code. | |||||
*/ | |||||
#ifndef NM_OS_MAGIC | |||||
#define NM_OS_MAGIC uint32_t | |||||
#endif /* !NM_OS_MAGIC */ | |||||
/* | |||||
* The "struct netmap_adapter" extends the "struct adapter" | * The "struct netmap_adapter" extends the "struct adapter" | ||||
* (or equivalent) device descriptor. | * (or equivalent) device descriptor. | ||||
* It contains all base fields needed to support netmap operation. | * It contains all base fields needed to support netmap operation. | ||||
* There are in fact different types of netmap adapters | * There are in fact different types of netmap adapters | ||||
* (native, generic, VALE switch...) so a netmap_adapter is | * (native, generic, VALE switch...) so a netmap_adapter is | ||||
* just the first field in the derived type. | * just the first field in the derived type. | ||||
*/ | */ | ||||
struct netmap_adapter { | struct netmap_adapter { | ||||
/* | /* | ||||
* On linux we do not have a good way to tell if an interface | * On linux we do not have a good way to tell if an interface | ||||
* is netmap-capable. So we always use the following trick: | * is netmap-capable. So we always use the following trick: | ||||
* NA(ifp) points here, and the first entry (which hopefully | * NA(ifp) points here, and the first entry (which hopefully | ||||
* always exists and is at least 32 bits) contains a magic | * always exists and is at least 32 bits) contains a magic | ||||
* value which we can use to detect that the interface is good. | * value which we can use to detect that the interface is good. | ||||
*/ | */ | ||||
uint32_t magic; | NM_OS_MAGIC magic; | ||||
uint32_t na_flags; /* enabled, and other flags */ | uint32_t na_flags; /* enabled, and other flags */ | ||||
#define NAF_SKIP_INTR 1 /* use the regular interrupt handler. | #define NAF_SKIP_INTR 1 /* use the regular interrupt handler. | ||||
* useful during initialization | * useful during initialization | ||||
*/ | */ | ||||
#define NAF_SW_ONLY 2 /* forward packets only to sw adapter */ | #define NAF_SW_ONLY 2 /* forward packets only to sw adapter */ | ||||
#define NAF_BDG_MAYSLEEP 4 /* the bridge is allowed to sleep when | #define NAF_BDG_MAYSLEEP 4 /* the bridge is allowed to sleep when | ||||
* forwarding packets coming from this | * forwarding packets coming from this | ||||
* interface | * interface | ||||
Show All 19 Lines | #define NAF_BUSY (1U<<31) /* the adapter is used internally and | ||||
* cannot be registered from userspace | * cannot be registered from userspace | ||||
*/ | */ | ||||
int active_fds; /* number of user-space descriptors using this | int active_fds; /* number of user-space descriptors using this | ||||
interface, which is equal to the number of | interface, which is equal to the number of | ||||
struct netmap_if objs in the mapped region. */ | struct netmap_if objs in the mapped region. */ | ||||
u_int num_rx_rings; /* number of adapter receive rings */ | u_int num_rx_rings; /* number of adapter receive rings */ | ||||
u_int num_tx_rings; /* number of adapter transmit rings */ | u_int num_tx_rings; /* number of adapter transmit rings */ | ||||
u_int num_host_rx_rings; /* number of host receive rings */ | |||||
u_int num_host_tx_rings; /* number of host transmit rings */ | |||||
u_int num_tx_desc; /* number of descriptor in each queue */ | u_int num_tx_desc; /* number of descriptor in each queue */ | ||||
u_int num_rx_desc; | u_int num_rx_desc; | ||||
/* tx_rings and rx_rings are private but allocated | /* tx_rings and rx_rings are private but allocated | ||||
* as a contiguous chunk of memory. Each array has | * as a contiguous chunk of memory. Each array has | ||||
* N+1 entries, for the adapter queues and for the host queue. | * N+1 entries, for the adapter queues and for the host queue. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | #define NAF_BUSY (1U<<31) /* the adapter is used internally and | ||||
int (*nm_notify)(struct netmap_kring *kring, int flags); | int (*nm_notify)(struct netmap_kring *kring, int flags); | ||||
#define NAF_FORCE_READ 1 | #define NAF_FORCE_READ 1 | ||||
#define NAF_FORCE_RECLAIM 2 | #define NAF_FORCE_RECLAIM 2 | ||||
#define NAF_CAN_FORWARD_DOWN 4 | #define NAF_CAN_FORWARD_DOWN 4 | ||||
/* return configuration information */ | /* return configuration information */ | ||||
int (*nm_config)(struct netmap_adapter *, struct nm_config_info *info); | int (*nm_config)(struct netmap_adapter *, struct nm_config_info *info); | ||||
int (*nm_krings_create)(struct netmap_adapter *); | int (*nm_krings_create)(struct netmap_adapter *); | ||||
void (*nm_krings_delete)(struct netmap_adapter *); | void (*nm_krings_delete)(struct netmap_adapter *); | ||||
#ifdef WITH_VALE | |||||
/* | /* | ||||
* nm_bdg_attach() initializes the na_vp field to point | * nm_bdg_attach() initializes the na_vp field to point | ||||
* to an adapter that can be attached to a VALE switch. If the | * to an adapter that can be attached to a VALE switch. If the | ||||
* current adapter is already a VALE port, na_vp is simply a cast; | * current adapter is already a VALE port, na_vp is simply a cast; | ||||
* otherwise, na_vp points to a netmap_bwrap_adapter. | * otherwise, na_vp points to a netmap_bwrap_adapter. | ||||
* If applicable, this callback also initializes na_hostvp, | * If applicable, this callback also initializes na_hostvp, | ||||
* that can be used to connect the adapter host rings to the | * that can be used to connect the adapter host rings to the | ||||
* switch. | * switch. | ||||
* Called with NMG_LOCK held. | * Called with NMG_LOCK held. | ||||
* | * | ||||
* nm_bdg_ctl() is called on the actual attach/detach to/from | * nm_bdg_ctl() is called on the actual attach/detach to/from | ||||
* to/from the switch, to perform adapter-specific | * to/from the switch, to perform adapter-specific | ||||
* initializations | * initializations | ||||
* Called with NMG_LOCK held. | * Called with NMG_LOCK held. | ||||
*/ | */ | ||||
int (*nm_bdg_attach)(const char *bdg_name, struct netmap_adapter *); | int (*nm_bdg_attach)(const char *bdg_name, struct netmap_adapter *, | ||||
struct nm_bridge *); | |||||
int (*nm_bdg_ctl)(struct nmreq_header *, struct netmap_adapter *); | int (*nm_bdg_ctl)(struct nmreq_header *, struct netmap_adapter *); | ||||
/* adapter used to attach this adapter to a VALE switch (if any) */ | /* adapter used to attach this adapter to a VALE switch (if any) */ | ||||
struct netmap_vp_adapter *na_vp; | struct netmap_vp_adapter *na_vp; | ||||
/* adapter used to attach the host rings of this adapter | /* adapter used to attach the host rings of this adapter | ||||
* to a VALE switch (if any) */ | * to a VALE switch (if any) */ | ||||
struct netmap_vp_adapter *na_hostvp; | struct netmap_vp_adapter *na_hostvp; | ||||
#endif | |||||
/* standard refcount to control the lifetime of the adapter | /* standard refcount to control the lifetime of the adapter | ||||
* (it should be equal to the lifetime of the corresponding ifp) | * (it should be equal to the lifetime of the corresponding ifp) | ||||
*/ | */ | ||||
int na_refcount; | int na_refcount; | ||||
/* memory allocator (opaque) | /* memory allocator (opaque) | ||||
* We also cache a pointer to the lut_entry for translating | * We also cache a pointer to the lut_entry for translating | ||||
Show All 19 Lines | #define NAF_CAN_FORWARD_DOWN 4 | ||||
/* Max number of bytes that the NIC can store in the buffer | /* Max number of bytes that the NIC can store in the buffer | ||||
* referenced by each RX descriptor. This translates to the maximum | * referenced by each RX descriptor. This translates to the maximum | ||||
* bytes that a single netmap slot can reference. Larger packets | * bytes that a single netmap slot can reference. Larger packets | ||||
* require NS_MOREFRAG support. */ | * require NS_MOREFRAG support. */ | ||||
unsigned rx_buf_maxsize; | unsigned rx_buf_maxsize; | ||||
char name[NETMAP_REQ_IFNAMSIZ]; /* used at least by pipes */ | char name[NETMAP_REQ_IFNAMSIZ]; /* used at least by pipes */ | ||||
#ifdef WITH_MONITOR | |||||
unsigned long monitor_id; /* debugging */ | |||||
#endif | |||||
}; | }; | ||||
static __inline u_int | static __inline u_int | ||||
nma_get_ndesc(struct netmap_adapter *na, enum txrx t) | nma_get_ndesc(struct netmap_adapter *na, enum txrx t) | ||||
{ | { | ||||
return (t == NR_TX ? na->num_tx_desc : na->num_rx_desc); | return (t == NR_TX ? na->num_tx_desc : na->num_rx_desc); | ||||
} | } | ||||
static __inline void | static __inline void | ||||
nma_set_ndesc(struct netmap_adapter *na, enum txrx t, u_int v) | nma_set_ndesc(struct netmap_adapter *na, enum txrx t, u_int v) | ||||
{ | { | ||||
if (t == NR_TX) | if (t == NR_TX) | ||||
na->num_tx_desc = v; | na->num_tx_desc = v; | ||||
else | else | ||||
na->num_rx_desc = v; | na->num_rx_desc = v; | ||||
} | } | ||||
static __inline u_int | static __inline u_int | ||||
nma_get_nrings(struct netmap_adapter *na, enum txrx t) | nma_get_nrings(struct netmap_adapter *na, enum txrx t) | ||||
{ | { | ||||
return (t == NR_TX ? na->num_tx_rings : na->num_rx_rings); | return (t == NR_TX ? na->num_tx_rings : na->num_rx_rings); | ||||
} | } | ||||
static __inline u_int | |||||
nma_get_host_nrings(struct netmap_adapter *na, enum txrx t) | |||||
{ | |||||
return (t == NR_TX ? na->num_host_tx_rings : na->num_host_rx_rings); | |||||
} | |||||
static __inline void | static __inline void | ||||
nma_set_nrings(struct netmap_adapter *na, enum txrx t, u_int v) | nma_set_nrings(struct netmap_adapter *na, enum txrx t, u_int v) | ||||
{ | { | ||||
if (t == NR_TX) | if (t == NR_TX) | ||||
na->num_tx_rings = v; | na->num_tx_rings = v; | ||||
else | else | ||||
na->num_rx_rings = v; | na->num_rx_rings = v; | ||||
} | } | ||||
static __inline void | |||||
nma_set_host_nrings(struct netmap_adapter *na, enum txrx t, u_int v) | |||||
{ | |||||
if (t == NR_TX) | |||||
na->num_host_tx_rings = v; | |||||
else | |||||
na->num_host_rx_rings = v; | |||||
} | |||||
static __inline struct netmap_kring** | static __inline struct netmap_kring** | ||||
NMR(struct netmap_adapter *na, enum txrx t) | NMR(struct netmap_adapter *na, enum txrx t) | ||||
{ | { | ||||
return (t == NR_TX ? na->tx_rings : na->rx_rings); | return (t == NR_TX ? na->tx_rings : na->rx_rings); | ||||
} | } | ||||
int nma_intr_enable(struct netmap_adapter *na, int onoff); | int nma_intr_enable(struct netmap_adapter *na, int onoff); | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | #endif | ||||
int rxsg; | int rxsg; | ||||
/* Is the transmission path controlled by a netmap-aware | /* Is the transmission path controlled by a netmap-aware | ||||
* device queue (i.e. qdisc on linux)? */ | * device queue (i.e. qdisc on linux)? */ | ||||
int txqdisc; | int txqdisc; | ||||
}; | }; | ||||
#endif /* WITH_GENERIC */ | #endif /* WITH_GENERIC */ | ||||
static __inline int | static __inline u_int | ||||
netmap_real_rings(struct netmap_adapter *na, enum txrx t) | netmap_real_rings(struct netmap_adapter *na, enum txrx t) | ||||
{ | { | ||||
return nma_get_nrings(na, t) + !!(na->na_flags & NAF_HOST_RINGS); | return nma_get_nrings(na, t) + | ||||
!!(na->na_flags & NAF_HOST_RINGS) * nma_get_host_nrings(na, t); | |||||
} | } | ||||
#ifdef WITH_VALE | /* account for fake rings */ | ||||
static __inline u_int | |||||
netmap_all_rings(struct netmap_adapter *na, enum txrx t) | |||||
{ | |||||
return max(nma_get_nrings(na, t) + 1, netmap_real_rings(na, t)); | |||||
} | |||||
int netmap_default_bdg_attach(const char *name, struct netmap_adapter *na, | |||||
struct nm_bridge *); | |||||
struct nm_bdg_polling_state; | struct nm_bdg_polling_state; | ||||
/* | /* | ||||
* Bridge wrapper for non VALE ports attached to a VALE switch. | * Bridge wrapper for non VALE ports attached to a VALE switch. | ||||
* | * | ||||
* The real device must already have its own netmap adapter (hwna). | * The real device must already have its own netmap adapter (hwna). | ||||
* The bridge wrapper and the hwna adapter share the same set of | * The bridge wrapper and the hwna adapter share the same set of | ||||
* netmap rings and buffers, but they have two separate sets of | * netmap rings and buffers, but they have two separate sets of | ||||
* krings descriptors, with tx/rx meanings swapped: | * krings descriptors, with tx/rx meanings swapped: | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | struct netmap_bwrap_adapter { | ||||
/* we overwrite the hwna->na_vp pointer, so we save | /* we overwrite the hwna->na_vp pointer, so we save | ||||
* here its original value, to be restored at detach | * here its original value, to be restored at detach | ||||
*/ | */ | ||||
struct netmap_vp_adapter *saved_na_vp; | struct netmap_vp_adapter *saved_na_vp; | ||||
}; | }; | ||||
int nm_bdg_ctl_attach(struct nmreq_header *hdr, void *auth_token); | int nm_bdg_ctl_attach(struct nmreq_header *hdr, void *auth_token); | ||||
int nm_bdg_ctl_detach(struct nmreq_header *hdr, void *auth_token); | int nm_bdg_ctl_detach(struct nmreq_header *hdr, void *auth_token); | ||||
int nm_bdg_polling(struct nmreq_header *hdr); | int nm_bdg_polling(struct nmreq_header *hdr); | ||||
int netmap_bwrap_attach(const char *name, struct netmap_adapter *); | int netmap_bdg_list(struct nmreq_header *hdr); | ||||
#ifdef WITH_VALE | |||||
int netmap_vi_create(struct nmreq_header *hdr, int); | int netmap_vi_create(struct nmreq_header *hdr, int); | ||||
int nm_vi_create(struct nmreq_header *); | int nm_vi_create(struct nmreq_header *); | ||||
int nm_vi_destroy(const char *name); | int nm_vi_destroy(const char *name); | ||||
int netmap_bdg_list(struct nmreq_header *hdr); | |||||
#else /* !WITH_VALE */ | #else /* !WITH_VALE */ | ||||
#define netmap_vi_create(hdr, a) (EOPNOTSUPP) | #define netmap_vi_create(hdr, a) (EOPNOTSUPP) | ||||
#endif /* WITH_VALE */ | #endif /* WITH_VALE */ | ||||
#ifdef WITH_PIPES | #ifdef WITH_PIPES | ||||
#define NM_MAXPIPES 64 /* max number of pipes per adapter */ | #define NM_MAXPIPES 64 /* max number of pipes per adapter */ | ||||
▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | |||||
#define netmap_ifp_to_host_vp(_ifp) (NA(_ifp)->na_hostvp) | #define netmap_ifp_to_host_vp(_ifp) (NA(_ifp)->na_hostvp) | ||||
#define netmap_bdg_idx(_vp) ((_vp)->bdg_port) | #define netmap_bdg_idx(_vp) ((_vp)->bdg_port) | ||||
const char *netmap_bdg_name(struct netmap_vp_adapter *); | const char *netmap_bdg_name(struct netmap_vp_adapter *); | ||||
#else /* !WITH_VALE */ | #else /* !WITH_VALE */ | ||||
#define netmap_vp_to_ifp(_vp) NULL | #define netmap_vp_to_ifp(_vp) NULL | ||||
#define netmap_ifp_to_vp(_ifp) NULL | #define netmap_ifp_to_vp(_ifp) NULL | ||||
#define netmap_ifp_to_host_vp(_ifp) NULL | #define netmap_ifp_to_host_vp(_ifp) NULL | ||||
#define netmap_bdg_idx(_vp) -1 | #define netmap_bdg_idx(_vp) -1 | ||||
#define netmap_bdg_name(_vp) NULL | |||||
#endif /* WITH_VALE */ | #endif /* WITH_VALE */ | ||||
static inline int | static inline int | ||||
nm_netmap_on(struct netmap_adapter *na) | nm_netmap_on(struct netmap_adapter *na) | ||||
{ | { | ||||
return na && na->na_flags & NAF_NETMAP_ON; | return na && na->na_flags & NAF_NETMAP_ON; | ||||
} | } | ||||
Show All 14 Lines | |||||
{ | { | ||||
/* Process nr_mode and nr_pending_mode for host rings. */ | /* Process nr_mode and nr_pending_mode for host rings. */ | ||||
na->tx_rings[na->num_tx_rings]->nr_mode = | na->tx_rings[na->num_tx_rings]->nr_mode = | ||||
na->tx_rings[na->num_tx_rings]->nr_pending_mode; | na->tx_rings[na->num_tx_rings]->nr_pending_mode; | ||||
na->rx_rings[na->num_rx_rings]->nr_mode = | na->rx_rings[na->num_rx_rings]->nr_mode = | ||||
na->rx_rings[na->num_rx_rings]->nr_pending_mode; | na->rx_rings[na->num_rx_rings]->nr_pending_mode; | ||||
} | } | ||||
/* set/clear native flags and if_transmit/netdev_ops */ | void nm_set_native_flags(struct netmap_adapter *); | ||||
static inline void | void nm_clear_native_flags(struct netmap_adapter *); | ||||
nm_set_native_flags(struct netmap_adapter *na) | |||||
{ | |||||
struct ifnet *ifp = na->ifp; | |||||
/* We do the setup for intercepting packets only if we are the | |||||
* first user of this adapapter. */ | |||||
if (na->active_fds > 0) { | |||||
return; | |||||
} | |||||
na->na_flags |= NAF_NETMAP_ON; | |||||
#ifdef IFCAP_NETMAP /* or FreeBSD ? */ | |||||
ifp->if_capenable |= IFCAP_NETMAP; | |||||
#endif | |||||
#if defined (__FreeBSD__) | |||||
na->if_transmit = ifp->if_transmit; | |||||
ifp->if_transmit = netmap_transmit; | |||||
#elif defined (_WIN32) | |||||
(void)ifp; /* prevent a warning */ | |||||
#elif defined (linux) | |||||
na->if_transmit = (void *)ifp->netdev_ops; | |||||
ifp->netdev_ops = &((struct netmap_hw_adapter *)na)->nm_ndo; | |||||
((struct netmap_hw_adapter *)na)->save_ethtool = ifp->ethtool_ops; | |||||
ifp->ethtool_ops = &((struct netmap_hw_adapter*)na)->nm_eto; | |||||
#endif /* linux */ | |||||
nm_update_hostrings_mode(na); | |||||
} | |||||
static inline void | |||||
nm_clear_native_flags(struct netmap_adapter *na) | |||||
{ | |||||
struct ifnet *ifp = na->ifp; | |||||
/* We undo the setup for intercepting packets only if we are the | |||||
* last user of this adapapter. */ | |||||
if (na->active_fds > 0) { | |||||
return; | |||||
} | |||||
nm_update_hostrings_mode(na); | |||||
#if defined(__FreeBSD__) | |||||
ifp->if_transmit = na->if_transmit; | |||||
#elif defined(_WIN32) | |||||
(void)ifp; /* prevent a warning */ | |||||
#else | |||||
ifp->netdev_ops = (void *)na->if_transmit; | |||||
ifp->ethtool_ops = ((struct netmap_hw_adapter*)na)->save_ethtool; | |||||
#endif | |||||
na->na_flags &= ~NAF_NETMAP_ON; | |||||
#ifdef IFCAP_NETMAP /* or FreeBSD ? */ | |||||
ifp->if_capenable &= ~IFCAP_NETMAP; | |||||
#endif | |||||
} | |||||
#ifdef linux | |||||
int netmap_linux_config(struct netmap_adapter *na, | |||||
struct nm_config_info *info); | |||||
#endif /* linux */ | |||||
/* | /* | ||||
* nm_*sync_prologue() functions are used in ioctl/poll and ptnetmap | * nm_*sync_prologue() functions are used in ioctl/poll and ptnetmap | ||||
* kthreads. | * kthreads. | ||||
* We need netmap_ring* parameter, because in ptnetmap it is decoupled | * We need netmap_ring* parameter, because in ptnetmap it is decoupled | ||||
* from host kring. | * from host kring. | ||||
* The user-space ring pointers (head/cur/tail) are shared through | * The user-space ring pointers (head/cur/tail) are shared through | ||||
* CSB between host and guest. | * CSB between host and guest. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | |||||
u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); | u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); | ||||
int netmap_get_na(struct nmreq_header *hdr, struct netmap_adapter **na, | int netmap_get_na(struct nmreq_header *hdr, struct netmap_adapter **na, | ||||
struct ifnet **ifp, struct netmap_mem_d *nmd, int create); | struct ifnet **ifp, struct netmap_mem_d *nmd, int create); | ||||
void netmap_unget_na(struct netmap_adapter *na, struct ifnet *ifp); | void netmap_unget_na(struct netmap_adapter *na, struct ifnet *ifp); | ||||
int netmap_get_hw_na(struct ifnet *ifp, | int netmap_get_hw_na(struct ifnet *ifp, | ||||
struct netmap_mem_d *nmd, struct netmap_adapter **na); | struct netmap_mem_d *nmd, struct netmap_adapter **na); | ||||
#ifdef WITH_VALE | |||||
/* | /* | ||||
* The following bridge-related functions are used by other | * The following bridge-related functions are used by other | ||||
* kernel modules. | * kernel modules. | ||||
* | * | ||||
* VALE only supports unicast or broadcast. The lookup | * VALE only supports unicast or broadcast. The lookup | ||||
* function can return 0 .. NM_BDG_MAXPORTS-1 for regular ports, | * function can return 0 .. NM_BDG_MAXPORTS-1 for regular ports, | ||||
* NM_BDG_MAXPORTS for broadcast, NM_BDG_MAXPORTS+1 to indicate | * NM_BDG_MAXPORTS for broadcast, NM_BDG_MAXPORTS+1 to indicate | ||||
* drop. | * drop. | ||||
*/ | */ | ||||
typedef uint32_t (*bdg_lookup_fn_t)(struct nm_bdg_fwd *ft, uint8_t *ring_nr, | typedef uint32_t (*bdg_lookup_fn_t)(struct nm_bdg_fwd *ft, uint8_t *ring_nr, | ||||
struct netmap_vp_adapter *, void *private_data); | struct netmap_vp_adapter *, void *private_data); | ||||
typedef int (*bdg_config_fn_t)(struct nm_ifreq *); | typedef int (*bdg_config_fn_t)(struct nm_ifreq *); | ||||
typedef void (*bdg_dtor_fn_t)(const struct netmap_vp_adapter *); | typedef void (*bdg_dtor_fn_t)(const struct netmap_vp_adapter *); | ||||
typedef void *(*bdg_update_private_data_fn_t)(void *private_data, void *callback_data, int *error); | typedef void *(*bdg_update_private_data_fn_t)(void *private_data, void *callback_data, int *error); | ||||
typedef int (*bdg_vp_create_fn_t)(struct nmreq_header *hdr, | |||||
struct ifnet *ifp, struct netmap_mem_d *nmd, | |||||
struct netmap_vp_adapter **ret); | |||||
typedef int (*bdg_bwrap_attach_fn_t)(const char *nr_name, struct netmap_adapter *hwna); | |||||
struct netmap_bdg_ops { | struct netmap_bdg_ops { | ||||
bdg_lookup_fn_t lookup; | bdg_lookup_fn_t lookup; | ||||
bdg_config_fn_t config; | bdg_config_fn_t config; | ||||
bdg_dtor_fn_t dtor; | bdg_dtor_fn_t dtor; | ||||
bdg_vp_create_fn_t vp_create; | |||||
bdg_bwrap_attach_fn_t bwrap_attach; | |||||
char name[IFNAMSIZ]; | |||||
}; | }; | ||||
int netmap_bwrap_attach(const char *name, struct netmap_adapter *, struct netmap_bdg_ops *); | |||||
int netmap_bdg_regops(const char *name, struct netmap_bdg_ops *bdg_ops, void *private_data, void *auth_token); | |||||
uint32_t netmap_bdg_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring, | |||||
struct netmap_vp_adapter *, void *private_data); | |||||
#define NM_BRIDGES 8 /* number of bridges */ | #define NM_BRIDGES 8 /* number of bridges */ | ||||
#define NM_BDG_MAXPORTS 254 /* up to 254 */ | #define NM_BDG_MAXPORTS 254 /* up to 254 */ | ||||
#define NM_BDG_BROADCAST NM_BDG_MAXPORTS | #define NM_BDG_BROADCAST NM_BDG_MAXPORTS | ||||
#define NM_BDG_NOPORT (NM_BDG_MAXPORTS+1) | #define NM_BDG_NOPORT (NM_BDG_MAXPORTS+1) | ||||
/* these are redefined in case of no VALE support */ | |||||
int netmap_get_bdg_na(struct nmreq_header *hdr, struct netmap_adapter **na, | |||||
struct netmap_mem_d *nmd, int create); | |||||
struct nm_bridge *netmap_init_bridges2(u_int); | struct nm_bridge *netmap_init_bridges2(u_int); | ||||
void netmap_uninit_bridges2(struct nm_bridge *, u_int); | void netmap_uninit_bridges2(struct nm_bridge *, u_int); | ||||
int netmap_init_bridges(void); | int netmap_init_bridges(void); | ||||
void netmap_uninit_bridges(void); | void netmap_uninit_bridges(void); | ||||
int netmap_bdg_regops(const char *name, struct netmap_bdg_ops *bdg_ops, void *private_data, void *auth_token); | |||||
int nm_bdg_update_private_data(const char *name, bdg_update_private_data_fn_t callback, | int nm_bdg_update_private_data(const char *name, bdg_update_private_data_fn_t callback, | ||||
void *callback_data, void *auth_token); | void *callback_data, void *auth_token); | ||||
int netmap_bdg_config(struct nm_ifreq *nifr); | int netmap_bdg_config(struct nm_ifreq *nifr); | ||||
void *netmap_bdg_create(const char *bdg_name, int *return_status); | |||||
int netmap_bdg_destroy(const char *bdg_name, void *auth_token); | |||||
#ifdef WITH_VALE | |||||
uint32_t netmap_bdg_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring, | |||||
struct netmap_vp_adapter *, void *private_data); | |||||
/* these are redefined in case of no VALE support */ | |||||
int netmap_get_vale_na(struct nmreq_header *hdr, struct netmap_adapter **na, | |||||
struct netmap_mem_d *nmd, int create); | |||||
void *netmap_vale_create(const char *bdg_name, int *return_status); | |||||
int netmap_vale_destroy(const char *bdg_name, void *auth_token); | |||||
#else /* !WITH_VALE */ | #else /* !WITH_VALE */ | ||||
#define netmap_get_bdg_na(_1, _2, _3, _4) 0 | #define netmap_bdg_learning(_1, _2, _3, _4) 0 | ||||
#define netmap_init_bridges(_1) 0 | #define netmap_get_vale_na(_1, _2, _3, _4) 0 | ||||
#define netmap_uninit_bridges() | #define netmap_bdg_create(_1, _2) NULL | ||||
#define netmap_bdg_regops(_1, _2) EINVAL | #define netmap_bdg_destroy(_1, _2) 0 | ||||
#endif /* !WITH_VALE */ | #endif /* !WITH_VALE */ | ||||
#ifdef WITH_PIPES | #ifdef WITH_PIPES | ||||
/* max number of pipes per device */ | /* max number of pipes per device */ | ||||
#define NM_MAXPIPES 64 /* XXX this should probably be a sysctl */ | #define NM_MAXPIPES 64 /* XXX this should probably be a sysctl */ | ||||
void netmap_pipe_dealloc(struct netmap_adapter *); | void netmap_pipe_dealloc(struct netmap_adapter *); | ||||
int netmap_get_pipe_na(struct nmreq_header *hdr, struct netmap_adapter **na, | int netmap_get_pipe_na(struct nmreq_header *hdr, struct netmap_adapter **na, | ||||
struct netmap_mem_d *nmd, int create); | struct netmap_mem_d *nmd, int create); | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | enum { /* verbose flags */ | ||||
NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ | NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ | ||||
NM_VERB_TXINTR = 0x200, | NM_VERB_TXINTR = 0x200, | ||||
NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ | NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ | ||||
NM_VERB_NIC_TXSYNC = 0x2000, | NM_VERB_NIC_TXSYNC = 0x2000, | ||||
}; | }; | ||||
extern int netmap_txsync_retry; | extern int netmap_txsync_retry; | ||||
extern int netmap_flags; | extern int netmap_flags; | ||||
extern int netmap_generic_hwcsum; | |||||
extern int netmap_generic_mit; | extern int netmap_generic_mit; | ||||
extern int netmap_generic_ringsize; | extern int netmap_generic_ringsize; | ||||
extern int netmap_generic_rings; | extern int netmap_generic_rings; | ||||
#ifdef linux | #ifdef linux | ||||
extern int netmap_generic_txqdisc; | extern int netmap_generic_txqdisc; | ||||
#endif | #endif | ||||
extern int ptnetmap_tx_workers; | extern int ptnetmap_tx_workers; | ||||
/* | /* | ||||
* NA returns a pointer to the struct netmap adapter from the ifp, | * NA returns a pointer to the struct netmap adapter from the ifp. | ||||
* WNA is used to write it. | * WNA is os-specific and must be defined in glue code. | ||||
*/ | */ | ||||
#define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) | #define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) | ||||
/* | /* | ||||
* we provide a default implementation of NM_ATTACH_NA/NM_DETACH_NA | |||||
* based on the WNA field. | |||||
* Glue code may override this by defining its own NM_ATTACH_NA | |||||
*/ | |||||
#ifndef NM_ATTACH_NA | |||||
/* | |||||
* On old versions of FreeBSD, NA(ifp) is a pspare. On linux we | * On old versions of FreeBSD, NA(ifp) is a pspare. On linux we | ||||
* overload another pointer in the netdev. | * overload another pointer in the netdev. | ||||
* | * | ||||
* We check if NA(ifp) is set and its first element has a related | * We check if NA(ifp) is set and its first element has a related | ||||
* magic value. The capenable is within the struct netmap_adapter. | * magic value. The capenable is within the struct netmap_adapter. | ||||
*/ | */ | ||||
#define NETMAP_MAGIC 0x52697a7a | #define NETMAP_MAGIC 0x52697a7a | ||||
#define NM_NA_VALID(ifp) (NA(ifp) && \ | #define NM_NA_VALID(ifp) (NA(ifp) && \ | ||||
((uint32_t)(uintptr_t)NA(ifp) ^ NA(ifp)->magic) == NETMAP_MAGIC ) | ((uint32_t)(uintptr_t)NA(ifp) ^ NA(ifp)->magic) == NETMAP_MAGIC ) | ||||
#define NM_ATTACH_NA(ifp, na) do { \ | #define NM_ATTACH_NA(ifp, na) do { \ | ||||
WNA(ifp) = na; \ | WNA(ifp) = na; \ | ||||
if (NA(ifp)) \ | if (NA(ifp)) \ | ||||
NA(ifp)->magic = \ | NA(ifp)->magic = \ | ||||
((uint32_t)(uintptr_t)NA(ifp)) ^ NETMAP_MAGIC; \ | ((uint32_t)(uintptr_t)NA(ifp)) ^ NETMAP_MAGIC; \ | ||||
} while(0) | } while(0) | ||||
#define NM_RESTORE_NA(ifp, na) WNA(ifp) = na; | |||||
#define NM_DETACH_NA(ifp) do { WNA(ifp) = NULL; } while (0) | |||||
#define NM_NA_CLASH(ifp) (NA(ifp) && !NM_NA_VALID(ifp)) | |||||
#endif /* !NM_ATTACH_NA */ | |||||
#define NM_IS_NATIVE(ifp) (NM_NA_VALID(ifp) && NA(ifp)->nm_dtor == netmap_hw_dtor) | #define NM_IS_NATIVE(ifp) (NM_NA_VALID(ifp) && NA(ifp)->nm_dtor == netmap_hw_dtor) | ||||
#if defined(__FreeBSD__) | #if defined(__FreeBSD__) | ||||
/* Assigns the device IOMMU domain to an allocator. | /* Assigns the device IOMMU domain to an allocator. | ||||
* Returns -ENOMEM in case the domain is different */ | * Returns -ENOMEM in case the domain is different */ | ||||
#define nm_iommu_group_id(dev) (0) | #define nm_iommu_group_id(dev) (0) | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | netmap_unload_map(struct netmap_adapter *na, | ||||
bus_dma_tag_t tag, bus_dmamap_t map, u_int sz) | bus_dma_tag_t tag, bus_dmamap_t map, u_int sz) | ||||
{ | { | ||||
if (*map) { | if (*map) { | ||||
dma_unmap_single(na->pdev, *map, sz, | dma_unmap_single(na->pdev, *map, sz, | ||||
DMA_BIDIRECTIONAL); | DMA_BIDIRECTIONAL); | ||||
} | } | ||||
} | } | ||||
#ifdef NETMAP_LINUX_HAVE_DMASYNC | |||||
static inline void | static inline void | ||||
netmap_sync_map(struct netmap_adapter *na, | netmap_sync_map_cpu(struct netmap_adapter *na, | ||||
bus_dma_tag_t tag, bus_dmamap_t map, u_int sz, enum txrx t) | bus_dma_tag_t tag, bus_dmamap_t map, u_int sz, enum txrx t) | ||||
{ | { | ||||
if (*map) { | if (*map) { | ||||
if (t == NR_RX) | |||||
dma_sync_single_for_cpu(na->pdev, *map, sz, | dma_sync_single_for_cpu(na->pdev, *map, sz, | ||||
DMA_FROM_DEVICE); | (t == NR_TX ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); | ||||
else | } | ||||
} | |||||
static inline void | |||||
netmap_sync_map_dev(struct netmap_adapter *na, | |||||
bus_dma_tag_t tag, bus_dmamap_t map, u_int sz, enum txrx t) | |||||
{ | |||||
if (*map) { | |||||
dma_sync_single_for_device(na->pdev, *map, sz, | dma_sync_single_for_device(na->pdev, *map, sz, | ||||
DMA_TO_DEVICE); | (t == NR_TX ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); | ||||
} | } | ||||
} | } | ||||
static inline void | static inline void | ||||
netmap_reload_map(struct netmap_adapter *na, | netmap_reload_map(struct netmap_adapter *na, | ||||
bus_dma_tag_t tag, bus_dmamap_t map, void *buf) | bus_dma_tag_t tag, bus_dmamap_t map, void *buf) | ||||
{ | { | ||||
u_int sz = NETMAP_BUF_SIZE(na); | u_int sz = NETMAP_BUF_SIZE(na); | ||||
if (*map) { | if (*map) { | ||||
dma_unmap_single(na->pdev, *map, sz, | dma_unmap_single(na->pdev, *map, sz, | ||||
DMA_BIDIRECTIONAL); | DMA_BIDIRECTIONAL); | ||||
} | } | ||||
*map = dma_map_single(na->pdev, buf, sz, | *map = dma_map_single(na->pdev, buf, sz, | ||||
DMA_BIDIRECTIONAL); | DMA_BIDIRECTIONAL); | ||||
} | } | ||||
#else /* !NETMAP_LINUX_HAVE_DMASYNC */ | |||||
#define netmap_sync_map_cpu(na, tag, map, sz, t) | |||||
#define netmap_sync_map_dev(na, tag, map, sz, t) | |||||
#endif /* NETMAP_LINUX_HAVE_DMASYNC */ | |||||
#endif /* linux */ | #endif /* linux */ | ||||
/* | /* | ||||
* functions to map NIC to KRING indexes (n2k) and vice versa (k2n) | * functions to map NIC to KRING indexes (n2k) and vice versa (k2n) | ||||
*/ | */ | ||||
static inline int | static inline int | ||||
▲ Show 20 Lines • Show All 424 Lines • ▼ Show 20 Lines | bool netmap_pt_guest_txsync(struct ptnet_csb_gh *ptgh, | ||||
int flags); | int flags); | ||||
bool netmap_pt_guest_rxsync(struct ptnet_csb_gh *ptgh, | bool netmap_pt_guest_rxsync(struct ptnet_csb_gh *ptgh, | ||||
struct ptnet_csb_hg *pthg, | struct ptnet_csb_hg *pthg, | ||||
struct netmap_kring *kring, int flags); | struct netmap_kring *kring, int flags); | ||||
int ptnet_nm_krings_create(struct netmap_adapter *na); | int ptnet_nm_krings_create(struct netmap_adapter *na); | ||||
void ptnet_nm_krings_delete(struct netmap_adapter *na); | void ptnet_nm_krings_delete(struct netmap_adapter *na); | ||||
void ptnet_nm_dtor(struct netmap_adapter *na); | void ptnet_nm_dtor(struct netmap_adapter *na); | ||||
#endif /* WITH_PTNETMAP_GUEST */ | #endif /* WITH_PTNETMAP_GUEST */ | ||||
#ifdef __FreeBSD__ | |||||
/* | |||||
* 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 */ | |||||
#endif /* __FreeBSD__ */ | |||||
struct nmreq_option * nmreq_findoption(struct nmreq_option *, uint16_t); | struct nmreq_option * nmreq_findoption(struct nmreq_option *, uint16_t); | ||||
int nmreq_checkduplicate(struct nmreq_option *); | int nmreq_checkduplicate(struct nmreq_option *); | ||||
#endif /* _NET_NETMAP_KERN_H_ */ | #endif /* _NET_NETMAP_KERN_H_ */ |