[libvirt] [PATCH v2 0/5]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 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 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/5, 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 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(2) [PATCH v2 1/5] conf: fix mismatch on two domain VIR_ENUM_IMPL macro [PATCH v2 2/5] add domain NIC model enum macro [PATCH v2 3/5] net: use virDomainNICModelType{From|To}String functions [PATCH v2 4/5] qemu: add NIC model checking for qemu hypervisor [PATCH v2 5/5] qemu: add usb-net support docs/formatdomain.html.in | 29 +++++++++++------------------ src/conf/domain_conf.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- 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 | 23 ++++++++++++----------- src/xenxs/xen_xm.c | 21 +++++++++++---------- 14 files changed, 215 insertions(+), 142 deletions(-)

--- src/conf/domain_conf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 13c14e9..02124bb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -578,7 +578,7 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_LAST, VIR_ENUM_IMPL(virDomainNostateReason, VIR_DOMAIN_NOSTATE_LAST, "unknown") -#define VIR_DOMAIN_RUNNING_LAST (VIR_DOMAIN_RUNNING_SAVE_CANCELED + 1) +#define VIR_DOMAIN_RUNNING_LAST (VIR_DOMAIN_RUNNING_WAKEUP + 1) VIR_ENUM_IMPL(virDomainRunningReason, VIR_DOMAIN_RUNNING_LAST, "unknown", "booted", @@ -587,13 +587,14 @@ VIR_ENUM_IMPL(virDomainRunningReason, VIR_DOMAIN_RUNNING_LAST, "from snapshot", "unpaused", "migration canceled", - "save canceled") + "save canceled", + "wakeup event") #define VIR_DOMAIN_BLOCKED_LAST (VIR_DOMAIN_BLOCKED_UNKNOWN + 1) VIR_ENUM_IMPL(virDomainBlockedReason, VIR_DOMAIN_BLOCKED_LAST, "unknown") -#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_SHUTTING_DOWN + 1) +#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_SNAPSHOT + 1) VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST, "unknown", "user", @@ -603,7 +604,8 @@ VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST, "ioerror", "watchdog", "from snapshot", - "shutdown") + "shutdown", + "snapshot") #define VIR_DOMAIN_SHUTDOWN_LAST (VIR_DOMAIN_SHUTDOWN_USER + 1) VIR_ENUM_IMPL(virDomainShutdownReason, VIR_DOMAIN_SHUTDOWN_LAST, -- 1.7.11.2

--- 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 02124bb..46b2b1e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -694,6 +694,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 ce36003..353af71 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -768,6 +768,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 { @@ -2301,6 +2323,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 | 23 ++++++++-------- src/xenxs/xen_xm.c | 21 ++++++++------- 13 files changed, 111 insertions(+), 116 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 46b2b1e..4c4d60f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1118,8 +1118,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); @@ -4970,9 +4968,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 @@ -5341,23 +5336,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 || @@ -10989,10 +10978,11 @@ static bool virDomainNetDefCheckABIStability(virDomainNetDefPtr src, goto cleanup; } - 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)); goto cleanup; } @@ -12936,8 +12926,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 353af71..76c1680 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -865,7 +865,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 521f8e0..9d87a5c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -465,6 +465,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 9245a24..1e5e790 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -583,8 +583,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 ea193af..7038969 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1812,7 +1812,7 @@ static int parallelsApplyIfaceParams(parallelsDomObjPtr pdom, return -1; } - 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")); return -1; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 981c692..9ba27a1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -153,7 +153,7 @@ qemuPhysIfaceConnect(virDomainDefPtr def, int vnet_hdr = 0; if (qemuCapsGet(caps, QEMU_CAPS_VNET_HDR) && - net->model && STREQ(net->model, "virtio")) + net->model == VIR_DOMAIN_NIC_MODEL_VIRTIO) vnet_hdr = 1; rc = virNetDevMacVLanCreateWithVPortProfile( @@ -261,7 +261,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, } if (qemuCapsGet(caps, 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; } @@ -339,7 +339,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 " @@ -808,10 +808,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; } @@ -898,8 +898,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) @@ -3149,7 +3148,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(); @@ -3172,7 +3171,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"; @@ -3181,7 +3180,7 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, } usingVirtio = true; } else { - nic = net->model; + nic = virDomainNICModelTypeToString(net->model); } virBufferAdd(&buf, nic, strlen(nic)); @@ -7829,8 +7828,9 @@ qemuParseCommandLineNet(virCapsPtr caps, 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 8c39864..fa685c9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5360,7 +5360,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 19172e1..8ec3e55 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1462,15 +1462,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 2f08215..f1c6ca5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2314,24 +2314,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; @@ -2498,7 +2498,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 2b3fa25..c7147f6 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3004,21 +3004,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); @@ -4394,7 +4393,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) { @@ -4415,25 +4415,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..0bf69a7 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -591,7 +591,7 @@ xenParseSxprNets(virDomainDefPtr def, if (tmp && !(net->data.ethernet.ipaddr = strdup(tmp))) goto no_memory; - } + } tmp = sexpr_node(node, "device/vif/vifname"); /* If vifname is specified in xend config, include it in net @@ -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 code 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 76c1680..6ec2801 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -777,6 +777,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 9ba27a1..fcd7512 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6020,6 +6020,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 bb0b199..2cba848 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2946,24 +2946,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.2)</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 4c4d60f..2d55db7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -702,6 +702,7 @@ VIR_ENUM_IMPL(virDomainNICModel, VIR_DOMAIN_NIC_MODEL_LAST, "default", "spapr-vlan", /* qemu */ + "usb-net", "virtio", /* qemu and vbox */ @@ -5177,14 +5178,15 @@ 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_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; } @@ -5391,6 +5393,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 6ec2801..7e23bd4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -771,6 +771,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 fcd7512..89c9668 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1557,7 +1557,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) @@ -3179,6 +3180,11 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, nic = "virtio-net-pci"; } usingVirtio = true; + } else if ((net->model == VIR_DOMAIN_NIC_MODEL_USB_NET) && + !qemuCapsGet(caps, 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