mirror of
https://github.com/opnsense/src.git
synced 2026-03-07 07:44:13 -05:00
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)
This commit is contained in:
parent
ed74b69c2d
commit
a38e2a64dc
4 changed files with 85 additions and 29 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -637,6 +638,30 @@ pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn)
|
|||
hq->hq_cur_aidx = 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue