<p>Last time, we set up a three layer container test environment:</p>

<ul>
<li><p><b>Laptop</b> - the host system running on real hardware (my Ubuntu
laptop).</p></li>
<li><p><b>KVM</b> - a virtual debian Sid system running under KVM.<p></li>
<li><p><b>Container</b> - a simple busybox-based system running in a
container.</p></li>
</ul>

<p>So "Laptop" hosts "KVM" which hosts "Container".  This lets us reconfigure
and reboot the container host (the KVM system) without screwing up our
real host environment (the Laptop system).</p>

<p>We ended with a shell prompt inside a container.  Now we're going to set up
networking in the container, with different routing than the KVM system so
the Container system and KVM system have different views of the outside
world.</p>

<p>LXC supports several different virtual network types, listed in
the lxc.conf man page: veth uses Linux's ethernet bridging support,
vlan sets up a virtual interface selects packets by IP address, and
macvlan sets up a virtual interface that selects packets by mac address,
that routes packets at the IP level, and veth joins interfaces together
using Linux's ethernet bridging support (and the ebtables subsystem).</p>

<p>The other two networking options LXC supports are "empty" (just the
loopback interface), and "phys" to move one of the host's ethernet interfaces
into the container (removing it from the host system).</p>

<p>We're going to add a second ethernet interface to the KVM system, and
use the "phys" option to move it into the container.</p>

<b><h2>Step 1: Add a TAP interface to the Laptop.</h2></b>

<p>The TUN/TAP subsystem creates a virtual ethernet interface attached to a
process.  (A TUN interface allows a userspace program to read/write IP packets,
and a TAP interface works with ethernet frames instead.)  For details, see the
<a href=http://kernel.org/doc/Documentation/networking/tuntap.txt>kernel
TUN/TAP documentation</a>.</p>

<p>We're going to attach a TAP interface to KVM, to add a second ethernet
interface to the KVM system.  Doing so requires root access
on the laptop, but we can use the "tunctl" program (from the "uml-utilities"
package) to create a new TUN/TAP interface and then hand it over to a
non-root user (so we don't have to run KVM as root).</p>

<p>Run this as root:</p>

<blockquote><pre>
# Replace "landley" with your username
tunctl -u landley -t kvm0
ifconfig kvm0 192.168.254.1 netmask 255.255.255.0
echo 1 > /proc/sys/net/ipv4/ip_forward
</pre></blockquote>

<p>The above commands last until the next time you reboot your Laptop system,
at which point you'll have to re-run them.  It associates the address
192.168.254.1 with the TAP interface on the Laptop host, and tells the
Laptop to route packets between interfaces.</p>

<p>If you want to remove the tun/tap interface from the host (without
rebooting), the command is:</p>

<blockquote><pre>
tunctl -d kvm0
</pre></blockquote>

<b><h2>Step 2: Launch KVM with two ethernet interfaces.</h2></b>

<p>We need to reboot our KVM system, still using the kernel and root filesystem
we built last time but this time specifing two ethernet interfaces.  The
first is still eth0 masqueraded through a virtual 10.0.2.x LAN (for use by
the KVM host), and the other's a TAP device connected directly to the host
(for use by the container).</p>

<p>To do this, we append a couple new arguments to the end of the previous
KVM command line:</p>

<blockquote><pre>
kvm -m 1024 -kernel arch/x86/boot/bzImage -no-reboot -hda ~/sid.ext3 \
  -append "root=/dev/hda rw panic=1" \
  -net nic,model=e1000 -net user,net=10.0.2.0/8 -redir tcp:9876::22 \
  -net nic,model=e1000 -net tap,ifname=kvm0,script=no
</pre></blockquote>

<p>The first "-net nic" still creates an e1000 interface as KVM's eth0, the
"-net user" plugs that interface into the masqueraded 10.0.2.x LAN, and
-redir forwards port 9876 of the laptop's loopback to port 22 on that
interface.  What's new is the second "-net nic" which adds another
e1000 interface (eth1) to KVM, and "-net tap" which connects that interface
to the TUN/TAP device we just created on the Laptop.</p>

<b><h2>Step 3: Set up a new container in the KVM system.</h2></b>

<p>We're using a more complex LXC config file this time, using the "phys"
network type, telling it to move the host's eth1 into the container as "eth0".
So ssh into the kvm system, in the directory containing the static "busybox"
binary, and as root run:</p>

<blockquote><pre>
cat > busybox.conf << EOF
lxc.utsname = busybox
lxc.network.type = phys
lxc.network.flags = up
lxc.network.link = eth1
lxc.network.name = eth0
EOF

PATH=$(pwd):$PATH lxc-create -f busybox.conf -t busybox -n busybox
lxc-start -n busybox
</pre></blockquote>

<p>And in a separate terminal:</p>

<blockquote><pre>
lxc-console -n busybox
</pre></blockquote>

<pre>
NFS export:

sudo mount -o port=4711,mountport=4711,mountvers=3,nfsvers=3,nolock,tcp 10.24.29.12:/home/landley/nfs /mnt

Let's start with the network configuration file.  The man page for "lxc.conf"
describes the file format.  We're going to move a physical interface (eth1)
from the host into the container.  This will remove it from the host's
namespace, and make it appear only in the container.

  cat > container.conf << EOF
  lxc.utsname = container
  lxc.work.type = phys
  lxc.work.flags = up
  lxc.work.link = eth1
  EOF


./unfsd -u -d -e $(pwd)/exports -n 4711 -m 4711 -p -t -l 10.24.29.12
</pre>