Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_virtio_net.c
Show First 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
pci_vtnet_rx(struct pci_vtnet_softc *sc) | pci_vtnet_rx(struct pci_vtnet_softc *sc) | ||||
{ | { | ||||
int prepend_hdr_len = sc->vhdrlen - sc->be_vhdrlen; | int prepend_hdr_len = sc->vhdrlen - sc->be_vhdrlen; | ||||
struct virtio_mrg_rxbuf_info info[VTNET_MAXSEGS]; | struct virtio_mrg_rxbuf_info info[VTNET_MAXSEGS]; | ||||
struct iovec iov[VTNET_MAXSEGS + 1]; | struct iovec iov[VTNET_MAXSEGS + 1]; | ||||
struct vqueue_info *vq; | struct vqueue_info *vq; | ||||
struct vi_req req; | |||||
vq = &sc->vsc_queues[VTNET_RXQ]; | vq = &sc->vsc_queues[VTNET_RXQ]; | ||||
/* Features must be negotiated */ | /* Features must be negotiated */ | ||||
if (!sc->features_negotiated) { | if (!sc->features_negotiated) { | ||||
return; | return; | ||||
} | } | ||||
Show All 24 Lines | for (;;) { | ||||
* many chains as necessary in order to make room | * many chains as necessary in order to make room | ||||
* for plen bytes. | * for plen bytes. | ||||
*/ | */ | ||||
riov_bytes = 0; | riov_bytes = 0; | ||||
riov_len = 0; | riov_len = 0; | ||||
riov = iov; | riov = iov; | ||||
n_chains = 0; | n_chains = 0; | ||||
do { | do { | ||||
int n = vq_getchain(vq, &info[n_chains].idx, riov, | int n = vq_getchain(vq, riov, VTNET_MAXSEGS - riov_len, | ||||
VTNET_MAXSEGS - riov_len, NULL); | &req); | ||||
info[n_chains].idx = req.idx; | |||||
if (n == 0) { | if (n == 0) { | ||||
/* | /* | ||||
* No rx buffers. Enable RX kicks and double | * No rx buffers. Enable RX kicks and double | ||||
* check. | * check. | ||||
*/ | */ | ||||
vq_kick_enable(vq); | vq_kick_enable(vq); | ||||
if (!vq_has_descs(vq)) { | if (!vq_has_descs(vq)) { | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* TX virtqueue processing, called by the TX thread. */ | /* TX virtqueue processing, called by the TX thread. */ | ||||
static void | static void | ||||
pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vqueue_info *vq) | pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vqueue_info *vq) | ||||
{ | { | ||||
struct iovec iov[VTNET_MAXSEGS + 1]; | struct iovec iov[VTNET_MAXSEGS + 1]; | ||||
struct iovec *siov = iov; | struct iovec *siov = iov; | ||||
uint16_t idx; | struct vi_req req; | ||||
ssize_t len; | ssize_t len; | ||||
int n; | int n; | ||||
/* | /* | ||||
* Obtain chain of descriptors. The first descriptor also | * Obtain chain of descriptors. The first descriptor also | ||||
* contains the virtio-net header. | * contains the virtio-net header. | ||||
*/ | */ | ||||
n = vq_getchain(vq, &idx, iov, VTNET_MAXSEGS, NULL); | n = vq_getchain(vq, iov, VTNET_MAXSEGS, &req); | ||||
assert(n >= 1 && n <= VTNET_MAXSEGS); | assert(n >= 1 && n <= VTNET_MAXSEGS); | ||||
if (sc->vhdrlen != sc->be_vhdrlen) { | if (sc->vhdrlen != sc->be_vhdrlen) { | ||||
/* | /* | ||||
* The frontend uses a virtio-net header, but the backend | * The frontend uses a virtio-net header, but the backend | ||||
* does not. We simply strip the header and ignore it, as | * does not. We simply strip the header and ignore it, as | ||||
* it should be zero-filled. | * it should be zero-filled. | ||||
*/ | */ | ||||
Show All 13 Lines | if (len < 0) { | ||||
len = 0; | len = 0; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Return the processed chain to the guest, reporting | * Return the processed chain to the guest, reporting | ||||
* the number of bytes that we read. | * the number of bytes that we read. | ||||
*/ | */ | ||||
vq_relchain(vq, idx, len); | vq_relchain(vq, req.idx, len); | ||||
} | } | ||||
/* Called on TX kick. */ | /* Called on TX kick. */ | ||||
static void | static void | ||||
pci_vtnet_ping_txq(void *vsc, struct vqueue_info *vq) | pci_vtnet_ping_txq(void *vsc, struct vqueue_info *vq) | ||||
{ | { | ||||
struct pci_vtnet_softc *sc = vsc; | struct pci_vtnet_softc *sc = vsc; | ||||
▲ Show 20 Lines • Show All 333 Lines • Show Last 20 Lines |