Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_virtio_net.c
Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
#include <pthread.h> | #include <pthread.h> | ||||
#include <pthread_np.h> | #include <pthread_np.h> | ||||
#include <sysexits.h> | #include <sysexits.h> | ||||
#include "bhyverun.h" | #include "bhyverun.h" | ||||
#include "pci_emul.h" | #include "pci_emul.h" | ||||
#include "mevent.h" | #include "mevent.h" | ||||
#include "virtio.h" | #include "virtio.h" | ||||
#include "net_utils.h" | |||||
#define VTNET_RINGSZ 1024 | #define VTNET_RINGSZ 1024 | ||||
#define VTNET_MAXSEGS 256 | #define VTNET_MAXSEGS 256 | ||||
/* | /* | ||||
* Host capabilities. Note that we only offer a few of these. | * Host capabilities. Note that we only offer a few of these. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 584 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
pci_vtnet_ping_ctlq(void *vsc, struct vqueue_info *vq) | pci_vtnet_ping_ctlq(void *vsc, struct vqueue_info *vq) | ||||
{ | { | ||||
DPRINTF(("vtnet: control qnotify!\n\r")); | DPRINTF(("vtnet: control qnotify!\n\r")); | ||||
} | } | ||||
#endif | #endif | ||||
static int | |||||
pci_vtnet_parsemac(char *mac_str, uint8_t *mac_addr) | |||||
{ | |||||
struct ether_addr *ea; | |||||
char *tmpstr; | |||||
char zero_addr[ETHER_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 }; | |||||
tmpstr = strsep(&mac_str,"="); | |||||
if ((mac_str != NULL) && (!strcmp(tmpstr,"mac"))) { | |||||
ea = ether_aton(mac_str); | |||||
if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) || | |||||
memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) { | |||||
fprintf(stderr, "Invalid MAC %s\n", mac_str); | |||||
return (EINVAL); | |||||
} else | |||||
memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN); | |||||
} | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
pci_vtnet_tap_setup(struct pci_vtnet_softc *sc, char *devname) | pci_vtnet_tap_setup(struct pci_vtnet_softc *sc, char *devname) | ||||
{ | { | ||||
char tbuf[80]; | char tbuf[80]; | ||||
#ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
nm_close(sc->vsc_nmd); | nm_close(sc->vsc_nmd); | ||||
sc->vsc_nmd = NULL; | sc->vsc_nmd = NULL; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | ||||
{ | { | ||||
MD5_CTX mdctx; | |||||
unsigned char digest[16]; | |||||
char nstr[80]; | |||||
char tname[MAXCOMLEN + 1]; | char tname[MAXCOMLEN + 1]; | ||||
struct pci_vtnet_softc *sc; | struct pci_vtnet_softc *sc; | ||||
char *devname; | char *devname; | ||||
char *vtopts; | char *vtopts; | ||||
int mac_provided; | int mac_provided; | ||||
sc = calloc(1, sizeof(struct pci_vtnet_softc)); | sc = calloc(1, sizeof(struct pci_vtnet_softc)); | ||||
Show All 20 Lines | |||||
sc->vsc_nmd = NULL; | sc->vsc_nmd = NULL; | ||||
if (opts != NULL) { | if (opts != NULL) { | ||||
int err; | int err; | ||||
devname = vtopts = strdup(opts); | devname = vtopts = strdup(opts); | ||||
(void) strsep(&vtopts, ","); | (void) strsep(&vtopts, ","); | ||||
if (vtopts != NULL) { | if (vtopts != NULL) { | ||||
err = pci_vtnet_parsemac(vtopts, sc->vsc_config.mac); | err = net_parsemac(vtopts, sc->vsc_config.mac); | ||||
if (err != 0) { | if (err != 0) { | ||||
free(devname); | free(devname); | ||||
return (err); | return (err); | ||||
} | } | ||||
mac_provided = 1; | mac_provided = 1; | ||||
} | } | ||||
if (strncmp(devname, "vale", 4) == 0) | if (strncmp(devname, "vale", 4) == 0) | ||||
pci_vtnet_netmap_setup(sc, devname); | pci_vtnet_netmap_setup(sc, devname); | ||||
if (strncmp(devname, "tap", 3) == 0 || | if (strncmp(devname, "tap", 3) == 0 || | ||||
strncmp(devname, "vmnet", 5) == 0) | strncmp(devname, "vmnet", 5) == 0) | ||||
pci_vtnet_tap_setup(sc, devname); | pci_vtnet_tap_setup(sc, devname); | ||||
free(devname); | free(devname); | ||||
} | } | ||||
/* | |||||
* The default MAC address is the standard NetApp OUI of 00-a0-98, | |||||
* followed by an MD5 of the PCI slot/func number and dev name | |||||
*/ | |||||
if (!mac_provided) { | if (!mac_provided) { | ||||
snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot, | net_genmac(pi, sc->vsc_config.mac); | ||||
pi->pi_func, vmname); | |||||
MD5Init(&mdctx); | |||||
MD5Update(&mdctx, nstr, strlen(nstr)); | |||||
MD5Final(digest, &mdctx); | |||||
sc->vsc_config.mac[0] = 0x00; | |||||
sc->vsc_config.mac[1] = 0xa0; | |||||
sc->vsc_config.mac[2] = 0x98; | |||||
sc->vsc_config.mac[3] = digest[0]; | |||||
sc->vsc_config.mac[4] = digest[1]; | |||||
sc->vsc_config.mac[5] = digest[2]; | |||||
} | } | ||||
/* initialize config space */ | /* initialize config space */ | ||||
pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET); | pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET); | ||||
pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); | pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); | ||||
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK); | pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK); | ||||
pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET); | pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET); | ||||
pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); | pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); | ||||
▲ Show 20 Lines • Show All 87 Lines • Show Last 20 Lines |