Skip to content

Instantly share code, notes, and snippets.

@gdamjan
Last active October 11, 2024 06:36
Show Gist options
  • Save gdamjan/ed095763b8c322ee5bed17e11bbaed6d to your computer and use it in GitHub Desktop.
Save gdamjan/ed095763b8c322ee5bed17e11bbaed6d to your computer and use it in GitHub Desktop.
libvirt with ipvtap over wifi

ipvtap over wifi for libvirt

ipvtap is similar to macvtap, but works over wifi too, since it uses the same mac address as the wifi interface.

libvirt doesn't support ipvtap, so we have to configure everything manually. Important data we need before we start:

  • the name of the wifi interface, wlan0 in my case (it's already connected - use NM or networkd+iwd).
  • the mac address of the wifi interface (it must be the same in the guest too)

On the host:

sudo ip link add name ipvtap0 link wlan0 type ipvtap  mode l2 bridge
sudo ip link set up ipvtap0

The network interface for the guest is configured via the following xml using the mac address from wlan0/ipvtap0:

<interface type="ethernet">
  <mac address="f8:d1:11:18:81:c3"/>
  <target dev="ipvtap0" managed="no"/>
  <model type="virtio"/>
  <alias name="net0"/>
  <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</interface>

⚠️ DHCP is a … bit complicated

Now, I can start the VM, but I can't ping from/to router to/from the VM, until I configure the guest address on the host ipvtap0 too:

sudo ip addr add dev ipvtap0 192.168.17.111/32

this might be fixable with some proxy-arp?

Tested on:

Host:

  • Archlinux, 5.6.15-arch1-1
  • libvirt 6.4.0-1
  • qemu-headless 5.0.0-6

Guest:

  • Archlinux testing, 5.7.0-zen1-1-zen
@gdamjan
Copy link
Author

gdamjan commented Jun 4, 2020

DHCP:
the dhcp Discover does arrive at the router, but it would need to respond with the predefined IP on the ipvtap0 interface for it to get to the guest.

@dareni
Copy link

dareni commented Sep 8, 2021

Works great for my eth/wlan bond. Thanks

@joez
Copy link

joez commented Jun 8, 2022

Very helpful instructions on how to use IPVTAP for a VM, actually the only one I could find over the Internet
But I have one issue, once I configured the same guest address on the host ipvtap0, I can't connect the host from another machine any more.
Would you give me a hand?

Here are the steps I am doing

sudo ip link add ipvtap0 link wlan0 type ipvtap mode l2 bridge
sudo ip link set dev ipvtap0 up

Launch QEMU with option

-netdev tap,id=ipvtap,fd=3 3<>/dev/tap$(< /sys/class/net/ipvtap0/ifindex) -device virtio-net,netdev=ipvtap,mac=$(< /sys/class/net/ipvtap0/address)

When VM is booted, configure the NIC in the guest OS manually with static IP

  • IP address is 192.168.1.20/24
  • Gateway and DNS server are both 192.168.1.1

Configure the same IP address on the host ipvtap0 too

sudo ip addr add 192.168.1.20/24 dev ipvtap0

@Segment0895
Copy link

For DHCP you still need to configure the ipvtap0 ip, host side, manually.
That being said, you can use:
dhcrelay -d -4 -id ipvtap0 -iu wlp0s20f3 192.168.1.1
to get a DHCP reply inside the guest and get the interface (guest-side) configured.

You'll still need to discover which IP is that (that the guest received) to configure ipvtap0. If guest-side IP was 192.168.1.123, then you'd still need to do
sudo ip addr add dev ipvtap0 192.168.1.123/32
on the host

@wrobelda
Copy link

wrobelda commented Sep 5, 2022

@pt3244 that's expected, because the routing table now has same network addressable via two interfaces, which is not OK. IPVTap was designed to be used with namespaces, according to the author themselves: https://docs.kernel.org/networking/ipvlan.html#example-configuration . See exemplary solution here: https://serverfault.com/a/706274

It should be perfectly fine to set another IP on that ipvtap0 interface, see the diagram on IPVLAN (analogous to IPVTap) on the right here: https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking#ipvlan. This is, however, an unlikely solution, depending on the use case.

I honestly don't know how @gdamjan managed to have a functional setup with the same IP on both host and guest interfaces with just these commands. It's possible that libvirt sets up namespaces implicitly.

@xalt7x
Copy link

xalt7x commented Oct 15, 2023

Thanks for this instruction. It helped me to get the wifi bridged network working without parprouted or over-complicated settings.
I guess it's better to remove this part

  <alias name="net0"/>
  <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>

virt-manager didn't allow me to save the config because the "bus" had already been bound to another device.

XML error: Attempted double use of
PCI Address 0000:05:00.0

So I just deleted the "address" line and virt-manager added the missing part itself with a free bus number. Same with the"alias" part.


Also, it's worth noting that the IP address needs to be manually set on a guest.

@ja-cop
Copy link

ja-cop commented Jul 31, 2024

Does anyone know if/how this can work with multiple VMs on the same host? i.e. multiple VMs connected directly to the same LAN as the hypervisor host. It seems like libvirt complains if you try to attach a network interface to a VM that has the same MAC address as an interface on an existing VM.

@mcnels1
Copy link

mcnels1 commented Oct 5, 2024

I've used these instructions to set up an Intel wireless card in AP mode as an interface for pfSense running inside KVM, using hostapd in the Linux host OS to configure the card. I'm planning to use this to isolate IOT devices from my main network.

I use virt-install to set up my VMs, and so far as I can tell virt-install does not natively support <interface>. But it can be generated using virt-install's --xml option:

  --xml ./devices/interface/@type=ethernet \
  --xml ./devices/interface/mac/@address=94:e2:3c:17:f6:ce \
  --xml ./devices/interface/target/@dev=ipvtap0 \
  --xml ./devices/interface/target/@managed=no \
  --xml ./devices/interface/model/@type=virtio

@mcnels1
Copy link

mcnels1 commented Oct 5, 2024

@wrobelda I am configuring the same IP address on ipvtap0 in my host OS and on the interface inside the VM; if I do not it is not reachable. I am not setting up any namespaces, and libvirt does not seem to be implicitly creating namespaces, as ip netns list returns nothing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment