Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_virtio_net.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#ifndef NETMAP_WITH_LIBS | #ifndef NETMAP_WITH_LIBS | ||||
#define NETMAP_WITH_LIBS | #define NETMAP_WITH_LIBS | ||||
#endif | #endif | ||||
#include <net/netmap_user.h> | #include <net/netmap_user.h> | ||||
#ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
#include <capsicum_helpers.h> | #include <capsicum_helpers.h> | ||||
#endif | #endif | ||||
#include <machine/vmm_snapshot.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <strings.h> | #include <strings.h> | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | struct pci_vtnet_softc { | ||||
int tx_in_progress; | int tx_in_progress; | ||||
void (*pci_vtnet_rx)(struct pci_vtnet_softc *sc); | void (*pci_vtnet_rx)(struct pci_vtnet_softc *sc); | ||||
void (*pci_vtnet_tx)(struct pci_vtnet_softc *sc, struct iovec *iov, | void (*pci_vtnet_tx)(struct pci_vtnet_softc *sc, struct iovec *iov, | ||||
int iovcnt, int len); | int iovcnt, int len); | ||||
}; | }; | ||||
static void pci_vtnet_reset(void *); | static void pci_vtnet_reset(void *); | ||||
static void pci_vtnet_pause(void *); | |||||
static void pci_vtnet_resume(void *); | |||||
static int pci_vtnet_snapshot(void *, struct vm_snapshot_meta *); | |||||
/* static void pci_vtnet_notify(void *, struct vqueue_info *); */ | /* static void pci_vtnet_notify(void *, struct vqueue_info *); */ | ||||
static int pci_vtnet_cfgread(void *, int, int, uint32_t *); | static int pci_vtnet_cfgread(void *, int, int, uint32_t *); | ||||
static int pci_vtnet_cfgwrite(void *, int, int, uint32_t); | static int pci_vtnet_cfgwrite(void *, int, int, uint32_t); | ||||
static void pci_vtnet_neg_features(void *, uint64_t); | static void pci_vtnet_neg_features(void *, uint64_t); | ||||
static struct virtio_consts vtnet_vi_consts = { | static struct virtio_consts vtnet_vi_consts = { | ||||
"vtnet", /* our name */ | "vtnet", /* our name */ | ||||
VTNET_MAXQ - 1, /* we currently support 2 virtqueues */ | VTNET_MAXQ - 1, /* we currently support 2 virtqueues */ | ||||
sizeof(struct virtio_net_config), /* config reg size */ | sizeof(struct virtio_net_config), /* config reg size */ | ||||
pci_vtnet_reset, /* reset */ | pci_vtnet_reset, /* reset */ | ||||
NULL, /* device-wide qnotify -- not used */ | NULL, /* device-wide qnotify -- not used */ | ||||
pci_vtnet_cfgread, /* read PCI config */ | pci_vtnet_cfgread, /* read PCI config */ | ||||
pci_vtnet_cfgwrite, /* write PCI config */ | pci_vtnet_cfgwrite, /* write PCI config */ | ||||
pci_vtnet_neg_features, /* apply negotiated features */ | pci_vtnet_neg_features, /* apply negotiated features */ | ||||
VTNET_S_HOSTCAPS, /* our capabilities */ | VTNET_S_HOSTCAPS, /* our capabilities */ | ||||
pci_vtnet_pause, /* pause rx/tx threads */ | |||||
pci_vtnet_resume, /* resume rx/tx threads */ | |||||
pci_vtnet_snapshot, /* save / restore device state */ | |||||
}; | }; | ||||
/* | /* | ||||
* If the transmit thread is active then stall until it is done. | * If the transmit thread is active then stall until it is done. | ||||
*/ | */ | ||||
static void | static void | ||||
pci_vtnet_txwait(struct pci_vtnet_softc *sc) | pci_vtnet_txwait(struct pci_vtnet_softc *sc) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | pci_vtnet_reset(void *vsc) | ||||
sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); | sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); | ||||
/* now reset rings, MSI-X vectors, and negotiated capabilities */ | /* now reset rings, MSI-X vectors, and negotiated capabilities */ | ||||
vi_reset_dev(&sc->vsc_vs); | vi_reset_dev(&sc->vsc_vs); | ||||
sc->resetting = 0; | sc->resetting = 0; | ||||
} | } | ||||
static void | |||||
pci_vtnet_pause(void *vsc) | |||||
{ | |||||
struct pci_vtnet_softc *sc = vsc; | |||||
DPRINTF(("vtnet: device pause requested !\n")); | |||||
pthread_mutex_lock(&sc->tx_mtx); | |||||
pthread_mutex_lock(&sc->rx_mtx); | |||||
sc->resetting = 1; | |||||
pthread_mutex_unlock(&sc->rx_mtx); | |||||
pthread_mutex_unlock(&sc->tx_mtx); | |||||
/* | /* | ||||
* Wait for the transmit and receive threads to finish their | |||||
* processing. | |||||
*/ | |||||
pci_vtnet_txwait(sc); | |||||
pci_vtnet_rxwait(sc); | |||||
} | |||||
static void | |||||
pci_vtnet_resume(void *vsc) | |||||
{ | |||||
struct pci_vtnet_softc *sc = vsc; | |||||
DPRINTF(("vtnet: device resume requested !\n")); | |||||
pthread_mutex_lock(&sc->tx_mtx); | |||||
pthread_mutex_lock(&sc->rx_mtx); | |||||
sc->resetting = 0; | |||||
pthread_mutex_unlock(&sc->rx_mtx); | |||||
pthread_mutex_unlock(&sc->tx_mtx); | |||||
} | |||||
static int | |||||
pci_vtnet_snapshot(void *vsc, struct vm_snapshot_meta *meta) | |||||
{ | |||||
int ret; | |||||
struct pci_vtnet_softc *sc = vsc; | |||||
DPRINTF(("vtnet: device snapshot requested !\n")); | |||||
/* Queues and consts should have been saved by the more generic | |||||
* vi_pci_snapshot function. We need to save only our features and | |||||
* config. | |||||
*/ | |||||
SNAPSHOT_VAR_OR_LEAVE(sc->vsc_features, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(sc->vsc_config, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(sc->rx_vhdrlen, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(sc->rx_merge, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(sc->vsc_rx_ready, meta, ret, done); | |||||
done: | |||||
return (ret); | |||||
} | |||||
/* | |||||
* Called to send a buffer chain out to the tap device | * Called to send a buffer chain out to the tap device | ||||
*/ | */ | ||||
static void | static void | ||||
pci_vtnet_tap_tx(struct pci_vtnet_softc *sc, struct iovec *iov, int iovcnt, | pci_vtnet_tap_tx(struct pci_vtnet_softc *sc, struct iovec *iov, int iovcnt, | ||||
int len) | int len) | ||||
{ | { | ||||
static char pad[60]; /* all zero bytes */ | static char pad[60]; /* all zero bytes */ | ||||
▲ Show 20 Lines • Show All 726 Lines • ▼ Show 20 Lines | if (!(sc->vsc_features & VIRTIO_NET_F_MRG_RXBUF)) { | ||||
sc->rx_vhdrlen -= 2; | sc->rx_vhdrlen -= 2; | ||||
} | } | ||||
} | } | ||||
struct pci_devemu pci_de_vnet = { | struct pci_devemu pci_de_vnet = { | ||||
.pe_emu = "virtio-net", | .pe_emu = "virtio-net", | ||||
.pe_init = pci_vtnet_init, | .pe_init = pci_vtnet_init, | ||||
.pe_barwrite = vi_pci_write, | .pe_barwrite = vi_pci_write, | ||||
.pe_barread = vi_pci_read | .pe_barread = vi_pci_read, | ||||
.pe_snapshot = vi_pci_snapshot, | |||||
}; | }; | ||||
PCI_EMUL_SET(pci_de_vnet); | PCI_EMUL_SET(pci_de_vnet); |