summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2013-07-04 05:35:56 +0000
committergrehan <grehan@FreeBSD.org>2013-07-04 05:35:56 +0000
commit4afc69bc7618a2445997ba51f65a74a54d461acb (patch)
tree1475820278721b7a4feacaea3c2716ad349e638a /usr.sbin/bhyve
parent67f40d0cd39e244cabb915e7828711647be1f159 (diff)
downloadFreeBSD-src-4afc69bc7618a2445997ba51f65a74a54d461acb.zip
FreeBSD-src-4afc69bc7618a2445997ba51f65a74a54d461acb.tar.gz
Support an optional "mac=" parameter to virtio-net config, to allow
users to set the MAC address for a device. Clean up some obsolete code in pci_virtio_net.c Allow an error return from a PCI device emulation's init routine to be propagated all the way back to the top-level and result in the process exiting. Submitted by: Dinakar Medavaram dinnu sun at gmail (original version)
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/bhyverun.c8
-rw-r--r--usr.sbin/bhyve/pci_emul.c21
-rw-r--r--usr.sbin/bhyve/pci_emul.h2
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c83
4 files changed, 85 insertions, 29 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 66883be..ae22de2 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -734,7 +734,13 @@ main(int argc, char *argv[])
init_mem();
init_inout();
- init_pci(ctx);
+
+ /*
+ * Exit if a device emulation finds an error in it's initilization
+ */
+ if (init_pci(ctx) != 0)
+ exit(1);
+
if (ioapic)
ioapic_init(0);
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index 76e536c..00adf62 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -662,11 +662,13 @@ pci_emul_finddev(char *name)
return (NULL);
}
-static void
+static int
pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
char *params)
{
struct pci_devinst *pdi;
+ int err;
+
pdi = malloc(sizeof(struct pci_devinst));
bzero(pdi, sizeof(*pdi));
@@ -684,12 +686,15 @@ pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
pci_set_cfgdata8(pdi, PCIR_COMMAND,
PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
- if ((*pde->pe_init)(ctx, pdi, params) != 0) {
+ err = (*pde->pe_init)(ctx, pdi, params);
+ if (err != 0) {
free(pdi);
} else {
pci_emul_devices++;
pci_slotinfo[slot][func].si_devi = pdi;
- }
+ }
+
+ return (err);
}
void
@@ -989,7 +994,7 @@ pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
return (0);
}
-void
+int
init_pci(struct vmctx *ctx)
{
struct mem_range memp;
@@ -1009,8 +1014,10 @@ init_pci(struct vmctx *ctx)
if (si->si_name != NULL) {
pde = pci_emul_finddev(si->si_name);
assert(pde != NULL);
- pci_emul_init(ctx, pde, slot, func,
- si->si_param);
+ error = pci_emul_init(ctx, pde, slot, func,
+ si->si_param);
+ if (error)
+ return (error);
}
}
}
@@ -1047,6 +1054,8 @@ init_pci(struct vmctx *ctx)
error = register_mem_fallback(&memp);
assert(error == 0);
+
+ return (0);
}
int
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
index 654b2f6..4e04a1e 100644
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -183,7 +183,7 @@ struct pciecap {
uint16_t slot_status2;
} __packed;
-void init_pci(struct vmctx *ctx);
+int init_pci(struct vmctx *ctx);
void msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
int bytes, uint32_t val);
void msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
index 4c03463..19f9ffe 100644
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/select.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
+#include <net/ethernet.h>
#include <errno.h>
#include <fcntl.h>
@@ -638,6 +639,30 @@ pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn)
}
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 int
pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
MD5_CTX mdctx;
@@ -646,6 +671,9 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
char tname[MAXCOMLEN + 1];
struct pci_vtnet_softc *sc;
const char *env_msi;
+ char *devname;
+ char *vtopts;
+ int mac_provided;
sc = malloc(sizeof(struct pci_vtnet_softc));
memset(sc, 0, sizeof(struct pci_vtnet_softc));
@@ -664,14 +692,31 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
}
/*
- * Attempt to open the tap device
+ * Attempt to open the tap device and read the MAC address
+ * if specified
*/
+ mac_provided = 0;
sc->vsc_tapfd = -1;
if (opts != NULL) {
char tbuf[80];
+ int err;
+
+ devname = vtopts = strdup(opts);
+ (void) strsep(&vtopts, ",");
+
+ if (vtopts != NULL) {
+ err = pci_vtnet_parsemac(vtopts, sc->vsc_macaddr);
+ if (err != 0) {
+ free(devname);
+ return (err);
+ }
+ mac_provided = 1;
+ }
strcpy(tbuf, "/dev/");
- strlcat(tbuf, opts, sizeof(tbuf));
+ strlcat(tbuf, devname, sizeof(tbuf));
+
+ free(devname);
sc->vsc_tapfd = open(tbuf, O_RDWR);
if (sc->vsc_tapfd == -1) {
@@ -701,29 +746,25 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
}
/*
- * The MAC address is the standard NetApp OUI of 00-a0-98,
- * followed by an MD5 of the vm name. The slot/func number is
- * prepended to this for slots other than 1:0, so that
- * a bootloader can netboot from the equivalent of slot 1.
+ * 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 (pi->pi_slot == 1 && pi->pi_func == 0) {
- strncpy(nstr, vmname, sizeof(nstr));
- } else {
+ if (!mac_provided) {
snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot,
- pi->pi_func, vmname);
+ pi->pi_func, vmname);
+
+ MD5Init(&mdctx);
+ MD5Update(&mdctx, nstr, strlen(nstr));
+ MD5Final(digest, &mdctx);
+
+ sc->vsc_macaddr[0] = 0x00;
+ sc->vsc_macaddr[1] = 0xa0;
+ sc->vsc_macaddr[2] = 0x98;
+ sc->vsc_macaddr[3] = digest[0];
+ sc->vsc_macaddr[4] = digest[1];
+ sc->vsc_macaddr[5] = digest[2];
}
- MD5Init(&mdctx);
- MD5Update(&mdctx, nstr, strlen(nstr));
- MD5Final(digest, &mdctx);
-
- sc->vsc_macaddr[0] = 0x00;
- sc->vsc_macaddr[1] = 0xa0;
- sc->vsc_macaddr[2] = 0x98;
- sc->vsc_macaddr[3] = digest[0];
- sc->vsc_macaddr[4] = digest[1];
- sc->vsc_macaddr[5] = digest[2];
-
/* initialize config space */
pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET);
pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
OpenPOWER on IntegriCloud