I'm using qemu/kvm to create a VM and want to assign an existing tap interface to the VM. How does one do that with the virsh CLI or virt-manager GUI?

I'm looking for the libvirt-equivalent of this manual qemu-invocation:

qemu-system-x86_64 -net nic,model=virtio,macaddr= -net tap,ifname=MY_EXISTING_TAP_INTERFACE,script=no

I want this because I have a complex multi-homed firewall & router on which I manage all networking, including bridges, myself. I want the VM to just use the tap interface I prepared for it and do nothing else.

2 Answers 2


With the virt-manager GUI, you can look at the details for your VM, click on the Add Hardware button, select Network and enter the details in the dialog box.

From the command-line, you can use virsh attach-interface or, if you have created/copied a suitable XML fragment for the NIC, use virsh attach-device (BTW, the attach-interface sub-command has a --print-xml option that just prints the XML fragment rather than attaching the interface).

virsh is well documented in its man page and on the libvirt.org web site, and also has extensive built-in help. For example:

# virsh attach-interface --help
    attach-interface - attach network interface

    attach-interface <domain> <type> <source> [--target <string>] [--mac <string>]
      [--script <string>] [--model <string>] [--alias <string>] [--inbound <string>]
      [--outbound <string>] [--persistent] [--config] [--live] [--current] [--print-xml]
      [--managed] [--source-mode <string>]

    Attach new network interface.

    [--domain] <string>  domain name, id or uuid
    [--type] <string>  network interface type
    [--source] <string>  source of network interface
    --target <string>  target network name
    --mac <string>   MAC address
    --script <string>  script used to bridge network interface
    --model <string>  model type
    --alias <string>  custom alias name of interface device
    --inbound <string>  control domain's incoming traffics
    --outbound <string>  control domain's outgoing traffics
    --persistent     make live change persistent
    --config         affect next boot
    --live           affect running domain
    --current        affect current domain
    --print-xml      print XML document rather than attach the interface
    --managed        libvirt will automatically detach/attach the device from/to host
    --source-mode <string>  mode attribute of <source/> element

# virsh attach-device --help
    attach-device - attach device from an XML file

    attach-device <domain> <file> [--persistent] [--config] [--live] [--current]

    Attach device from an XML <file>.

    [--domain] <string>  domain name, id or uuid
    [--file] <string>  XML file
    --persistent     make live change persistent
    --config         affect next boot
    --live           affect running domain
    --current        affect current domain

Remember that with libvirt, everything about a VM ("domain") is ultimately configured with XML. virsh and virt-manager are both tools for creating and modifying the XML config files and config-file fragments for both libvirt itself and any VMs managed by libvirt.

virsh has several commands for dumping the entire XML config for a domain, or just XML fragments for particular devices, to stdout. This can be redirected to a file for later use. It can also be modified with xmlstarlet or similar (note that the XML output is conveniently in an almost line-oriented format so could reasonably be modified with awk or sed or perl etc...but you're still better off using a tool or language that can parse and generate correct XML) and re-used to either update the existing VM or create a new slightly different VM.

For example, try running virsh help | grep -i xml to get an idea of the kinds of things you can do with the virsh command and XML config files/fragments.

BTW, the various "edit" sub-commands (e.g. edit, iface-edit, pool-edit, etc) load the XML into your preferred editor (via the usual $EDITOR or $VISUAL env vars) so you can edit it - after you save your changes, if the XML passes validation, it is used to reconfigure the VM or libvirt itself, depending on what you're editing.

  • 2
    Thanks for your comprehensive reply! I know my way around virsh and should have worded my question more explicit: How do I attach an existing tap device? The closest thing I find in virsh attach-interface is the "direct" type, but it doesn't work: virsh attach-interface rpval direct MY_EXISTING_TAP --persistent --mac 52:54:00:74:01:04 makes it create a macvtap (which I don't want) and gives this: error creating macvtap interface macvtap2@MY_EXISTING_TAP (52:54:00:74:01:04): Device or resource busy Dec 11, 2022 at 8:45
  • I also tried the "hostdev" type, but it wants a physical device ("cannot parse pci address"), not a tap device Dec 11, 2022 at 8:52
  • That's something I don't know - aside from a very few occasions with PCI passthrough of a NIC, I pretty much exclusively use the brN bridge device (on the hosts running kvm AND their guest VMs), so that each VM is just another host on that LAN segment. I've never had any need to use or even look into tap devices. (I do have a vague recollection of experimenting with some network tunnelling based on tap from back in the late 90s or early 2000s, and that's about all I can recall about it). I certainly don't know the pros and cons of using tap vs bridge - is there a compelling benefit to either?
    – cas
    Dec 11, 2022 at 9:09

Had the same issue. Here is the XML that got (mostly) host-based networking going for me:

<interface type="ethernet">
  <script path="/vm/qemu/tap-up.sh"/>
  <target dev="tap10"/>
  <mac address="00:11:22:33:44:55"/>
  <model type="virtio"/>
  <address type:="pci"/>

When using QEMU natively all of the network configuration was done on the host, but for some reason libvirt is ignoring the "managed" directive mentioned here: https://libvirt.org/formatdomain.html#generic-ethernet-connection

So, I simply configure the bridge on the host and let libvirt create the tap. The script listed above adds "tap10" as a member of that bridge interface after the tap is created. It's not ideal, but it works.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .