[libvirt] [PATCH v2 resend 0/4]use VIR_ENUM_DECL for domain NIC model and add usb-net

v1 to v2 *removed i8* NIC models support for QEMU/KVM *updated docs *rebased This patchset uses VIR_ENUM_DECL and VIR_ENUM_IMPL macros for NIC models and changes the related codes to use them. All of NIC models supported by various hypervisors comprise of the enum, so the problem is that we need to do further checking in hypervisor-specific implementation. Fortunately, VMX and Vbox did this checking very well already. In 4/4, a similar job is performed for QEMU/KVM. And, adds usb-net support. The vendorId and productID of is 0525:a4a2. The corresponding item in usb-ids is as follows: 0525 Netchip Technology, Inc. a4a2 Linux-USB Ethernet/RNDIS Gadget In my opinion, using usb-net directly is good enough, so I keep it. Any other idea is welcome. Libvirt XML sample: <devices> <interface type='user'> <mac address='52:54:00:32:6a:91'/> <model type='usb-net'/> <alias name='net1'/> <address type='usb' bus='0' port='1'/> </interface> </devices> qemu commandline: qemu ${other_vm_args} -netdev user,id=hostnet1 \ -device usb-net,netdev=hostnet1,id=net1,\ mac=52:54:00:32:6a:91,bus=usb.0,port=1 Guannan Ren(4) [PATCH v2 resend 1/4] add domain NIC model enum macro [PATCH v2 resend 2/4] net: use virDomainNICModelType{From|To}String functions [PATCH v2 resend 3/4] qemu: add NIC model checking for qemu hypervisor [PATCH v2 resend 4/4] qemu: add usb-net support docs/formatdomain.html.in | 29 +++++++++++------------------ src/conf/domain_conf.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ src/conf/domain_conf.h | 32 +++++++++++++++++++++++++++++++- src/libvirt_private.syms | 2 ++ src/libxl/libxl_conf.c | 5 +++-- src/parallels/parallels_driver.c | 2 +- src/qemu/qemu_command.c | 41 +++++++++++++++++++++++++++-------------- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 10 ++++++---- src/qemu/qemu_process.c | 14 +++++++------- src/vbox/vbox_tmpl.c | 57 +++++++++++++++++++++++++++------------------------------ src/vmx/vmx.c | 31 ++++++++++++++++--------------- src/xenxs/xen_sxpr.c | 21 +++++++++++---------- src/xenxs/xen_xm.c | 21 +++++++++++---------- 14 files changed, 208 insertions(+), 137 deletions(-)

--- src/conf/domain_conf.c | 31 +++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 23 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0c75838..90a6359 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -700,6 +700,37 @@ VIR_ENUM_IMPL(virDomainNumatuneMemPlacementMode, "static", "auto"); +/* For NIC model macro, a comment marks the start of a model + * group which ends with the model just before next comment + * or extends to the end of list. + */ +VIR_ENUM_IMPL(virDomainNICModel, + VIR_DOMAIN_NIC_MODEL_LAST, + "default", + "spapr-vlan", /* qemu */ + + "virtio", /* qemu and vbox */ + + "ne2k_isa", /* qemu and Xen */ + "ne2k_pci", + "pcnet", + "rtl8139", + + "e1000", /* qemu, Xen and VMX */ + + "netfront", /* Xen(hvm) and libxl */ + + "vlance", /* VMX */ + "vmxnet", + "vmxnet2", + "vmxnet3", + + "Am79C970A", /* vbox */ + "Am79C973", + "82540EM", + "82545EM", + "82543GC"); + #define VIR_DOMAIN_XML_WRITE_FLAGS VIR_DOMAIN_XML_SECURE #define VIR_DOMAIN_XML_READ_FLAGS VIR_DOMAIN_XML_INACTIVE diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 4ffa4aa..0a06e11 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -782,6 +782,28 @@ struct _virDomainFSDef { unsigned long long space_soft_limit; /* in bytes */ }; +enum virDomainNICModel { + VIR_DOMAIN_NIC_MODEL_DEFAULT = 0, + VIR_DOMAIN_NIC_MODEL_SPAPR_VLAN, + VIR_DOMAIN_NIC_MODEL_VIRTIO, + VIR_DOMAIN_NIC_MODEL_NE2K_ISA, + VIR_DOMAIN_NIC_MODEL_NE2K_PCI, + VIR_DOMAIN_NIC_MODEL_PCNET, + VIR_DOMAIN_NIC_MODEL_RTL8139, + VIR_DOMAIN_NIC_MODEL_E1000, + VIR_DOMAIN_NIC_MODEL_NETFRONT, + VIR_DOMAIN_NIC_MODEL_VLANCE, + VIR_DOMAIN_NIC_MODEL_VMXNET, + VIR_DOMAIN_NIC_MODEL_VMXNET2, + VIR_DOMAIN_NIC_MODEL_VMXNET3, + VIR_DOMAIN_NIC_MODEL_AM79C970A, + VIR_DOMAIN_NIC_MODEL_AM79C973, + VIR_DOMAIN_NIC_MODEL_82540EM, + VIR_DOMAIN_NIC_MODEL_82545EM, + VIR_DOMAIN_NIC_MODEL_82543GC, + + VIR_DOMAIN_NIC_MODEL_LAST +}; /* 5 different types of networking config */ enum virDomainNetType { @@ -2324,6 +2346,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceClipboardCopypaste) VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode) VIR_ENUM_DECL(virDomainNumatuneMemMode) VIR_ENUM_DECL(virDomainNumatuneMemPlacementMode) +VIR_ENUM_DECL(virDomainNICModel) VIR_ENUM_DECL(virDomainHyperv) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) -- 1.7.11.2

