Create network bridge for guest VM on same subnet as host using QEMU/KVM virt-manager

Hi all,
I have been putting off migrating from VirtualBox to QEMU/KVM because for almost two years every time I tried to figure out how to setup the guest VM to be on the same subnet, I either got to a thread that got me more confused than before (for example this thread) or got me to end up disabling my host network by obviously making a mistake (for example this site).
I do admit sometimes it is too overwhelming to read all different advises and end up with nothing or not get anywhere.
I only want to achieve same results as VirtualBox, meaning guest being on same subnet as host (192.168.0.x), but with virt-manager, and regular NAT connection internet works but guest is on (192.168.122.x).

The setup of hypervisor was through YaST by installing KVM Server and libvirt LXC daemon. Installed virt-manager, qemu-kvm, and libvirt-client through zypper.

sudo virsh net-autostart default
sudo usermod -a -G libvirt USERNAME
sudo usermod -a -G kvm USERNAME

Right now I have:

ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d8:bb:c1:47:1b:db brd ff:ff:ff:ff:ff:ff
    altname enp5s0
    inet 192.168.0.10/24 brd 192.168.0.255 scope global dynamic noprefixroute eth1
       valid_lft 59340sec preferred_lft 59340sec
    inet6 fe80::1872:946c:c577:4092/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 42:be:c9:a8:c1:92 brd ff:ff:ff:ff:ff:ff permaddr 64:79:f0:44:e9:2c
    altname wlo1
    altname wlp0s20f3
7: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:66:41:3b brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
9: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether ea:19:f5:ed:5d:8e brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.192/24 brd 192.168.0.255 scope global noprefixroute br0
       valid_lft forever preferred_lft forever

and,

nmcli device show
GENERAL.DEVICE:                         eth1
GENERAL.TYPE:                           ethernet
GENERAL.HWADDR:                         D8:BB:C1:47:1B:DB
GENERAL.MTU:                            1500
GENERAL.STATE:                          100 (connected)
GENERAL.CONNECTION:                     eth0
GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/1
WIRED-PROPERTIES.CARRIER:               on
IP4.ADDRESS[1]:                         192.168.0.10/24
IP4.GATEWAY:                            192.168.0.1
IP4.ROUTE[1]:                           dst = 0.0.0.0/0, nh = 192.168.0.1, mt = 100
IP4.ROUTE[2]:                           dst = 192.168.0.0/24, nh = 0.0.0.0, mt = 100
IP4.DNS[1]:                             192.168.0.1
IP6.ADDRESS[1]:                         fe80::1872:946c:c577:4092/64
IP6.GATEWAY:                            fe80::264b:feff:feae:3ef8
IP6.ROUTE[1]:                           dst = fe80::/64, nh = ::, mt = 100
IP6.ROUTE[2]:                           dst = ::/0, nh = fe80::264b:feff:feae:3ef8, mt = 20100

GENERAL.DEVICE:                         br0
GENERAL.TYPE:                           bridge
GENERAL.HWADDR:                         EA:19:F5:ED:5D:8E
GENERAL.MTU:                            1500
GENERAL.STATE:                          100 (connected)
GENERAL.CONNECTION:                     bridge_virt
GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/7
IP4.ADDRESS[1]:                         192.168.0.192/24
IP4.GATEWAY:                            --
IP4.ROUTE[1]:                           dst = 192.168.0.0/24, nh = 0.0.0.0, mt = 425

GENERAL.DEVICE:                         virbr0
GENERAL.TYPE:                           bridge
GENERAL.HWADDR:                         52:54:00:66:41:3B
GENERAL.MTU:                            1500
GENERAL.STATE:                          100 (connected (externally))
GENERAL.CONNECTION:                     virbr0
GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/5
IP4.ADDRESS[1]:                         192.168.122.1/24
IP4.GATEWAY:                            --
IP4.ROUTE[1]:                           dst = 192.168.122.0/24, nh = 0.0.0.0, mt = 0
IP6.GATEWAY:                            --

GENERAL.DEVICE:                         wlan0
GENERAL.TYPE:                           wifi
GENERAL.HWADDR:                         F6:50:9C:08:EB:30
GENERAL.MTU:                            1500
GENERAL.STATE:                          30 (disconnected)
GENERAL.CONNECTION:                     --
GENERAL.CON-PATH:                       --

GENERAL.DEVICE:                         p2p-dev-wlan0
GENERAL.TYPE:                           wifi-p2p
GENERAL.HWADDR:                         (unknown)
GENERAL.MTU:                            0
GENERAL.STATE:                          30 (disconnected)
GENERAL.CONNECTION:                     --
GENERAL.CON-PATH:                       --

