This page describes how to set up the various transports and to provide a UML instance with network access to the host, other machines on the local net, and the rest of the net.
As of 2.4.5, UML networking has been completely redone to make it much easier to set up, fix bugs, and add new features.
There is a new helper, uml_net, which does the host setup that requires root privileges.
There are currently five transport types available for a UML virtual machine to exchange packets with other hosts:
The daemon and multicast transports provide a completely virtual network to other virtual machines. This network is completely disconnected from the physical network unless one of the virtual machines on it is acting as a gateway.
With so many host transports, which one should you use? Here's when you should use each one:
First, you must have the virtual network enabled in your UML. If are running a prebuilt kernel from this site, everything is already enabled. If you build the kernel yourself, under the "Network device support" menu, enable "Network device support", and then the three transports.
The next step is to provide a network device to the virtual machine. This is done by describing it on the kernel command line.
The general format is
eth <n> = <transport> , <transport args>
For example, a virtual ethernet device may be attached to a host ethertap
device as follows:
eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
This sets up eth0 inside the virtual machine to attach itself to the
host /dev/tap0, assigns it an ethernet address, and assigns the host
tap0 interface an IP address.
Note that when you configure the host side of an interface, it is only acting as a gateway. It will respond to pings sent to it locally, but is not useful to do that since it's a host interface. You are not talking to the UML when you ping that interface and get a response.
You can also add devices to a UML and remove them at runtime. See the The Management Console page for details.
The sections below describe this in more detail.
Once you've decided how you're going to set up the devices, you boot UML, log in, configure the UML side of the devices, and set up routes to the outside world. At that point, you will be able to talk to any other machines, physical or virtual, on the net.
You will likely need the setuid helper, or the switch daemon, or both. They are both installed with the RPM and deb, so if you've installed either, you can skip the rest of this section.
If not, then you need to check them out of CVS, build them, and install them. The helper is uml_net, in CVS /tools/uml_net, and the daemon is uml_switch, in CVS /tools/uml_router. They are both built with a plain 'make'. Both need to be installed in a directory that's in your path - /usr/bin is recommend. On top of that, uml_net needs to the setuid root.
Below, you will see that the TUN/TAP, ethertap, and daemon interfaces allow you to specify hardware addresses for the virtual ethernet devices. This is generally not necessary. If you don't have a specific reason to do it, you probably shouldn't. If one is not specified on the command line, the driver will assign one based on the device IP address. It will provide the address
fe:fd:nn:nn:nn:nn
where nn.nn.nn.nn is the device IP address. This is nearly always
sufficient to guarantee a unique hardware address for the device. A
couple of exceptions are:
ifconfig eth0 192.168.0.250 up
If you decide to assign the hardware address yourself, make sure that
the first byte of the address is even. Addresses with an odd first byte
are broadcast addresses, which you don't want assigned to a device.
Once the network devices have been described on the command line, you should boot UML and log in.
The first thing to do is bring the interface up:
ifconfig eth <n> <ip-address> up
You should be able to ping the host at this point.
To reach the rest of the world, you should set a default route to the host:
route add default gw <host ip>
Again, with host ip of 192.168.0.4:
route add default gw 192.168.0.4
This page used to recommend setting a network route to your local
net. This is wrong, because it will cause UML to try to figure out
hardware addresses of the local machines by arping on the interface to
the host. Since that interface is basically a single strand of
ethernet with two nodes on it (UML and the host) and arp requests
don't cross networks, they will fail to elicit any responses. So,
what you want is for UML to just blindly throw all packets at the host
and let it figure out what to do with them, which is what leaving out
the network route and adding the default route does.
Note: If you can't communicate with other hosts on your physical ethernet, it's probably because of a network route that's automatically set up. If you run 'route -n' and see a route that looks like this:
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
with a mask that's not 255.255.255.255, then replace it with a route
to your host:
route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
route add -host 192.168.0.4 dev eth0
This, plus the default route to the host, will allow UML to exchange
packets with any machine on your ethernet.
The simplest way to set up a virtual network between multiple UMLs is to use the mcast transport. This was written by Harald Welte and is present in UML version 2.4.5-5um and later. Your system must have multicast enabled in the kernel and there must be a multicast-capable network device on the host. Normally, this is eth0, but if there is no ethernet card on the host, then you will likely get strange error messages when you bring the device up inside UML.
To use it, run two UMLs with
eth0=mcast
on their command lines. Log in, configure the ethernet device in each
machine with different IP addresses:
uml1# ifconfig eth0 192.168.0.254
uml2# ifconfig eth0 192.168.0.253
and they should be able to talk to each other.
The full set of command line options for this transport are
eth <n> =mcast, <ethernet address> , <multicast
address> , <multicast port> , <ttl>
Harald's original README is
here and explains
these in detail, as well as some other issues.
TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the host. The TUN/TAP backend has been in UML since 2.4.9-3um.
If you specify an IP address for the host side of the device, the uml_net helper will do all necessary setup on the host - the only requirement is that TUN/TAP be available, either built in to the host kernel or as the tun.o module.
The format of the command line switch to attach a device to a TUN/TAP device is
eth <n> =tuntap,,, <IP address>
For example, this argument will attach the UML's eth0 to
the next available tap device and assign an ethernet address to it
based on its IP address
eth0=tuntap,,,192.168.0.254
If you prefer not to have UML use uml_net (which is somewhat insecure), with UML 2.4.17-11, you can set up a TUN/TAP device beforehand. The setup needs to be done as root, but once that's done, there is no need for root assistance. Setting up the device is done as follows:
tunctl <uid>
where uid is the user id that UML will be run as. This will
tell you what device was created.
ifconfig tap0 192.168.0.254 up
sudo bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
sudo route add -host 192.168.0.253 dev tap0
sudo bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
sudo arp -Ds 192.168.0.253 eth0 pub
Note that this must be done every time the host boots - this
configuration is not stored across host reboots. So, it's probably a
good idea to stick it in an rc file. An even better idea would be a
little utility which reads the information from a config file and sets
up devices at boot time.
Note that the IP address that must be used for the eth device inside UML is fixed by the routing and proxy arp that is set up on the TUN/TAP device on the host. You can use a different one, but it won't work because reply packets won't reach the UML. This is a feature. It prevents a nasty UML user from doing things like setting the UML IP to the same as the network's nameserver or mail server.
There are a couple potential problems with running the TUN/TAP transport on a 2.4 host kernel
File descriptor in bad state
This is due to a header mismatch between the upgraded kernel and the
kernel that was originally installed on the machine. The fix is to
make sure that /usr/src/linux points to the headers for the running kernel.
Ethertap is the general mechanism on 2.2 for userspace processes to exchange packets with the kernel.
To use this transport, you need to describe the virtual network device on the UML command line. The general format for this is
eth <n> =ethertap, <device> , <ethernet address> , <tap IP address>
So, the previous example
eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
attaches the UML eth0 device to the host
/dev/tap0, assigns it the
ethernet address fe:fd:0:0:0:1, and assigns the IP address
192.168.0.254 to the tap device.
The tap device is mandatory, but the others are optional. If the ethernet address is omitted, one will be assigned to it.
The presence of the tap IP address will cause the helper to run and do whatever host setup is needed to allow the virtual machine to communicate with the outside world. If you're not sure you know what you're doing, this is the way to go.
If it is absent, then you must configure the tap device and whatever arping and routing you will need on the host. However, even in this case, the uml_net helper still needs to be in your path and it must be setuid root if you're not running UML as root. This is because the tap device doesn't support SIGIO, which UML needs in order to use something as a source of input. So, the helper is used as a convenient asynchronous IO thread.
If you're using the uml_net helper, you can ignore the following host setup - uml_net will do it for you. You just need to make sure you have ethertap available, either built in to the host kernel or available as a module.
If you want to set things up yourself, you need to make sure that the appropriate /dev entry exists. If it doesn't, become root and create it as follows:
mknod /dev/tap <minor> c 36 <minor> + 16
For example, this is how to create /dev/tap0:
mknod /dev/tap0 c 36 0 + 16
You also need to make sure that the host kernel has ethertap support. If ethertap is enabled as a module, you apparently need to insmod ethertap once for each ethertap device you want to enable. So,
insmod ethertap
will give you the tap0 interface. To get the tap1 interface, you need
to run
insmod ethertap unit=1 -o ethertap1
Note: This is the daemon formerly known as uml_router, but which was renamed so the network weenies of the world would stop growling at me.
The switch daemon, uml_switch, provides a mechanism for creating a totally virtual network with no connection to the host network.
The first thing you need to do is run the daemon. Running it with no arguments will make it listen on a default pair of unix domain sockets.
If you want it to listen on a different pair of sockets, use
-unix <control socket> <data socket>
If you want it to act as a hub rather than a switch, use
-hub
The general format of the kernel command line switch is
eth <n> =daemon, <ethernet address> , <socket
type> , <control socket> , <data socket>
You can leave off everything except the 'daemon'. You only need to
specify the ethernet address if the one that will be assigned to it
isn't acceptable for some reason. The rest of the arguments describe
how to communicate with the daemon. You should only specify them if
you told the daemon to use different sockets than the default. So, if
you ran the daemon with no arguments, running the UML on the same
machine with
eth0=daemon
will cause the eth0 driver to attach itself to the daemon correctly.
Slip is another, less general, mechanism for a process to communicate with the host networking. In contrast to the ethertap interface, which exchanges ethernet frames with the host and can be used to transport any higher-level protocol, it can only be used to transport IP.
The general format of the command line switch is
eth <n> =slip, <slip IP>
The slip IP argument is the IP address that will be assigned to the
host end of the slip device. If it is specified, the helper will run
and will set up the host so that the virtual machine can reach it and
the rest of the network.
There are some oddities with this interface that you should be aware of. You should only specify one slip device on a given virtual machine, and its name inside UML will be 'umn', not 'eth0' or whatever you specified on the command line. These problems will be fixed at some point.
If you don't specify an address for the host side of the ethertap or slip device, UML won't do any setup on the host. So this is what is needed to get things working (the examples use a host-side IP of 192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your own network):
ifconfig tap0 arp mtu 1484 192.168.0.251 up
ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
route add -host 192.168.0.250 gw 192.168.0.251
arp -Ds 192.168.0.250 eth0 pub
echo 1 > /proc/sys/net/ipv4/ip_forward