Skip to content

Instantly share code, notes, and snippets.

@lukasnellen
Last active July 29, 2024 09:54
Show Gist options
  • Save lukasnellen/d597f52441d6ca65ea0f0c79c9c170e7 to your computer and use it in GitHub Desktop.
Save lukasnellen/d597f52441d6ca65ea0f0c79c9c170e7 to your computer and use it in GitHub Desktop.
Connect host and VM when using MACVTAP instead of TAP interfaces

Connect host and VM when using a MACVTAP interface

NB: The following is only of interest if you want to share the host network with your virtual machine. The most common way this gets implemented is by setting up a bridge which includes the physical interface. Using a MACVTAP inerface is suposed to be more efficient, since it avoids the additional bridge in the network setup.

In this gist, we extend the information provided in the documenation on linux virtual interfaces.

In the following, we assume you host interface is eth0. IP addresses used:

  • host: 198.51.100.50/24
  • virtual machine: 198.51.100.198/24
  • default gateway: 198.51.100.254

Normal setup

In the normal setup, the host will use eth0 to comunicate with the outside and will have the IP addresses assigned to that interface.

ip addr add dev eth0 198.51.100.50/24
ip route add default via 198.51.100.254

When you look at the docummentation of linux virtual interfaces you notice that, normally, you cannot communicate between the host and a virtual machine using MACVTAP (or direct attachment) instead of a bridged network to connect to the host network. Unless you have support by external hardware, you should use bridge mode.

Here is a snippet used to set up a domain in libvirt with direct attachment to the physical interface:

<interface type='direct' trustGuestRxFilters='yes'>
  <source dev='eth0' mode='bridge'/>
  <target dev='macvtap0'/>
  <model type='virtio'/>
  <alias name='net0'/>
  <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>

This will create a MACVTAP interface connected to eth0. If you have several virtual machines set up this way, they will be able to communicate. It is not possible, though, for packages to get bridged from eth0 to one of the MACVTAP interfaces.

macvtap-no-host drawio

On-host MACVLAN

To work around this, you can add an additional, virtual, interface for the host and use that for outgoing connections. This will be a MACVLAN interface, which is more often used for containers. Here, we will create the MACVLAN inerface in the host's main network namespace and not in the namespace of a container, so it is accessible as an additional interface on the host. Briding works also between MACVTAP and MACVLAN interfaces, so the host can communicate from veth0 to the VMs and to the outside.

We will create the interface veth0 in the main network namespace and assign the IP addresses to that interface.

ip link set eth0 up
ip link add veth0 link eth0 type macvlan mode bridge
ip addr add dev veth0 198.51.100.50/24
ip route add default via 198.51.100.254

Note that eth0 is activated, but does not have any IP address assigned. The host can now communicate to both to external host and to internal VMs on the 198.51.100.0/24 network.

macvtap-veth drawio

debian-style interfaces example

In the setup for a debian system, this translates to the /etc/network/interfaces file as:

auto veth0

iface veth0 inet static
    pre-up ifup eth0 || true
    pre-up ip link add veth0 link eth0 type macvlan mode bridge
    post-down ip link del veth0
    address 198.51.100.50
    netmask 255.255.255.0
    network 198.51.100.0
    broadcast 198.51.100.255
    gateway 198.51.100.254
    # dns-* options are implemented by the resolvconf package, if installed
    dns-nameservers 8.8.8.8 1.1.1.1

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