35. LVS: Running LVS under UML (User Mode Linux), by Brett Elliot

User Mode Linux (UML) is a version of Linux, written by Jeff Dike, that boots and runs kernels as a job. (VMWare does the same thing.) UML thus can be running several Linux kernels, you can log into each Linux job separately, and each linux job appears to be a kernel running on its own machine. You can simulate ethernet devices (and other hardware) in each kernel and you can setup IP networks between the different kernels. You can simulate CPUs and have each kernel think it's running on a 64-way SMP machine. Of course you won't get any more performance than from one CPU, but you can test your 64-way CPU code. You can setup and test a full LVS with redundant directors and multiple realservers, all on your laptop (Horms and Ratz do this using VMWare, since UML wasn't available till a couple of years ago). With multiple kernels running on the resources that normally run only one kernel, resources can become limiting. In particular, with the kernel allocating all memory and not swapping any out till the memory is needed for something else, the job kernels are always fighting for memory (at least they were in 2002, it appears now that you limit the amount of memory available to each linux job).

The following write up on setting up LVS under UML was sent in by Brett Elliot brettspamacct (at) fastclick (dot) com 25 Feb 2004

35.1. Introduction

User Mode Linux(UML) allows you to run linux inside itself. Linux Virtual Server(LVS) allows you to load balance traffic between machines. Using both of these together can be useful.

It is assumed that the reader has read both the UML HOWTO and the LVS HOWTO.

The nomeclature of the two types of kernels is not clear in the UML-HOWTO.

  • UML kernels: The name of the kernels that are run as executables (at the command prompt you run ./linux).

    The UML kernel is a regular kernel that has been patched with the kernel specific UML code.

  • host kernel: The name of the kernel whose job it is to execute the UML kernels.

    The host kernel can be a regular unmodified, unpatched, kernel (from ftp.kernel.org).

    If you want to run the UML kernels faster, you use the "skas" patch on the host kernel. The UML kernel recognises the skas patch and will make use of it, running much faster. With the skas patch, you will notice 4 processes in the host kernel (but not the processes launched by the UML kernels). Without the skas patch, the processes running under the UML kernel appear in the host kernel process table.

For example, I had a 2.4.23 machine. I wanted to run a 2.6.2 UML kernel under it. I patched the 2.6.2 kernel with the UML patch (make ARCH=um menuconfig, then make ARCH=um linux) to make a UML kernel linux executable in the /usr/src/linux-2.6.2 directory. From the 2.4.23 host kernel, I ran the linux-2.6.2 UML executable kernel.

To make the UML kernel run faster, I patched the 2.4.23 host kernel with the skas patch, and rebooted. I re-ran the 2.6.2 UML kernel, which recognized the skas patch and ran much faster.

35.2. Ethernet bridging

35.2.1. Overview

Please refer to the UML Bridging HOWTO (http://edeca.net/articles/bridging/index.html) for a detailed explanation. Basically ethernet bridging allows us to create an ethernet bridge in the kernel and attach ethernet interfaces to it. We can create an arbitrary ethernet interface with its own MAC address using the tun interface, then attache tun interfaces to the ethernet bridge, allowing for communication between interfaces. We then "hand off" the ethernet interface created to the UML kernel.

35.2.2. Prerequisites

You will need to recompile the host kernel and install user-space tools on the host kernel machine.

On the host kernel (the kernel housing the UML kernel), enable "802.1d Ethernet Bridging" (CONFIG_BRIDGE) under "Networking options" and enable "Universal TUN/TAP device driver support" (CONFIG_TUN) under "Network device support". Recompile the kernel.

Note
there is no need to modify the UML kernel configuration.

For the userspace tools on the host kernel machine you will need the bridge utils and tun utils. You will also need maketundev.sh to create the tun device:

#!/bin/sh
#
#  Universal TUN/TAP device driver.
#  Copyright (C) 1999-2000 Maxim Krasnyansky <[email protected]>
#
#  Create TUN and TAP devices in /dev
#
#  $Id: create_dev,v 1.2 2000/10/28 21:22:37 maxk Exp $
#

case $1 in
   2.2*)
        TUN_MAJOR=90
        TUN_MINOR=0
        TAP_MINOR=128
        #
        # TUN
        rm -f /dev/tun*
        for i in 0 1 2 3; do
           mknod /dev/tun$i c ${TUN_MAJOR} $i
        done
        #
        # TAP
        rm -f /dev/tap*
        for i in 0 1 2 3; do
           mknod /dev/tap$i c ${TUN_MAJOR} `expr $i + ${TAP_MINOR}`
        done
        ;;

   2.4*)
        TUN_MAJOR=10
        TUN_MINOR=200
        if [ ! -d /dev/net ]; then
           mkdir /dev/net
        fi
        rm -f /dev/net/tun
        mknod /dev/net/tun c ${TUN_MAJOR} ${TUN_MINOR}
        ;;

   *)
        echo "Unknown kernel version"
        ;;

esac

35.2.3. Ethernet bridging to the world

This will show you how to bring up the UML kernel so it is connected to the world.

We assume that the host kernel (i.e. the kernel which houses the UML kernel) has IP address 10.1.1.219. The UML kernel will have IP address 10.1.1.220. First, run maketundev.sh kernel_version to create the tun device(s). Next, you will need to execute the following commands:

ifconfig eth0 0.0.0.0 promisc up
brctl addbr uml-bridge
brctl setfd uml-bridge 0
brctl sethello uml-bridge 0
brctl stp uml-bridge off
ifconfig uml-bridge 10.1.1.219 netmask 255.0.0.0 up
brctl addif uml-bridge eth0
tunctl uml-conn0
ifconfig uml-conn0 0.0.0.0 promisc up
brctl addif uml-bridge uml-conn0

For a detailed description of what these commands do, please see the UML Bridging HOWTO (http://edeca.net/articles/bridging/index.html). These commands set up an ethernet bridge with the name of uml-bridge, attach eth0 to it in promiscuous mode and create an ethernet interface called uml-conn0 in promiscuous mode which is attached to uml-bridge. In this manner, two ethernet interfaces, eth0 and uml-conn0 will be part of the same network. Ethernet packets sent to eth0 will be intelligently sent to uml-conn0 and vice versa, acting as a sort of switch in the linux kernel. Note that if you are connected to the host machine via the network and enter the commands interactively, you will be disconnected unless you execute the above commands in a script.

Next we must simply run the UML kernel (run the UML "linux" executable) and provide uml-conn0 as its ethernet device:

./linux eth0=tuntap,uml-conn0

Then, within UML linux, set the IP to 10.1.1.220. You should be able to ping 10.1.1.219 and the outside world within the UML you just created.

35.2.4. Local ethernet bridging

This will show you how to bring up the UML kernel, so it can communicate with one or more UML kernels on the same machine, but not allowing for outside network connectivity within the UMLs. This could be used for testing a multi-node environment, without affecting others on the networks.

We assume, like before, that the host kernel has IP address 10.1.1.219, although this isn't terribly important for this example. We will then add to the host kernel IP address 172.16.1.1, then give the UML kernel IP address 172.16.1.2. So, you can ping the UML kernel, by pinging its IP address 172.16.1.2, from the host kernel and you can ping from the UML kernel to the host kernel at IP 172.16.1.1. The UML kernel will not, however, be able to communicate to the outside world.

First run maketunedev.sh kernel_version then run:

brctl addbr uml-bridge
brctl setfd uml-bridge 0
brctl sethello uml-bridge 0
brctl stp uml-bridge off
tunctl -t uml-conn0
ifconfig uml-conn0 0.0.0.0 promisc up
brctl addif uml-bridge uml-conn0
ifconfig uml-bridge 172.16.1.1 up

This sequence of commands will set up a bridge named uml-bridge then it will create tun interface uml-conn0. It will attach 172.16.1.1 to the uml-bridge for the host kernel. We then invoke the UML, giving it uml-conn0 for its ethernet address:

linux eth0=tuntap,uml-conn0

Configure the UML to use IP address 172.16.1.2 and the host and UML kernels can communicate via IPs 172.16.1.1. and 172.16.1.2 respectively. You can create more than one UML kernel, giving each IPs in the 172.16.0.0 network. The only caveat is that you must assign a unique ethernet address to each one as they will by default use ethernet address fe:fd:0:0:0:0. So for the second UML you can do the following, after bringing up the network:

ifconfig eth0 hw ether fe:fd:01:00:00:00

to force it to use ethernet address fe:fd:01:00:00:00

35.3. Putting it all together: UML + LVS examples (not finished)

35.3.1. Ethernet bridging to the world

We will have 1 UML kernel acting as the LVS director for clients and realservers located on outside machines.

35.3.2. Local ethernet bridging with 2 UML kernels

We will have 1 UML kernel for the director and 1 for the realserver. We can connect from the host kernel to the director, routing to the realserver, but we cannot communicate to the outside world. This allows us to do multinode testing within one machine while not disturbing anyone else.