Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/virtio/network/if_vtnet.c
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/taskqueue.h> | #include <sys/taskqueue.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <machine/smp.h> | #include <machine/smp.h> | ||||
#include <vm/uma.h> | #include <vm/uma.h> | ||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <net/pfil.h> | |||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/if_arp.h> | #include <net/if_arp.h> | ||||
#include <net/if_dl.h> | #include <net/if_dl.h> | ||||
#include <net/if_types.h> | #include <net/if_types.h> | ||||
#include <net/if_media.h> | #include <net/if_media.h> | ||||
#include <net/if_vlan_var.h> | #include <net/if_vlan_var.h> | ||||
▲ Show 20 Lines • Show All 859 Lines • ▼ Show 20 Lines | vtnet_alloc_virtqueues(struct vtnet_softc *sc) | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
vtnet_setup_interface(struct vtnet_softc *sc) | vtnet_setup_interface(struct vtnet_softc *sc) | ||||
{ | { | ||||
device_t dev; | device_t dev; | ||||
struct pfil_head_args pa; | |||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
dev = sc->vtnet_dev; | dev = sc->vtnet_dev; | ||||
ifp = sc->vtnet_ifp = if_alloc(IFT_ETHER); | ifp = sc->vtnet_ifp = if_alloc(IFT_ETHER); | ||||
if (ifp == NULL) { | if (ifp == NULL) { | ||||
device_printf(dev, "cannot allocate ifnet structure\n"); | device_printf(dev, "cannot allocate ifnet structure\n"); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | sc->vtnet_vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, | ||||
vtnet_unregister_vlan, sc, EVENTHANDLER_PRI_FIRST); | vtnet_unregister_vlan, sc, EVENTHANDLER_PRI_FIRST); | ||||
} | } | ||||
vtnet_set_rx_process_limit(sc); | vtnet_set_rx_process_limit(sc); | ||||
vtnet_set_tx_intr_threshold(sc); | vtnet_set_tx_intr_threshold(sc); | ||||
NETDUMP_SET(ifp, vtnet); | NETDUMP_SET(ifp, vtnet); | ||||
pa.pa_version = PFIL_VERSION; | |||||
pa.pa_flags = PFIL_IN; | |||||
pa.pa_type = PFIL_TYPE_ETHERNET; | |||||
pa.pa_headname = ifp->if_xname; | |||||
sc->vtnet_pfil = pfil_head_register(&pa); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
vtnet_change_mtu(struct vtnet_softc *sc, int new_mtu) | vtnet_change_mtu(struct vtnet_softc *sc, int new_mtu) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int frame_size, clsize; | int frame_size, clsize; | ||||
▲ Show 20 Lines • Show All 727 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
vtnet_rxq_eof(struct vtnet_rxq *rxq) | vtnet_rxq_eof(struct vtnet_rxq *rxq) | ||||
{ | { | ||||
struct virtio_net_hdr lhdr, *hdr; | struct virtio_net_hdr lhdr, *hdr; | ||||
struct vtnet_softc *sc; | struct vtnet_softc *sc; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct virtqueue *vq; | struct virtqueue *vq; | ||||
struct mbuf *m; | struct mbuf *m, *mr; | ||||
struct virtio_net_hdr_mrg_rxbuf *mhdr; | struct virtio_net_hdr_mrg_rxbuf *mhdr; | ||||
int len, deq, nbufs, adjsz, count; | int len, deq, nbufs, adjsz, count; | ||||
pfil_return_t pfil; | |||||
bool pfil_done; | |||||
sc = rxq->vtnrx_sc; | sc = rxq->vtnrx_sc; | ||||
vq = rxq->vtnrx_vq; | vq = rxq->vtnrx_vq; | ||||
ifp = sc->vtnet_ifp; | ifp = sc->vtnet_ifp; | ||||
hdr = &lhdr; | hdr = &lhdr; | ||||
deq = 0; | deq = 0; | ||||
count = sc->vtnet_rx_process_limit; | count = sc->vtnet_rx_process_limit; | ||||
Show All 20 Lines | if ((sc->vtnet_flags & VTNET_FLAG_MRG_RXBUFS) == 0) { | ||||
*/ | */ | ||||
len += VTNET_RX_HEADER_PAD; | len += VTNET_RX_HEADER_PAD; | ||||
} else { | } else { | ||||
mhdr = mtod(m, struct virtio_net_hdr_mrg_rxbuf *); | mhdr = mtod(m, struct virtio_net_hdr_mrg_rxbuf *); | ||||
nbufs = mhdr->num_buffers; | nbufs = mhdr->num_buffers; | ||||
adjsz = sizeof(struct virtio_net_hdr_mrg_rxbuf); | adjsz = sizeof(struct virtio_net_hdr_mrg_rxbuf); | ||||
} | } | ||||
/* | |||||
* If we have enough data in first mbuf, run it through | |||||
* pfil before we allocated any new one. | |||||
*/ | |||||
if (PFIL_HOOKED_IN(sc->vtnet_pfil) && | |||||
len - adjsz >= ETHER_HDR_LEN + max_protohdr) { | |||||
pfil = pfil_run_hooks(sc->vtnet_pfil, | |||||
m->m_data + adjsz, ifp, | |||||
len - adjsz | PFIL_MEMPTR | PFIL_IN, NULL); | |||||
switch (pfil) { | |||||
case PFIL_REALLOCED: | |||||
mr = *(struct mbuf **)(m->m_data + adjsz); | |||||
vtnet_rxq_input(rxq, mr, hdr); | |||||
ae: Is it safe to call vtnet_rxq_discard_buf() just after if_input()? | |||||
glebiusAuthorUnsubmitted Done Inline ActionsThis part of patch has changed. I will update pull request soon. glebius: This part of patch has changed. I will update pull request soon. | |||||
case PFIL_DROPPED: | |||||
case PFIL_CONSUMED: | |||||
vtnet_rxq_discard_buf(rxq, m); | |||||
continue; | |||||
default: | |||||
KASSERT(pfil == PFIL_PASS, | |||||
("Filter returned %d!\n", pfil)); | |||||
}; | |||||
pfil_done = true; | |||||
} else | |||||
pfil_done = false; | |||||
if (vtnet_rxq_replace_buf(rxq, m, len) != 0) { | if (vtnet_rxq_replace_buf(rxq, m, len) != 0) { | ||||
rxq->vtnrx_stats.vrxs_iqdrops++; | rxq->vtnrx_stats.vrxs_iqdrops++; | ||||
vtnet_rxq_discard_buf(rxq, m); | vtnet_rxq_discard_buf(rxq, m); | ||||
if (nbufs > 1) | if (nbufs > 1) | ||||
vtnet_rxq_discard_merged_bufs(rxq, nbufs); | vtnet_rxq_discard_merged_bufs(rxq, nbufs); | ||||
continue; | continue; | ||||
} | } | ||||
Show All 13 Lines | while (count-- > 0) { | ||||
* mbuf data. We no longer need num_buffers, so always use a | * mbuf data. We no longer need num_buffers, so always use a | ||||
* regular header. | * regular header. | ||||
* | * | ||||
* BMV: Is this memcpy() expensive? We know the mbuf data is | * BMV: Is this memcpy() expensive? We know the mbuf data is | ||||
* still valid even after the m_adj(). | * still valid even after the m_adj(). | ||||
*/ | */ | ||||
memcpy(hdr, mtod(m, void *), sizeof(struct virtio_net_hdr)); | memcpy(hdr, mtod(m, void *), sizeof(struct virtio_net_hdr)); | ||||
m_adj(m, adjsz); | m_adj(m, adjsz); | ||||
if (PFIL_HOOKED_IN(sc->vtnet_pfil) && pfil_done == false) { | |||||
pfil = pfil_run_hooks(sc->vtnet_pfil, &m, ifp, PFIL_IN, | |||||
NULL); | |||||
switch (pfil) { | |||||
case PFIL_DROPPED: | |||||
case PFIL_CONSUMED: | |||||
continue; | |||||
default: | |||||
KASSERT(pfil == PFIL_PASS, | |||||
("Filter returned %d!\n", pfil)); | |||||
} | |||||
} | |||||
vtnet_rxq_input(rxq, m, hdr); | vtnet_rxq_input(rxq, m, hdr); | ||||
/* Must recheck after dropping the Rx lock. */ | /* Must recheck after dropping the Rx lock. */ | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,199 Lines • Show Last 20 Lines |
Is it safe to call vtnet_rxq_discard_buf() just after if_input()?