<h5><a id="elementsNICSEthernet">Generic ethernet connection</a></h5>
<p>
- Provides a means for the administrator to execute an arbitrary script
- to connect the guest's network to the LAN. The guest will have a tun
- device created with a name of vnetN, which can also be overridden with the
- <target> element. After creating the tun device a shell script will
- be run which is expected to do whatever host network integration is
- required. By default this script is called /etc/qemu-ifup but can be
- overridden.
+ Provides a means to use a new or existing tap device (or veth
+ device pair, depening on the needs of the hypervisor driver)
+ that is partially or wholly setup external to libvirt (either
+ prior to the guest starting, or while the guest is being started
+ via an optional script specified in the config).
+ </p>
+ <p>
+ The name of the tap device can optionally be specified with
+ the <code>dev</code> attribute of the
+ <code><target></code> element. If no target dev is
+ specified, libvirt will create a new standard tap device with a
+ name of the pattern "vnetN", where "N" is replaced with a
+ number. If a target dev is specified and that device doesn't
+ exist, then a new standard tap device will be created with the
+ exact dev name given. If the specified target dev does exist,
+ then that existing device will be used. Usually some basic setup
+ of the device is done by libvirt, including setting a MAC
+ address, and the IFF_UP flag, but if the <code>dev</code> is a
+ pre-existing device, and the <code>managed</code> attribute of
+ the <code>target</code> element is also set to "no" (the default
+ value is "yes"), even this basic setup will not be performed -
+ libvirt will simply pass the device on to the hypervisor with no
+ setup at all. <span class="since">Since 5.7.0</span> Using
+ managed='no' with a pre-created tap device is useful because
+ it permits a virtual machine managed by an unprivileged libvirtd
+ to have emulated network devices based on tap devices.
+ </p>
+ <p>
+ After creating/opening the tap device, an optional shell script
+ (given in the <code>path</code> attribute of
+ the <code><script></code> element) will be run; this can
+ be used to do whatever extra host network integration is
+ required.
</p>
<pre>
...
<devices>
- <interface type='ethernet'/>
- ...
<interface type='ethernet'>
- <target dev='vnet7'/>
<script path='/etc/qemu-ifup-mynet'/>
</interface>
+ ...
+ <interface type='ethernet'>
+ <target dev='mytap1' managed='no'/>
+ <model type='virtio'/>
+ </interface>
</devices>
...</pre>
<attribute name="dev">
<ref name="deviceName"/>
</attribute>
+ <optional>
+ <attribute name="managed">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</optional>
virDomainNetTypeToString(net->type));
return -1;
}
+ if (net->managed_tap == VIR_TRISTATE_BOOL_NO &&
+ net->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unmanaged target dev is not supported on "
+ "interfaces of type '%s'"),
+ virDomainNetTypeToString(net->type));
+ return -1;
+ }
return 0;
}
VIR_AUTOFREE(char *) bridge = NULL;
VIR_AUTOFREE(char *) dev = NULL;
VIR_AUTOFREE(char *) ifname = NULL;
+ VIR_AUTOFREE(char *) managed_tap = NULL;
VIR_AUTOFREE(char *) ifname_guest = NULL;
VIR_AUTOFREE(char *) ifname_guest_actual = NULL;
VIR_AUTOFREE(char *) script = NULL;
} else if (!ifname &&
virXMLNodeNameEqual(cur, "target")) {
ifname = virXMLPropString(cur, "dev");
- if (ifname &&
- (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
- (STRPREFIX(ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
- (prefix && STRPREFIX(ifname, prefix)))) {
- /* An auto-generated target name, blank it out */
- VIR_FREE(ifname);
- }
+ managed_tap = virXMLPropString(cur, "managed");
} else if ((!ifname_guest || !ifname_guest_actual) &&
virXMLNodeNameEqual(cur, "guest")) {
ifname_guest = virXMLPropString(cur, "dev");
ctxt, &def->guestIP) < 0)
goto error;
+ if (managed_tap) {
+ if (STREQ(managed_tap, "no")) {
+ def->managed_tap = VIR_TRISTATE_BOOL_NO;
+ } else if (STREQ(managed_tap, "yes")) {
+ def->managed_tap = VIR_TRISTATE_BOOL_YES;
+ } else {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid 'managed' value '%s'"),
+ managed_tap);
+ goto error;
+ }
+ }
+
+ if (def->managed_tap != VIR_TRISTATE_BOOL_NO && ifname &&
+ (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
+ (STRPREFIX(ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
+ (prefix && STRPREFIX(ifname, prefix)))) {
+ /* An auto-generated target name, blank it out */
+ VIR_FREE(ifname);
+ }
+
if (script != NULL)
VIR_STEAL_PTR(def->script, script);
if (domain_name != NULL)
virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name);
if (def->ifname &&
- !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) &&
- (STRPREFIX(def->ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
- (prefix && STRPREFIX(def->ifname, prefix))))) {
+ (def->managed_tap == VIR_TRISTATE_BOOL_NO ||
+ !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) &&
+ (STRPREFIX(def->ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
+ (prefix && STRPREFIX(def->ifname, prefix)))))) {
/* Skip auto-generated target names for inactive config. */
virBufferEscapeString(&attrBuf, " dev='%s'", def->ifname);
}
+ if (def->managed_tap != VIR_TRISTATE_BOOL_ABSENT) {
+ virBufferAsprintf(&attrBuf, " managed='%s'",
+ virTristateBoolTypeToString(def->managed_tap));
+ }
if (virXMLFormatElement(buf, "target", &attrBuf, NULL) < 0)
return -1;
char *script;
char *domain_name; /* backend domain name */
char *ifname; /* interface name on the host (<target dev='x'/>) */
+ int managed_tap; /* enum virTristateBool - ABSENT == YES */
virNetDevIPInfo hostIP;
char *ifname_guest_actual;
char *ifname_guest;
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <interface type='ethernet'>
+ <mac address='fe:11:22:33:44:55'/>
+ <target dev='mytap0' managed='no'/>
+ <model type='virtio'/>
+ </interface>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <interface type='ethernet'>
+ <mac address='fe:11:22:33:44:55'/>
+ <target dev='mytap0' managed='no'/>
+ <model type='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </interface>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
DO_TEST("net-eth", NONE);
DO_TEST("net-eth-ifname", NONE);
DO_TEST("net-eth-hostip", NONE);
+ DO_TEST("net-eth-unmanaged-tap", NONE);
DO_TEST("net-virtio-network-portgroup", NONE);
DO_TEST("net-virtio-rxtxqueuesize", NONE);
DO_TEST("net-hostdev", NONE);