Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/netmap/netmap.c
Show First 20 Lines • Show All 515 Lines • ▼ Show 20 Lines | |||||
#ifdef linux | #ifdef linux | ||||
int netmap_generic_txqdisc = 1; | int netmap_generic_txqdisc = 1; | ||||
#endif | #endif | ||||
/* Default number of slots and queues for generic adapters. */ | /* Default number of slots and queues for generic adapters. */ | ||||
int netmap_generic_ringsize = 1024; | int netmap_generic_ringsize = 1024; | ||||
int netmap_generic_rings = 1; | int netmap_generic_rings = 1; | ||||
/* Non-zero to enable checksum offloading in NIC drivers */ | |||||
int netmap_generic_hwcsum = 0; | |||||
/* Non-zero if ptnet devices are allowed to use virtio-net headers. */ | /* Non-zero if ptnet devices are allowed to use virtio-net headers. */ | ||||
int ptnet_vnet_hdr = 1; | int ptnet_vnet_hdr = 1; | ||||
/* 0 if ptnetmap should not use worker threads for TX processing */ | /* 0 if ptnetmap should not use worker threads for TX processing */ | ||||
int ptnetmap_tx_workers = 1; | int ptnetmap_tx_workers = 1; | ||||
/* | /* | ||||
* SYSCTL calls are grouped between SYSBEGIN and SYSEND to be emulated | * SYSCTL calls are grouped between SYSBEGIN and SYSEND to be emulated | ||||
Show All 12 Lines | |||||
SYSCTL_INT(_dev_netmap, OID_AUTO, txsync_retry, CTLFLAG_RW, | SYSCTL_INT(_dev_netmap, OID_AUTO, txsync_retry, CTLFLAG_RW, | ||||
&netmap_txsync_retry, 0, "Number of txsync loops in bridge's flush."); | &netmap_txsync_retry, 0, "Number of txsync loops in bridge's flush."); | ||||
SYSCTL_INT(_dev_netmap, OID_AUTO, fwd, CTLFLAG_RW, &netmap_fwd, 0, | SYSCTL_INT(_dev_netmap, OID_AUTO, fwd, CTLFLAG_RW, &netmap_fwd, 0, | ||||
"Force NR_FORWARD mode"); | "Force NR_FORWARD mode"); | ||||
SYSCTL_INT(_dev_netmap, OID_AUTO, admode, CTLFLAG_RW, &netmap_admode, 0, | SYSCTL_INT(_dev_netmap, OID_AUTO, admode, CTLFLAG_RW, &netmap_admode, 0, | ||||
"Adapter mode. 0 selects the best option available," | "Adapter mode. 0 selects the best option available," | ||||
"1 forces native adapter, 2 forces emulated adapter"); | "1 forces native adapter, 2 forces emulated adapter"); | ||||
SYSCTL_INT(_dev_netmap, OID_AUTO, generic_hwcsum, CTLFLAG_RW, &netmap_generic_hwcsum, | |||||
0, "Hardware checksums. 0 to disable checksum generation by the NIC (default)," | |||||
"1 to enable checksum generation by the NIC"); | |||||
SYSCTL_INT(_dev_netmap, OID_AUTO, generic_mit, CTLFLAG_RW, &netmap_generic_mit, | SYSCTL_INT(_dev_netmap, OID_AUTO, generic_mit, CTLFLAG_RW, &netmap_generic_mit, | ||||
0, "RX notification interval in nanoseconds"); | 0, "RX notification interval in nanoseconds"); | ||||
SYSCTL_INT(_dev_netmap, OID_AUTO, generic_ringsize, CTLFLAG_RW, | SYSCTL_INT(_dev_netmap, OID_AUTO, generic_ringsize, CTLFLAG_RW, | ||||
&netmap_generic_ringsize, 0, | &netmap_generic_ringsize, 0, | ||||
"Number of per-ring slots for emulated netmap mode"); | "Number of per-ring slots for emulated netmap mode"); | ||||
SYSCTL_INT(_dev_netmap, OID_AUTO, generic_rings, CTLFLAG_RW, | SYSCTL_INT(_dev_netmap, OID_AUTO, generic_rings, CTLFLAG_RW, | ||||
&netmap_generic_rings, 0, | &netmap_generic_rings, 0, | ||||
"Number of TX/RX queues for emulated netmap adapters"); | "Number of TX/RX queues for emulated netmap adapters"); | ||||
▲ Show 20 Lines • Show All 262 Lines • ▼ Show 20 Lines | netmap_krings_create(struct netmap_adapter *na, u_int tailroom) | ||||
enum txrx t; | enum txrx t; | ||||
if (na->tx_rings != NULL) { | if (na->tx_rings != NULL) { | ||||
D("warning: krings were already created"); | D("warning: krings were already created"); | ||||
return 0; | return 0; | ||||
} | } | ||||
/* account for the (possibly fake) host rings */ | /* account for the (possibly fake) host rings */ | ||||
n[NR_TX] = na->num_tx_rings + 1; | n[NR_TX] = netmap_all_rings(na, NR_TX); | ||||
n[NR_RX] = na->num_rx_rings + 1; | n[NR_RX] = netmap_all_rings(na, NR_RX); | ||||
len = (n[NR_TX] + n[NR_RX]) * | len = (n[NR_TX] + n[NR_RX]) * | ||||
(sizeof(struct netmap_kring) + sizeof(struct netmap_kring *)) | (sizeof(struct netmap_kring) + sizeof(struct netmap_kring *)) | ||||
+ tailroom; | + tailroom; | ||||
na->tx_rings = nm_os_malloc((size_t)len); | na->tx_rings = nm_os_malloc((size_t)len); | ||||
if (na->tx_rings == NULL) { | if (na->tx_rings == NULL) { | ||||
D("Cannot allocate krings"); | D("Cannot allocate krings"); | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
* Destructor for NIC ports. They also have an mbuf queue | * Destructor for NIC ports. They also have an mbuf queue | ||||
* on the rings connected to the host so we need to purge | * on the rings connected to the host so we need to purge | ||||
* them first. | * them first. | ||||
*/ | */ | ||||
/* call with NMG_LOCK held */ | /* call with NMG_LOCK held */ | ||||
void | void | ||||
netmap_hw_krings_delete(struct netmap_adapter *na) | netmap_hw_krings_delete(struct netmap_adapter *na) | ||||
{ | { | ||||
struct mbq *q = &na->rx_rings[na->num_rx_rings]->rx_queue; | u_int lim = netmap_real_rings(na, NR_RX), i; | ||||
for (i = nma_get_nrings(na, NR_RX); i < lim; i++) { | |||||
struct mbq *q = &NMR(na, NR_RX)[i]->rx_queue; | |||||
ND("destroy sw mbq with len %d", mbq_len(q)); | ND("destroy sw mbq with len %d", mbq_len(q)); | ||||
mbq_purge(q); | mbq_purge(q); | ||||
mbq_safe_fini(q); | mbq_safe_fini(q); | ||||
} | |||||
netmap_krings_delete(na); | netmap_krings_delete(na); | ||||
} | } | ||||
static void | static void | ||||
netmap_mem_drop(struct netmap_adapter *na) | netmap_mem_drop(struct netmap_adapter *na) | ||||
{ | { | ||||
int last = netmap_mem_deref(na->nm_mem, na); | int last = netmap_mem_deref(na->nm_mem, na); | ||||
/* if the native allocator had been overrided on regif, | /* if the native allocator had been overrided on regif, | ||||
▲ Show 20 Lines • Show All 584 Lines • ▼ Show 20 Lines | if (error || *na != NULL) | ||||
goto out; | goto out; | ||||
/* try to see if this is a pipe port */ | /* try to see if this is a pipe port */ | ||||
error = netmap_get_pipe_na(hdr, na, nmd, create); | error = netmap_get_pipe_na(hdr, na, nmd, create); | ||||
if (error || *na != NULL) | if (error || *na != NULL) | ||||
goto out; | goto out; | ||||
/* try to see if this is a bridge port */ | /* try to see if this is a bridge port */ | ||||
error = netmap_get_bdg_na(hdr, na, nmd, create); | error = netmap_get_vale_na(hdr, na, nmd, create); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
if (*na != NULL) /* valid match in netmap_get_bdg_na() */ | if (*na != NULL) /* valid match in netmap_get_bdg_na() */ | ||||
goto out; | goto out; | ||||
/* | /* | ||||
* This must be a hardware na, lookup the name in the system. | * This must be a hardware na, lookup the name in the system. | ||||
▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | for_rx_tx(t) { | ||||
case NR_REG_SW: | case NR_REG_SW: | ||||
case NR_REG_NIC_SW: | case NR_REG_NIC_SW: | ||||
if (!(na->na_flags & NAF_HOST_RINGS)) { | if (!(na->na_flags & NAF_HOST_RINGS)) { | ||||
D("host rings not supported"); | D("host rings not supported"); | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
priv->np_qfirst[t] = (nr_mode == NR_REG_SW ? | priv->np_qfirst[t] = (nr_mode == NR_REG_SW ? | ||||
nma_get_nrings(na, t) : 0); | nma_get_nrings(na, t) : 0); | ||||
priv->np_qlast[t] = nma_get_nrings(na, t) + 1; | priv->np_qlast[t] = netmap_all_rings(na, t); | ||||
ND("%s: %s %d %d", nr_mode == NR_REG_SW ? "SW" : "NIC+SW", | ND("%s: %s %d %d", nr_mode == NR_REG_SW ? "SW" : "NIC+SW", | ||||
nm_txrx2str(t), | nm_txrx2str(t), | ||||
priv->np_qfirst[t], priv->np_qlast[t]); | priv->np_qfirst[t], priv->np_qlast[t]); | ||||
break; | break; | ||||
case NR_REG_ONE_NIC: | case NR_REG_ONE_NIC: | ||||
if (nr_ringid >= na->num_tx_rings && | if (nr_ringid >= na->num_tx_rings && | ||||
nr_ringid >= na->num_rx_rings) { | nr_ringid >= na->num_rx_rings) { | ||||
D("invalid ring id %d", nr_ringid); | D("invalid ring id %d", nr_ringid); | ||||
▲ Show 20 Lines • Show All 699 Lines • ▼ Show 20 Lines | case NETMAP_REQ_PORT_HDR_SET: { | ||||
req->nr_hdr_len != sizeof(struct nm_vnet_hdr) && | req->nr_hdr_len != sizeof(struct nm_vnet_hdr) && | ||||
req->nr_hdr_len != 12) { | req->nr_hdr_len != 12) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
NMG_LOCK(); | NMG_LOCK(); | ||||
hdr->nr_reqtype = NETMAP_REQ_REGISTER; | hdr->nr_reqtype = NETMAP_REQ_REGISTER; | ||||
hdr->nr_body = (uintptr_t)®req; | hdr->nr_body = (uintptr_t)®req; | ||||
error = netmap_get_bdg_na(hdr, &na, NULL, 0); | error = netmap_get_vale_na(hdr, &na, NULL, 0); | ||||
hdr->nr_reqtype = NETMAP_REQ_PORT_HDR_SET; | hdr->nr_reqtype = NETMAP_REQ_PORT_HDR_SET; | ||||
hdr->nr_body = (uintptr_t)req; | hdr->nr_body = (uintptr_t)req; | ||||
if (na && !error) { | if (na && !error) { | ||||
struct netmap_vp_adapter *vpna = | struct netmap_vp_adapter *vpna = | ||||
(struct netmap_vp_adapter *)na; | (struct netmap_vp_adapter *)na; | ||||
na->virt_hdr_len = req->nr_hdr_len; | na->virt_hdr_len = req->nr_hdr_len; | ||||
if (na->virt_hdr_len) { | if (na->virt_hdr_len) { | ||||
vpna->mfs = NETMAP_BUF_SIZE(na); | vpna->mfs = NETMAP_BUF_SIZE(na); | ||||
▲ Show 20 Lines • Show All 776 Lines • ▼ Show 20 Lines | netmap_attach_common(struct netmap_adapter *na) | ||||
} | } | ||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
if (na->na_flags & NAF_HOST_RINGS && na->ifp) { | if (na->na_flags & NAF_HOST_RINGS && na->ifp) { | ||||
na->if_input = na->ifp->if_input; /* for netmap_send_up */ | na->if_input = na->ifp->if_input; /* for netmap_send_up */ | ||||
} | } | ||||
na->pdev = na; /* make sure netmap_mem_map() is called */ | na->pdev = na; /* make sure netmap_mem_map() is called */ | ||||
#endif /* __FreeBSD__ */ | #endif /* __FreeBSD__ */ | ||||
if (na->na_flags & NAF_HOST_RINGS) { | |||||
if (na->num_host_rx_rings == 0) | |||||
na->num_host_rx_rings = 1; | |||||
if (na->num_host_tx_rings == 0) | |||||
na->num_host_tx_rings = 1; | |||||
} | |||||
if (na->nm_krings_create == NULL) { | if (na->nm_krings_create == NULL) { | ||||
/* we assume that we have been called by a driver, | /* we assume that we have been called by a driver, | ||||
* since other port types all provide their own | * since other port types all provide their own | ||||
* nm_krings_create | * nm_krings_create | ||||
*/ | */ | ||||
na->nm_krings_create = netmap_hw_krings_create; | na->nm_krings_create = netmap_hw_krings_create; | ||||
na->nm_krings_delete = netmap_hw_krings_delete; | na->nm_krings_delete = netmap_hw_krings_delete; | ||||
} | } | ||||
if (na->nm_notify == NULL) | if (na->nm_notify == NULL) | ||||
na->nm_notify = netmap_notify; | na->nm_notify = netmap_notify; | ||||
na->active_fds = 0; | na->active_fds = 0; | ||||
if (na->nm_mem == NULL) { | if (na->nm_mem == NULL) { | ||||
/* use the global allocator */ | /* use the global allocator */ | ||||
na->nm_mem = netmap_mem_get(&nm_mem); | na->nm_mem = netmap_mem_get(&nm_mem); | ||||
} | } | ||||
#ifdef WITH_VALE | #ifdef WITH_VALE | ||||
if (na->nm_bdg_attach == NULL) | if (na->nm_bdg_attach == NULL) | ||||
/* no special nm_bdg_attach callback. On VALE | /* no special nm_bdg_attach callback. On VALE | ||||
* attach, we need to interpose a bwrap | * attach, we need to interpose a bwrap | ||||
*/ | */ | ||||
na->nm_bdg_attach = netmap_bwrap_attach; | na->nm_bdg_attach = netmap_default_bdg_attach; | ||||
#endif | #endif | ||||
return 0; | return 0; | ||||
} | } | ||||
/* Wrapper for the register callback provided netmap-enabled | /* Wrapper for the register callback provided netmap-enabled | ||||
* hardware drivers. | * hardware drivers. | ||||
* nm_iszombie(na) means that the driver module has been | * nm_iszombie(na) means that the driver module has been | ||||
Show All 25 Lines | out: | ||||
nm_os_ifnet_unlock(); | nm_os_ifnet_unlock(); | ||||
return error; | return error; | ||||
} | } | ||||
static void | static void | ||||
netmap_hw_dtor(struct netmap_adapter *na) | netmap_hw_dtor(struct netmap_adapter *na) | ||||
{ | { | ||||
if (nm_iszombie(na) || na->ifp == NULL) | if (na->ifp == NULL) | ||||
return; | return; | ||||
WNA(na->ifp) = NULL; | NM_DETACH_NA(na->ifp); | ||||
} | } | ||||
/* | /* | ||||
* Allocate a netmap_adapter object, and initialize it from the | * Allocate a netmap_adapter object, and initialize it from the | ||||
* 'arg' passed by the driver on attach. | * 'arg' passed by the driver on attach. | ||||
* We allocate a block of memory of 'size' bytes, which has room | * We allocate a block of memory of 'size' bytes, which has room | ||||
* for struct netmap_adapter plus additional room private to | * for struct netmap_adapter plus additional room private to | ||||
* the caller. | * the caller. | ||||
* Return 0 on success, ENOMEM otherwise. | * Return 0 on success, ENOMEM otherwise. | ||||
*/ | */ | ||||
int | int | ||||
netmap_attach_ext(struct netmap_adapter *arg, size_t size, int override_reg) | netmap_attach_ext(struct netmap_adapter *arg, size_t size, int override_reg) | ||||
{ | { | ||||
struct netmap_hw_adapter *hwna = NULL; | struct netmap_hw_adapter *hwna = NULL; | ||||
struct ifnet *ifp = NULL; | struct ifnet *ifp = NULL; | ||||
if (size < sizeof(struct netmap_hw_adapter)) { | if (size < sizeof(struct netmap_hw_adapter)) { | ||||
D("Invalid netmap adapter size %d", (int)size); | D("Invalid netmap adapter size %d", (int)size); | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
if (arg == NULL || arg->ifp == NULL) | if (arg == NULL || arg->ifp == NULL) | ||||
goto fail; | return EINVAL; | ||||
ifp = arg->ifp; | ifp = arg->ifp; | ||||
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 10 Lines | netmap_attach_ext(struct netmap_adapter *arg, size_t size, int override_reg) | ||||
if (netmap_attach_common(&hwna->up)) { | if (netmap_attach_common(&hwna->up)) { | ||||
nm_os_free(hwna); | nm_os_free(hwna); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
netmap_adapter_get(&hwna->up); | netmap_adapter_get(&hwna->up); | ||||
NM_ATTACH_NA(ifp, &hwna->up); | NM_ATTACH_NA(ifp, &hwna->up); | ||||
#ifdef linux | nm_os_onattach(ifp); | ||||
if (ifp->netdev_ops) { | |||||
/* prepare a clone of the netdev ops */ | |||||
#ifndef NETMAP_LINUX_HAVE_NETDEV_OPS | |||||
hwna->nm_ndo.ndo_start_xmit = ifp->netdev_ops; | |||||
#else | |||||
hwna->nm_ndo = *ifp->netdev_ops; | |||||
#endif /* NETMAP_LINUX_HAVE_NETDEV_OPS */ | |||||
} | |||||
hwna->nm_ndo.ndo_start_xmit = linux_netmap_start_xmit; | |||||
hwna->nm_ndo.ndo_change_mtu = linux_netmap_change_mtu; | |||||
if (ifp->ethtool_ops) { | |||||
hwna->nm_eto = *ifp->ethtool_ops; | |||||
} | |||||
hwna->nm_eto.set_ringparam = linux_netmap_set_ringparam; | |||||
#ifdef NETMAP_LINUX_HAVE_SET_CHANNELS | |||||
hwna->nm_eto.set_channels = linux_netmap_set_channels; | |||||
#endif /* NETMAP_LINUX_HAVE_SET_CHANNELS */ | |||||
if (arg->nm_config == NULL) { | |||||
hwna->up.nm_config = netmap_linux_config; | |||||
} | |||||
#endif /* linux */ | |||||
if (arg->nm_dtor == NULL) { | if (arg->nm_dtor == NULL) { | ||||
hwna->up.nm_dtor = netmap_hw_dtor; | hwna->up.nm_dtor = netmap_hw_dtor; | ||||
} | } | ||||
if_printf(ifp, "netmap queues/slots: TX %d/%d, RX %d/%d\n", | if_printf(ifp, "netmap queues/slots: TX %d/%d, RX %d/%d\n", | ||||
hwna->up.num_tx_rings, hwna->up.num_tx_desc, | hwna->up.num_tx_rings, hwna->up.num_tx_desc, | ||||
hwna->up.num_rx_rings, hwna->up.num_rx_desc); | hwna->up.num_rx_rings, hwna->up.num_rx_desc); | ||||
return 0; | return 0; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
/* nm_krings_create callback for all hardware native adapters */ | /* nm_krings_create callback for all hardware native adapters */ | ||||
int | int | ||||
netmap_hw_krings_create(struct netmap_adapter *na) | netmap_hw_krings_create(struct netmap_adapter *na) | ||||
{ | { | ||||
int ret = netmap_krings_create(na, 0); | int ret = netmap_krings_create(na, 0); | ||||
if (ret == 0) { | if (ret == 0) { | ||||
/* initialize the mbq for the sw rx ring */ | /* initialize the mbq for the sw rx ring */ | ||||
mbq_safe_init(&na->rx_rings[na->num_rx_rings]->rx_queue); | u_int lim = netmap_real_rings(na, NR_RX), i; | ||||
for (i = na->num_rx_rings; i < lim; i++) { | |||||
mbq_safe_init(&NMR(na, NR_RX)[i]->rx_queue); | |||||
} | |||||
ND("initialized sw rx queue %d", na->num_rx_rings); | ND("initialized sw rx queue %d", na->num_rx_rings); | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct netmap_adapter *na = NA(ifp); | struct netmap_adapter *na = NA(ifp); | ||||
struct netmap_kring *kring, *tx_kring; | struct netmap_kring *kring, *tx_kring; | ||||
u_int len = MBUF_LEN(m); | u_int len = MBUF_LEN(m); | ||||
u_int error = ENOBUFS; | u_int error = ENOBUFS; | ||||
unsigned int txr; | unsigned int txr; | ||||
struct mbq *q; | struct mbq *q; | ||||
int busy; | int busy; | ||||
u_int i; | |||||
kring = na->rx_rings[na->num_rx_rings]; | i = MBUF_TXQ(m); | ||||
if (i >= na->num_host_rx_rings) { | |||||
i = i % na->num_host_rx_rings; | |||||
} | |||||
kring = NMR(na, NR_RX)[nma_get_nrings(na, NR_RX) + i]; | |||||
// XXX [Linux] we do not need this lock | // XXX [Linux] we do not need this lock | ||||
// if we follow the down/configure/up protocol -gl | // if we follow the down/configure/up protocol -gl | ||||
// mtx_lock(&na->core_lock); | // mtx_lock(&na->core_lock); | ||||
if (!nm_netmap_on(na)) { | if (!nm_netmap_on(na)) { | ||||
D("%s not in netmap mode anymore", na->name); | D("%s not in netmap mode anymore", na->name); | ||||
error = ENXIO; | error = ENXIO; | ||||
goto done; | goto done; | ||||
Show All 13 Lines | netmap_transmit(struct ifnet *ifp, struct mbuf *m) | ||||
// XXX reconsider long packets if we handle fragments | // XXX reconsider long packets if we handle fragments | ||||
if (len > NETMAP_BUF_SIZE(na)) { /* too long for us */ | if (len > NETMAP_BUF_SIZE(na)) { /* too long for us */ | ||||
D("%s from_host, drop packet size %d > %d", na->name, | D("%s from_host, drop packet size %d > %d", na->name, | ||||
len, NETMAP_BUF_SIZE(na)); | len, NETMAP_BUF_SIZE(na)); | ||||
goto done; | goto done; | ||||
} | } | ||||
if (nm_os_mbuf_has_offld(m)) { | if (!netmap_generic_hwcsum) { | ||||
RD(1, "%s drop mbuf that needs offloadings", na->name); | if (nm_os_mbuf_has_csum_offld(m)) { | ||||
RD(1, "%s drop mbuf that needs checksum offload", na->name); | |||||
goto done; | goto done; | ||||
} | } | ||||
} | |||||
if (nm_os_mbuf_has_seg_offld(m)) { | |||||
RD(1, "%s drop mbuf that needs generic segmentation offload", na->name); | |||||
goto done; | |||||
} | |||||
/* protect against netmap_rxsync_from_host(), netmap_sw_to_nic() | /* protect against netmap_rxsync_from_host(), netmap_sw_to_nic() | ||||
* and maybe other instances of netmap_transmit (the latter | * and maybe other instances of netmap_transmit (the latter | ||||
* not possible on Linux). | * not possible on Linux). | ||||
* We enqueue the mbuf only if we are sure there is going to be | * We enqueue the mbuf only if we are sure there is going to be | ||||
* enough room in the host RX ring, otherwise we drop it. | * enough room in the host RX ring, otherwise we drop it. | ||||
*/ | */ | ||||
mbq_lock(q); | mbq_lock(q); | ||||
▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | if (!nm_netmap_on(na)) | ||||
return NM_IRQ_PASS; | return NM_IRQ_PASS; | ||||
if (na->na_flags & NAF_SKIP_INTR) { | if (na->na_flags & NAF_SKIP_INTR) { | ||||
ND("use regular interrupt"); | ND("use regular interrupt"); | ||||
return NM_IRQ_PASS; | return NM_IRQ_PASS; | ||||
} | } | ||||
return netmap_common_irq(na, q, work_done); | return netmap_common_irq(na, q, work_done); | ||||
} | |||||
/* set/clear native flags and if_transmit/netdev_ops */ | |||||
void | |||||
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; | |||||
nm_os_onenter(ifp); | |||||
nm_update_hostrings_mode(na); | |||||
} | |||||
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); | |||||
nm_os_onexit(ifp); | |||||
na->na_flags &= ~NAF_NETMAP_ON; | |||||
} | } | ||||
/* | /* | ||||
* Module loader and unloader | * Module loader and unloader | ||||
* | * | ||||
* netmap_init() creates the /dev/netmap device and initializes | * netmap_init() creates the /dev/netmap device and initializes | ||||
* all global variables. Returns 0 on success, errno on failure | * all global variables. Returns 0 on success, errno on failure | ||||
▲ Show 20 Lines • Show All 62 Lines • Show Last 20 Lines |