diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index bb72452c05..e7b585cfed 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3874,7 +3874,11 @@ qemu-kvm -net nic,model=? /dev/null <source network='default'/> <target dev='vnet1'/> <model type='virtio'/> - <driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5'/> + <driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5'> + <host csum='off' gso='off' tso4='off' tso6='off' ecn='off' ufo='off'/> + <guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off'/> + </driver> + </interface> </devices> ... @@ -3978,6 +3982,24 @@ qemu-kvm -net nic,model=? /dev/null processor, resulting in much higher throughput. Since 1.0.6 (QEMU and KVM only) +
host offloading options
+
+ The csum, gso, tso4, + tso6, ecn and ufo + attributes with possible values on + and off can be used to turn off host offloading options. + By default, the supported offloads are enabled by QEMU. + Since 1.2.9 (QEMU only) +
+
guest offloading options
+
+ The csum, tso4, + tso6, ecn and ufo + attributes with possible values on + and off can be used to turn off guest offloading options. + By default, the supported offloads are enabled by QEMU. + Since 1.2.9 (QEMU only) +
Setting network backend-specific options
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index b6b309d838..1a266e571c 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2366,7 +2366,71 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0a7d0b804b..b114737549 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -6919,6 +6919,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *ioeventfd = NULL; char *event_idx = NULL; char *queues = NULL; + char *str = NULL; char *filter = NULL; char *internal = NULL; char *devaddr = NULL; @@ -7414,6 +7415,115 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, } def->driver.virtio.queues = q; } + if ((str = virXPathString("string(./driver/host/@csum)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown host csum mode '%s'"), + str); + goto error; + } + def->driver.virtio.host.csum = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/host/@gso)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown host gso mode '%s'"), + str); + goto error; + } + def->driver.virtio.host.gso = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/host/@tso4)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown host tso4 mode '%s'"), + str); + goto error; + } + def->driver.virtio.host.tso4 = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/host/@tso6)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown host tso6 mode '%s'"), + str); + goto error; + } + def->driver.virtio.host.tso6 = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/host/@ecn)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown host ecn mode '%s'"), + str); + goto error; + } + def->driver.virtio.host.ecn = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/host/@ufo)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown host ufo mode '%s'"), + str); + goto error; + } + def->driver.virtio.host.ufo = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/guest/@csum)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown guest csum mode '%s'"), + str); + goto error; + } + def->driver.virtio.guest.csum = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/guest/@tso4)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown guest tso4 mode '%s'"), + str); + goto error; + } + def->driver.virtio.guest.tso4 = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/guest/@tso6)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown guest tso6 mode '%s'"), + str); + goto error; + } + def->driver.virtio.guest.tso6 = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/guest/@ecn)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown guest ecn mode '%s'"), + str); + goto error; + } + def->driver.virtio.guest.ecn = val; + } + VIR_FREE(str); + if ((str = virXPathString("string(./driver/guest/@ufo)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown guest ufo mode '%s'"), + str); + goto error; + } + def->driver.virtio.guest.ufo = val; + } } def->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT; @@ -7471,6 +7581,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(ioeventfd); VIR_FREE(event_idx); VIR_FREE(queues); + VIR_FREE(str); VIR_FREE(filter); VIR_FREE(type); VIR_FREE(internal); @@ -16511,6 +16622,80 @@ virDomainActualNetDefFormat(virBufferPtr buf, } +static int +virDomainVirtioNetGuestOptsFormat(char **outstr, + virDomainNetDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + if (def->driver.virtio.guest.csum) { + virBufferAsprintf(&buf, "csum='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.guest.csum)); + } + if (def->driver.virtio.guest.tso4) { + virBufferAsprintf(&buf, "tso4='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.guest.tso4)); + } + if (def->driver.virtio.guest.tso6) { + virBufferAsprintf(&buf, "tso6='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.guest.tso6)); + } + if (def->driver.virtio.guest.ecn) { + virBufferAsprintf(&buf, "ecn='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.guest.ecn)); + } + if (def->driver.virtio.guest.ufo) { + virBufferAsprintf(&buf, "ufo='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.guest.ufo)); + } + virBufferTrim(&buf, " ", -1); + + if (virBufferCheckError(&buf) < 0) + return -1; + + *outstr = virBufferContentAndReset(&buf); + return 0; +} + + +static int +virDomainVirtioNetHostOptsFormat(char **outstr, + virDomainNetDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + if (def->driver.virtio.host.csum) { + virBufferAsprintf(&buf, "csum='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.host.csum)); + } + if (def->driver.virtio.host.gso) { + virBufferAsprintf(&buf, "gso='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.host.gso)); + } + if (def->driver.virtio.host.tso4) { + virBufferAsprintf(&buf, "tso4='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.host.tso4)); + } + if (def->driver.virtio.host.tso6) { + virBufferAsprintf(&buf, "tso6='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.host.tso6)); + } + if (def->driver.virtio.host.ecn) { + virBufferAsprintf(&buf, "ecn='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.host.ecn)); + } + if (def->driver.virtio.host.ufo) { + virBufferAsprintf(&buf, "ufo='%s' ", + virTristateSwitchTypeToString(def->driver.virtio.host.ufo)); + } + virBufferTrim(&buf, " ", -1); + + if (virBufferCheckError(&buf) < 0) + return -1; + + *outstr = virBufferContentAndReset(&buf); + return 0; +} + + static int virDomainVirtioNetDriverFormat(char **outstr, virDomainNetDefPtr def) @@ -16562,7 +16747,6 @@ virDomainNetDefFormat(virBufferPtr buf, virDomainHostdevDefPtr hostdef = NULL; char macstr[VIR_MAC_STRING_BUFLEN]; - if (publicActual) { if (!(typeStr = virDomainNetTypeToString(actualType))) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -16721,14 +16905,36 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, "\n", def->model); if (STREQ(def->model, "virtio")) { - char *str; + char *str = NULL, *gueststr = NULL, *hoststr = NULL; + int rc = 0; - if (virDomainVirtioNetDriverFormat(&str, def) < 0) - return -1; + if (virDomainVirtioNetDriverFormat(&str, def) < 0 || + virDomainVirtioNetGuestOptsFormat(&gueststr, def) < 0 || + virDomainVirtioNetHostOptsFormat(&hoststr, def) < 0) + rc = -1; - if (str) - virBufferAsprintf(buf, "\n", str); + if (!gueststr && !hoststr) { + if (str) + virBufferAsprintf(buf, "\n", str); + } else { + if (str) + virBufferAsprintf(buf, "\n", str); + else + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + if (hoststr) + virBufferAsprintf(buf, "\n", hoststr); + if (gueststr) + virBufferAsprintf(buf, "\n", gueststr); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } VIR_FREE(str); + VIR_FREE(hoststr); + VIR_FREE(gueststr); + + if (rc < 0) + return -1; } } if (def->backend.tap || def->backend.vhost) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d97b1f8619..ea201b3a33 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -895,6 +895,21 @@ struct _virDomainNetDef { virTristateSwitch ioeventfd; virTristateSwitch event_idx; unsigned int queues; /* Multiqueue virtio-net */ + struct { + virTristateSwitch csum; + virTristateSwitch gso; + virTristateSwitch tso4; + virTristateSwitch tso6; + virTristateSwitch ecn; + virTristateSwitch ufo; + } host; + struct { + virTristateSwitch csum; + virTristateSwitch tso4; + virTristateSwitch tso6; + virTristateSwitch ecn; + virTristateSwitch ufo; + } guest; } virtio; } driver; struct { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-disable-offloads.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-disable-offloads.xml new file mode 100644 index 0000000000..e368c4352a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-disable-offloads.xml @@ -0,0 +1,35 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + + + + + + + + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 56a371ea38..9a568806d7 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -261,6 +261,7 @@ mymain(void) DO_TEST("net-user"); DO_TEST("net-virtio"); DO_TEST("net-virtio-device"); + DO_TEST("net-virtio-disable-offloads"); DO_TEST("net-eth"); DO_TEST("net-eth-ifname"); DO_TEST("net-virtio-network-portgroup");