--- src/conf/domain_conf.c | 32 ++++++++-------------- src/conf/domain_conf.h | 2 +- src/libvirt_private.syms | 2 ++ src/libxl/libxl_conf.c | 5 ++-- src/parallels/parallels_driver.c | 2 +- src/qemu/qemu_command.c | 26 +++++++++--------- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 10 ++++--- src/qemu/qemu_process.c | 14 +++++----- src/vbox/vbox_tmpl.c | 57 +++++++++++++++++++--------------------- src/vmx/vmx.c | 31 +++++++++++----------- src/xenxs/xen_sxpr.c | 21 ++++++++------- src/xenxs/xen_xm.c | 21 ++++++++------- 13 files changed, 110 insertions(+), 115 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 90a6359..96203e2 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1150,8 +1150,6 @@ void virDomainNetDefFree(virDomainNetDefPtr def) if (!def) return; - VIR_FREE(def->model); - switch (def->type) { case VIR_DOMAIN_NET_TYPE_ETHERNET: VIR_FREE(def->data.ethernet.dev); @@ -5220,9 +5218,6 @@ error: return ret; } -#define NET_MODEL_CHARS \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ091234567890_-" - /* Parse the XML definition for a network interface * @param node XML nodeset to parse for net definition * @return 0 on success, -1 on failure @@ -5592,23 +5587,17 @@ virDomainNetDefParseXML(virCapsPtr caps, ifname = NULL; } - /* NIC model (see -net nic,model=?). We only check that it looks - * reasonable, not that it is a supported NIC type. FWIW kvm - * supports these types as of April 2008: - * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio - * QEMU PPC64 supports spapr-vlan - */ if (model != NULL) { - if (strspn(model, NET_MODEL_CHARS) < strlen(model)) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("Model name contains invalid characters")); + int m; + if ((m = virDomainNICModelTypeFromString(model)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unknown NIC model has been specified")); goto error; } - def->model = model; - model = NULL; + def->model = m; } - if (def->model && STREQ(def->model, "virtio")) { + if (def->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) { if (backend != NULL) { int name; if ((name = virDomainNetBackendTypeFromString(backend)) < 0 || @@ -11254,10 +11243,11 @@ virDomainNetDefCheckABIStability(virDomainNetDefPtr src, return false; } - if (STRNEQ_NULLABLE(src->model, dst->model)) { + if (src->model != dst->model) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target network card model %s does not match source %s"), - NULLSTR(dst->model), NULLSTR(src->model)); + virDomainNICModelTypeToString(dst->model), + virDomainNICModelTypeToString(src->model)); return false; } @@ -13175,8 +13165,8 @@ virDomainNetDefFormat(virBufferPtr buf, } if (def->model) { virBufferEscapeString(buf, "<model type='%s'/>\n", - def->model); - if (STREQ(def->model, "virtio") && + virDomainNICModelTypeToString(def->model)); + if ((def->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) && (def->driver.virtio.name || def->driver.virtio.txmode)) { virBufferAddLit(buf, "<driver"); if (def->driver.virtio.name) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0a06e11..6425290 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -879,7 +879,7 @@ struct _virDomainActualNetDef { struct _virDomainNetDef { enum virDomainNetType type; virMacAddr mac; - char *model; + int model; union { struct { enum virDomainNetBackendType name; /* which driver backend to use */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f399871..499add9 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -250,6 +250,8 @@ virDomainNetGetActualVlan; virDomainNetInsert; virDomainNetRemove; virDomainNetTypeToString; +virDomainNICModelTypeFromString; +virDomainNICModelTypeToString; virDomainNostateReasonTypeFromString; virDomainNostateReasonTypeToString; virDomainNumatuneMemModeTypeFromString; diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 4ce5dec..c963834 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -587,8 +587,9 @@ libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic) virMacAddrGetRaw(&l_nic->mac, x_nic->mac); - if (l_nic->model && !STREQ(l_nic->model, "netfront")) { - if ((x_nic->model = strdup(l_nic->model)) == NULL) { + if (l_nic->model && l_nic->model != VIR_DOMAIN_NIC_MODEL_NETFRONT) { + const char *model = virDomainNICModelTypeToString(l_nic->model); + if ((x_nic->model = strdup(model)) == NULL) { virReportOOMError(); return -1; } diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index 8f8fdac..ed1d4d4 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1814,7 +1814,7 @@ static int parallelsApplyIfaceParams(parallelsDomObjPtr pdom, goto cleanup; } - if (!STREQ_NULLABLE(oldnet->model, newnet->model)) { + if (oldnet->model != newnet->model) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("Changing network device model is not supported")); goto cleanup; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dee493f..5cb013c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -155,7 +155,7 @@ qemuPhysIfaceConnect(virDomainDefPtr def, virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNET_HDR) && - net->model && STREQ(net->model, "virtio")) + net->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) vnet_hdr = 1; rc = virNetDevMacVLanCreateWithVPortProfile( @@ -266,7 +266,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, } if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNET_HDR) && - net->model && STREQ(net->model, "virtio")) { + net->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) { tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR; } @@ -345,7 +345,7 @@ qemuOpenVhostNet(virDomainDefPtr def, } /* If the nic model isn't virtio, don't try to open. */ - if (!(net->model && STREQ(net->model, "virtio"))) { + if (net->model != VIR_DOMAIN_NIC_MODEL_VIRTIO) { if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("vhost-net is only supported for " @@ -814,10 +814,10 @@ qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def, for (i = 0; i < def->nnets ; i++) { if ((def->os.arch == VIR_ARCH_S390 || def->os.arch == VIR_ARCH_S390X) && - def->nets[i]->model == NULL) { - def->nets[i]->model = strdup("virtio"); + !def->nets[i]->model) { + def->nets[i]->model = VIR_DOMAIN_NIC_MODEL_VIRTIO; } - if (STREQ(def->nets[i]->model,"virtio") && + if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_VIRTIO && def->nets[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { def->nets[i]->info.type = type; } @@ -908,8 +908,7 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, /* Default values match QEMU. See spapr_(llan|vscsi|vty).c */ for (i = 0 ; i < def->nnets; i++) { - if (def->nets[i]->model && - STREQ(def->nets[i]->model, "spapr-vlan")) + if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_SPAPR_VLAN) def->nets[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; if (qemuAssignSpaprVIOAddress(def, &def->nets[i]->info, 0x1000ul) < 0) @@ -3137,7 +3136,7 @@ qemuBuildNicStr(virDomainNetDefPtr net, net->mac.addr[4], net->mac.addr[5], vlan, (net->model ? ",model=" : ""), - (net->model ? net->model : ""), + (net->model ? virDomainNICModelTypeToString(net->model) : ""), (net->info.alias ? ",name=" : ""), (net->info.alias ? net->info.alias : "")) < 0) { virReportOOMError(); @@ -3160,7 +3159,7 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, if (!net->model) { nic = "rtl8139"; - } else if (STREQ(net->model, "virtio")) { + } else if (net->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) { if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { nic = "virtio-net-s390"; @@ -3169,7 +3168,7 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, } usingVirtio = true; } else { - nic = net->model; + nic = virDomainNICModelTypeToString(net->model); } virBufferAdd(&buf, nic, strlen(nic)); @@ -7848,8 +7847,9 @@ qemuParseCommandLineNet(virCapsPtr qemuCaps, goto cleanup; } } else if (STREQ(keywords[i], "model")) { - def->model = values[i]; - values[i] = NULL; + if ((def->model = virDomainNICModelTypeFromString(values[i])) < 0) + goto cleanup; + VIR_FREE(values[i]); } else if (STREQ(keywords[i], "vhost")) { if ((values[i] == NULL) || STREQ(values[i], "on")) { def->driver.virtio.name = VIR_DOMAIN_NET_BACKEND_TYPE_VHOST; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 435c37c..76b1082 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5279,7 +5279,7 @@ static char *qemuDomainXMLToNative(virConnectPtr conn, for (i = 0 ; i < def->nnets ; i++) { virDomainNetDefPtr net = def->nets[i]; int bootIndex = net->info.bootIndex; - char *model = net->model; + int model = net->model; if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { int actualType = virDomainNetGetActualType(net); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 78961a7..215b0a8 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1476,15 +1476,17 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, goto cleanup; } - if (STRNEQ_NULLABLE(olddev->model, newdev->model)) { + if (olddev->model != newdev->model) { virReportError(VIR_ERR_NO_SUPPORT, _("cannot modify network device model from %s to %s"), - olddev->model ? olddev->model : "(default)", - newdev->model ? newdev->model : "(default)"); + olddev->model ? virDomainNICModelTypeToString(olddev->model) : + "(default)", + newdev->model ? virDomainNICModelTypeToString(newdev->model) : + "(default)"); goto cleanup; } - if (olddev->model && STREQ(olddev->model, "virtio") && + if (olddev->model == VIR_DOMAIN_NIC_MODEL_VIRTIO && (olddev->driver.virtio.name != newdev->driver.virtio.name || olddev->driver.virtio.txmode != newdev->driver.virtio.txmode || olddev->driver.virtio.ioeventfd != newdev->driver.virtio.ioeventfd || diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 732964f..c5f5cee 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2359,24 +2359,24 @@ qemuProcessGetPCINetVendorProduct(virDomainNetDefPtr def, if (!def->model) return -1; - if (STREQ(def->model, "ne2k_pci")) { + if (def->model == VIR_DOMAIN_NIC_MODEL_NE2K_PCI) { *vendor = QEMU_PCI_VENDOR_REALTEK; *product = QEMU_PCI_PRODUCT_NIC_NE2K; - } else if (STREQ(def->model, "pcnet")) { + } else if (def->model == VIR_DOMAIN_NIC_MODEL_PCNET) { *vendor = QEMU_PCI_VENDOR_AMD; *product = QEMU_PCI_PRODUCT_NIC_PCNET; - } else if (STREQ(def->model, "rtl8139")) { + } else if (def->model == VIR_DOMAIN_NIC_MODEL_RTL8139) { *vendor = QEMU_PCI_VENDOR_REALTEK; *product = QEMU_PCI_PRODUCT_NIC_RTL8139; - } else if (STREQ(def->model, "e1000")) { + } else if (def->model == VIR_DOMAIN_NIC_MODEL_E1000) { *vendor = QEMU_PCI_VENDOR_INTEL; *product = QEMU_PCI_PRODUCT_NIC_E1000; - } else if (STREQ(def->model, "virtio")) { + } else if (def->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) { *vendor = QEMU_PCI_VENDOR_REDHAT; *product = QEMU_PCI_PRODUCT_NIC_VIRTIO; } else { VIR_INFO("Unexpected NIC model %s, cannot get PCI address", - def->model); + virDomainNICModelTypeToString(def->model)); return -1; } return 0; @@ -2543,7 +2543,7 @@ qemuProcessDetectPCIAddresses(virDomainObjPtr vm, addrs, naddrs) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot find PCI address for %s NIC"), - vm->def->nets[i]->model); + virDomainNICModelTypeToString(vm->def->nets[i]->model)); return -1; } } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index cd88579..fc50aad 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3015,21 +3015,20 @@ sharedFoldersCleanup: } adapter->vtbl->GetAdapterType(adapter, &adapterType); - if (adapterType == NetworkAdapterType_Am79C970A) { - def->nets[netAdpIncCnt]->model = strdup("Am79C970A"); - } else if (adapterType == NetworkAdapterType_Am79C973) { - def->nets[netAdpIncCnt]->model = strdup("Am79C973"); - } else if (adapterType == NetworkAdapterType_I82540EM) { - def->nets[netAdpIncCnt]->model = strdup("82540EM"); - } else if (adapterType == NetworkAdapterType_I82545EM) { - def->nets[netAdpIncCnt]->model = strdup("82545EM"); - } else if (adapterType == NetworkAdapterType_I82543GC) { - def->nets[netAdpIncCnt]->model = strdup("82543GC"); + if (adapterType == NetworkAdapterType_Am79C970A) + def->nets[netAdpIncCnt]->model = VIR_DOMAIN_NIC_MODEL_AM79C970A; + else if (adapterType == NetworkAdapterType_Am79C973) + def->nets[netAdpIncCnt]->model = VIR_DOMAIN_NIC_MODEL_AM79C973; + else if (adapterType == NetworkAdapterType_I82540EM) + def->nets[netAdpIncCnt]->model = VIR_DOMAIN_NIC_MODEL_82540EM; + else if (adapterType == NetworkAdapterType_I82545EM) + def->nets[netAdpIncCnt]->model = VIR_DOMAIN_NIC_MODEL_82545EM; + else if (adapterType == NetworkAdapterType_I82543GC) + def->nets[netAdpIncCnt]->model = VIR_DOMAIN_NIC_MODEL_82543GC; #if VBOX_API_VERSION >= 3001 - } else if (adapterType == NetworkAdapterType_Virtio) { - def->nets[netAdpIncCnt]->model = strdup("virtio"); + else if (adapterType == NetworkAdapterType_Virtio) + def->nets[netAdpIncCnt]->model = VIR_DOMAIN_NIC_MODEL_VIRTIO; #endif /* VBOX_API_VERSION >= 3001 */ - } adapter->vtbl->GetMACAddress(adapter, &MACAddressUtf16); VBOX_UTF16_TO_UTF8(MACAddressUtf16, &MACAddress); @@ -4402,7 +4401,8 @@ vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0'; VIR_DEBUG("NIC(%d): Type: %d", i, def->nets[i]->type); - VIR_DEBUG("NIC(%d): Model: %s", i, def->nets[i]->model); + VIR_DEBUG("NIC(%d): Model: %s", i, + virDomainNICModelTypeToString(def->nets[i]->model)); VIR_DEBUG("NIC(%d): Mac: %s", i, macaddr); VIR_DEBUG("NIC(%d): ifname: %s", i, def->nets[i]->ifname); if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { @@ -4423,25 +4423,22 @@ vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) adapter->vtbl->SetEnabled(adapter, 1); - if (def->nets[i]->model) { - if (STRCASEEQ(def->nets[i]->model , "Am79C970A")) { - adapterType = NetworkAdapterType_Am79C970A; - } else if (STRCASEEQ(def->nets[i]->model , "Am79C973")) { - adapterType = NetworkAdapterType_Am79C973; - } else if (STRCASEEQ(def->nets[i]->model , "82540EM")) { - adapterType = NetworkAdapterType_I82540EM; - } else if (STRCASEEQ(def->nets[i]->model , "82545EM")) { - adapterType = NetworkAdapterType_I82545EM; - } else if (STRCASEEQ(def->nets[i]->model , "82543GC")) { - adapterType = NetworkAdapterType_I82543GC; + if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_AM79C970A) + adapterType = NetworkAdapterType_Am79C970A; + else if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_AM79C973) + adapterType = NetworkAdapterType_Am79C973; + else if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_82540EM) + adapterType = NetworkAdapterType_I82540EM; + else if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_82545EM) + adapterType = NetworkAdapterType_I82545EM; + else if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_82543GC) + adapterType = NetworkAdapterType_I82543GC; #if VBOX_API_VERSION >= 3001 - } else if (STRCASEEQ(def->nets[i]->model , "virtio")) { - adapterType = NetworkAdapterType_Virtio; + else if (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) + adapterType = NetworkAdapterType_Virtio; #endif /* VBOX_API_VERSION >= 3001 */ - } - } else { + else adapterType = NetworkAdapterType_Am79C973; - } adapter->vtbl->SetAdapterType(adapter, adapterType); diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index c604bd2..0409b0b 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -2597,10 +2597,10 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def) /* Setup virDomainNetDef */ if (connectionType == NULL || STRCASEEQ(connectionType, "bridged")) { (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE; - (*def)->model = virtualDev; + (*def)->model = virDomainNICModelTypeFromString(virtualDev); (*def)->data.bridge.brname = networkName; - virtualDev = NULL; + VIR_FREE(virtualDev); networkName = NULL; } else if (STRCASEEQ(connectionType, "hostonly")) { /* FIXME */ @@ -2610,16 +2610,16 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def) goto cleanup; } else if (STRCASEEQ(connectionType, "nat")) { (*def)->type = VIR_DOMAIN_NET_TYPE_USER; - (*def)->model = virtualDev; + (*def)->model = virDomainNICModelTypeFromString(virtualDev); - virtualDev = NULL; + VIR_FREE(virtualDev); } else if (STRCASEEQ(connectionType, "custom")) { (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE; - (*def)->model = virtualDev; + (*def)->model = virDomainNICModelTypeFromString(virtualDev); (*def)->data.bridge.brname = networkName; (*def)->ifname = vnet; - virtualDev = NULL; + VIR_FREE(virtualDev); networkName = NULL; vnet = NULL; } else { @@ -3697,27 +3697,28 @@ virVMXFormatEthernet(virDomainNetDefPtr def, int controller, virBufferAsprintf(buffer, "ethernet%d.present = \"true\"\n", controller); /* def:model -> vmx:virtualDev, vmx:features */ - if (def->model != NULL) { - if (STRCASENEQ(def->model, "vlance") && - STRCASENEQ(def->model, "vmxnet") && - STRCASENEQ(def->model, "vmxnet2") && - STRCASENEQ(def->model, "vmxnet3") && - STRCASENEQ(def->model, "e1000")) { + if (def->model) { + const char * model = virDomainNICModelTypeToString(def->model); + if (STRCASENEQ(model, "vlance") && + STRCASENEQ(model, "vmxnet") && + STRCASENEQ(model, "vmxnet2") && + STRCASENEQ(model, "vmxnet3") && + STRCASENEQ(model, "e1000")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Expecting domain XML entry 'devices/interface/model' " "to be 'vlance' or 'vmxnet' or 'vmxnet2' or 'vmxnet3' " - "or 'e1000' but found '%s'"), def->model); + "or 'e1000' but found '%s'"), model); return -1; } - if (STRCASEEQ(def->model, "vmxnet2")) { + if (STRCASEEQ(model, "vmxnet2")) { virBufferAsprintf(buffer, "ethernet%d.virtualDev = \"vmxnet\"\n", controller); virBufferAsprintf(buffer, "ethernet%d.features = \"15\"\n", controller); } else { virBufferAsprintf(buffer, "ethernet%d.virtualDev = \"%s\"\n", - controller, def->model); + controller, model); } } diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index 83b7c74..20cc6c0 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -615,13 +615,12 @@ xenParseSxprNets(virDomainDefPtr def, } if (model && - !(net->model = strdup(model))) - goto no_memory; + (net->model = virDomainNICModelTypeFromString(model)) < 0) + goto cleanup; if (!model && type && - STREQ(type, "netfront") && - !(net->model = strdup("netfront"))) - goto no_memory; + STREQ(type, "netfront")) + net->model = VIR_DOMAIN_NIC_MODEL_NETFRONT; if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0) goto no_memory; @@ -2002,16 +2001,18 @@ xenFormatSxprNet(virConnectPtr conn, virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname); if (!hvm) { - if (def->model != NULL) - virBufferEscapeSexpr(buf, "(model '%s')", def->model); + if (def->model) + virBufferEscapeSexpr(buf, "(model '%s')", + virDomainNICModelTypeToString(def->model)); } else { - if (def->model != NULL && STREQ(def->model, "netfront")) { + if (def->model == VIR_DOMAIN_NIC_MODEL_NETFRONT) { virBufferAddLit(buf, "(type netfront)"); } else { - if (def->model != NULL) { - virBufferEscapeSexpr(buf, "(model '%s')", def->model); + if (def->model) { + virBufferEscapeSexpr(buf, "(model '%s')", + virDomainNICModelTypeToString(def->model)); } /* * apparently (type ioemu) breaks paravirt drivers on HVM so skip diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index 73ba06b..f308542 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -779,13 +779,12 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, goto no_memory; if (model[0] && - !(net->model = strdup(model))) - goto no_memory; + (net->model = virDomainNICModelTypeFromString(model)) < 0) + goto cleanup; if (!model[0] && type[0] && - STREQ(type, "netfront") && - !(net->model = strdup("netfront"))) - goto no_memory; + STREQ(type, "netfront")) + net->model = VIR_DOMAIN_NIC_MODEL_NETFRONT; if (vifname[0] && !(net->ifname = strdup(vifname))) @@ -1387,16 +1386,18 @@ static int xenFormatXMNet(virConnectPtr conn, } if (!hvm) { - if (net->model != NULL) - virBufferAsprintf(&buf, ",model=%s", net->model); + if (net->model) + virBufferAsprintf(&buf, ",model=%s", + virDomainNICModelTypeToString(net->model)); } else { - if (net->model != NULL && STREQ(net->model, "netfront")) { + if (net->model == VIR_DOMAIN_NIC_MODEL_NETFRONT) { virBufferAddLit(&buf, ",type=netfront"); } else { - if (net->model != NULL) - virBufferAsprintf(&buf, ",model=%s", net->model); + if (net->model) + virBufferAsprintf(&buf, ",model=%s", + virDomainNICModelTypeToString(net->model)); /* * apparently type ioemu breaks paravirt drivers on HVM so skip this -- 1.7.11.2

As the enum virDomainNICModel is a big collection of NIC models for all of hypervisors, for qemu/kvm, only some of them are supported, so the patch tries to add a checking for NIC model that is qemu specific. The way of doing this is the same as VMX and Vbox do which have codes to validate the hypervisor-specific NIC model in their implementation rather than domain XML parsing code. --- src/conf/domain_conf.h | 6 ++++++ src/qemu/qemu_command.c | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6425290..687032b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -791,6 +791,12 @@ enum virDomainNICModel { VIR_DOMAIN_NIC_MODEL_PCNET, VIR_DOMAIN_NIC_MODEL_RTL8139, VIR_DOMAIN_NIC_MODEL_E1000, + + /* Add new NIC model for qemu above this. + */ + VIR_DOMAIN_NIC_MODEL_FOR_QEMU_END = + VIR_DOMAIN_NIC_MODEL_E1000, + VIR_DOMAIN_NIC_MODEL_NETFRONT, VIR_DOMAIN_NIC_MODEL_VLANCE, VIR_DOMAIN_NIC_MODEL_VMXNET, diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5cb013c..3a98566 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6032,6 +6032,13 @@ qemuBuildCommandLine(virConnectPtr conn, else vlan = i; + if (net->model < 0 || net->model > VIR_DOMAIN_NIC_MODEL_FOR_QEMU_END) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("NIC model '%s' is unsupported for QEMU"), + virDomainNICModelTypeToString(net->model)); + goto error; + } + /* If appropriate, grab a physical device from the configured * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. -- 1.7.11.2

For USB device, the <address> is optional, so is usb-net. Currently, we couldn't assign default usb address to usb devices, so we definitly ignore it during the assignment of PCI address. Libvirt XML sample: <devices> <interface type='user'> <mac address='52:54:00:32:6a:91'/> <model type='usb-net'/> <alias name='net1'/> <address type='usb' bus='0' port='1'/> </interface> </devices> qemu commandline: qemu ${other_vm_args} -netdev user,id=hostnet1 \ -device usb-net,netdev=hostnet1,id=net1,\ mac=52:54:00:32:6a:91,bus=usb.0,port=1 --- docs/formatdomain.html.in | 29 +++++++++++------------------ src/conf/domain_conf.c | 15 ++++++++++++--- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 8 +++++++- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a9003d7..eb7b5dc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2960,24 +2960,17 @@ <p> For hypervisors which support this, you can set the model of - emulated network interface card. - </p> - - <p> - The values for <code>type</code> aren't defined specifically by - libvirt, but by what the underlying hypervisor supports (if - any). For QEMU and KVM you can get a list of supported models - with these commands: - </p> - -<pre> -qemu -net nic,model=? /dev/null -qemu-kvm -net nic,model=? /dev/null -</pre> - - <p> - Typical values for QEMU and KVM include: - ne2k_isa i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio + emulated network interface card. For QEMU and KVM, the supported NIC models + are virtio, ne2k_isa, ne2k_pci, pcnet, rtl8139, e1000, usb-net + <span class="since">(since 1.0.3)</span>, spapr-vlan(only PPC64). + For Xen, there are ne2k_isa, ne2k_pci, pcnet, rtl8139, e1000, netfront. For VMWare, + vlance, vmxnet, vmxnet2, vmxnet3 are supported. And for Vbox, Am79C970A, Am79C973, + 82540EM, 82545EM, 82543GC are its supported models. + (All of these models are PCI devices, except usb-net which emulates a Netchip + Linux-USB Ethernet/RNDIS usb ethernet device). For models of PCI type, a sub-element + <code><address></code> with <code>type='pci'</code> can be used to tie + the device to a particular PCI slot. It is <code>type='usb'</code> for usb-net + to tie to USB controller. <a href="#elementsAddress">documented above</a>. </p> <h5><a name="elementsDriverBackendOptions">Setting NIC driver-specific options</a></h5> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 96203e2..78a9a77 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -708,6 +708,7 @@ VIR_ENUM_IMPL(virDomainNICModel, VIR_DOMAIN_NIC_MODEL_LAST, "default", "spapr-vlan", /* qemu */ + "usb-net", "virtio", /* qemu and vbox */ @@ -5427,15 +5428,16 @@ virDomainNetDefParseXML(virCapsPtr caps, goto error; } - /* XXX what about ISA/USB based NIC models - once we support + /* XXX what about ISA based NIC models - once we support * them we should make sure address type is correct */ if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && - def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Network interfaces must use 'pci' address type")); + _("Network interfaces have incorrect address type")); goto error; } @@ -5642,6 +5644,13 @@ virDomainNetDefParseXML(virCapsPtr caps, } def->driver.virtio.event_idx = idx; } + } else if (def->model == VIR_DOMAIN_NIC_MODEL_USB_NET) { + if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Interface of usb-net model requires address of usb type")); + goto error; + } } def->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 687032b..8ef044e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -785,6 +785,7 @@ struct _virDomainFSDef { enum virDomainNICModel { VIR_DOMAIN_NIC_MODEL_DEFAULT = 0, VIR_DOMAIN_NIC_MODEL_SPAPR_VLAN, + VIR_DOMAIN_NIC_MODEL_USB_NET, VIR_DOMAIN_NIC_MODEL_VIRTIO, VIR_DOMAIN_NIC_MODEL_NE2K_ISA, VIR_DOMAIN_NIC_MODEL_NE2K_PCI, diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3a98566..ad4ffec 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1530,7 +1530,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, * instead of here. */ if ((def->nets[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) || - (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) { + (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) || + (def->nets[i]->model == VIR_DOMAIN_NIC_MODEL_USB_NET)) { continue; } if (qemuDomainPCIAddressSetNextAddr(addrs, &def->nets[i]->info) < 0) @@ -3167,6 +3168,11 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, nic = "virtio-net-pci"; } usingVirtio = true; + } else if ((net->model == VIR_DOMAIN_NIC_MODEL_USB_NET) && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_NET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("usb-net is not supported in this QEMU binary")); + goto error; } else { nic = virDomainNICModelTypeToString(net->model); } -- 1.7.11.2
participants (1)
-
Guannan Ren