GENERAL.DEVICE:                         lo
GENERAL.TYPE:                           loopback
GENERAL.HWADDR:                         00:00:00:00:00:00
GENERAL.MTU:                            65536
GENERAL.STATE:                          10 (unmanaged)
GENERAL.CONNECTION:                     --
GENERAL.CON-PATH:                       --
IP4.ADDRESS[1]:                         127.0.0.1/8
IP4.GATEWAY:                            --
IP6.ADDRESS[1]:                         ::1/128
IP6.GATEWAY:                            --
IP6.ROUTE[1]:                           dst = ::1/128, nh = ::, mt = 256

I created the br0 following this website but instead of using ‘nmtui’ I used NetworkManager connections and gave it 192.168.0.192 as a static IP thinking I can dedicate the said IP to that VM on my router (which I used to do when using VirtualBox) so I can port forward to guest VM.

I would appreciate if someone could help me I would greatly appreciate it. I am not as tech savvy as most people are, but I try my best.

Greatly appreciate your help and guidance.

@simorgh If you not using the wireless for you main (host) connection, then I would suggest a USB to Ethernet device for the bridge connection to your virtual machines. I use TP-Link USB to Ethernet Adapter (UE306) ones, work out of the box.

Else use the wireless for you host system and then bridge eth1 to the bridge and ensure that eth1 is disable in NM with respect to getting a ipv4 or ipv6 address.

I have also found the nm-connection-editor great for setting up connections…

Screenshot from 2023-01-19 20-48-40

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 48:0f:cf:51:4e:24 brd ff:ff:ff:ff:ff:ff
    altname enp0s25
    inet 192.168.10.50/24 brd 192.168.10.255 scope global noprefixroute eno1
       valid_lft forever preferred_lft forever
3: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether 88:c9:b3:bf:07:b4 brd ff:ff:ff:ff:ff:ff
4: enp8s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br1 state UP group default qlen 1000
    link/ether 88:c9:b3:bf:07:b5 brd ff:ff:ff:ff:ff:ff
5: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 88:c9:b3:bf:07:b6 brd ff:ff:ff:ff:ff:ff
6: enp10s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 88:c9:b3:bf:07:b7 brd ff:ff:ff:ff:ff:ff
7: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ae:94:c8:51:ca:7b brd ff:ff:ff:ff:ff:ff
8: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0e:24:64:bc:43:76 brd ff:ff:ff:ff:ff:ff

So my vm’s use either br0 or br1 and get an ip address on my local network, or use static ips on the local network.

1 Like

@malcolmlewis thank you for your reply. I truly appreciate it.
I am far away from the WiFi and will loose significant speed if I used WiFi. Is there absolutely no way to bridge to the Ethernet connection?
Thank you

@simorgh Then you need to just use NAT to share eth1. Else a small network switch and USB to ethernet and use the current connection to your router.

1 Like

@malcolmlewis if using NAT to share the eth1, doesn’t guest VM get a different subnet?
I don’t understand, is the way VirtualBox does it, any different than QEMU/KVM?

@simorgh yes it does, hence the need for a dedicated interface and bridge setup. I think this may help: KVM Networking - NAT & Host-Only - Amol Dighe

1 Like

Is that site not need a dedicated interface (an actual separate NIC) ?
What I am trying to achieve is the same result as VirtualBox as it uses bridge network and puts the guest VM on the same network subnet as the host.

@simorgh No experience with virtualbox, but I suspect it’s doing something similar to the link I posted. I’ve always just run a dedicated interface/bridge…

This thread

https://forums.opensuse.org/t/qemu-kvm-user-management-create-launch-create-a-bridge-use-a-bridge/

is for using QEMU without using Virt.

Why not using Virt (and root admin) ? Because I want to use the QEMU VM as easy as I use a VirtualBox VM.

VirtualBox is my preferred app, but I can’t create an Android VM with VirtualBox.

1 Like

Thank you @arvidjaar , @malcolmlewis , and @promeneur
The more I read I have to be honest the more confused I get. It feels everyone has their method but it is specifically to ubuntu, or fedora, or … now there is another factor that talks about I can easily be able to do it through NetworkManager but if the distro is newwer than 2015, which mine is Leap 15.4.

Is there a possibility that there is a configuration or limitation caused by firewall that I am not aware of?
I have opened libvirt, libvirt-tls, and libvirt-relocation-server in firewall in YaST though.

After a lot of trial and error I have figured it out. The solution is as follows:
Disconnect or turn off (the best way is to delete) the existing wired network connection. This is very important so the existing connection doesn’t interfere with the setup.
The setup is by using nmcli (command-line tool for controlling NetworkManager) and brctl (ethernet bridge administration)

sudo nmcli con show
NAME    UUID                                  TYPE    DEVICE
virbr0  c42932ae-be14-4b8e-9c70-69868d093483  bridge  virbr0

sudo brctl show
bridge name     bridge id               STP enabled     interfaces
virbr0          8000.52540066413b       yes

