ne2k_isa i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
</p>
+ <h5><a name="elementsDriverBackendOptions">Setting NIC driver-specific options</a></h5>
+
+<pre>
+ ...
+ <devices>
+ <interface type='network'>
+ <source network='default'/>
+ <target dev='vnet1'/>
+ <model type='virtio'/>
+ <b><driver txmode='iothread'/></b>
+ </interface>
+ </devices>
+ ...</pre>
+
+ <p>
+ Some NICs may have tunable driver-specific options. These are
+ set as attributes of the <code>driver</code> sub-element of the
+ interface definition. Currently the following attributes are
+ available for the <code>"virtio"</code> NIC driver:
+ </p>
+
+ <dl>
+ <dt><code>txmode</code></dt>
+ <dd>
+ The <code>txmode</code> attribute specifies how to handle
+ transmission of packets when the transmit buffer is full. The
+ value can be either 'iothread' or 'timer'.
+ <span class="since">Since 0.8.8 (QEMU and KVM only)</span><br><br>
+
+ If set to 'iothread', packet tx is all done in an iothread in
+ the bottom half of the driver (this option translates into
+ adding "tx=bh" to the qemu commandline -device virtio-net-pci
+ option).<br><br>
+
+ If set to 'timer', tx work is done in qemu, and if there is
+ more tx data than can be sent at the present time, a timer is
+ set before qemu moves on to do other things; when the timer
+ fires, another attempt is made to send more data.<br><br>
+
+ The resulting difference, according to the qemu developer who
+ added the option is: "bh makes tx more asynchronous and reduces
+ latency, but potentially causes more processor bandwidth
+ contention since the cpu doing the tx isn't necessarily the
+ cpu where the guest generated the packets."<br><br>
+
+ <b>In general you should leave this option alone, unless you
+ are very certain you know what you are doing.</b>
+ </dd>
+ </dl>
+
<h5><a name="elementsNICSTargetOverride">Overriding the target element</a></h5>
<pre>
</choice>
</attribute>
</optional>
+ <optional>
+ <attribute name="txmode">
+ <choice>
+ <value>iothread</value>
+ <value>timer</value>
+ </choice>
+ </attribute>
+ </optional>
<empty/>
</element>
</optional>
"qemu",
"vhost")
+VIR_ENUM_IMPL(virDomainNetVirtioTxMode, VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST,
+ "default",
+ "iothread",
+ "timer")
+
VIR_ENUM_IMPL(virDomainChrChannelTarget,
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
"guestfwd",
char *port = NULL;
char *model = NULL;
char *backend = NULL;
+ char *txmode = NULL;
char *filter = NULL;
char *internal = NULL;
char *devaddr = NULL;
model = virXMLPropString(cur, "type");
} else if (xmlStrEqual (cur->name, BAD_CAST "driver")) {
backend = virXMLPropString(cur, "name");
+ txmode = virXMLPropString(cur, "txmode");
} else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
filter = virXMLPropString(cur, "filter");
VIR_FREE(filterparams);
}
def->driver.virtio.name = name;
}
+ if (txmode != NULL) {
+ int m;
+ if (((m = virDomainNetVirtioTxModeTypeFromString(txmode)) < 0) ||
+ (m == VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT)) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown interface <driver txmode='%s'> "
+ "has been specified"),
+ txmode);
+ goto error;
+ }
+ def->driver.virtio.txmode = m;
+ }
}
if (filter != NULL) {
VIR_FREE(bridge);
VIR_FREE(model);
VIR_FREE(backend);
+ VIR_FREE(txmode);
VIR_FREE(filter);
VIR_FREE(type);
VIR_FREE(internal);
virBufferEscapeString(buf, " <model type='%s'/>\n",
def->model);
if (STREQ(def->model, "virtio") &&
- def->driver.virtio.name) {
+ (def->driver.virtio.name || def->driver.virtio.txmode)) {
virBufferAddLit(buf, " <driver");
if (def->driver.virtio.name) {
virBufferVSprintf(buf, " name='%s'",
virDomainNetBackendTypeToString(def->driver.virtio.name));
}
+ if (def->driver.virtio.txmode) {
+ virBufferVSprintf(buf, " txmode='%s'",
+ virDomainNetVirtioTxModeTypeToString(def->driver.virtio.txmode));
+ }
virBufferAddLit(buf, "/>\n");
}
}
VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
};
+/* the TX algorithm used for virtio interfaces */
+enum virDomainNetVirtioTxModeType {
+ VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT, /* default for this version of qemu */
+ VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD,
+ VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER,
+
+ VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST,
+};
+
/* the mode type for macvtap devices */
enum virDomainNetdevMacvtapType {
VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA,
union {
struct {
enum virDomainNetBackendType name; /* which driver backend to use */
+ enum virDomainNetVirtioTxModeType txmode;
} virtio;
} driver;
union {
VIR_ENUM_DECL(virDomainFSAccessMode)
VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainNetBackend)
+VIR_ENUM_DECL(virDomainNetVirtioTxMode)
VIR_ENUM_DECL(virDomainChrDevice)
VIR_ENUM_DECL(virDomainChrChannelTarget)
VIR_ENUM_DECL(virDomainChrConsoleTarget)
"-device", "?",
"-device", "pci-assign,?",
"-device", "virtio-blk-pci,?",
+ "-device", "virtio-net-pci,?",
NULL);
virCommandAddEnvPassCommon(cmd);
/* qemu -help goes to stdout, but qemu -device ? goes to stderr. */
if (strstr(str, "pci-assign.bootindex"))
*flags |= QEMUD_CMD_FLAG_PCI_BOOTINDEX;
}
+ if (strstr(str, "virtio-net-pci.tx="))
+ *flags |= QEMUD_CMD_FLAG_VIRTIO_TX_ALG;
return 0;
}
QEMUD_CMD_FLAG_CCID_PASSTHRU = (1LL << 55), /* -device ccid-card-passthru */
QEMUD_CMD_FLAG_CHARDEV_SPICEVMC = (1LL << 56), /* newer -chardev spicevmc */
QEMUD_CMD_FLAG_DEVICE_SPICEVMC = (1LL << 57), /* older -device spicevmc*/
+ QEMUD_CMD_FLAG_VIRTIO_TX_ALG = (1LL << 58), /* -device virtio-net-pci,tx=string */
};
virCapsPtr qemuCapsInit(virCapsPtr old_caps);
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
const char *nic;
+ bool usingVirtio = false;
if (!net->model) {
nic = "rtl8139";
} else if (STREQ(net->model, "virtio")) {
nic = "virtio-net-pci";
+ usingVirtio = true;
} else {
nic = net->model;
}
virBufferAdd(&buf, nic, strlen(nic));
+ if (usingVirtio && net->driver.virtio.txmode) {
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_VIRTIO_TX_ALG) {
+ virBufferAddLit(&buf, ",tx=");
+ switch (net->driver.virtio.txmode) {
+ case VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD:
+ virBufferAddLit(&buf, "bh");
+ break;
+
+ case VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER:
+ virBufferAddLit(&buf, "timer");
+ break;
+ default:
+ /* this should never happen, if it does, we need
+ * to add another case to this switch.
+ */
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unrecognized virtio-net-pci 'tx' option"));
+ goto error;
+ }
+ } else {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("virtio-net-pci 'tx' option not supported in this QEMU binary"));
+ goto error;
+ }
+ }
if (vlan == -1)
virBufferVSprintf(&buf, ",netdev=host%s", net->info.alias);
else
virtio-blk-pci.vectors=uint32
virtio-blk-pci.indirect_desc=on/off
virtio-blk-pci.scsi=on/off
+virtio-net-pci.vectors=uint32
+virtio-net-pci.indirect_desc=on/off
+virtio-net-pci.csum=on/off
+virtio-net-pci.guest_csum=on/off
+virtio-net-pci.gso=on/off
+virtio-net-pci.guest_tso4=on/off
+virtio-net-pci.guest_tso6=on/off
+virtio-net-pci.guest_ecn=on/off
+virtio-net-pci.guest_ufo=on/off
+virtio-net-pci.host_tso4=on/off
+virtio-net-pci.host_tso6=on/off
+virtio-net-pci.host_ecn=on/off
+virtio-net-pci.host_ufo=on/off
+virtio-net-pci.mrg_rxbuf=on/off
+virtio-net-pci.status=on/off
+virtio-net-pci.ctrl_vq=on/off
+virtio-net-pci.ctrl_rx=on/off
+virtio-net-pci.ctrl_vlan=on/off
+virtio-net-pci.ctrl_rx_extra=on/off
+virtio-net-pci.mac=macaddr
+virtio-net-pci.vlan=vlan
+virtio-net-pci.netdev=netdev
+virtio-net-pci.x-txtimer=uint32
+virtio-net-pci.x-txburst=int32
+virtio-net-pci.tx=string
pci-assign.host=pci-hostaddr
pci-assign.iommu=uint32
pci-assign.configfd=string
+virtio-net-pci.vectors=uint32
+virtio-net-pci.indirect_desc=on/off
+virtio-net-pci.csum=on/off
+virtio-net-pci.guest_csum=on/off
+virtio-net-pci.gso=on/off
+virtio-net-pci.guest_tso4=on/off
+virtio-net-pci.guest_tso6=on/off
+virtio-net-pci.guest_ecn=on/off
+virtio-net-pci.guest_ufo=on/off
+virtio-net-pci.host_tso4=on/off
+virtio-net-pci.host_tso6=on/off
+virtio-net-pci.host_ecn=on/off
+virtio-net-pci.host_ufo=on/off
+virtio-net-pci.mrg_rxbuf=on/off
+virtio-net-pci.status=on/off
+virtio-net-pci.ctrl_vq=on/off
+virtio-net-pci.ctrl_rx=on/off
+virtio-net-pci.ctrl_vlan=on/off
+virtio-net-pci.ctrl_rx_extra=on/off
+virtio-net-pci.mac=macaddr
+virtio-net-pci.vlan=vlan
+virtio-net-pci.netdev=netdev
QEMUD_CMD_FLAG_HDA_DUPLEX |
QEMUD_CMD_FLAG_DRIVE_AIO |
QEMUD_CMD_FLAG_CCID_PASSTHRU |
- QEMUD_CMD_FLAG_CHARDEV_SPICEVMC,
+ QEMUD_CMD_FLAG_CHARDEV_SPICEVMC |
+ QEMUD_CMD_FLAG_VIRTIO_TX_ALG,
12001, 1, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \
-/dev/HostVG/QEMUGuest1 -device virtio-net-pci,vlan=0,id=net0,\
+/dev/HostVG/QEMUGuest1 -device virtio-net-pci,tx=bh,vlan=0,id=net0,\
mac=00:11:22:33:44:55,bus=pci.0,addr=0x2 -net user,vlan=0,name=hostnet0 -usb \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
</disk>
+ <controller type='ide' index='0'/>
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
+ <driver txmode='iothread'/>
</interface>
<memballoon model='virtio'/>
</devices>
DO_TEST("net-user", 0, false);
DO_TEST("net-virtio", 0, false);
DO_TEST("net-virtio-device", QEMUD_CMD_FLAG_DEVICE |
- QEMUD_CMD_FLAG_NODEFCONFIG, false);
+ QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_VIRTIO_TX_ALG, false);
DO_TEST("net-virtio-netdev", QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_NETDEV | QEMUD_CMD_FLAG_NODEFCONFIG, false);
DO_TEST("net-eth", 0, false);
DO_TEST("misc-no-reboot");
DO_TEST("net-user");
DO_TEST("net-virtio");
+ DO_TEST("net-virtio-device");
DO_TEST("net-eth");
DO_TEST("net-eth-ifname");
DO_TEST("sound");