svn commit: r252682 - head/usr.sbin/bhyve

Peter Grehan grehan at FreeBSD.org
Thu Jul 4 05:35:58 UTC 2013


Author: grehan
Date: Thu Jul  4 05:35:56 2013
New Revision: 252682
URL: http://svnweb.freebsd.org/changeset/base/252682

Log:
  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)

Modified:
  head/usr.sbin/bhyve/bhyverun.c
  head/usr.sbin/bhyve/pci_emul.c
  head/usr.sbin/bhyve/pci_emul.h
  head/usr.sbin/bhyve/pci_virtio_net.c

Modified: head/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- head/usr.sbin/bhyve/bhyverun.c	Thu Jul  4 04:26:19 2013	(r252681)
+++ head/usr.sbin/bhyve/bhyverun.c	Thu Jul  4 05:35:56 2013	(r252682)
@@ -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);
 

Modified: head/usr.sbin/bhyve/pci_emul.c
==============================================================================
--- head/usr.sbin/bhyve/pci_emul.c	Thu Jul  4 04:26:19 2013	(r252681)
+++ head/usr.sbin/bhyve/pci_emul.c	Thu Jul  4 05:35:56 2013	(r252682)
@@ -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_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 *
 	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

Modified: head/usr.sbin/bhyve/pci_emul.h
==============================================================================
--- head/usr.sbin/bhyve/pci_emul.h	Thu Jul  4 04:26:19 2013	(r252681)
+++ head/usr.sbin/bhyve/pci_emul.h	Thu Jul  4 05:35:56 2013	(r252682)
@@ -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,

Modified: head/usr.sbin/bhyve/pci_virtio_net.c
==============================================================================
--- head/usr.sbin/bhyve/pci_virtio_net.c	Thu Jul  4 04:26:19 2013	(r252681)
+++ head/usr.sbin/bhyve/pci_virtio_net.c	Thu Jul  4 05:35:56 2013	(r252682)
@@ -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_sof
 }
 
 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
 	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
 	}
 
 	/*
-	 * 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,28 +746,24 @@ pci_vtnet_init(struct vmctx *ctx, struct
 	}
 
 	/*
-	 * 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);


More information about the svn-src-all mailing list