Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/netmap/netmap.c
Context not available. | |||||
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; | ||||
Context not available. | |||||
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, | ||||
Context not available. | |||||
} | } | ||||
/* 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 *)) | ||||
Context not available. | |||||
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; | ||||
ND("destroy sw mbq with len %d", mbq_len(q)); | for (i = nma_get_nrings(na, NR_RX); i < lim; i++) { | ||||
mbq_purge(q); | struct mbq *q = &NMR(na, NR_RX)[i]->rx_queue; | ||||
mbq_safe_fini(q); | ND("destroy sw mbq with len %d", mbq_len(q)); | ||||
mbq_purge(q); | |||||
mbq_safe_fini(q); | |||||
} | |||||
netmap_krings_delete(na); | netmap_krings_delete(na); | ||||
} | } | ||||
Context not available. | |||||
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; | ||||
Context not available. | |||||
} | } | ||||
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]); | ||||
Context not available. | |||||
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) { | ||||
Context not available. | |||||
} | } | ||||
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 | ||||
Context not available. | |||||
/* 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; | ||||
Context not available. | |||||
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); | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
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 | ||||
Context not available. | |||||
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; | ||||
} | } | ||||
Context not available. | |||||
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; | ||||
Context not available. | |||||
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); | ||||
Context not available. | |||||
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; | |||||
} | |||||
} | |||||
if (nm_os_mbuf_has_seg_offld(m)) { | |||||
RD(1, "%s drop mbuf that needs generic segmentation offload", na->name); | |||||
goto done; | goto done; | ||||
} | } | ||||
Context not available. | |||||
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. */ | |||||
bcr: s/adapapter/adapter/ | |||||
vmaffioneAuthorUnsubmitted Done Inline ActionsThanks, I fixed it in the new version. vmaffione: Thanks, I fixed it in the new version. | |||||
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 | ||||
* | * | ||||
Context not available. |
s/adapapter/adapter/