Project

General

Profile

Dynamic Uml Mesh Modeler

Dumm is a framework to set up a virtual network using user mode linux guests.
It cleverly glues together some nice technologies to build networks dynamically.
To change the network topology, hosts are not required to reboot, changes apply
instantly and configuration can be done on the host (no network connection
required to change anything).

Status

Dumm is experimental and in development (see source:src/dumm).
Along with the dumm library, two frontends are currently usable:
  • A graphical GTK client
  • A console client with Ruby bindings to script scenarios in Ruby
The graphical client is incomplete. It is missing:
  • Removal of added switches
  • Disconnecting guests from switches
  • Scenario management

The Ruby console client also misses a surrounding testing infrastructure which
will be built with ruby in the near future.

Why UML?

UML is a senior in vitualization technologies, and there is a lot of new
hyped stuff about virtualization around. However, UML is lightweight, easy to
set up and allows dynamic reconfiguration (e.g. add/remove interfaces at
runtime), allows access to the hosts filesystem through hostfs and has some
other neat features.
Performance is not critical for our needs, and maybe we get hardware
virtualization support soon in UML.
It is free and fits perfectly.

Requirements

  • Host:
    • Kernel:
      • A recent 2.6 kernel
      • SKAS3 patch recommended
      • FUSE enabled
      • support for TAP devices
    • Userland:
      • libstrongswan
      • libbridge from bridge-utils
      • using the GTK client:
        • GTK+2 with developement headers
        • Gnome VteTerminal with developement headers
      • using the Ruby client:
        • Ruby 1.8 with developement headers
        • IRB
  • Guest:
    • Kernel:
    • Userland:
      • ip from iproute2

Architecture

Working set

Dumm needs a directory to store all its files, guest configurations and other
stuff. Inside that working directory, you'll find:

workingdir/      - root folder containing a set of hosts and scenarios
  guests/        - contains all created guests
    alice/       - subdirectory for host "alice" 
      alice/     - UML created folder (named umid) containing UML runtime files
      args       - additional arguments to pass to guest, such as memory configuration
      pid        - PID file if guest is running, handy to attach gdb to kernel
      linux      - symlinked UML kernel this host uses
      master/    - symlinked master root file system for this host
      diff/      - copy-on-write overlay to master this host uses
      union/     - mounted unified filesystem (master + diff + optional scenario)
    bob/
      ...        - same stuff as in alice
  templates/     - contains all scenario templates
    test1/       - a scenario folder
      diff/      - copy-on-write overlays for each guest's union folder
        alice/   - COW for alice
        bob/     - COW for bob

Networking

Network connectivity is realized through tap devices. When creating a eth0
network device on alice, a alice-eth0 tap device appears on the host. These
are directly connected, when alice sends traffic to eth0, it appears on the
host at alice-eth0. You can see that as a small network segment (or just a
cable), where these interfaces are attached directly.
To build larger network segments, linux bridging on the host comes into play.
Segments are created by creating a bridge (as with brctl), and then attaching
our tap devices to that bridge. Routing can be done on a UML guest, or even on
the host.
This setup has some advantages over the uml_switch solution. Bridging works
more reliable in the kernel, and as we see every network interface on the host,
we can sniff at every interface to get some clue what the guests are doing.

HowTo

In this mini-howto, we build and boot a minimalistic debian guest on a ubuntu host.
We do everything as root here to simplify things!

Host setup

  • Install required packages:
    apt-get install libfuse-dev libgtk2.0-dev libvte-dev ruby ruby1.8-dev irb1.8
    
  • Install libbridge manually:
    git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/bridge-utils.git
    cd bridge-utils
    autoconf
    ./configure
    cd libbridge
    gcc -fPIC -c libbridge_devif.c libbridge_if.c libbridge_init.c libbridge_misc.c
    ar rcs libbridge.a libbridge_devif.o libbridge_if.o libbridge_init.o libbridge_misc.o
    ranlib libbridge.a
    install libbridge.a /usr/local/lib
    install libbridge.h /usr/local/include
    
  • Build and install strongSwan from Git sources:
    git clone http://git.strongswan.org/strongswan.git
    cd strongswan
    less HACKING
    ./autogen
    ./configure --enable-dumm [other options]
    make
    make install
    
  • Ubuntu kernels almost fit our needs, they have FUSE and TAP device support. However, SKAS3 mode is missing. Build your own kernel based on the Ubuntu Howto, patched with the SKAS3 patch. SKAS3 is not required, but guests run much faster with SKAS3 enabled on the host.

Guest master filesystem setup

  • Create a clean directory and a directory for our master filesystem in it:
    mkdir umldir
    cd umldir
    mkdir master
    
  • Bootstrap a debian sid system into master:
    apt-get install debootstrap
    debootstrap sid master http://mirror.switch.ch/ftp/pub/debian/
    
    To build a x86 guest on a x64 host, use the --arch option.
  • Enter chroot
    chroot master
    
  • Enable main repository
    echo deb http://mirror.switch.ch/ftp/pub/debian sid main contrib > /etc/apt/sources.list
    apt-get update
    
  • Install proper locales support
    apt-get install locales
    dpkg-reconfigure locales
    
  • For Ubuntu lucid guests, you'll have to specify the locales before generating them:
    echo "en_US.UTF-8 UTF-8" >> /var/lib/locales/supported.d/local
    
  • Install some packages for strongSwan
    apt-get install libgmp3c2 libsqlite3-0 libcurl3 dropbear gdb binutils
    
  • Remove the root password by deleting the asterisk in /etc/shadow
    grep root /etc/shadow
    root:*:15173:0:99999:7:::
    vi /etc/shadow
    grep root /etc/shadow
    root::15173:0:99999:7:::
    
  • Leave chroot
    exit
    

Build a UML guest kernel

git clone git://git.strongswan.org/linux-dumm.git
cd linux-dumm
git checkout -b uml-ha-2.6.39 uml-ha-2.6.39
wget http://download.strongswan.org/uml/config-2.6.39
mv config-2.6.39 .config
make linux ARCH=um SUBARCH=i386

Start a network

You'll have to run the tools as root. Make sure you have a DISPLAY set, e.g. by starting it under sudo.

  • Invoke the graphical client
    sudo ipsec dumm
    

    Add guests, select our master filesystem and the compiled kernel. Add a bridges and connect your guests to it.
    Start your guests and configure them.
  • Using the irdumm ruby client
    sudo ipsec irdumm
    irb> sun = Guest.new("sun", "path/to/linux-2.6.27/linux", "path/to/master/", "mem=64M con1=xterm")
    irb> sun.start
    irb> sun.exec("echo sun > /etc/hostname")
    irb> sun.add("eth0").connect(Bridge.new("br0")).add("192.168.0.1")
    irb> sun.exec("ifconfig") { |line| puts line }
    irb> quit
    

Installing strongSwan on guests

As we have full access to the master filesystem on the host, we can build strongSwan on the host and install it to the guests

cd path/to/strongswan/
DESTDIR=/full/path/to/master make install

Troubleshooting

The kernel cant find init, but it's there!?

Double check you are using the same architecture for kernel and filesystem. A i386 kernel can't boot a x64 init, and it currently does not work vice-versa, either. Pass the ARCH/SUBARCH variables after make, otherwise they get ignored!

Debugging with gdb inside a x64 UML guest fails with an Input/Output error!

This is a known issue, but has not yet been solved.

I'm using a maverick i386 guest on a x64 host, but condition variables behave strangely.

This is a known issue, somehow related to eglibc version. Threads waiting in condvars don't get
wakened up while signaled. Not yet solved.

Unix sockets created in the guest through hostfs are inaccessible in the guest.

Looks like an issue with hostfs, not yet solved. Creating Unix Sockets on an in-guest mounted tmpfs should work.