Index: usr.sbin/bhyve/bhyve.8 =================================================================== --- usr.sbin/bhyve/bhyve.8 +++ usr.sbin/bhyve/bhyve.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 13, 2019 +.Dd January 23, 2020 .Dt BHYVE 8 .Os .Sh NAME @@ -584,6 +584,11 @@ -A -H -P -m 24G bigvm .Ed .Pp +The virtio-net device accepts an additional option to explicitely enable +or disable the virtio-net `mergeable rx buffers` feature. If the option +is not specified, bhyve will advertise the feature only when the vale(4) +net backend is used. +.Pp Run an 8GB quad-CPU virtual machine with 8 AHCI SATA disks, an AHCI ATAPI CD-ROM, a single virtio network port, an AMD hostbridge, and the console port connected to an Index: usr.sbin/bhyve/net_backends.c =================================================================== --- usr.sbin/bhyve/net_backends.c +++ usr.sbin/bhyve/net_backends.c @@ -279,7 +279,6 @@ static uint64_t tap_get_cap(struct net_backend *be) { - return (0); /* no capabilities for now */ } Index: usr.sbin/bhyve/net_utils.c =================================================================== --- usr.sbin/bhyve/net_utils.c +++ usr.sbin/bhyve/net_utils.c @@ -44,21 +44,19 @@ net_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) + return (EINVAL); - if ((mac_str != NULL) && (!strcmp(tmpstr,"mac"))) { - ea = ether_aton(mac_str); + ea = ether_aton(mac_str); - if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) || - memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) { - EPRINTLN("Invalid MAC %s", mac_str); - return (EINVAL); - } else - memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN); - } + if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) || + memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) { + EPRINTLN("Invalid MAC %s", mac_str); + return (EINVAL); + } else + memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN); return (0); } Index: usr.sbin/bhyve/pci_e82545.c =================================================================== --- usr.sbin/bhyve/pci_e82545.c +++ usr.sbin/bhyve/pci_e82545.c @@ -2328,18 +2328,38 @@ mac_provided = 0; sc->esc_be = NULL; if (opts != NULL) { - int err; + int err = 0; devname = vtopts = strdup(opts); (void) strsep(&vtopts, ","); - if (vtopts != NULL) { - err = net_parsemac(vtopts, sc->esc_mac.octet); - if (err != 0) { - free(devname); - return (err); + /* + * Parse the list of options in the form + * key1=value1,...,keyN=valueN. + */ + while (vtopts != NULL) { + char *value = vtopts; + char *key; + + key = strsep(&value, "="); + if (value == NULL) { + break; + } + vtopts = value; + (void) strsep(&vtopts, ","); + + if (strcmp(key, "mac") == 0) { + err = net_parsemac(value, sc->esc_mac.octet); + if (err) { + break; + } + mac_provided = 1; } - mac_provided = 1; + } + + if (err) { + free(devname); + return (err); } err = netbe_init(&sc->esc_be, devname, e82545_rx_callback, sc); Index: usr.sbin/bhyve/pci_virtio_net.c =================================================================== --- usr.sbin/bhyve/pci_virtio_net.c +++ usr.sbin/bhyve/pci_virtio_net.c @@ -464,21 +464,52 @@ */ mac_provided = 0; if (opts != NULL) { + int mrg_rxbuf_enabled = 0; + int mrg_rxbuf_disabled = 0; char *devname; char *vtopts; - int err; + int err = 0; + /* Get the device name. */ devname = vtopts = strdup(opts); (void) strsep(&vtopts, ","); - if (vtopts != NULL) { - err = net_parsemac(vtopts, sc->vsc_config.mac); - if (err != 0) { - free(devname); - free(sc); - return (err); + /* + * Parse the list of options in the form + * key1=value1,...,keyN=valueN. + */ + while (vtopts != NULL) { + char *value = vtopts; + char *key; + + key = strsep(&value, "="); + if (value == NULL) { + break; + } + vtopts = value; + (void) strsep(&vtopts, ","); + + if (strcmp(key, "mac") == 0) { + err = net_parsemac(value, sc->vsc_config.mac); + if (err) { + break; + } + mac_provided = 1; + } else if (strcmp(key, "mrgrxbuf") == 0) { + if (strcmp(value, "on") == 0) { + mrg_rxbuf_enabled = 1; + mrg_rxbuf_disabled = 0; + } else { + mrg_rxbuf_disabled = 1; + mrg_rxbuf_enabled = 0; + } } - mac_provided = 1; + } + + if (err) { + free(devname); + free(sc); + return (err); } err = netbe_init(&sc->vsc_be, devname, pci_vtnet_rx_callback, @@ -489,6 +520,11 @@ return (err); } sc->vsc_consts.vc_hv_caps |= netbe_get_cap(sc->vsc_be); + if (mrg_rxbuf_enabled) + sc->vsc_consts.vc_hv_caps |= VIRTIO_NET_F_MRG_RXBUF; + else if (mrg_rxbuf_disabled) + sc->vsc_consts.vc_hv_caps &= ~VIRTIO_NET_F_MRG_RXBUF; + } if (!mac_provided) {