diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index c67dcfb4bf..0ac88b2dfb 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5338,6 +5338,24 @@ following attributes are available for the ``"virtio"`` NIC driver:
only for ``vhostuser`` type. :since:`Since 3.7.0 (QEMU and KVM only)`
**In general you should leave this option alone, unless you are very certain
you know what you are doing.**
+``rss``
+ The ``rss`` option enables in-qemu/ebpf RSS for virtio NIC. RSS works with
+ virtio and tap backends only. Virtio NIC will be launched with "rss"
+ property. For now "in-qemu" RSS is supported by libvirt.
+ QEMU may load eBPF RSS if it has CAP_SYS_ADMIN permissions, which is
+ not supported by default in libvirt.
+ **In general you should leave this option alone, unless you are very certain
+ you know what you are doing. Proper RSS configuration depends from vcpu,
+ tap, and vhost settings.**
+``rss_hash_report``
+ The ``rss_hash_report`` option enables in-qemu RSS hash report for virtio
+ NIC. Virtio NIC will be launched with a "hash" property. Network packets provided
+ to VM will contain a hash of the packet in the virt header. Usually enabled
+ alongside with ``rss``. Without ``rss`` option, the hash report doesn't affect
+ steering itself but provides vnet header with a calculated hash.
+ **In general you should leave this option alone, unless you are very certain
+ you know what you are doing. Proper RSS configuration depends from vcpu,
+ tap, and vhost settings.**
virtio options
For virtio interfaces, `Virtio-specific options <#elementsVirtio>`__ can also
be set. ( :since:`Since 3.5.0` )
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 98df54e78c..33eace04dc 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10777,6 +10777,16 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
&def->driver.virtio.tx_queue_size) < 0)
goto error;
+ if (virXMLPropTristateSwitch(driver_node, "rss",
+ VIR_XML_PROP_NONE,
+ &def->driver.virtio.rss) < 0)
+ goto error;
+
+ if (virXMLPropTristateSwitch(driver_node, "rss_hash_report",
+ VIR_XML_PROP_NONE,
+ &def->driver.virtio.rss_hash_report) < 0)
+ goto error;
+
if ((tmpNode = virXPathNode("./driver/host", ctxt))) {
if (virXMLPropTristateSwitch(tmpNode, "csum", VIR_XML_PROP_NONE,
&def->driver.virtio.host.csum) < 0)
@@ -24616,6 +24626,14 @@ virDomainVirtioNetDriverFormat(virBuffer *buf,
if (def->driver.virtio.tx_queue_size)
virBufferAsprintf(buf, " tx_queue_size='%u'",
def->driver.virtio.tx_queue_size);
+ if (def->driver.virtio.rss != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(buf, " rss='%s'",
+ virTristateSwitchTypeToString(def->driver.virtio.rss));
+ }
+ if (def->driver.virtio.rss_hash_report != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(buf, " rss_hash_report='%s'",
+ virTristateSwitchTypeToString(def->driver.virtio.rss_hash_report));
+ }
virDomainVirtioOptionsFormat(buf, def->virtio);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1ef3dc8a2b..694491cd63 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1069,6 +1069,8 @@ struct _virDomainNetDef {
virTristateSwitch ecn;
virTristateSwitch ufo;
} guest;
+ virTristateSwitch rss;
+ virTristateSwitch rss_hash_report;
} virtio;
} driver;
struct {
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 8345976e81..c0c14fe558 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -3603,6 +3603,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/net-virtio-rss.xml b/tests/qemuxml2argvdata/net-virtio-rss.xml
new file mode 100644
index 0000000000..5934e1c2d2
--- /dev/null
+++ b/tests/qemuxml2argvdata/net-virtio-rss.xml
@@ -0,0 +1,58 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+ qemu64
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/virtio-options.xml b/tests/qemuxml2argvdata/virtio-options.xml
index 59e293d8e9..486bc453a1 100644
--- a/tests/qemuxml2argvdata/virtio-options.xml
+++ b/tests/qemuxml2argvdata/virtio-options.xml
@@ -53,7 +53,7 @@
-
+
diff --git a/tests/qemuxml2xmloutdata/net-virtio-rss.x86_64-latest.xml b/tests/qemuxml2xmloutdata/net-virtio-rss.x86_64-latest.xml
new file mode 120000
index 0000000000..90c32c96bb
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/net-virtio-rss.x86_64-latest.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/net-virtio-rss.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 9177705254..4d2b2ad784 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -487,6 +487,7 @@ mymain(void)
DO_TEST_NOCAPS("net-many-models");
DO_TEST("net-vdpa", QEMU_CAPS_NETDEV_VHOST_VDPA);
DO_TEST("net-vdpa-multiqueue", QEMU_CAPS_NETDEV_VHOST_VDPA);
+ DO_TEST_CAPS_LATEST("net-virtio-rss");
DO_TEST_NOCAPS("serial-tcp-tlsx509-chardev");
DO_TEST_NOCAPS("serial-tcp-tlsx509-chardev-notls");