In this case we are ignoring virbr0 as it is already created by VirtualBox I think.

Add a new bridge interface on host machine:

sudo nmcli con add type bridge ifname br0
Connection 'bridge-br0' (0ac8ba53-3ae8-4241-b464-ec0671aa0239) successfully added.

ip a
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d8:bb:c1:47:1b:bb brd ff:ff:ff:ff:ff:ff   <---
    altname enp5s0
6: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 66:bb:79:6b:bb:67 brd ff:ff:ff:ff:ff:ff   <---

Attach the newly added bridge br0 to physical interface on host, in this case eth1 :

sudo nmcli con add type bridge-slave ifname eth1 master br0
Connection 'bridge-slave-eth1' (4696cbda-1002-469c-9893-c085e726ebd5) successfully added.
sudo nmcli con show
NAME               UUID                                  TYPE      DEVICE 
bridge-br0         0ac8ba53-3ae8-4241-b464-ec0671aa0239  bridge    br0   <---
bridge-slave-eth1  4696cbda-1002-469c-9893-c085e726ebd5  ethernet  eth1   <---
virbr0             c42932ae-be14-4b8e-9c70-69868d093483  bridge    virbr0

ip a
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether d8:bb:c1:47:1b:bb brd ff:ff:ff:ff:ff:ff   <---
    altname enp5s0
6: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether d8:bb:c1:47:1b:bb brd ff:ff:ff:ff:ff:ff   <---
    inet 192.168.0.10/24 brd 192.168.0.255 scope global dynamic noprefixroute br0
       valid_lft 86071sec preferred_lft 86071sec
    inet6 fe80::291e:4838:6d3b:6620/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

Notice that br0 is now attached to the physical interface eth1. This will also reflect in ‘brctl show’ :

sudo brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.d8bbc1471bdb       yes             eth1   <---
virbr0          8000.52540066413b       yes

Configure the Virtual Machine Manager (QEMU/KVM) to use Network Source as ‘Bridge device’ and ‘Device name’: br0

1 Like

How to get an IP of your LAN (192.168.0.x) as your PC gets one ?
We assume you get as Network interface “eth0”

  1. With VirtualBox

Just in “Network” select “Bridge” and be sure “eth0” is selected.

You know why I prefer VB.

  1. With QEMU (without using virt to manage the VM (creating, setting,launching)

We assume you have already created the VM

2.1 create a bridge with the name “br0” with KDE network manager

2.2 Install the rpms

— tunctl
— bridge-utils

for openSUSE tumbleweed, the RPMs are in the standard repo
for openSUSE 15.4, RPMs are in the repo “network:utilities”

2.3 Generate a QEMU VM mac address for your VM.

you must use macgen.py from Redhat to generate mac addresses.

just run the python script in a text console.

2.4 add this statement in the QUEMU script

-nic bridge,mac=generated_mac_address \

an example of script to launch a VM using the bridge

#!/bin/bash

bash -c ’
qemu-kvm -enable-kvm
-m 2048 -smp 4 -cpu host
-display gtk,gl=on,zoom-to-fit=off
-device virtio-vga-gl
-device qemu-xhci,p2=5,p3=5,id=xhci
-device usb-kbd
-device usb-mouse
-device usb-tablet
-device intel-hda
-device hda-duplex,audiodev=snd0
-audiodev pa,id=snd0
-device usb-host,bus=xhci.0,vendorid=0x046d,productid=0x081b
-device usb-host,vendorid=0x0a5c,productid=0x21e8
-boot menu=on
-nic bridge,mac=00:16:3e:49:76:ce
~/QEMU_VM/opensuse_tumbleweed.img
’ &

2.5 additional settings if you don’t use virt to manage a VM.

No need to edit the firewall settings.

2.5.1 you need to modify the content of /etc/qemu/bridge.conf as following

the contents must be :

allow br0

2.5.2 you need to alter some acl

— change the acl of bridge.conf

sudo chown root:kvm /etc/qemu/bridge.conf
sudo chmod 0660 /etc/qemu/bridge.conf

— change the acl of qemu-bridge-helper

sudo chmod u+s /usr/lib/qemu-bridge-helper

— you need your user-id to be in “KVM” group

usermod -a -G kvm user-id

2.6 restart your OS

open your kde session

if you use gkrellm
you see 2 network interfaces

— br0
— eth0

Once you have launched the QEMU VM you see 3 network interfaces

— br0
— eth0
— tap0

if you launch several VMs with each one with its own mac addresses you get several network interfaces “tapx”

REMEMBER, if you use virt to manage your VM you don’t need all the preceding things of chapter 2, you don’t need any QEMU script, just use virt.

Would you please share with me what would be the purpose of this and what would it accomplish in addition to my last post?