@@ -436,6 +436,10 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
"hostdev",
"udp")
+VIR_ENUM_IMPL(virDomainNetModel, VIR_DOMAIN_NET_MODEL_LAST,
+ "unknown",
+ "netfront")
+
VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
"default",
"qemu",
@@ -2121,6 +2125,7 @@ virDomainNetDefClear(virDomainNetDefPtr def)
return;
VIR_FREE(def->modelstr);
+ def->model = VIR_DOMAIN_NET_MODEL_UNKNOWN;
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@@ -11390,21 +11395,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
goto error;
}
- /* 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"));
- goto error;
- }
- def->modelstr = model;
- model = NULL;
- }
+ if (model != NULL &&
+ virDomainNetSetModelString(def, model) < 0)
+ goto error;
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_NETWORK:
@@ -21978,6 +21971,14 @@ virDomainNetDefCheckABIStability(virDomainNetDefPtr src,
return false;
}
+ if (src->model != dst->model) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target network card model %s does not match source %s"),
+ virDomainNetModelTypeToString(dst->model),
+ virDomainNetModelTypeToString(src->model));
+ return false;
+ }
+
if (src->mtu != dst->mtu) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target network card MTU %d does not match source %d"),
@@ -29841,6 +29842,8 @@ virDomainNetGetActualTrustGuestRxFilters(virDomainNetDefPtr iface)
const char *
virDomainNetGetModelString(const virDomainNetDef *iface)
{
+ if (iface->model)
+ return virDomainNetModelTypeToString(iface->model);
return iface->modelstr;
}
@@ -29848,13 +29851,31 @@ int
virDomainNetSetModelString(virDomainNetDefPtr iface,
const char *model)
{
- return VIR_STRDUP(iface->modelstr, model);
+ VIR_FREE(iface->modelstr);
+ if ((iface->model = virDomainNetModelTypeFromString(model)) >= 0)
+ return 0;
+
+ iface->model = VIR_DOMAIN_NET_MODEL_UNKNOWN;
+ if (!model)
+ return 0;
+
+ if (strspn(model, NET_MODEL_CHARS) < strlen(model)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Model name contains invalid characters"));
+ return -1;
+ }
+
+ if (VIR_STRDUP(iface->modelstr, model) < 0)
+ return -1;
+ return 0;
}
int
virDomainNetStreqModelString(const virDomainNetDef *iface,
const char *model)
{
+ if (iface->model)
+ return iface->model == virDomainNetModelTypeFromString(model);
return STREQ_NULLABLE(iface->modelstr, model);
}
@@ -29862,6 +29883,9 @@ int
virDomainNetStrcaseeqModelString(const virDomainNetDef *iface,
const char *model)
{
+ if (iface->model)
+ return STRCASEEQ(virDomainNetModelTypeToString(iface->model),
+ model);
return iface->modelstr && STRCASEEQ(iface->modelstr, model);
}
@@ -960,6 +960,14 @@ typedef enum {
VIR_DOMAIN_NET_TYPE_LAST
} virDomainNetType;
+/* network model types */
+typedef enum {
+ VIR_DOMAIN_NET_MODEL_UNKNOWN,
+ VIR_DOMAIN_NET_MODEL_NETFRONT,
+
+ VIR_DOMAIN_NET_MODEL_LAST
+} virDomainNetModelType;
+
/* the backend driver used for virtio interfaces */
typedef enum {
VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT, /* prefer kernel, fall back to user */
@@ -1021,6 +1029,7 @@ struct _virDomainNetDef {
virDomainNetType type;
virMacAddr mac;
bool mac_generated; /* true if mac was *just now* auto-generated by libvirt */
+ int model; /* virDomainNetModelType */
char *modelstr;
union {
struct {
@@ -3493,6 +3502,7 @@ VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainNetBackend)
VIR_ENUM_DECL(virDomainNetVirtioTxMode)
VIR_ENUM_DECL(virDomainNetInterfaceLinkState)
+VIR_ENUM_DECL(virDomainNetModel)
VIR_ENUM_DECL(virDomainChrDevice)
VIR_ENUM_DECL(virDomainChrChannelTarget)
VIR_ENUM_DECL(virDomainChrConsoleTarget)
@@ -475,6 +475,8 @@ virDomainNetGetActualVlan;
virDomainNetGetModelString;
virDomainNetHasVirtioModel;
virDomainNetInsert;
+virDomainNetModelTypeFromString;
+virDomainNetModelTypeToString;
virDomainNetNotifyActualDevice;
virDomainNetReleaseActualDevice;
virDomainNetRemove;
@@ -1269,7 +1269,7 @@ libxlMakeNic(virDomainDefPtr def,
if (virDomainNetGetModelString(l_nic)) {
if ((def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
def->os.type == VIR_DOMAIN_OSTYPE_XENPVH) &&
- !virDomainNetStreqModelString(l_nic, "netfront")) {
+ l_nic->model != VIR_DOMAIN_NET_MODEL_NETFRONT) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("only model 'netfront' is supported for "
"Xen PV(H) domains"));
@@ -1277,7 +1277,7 @@ libxlMakeNic(virDomainDefPtr def,
}
if (VIR_STRDUP(x_nic->model, virDomainNetGetModelString(l_nic)) < 0)
goto cleanup;
- if (virDomainNetStreqModelString(l_nic, "netfront"))
+ if (l_nic->model == VIR_DOMAIN_NET_MODEL_NETFRONT)
x_nic->nictype = LIBXL_NIC_TYPE_VIF;
else
x_nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
@@ -3711,6 +3711,14 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
goto cleanup;
}
+ if (olddev->model != newdev->model) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("cannot modify network device model from %s to %s"),
+ virDomainNetModelTypeToString(olddev->model),
+ virDomainNetModelTypeToString(newdev->model));
+ goto cleanup;
+ }
+
if (virDomainNetHasVirtioModel(olddev) &&
(olddev->driver.virtio.name != newdev->driver.virtio.name ||
olddev->driver.virtio.txmode != newdev->driver.virtio.txmode ||
@@ -1068,13 +1068,13 @@ xenParseVif(char *entry, const char *vif_typename)
VIR_STRDUP(net->script, script) < 0)
goto cleanup;
- if (model[0] &&
- virDomainNetSetModelString(net, model) < 0)
- goto cleanup;
-
- if (!model[0] && type[0] && STREQ(type, vif_typename) &&
- virDomainNetSetModelString(net, "netfront") < 0)
- goto cleanup;
+ if (model[0]) {
+ if (virDomainNetSetModelString(net, model) < 0)
+ goto cleanup;
+ } else {
+ if (type[0] && STREQ(type, vif_typename))
+ net->model = VIR_DOMAIN_NET_MODEL_NETFRONT;
+ }
if (vifname[0] &&
VIR_STRDUP(net->ifname, vifname) < 0)
@@ -1427,7 +1427,7 @@ xenFormatNet(virConnectPtr conn,
virBufferAsprintf(&buf, ",model=%s",
virDomainNetGetModelString(net));
} else {
- if (virDomainNetStreqModelString(net, "netfront"))
+ if (net->model == VIR_DOMAIN_NET_MODEL_NETFRONT)
virBufferAsprintf(&buf, ",type=%s", vif_typename);
else
virBufferAsprintf(&buf, ",model=%s",
@@ -642,12 +642,13 @@ xenParseSxprNets(virDomainDefPtr def,
}
}
- if (virDomainNetSetModelString(net, model) < 0)
- goto cleanup;
-
- if (!model && type && STREQ(type, "netfront") &&
- virDomainNetSetModelString(net, "netfront") < 0)
- goto cleanup;
+ if (model) {
+ if (virDomainNetSetModelString(net, model) < 0)
+ goto cleanup;
+ } else {
+ if (type && STREQ(type, "netfront"))
+ net->model = VIR_DOMAIN_NET_MODEL_NETFRONT;
+ }
tmp = sexpr_node(node, "device/vif/rate");
if (tmp) {
@@ -1940,7 +1941,7 @@ xenFormatSxprNet(virConnectPtr conn,
virBufferEscapeSexpr(buf, "(model '%s')",
virDomainNetGetModelString(def));
} else {
- if (virDomainNetStreqModelString(def, "netfront"))
+ if (def->model == VIR_DOMAIN_NET_MODEL_NETFRONT)
virBufferAddLit(buf, "(type netfront)");
else
virBufferEscapeSexpr(buf, "(model '%s')",
This adds a network model enum. The virDomainNetDef property is named 'model' like most other devices. When the XML parser or a driver calls NetSetModelString, if the passed string is in the enum, we will set net->model, otherwise we copy the string into net->modelstr Add a single example for the 'netfront' xen model, and wire that up, just to verify it's all working Signed-off-by: Cole Robinson <crobinso@redhat.com> --- src/conf/domain_conf.c | 56 +++++++++++++++++++++++++++----------- src/conf/domain_conf.h | 10 +++++++ src/libvirt_private.syms | 2 ++ src/libxl/libxl_conf.c | 4 +-- src/qemu/qemu_hotplug.c | 8 ++++++ src/xenconfig/xen_common.c | 16 +++++------ src/xenconfig/xen_sxpr.c | 15 +++++----- 7 files changed, 78 insertions(+), 33 deletions(-) -- 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list