How to enable DHCP for “br0” device for qemu

bridgedhcpkvm-virtualizationlinux-networkingqemu

I've created a Windows XP image and I'm booting it with qemu. I'm using qemu-bridge-helper to to setup networking. Following qemu totorials, I've configured /etc/qemu/bridge.conf to allow br0 bridge device.

This is how I boot Windows XP with qemu:

qemu-system-x86_64 --enable-kvm -m 2048 \
  -drive file=winxp.img,if=virtio \
  -net nic,model=virtio \
  -net bridge,br=br0

The image boots nicely but I don't get an IP address. The reason is that Windows is configured to use DHCP but "br0" is not providing a DHCP address as it's just a bridge interface.

My question is – how do I configure "br0" to give addresses to winxp over DHCP?

(When using "user mode networking" via -net user, Windows gets an IP assigned so Windows drivers are installed correctly.)

Best Answer

br0 is only a layer 2 networking abstraction - a virtual switch, essentially. If you have a DHCP server running on your hypervisor, have a an IP address assigned to the br0 interface that the DHCP server is pointed at (on the hypervisor itself), and have the DHCP server define a subnet matching the network of your layer 3 address with an appropriate range, then this will work without any other devices.

However, in most cases when using a bridged interface, there is already a DHCP server on the broadcast domain that you're attaching to. br0 acts as a switch, so that traffic is passed to your guests. From your description of your problems, I can offer you an example configuration that will solve most of your problems.

Remember that you must honor the OSI model when stacking interfaces. What this means is that when creating a layer 2 abstraction such as a bridge, you cannot have any layer 3 addressing underneath it. It simply won't work. Since a bridge acts as a switch, you will be giving the bridge itself an IP address and attaching other interfaces in a link layer capacity only. This includes virtual interfaces for VMs and physical interfaces for bridging the external network to said VMs and to the hypervisor.

In this configuration, eth0 is attached to br0, and br0 gets your addressing. VMs attach to br0, and DHCP services (whether they're on your hypervisor or external to it on the same layer 2 domain) will give addresses to your VMs.

# cat /etc/network/interfaces

auto eth0
    iface eth0 inet manual

auto br0
    iface br0 inet dhcp
    bridge_ports eth0

This assumes you're using DHCP to get your address for br0. If not, you will need to apply static addressing to the br0 interface.

When this is done, you will need to restart networking (# systemctl stop networking && systemctl start networking). This will break your link, so you will need to have an OOB method to get into your machine if your configuration fails. If it's correct, you should be able to reconnect via SSH after the services have been started. It's very important to be able to access the machine via OOB for this kind of task, as it's very easy to get locked out.

Alternatively, and recommended

This is really a job for libvirt to handle. Using libvirt, you can easily use the built in NAT networking for VMs that don't need to be accessed from outside yet need access to the internet. It's also easier to define VMs, create consistent configurations, and to generally manage resources.

You can use a combination of virsh, virt-install, and qemu-img to manage this via the cli. There are many other graphical frontends that you could use alternatively to manage libvirt, such as oVirt or Virtual Machine Manager (virt-manager)