WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Vnet update.

# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID 6bad5eb72ce03ec54e2f44f06e0b46ba2db1715b
# Parent  a43cc4e06814859cffe6ea09e07d6e87f6fec6ab
Vnet update.
Fix the tools/vnet makefiles so that vnets will compile
and includes updates to the vnet implementation.
Vnet ids are increased to 128 bits. The vnet module will
insmod whether xen-br0 exists or not.
Signed-off-by: Mike Wray <mike.wray@xxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>

diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/00INSTALL
--- a/tools/vnet/00INSTALL      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/00INSTALL      Fri Aug 26 10:52:53 2005
@@ -1,14 +1,34 @@
 
-To compile and install run "make install"; if it fails or you need to 
reinstall 
-run "make clean" first or the build will fail, at least that is what I have 
-found under 2.6.10.
+make
+        - compile in local dirs. The module is in vnet-module/vnet_module.ko.
 
-Other important items:
+make dist
+        - compile and install into $(XEN_ROOT)/dist/install,
+        - where XEN_ROOT is the root of the xen tree.
+
+make install
+        - compile and install into system.
+
+The xen0 kernel must have been compiled before building the vnet module.
+The vnet module installs to
+ /lib/modules/<kernel version>-xen0/kernel/xen/vnet_module.ko
+
+The vnet module should be loaded before starting xend, or
+xend will fail to create any persistent vnets it has in its configuration.
+The script network-vnet is a modified version of the xen network script
+that loads the module if it's not already loaded.
+
+The module uses kernel crypto functions, and these need to be
+enabled in the xen0 kernel config. They should be on by default -
+if they're not you will get compile or insmod errors (see below).
+
+Kernel config options:
+
 1)     You will need to have your xen0 kernel compiled with HMAC_SUPPORT 
        2.6.x = (MAIN MENU: Cryptographic Options -> HMAC Support)
        BEFORE running "make install".
 
-2)     You will want at least some of the other alogorithms listed under
+2)     You will want at least some of the other algorithms listed under
        "Cryptographic Options" for the kernel compiled as modules.
 
 3)     You will want the networking IPsec/VLAN options compiled in as modules
@@ -23,9 +43,5 @@
        
                                        802.1Q VLAN Support
 
-4)     The module (vnet_module) will not properly load from the command line
-       with a "modprobe vnet_module".  Use network-vnet to properly configure
-       your system and load the module for you.
-
 Please refer to the additional documentation found in tools/vnet/doc for
 proper syntax and config file parameters.
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/Makefile
--- a/tools/vnet/Makefile       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/Makefile       Fri Aug 26 10:52:53 2005
@@ -1,18 +1,21 @@
+# -*- mode: Makefile; -*-
 
-export LINUX_SERIES ?=2.6
+ifndef VNET_ROOT
+export VNET_ROOT = $(shell pwd)
+include $(VNET_ROOT)/Make.env
+endif
 
-# Root path to install in.
-# Set to '/' to install relative to filesystem root.
-export prefix?=$(shell cd ../../dist/install && pwd)
+.PHONY: all compile install dist clean pristine
+.PHONY: gc-all gc-install gc-clean
 
-.PHONY: all compile
-.PHONY: gc-install gc-clean gc-prstine
-.PHONY: libxutil vnetd vnet-module install dist clean pristine
+SUBDIRS:=
+SUBDIRS+= examples
+SUBDIRS+= gc
+SUBDIRS+= libxutil
+SUBDIRS+= vnetd
+SUBDIRS+= vnet-module
 
 all: compile
-
-compile: libxutil vnetd vnet-module
-#compile: vnet-module
 
 gc.tar.gz:
        wget http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/$@
@@ -21,36 +24,39 @@
        tar xfz gc.tar.gz
        ln -sf gc?.? gc
 
-gc-install: gc 
-       (cd gc && make test && ./configure --prefix=`pwd`/install)
+$(GC_LIB_A): gc
+       (cd gc && ./configure --prefix=$(GC_DIR) )
        make -C gc
-       make -C gc install
+       DESTDIR="" make -C gc install
+
+gc-all: $(GC_LIB_A)
+
+gc-install:
 
 gc-clean:
-       -$(MAKE) -C gc clean
+       -@$(RM) -r gc?.? gc
 
-gc-pristine:
-       -rm -rf gc?.? gc
+submak = $(MAKE) -C $(patsubst %-$(1),%,$(@)) $(1)
+subtgt = $(patsubst %,%-$(1),$(SUBDIRS))
 
-libxutil:
-       $(MAKE) -C libxutil
+%-all:
+       $(call submak,all)
 
-vnetd: gc-install
-       $(MAKE) -C vnetd
+%-clean:
+       -$(call submak,clean)
 
-vnet-module:
-       $(MAKE) -C vnet-module
+%-install:
+       $(call submak,install)
 
-install: compile
-       $(MAKE) -C libxutil install
-       $(MAKE) -C vnetd install
-       $(MAKE) -C vnet-module install
-       $(MAKE) -C examples install
+compile: $(call subtgt,all)
 
-clean:
-       -$(MAKE) -C libxutil clean
-       -$(MAKE) -C vnetd clean
-       -$(MAKE) -C vnet-module clean
-       -rm -rf gc?.? gc
+install: DESTDIR=
+install: dist
 
-pristine: clean gc-pristine
+dist: compile $(call subtgt,install)
+
+clean: $(call subtgt,clean)
+       -@$(RM) -r build
+
+pristine: clean
+       -@$(RM) gc.tar.gz
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/doc/vnet-module.txt
--- a/tools/vnet/doc/vnet-module.txt    Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/doc/vnet-module.txt    Fri Aug 26 10:52:53 2005
@@ -1,20 +1,33 @@
 Vnet Module Command Interface
 Mike Wray <mike.wray@xxxxxx>
-2004/09/17
+2005/08/25
 
 When insmod the vnet-module creates /proc/vnet/policy which
 can be used to control the module by writing commands into it.
 The return code from the command should be returned by close.
+Xend uses these commands to implement its vnet interface.
 
 The commands are:
 
-(vnet.add (id <id>) [(security { none | auth | conf } )] )
+(vnet.add (id <id>) [(vnetif <ifname>)] [(security { none | auth | conf } )] )
 
 Create the vnet with id <id> and the given security level (default none).
+Vnet ids are 128-bit and can be specified as 8 fields of 1 to 4 hex digits
+separated by colons. A vnet id with no colons is treated as one with the first
+7 fields zero. Examples:
+
+1500 - equivalent to 0:0:0:0:0:0:0:1500
+aaff:0:0:0:0:0:77:88
+
 Security levels:
 - none: no security
 - auth: message authentication (IPSEC hmac)
 - conf: message confidentiality (IPSEC hmac and encryption)
+
+The <ifname> is the name of the network device created for the vnet.
+If not given it defaults to vnif<N>, where <N> is the hex for the
+8-th field in the id. Note that network device names can have a
+maximum of 14 characters.
 
 (vnet.del (id <id>))
 
@@ -31,11 +44,17 @@
 Remove the vif with MAC address <macaddr> from the vnet with id <vnetid>.
 The vnet module will stop responding to VARP for the vif.
 
+(vif.print)
+
+Print the known vnets, vifs and varp cache on the console.
+
 Examples:
 
 To create vnet 10 with no security:
 
 echo '(vnet.add (id 10))' > /proc/vnet/policy
+
+This creates a device vnif0010.
 
 To create vnet 11 with message authentication:
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/doc/vnet-xend.txt
--- a/tools/vnet/doc/vnet-xend.txt      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/doc/vnet-xend.txt      Fri Aug 26 10:52:53 2005
@@ -3,11 +3,13 @@
 
 Mike Wray <mike.wray@xxxxxx>
 
+2005/08/25
+
 0) Introduction
 ---------------
 
 Vnets provide virtual private LANs for virtual machines.
-This is done using bridging and tunneling. A virtual interface
+This is done using bridging and multipoint tunneling. A virtual interface
 on a vnet can only see other interfaces on the same vnet - it cannot
 see the real network, and the real network cannot see it either.
 
@@ -32,13 +34,16 @@
 
 Restart xend.
 
+Alternatively insert the vnet module using vnet-insert,
+preferably before xend starts.
+
 2) Creating vnets
 -----------------
 
 Xend already implements commands to add/remove vnets and
 bridge to them. To add a vnet use
 
-xm call vnet_add <vnet config file>
+xm vnet-create <vnet config file>
 
 For example, if vnet97.sxp contains:
 
@@ -46,7 +51,7 @@
 
 do
 
-xm call vnet_add vnet97.sxp
+xm vnet-create vnet97.sxp
 
 This will define a vnet with id 97 and no security. The bridge for the
 vnet is called vnet97 and the virtual interface for it is vnetif97.
@@ -64,31 +69,35 @@
 Once configured, vnets are persistent in the xend database.
 To remove a vnet use
 
-xm call vnet_delete <vnet id>
+xm vnet-delete <vnet id>
 
 To list vnets use
 
-xm call vnets
+xm vnet-list
 
 To get information on a vnet id use
 
-xm call vnet <vnet id>
+xm vnet-list <vnet id>
 
 3) Troubleshooting
 ------------------
 
 The vnet module should appear in 'lsmod'.
-If a vnet has been configured it should appear in the output of 'xm call 
vnets'.
+If a vnet has been configured it should appear in the output of 'xm vnet-list'.
 Its bridge and interface should appear in 'ifconfig'.
 It should also show in 'brctl show', with its attached interfaces.
 
-You can 'see into' a vnet from dom0 if you put an IP address on the bridge.
+You can 'see into' a vnet from dom0 if you put an IP address on the bridge
+and configure its MAC address as a vif.
 For example, if you have vnet97 with a vm with ip addr 10.0.0.12 on it,
-then
+and <mac> is the MAC address of vnet97 (use ifconfig), then
 
+echo '(vif.add (vnet 97) (vmac <mac>))' >/proc/vnet/policy
 ifconfig vnet97 10.0.0.20 up
 
 should let you ping 10.0.0.12 via the vnet97 bridge.
+This works even if the vm with vif 10.0.0.12 is on another
+machine (it only works locally if you don't use vif.add).
 
 4) Examples
 -----------
@@ -104,11 +113,11 @@
   (linux
    (kernel /boot/vmlinuz-2.6-xenU)
    (ip 10.0.0.12:1.2.3.4::::eth0:off)
-   (root /dev/hda1)
+   (root /dev/sda1)
    (args 'rw fastboot 4')
   )
  )
- (device (vbd (uname phy:hda2) (dev hda1) (mode w)))
+ (device (vbd (uname phy:hda2) (dev sda1) (mode w)))
  (device (vif (mac aa:00:00:11:00:12) (bridge vnet97)))
 )
 
@@ -123,11 +132,11 @@
   (linux
    (kernel /boot/vmlinuz-2.6-xenU)
    (ip 10.0.0.11:1.2.3.4::::eth0:off)
-   (root /dev/hda1)
+   (root /dev/sda1)
    (args 'rw fastboot 4')
   )
  )
- (device (vbd (uname phy:hda3) (dev hda1) (mode w)))
+ (device (vbd (uname phy:hda3) (dev sda1) (mode w)))
  (device (vif (mac aa:00:00:11:00:11) (bridge vnet97)))
 )
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/examples/Makefile
--- a/tools/vnet/examples/Makefile      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/examples/Makefile      Fri Aug 26 10:52:53 2005
@@ -2,11 +2,14 @@
 #============================================================================
 
 XEN_SCRIPT_DIR:=/etc/xen/scripts
+
+.PHONY: all install clean
 
 all:
 
 install:
        install -m 0755 -d $(DESTDIR)$(XEN_SCRIPT_DIR)
        install -m 0554 network-vnet $(DESTDIR)$(XEN_SCRIPT_DIR)
+       install -m 0554 vnet-insert $(DESTDIR)$(XEN_SCRIPT_DIR)
 
 clean:
\ No newline at end of file
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/examples/network-vnet
--- a/tools/vnet/examples/network-vnet  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/examples/network-vnet  Fri Aug 26 10:52:53 2005
@@ -1,218 +1,10 @@
 #!/bin/sh
-#============================================================================
-# Default Xen network start/stop script.
-# Xend calls a network script when it starts.
-# The script name to use is defined in /etc/xen/xend-config.sxp
-# in the network-script field.
-#
-# This script creates a bridge (default xen-br0), adds a device
-# (default eth0) to it, copies the IP addresses from the device
-# to the bridge and adjusts the routes accordingly.
-#
-# If all goes well, this should ensure that networking stays up.
-# However, some configurations are upset by this, especially
-# NFS roots. If the bridged setup does not meet your needs,
-# configure a different script, for example using routing instead.
-#
-# Usage:
-#
-# network (start|stop|status) {VAR=VAL}*
-#
-# Vars:
-#
-# bridge     The bridge to use (default xen-br0).
-# netdev     The interface to add to the bridge (default eth0).
-# antispoof  Whether to use iptables to prevent spoofing (default yes).
-#
-# start:
-# Creates the bridge and enslaves netdev to it.
-# Copies the IP addresses from netdev to the bridge.
-# Deletes the routes to netdev and adds them on bridge.
-#
-# stop:
-# Removes netdev from the bridge.
-# Deletes the routes to bridge and adds them to netdev.
-#
-# status:
-# Print ifconfig for netdev and bridge.
-# Print routes.
-#
-#============================================================================
+scriptdir=/etc/xen/scripts/
 
-# Exit if anything goes wrong.
-set -e 
+case ${1} in
+    start)
+        ${scriptdir}/vnet-insert
+        ;;
+esac
 
-# First arg is the operation.
-OP=$1
-shift
-
-# Pull variables in args in to environment.
-for arg ; do export "${arg}" ; done
-
-bridge=${bridge:-xen-br0}
-netdev=${netdev:-eth0}
-antispoof=${antispoof:-yes}
-
-echo "network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof"
-
-# Usage: transfer_addrs src dst
-# Copy all IP addresses (including aliases) from device $src to device $dst.
-transfer_addrs () {
-    local src=$1
-    local dst=$2
-    # Don't bother if $dst already has IP addresses.
-    if ip addr show dev ${dst} | egrep -q '^ *inet' ; then
-        return
-    fi
-    # Address lines start with 'inet' and have the device in them.
-    # Replace 'inet' with 'ip addr add' and change the device name $src
-    # to 'dev $src'. Remove netmask as we'll add routes later.
-    ip addr show dev ${src} | egrep '^ *inet' | sed -e "
-s/inet/ip addr add/
-s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@
-s/${src}/dev ${dst}/
-" | sh -e
-}
-
-# Usage: transfer_routes src dst
-# Get all IP routes to device $src, delete them, and
-# add the same routes to device $dst.
-# The original routes have to be deleted, otherwise adding them
-# for $dst fails (duplicate routes).
-transfer_routes () {
-    local src=$1
-    local dst=$2
-    # List all routes and grep the ones with $src in.
-    # Stick 'ip route del' on the front to delete.
-    # Change $src to $dst and use 'ip route add' to add.
-    ip route list | grep ${src} | sed -e "
-h
-s/^/ip route del /
-P
-g
-s/${src}/${dst}/
-s/^/ip route add /
-P
-d
-" | sh -e
-}
-
-# Usage: create_bridge dev bridge
-# Create bridge $bridge and add device $dev to it.
-create_bridge () {
-    local dev=$1
-    local bridge=$2
-
-    # Don't create the bridge if it already exists.
-    if ! brctl show | grep -q ${bridge} ; then
-        brctl addbr ${bridge}
-        brctl stp ${bridge} off
-        brctl setfd ${bridge} 0
-    fi
-    ifconfig ${bridge} up
-}
-
-# Usage: antispoofing dev bridge
-# Set the default forwarding policy for $dev to drop.
-# Allow forwarding to the bridge.
-antispoofing () {
-    local dev=$1
-    local bridge=$2
-
-    iptables -P FORWARD DROP
-    iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT
-}
-
-# Usage: show_status dev bridge
-# Print ifconfig and routes.
-show_status () {
-    local dev=$1
-    local bridge=$2
-    
-    echo '============================================================'
-    ifconfig ${dev}
-    ifconfig ${bridge}
-    echo ' '
-    ip route list
-    echo ' '
-    route -n
-    echo '============================================================'
-}
-
-# Insert the vnet module if it can be found and
-# it's not already there.
-vnet_insert () {
-    local module="vnet_module"
-    local mod_dir=/lib/modules/$(uname -r)/kernel
-    local mod_path="${mod_dir}/${module}"
-    local mod_obj=""
-
-    for ext in ".o" ".ko" ; do
-        f=${mod_path}${ext}
-        if [ -f ${f} ] ; then
-            mod_obj=$f
-            break
-        fi
-    done
-    if [ "${mod_obj}" == "" ] ; then
-        return
-    fi
-    if lsmod | grep -q ${module} ; then
-        echo "VNET: ${module} loaded"
-    else
-        echo "VNET: Loading ${module}..."
-               insmod ${mod_obj}
-    fi
-}
-
-op_start () {
-    if [ "${bridge}" == "null" ] ; then
-        return
-    fi
-    # Create the bridge and give it the interface IP addresses.
-    # Move the interface routes onto the bridge.
-    create_bridge ${netdev} ${bridge}
-    transfer_addrs ${netdev} ${bridge}
-    transfer_routes ${netdev} ${bridge}
-    # Don't add $dev to $bridge if it's already on a bridge.
-    if ! brctl show | grep -q ${netdev} ; then
-        brctl addif ${bridge} ${netdev}
-    fi
-    
-    if [ ${antispoof} == 'yes' ] ; then
-        antispoofing ${netdev} ${bridge}
-    fi
-
-    vnet_insert
-}
-
-op_stop () {
-    if [ "${bridge}" == "null" ] ; then
-        return
-    fi
-    # Remove the interface from the bridge.
-    # Move the routes back to the interface.
-    brctl delif ${bridge} ${netdev}
-    transfer_routes ${bridge} ${netdev}
-
-    # It's not our place to be enabling forwarding...
-}
-
-case ${OP} in
-    start)
-        op_start
-        ;;
-    
-    stop)
-        op_stop
-        ;;
-
-    status)
-        show_status ${netdev} ${bridge}
-       ;;
-
-    *)
-       echo 'Unknown command: ' ${OP}
-       echo 'Valid commands are: start, stop, status'
-       exit 1
-esac
+${scriptdir}/network-bridge "$@"
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/examples/vnet97.sxp
--- a/tools/vnet/examples/vnet97.sxp    Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/examples/vnet97.sxp    Fri Aug 26 10:52:53 2005
@@ -1,3 +1,2 @@
 # Vnet configuration for a vnet with id 97 and no security.
-# Configure using 'xm call vnet_add vnet97.sxp'.
 (vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none))
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/examples/vnet98.sxp
--- a/tools/vnet/examples/vnet98.sxp    Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/examples/vnet98.sxp    Fri Aug 26 10:52:53 2005
@@ -1,3 +1,2 @@
 # Vnet configuration for a vnet with id 98 and message authentication.
-# Configure using 'xm call vnet_add vnet98.sxp'.
 (vnet (id 98) (bridge vnet98) (vnetif vnetif98) (security auth))
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/examples/vnet99.sxp
--- a/tools/vnet/examples/vnet99.sxp    Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/examples/vnet99.sxp    Fri Aug 26 10:52:53 2005
@@ -1,3 +1,2 @@
 # Vnet configuration for a vnet with id 99 and message confidentiality.
-# Configure using 'xm call vnet_add vnet99.sxp'.
 (vnet (id 99) (bridge vnet99) (vnetif vnetif99) (security conf))
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/Makefile
--- a/tools/vnet/libxutil/Makefile      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/Makefile      Fri Aug 26 10:52:53 2005
@@ -1,5 +1,8 @@
+ifndef VNET_ROOT
+export VNET_ROOT = $(shell cd .. && pwd)
+include $(VNET_ROOT)/Make.env
+endif
 
-XEN_ROOT = ../../..
 INSTALL                = install
 INSTALL_DATA   = $(INSTALL) -m0644
 INSTALL_PROG   = $(INSTALL) -m0755
@@ -15,6 +18,7 @@
 LIB_SRCS += hash_table.c
 LIB_SRCS += iostream.c
 LIB_SRCS += lexis.c
+LIB_SRCS += mem_stream.c
 LIB_SRCS += string_stream.c
 LIB_SRCS += sxpr.c
 LIB_SRCS += sxpr_parser.c
@@ -26,6 +30,7 @@
 PIC_OBJS := $(LIB_SRCS:.c=.opic)
 
 CFLAGS   += -Wall -Werror -O3 -fno-strict-aliasing
+CFLAGS   += -g
 
 # Get gcc to generate the dependencies for us.
 CFLAGS   += -Wp,-MD,.$(@F).d
@@ -39,6 +44,7 @@
 LIB      += libxutil.a
 
 all: build
+
 build: check-for-zlib
        $(MAKE) $(LIB)
 
@@ -70,8 +76,8 @@
        ln -sf libxutil.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxutil.so
 
 clean:
-       $(RM) *.a *.so* *.o *.opic *.rpm 
-       $(RM) *~
-       $(RM) $(DEPS)
+       -@$(RM) *.a *.so* *.o *.opic *.rpm 
+       -@$(RM) *~
+       -@$(RM) $(DEPS)
 
 -include $(DEPS)
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/debug.h
--- a/tools/vnet/libxutil/debug.h       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/debug.h       Fri Aug 26 10:52:53 2005
@@ -49,9 +49,9 @@
 #ifdef DEBUG
 
 #define dprintf(fmt, args...) fprintf(stdout, "%d [DBG] " MODULE_NAME ">%s" 
fmt, getpid(), __FUNCTION__, ##args)
-#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME ">%s" 
fmt, getpid(),__FUNCTION__, ##args)
-#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME ">%s" 
fmt, getpid(),__FUNCTION__, ##args)
-#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME ">%s" 
fmt, getpid(),__FUNCTION__, ##args)
+#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME ">%s" 
fmt, getpid(), __FUNCTION__, ##args)
+#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME ">%s" 
fmt, getpid(), __FUNCTION__, ##args)
+#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME ">%s" 
fmt, getpid(), __FUNCTION__, ##args)
 
 #else
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/sxpr.c
--- a/tools/vnet/libxutil/sxpr.c        Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/sxpr.c        Fri Aug 26 10:52:53 2005
@@ -405,7 +405,6 @@
 #endif /* USE_GC */
 
 /** Create a new atom with the given name.
- * Makes an integer sxpr if the name can be parsed as an int.
  *
  * @param name the name
  * @return new atom
@@ -414,7 +413,8 @@
     Sxpr n, obj = ONOMEM;
     long v;
 
-    if(convert_atol(name, &v) == 0){
+    // Don't always want to do this.
+    if(0 && convert_atol(name, &v) == 0){
         obj = OINT(v);
     } else {
         n = string_new(name);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/sxpr.h
--- a/tools/vnet/libxutil/sxpr.h        Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/sxpr.h        Fri Aug 26 10:52:53 2005
@@ -228,7 +228,9 @@
  *
  * @param val pointer
  */
-#define PTR(val) OBJP(T_UINT, (void*)(val))
+static inline Sxpr PTR(void *val){
+    return OBJP(T_UINT, (void*)(val));
+}
 
 /** Allocate some memory and return an sxpr containing it.
  * Returns ONOMEM if allocation failed.
@@ -237,7 +239,9 @@
  * @param ty typecode
  * @return sxpr
  */
-#define halloc(_n, _ty) OBJP(_ty, allocate(_n))
+static inline Sxpr halloc(int n, int ty){
+    return OBJP(ty, allocate(n));
+}
 
 /** Allocate an sxpr containing a pointer to the given type.
  *
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/sxpr_parser.c
--- a/tools/vnet/libxutil/sxpr_parser.c Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/sxpr_parser.c Fri Aug 26 10:52:53 2005
@@ -472,7 +472,14 @@
 }
 
 int Parser_atom(Parser *p){
-    Sxpr obj = atom_new(peek_token(p));
+    Sxpr obj;
+    long v;
+    if(Parser_flags(p, PARSE_INT) &&
+       convert_atol(peek_token(p), &v) == 0){
+        obj = OINT(v);
+    } else {
+        obj = atom_new(peek_token(p));
+    }
     return Parser_set_value(p, obj);
 }
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/sxpr_parser.h
--- a/tools/vnet/libxutil/sxpr_parser.h Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/sxpr_parser.h Fri Aug 26 10:52:53 2005
@@ -89,15 +89,17 @@
 
 
 /** Parser flags. */
-//enum {
-//};
+enum {
+    /** Convert integer atoms to ints. */
+    PARSE_INT=1,
+};
 
 /** Raise some parser flags.
  *
  * @param in parser
  * @param flags flags mask
  */
-inline static void Parser_flags_raise(Parser *in, int flags){
+static inline void Parser_flags_raise(Parser *in, int flags){
     in->flags |= flags;
 }
 
@@ -106,7 +108,7 @@
  * @param in parser
  * @param flags flags mask
  */
-inline static void Parser_flags_lower(Parser *in, int flags){
+static inline void Parser_flags_lower(Parser *in, int flags){
     in->flags &= ~flags;
 }
 
@@ -114,8 +116,12 @@
  *
  * @param in parser
  */
-inline static void Parser_flags_clear(Parser *in){
+static inline void Parser_flags_clear(Parser *in){
     in->flags = 0;
+}
+
+static inline int Parser_flags(Parser *in, int flags){
+    return in->flags & flags;
 }
 
 extern void Parser_free(Parser *z);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/sys_string.c
--- a/tools/vnet/libxutil/sys_string.c  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/sys_string.c  Fri Aug 26 10:52:53 2005
@@ -27,6 +27,31 @@
 
 #include "allocate.h"
 #include "sys_string.h"
+
+#ifdef __KERNEL__
+
+#define deferr(_err) case _err: return #_err
+
+extern char *strerror(int err)
+{
+    switch(err){
+        deferr(EPERM);
+        deferr(ENOENT);
+        deferr(ESRCH);
+        deferr(EINTR);
+        deferr(EIO);
+        deferr(EINVAL);
+        deferr(ENOMEM);
+        deferr(EACCES);
+        deferr(EFAULT);
+        deferr(EBUSY);
+        
+    default:
+        return "ERROR";
+    }
+}
+
+#endif
 
 /** Set the base to use for converting a string to a number.  Base is
  * hex if starts with 0x, otherwise decimal.
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/libxutil/sys_string.h
--- a/tools/vnet/libxutil/sys_string.h  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/libxutil/sys_string.h  Fri Aug 26 10:52:53 2005
@@ -31,6 +31,8 @@
 #include <linux/types.h>
 #include <stdarg.h>
 #include "allocate.h"
+
+extern char *strerror(int err);
 
 #if 0
 static inline int tolower(int c){
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/00README
--- a/tools/vnet/vnet-module/00README   Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/00README   Fri Aug 26 10:52:53 2005
@@ -6,11 +6,11 @@
 The makefiles  use the following variables, which
 can be set in your env or on the make command line:
 
-LINUX_SERIES: linux release to compile for, 2.4 (default), or 2.6.
-XEN_ROOT: root of the xen tree containing kernel source.
+LINUX_SERIES:   linux release to compile for: 2.4, or 2.6 (default).
+XEN_ROOT:       root of the xen tree containing kernel source.
 KERNEL_VERSION: kernel version, default got from XEN_ROOT.
-KERNEL_MINOR: kernel minor version, default -xen0.
-KERNEL_SRC: path to kernel source, default linux-<VERSION> under XEN_ROOT.
+KERNEL_MINOR:   kernel minor version, default -xen0.
+KERNEL_SRC:     path to kernel source, default linux-<VERSION> under XEN_ROOT.
 
 *) For 2.4 kernel
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/Makefile
--- a/tools/vnet/vnet-module/Makefile   Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/Makefile   Fri Aug 26 10:52:53 2005
@@ -18,9 +18,13 @@
 # 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
 #============================================================================
 
+ifndef VNET_ROOT
+export VNET_ROOT = $(shell cd .. && pwd)
+include $(VNET_ROOT)/Make.env
+endif
+
 #============================================================================
 ifeq ($(src),)
-LINUX_SERIES ?=2.6
 
 include Makefile-$(LINUX_SERIES)
 
@@ -45,7 +49,7 @@
 # Setup explicit rules for them using the kbuild C compile rule.
 
 # File names in the lib dir.
-remote_srcs = $(foreach file,$(VNET_LIB_SRC),$(LIB_DIR)/$(file))
+remote_srcs = $(foreach file,$(VNET_LIB_SRC),$(LIBXUTIL_DIR)/$(file))
 
 # Equivalent file names here.
 local_srcs = $(foreach file,$(VNET_LIB_SRC),$(src)/$(file))
@@ -54,12 +58,12 @@
 local_objs = $(local_srcs:.c=.o)
 
 # Make the local objects depend on compiling the remote sources.
-$(local_objs): $(src)/%.o: $(LIB_DIR)/%.c
+$(local_objs): $(src)/%.o: $(LIBXUTIL_DIR)/%.c
        $(call if_changed_rule,cc_o_c)
 #----------------------------------------------------------------------------
 
-vpath %.h $(LIB_DIR)
-EXTRA_CFLAGS += -I $(LIB_DIR)
+vpath %.h $(LIBXUTIL_DIR)
+EXTRA_CFLAGS += -I $(LIBXUTIL_DIR)
 EXTRA_CFLAGS += -I $(src)
 
 endif
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/Makefile-2.4
--- a/tools/vnet/vnet-module/Makefile-2.4       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/Makefile-2.4       Fri Aug 26 10:52:53 2005
@@ -21,7 +21,7 @@
 #============================================================================
 # Vnet module makefile for 2.4 series kernels.
 
-LINUX_SERIES ?=2.4
+LINUX_SERIES =2.4
 include Makefile.ver
 
 KERNEL_MODULE := vnet_module.o
@@ -37,9 +37,9 @@
 vpath %.h $(KERNEL_SRC)/include
 INCLUDES+= -I $(KERNEL_SRC)/include
 
-vpath %.h $(LIB_DIR)
-vpath %.c $(LIB_DIR)
-INCLUDES += -I $(LIB_DIR)
+vpath %.h $(LIBXUTIL_DIR)
+vpath %.c $(LIBXUTIL_DIR)
+INCLUDES += -I $(LIBXUTIL_DIR)
 
 INCLUDES+= -I .
 
@@ -61,6 +61,7 @@
 CFLAGS += -Wno-unused-function
 CFLAGS += -Wno-unused-parameter 
 
+CFLAGS += -g
 CFLAGS += -O2
 CFLAGS += -fno-strict-aliasing 
 CFLAGS += -fno-common 
@@ -90,8 +91,8 @@
 
 .PHONY: clean
 clean:
-       @rm -f *.a *.o *.ko *~
-       @rm -f $(VNET_DEP) .*.cmd *.mod.?
-       @rm -rf .tmp_versions
+       -@$(RM) *.a *.o *.ko *~
+       -@$(RM) $(VNET_DEP) .*.cmd *.mod.?
+       -@$(RM) -r .tmp_versions
 
 -include $(VNET_DEP)
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/Makefile-2.6
--- a/tools/vnet/vnet-module/Makefile-2.6       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/Makefile-2.6       Fri Aug 26 10:52:53 2005
@@ -21,7 +21,7 @@
 #============================================================================
 # Vnet module makefile for 2.6 series kernels.
 
-LINUX_SERIES ?=2.6
+LINUX_SERIES =2.6
 include Makefile.ver
 
 KERNEL_MODULE = vnet_module.ko
@@ -38,13 +38,14 @@
 
 .PHONY: install install-module modules_install
 install install-module modules_install: module
-       install -m 0755 -d $(DESTDIR)$(KERNEL_MODULE_DIR)/xen
-       install -m 0554 $(KERNEL_MODULE) $(DESTDIR)$(KERNEL_MODULE_DIR)/xen
+       install -m 0755 -d $(DESTDIR)$(KERNEL_MODULE_DIR)
+       install -m 0554 $(KERNEL_MODULE) $(DESTDIR)$(KERNEL_MODULE_DIR)
 
 .PHONY: clean
 clean:
-       @$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
-       @rm -f *.a *.o *.ko *~ .*.d .*.cmd *.mod.?
+       -@$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
+       -@$(RM) *.a *.o *.ko *~ .*.d .*.cmd *.mod.?
+       -@$(RM) -r .tmp_versions
 
 TAGS:
        etags *.c *.h
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/Makefile.ver
--- a/tools/vnet/vnet-module/Makefile.ver       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/Makefile.ver       Fri Aug 26 10:52:53 2005
@@ -18,22 +18,11 @@
 # 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
 #============================================================================
 
-#----------------------------------------------------------------------------
-# Xeno/xen.
-
-# Root of xen tree.
-XEN_ROOT ?=../../..
-
-# Path to relativize the install. Set to /
-# to install relative to filesystem root.
-prefix ?=$(XEN_ROOT)/install/
-#----------------------------------------------------------------------------
-
 LINUX_SERIES ?=2.6
 KERNEL_MINOR ?=-xen0
 
-LINUX_VERSION ?= $(shell ( /bin/ls -ld 
$(XEN_ROOT)/linux-$(LINUX_SERIES).*-xen-sparse ) 2>/dev/null | \
-                      sed -e 's!^.*linux-\(.\+\)-xen-sparse!\1!' )
+LINUX_VERSION ?= $(shell ( /bin/ls -ld 
$(XEN_ROOT)/linux-$(LINUX_SERIES).*-xen0 ) 2>/dev/null | \
+                      sed -e 's!^.*linux-\(.\+\)-xen0!\1!' )
 
 ifeq ($(LINUX_VERSION),)
 $(error Kernel source for linux $(LINUX_SERIES) not found)
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/Makefile.vnet
--- a/tools/vnet/vnet-module/Makefile.vnet      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/Makefile.vnet      Fri Aug 26 10:52:53 2005
@@ -23,8 +23,6 @@
 else
 SRC_DIR=$(src)/
 endif
-
-LIB_DIR := $(SRC_DIR)../libxutil
 
 VNET_SRC :=
 VNET_SRC += esp.c
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/etherip.c
--- a/tools/vnet/vnet-module/etherip.c  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/etherip.c  Fri Aug 26 10:52:53 2005
@@ -42,6 +42,7 @@
 #include <vnet.h>
 #include <varp.h>
 #include <if_varp.h>
+#include <varp.h>
 #include <skb_util.h>
 
 #define MODULE_NAME "VNET"
@@ -53,22 +54,18 @@
  * The etherip protocol is used to transport Ethernet frames in IP packets.
  */
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define MAC_ETH(_skb) ((struct ethhdr *)(_skb)->mac.raw)
+/** Get the vnet label from an etherip header.
+ *
+ * @param hdr header
+ * @@param vnet (in net order)
+ */
+void etheriphdr_get_vnet(struct etheriphdr *hdr, VnetId *vnet){
+#ifdef CONFIG_ETHERIP_EXT
+    *vnet = *(VnetId*)hdr->vnet;
 #else
-#define MAC_ETH(_skb) ((_skb)->mac.ethernet)
-#endif
-
-/** Get the vnet label from an etherip header.
- *
- * @param hdr header
- * @return vnet (in host order)
- */
-int etheriphdr_get_vnet(struct etheriphdr *hdr){
-#ifdef CONFIG_ETHERIP_EXT
-    return ntohl(hdr->vnet);
-#else
-    return hdr->reserved;
+    *vnet = (VnetId){};
+    vnet->u.vnet16[7] = (unsigned short)hdr->reserved;
+    
 #endif
 }
 
@@ -76,15 +73,15 @@
  * Also sets the etherip version.
  *
  * @param hdr header
- * @param vnet vnet label (in host order)
- */
-void etheriphdr_set_vnet(struct etheriphdr *hdr, int vnet){
+ * @param vnet vnet label (in net order)
+ */
+void etheriphdr_set_vnet(struct etheriphdr *hdr, VnetId *vnet){
 #ifdef CONFIG_ETHERIP_EXT
-    hdr->version = 4;
-    hdr->vnet = htonl(vnet);
+    hdr->version = ETHERIP_VERSION;
+    *(VnetId*)hdr->vnet = *vnet;
 #else
-    hdr->version = 3;
-    hdr->reserved = vnet & 0x0fff;
+    hdr->version = ETHERIP_VERSION;
+    hdr->reserved = (vnet->u.vnet16[7] & 0x0fff);
 #endif
 }
 
@@ -119,12 +116,12 @@
     const int ip_n = sizeof(struct iphdr);
     const int eth_n = ETH_HLEN;
     int head_n = 0;
-    int vnet = tunnel->key.vnet;
+    VnetId *vnet = &tunnel->key.vnet;
     struct etheriphdr *etheriph;
     struct ethhdr *ethh;
     u32 saddr = 0;
 
-    dprintf("> skb=%p vnet=%d\n", skb, vnet);
+    //dprintf("> skb=%p vnet=%d\n", skb, vnet);
     head_n = etherip_n + ip_n + eth_n;
     err = skb_make_room(&skb, skb, head_n, 0);
     if(err) goto exit;
@@ -133,7 +130,7 @@
     //if(err) goto exit;
     
     // The original ethernet header.
-    ethh = MAC_ETH(skb);
+    ethh = eth_hdr(skb);
     //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len);
     // Null the pointer as we are pushing a new IP header.
     skb->mac.raw = NULL;
@@ -155,7 +152,7 @@
     skb->nh.iph->ttl      = 64;                        // Linux default 
time-to-live.
     skb->nh.iph->protocol = IPPROTO_ETHERIP;    // IP protocol number.
     skb->nh.iph->saddr    = saddr;             // Source address.
-    skb->nh.iph->daddr    = tunnel->key.addr;  // Destination address.
+    skb->nh.iph->daddr    = tunnel->key.addr.u.ip4.s_addr;     // Destination 
address.
     skb->nh.iph->check    = 0;
 
     // Ethernet header will be filled-in by device.
@@ -213,15 +210,18 @@
     struct etheriphdr *etheriph;
     struct ethhdr *ethhdr;
     Vnet *vinfo = NULL;
-    u32 vnet;
-
-    ethhdr = MAC_ETH(skb);
-    if(MULTICAST(skb->nh.iph->daddr) &&
-       (skb->nh.iph->daddr != varp_mcast_addr)){
+    VnetId vnet = {};
+    u32 saddr, daddr;
+    char vnetbuf[VNET_ID_BUF];
+
+    saddr = skb->nh.iph->saddr;
+    daddr = skb->nh.iph->daddr;
+    ethhdr = eth_hdr(skb);
+    if(MULTICAST(daddr) && (daddr != varp_mcast_addr)){
         // Ignore multicast packets not addressed to us.
-        dprintf("> dst=%u.%u.%u.%u varp_mcast_addr=%u.%u.%u.%u\n",
-                NIPQUAD(skb->nh.iph->daddr),
-                NIPQUAD(varp_mcast_addr));
+        dprintf("> Ignoring mcast skb: src=%u.%u.%u.%u dst=%u.%u.%u.%u"
+                " varp_mcast_addr=%u.%u.%u.%u\n",
+                NIPQUAD(saddr), NIPQUAD(daddr), NIPQUAD(varp_mcast_addr));
         goto exit;
     }
     ip_n = (skb->nh.iph->ihl << 2);
@@ -229,7 +229,8 @@
         // skb->data points at ethernet header.
         //dprintf("> len=%d\n", skb->len);
         if (!pskb_may_pull(skb, eth_n + ip_n)){
-            wprintf("> Malformed skb\n");
+            wprintf("> Malformed skb (eth+ip) src=%u.%u.%u.%u\n",
+                    NIPQUAD(saddr));
             err = -EINVAL;
             goto exit;
         }
@@ -237,18 +238,30 @@
     }
     // Assume skb->data points at etherip header.
     etheriph = (void*)skb->data;
-    if(!pskb_may_pull(skb, etherip_n)){
-        wprintf("> Malformed skb\n");
+    if(etheriph->version != ETHERIP_VERSION){
+        wprintf("> Bad etherip version=%d src=%u.%u.%u.%u\n",
+                etheriph->version,
+                NIPQUAD(saddr));
         err = -EINVAL;
         goto exit;
     }
-    vnet = etheriphdr_get_vnet(etheriph);
-    dprintf("> Rcvd skb=%p vnet=%d\n", skb, vnet);
+    if(!pskb_may_pull(skb, etherip_n)){
+        wprintf("> Malformed skb (etherip) src=%u.%u.%u.%u\n",
+                NIPQUAD(saddr));
+        err = -EINVAL;
+        goto exit;
+    }
+    etheriphdr_get_vnet(etheriph, &vnet);
+    dprintf("> Rcvd skb vnet=%s src=%u.%u.%u.%u\n",
+            VnetId_ntoa(&vnet, vnetbuf),
+            NIPQUAD(saddr));
     // If vnet is secure, context must include IPSEC ESP.
-    err = vnet_check_context(vnet, SKB_CONTEXT(skb), &vinfo);
+    err = vnet_check_context(&vnet, SKB_CONTEXT(skb), &vinfo);
     Vnet_decref(vinfo);
     if(err){
-        wprintf("> Failed security check\n");
+        wprintf("> Failed security check vnet=%s src=%u.%u.%u.%u\n",
+                VnetId_ntoa(&vnet, vnetbuf),
+                NIPQUAD(saddr));
         goto exit;
     }
     mine = 1;
@@ -258,19 +271,29 @@
     // Know source ip, vnet, vmac, so could update varp cache.
     // But if traffic comes to us over a vnetd tunnel this points the coa
     // at the vnetd rather than the endpoint. So don't do it.
-    //varp_update(htonl(vnet), MAC_ETH(skb)->h_source, skb->nh.iph->saddr);
+    //varp_update(vnet, eth_hdr(skb)->h_source, skb->nh.iph->saddr);
 
     // Assuming a standard Ethernet frame.
+    // Should check for protocol? Support ETH_P_8021Q too.
     skb->nh.raw = skb_pull(skb, ETH_HLEN);
+
+    dprintf("> Unpacked vnet=%s srcmac=" MACFMT " dstmac=" MACFMT "\n",
+            VnetId_ntoa(&vnet, vnetbuf),
+            MAC6TUPLE(eth_hdr(skb)->h_source),
+            MAC6TUPLE(eth_hdr(skb)->h_dest));
 
 #ifdef CONFIG_NETFILTER
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
     // This stops our new pkt header being clobbered by a subsequent
-    // call to nf_bridge_maybe_copy_header. Just replicate the
-    // corresponding nf_bridge_save_header.
+    // call to nf_bridge_maybe_copy_header.
+    // Code from nf_bridge_save_header() modidifed to use h_proto
+    // instead of skb->protocol.
     if(skb->nf_bridge){
+        // Hmm. Standard ethernet header is ETH_HLEN (14),
+        // VLAN header (802.1q) is VLAN_ETH_HLEN (18).
+        // Where does 16 come from?
         int header_size = 16;
-        if(MAC_ETH(skb)->h_proto == __constant_htons(ETH_P_8021Q)) {
+        if(eth_hdr(skb)->h_proto == __constant_htons(ETH_P_8021Q)) {
             header_size = 18;
         }
         memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
@@ -279,7 +302,7 @@
 #endif
     
     if(1){
-       struct ethhdr *eth = MAC_ETH(skb);
+       struct ethhdr *eth = eth_hdr(skb);
         // Devices use eth_type_trans() to set skb->pkt_type and skb->protocol.
         // Set them from contained ethhdr, or leave as received?
         // 'Ware use of hard_header_len in eth_type_trans().
@@ -310,6 +333,7 @@
         }
         dst_release(skb->dst);
         skb->dst = NULL;
+
 #ifdef CONFIG_NETFILTER
         nf_conntrack_put(skb->nfct);
         skb->nfct = NULL;
@@ -321,7 +345,7 @@
 
     //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len + ETH_HLEN);
 
-    err = vnet_skb_recv(skb, vnet, (Vmac*)MAC_ETH(skb)->h_dest);
+    err = vnet_skb_recv(skb, &vnet, (Vmac*)eth_hdr(skb)->h_dest);
   exit:
     if(mine) err = 1;
     dprintf("< skb=%p err=%d\n", skb, err);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/if_etherip.h
--- a/tools/vnet/vnet-module/if_etherip.h       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/if_etherip.h       Fri Aug 26 10:52:53 2005
@@ -18,15 +18,30 @@
  */
 #ifndef _VNET_IF_ETHERIP_H_
 #define _VNET_IF_ETHERIP_H_
-/*----------------------------------------------------------------------------*/
+
+#define CONFIG_ETHERIP_EXT
+
 #ifdef CONFIG_ETHERIP_EXT
+
+#define ETHERIP_VERSION 4
+
 struct etheriphdr {
-    __u8 version;
-    __u32 vnet;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+    __u16    reserved:12,
+             version:4;
+#elif defined (__BIG_ENDIAN_BITFIELD)
+    __u16    version:4,
+            reserved:12;
+#else
+#error  "Please fix <asm/byteorder.h>"
+#endif
+    __u8 vnet[16];
 } __attribute__ ((packed));
 
-/*----------------------------------------------------------------------------*/
 #else
+
+#define ETHERIP_VERSION 3
+
 struct etheriphdr
 {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
@@ -42,10 +57,9 @@
 };
 #endif
 
+
 #ifndef IPPROTO_ETHERIP
 #define IPPROTO_ETHERIP 97
 #endif
 
-/*----------------------------------------------------------------------------*/
-
 #endif /* ! _VNET_IF_ETHERIP_H_ */
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/if_varp.h
--- a/tools/vnet/vnet-module/if_varp.h  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/if_varp.h  Fri Aug 26 10:52:53 2005
@@ -20,6 +20,14 @@
 #ifndef _VNET_IF_VARP_H
 #define _VNET_IF_VARP_H
 
+/* Need struct in_addr, struct in6_addr. */
+#ifdef __KERNEL__
+#include <linux/in.h>
+#include <linux/in6.h>
+#else
+#include <netinet/in.h>
+#endif
+
 typedef struct Vmac {
     unsigned char mac[ETH_ALEN];
 } Vmac;
@@ -30,17 +38,35 @@
     VARP_OP_ANNOUNCE = 2,
 };
 
+typedef struct VnetId {
+    union {
+        uint8_t vnet8[16];
+        uint16_t vnet16[8];
+        uint32_t vnet32[4];
+    } u;
+} __attribute__((packed)) VnetId;
+
+typedef struct VarpAddr {
+    uint8_t family; // AF_INET or AF_INET6.
+    union {
+        uint8_t raw[16];
+        struct in_addr ip4;
+        struct in6_addr ip6;
+    } u;
+} __attribute__((packed)) VarpAddr;
+
 typedef struct VnetMsgHdr {
     uint16_t id;
     uint16_t opcode;
 } __attribute__((packed)) VnetMsgHdr;
 
 typedef struct VarpHdr {
-    VnetMsgHdr vnetmsghdr;
-    uint32_t vnet;
-    Vmac vmac;
-    uint32_t addr;
+  VnetMsgHdr hdr;
+  VnetId vnet;
+  Vmac vmac;
+  VarpAddr addr;
 } __attribute__((packed)) VarpHdr;
+
 
 /** Default address for varp/vnet broadcasts: 224.10.0.1 */
 #define VARP_MCAST_ADDR     0xe00a0001
@@ -48,6 +74,4 @@
 /** UDP port to use for varp protocol. */
 #define VARP_PORT           1798
 
-
-
-#endif  /* ! _VNET_IF_VARP_H */
+#endif /* ! _VNET_IF_VARP_H */
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/skb_util.h
--- a/tools/vnet/vnet-module/skb_util.h Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/skb_util.h Fri Aug 26 10:52:53 2005
@@ -19,7 +19,9 @@
 #ifndef _VNET_SKB_UTIL_H_
 #define _VNET_SKB_UTIL_H_
 
-struct sk_buff;
+#include <net/route.h>
+#include <linux/skbuff.h>
+
 struct scatterlist;
 
 extern int skb_make_room(struct sk_buff **pskb, struct sk_buff *skb, int 
head_n, int tail_n);
@@ -40,4 +42,53 @@
 extern void print_skb_data(char *msg, int count, struct sk_buff *skb, u8 
*data, int len);
 
 
+/* The mac.ethernet field went away in 2.6 in favour of eth_hdr().
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#else
+static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
+{
+       return (struct ethhdr *)skb->mac.raw;
+}
 #endif
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
+static inline int skb_route(struct sk_buff *skb, struct rtable **prt){
+    int err = 0;
+    struct flowi fl = {
+        .nl_u = {
+            .ip4_u = {
+                .daddr = skb->nh.iph->daddr,
+                .saddr = skb->nh.iph->saddr,
+                .tos   = skb->nh.iph->tos,
+            }
+        }
+    };
+    
+    if(skb->dev){
+        fl.oif = skb->dev->ifindex;
+    }
+    err = ip_route_output_key(prt, &fl);
+    return err;
+}
+
+#else
+
+static inline int skb_route(struct sk_buff *skb, struct rtable **prt){
+    int err = 0;
+    struct rt_key key = { };
+    key.dst = skb->nh.iph->daddr;
+    key.src = skb->nh.iph->saddr;
+    key.tos = skb->nh.iph->tos;
+    if(skb->dev){
+        key.oif = skb->dev->ifindex;
+    }
+    err = ip_route_output_key(prt, &key);
+    return err;
+}
+
+#endif
+
+#endif
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/tunnel.c
--- a/tools/vnet/vnet-module/tunnel.c   Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/tunnel.c   Fri Aug 26 10:52:53 2005
@@ -36,7 +36,7 @@
 #include "hash_table.h"
 
 #define MODULE_NAME "VNET"
-//#define DEBUG 1
+#define DEBUG 1
 #undef DEBUG
 #include "debug.h"
 
@@ -56,11 +56,9 @@
     }
 }
 
-int Tunnel_create(TunnelType *type, u32 vnet, u32 addr, Tunnel *base, Tunnel 
**val){
+int Tunnel_create(TunnelType *type, VnetId *vnet, VarpAddr *addr, Tunnel 
*base, Tunnel **val){
     int err = 0;
     Tunnel *tunnel = NULL;
-    dprintf("> type=%s vnet=%d addr=" IPFMT " base=%s\n",
-            type->name, vnet, NIPQUAD(addr), (base ? base->type->name : "ip"));
     if(!type || !type->open || !type->send || !type->close){
         err = -EINVAL;
         goto exit;
@@ -71,8 +69,8 @@
         goto exit;
     }
     atomic_set(&tunnel->refcount, 1);
-    tunnel->key.vnet = vnet;
-    tunnel->key.addr = addr;
+    tunnel->key.vnet = *vnet;
+    tunnel->key.addr = *addr;
     tunnel->type = type;
     tunnel->data = NULL;
     tunnel->send_stats = (TunnelStats){};
@@ -89,7 +87,7 @@
     return err;
 }
 
-int Tunnel_open(TunnelType *type, u32 vnet, u32 addr, Tunnel *base, Tunnel 
**tunnel){
+int Tunnel_open(TunnelType *type, VnetId *vnet, VarpAddr *addr, Tunnel *base, 
Tunnel **tunnel){
     int err = 0;
 
     dprintf(">\n");
@@ -123,15 +121,16 @@
 static inline Hashcode tunnel_table_key_hash_fn(void *k){
     TunnelKey *key = k;
     Hashcode h = 0;
-    h = hash_2ul(key->vnet, key->addr);
+    h = VnetId_hash(h, &key->vnet);
+    h = VarpAddr_hash(h, &key->addr);
     return h;
 }
 
 static int tunnel_table_key_equal_fn(void *k1, void *k2){
     TunnelKey *key1 = k1;
     TunnelKey *key2 = k2;
-    return (key1->vnet == key2->vnet)
-        && (key1->addr == key2->addr);
+    return VnetId_eq(&key1->vnet, &key2->vnet) &&
+           VarpAddr_eq(&key1->addr, &key2->addr);
 }
 
 static void tunnel_table_entry_free_fn(HashTable *table, HTEntry *entry){
@@ -165,9 +164,9 @@
  * @param addr destination address
  * @return tunnel state or NULL
  */
-Tunnel * Tunnel_lookup(u32 vnet, u32 addr){
+Tunnel * Tunnel_lookup(VnetId *vnet, VarpAddr *addr){
     Tunnel *tunnel = NULL;
-    TunnelKey key = {.vnet = vnet, .addr = addr };
+    TunnelKey key = {.vnet = *vnet, .addr = *addr };
     dprintf(">\n");
     tunnel = HashTable_get(tunnel_table, &key);
     Tunnel_incref(tunnel);
@@ -199,23 +198,16 @@
  */
 int Tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
     int err = 0;
-    int len;
     dprintf("> tunnel=%p skb=%p\n", tunnel, skb);
-    len = skb->len;
     if(tunnel){
+        int len = skb->len;
         dprintf("> type=%s type->send...\n", tunnel->type->name);
+        // Must not refer to skb after sending - might have been freed.
         err = tunnel->type->send(tunnel, skb);
-        // Must not refer to skb after sending - might have been freed.
         TunnelStats_update(&tunnel->send_stats, len, err);
     } else {
-        struct net_device *dev = NULL;
-        err = vnet_get_device(DEVICE, &dev);
-        if(err) goto exit;
-        skb->dev = dev;
         err = skb_xmit(skb);
-        dev_put(dev);
-    }
-  exit:
+    }
     dprintf("< err=%d\n", err);
     return err;
 }
@@ -225,4 +217,8 @@
 }
 
 void __exit tunnel_module_exit(void){
-}
+    if(tunnel_table){
+        HashTable_free(tunnel_table);
+        tunnel_table = NULL;
+    }
+}
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/tunnel.h
--- a/tools/vnet/vnet-module/tunnel.h   Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/tunnel.h   Fri Aug 26 10:52:53 2005
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <asm/atomic.h>
+#include <if_varp.h>
 
 struct sk_buff;
 struct Tunnel;
@@ -41,8 +42,8 @@
 } TunnelStats;
 
 typedef struct TunnelKey {
-    u32 vnet;
-    u32 addr;
+    VnetId vnet;
+    VarpAddr addr;
 } TunnelKey;
 
 typedef struct Tunnel {
@@ -87,13 +88,15 @@
 }
 
 extern int Tunnel_init(void);
-extern Tunnel * Tunnel_lookup(u32 vnet, u32 addr);
+extern Tunnel * Tunnel_lookup(struct VnetId *vnet, struct VarpAddr *addr);
 extern int Tunnel_add(Tunnel *tunnel);
 extern int Tunnel_del(Tunnel *tunnel);
 extern int Tunnel_send(Tunnel *tunnel, struct sk_buff *skb);
 
-extern int Tunnel_create(TunnelType *type, u32 vnet, u32 addr, Tunnel *base, 
Tunnel **tunnelp);
-extern int Tunnel_open(TunnelType *type, u32 vnet, u32 addr, Tunnel *base, 
Tunnel **tunnelp);
+extern int Tunnel_create(TunnelType *type, struct VnetId *vnet, struct 
VarpAddr *addr,
+                         Tunnel *base, Tunnel **tunnelp);
+extern int Tunnel_open(TunnelType *type, struct VnetId *vnet, struct VarpAddr 
*addr,
+                       Tunnel *base, Tunnel **tunnelp);
 
 extern int tunnel_module_init(void);
 extern void tunnel_module_exit(void);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/varp.c
--- a/tools/vnet/vnet-module/varp.c     Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/varp.c     Fri Aug 26 10:52:53 2005
@@ -40,26 +40,20 @@
 #include <tunnel.h>
 #include <vnet.h>
 #include <vif.h>
+#include <if_varp.h>
 #include <varp.h>
-#include <if_varp.h>
+#include <vnet.h>
 
 #include "allocate.h"
 #include "hash_table.h"
 #include "sys_net.h"
 #include "sys_string.h"
+#include "skb_util.h"
 
 #define MODULE_NAME "VARP"
-//#define DEBUG 1
+#define DEBUG 1
 #undef DEBUG
 #include "debug.h"
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-// The 'ethernet' field in the skb->mac union went away.
-#define MAC_ETH(_skb) ((struct ethhdr *)(_skb)->mac.raw)
-#else
-#define MAC_ETH(_skb) ((_skb)->mac.ethernet)
-#endif
 
 /** @file VARP: Virtual ARP.
  *
@@ -121,8 +115,8 @@
 
 /** Key for varp entries. */
 typedef struct VarpKey {
-    /** Vnet id (host order). */
-    u32 vnet;
+    /** Vnet id (network order). */
+    VnetId vnet;
     /** Virtual MAC address. */
     Vmac vmac;
 } VarpKey;
@@ -132,7 +126,7 @@
     /** Key for the entry. */
     VarpKey key;
     /** Care-of address for the key. */
-    u32 addr;
+    VarpAddr addr;
     /** Last-updated timestamp. */
     unsigned long timestamp;
     /** State. */
@@ -152,8 +146,6 @@
     struct sk_buff_head queue;
     /** Maximum size of the queue. */
     int queue_max;
-
-    int locks;
 } VarpEntry;
 
 /** The varp cache. Varp entries indexed by VarpKey. */
@@ -181,14 +173,10 @@
 /** Multicast address (network order). */
 u32 varp_mcast_addr = 0;
 
-/** Unicast address (network order). */
-u32 varp_ucast_addr = 0;
-
 /** UDP port (network order). */
 u16 varp_port = 0;
 
-/** Network device to use. */
-char *varp_device = DEVICE;
+char *varp_device = "xen-br0";
 
 #define VarpTable_read_lock(z, flags)    do{ (flags) = 0; down(&(z)->lock); } 
while(0)
 #define VarpTable_read_unlock(z, flags)  do{ (flags) = 0; up(&(z)->lock); } 
while(0)
@@ -199,7 +187,10 @@
 #define VarpEntry_unlock(ventry, flags)  
write_unlock_irqrestore(&(ventry)->lock, (flags))
 
 void VarpTable_sweep(VarpTable *z, int all);
+void VarpTable_flush(VarpTable *z);
 void VarpTable_print(VarpTable *z);
+
+#include "./varp_util.c"
 
 /** Print the varp cache (if debug on).
  */
@@ -209,14 +200,53 @@
 #endif
 } 
 
+/** Flush the varp cache.
+ */
+void varp_flush(void){
+    VarpTable_flush(varp_table);
+}
+
+static int device_ucast_addr(const char *device, uint32_t *addr)
+{
+    int err;
+    struct net_device *dev = NULL;
+
+    err = vnet_get_device(device, &dev);
+    if(err) goto exit;
+    err = vnet_get_device_address(dev, addr);
+  exit:
+    if(err){
+        *addr = 0;
+    }
+    return err;
+}
+
+/** Get the unicast address of the varp device.
+ */
+int varp_ucast_addr(uint32_t *addr)
+{
+    int err = -ENODEV;
+    const char *devices[] = { varp_device, "eth0", "eth1", "eth2", NULL };
+    const char **p;
+    for(p = devices; err && *p; p++){
+        err = device_ucast_addr(*p, addr);
+    }
+    return err;
+}
+
 /** Print varp info and the varp cache.
  */
 void varp_print(void){
+    uint32_t addr = 0;
+    varp_ucast_addr(&addr);
+
     printk(KERN_INFO "=== VARP 
===============================================================\n");
     printk(KERN_INFO "varp_device     %s\n", varp_device);
     printk(KERN_INFO "varp_mcast_addr " IPFMT "\n", NIPQUAD(varp_mcast_addr));
-    printk(KERN_INFO "varp_ucast_addr " IPFMT "\n", NIPQUAD(varp_ucast_addr));
+    printk(KERN_INFO "varp_ucast_addr " IPFMT "\n", NIPQUAD(addr));
     printk(KERN_INFO "varp_port       %d\n", ntohs(varp_port));
+    vnet_print();
+    vif_print();
     VarpTable_print(varp_table);
     printk(KERN_INFO 
"========================================================================\n");
 }
@@ -246,18 +276,43 @@
     int err = 0;
     struct in_device *in_dev;
 
-    //printk("%s>\n", __FUNCTION__);
     in_dev = in_dev_get(dev);
     if(!in_dev){
-        err = -EIO;
+        err = -ENODEV;
         goto exit;
     }
     *addr = in_dev->ifa_list->ifa_address;
     in_dev_put(in_dev);
   exit:
-    //printk("%s< err=%d\n", __FUNCTION__, err);
-    return err;
-}
+    return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
+static inline int addr_route(u32 daddr, struct rtable **prt){
+    int err = 0;
+    struct flowi fl = {
+        .nl_u = {
+            .ip4_u = {
+                .daddr = daddr,
+            }
+        }
+    };
+    
+    err = ip_route_output_key(prt, &fl);
+    return err;
+}
+
+#else
+
+static inline int addr_route(u32 daddr, struct rtable **prt){
+    int err = 0;
+    struct rt_key key = { .dst = daddr };
+    err = ip_route_output_key(prt, &key);
+    return err;
+}
+
+#endif
 
 #ifndef LL_RESERVED_SPACE
 #define HH_DATA_MOD    16
@@ -270,12 +325,12 @@
  * @param opcode varp opcode (host order)
  * @param dev device (may be null)
  * @param skb skb being replied to (may be null)
- * @param vnet vnet id (in host order)
+ * @param vnet vnet id (in network order)
  * @param vmac vmac (in network order)
  * @return 0 on success, error code otherwise
  */
 int varp_send(u16 opcode, struct net_device *dev, struct sk_buff *skbin,
-              u32 vnet, Vmac *vmac){
+              VnetId *vnet, Vmac *vmac){
     int err = 0;
     int link_n = 0;
     int ip_n = sizeof(struct iphdr);
@@ -285,45 +340,53 @@
     struct in_device *in_dev = NULL;
     VarpHdr *varph = NULL;
     u8 macbuf[6] = {};
-    u8 *smac, *dmac;
+    u8 *smac, *dmac = macbuf;
     u32 saddr, daddr;
     u16 sport, dport;
-
-    dmac = macbuf;
-    dprintf("> opcode=%d vnet=%d vmac=" MACFMT "\n",
-            opcode, ntohl(vnet), MAC6TUPLE(vmac->mac));
-    if(!dev){
-        //todo: should use routing for daddr to get device.
-        err = vnet_get_device(varp_device, &dev);
-        if(err) goto exit;
-    }
-    link_n = LL_RESERVED_SPACE(dev);
-    in_dev = in_dev_get(dev);
-    if(!in_dev) goto exit;
-
-    smac = dev->dev_addr;
-    saddr = in_dev->ifa_list->ifa_address;
-
+#if defined(DEBUG)
+    char vnetbuf[VNET_ID_BUF];
+#endif
+
+    dprintf("> opcode=%d vnet= %s vmac=" MACFMT "\n",
+            opcode, VnetId_ntoa(vnet, vnetbuf), MAC6TUPLE(vmac->mac));
+
+    dport = varp_port;
     if(skbin){
-        dmac = MAC_ETH(skbin)->h_source;
+        daddr = skbin->nh.iph->saddr;
+        dmac = eth_hdr(skbin)->h_source;
         sport = skbin->h.uh->dest;
-        daddr = skbin->nh.iph->saddr;
-        //dport = skbin->h.uh->source;
-        dport = varp_port;
     } else {
-        if(!in_dev) goto exit;
         if(MULTICAST(varp_mcast_addr)){
             daddr = varp_mcast_addr;
             ip_eth_mc_map(daddr, dmac);
         } else {
-            daddr = in_dev->ifa_list->ifa_broadcast;
-            dmac = dev->broadcast;
+            daddr = INADDR_BROADCAST;
         }
         sport = varp_port;
-        dport = varp_port;
+    }
+
+    if(!dev){
+        struct rtable *rt = NULL;
+        err = addr_route(daddr, &rt);
+        if(err) goto exit;
+        dev = rt->u.dst.dev;
+    }
+
+    in_dev = in_dev_get(dev);
+    if(!in_dev){
+        err = -ENODEV;
+        goto exit;
+    }
+    link_n = LL_RESERVED_SPACE(dev);
+    saddr = in_dev->ifa_list->ifa_address;
+    smac = dev->dev_addr;
+    if(daddr == INADDR_BROADCAST){
+        daddr = in_dev->ifa_list->ifa_broadcast;
+        dmac = dev->broadcast;
     }
     in_dev_put(in_dev);
 
+    dprintf("> dev=%s\n", dev->name);
     dprintf("> smac=" MACFMT " dmac=" MACFMT "\n", MAC6TUPLE(smac), 
MAC6TUPLE(dmac));
     dprintf("> saddr=" IPFMT " daddr=" IPFMT "\n", NIPQUAD(saddr), 
NIPQUAD(daddr));
     dprintf("> sport=%u dport=%u\n", ntohs(sport), ntohs(dport));
@@ -368,11 +431,12 @@
     // Varp header.
     varph = (void*)skb_put(skbout, varp_n);
     *varph = (VarpHdr){};
-    varph->vnetmsghdr.id     = htons(VARP_ID);
-    varph->vnetmsghdr.opcode = htons(opcode);
-    varph->vnet              = htonl(vnet);
+    varph->hdr.id            = htons(VARP_ID);
+    varph->hdr.opcode        = htons(opcode);
+    varph->vnet              = *vnet;
     varph->vmac              = *vmac;
-    varph->addr              = saddr;
+    varph->addr.family       = AF_INET;
+    varph->addr.u.ip4.s_addr = saddr;
 
     err = skb_xmit(skbout);
 
@@ -385,16 +449,13 @@
 /** Send a varp request for the vnet and destination mac of a packet.
  *
  * @param skb packet
- * @param vnet vnet (in host order)
+ * @param vnet vnet (in network order)
  * @return 0 on success, error code otherwise
  */
-int varp_solicit(struct sk_buff *skb, int vnet){
-    int err = 0;
-    dprintf("> skb=%p\n", skb);
-    varp_dprint();
+int varp_solicit(struct sk_buff *skb, VnetId *vnet){
+    int err = 0;
     err = varp_send(VARP_OP_REQUEST, NULL, NULL,
-                    vnet, (Vmac*)MAC_ETH(skb)->h_dest);
-    dprintf("< err=%d\n", err);
+                    vnet, (Vmac*)eth_hdr(skb)->h_dest);
     return err;
 }
 
@@ -430,22 +491,26 @@
  */
 void VarpEntry_print(VarpEntry *ventry){
     if(ventry){
-        char *c, *d;
+        char *state, *flags;
+        char vnetbuf[VNET_ID_BUF];
+        char addrbuf[VARP_ADDR_BUF];
+
         switch(ventry->state){
-        case VARP_STATE_INCOMPLETE: c = "INC"; break;
-        case VARP_STATE_REACHABLE:  c = "RCH"; break;
-        case VARP_STATE_FAILED:     c = "FLD"; break;
-        default:                    c = "UNK"; break;
+        case VARP_STATE_INCOMPLETE: state = "INC"; break;
+        case VARP_STATE_REACHABLE:  state = "RCH"; break;
+        case VARP_STATE_FAILED:     state = "FLD"; break;
+        default:                    state = "UNK"; break;
         }
-        d = (VarpEntry_get_flags(ventry, VARP_FLAG_PROBING) ? "P" : " ");
-
-        printk(KERN_INFO "VENTRY(%p ref=%1d %s %s vnet=%d vmac=" MACFMT " 
addr=" IPFMT " q=%d t=%lu)\n",
+        flags = (VarpEntry_get_flags(ventry, VARP_FLAG_PROBING) ? "P" : " ");
+
+        printk(KERN_INFO "VENTRY(%p ref=%1d %s %s vnet=%s vmac=" MACFMT
+               " addr=%s q=%3d t=%lu)\n",
                ventry,
                atomic_read(&ventry->refcount),
-               c, d,
-               ventry->key.vnet,
+               state, flags,
+               VnetId_ntoa(&ventry->key.vnet, vnetbuf),
                MAC6TUPLE(ventry->key.vmac.mac),
-               NIPQUAD(ventry->addr),
+               VarpAddr_ntoa(&ventry->addr, addrbuf),
                skb_queue_len(&ventry->queue),
                ventry->timestamp);
     } else {
@@ -469,7 +534,6 @@
 void VarpEntry_incref(VarpEntry *z){
     if(!z) return;
     atomic_inc(&z->refcount);
-    //dprintf("> "); VarpEntry_print(z);
 }
 
 /** Decrement reference count, freeing if zero.
@@ -478,9 +542,7 @@
  */
 void VarpEntry_decref(VarpEntry *z){
     if(!z) return;
-    //dprintf("> "); VarpEntry_print(z);
     if(atomic_dec_and_test(&z->refcount)){
-        //dprintf("> freeing %p...\n", z);
         VarpEntry_free(z);
     }
 }
@@ -499,7 +561,7 @@
 
 /** Schedule the varp entry timer.
  * Must increment the reference count before doing
- * this the first time, so the ventry won' be freed
+ * this the first time, so the ventry won't be freed
  * before the timer goes off.
  *
  * @param ventry varp entry
@@ -538,7 +600,7 @@
                 atomic_inc(&ventry->probes);
                 VarpEntry_unlock(ventry, flags);
                 locked = 0;
-                varp_solicit(skb, ventry->key.vnet);
+                varp_solicit(skb, &ventry->key.vnet);
             } else {
                 dprintf("> empty queue.\n");
             }
@@ -568,7 +630,7 @@
  * @param vmac virtual MAC address (copied)
  * @return ventry or null
  */
-VarpEntry * VarpEntry_new(u32 vnet, Vmac *vmac){
+VarpEntry * VarpEntry_new(VnetId *vnet, Vmac *vmac){
     VarpEntry *z = ALLOCATE(VarpEntry);
     if(z){
         unsigned long now = jiffies;
@@ -584,7 +646,7 @@
         z->timestamp = now;
         z->error = varp_error_fn;
 
-        z->key.vnet = vnet;
+        z->key.vnet = *vnet;
         z->key.vmac = *vmac;
     }
     return z;
@@ -598,15 +660,9 @@
  */
 Hashcode varp_key_hash_fn(void *k){
     VarpKey *key = k;
-    Hashcode h;
-    h = hash_2ul(key->vnet,
-                 (key->vmac.mac[0] << 24) |
-                 (key->vmac.mac[1] << 16) |
-                 (key->vmac.mac[2] <<  8) |
-                 (key->vmac.mac[3]      ));
-    h = hash_hul(h, 
-                 (key->vmac.mac[4] <<   8) |
-                 (key->vmac.mac[5]       ));
+    Hashcode h = 0;
+    h = VnetId_hash(h, &key->vnet);
+    h = Vmac_hash(h, &key->vmac);
     return h;
 }
 
@@ -620,8 +676,8 @@
 int varp_key_equal_fn(void *k1, void *k2){
     VarpKey *key1 = k1;
     VarpKey *key2 = k2;
-    return (key1->vnet == key2->vnet)
-        && (memcmp(key1->vmac.mac, key2->vmac.mac, ETH_ALEN) == 0);
+    return (VnetId_eq(&key1->vnet, &key2->vnet) &&
+            Vmac_eq(&key1->vmac, &key2->vmac));
 }
 
 /** Free an entry in the varp cache.
@@ -670,12 +726,10 @@
  */
 static void varp_table_timer_fn(unsigned long arg){
     VarpTable *z = (VarpTable *)arg;
-    //dprintf("> z=%p\n", z);
     if(z){
         VarpTable_sweep(z, 0);
         VarpTable_schedule(z);
     }
-    //dprintf("<\n");
 }
 
 /** Print a varp table.
@@ -687,7 +741,6 @@
     VarpEntry *ventry;
     unsigned long flags, vflags;
 
-    //dprintf(">\n");
     VarpTable_read_lock(z, flags);
     HashTable_for_each(entry, varp_table->table){
         ventry = entry->value;
@@ -696,7 +749,6 @@
         VarpEntry_unlock(ventry, vflags);
     }
     VarpTable_read_unlock(z, flags);
-    //dprintf("<\n");
 }
 
 /** Create a varp table.
@@ -735,7 +787,7 @@
  * @param vmac virtual MAC address (copied)
  * @return new entry or null
  */
-VarpEntry * VarpTable_add(VarpTable *z, u32 vnet, Vmac *vmac){
+VarpEntry * VarpTable_add(VarpTable *z, VnetId *vnet, Vmac *vmac){
     int err = -ENOMEM;
     VarpEntry *ventry;
     HTEntry *entry;
@@ -743,7 +795,6 @@
 
     ventry = VarpEntry_new(vnet, vmac);
     if(!ventry) goto exit;
-    //dprintf("> "); VarpEntry_print(ventry);
     VarpTable_write_lock(z, flags);
     entry = HashTable_add(z->table, ventry, ventry);
     VarpTable_write_unlock(z, flags);
@@ -775,19 +826,20 @@
  * @param vmac virtual MAC addres
  * @return entry found or null
  */
-VarpEntry * VarpTable_lookup(VarpTable *z, u32 vnet, Vmac *vmac){
+VarpEntry * VarpTable_lookup(VarpTable *z, VnetId *vnet, Vmac *vmac){
     unsigned long flags;
-    VarpKey key = { .vnet = vnet, .vmac = *vmac };
+    VarpKey key = { .vnet = *vnet, .vmac = *vmac };
     VarpEntry *ventry;
     VarpTable_read_lock(z, flags);
     ventry = HashTable_get(z->table, &key);
+    if(ventry) VarpEntry_incref(ventry);
     VarpTable_read_unlock(z, flags);
-    if(ventry) VarpEntry_incref(ventry);
     return ventry;
 }
 
 /** Handle output for a reachable ventry.
  * Send the skb using the tunnel to the care-of address.
+ * Assumes the ventry lock is held.
  *
  * @param ventry varp entry
  * @param skb skb to send
@@ -796,12 +848,12 @@
 int VarpEntry_send(VarpEntry *ventry, struct sk_buff *skb){
     int err = 0;
     unsigned long flags = 0;
-    u32 addr;
+    VarpAddr addr;
 
     dprintf("> skb=%p\n", skb);
     addr = ventry->addr;
     VarpEntry_unlock(ventry, flags);
-    err = vnet_tunnel_send(ventry->key.vnet, addr, skb);
+    err = vnet_tunnel_send(&ventry->key.vnet, &addr, skb);
     VarpEntry_lock(ventry, flags);
     dprintf("< err=%d\n", err);
     return err;
@@ -811,6 +863,7 @@
  * If the entry is still incomplete, queue the skb, otherwise
  * send it. If the queue is full, dequeue and free an old skb to
  * make room for the new one.
+ * Assumes the ventry lock is held.
  *
  * @param ventry varp entry
  * @param skb skb to send
@@ -820,7 +873,7 @@
     int err = 0;
     unsigned long flags = 0;
 
-    dprintf("> skb=%p\n", skb); //VarpEntry_print(ventry);
+    dprintf("> skb=%p\n", skb);
     ventry->state = VARP_STATE_INCOMPLETE;
     atomic_set(&ventry->probes, 1);
     if(!VarpEntry_get_flags(ventry, VARP_FLAG_PROBING)){
@@ -829,7 +882,7 @@
         VarpEntry_schedule(ventry);
     }
     VarpEntry_unlock(ventry, flags);
-    varp_solicit(skb, ventry->key.vnet);
+    varp_solicit(skb, &ventry->key.vnet);
     VarpEntry_lock(ventry, flags);
 
     if(ventry->state == VARP_STATE_INCOMPLETE){
@@ -837,7 +890,7 @@
             struct sk_buff *oldskb;
             oldskb = ventry->queue.next;
             __skb_unlink(oldskb, &ventry->queue);
-            dprintf("> purging skb=%p\n", oldskb);
+            dprintf("> dropping skb=%p\n", oldskb);
             kfree_skb(oldskb);
         }
         __skb_queue_tail(&ventry->queue, skb);
@@ -893,33 +946,39 @@
  * @param state state
  * @return 0 on success, error code otherwise
  */
-int VarpEntry_update(VarpEntry *ventry, u32 addr, int state){
+int VarpEntry_update(VarpEntry *ventry, VarpAddr *addr, int state){
     int err = 0;
     unsigned long now = jiffies;
     unsigned long flags;
 
     dprintf("> addr=" IPFMT " state=%d\n", NIPQUAD(addr), state);
-    //VarpEntry_print(ventry);
     VarpEntry_lock(ventry, flags);
     if(VarpEntry_get_flags(ventry, VARP_FLAG_PERMANENT)) goto exit;
-    ventry->addr = addr;
+    ventry->addr = *addr;
     ventry->timestamp = now;
     ventry->state = state;
     VarpEntry_process_queue(ventry);
   exit:
-    //dprintf("> "); VarpEntry_print(ventry);
     VarpEntry_unlock(ventry, flags);
     dprintf("< err=%d\n", err);
     return err;
 }
     
-int VarpTable_update(VarpTable *z, int vnet, Vmac *vmac, u32 addr,
+int VarpTable_update(VarpTable *z, VnetId *vnet, Vmac *vmac, VarpAddr *addr,
                      int state, int force){
     int err = 0;
     VarpEntry *ventry;
+#ifdef DEBUG
+    char vnetbuf[VNET_ID_BUF];
+    char addrbuf[VARP_ADDR_BUF];
+#endif
     
-    dprintf("> vnet=%d mac=" MACFMT " addr=" IPFMT " state=%d force=%d\n",
-            vnet, MAC6TUPLE(vmac->mac), NIPQUAD(addr), state, force);
+    dprintf("> vnet=%s mac=" MACFMT " addr=%s state=%d force=%d\n",
+            VnetId_ntoa(vnet, vnetbuf),
+            MAC6TUPLE(vmac->mac),
+            VarpAddr_ntoa(addr, addrbuf),
+            state,
+            force);
     ventry = VarpTable_lookup(z, vnet, vmac);
     if(force && !ventry){
         dprintf("> No entry, adding\n");
@@ -945,10 +1004,10 @@
  * @return 0 on success, -ENOENT if no entry found
  */
 int VarpTable_update_entry(VarpTable *z, VarpHdr *varph, int state){
-    return VarpTable_update(z, ntohl(varph->vnet), &varph->vmac, varph->addr, 
state, 0);
-}
-
-int varp_update(int vnet, unsigned char *vmac, u32 addr){
+    return VarpTable_update(z, &varph->vnet, &varph->vmac, &varph->addr, 
state, 0);
+}
+
+int varp_update(VnetId *vnet, unsigned char *vmac, VarpAddr *addr){
     if(!varp_table){
         return -ENOSYS;
     }
@@ -971,7 +1030,6 @@
     unsigned long old = now - VARP_ENTRY_TTL;
     unsigned long flags, vflags;
 
-    //dprintf(">\n");
     VarpTable_read_lock(z, flags);
     HashTable_for_each(entry, varp_table->table){
         ventry = entry->value;
@@ -984,7 +1042,36 @@
         VarpEntry_unlock(ventry, vflags);
     }
     VarpTable_read_unlock(z, flags);
-    //dprintf("<\n");
+}
+
+/** Flush the varp table.
+ * Remove old unreachable varp entries with empty queues.
+ * Permanent entries are not removed.
+ *
+ * @param z table
+ */
+void VarpTable_flush(VarpTable *z){
+    HashTable_for_decl(entry);
+    VarpEntry *ventry;
+    unsigned long now = jiffies;
+    unsigned long old = now - VARP_ENTRY_TTL;
+    unsigned long flags, vflags;
+    int flush;
+
+    VarpTable_write_lock(z, flags);
+    HashTable_for_each(entry, varp_table->table){
+        ventry = entry->value;
+        VarpEntry_lock(ventry, vflags);
+        flush = (!VarpEntry_get_flags(ventry, VARP_FLAG_PERMANENT) &&
+                 (ventry->timestamp < old) &&
+                 (ventry->state != VARP_STATE_REACHABLE) &&
+                 (skb_queue_len(&ventry->queue) == 0));
+        VarpEntry_unlock(ventry, vflags);
+        if(flush){
+            VarpTable_remove(z, ventry);
+        }
+    }
+    VarpTable_write_unlock(z, flags);
 }
 
 /** Handle a varp request. Look for a vif with the requested 
@@ -997,14 +1084,13 @@
  */
 int varp_handle_request(struct sk_buff *skb, VarpHdr *varph){
     int err = -ENOENT;
-    u32 vnet;
+    VnetId *vnet;
     Vmac *vmac;
     Vif *vif = NULL;
 
     dprintf(">\n");
-    vnet = ntohl(varph->vnet);
+    vnet = &varph->vnet;
     vmac = &varph->vmac;
-    dprintf("> vnet=%d vmac=" MACFMT "\n", vnet, MAC6TUPLE(vmac->mac));
     if(vif_lookup(vnet, vmac, &vif)) goto exit;
     varp_send(VARP_OP_ANNOUNCE, skb->dev, skb, vnet, vmac);
     vif_decref(vif);
@@ -1026,7 +1112,7 @@
         err = -ENOSYS;
         goto exit;
     }
-    err = varp_send(VARP_OP_ANNOUNCE, dev, NULL, vif->vnet, &vif->vmac);
+    err = varp_send(VARP_OP_ANNOUNCE, dev, NULL, &vif->vnet, &vif->vmac);
   exit:
     dprintf("< err=%d\n", err);
     return err;
@@ -1067,7 +1153,7 @@
        (skb->nh.iph->daddr != varp_mcast_addr)){
         // Ignore multicast packets not addressed to us.
         err = 0;
-        dprintf("> daddr=" IPFMT " mcaddr=" IPFMT "\n",
+        dprintf("> Ignoring daddr=" IPFMT " mcaddr=" IPFMT "\n",
                 NIPQUAD(skb->nh.iph->daddr), NIPQUAD(varp_mcast_addr));
         goto exit;
     }
@@ -1076,23 +1162,29 @@
         goto exit;
     }
     mine = 1;
-    if(varph->vnetmsghdr.id != htons(VARP_ID)){
+    if(varph->hdr.id != htons(VARP_ID)){
         // It's not varp at all - ignore it.
-        wprintf("> Unknown id: %d \n", ntohs(varph->vnetmsghdr.id));
+        wprintf("> Invalid varp id: %d, expected %d \n",
+                ntohs(varph->hdr.id),
+                VARP_ID);
         goto exit;
     }
-    if(1){
+#ifdef DEBUG
+    {
+        char vnetbuf[VNET_ID_BUF];
+        char addrbuf[VARP_ADDR_BUF];
         dprintf("> saddr=" IPFMT " daddr=" IPFMT "\n",
                 NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr));
         dprintf("> sport=%u dport=%u\n", ntohs(skb->h.uh->source), 
ntohs(skb->h.uh->dest));
-        dprintf("> opcode=%d vnet=%u vmac=" MACFMT " addr=" IPFMT "\n",
-                ntohs(varph->vnetmsghdr.opcode),
-                ntohl(varph->vnet),
+        dprintf("> opcode=%d vnet=%s vmac=" MACFMT " addr=%s\n",
+                ntohs(varph->hdr.opcode),
+                VnetId_ntoa(&varph->vnet, vnetbuf),
                 MAC6TUPLE(varph->vmac.mac),
-                NIPQUAD(varph->addr));
+                VarpAddr_ntoa(&varph->addr, addrbuf));
         varp_dprint();
     }
-    switch(ntohs(varph->vnetmsghdr.opcode)){
+#endif
+    switch(ntohs(varph->hdr.opcode)){
     case VARP_OP_REQUEST:
         err = varp_handle_request(skb, varph);
         break;
@@ -1100,8 +1192,8 @@
         err = varp_handle_announce(skb, varph);
         break;
     default:
-        wprintf("> Unknown opcode: %d \n", ntohs(varph->vnetmsghdr.opcode));
-       break;
+        wprintf("> Unknown opcode: %d \n", ntohs(varph->hdr.opcode));
+        break;
     }
   exit:
     if(mine) err = 1;
@@ -1112,30 +1204,32 @@
 /** Send an outgoing packet on the appropriate vnet tunnel.
  *
  * @param skb outgoing message
- * @param vnet vnet (host order)
+ * @param vnet vnet (network order)
  * @return 0 on success, error code otherwise
  */
-int varp_output(struct sk_buff *skb, u32 vnet){
+int varp_output(struct sk_buff *skb, VnetId *vnet){
     int err = 0;
     unsigned char *mac = NULL;
     Vmac *vmac = NULL;
     VarpEntry *ventry = NULL;
 
-    dprintf("> skb=%p vnet=%u\n", skb, vnet);
+    dprintf(">\n");
     if(!varp_table){
         err = -ENOSYS;
         goto exit;
     }
-    dprintf("> skb.mac=%p\n", skb->mac.raw);
     if(!skb->mac.raw){
         wprintf("> No ethhdr in skb!\n");
         err = -EINVAL;
         goto exit;
     }
-    mac = MAC_ETH(skb)->h_dest;
+    mac = eth_hdr(skb)->h_dest;
     vmac = (Vmac*)mac;
     if(mac_is_multicast(mac)){
-        err = vnet_tunnel_send(vnet, varp_mcast_addr, skb);
+        VarpAddr addr = {};
+        addr.family = AF_INET;
+        addr.u.ip4.s_addr = varp_mcast_addr;
+        err = vnet_tunnel_send(vnet, &addr, skb);
     } else {
         ventry = VarpTable_lookup(varp_table, vnet, vmac);
         if(!ventry){
@@ -1165,7 +1259,7 @@
     int err = 0;
     varp_close();
     varp_mcast_addr = addr;
-    err = varp_open(varp_mcast_addr, varp_ucast_addr, varp_port);
+    err = varp_open(varp_mcast_addr, varp_port);
     return err;
 }
 
@@ -1191,7 +1285,6 @@
  */
 int varp_init(void){
     int err = 0;
-    struct net_device *dev = NULL;
     
     dprintf(">\n");
     varp_table = VarpTable_new();
@@ -1200,18 +1293,10 @@
         goto exit;
     }
     varp_init_mcast_addr(varp_mcaddr);
-    err = vnet_get_device(varp_device, &dev);
-    dprintf("> vnet_get_device(%s)=%d\n", varp_device, err);
-    if(err) goto exit;
-    err = vnet_get_device_address(dev, &varp_ucast_addr);
-    dprintf("> vnet_get_device_address()=%d\n", err);
-    if(err) goto exit;
     varp_port = htons(VARP_PORT);
 
-    err = varp_open(varp_mcast_addr, varp_ucast_addr, varp_port);
-    dprintf("> varp_open()=%d\n", err);
+    err = varp_open(varp_mcast_addr, varp_port);
   exit:
-    if(dev) dev_put(dev);
     dprintf("< err=%d\n", err);
     return err;
 }
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/varp.h
--- a/tools/vnet/vnet-module/varp.h     Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/varp.h     Fri Aug 26 10:52:53 2005
@@ -19,6 +19,10 @@
 
 #ifndef _VNET_VARP_H
 #define _VNET_VARP_H
+#include "hash_table.h"
+#include "if_varp.h"
+#include "varp_util.h"
+
 
 #define CONFIG_VARP_GRATUITOUS 1
 
@@ -26,29 +30,26 @@
 struct sk_buff;
 struct Vif;
 
-#define DEVICE "xen-br0"
-
 extern int vnet_get_device(const char *name, struct net_device **dev);
 extern int vnet_get_device_address(struct net_device *dev, u32 *addr);
 
 extern int varp_handle_message(struct sk_buff *skb);
-extern int varp_output(struct sk_buff *skb, u32 vnet);
-extern int varp_update(int vnet, unsigned char *vmac, u32 addr);
+extern int varp_output(struct sk_buff *skb, struct VnetId *vnet);
+extern int varp_update(struct VnetId *vnet, unsigned char *vmac, struct 
VarpAddr *addr);
 
 extern int varp_init(void);
 extern void varp_exit(void);
 
-extern int varp_open(u32 mcaddr, u32 addr, u16 port);
+extern int varp_open(u32 mcaddr, u16 port);
 extern void varp_close(void);
 extern int varp_set_mcast_addr(u32 addr);
 
 extern void varp_print(void);
+extern void varp_flush(void);
 
 extern int varp_announce_vif(struct net_device *dev, struct Vif *vif);
-//extern int varp_announce_vifs(struct net_device *dev, struct task_struct 
*domain);
 
 extern u32 varp_mcast_addr;
-
 
 /* MAC broadcast addr is ff-ff-ff-ff-ff-ff (all 1's).
  * MAC multicast addr has low bit 1, i.e. 01-00-00-00-00-00.
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/varp_socket.c
--- a/tools/vnet/vnet-module/varp_socket.c      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/varp_socket.c      Fri Aug 26 10:52:53 2005
@@ -177,7 +177,7 @@
 
 
/*============================================================================*/
 /** Socket flags. */
-enum {
+enum VsockFlag {
     VSOCK_REUSE     =  1,
     VSOCK_BIND      =  2,
     VSOCK_CONNECT   =  4,
@@ -256,28 +256,13 @@
  */
 int setsock_multicast(int sock, uint32_t saddr){
     int err = 0;
-    struct net_device *dev = NULL;
-    u32 addr = 0;
     struct ip_mreqn mreq = {};
     int mloop = 0;
 
-    err = vnet_get_device(DEVICE, &dev);
-    if(err){
-        eprintf("> error getting device: %d %d\n", err, errno);
-        goto exit;
-    }
-    err = vnet_get_device_address(dev, &addr);
-    if(err){
-        eprintf("> error getting device address: %d %d\n", err, errno);
-        goto exit;
-    }
     // See 'man 7 ip' for these options.
     mreq.imr_multiaddr.s_addr = saddr;       // IP multicast address.
-    //mreq.imr_address.s_addr   = addr;        // Interface IP address.
     mreq.imr_address.s_addr   = INADDR_ANY;  // Interface IP address.
     mreq.imr_ifindex = 0;                    // Interface index (0 means any).
-    dprintf("> saddr=%u.%u.%u.%u addr=%u.%u.%u.%u ifindex=%d\n",
-            NIPQUAD(saddr), NIPQUAD(addr), mreq.imr_ifindex);
     err = setsockopt(sock, SOL_IP, IP_MULTICAST_LOOP, &mloop, sizeof(mloop));
     if(err < 0){
         eprintf("> setsockopt IP_MULTICAST_LOOP: %d %d\n", err, errno);
@@ -305,7 +290,7 @@
 }
 
 /** Create a socket.
- * The flags can include VSOCK_REUSE, VSOCK_BROADCAST, VSOCK_CONNECT.
+ * The flags can include values from enum VsockFlag.
  *
  * @param socktype socket type
  * @param saddr address
@@ -368,19 +353,15 @@
 /** Open the varp multicast socket.
  *
  * @param mcaddr multicast address 
- * @param saddr address 
  * @param port port
  * @param val return parameter for the socket
  * @return 0 on success, error code otherwise
  */
-int varp_mcast_open(uint32_t mcaddr, uint32_t saddr, uint16_t port, int *val){
+int varp_mcast_open(uint32_t mcaddr, uint16_t port, int *val){
     int err = 0;
     int flags = VSOCK_REUSE;
     int multicast = MULTICAST(mcaddr);
     int sock = 0;
-    struct sockaddr_in addr_in;
-    struct sockaddr *addr = (struct sockaddr *)&addr_in;
-    int addr_n = sizeof(addr_in);
     
     dprintf(">\n");
     flags |= VSOCK_MULTICAST;
@@ -392,23 +373,6 @@
         err = setsock_multicast_ttl(sock, 1);
         if(err < 0) goto exit;
     }
-    if(0){
-        addr_in.sin_family      = AF_INET;
-        addr_in.sin_addr.s_addr = saddr;
-        addr_in.sin_port        = port;
-        err = bind(sock, addr, addr_n);
-        if(err < 0){
-            eprintf("> bind: %d %d\n", err, errno);
-            goto exit;
-        }
-    }
-    if(0){
-        struct sockaddr_in self = {};
-        int self_n;
-        getsockname(sock, (struct sockaddr *)&self, &self_n);
-        dprintf("> sockname sock=%d addr=%u.%u.%u.%u port=%d\n",
-                sock, NIPQUAD(saddr), ntohs(port));
-    }
   exit:
     if(err){
         shutdown(sock, 2);
@@ -427,7 +391,7 @@
  */
 int varp_ucast_open(uint32_t addr, u16 port, int *val){
     int err = 0;
-    int flags = VSOCK_BIND | VSOCK_REUSE;
+    int flags = (VSOCK_BIND | VSOCK_REUSE);
     dprintf(">\n");
     err = create_socket(SOCK_DGRAM, addr, port, flags, val);
     dprintf("< err=%d val=%d\n", err, *val);
@@ -536,7 +500,6 @@
     err = sock_add_wait_queue(varp_mcast_sock, &mcast_wait);
     err = sock_add_wait_queue(varp_ucast_sock, &ucast_wait);
     for(n = 1; atomic_read(&varp_run) == 1; n++){
-        //dprintf("> n=%d\n", n);
         count = 0;
         count += handle_sock_skb(varp_mcast_sock);
         count += handle_sock_skb(varp_ucast_sock);
@@ -609,20 +572,18 @@
 /** Open the varp sockets and start the thread handling them.
  *
  * @param mcaddr multicast address
- * @param addr unicast address
  * @param port port
  * @return 0 on success, error code otherwise
  */
-int varp_open(u32 mcaddr, u32 addr, u16 port){
+int varp_open(u32 mcaddr, u16 port){
     int err = 0;
     mm_segment_t oldfs;
 
     //MOD_INC_USE_COUNT;
-    dprintf("> mcaddr=%u.%u.%u.%u addr=%u.%u.%u.%u port=%u\n",
-            NIPQUAD(mcaddr), NIPQUAD(addr), ntohs(port));
-    //MOD_INC_USE_COUNT;
+    dprintf("> mcaddr=%u.%u.%u.%u port=%u\n",
+            NIPQUAD(mcaddr), ntohs(port));
     oldfs = change_fs(KERNEL_DS);
-    err = varp_mcast_open(mcaddr, addr, port, &varp_mcast_sock);
+    err = varp_mcast_open(mcaddr, port, &varp_mcast_sock);
     if(err < 0 ) goto exit;
     err = varp_ucast_open(INADDR_ANY, port, &varp_ucast_sock);
     if(err < 0 ) goto exit;
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vif.c
--- a/tools/vnet/vnet-module/vif.c      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vif.c      Fri Aug 26 10:52:53 2005
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/version.h>
 
 #include <linux/net.h>
 #include <linux/in.h>
@@ -33,11 +34,14 @@
 #include <net/protocol.h>
 #include <net/route.h>
 #include <linux/skbuff.h>
+#include <linux/spinlock.h>
 
 #include <etherip.h>
 #include <if_varp.h>
 #include <vnet_dev.h>
 #include <vif.h>
+#include <varp.h>
+
 #include "allocate.h"
 #include "hash_table.h"
 #include "sys_net.h"
@@ -50,6 +54,27 @@
 
 /** Table of vifs indexed by VifKey. */
 HashTable *vif_table = NULL;
+rwlock_t vif_table_lock = RW_LOCK_UNLOCKED;
+
+#define vif_read_lock(flags)    read_lock_irqsave(&vif_table_lock, (flags))
+#define vif_read_unlock(flags)  read_unlock_irqrestore(&vif_table_lock, 
(flags))
+#define vif_write_lock(flags)   write_lock_irqsave(&vif_table_lock, (flags))
+#define vif_write_unlock(flags) write_unlock_irqrestore(&vif_table_lock, 
(flags))
+
+void vif_print(void){
+    HashTable_for_decl(entry);
+    Vif *vif;
+    unsigned long flags;
+    char vnetbuf[VNET_ID_BUF];
+
+    vif_read_lock(flags);
+    HashTable_for_each(entry, vif_table){
+        vif = entry->value;
+        printk(KERN_INFO "VIF(vnet=%s vmac=" MACFMT ")\n",
+               VnetId_ntoa(&vif->vnet, vnetbuf), MAC6TUPLE(vif->vmac.mac));
+    }
+    vif_read_unlock(flags);
+}
 
 void vif_decref(Vif *vif){
     if(!vif) return;
@@ -71,18 +96,11 @@
  */
 Hashcode vif_key_hash_fn(void *k){
     VifKey *key = k;
-    Hashcode h;
-    h = hash_2ul(key->vnet,
-                 (key->vmac.mac[0] << 24) |
-                 (key->vmac.mac[1] << 16) |
-                 (key->vmac.mac[2] <<  8) |
-                 (key->vmac.mac[3]      ));
-    h = hash_hul(h, 
-                 (key->vmac.mac[4] <<   8) |
-                 (key->vmac.mac[5]       ));
+    Hashcode h = 0;
+    h = VnetId_hash(h, &key->vnet);
+    h = Vmac_hash(h, &key->vmac);
     return h;
 }
-
 
 /** Test equality for keys in the vif table.
  * Compares vnet and mac.
@@ -94,7 +112,8 @@
 int vif_key_equal_fn(void *k1, void *k2){
     VifKey *key1 = k1;
     VifKey *key2 = k2;
-    return (key1->vnet == key2->vnet) && (memcmp(key1->vmac.mac, 
key2->vmac.mac, ETH_ALEN) == 0);
+    return (VnetId_eq(&key1->vnet , &key2->vnet) &&
+            Vmac_eq(&key1->vmac, &key2->vmac));
 }
 
 /** Free an entry in the vif table.
@@ -118,13 +137,13 @@
  * @param mac MAC address
  * @return 0 on success, -ENOENT otherwise
  */
-int vif_lookup(int vnet, Vmac *vmac, Vif **vif){
-    int err = 0;
-    VifKey key = {};
+int vif_lookup(VnetId *vnet, Vmac *vmac, Vif **vif){
+    int err = 0;
+    VifKey key = { .vnet = *vnet, .vmac = *vmac };
     HTEntry *entry = NULL;
+    unsigned long flags;
     
-    key.vnet = vnet;
-    key.vmac = *vmac;
+    vif_read_lock(flags);
     entry = HashTable_get_entry(vif_table, &key);
     if(entry){
         *vif = entry->value;
@@ -133,7 +152,7 @@
         *vif = NULL;
         err = -ENOENT;
     }
-    //dprintf("< err=%d addr=" IPFMT "\n", err, NIPQUAD(*coaddr));
+    vif_read_unlock(flags);
     return err;
 }
 
@@ -143,10 +162,12 @@
  * @param mac MAC address
  * @return 0 on success, negative error code otherwise
  */
-int vif_add(int vnet, Vmac *vmac, Vif **val){
+int vif_add(VnetId *vnet, Vmac *vmac, Vif **val){
     int err = 0;
     Vif *vif = NULL;
     HTEntry *entry;
+    unsigned long flags;
+
     dprintf("> vnet=%d\n", vnet);
     vif = ALLOCATE(Vif);
     if(!vif){
@@ -154,9 +175,11 @@
         goto exit;
     }
     atomic_set(&vif->refcount, 1);
-    vif->vnet = vnet;
+    vif->vnet = *vnet;
     vif->vmac = *vmac;
+    vif_write_lock(flags);
     entry = HashTable_add(vif_table, vif, vif);
+    vif_write_unlock(flags);
     if(!entry){
         err = -ENOMEM;
         deallocate(vif);
@@ -177,22 +200,14 @@
  * @param coaddr return parameter for care-of address
  * @return number of entries deleted, or negative error code
  */
-int vif_remove(int vnet, Vmac *vmac){
-    int err = 0;
-    VifKey key = { .vnet = vnet, .vmac = *vmac };
-    //dprintf("> vnet=%d addr=%u.%u.%u.%u\n", vnet, NIPQUAD(coaddr));
+int vif_remove(VnetId *vnet, Vmac *vmac){
+    int err = 0;
+    VifKey key = { .vnet = *vnet, .vmac = *vmac };
+    unsigned long flags;
+
+    vif_write_lock(flags);
     err = HashTable_remove(vif_table, &key);
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int vif_find(int vnet, Vmac *vmac, int create, Vif **vif){
-    int err = 0;
-
-    err = vif_lookup(vnet, vmac, vif);
-    if(err && create){
-        err = vif_add(vnet, vmac, vif);
-    }
+    vif_write_unlock(flags);
     return err;
 }
 
@@ -200,15 +215,15 @@
     HashTable_clear(vif_table);
 }
 
-int vif_create(int vnet, Vmac *vmac, Vif **vif){
+int vif_create(VnetId *vnet, Vmac *vmac, Vif **vif){
     int err = 0;
 
     dprintf(">\n");
-    if(!vif_lookup(vnet, vmac, vif)){
+    if(vif_lookup(vnet, vmac, vif) == 0){
+        vif_decref(*vif);
         err = -EEXIST;
         goto exit;
     }
-    dprintf("> vif_add...\n");
     err = vif_add(vnet, vmac, vif);
   exit:
     if(err){
@@ -218,25 +233,6 @@
     return err;
 }
 
-/** Create a vif.
- *
- * @param vnet vnet id
- * @param mac mac address (as a string)
- * @return 0 on success, error code otherwise
- */
-int mkvif(int vnet, char *mac){
-    int err = 0;
-    Vmac vmac = {};
-    Vif *vif = NULL;
-    dprintf("> vnet=%d mac=%s\n", vnet, mac);
-    err = mac_aton(mac, vmac.mac);
-    if(err) goto exit;
-    err = vif_create(vnet, &vmac, &vif);
-  exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
 /** Initialize the vif table.
  *
  * @return 0 on success, error code otherwise
@@ -250,12 +246,9 @@
         goto exit;
     }
     vif_table->entry_free_fn = vif_entry_free_fn;
-    vif_table->key_hash_fn = vif_key_hash_fn;
-    vif_table->key_equal_fn = vif_key_equal_fn;
-
-    // Some vifs for testing.
-    //mkvif(1, "aa:00:00:00:20:11");
-    //mkvif(2, "aa:00:00:00:20:12");
+    vif_table->key_hash_fn   = vif_key_hash_fn;
+    vif_table->key_equal_fn  = vif_key_equal_fn;
+
   exit:
     if(err < 0) wprintf("< err=%d\n", err);
     dprintf("< err=%d\n", err);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vif.h
--- a/tools/vnet/vnet-module/vif.h      Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vif.h      Fri Aug 26 10:52:53 2005
@@ -24,12 +24,12 @@
 
 /** Key for entries in the vif table. */
 typedef struct VifKey {
-    int vnet;
+    VnetId vnet;
     Vmac vmac;
 } VifKey;
 
 typedef struct Vif {
-    int vnet;
+    VnetId vnet;
     Vmac vmac;
     struct net_device *dev;
     atomic_t refcount;
@@ -38,15 +38,17 @@
 struct HashTable;
 extern struct HashTable *vif_table;
 
+extern void vif_print(void);
+
 extern void vif_decref(Vif *vif);
 extern void vif_incref(Vif *vif);
 
-extern int vif_create(int vnet, Vmac *vmac, Vif **vif);
+extern int vif_create(struct VnetId *vnet, Vmac *vmac, Vif **vif);
 
-extern int vif_add(int vnet, Vmac *vmac, Vif **vif);
-extern int vif_lookup(int vnet, Vmac *vmac, Vif **vif);
-extern int vif_remove(int vnet, Vmac *vmac);
-extern int vif_find(int vnet, Vmac *vmac, int create, Vif **vif);
+extern int vif_create(VnetId *vnet, Vmac *vmac, Vif **vif);
+extern int vif_add(struct VnetId *vnet, Vmac *vmac, Vif **vif);
+extern int vif_lookup(struct VnetId *vnet, Vmac *vmac, Vif **vif);
+extern int vif_remove(struct VnetId *vnet, Vmac *vmac);
 extern void vif_purge(void);
 
 extern int vif_init(void);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vnet.c
--- a/tools/vnet/vnet-module/vnet.c     Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vnet.c     Fri Aug 26 10:52:53 2005
@@ -47,6 +47,7 @@
 #include <random.h>
 #include <tunnel.h>
 
+#include <skb_util.h>
 #include <vnet_dev.h>
 #include <vnet.h>
 #include <vif.h>
@@ -70,7 +71,7 @@
 /** Key for entries in the vnet address table. */
 typedef struct VnetAddrKey {
     /** Vnet id. */
-    int vnet;
+    VnetId vnet;
     /** MAC address. */
     unsigned char mac[ETH_ALEN];
 } VnetAddrKey;
@@ -88,7 +89,6 @@
 void Vnet_decref(Vnet *info){
     if(!info) return;
     if(atomic_dec_and_test(&info->refcount)){
-        dprintf("> free vnet=%u\n", info->vnet);
         vnet_dev_remove(info);
         deallocate(info);
     }
@@ -101,6 +101,28 @@
 void Vnet_incref(Vnet *info){
     if(!info) return;
     atomic_inc(&info->refcount);
+}
+
+void Vnet_print(Vnet *info)
+{
+    char vnetbuf[VNET_ID_BUF];
+
+    printk(KERN_INFO "VNET(vnet=%s device=%s security=%c%c)\n",
+           VnetId_ntoa(&info->vnet, vnetbuf),
+           info->device,
+           ((info->security & SA_AUTH) ? 'a' : '-'),
+           ((info->security & SA_CONF) ? 'c' : '-'));
+}
+
+void vnet_print(void)
+{
+    HashTable_for_decl(entry);
+    Vnet *info;
+    
+    HashTable_for_each(entry, vnet_table){
+        info = entry->value;
+        Vnet_print(info);
+    }
 }
 
 /** Allocate a vnet, setting reference count to 1.
@@ -129,7 +151,7 @@
     HTEntry *entry = NULL;
     // Vnet_del(info->vnet); //todo: Delete existing vnet info?
     Vnet_incref(info);
-    entry = HashTable_add(vnet_table, HKEY(info->vnet), info);
+    entry = HashTable_add(vnet_table, &info->vnet, info);
     if(!entry){
         err = -ENOMEM;
         Vnet_decref(info);
@@ -142,8 +164,8 @@
  * @param vnet id of vnet to remove
  * @return number of vnets removed
  */
-int Vnet_del(vnetid_t vnet){
-    return HashTable_remove(vnet_table, HKEY(vnet));
+int Vnet_del(VnetId *vnet){
+    return HashTable_remove(vnet_table, vnet);
 }
 
 /** Lookup a vnet by id.
@@ -153,17 +175,14 @@
  * @param info return parameter for vnet
  * @return 0 on sucess, -ENOENT if no vnet found
  */
-int Vnet_lookup(vnetid_t vnet, Vnet **info){
-    int err = 0;
-    dprintf("> vnet=%u info=%p\n", vnet, info);
-    dprintf("> vnet_table=%p\n",vnet_table); 
-    *info = HashTable_get(vnet_table, HKEY(vnet));
+int Vnet_lookup(VnetId *vnet, Vnet **info){
+    int err = 0;
+    *info = HashTable_get(vnet_table, vnet);
     if(*info){
         Vnet_incref(*info);
     } else {
         err = -ENOENT;
     }
-    dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -191,22 +210,33 @@
  */
 static int vnet_setup(void){
     int err = 0;
-    int i, n = 5; //20;
+    int i, n = 3;
     int security = vnet_security_default;
+    uint32_t vnetid;
     Vnet *vnet;
 
-    dprintf(">\n");
     for(i=0; i<n; i++){
         err = Vnet_alloc(&vnet);
         if(err) break;
-        vnet->vnet = VNET_VIF + i;
-        vnet->security = (vnet->vnet > 10 ? security : 0);
-        //err = Vnet_add(vnet);
+        vnetid = VNET_VIF + i;
+        vnet->vnet = toVnetId(vnetid);
+        sprintf(vnet->device, "vnif%04x", vnetid);
+        vnet->security = (vnetid > 10 ? security : 0);
         err = Vnet_create(vnet);
         if(err) break;
     }
-    dprintf("< err=%d\n", err);
-    return err;
+    return err;
+}
+
+int vnet_key_equal_fn(void *k1, void *k2){
+    VnetId *key1 = k1;
+    VnetId *key2 = k2;
+    return VnetId_eq(key1, key2);
+}
+
+Hashcode vnet_key_hash_fn(void *k){
+    VnetId *key = k;
+    return VnetId_hash(0, key);
 }
 
 /** Initialize the vnet table and the physical vnet.
@@ -216,18 +246,18 @@
 int vnet_init(void){
     int err = 0;
 
-    dprintf(">\n");
     vnet_table = HashTable_new(0);
-    dprintf("> vnet_table=%p\n", vnet_table);
     if(!vnet_table){
         err = -ENOMEM;
         goto exit;
     }
+    vnet_table->key_equal_fn = vnet_key_equal_fn;
+    vnet_table->key_hash_fn = vnet_key_hash_fn;
     vnet_table->entry_free_fn = vnet_entry_free_fn;
 
     err = Vnet_alloc(&vnet_physical);
     if(err) goto exit;
-    vnet_physical->vnet = VNET_PHYS;
+    vnet_physical->vnet = toVnetId(VNET_PHYS);
     vnet_physical->security = 0;
     err = Vnet_add(vnet_physical);
     if(err) goto exit;
@@ -237,7 +267,6 @@
     if(err) goto exit;
     err = vif_init();
   exit:
-    if(err < 0) wprintf("< err=%d\n", err);
     return err;
 }
 
@@ -248,50 +277,28 @@
     vnet_table = NULL;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-
-static inline int skb_route(struct sk_buff *skb, struct rtable **prt){
-    int err = 0;
-    struct flowi fl = {
-        .oif = skb->dev->ifindex,
-        .nl_u = {
-            .ip4_u = {
-                .daddr = skb->nh.iph->daddr,
-                .saddr = skb->nh.iph->saddr,
-                .tos   = skb->nh.iph->tos,
-            }
-        }
-    };
-    
-    err = ip_route_output_key(prt, &fl);
-    return err;
-}
-
-#else
-
-static inline int skb_route(struct sk_buff *skb, struct rtable **prt){
-    int err = 0;
-    struct rt_key key = { };
-    key.dst = skb->nh.iph->daddr;
-    key.src = skb->nh.iph->saddr;
-    key.tos = skb->nh.iph->tos;
-    key.oif = skb->dev->ifindex;
-    err = ip_route_output_key(prt, &key);
-    return err;
-}
-
-#endif
-
 inline int skb_xmit(struct sk_buff *skb){
     int err = 0;
     struct rtable *rt = NULL;
 
-    dprintf("> skb=%p dev=%s\n", skb, skb->dev->name);
-
+    dprintf(">\n");
     skb->protocol = htons(ETH_P_IP);
     err = skb_route(skb, &rt);
-    if(err) goto exit;
+    if(err){
+        wprintf("> skb_route=%d\n", err);
+        wprintf("> dev=%s idx=%d src=%u.%u.%u.%u dst=%u.%u.%u.%u tos=%d\n",
+                (skb->dev ? skb->dev->name : "???"),
+                (skb->dev ? skb->dev->ifindex : -1),
+                NIPQUAD(skb->nh.iph->saddr),
+                NIPQUAD(skb->nh.iph->daddr),
+                skb->nh.iph->tos);
+                
+        goto exit;
+    }
     skb->dst = &rt->u.dst;
+    if(!skb->dev){
+        skb->dev = rt->u.dst.dev;
+    }
 
     ip_select_ident(skb->nh.iph, &rt->u.dst, NULL);
 
@@ -317,39 +324,27 @@
  *
  * @todo fixme
  */
-int vnet_skb_send(struct sk_buff *skb, u32 vnet){
-    int err = 0;
-    Vif *vif = NULL;
-
-    dprintf("> skb=%p vnet=%u\n", skb, vnet);
-    if(vnet == VNET_PHYS || !vnet){
-        // For completeness, send direct to the network.
-        if(skb->dev){
-            err = skb_xmit(skb);
-        } else {
-            // Can't assume eth0 - might be nbe-br or other. Need to route.
-            struct net_device *dev = NULL;
-            err = vnet_get_device(DEVICE, &dev);
-            if(err) goto exit;
-            skb->dev = dev;
-            err = skb_xmit(skb);
-            dev_put(dev);
-        }
+int vnet_skb_send(struct sk_buff *skb, VnetId *vnet){
+    int err = 0;
+    VnetId vnet_phys = toVnetId(VNET_PHYS);
+
+    dprintf(">\n");
+    skb->dev = NULL;
+    if(!vnet || VnetId_eq(vnet, &vnet_phys)){
+        // No vnet or physical vnet, send direct to the network. 
+        skb_xmit(skb);
     } else {
-        dprintf("> varp_output\n");
         err = varp_output(skb, vnet);
     }
-    //dprintf("< err=%d\n", err);
-  exit:
-    if(vif) vif_decref(vif);
     dprintf("< err=%d\n", err);
     return err;
 }
 
 /** Receive an skb for a vnet.
+ * We make the skb come out of the vif for the vnet, and
+ * let ethernet bridging forward it to related interfaces.
  * If the dest is broadcast, goes to all vifs on the vnet.
- * If the dest is unicast, goes to addressed vif on vnet.
- * For each vif we set the packet dev and receive the packet.
+ * If the dest is unicast, goes to the addressed vif on the vnet.
  *
  * The packet must have skb->mac.raw set and skb->data must point
  * after the device (ethernet) header.
@@ -359,139 +354,19 @@
  * @param vmac packet vmac
  * @return 0 on success, error code otherwise
  */
-#if 1
-int vnet_skb_recv(struct sk_buff *skb, u32 vnet, Vmac *vmac){
-    // Receive the skb for a vnet.
-    // We make the skb come out of the vif for the vnet, and
-    // let ethernet bridging forward it to related interfaces.
+int vnet_skb_recv(struct sk_buff *skb, VnetId *vnet, Vmac *vmac){
     int err = 0;
     Vnet *info = NULL;
 
-    dprintf("> vnet=%u mac=%s\n", vnet, mac_ntoa(vmac->mac));
     err = Vnet_lookup(vnet, &info);
     if(err) goto exit;
     skb->dev = info->dev;
-    dprintf("> netif_rx dev=%s\n", skb->dev->name);
     netif_rx(skb);
   exit:
     if(info) Vnet_decref(info);
     if(err){
-      kfree_skb(skb);
-    }
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
-#else
-int vnet_skb_recv(struct sk_buff *skb, u32 vnet, Vmac *vmac){
-    int err = 0;
-    Vif *vif = NULL;
-
-    dprintf("> vnet=%u mac=%s\n", vnet, mac_ntoa(vmac->mac));
-    if(mac_is_multicast(vmac->mac)){
-        HashTable_for_decl(entry);
-        int count = 0;
-        struct sk_buff *new_skb;
-
-        HashTable_for_each(entry, vif_table){
-            vif = entry->value;
-            if(vif->vnet != vnet) continue;
-            count++;
-            new_skb = skb_copy(skb, GFP_ATOMIC);
-            if(!new_skb) break;
-            new_skb->dev = vif->dev;
-            dprintf("> %d] netif_rx dev=%s\n", count, new_skb->dev->name);
-            netif_rx(new_skb);
-        }
         kfree_skb(skb);
-    } else {
-        err = vif_lookup(vnet, vmac, &vif);
-        if(err){
-            kfree_skb(skb);
-            goto exit;
-        }
-        skb->dev = vif->dev;
-        dprintf("> netif_rx dev=%s\n", skb->dev->name);
-        netif_rx(skb);
-    }
-  exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-#endif
-   
-/** Check validity of an incoming IP frame.
- *
- * @param skb frame
- * @return 0 if ok, error code otherwise
- *
- * @todo fixme Can prob skip most of this because linux will have done it.
- * @todo Only need the vnet skb context check.
- */
-int check_ip_frame(struct sk_buff *skb){
-    int err = -EINVAL;
-    struct iphdr* iph;
-    struct net_device *dev;
-    __u32  len;
-    __u16  check;
-
-#if 0
-    if(skb->context){
-        // Todo: After ESP want to skip most checks (including checksum),
-        // Todo: but in general may not want to skip all checks on detunnel.
-        //dprintf("> Skip check, has context\n");
-        err = 0;
-        goto exit;
-    }
-#endif
-    // Check we have enough for an ip header - the skb passed should
-    // have data pointing at the eth header and skb->len should include
-    // that. skb->nh should already have been set. Let the indvidual
-    // protocol handlers worry about the exact ip header len
-    // (i.e. whether any ip options are set).
-    dev = skb->dev;
-    
-    if(skb->len <  ETH_HLEN + sizeof(struct iphdr)){
-        wprintf("> packet too short for ip header\n");
-        goto exit;
-    }
-
-    iph = skb->nh.iph;
-    /*
-     * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the 
checksum.
-     *
-     * Is the datagram acceptable?
-     *
-     * 1.      Length at least the size of an ip header
-     * 2.      Version of 4
-     * 3.      Checksums correctly. [Speed optimisation for later, skip 
loopback checksums]
-     * 4.      Doesn't have a bogus length
-     */
-    if (iph->ihl < 5 || iph->version != 4){
-        wprintf("> len and version check failed\n");
-        goto exit;
-    }
-    if(skb->len < ETH_HLEN + (iph->ihl << 2)){
-        wprintf("> packet too short for given ihl\n");
-        goto exit;
-    }
-
-    check = iph->check;
-    //iph->check = 0;
-    //iph->check = compute_cksum((__u16 *)iph, (iph->ihl << 1));
-    if(iph->check != check){
-        wprintf("> invalid checksum\n");
-        goto exit;
-    }
-
-    len = ntohs(iph->tot_len); 
-    if (skb->len < len + ETH_HLEN || len < (iph->ihl << 2)){
-        wprintf("> packet too short for tot_len\n");
-        goto exit;
-    }
-    skb->h.raw = skb->nh.raw + (iph->ihl << 2);
-    err = 0;
-  exit:
+    }
     return err;
 }
 
@@ -539,14 +414,13 @@
  *
  * @todo Need to check that the sa provides the correct security level.
  */
-int vnet_check_context(int vnet, SkbContext *context, Vnet **val){
+int vnet_check_context(VnetId *vnet, SkbContext *context, Vnet **val){
     int err = 0;
     Vnet *info = NULL;
     SAState *sa = NULL;
     
     err = Vnet_lookup(vnet, &info);
     if(err){
-        wprintf("> No vnet %d\n", vnet);
         goto exit;
     }
     if(!info->security) goto exit;
@@ -556,7 +430,8 @@
         goto exit;
     }
     if(context->protocol != IPPROTO_ESP){
-        wprintf("> Invalid protocol: wanted %d, got %d\n", IPPROTO_ESP, 
context->protocol);
+        wprintf("> Invalid protocol: wanted %d, got %d\n",
+                IPPROTO_ESP, context->protocol);
         goto exit;
     }
     sa = context->data;
@@ -586,13 +461,11 @@
  */
 static void sa_tunnel_close(Tunnel *tunnel){
     SAState *sa;
-    dprintf(">\n");
     if(!tunnel) return;
     sa = tunnel->data;
     if(!sa) return;
     SAState_decref(sa);
     tunnel->data = NULL;
-    dprintf("<\n");
 }
 
 /** Packet send function for SA tunnels.
@@ -604,7 +477,6 @@
 static int sa_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
     int err = -EINVAL;
     SAState *sa;
-    //dprintf("> tunnel=%p\n", tunnel);
     if(!tunnel){
         wprintf("> Null tunnel!\n");
         goto exit;
@@ -616,7 +488,6 @@
     }
     err = SAState_send(sa, skb, tunnel->base);
   exit:
-    //dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -638,7 +509,7 @@
  * @param tunnel return parameter
  * @return 0 on success, error code otherwise
  */
-int vnet_tunnel_open(u32 vnet, u32 addr, Tunnel **tunnel){
+int vnet_tunnel_open(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){
     extern TunnelType *etherip_tunnel_type;
     int err = 0;
     Vnet *info = NULL;
@@ -646,20 +517,17 @@
     Tunnel *sa_tunnel = NULL;
     Tunnel *etherip_tunnel = NULL;
 
-    dprintf("> vnet=%u addr=" IPFMT "\n", vnet, NIPQUAD(addr));
     err = Vnet_lookup(vnet, &info);
-    dprintf("> Vnet_lookup=%d\n", err);
     if(err) goto exit;
     if(info->security){
         SAState *sa = NULL;
-        dprintf("> security=%d\n", info->security);
+        //FIXME: Assuming IPv4 for now.
+        u32 ipaddr = addr->u.ip4.s_addr;
         err = Tunnel_create(sa_tunnel_type, vnet, addr, base_tunnel, 
&sa_tunnel);
         if(err) goto exit;
-        dprintf("> sa_tunnel=%p\n", sa_tunnel);
-        err = sa_create(info->security, 0, IPPROTO_ESP, addr, &sa);
+        err = sa_create(info->security, 0, IPPROTO_ESP, ipaddr, &sa);
         if(err) goto exit;
         sa_tunnel->data = sa;
-        dprintf("> sa=%p\n", sa);
         base_tunnel = sa_tunnel;
     }
     err = Tunnel_create(etherip_tunnel_type, vnet, addr, base_tunnel, 
&etherip_tunnel);
@@ -673,7 +541,6 @@
     } else {
         *tunnel = etherip_tunnel;
     }
-    dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -685,14 +552,12 @@
  * @param tunnel return parameter
  * @return 0 on success, error code otherwise
  */
-int vnet_tunnel_lookup(u32 vnet, u32 addr, Tunnel **tunnel){
-    int err = 0;
-    dprintf("> vnet=%d addr=" IPFMT "\n", vnet, NIPQUAD(addr));
+int vnet_tunnel_lookup(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){
+    int err = 0;
     *tunnel = Tunnel_lookup(vnet, addr);
     if(!*tunnel){
         err = vnet_tunnel_open(vnet, addr, tunnel);
     }
-    dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -703,16 +568,14 @@
  * @param skb packet
  * @return 0 on success, error code otherwise
  */
-int vnet_tunnel_send(vnetid_t vnet, vnetaddr_t addr, struct sk_buff *skb){
+int vnet_tunnel_send(VnetId *vnet, VarpAddr *addr, struct sk_buff *skb){
     int err = 0;
     Tunnel *tunnel = NULL;
-    dprintf("> vnet=%u addr=" IPFMT "\n", vnet, NIPQUAD(addr));
     err = vnet_tunnel_lookup(vnet, addr, &tunnel);
     if(err) goto exit;
     err = Tunnel_send(tunnel, skb);
     Tunnel_decref(tunnel);
   exit:
-    dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -722,7 +585,7 @@
     vnet_exit();
     esp_module_exit();
     etherip_module_exit();
-    tunnel_module_init();
+    tunnel_module_exit();
     random_module_exit();
 }
 
@@ -753,12 +616,13 @@
     sa_algorithm_probe_all();
     err = sa_table_init();
     if(err) wprintf("> sa_table_init err=%d\n", err);
+    if(err) goto exit;
     ProcFS_init();
   exit:
     if(err < 0){
         vnet_module_exit();
-    }
-    if(err < 0) wprintf("< err=%d\n", err);
+        wprintf("< err=%d\n", err);
+    }
     return err;
 }
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vnet.h
--- a/tools/vnet/vnet-module/vnet.h     Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vnet.h     Fri Aug 26 10:52:53 2005
@@ -29,17 +29,15 @@
 struct Vif;
 struct net_device;
 
-typedef uint32_t vnetid_t;
-typedef uint32_t vnetaddr_t;
-
 /** Vnet property record. */
 typedef struct Vnet {
     /** Reference count. */
     atomic_t refcount;
     /** Vnet id. */
-    vnetid_t vnet;
+    struct VnetId vnet;
     /** Security flag. If true the vnet requires ESP. */
     int security;
+    char device[IFNAMSIZ];
 
     struct net_device *dev;
     struct net_device *bridge;
@@ -51,30 +49,28 @@
     int recursion;
 } Vnet;
 
-extern int Vnet_lookup(vnetid_t id, Vnet **vnet);
-extern int Vnet_add(Vnet *vnet);
-extern int Vnet_del(vnetid_t vnet);
-extern void Vnet_incref(Vnet *);
-extern void Vnet_decref(Vnet *);
-extern int Vnet_alloc(Vnet **vnet);
+extern void vnet_print(void);
+extern void Vnet_print(Vnet *info);
+
+extern int Vnet_lookup(struct VnetId *vnet, struct Vnet **info);
+extern int Vnet_add(struct Vnet *info);
+extern int Vnet_del(struct VnetId *vnet);
+extern void Vnet_incref(struct Vnet *info);
+extern void Vnet_decref(struct Vnet *info);
+extern int Vnet_alloc(struct Vnet **info);
 extern Vnet *vnet_physical;
 
 extern int skb_xmit(struct sk_buff *skb);
-extern int vnet_skb_send(struct sk_buff *skb, u32 vnet);
-extern int vnet_skb_recv(struct sk_buff *skb, u32 vnet, struct Vmac *vmac);
+extern int vnet_skb_send(struct sk_buff *skb, struct VnetId *vnet);
+extern int vnet_skb_recv(struct sk_buff *skb, struct VnetId *vnet, struct Vmac 
*vmac);
 
-extern int vnet_check_context(int vnet, SkbContext *context, Vnet **vinfo);
+extern int vnet_check_context(struct VnetId *vnet, SkbContext *context, Vnet 
**vinfo);
 
-extern int vnet_tunnel_open(vnetid_t vnet, vnetaddr_t addr, Tunnel **tunnel);
-extern int vnet_tunnel_lookup(vnetid_t vnet, vnetaddr_t addr, Tunnel **tunnel);
-extern int vnet_tunnel_send(vnetid_t vnet, vnetaddr_t addr, struct sk_buff 
*skb);
+extern int vnet_tunnel_open(struct VnetId *vnet, struct VarpAddr *addr, Tunnel 
**tunnel);
+extern int vnet_tunnel_lookup(struct VnetId *vnet, struct VarpAddr *addr, 
Tunnel **tunnel);
+extern int vnet_tunnel_send(struct VnetId *vnet, struct VarpAddr *addr, struct 
sk_buff *skb);
 
 extern int vnet_init(void);
-
-enum {
-    HANDLE_OK = 1,
-    HANDLE_NO = 0,
-};
 
 extern int vnet_sa_security(u32 spi, int protocol, u32 addr);
 struct SAState;
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vnet_dev.c
--- a/tools/vnet/vnet-module/vnet_dev.c Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vnet_dev.c Fri Aug 26 10:52:53 2005
@@ -48,15 +48,9 @@
 #undef DEBUG
 #include "debug.h"
 
-#define VNETIF_FMT "vnetif%u"
-#define VNETBR_FMT "vnet%u"
-
 #ifndef CONFIG_BRIDGE
 #error Must configure ethernet bridging in Network Options
 #endif
-
-#include <linux/../../net/bridge/br_private.h>
-#define dev_bridge(_dev) ((struct net_bridge *)(_dev)->priv)
 
 static void vnet_dev_destructor(struct net_device *dev){
     dprintf(">\n");
@@ -113,135 +107,16 @@
     Vnet *vnet = (void*)dev->priv;
 
     dprintf(">\n");
-    dprintf("> vnet=%d\n", vnet->vnet);
-    snprintf(dev->name, IFNAMSIZ - 1, VNETIF_FMT, vnet->vnet);
-    if(__dev_get_by_name(dev->name)){
+    if(__dev_get_by_name(vnet->device)){
         err = -ENOMEM;
-    }
+        wprintf("> vnet device name in use: %s\n", vnet->device);
+    }
+    strcpy(dev->name, vnet->device);
     dprintf("< err=%d\n", err);
     return err;
 }
 
-//============================================================================
-#ifdef CONFIG_VNET_BRIDGE
-
-#define BRIDGE DEVICE
-
-void vnet_bridge_fini(Vnet *vnet){
-    if(!vnet) return;
-    if(vnet->bridge){
-        br_del_bridge(vnet->bridge->name);
-        vnet->bridge = NULL;
-    }
-}
-
-/** Create the bridge for a vnet, and add the
- * vnet interface to it.
- *
- * @param vnet vnet
- * @return 0 on success, error code otherwise
- */
-int vnet_bridge_init(Vnet *vnet){
-    int err = 0;
-    char bridge[IFNAMSIZ] = {};
-    struct net_bridge *br;
-    vnet->bridge = NULL;
-    snprintf(bridge, IFNAMSIZ - 1, VNETBR_FMT, vnet->vnet);
-    rtnl_lock();
-    err = br_add_bridge(bridge);
-    rtnl_unlock();
-    if(err){
-        dprintf("> Error creating vnet bridge %s: err=%d\n", bridge, err);
-        goto exit;
-    }
-    vnet->bridge = __dev_get_by_name(bridge);
-    if(!vnet->bridge){
-        wprintf("> Vnet bridge %s is null!\n", bridge);
-        err = -EINVAL;
-        goto exit;
-    }
-    br = dev_bridge(vnet->bridge);
-    br->stp_enabled = 0;
-    br->bridge_hello_time = 0;
-    br->hello_time = 0;
-    br->bridge_forward_delay = 0;
-    br->forward_delay = 0;
-    rtnl_lock();
-    err = br_add_if(br, vnet->dev);
-    rtnl_unlock();
-    if(err){
-        dprintf("> Error adding vif %s to vnet bridge %s: err=%d\n",
-                vnet->dev->name, bridge, err);
-        goto exit;
-    }
-    rtnl_lock();
-    dev_open(vnet->dev);
-    dev_open(vnet->bridge);
-    rtnl_unlock();
-  exit:
-    if(err){
-        if(vnet->bridge){
-            rtnl_lock();
-            br_del_bridge(bridge);
-            rtnl_unlock();
-            vnet->bridge = NULL;
-        }
-    }
-    return err;
-}
-
-
-/** Add an interface to the bridge for a vnet.
- *
- * @param vnet vnet
- * @param dev interface
- * @return 0 on success, error code otherwise
- */
-int vnet_add_if(Vnet *vnet, struct net_device *dev){
-    int err = 0;
-    struct net_device *brdev;
-
-    dprintf(">\n");
-    if(!vnet->bridge){
-        err = -EINVAL;
-        goto exit;
-    }
-    // Delete the interface from the default bridge.
-    // todo: Really want to delete it from any bridge it's in.
-    if(!vnet_get_device(BRIDGE, &brdev)){
-        rtnl_lock();
-        br_del_if(dev_bridge(brdev), dev);
-        rtnl_unlock();
-    }
-    dprintf("> br_add_if %s %s\n", vnet->bridge->name, dev->name);
-    rtnl_lock();
-    dev_open(dev);
-    dev_open(vnet->bridge);
-    err = br_add_if(dev_bridge(vnet->bridge), dev);
-    rtnl_unlock();
-  exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
-int vnet_del_if(Vnet *vnet, struct net_device *dev){
-    int err = 0;
-
-    dprintf(">\n");
-    if(!vnet->bridge){
-        err = -EINVAL;
-        goto exit;
-    }
-    rtnl_lock();
-    br_del_if(dev_bridge(vnet->bridge), dev);
-    rtnl_unlock();
-  exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-    
-
-/** Create the bridge and virtual interface for a vnet.
+/** Create the virtual interface for a vnet.
  *
  * @param info vnet
  * @return 0 on success, error code otherwise
@@ -249,25 +124,13 @@
 int Vnet_create(Vnet *info){
     int err = 0;
 
-    dprintf("> %u\n", info->vnet);
     err = vnet_dev_add(info);
     if(err) goto exit;
-    dprintf("> vnet_bridge_init\n");
-    err = vnet_bridge_init(info);
-    if(err) goto exit;
-    dprintf("> Vnet_add...\n");
     err = Vnet_add(info);
   exit:
-    if(err){
-        dprintf("> vnet_bridge_fini...\n");
-        vnet_bridge_fini(info);
-    }
-    dprintf("< err=%d\n", err);
     return err;
 }
     
-
-
 /** Remove the net device for a vnet.
  * Clears the dev field of the vnet.
  * Safe to call if the vnet or its dev are null.
@@ -276,75 +139,13 @@
  */
 void vnet_dev_remove(Vnet *vnet){
     if(!vnet) return;
-    dprintf("> vnet=%u\n", vnet->vnet);
-    if(vnet->bridge){
-        dprintf("> br_del_bridge(%s)\n", vnet->bridge->name);
-        rtnl_lock();
-        br_del_bridge(vnet->bridge->name);
-        rtnl_unlock();
-        vnet->bridge = NULL;
-    }
     if(vnet->dev){
         //dev_put(vnet->dev);
         dprintf("> unregister_netdev(%s)\n", vnet->dev->name);
         unregister_netdev(vnet->dev);
         vnet->dev = NULL;
     }
-    dprintf("<\n");
-}
-
-//============================================================================
-#else
-//============================================================================
-
-/** Create the virtual interface for a vnet.
- *
- * @param info vnet
- * @return 0 on success, error code otherwise
- */
-int Vnet_create(Vnet *info){
-    int err = 0;
-
-    dprintf("> %u\n", info->vnet);
-    err = vnet_dev_add(info);
-    if(err) goto exit;
-    dprintf("> Vnet_add...\n");
-    err = Vnet_add(info);
-  exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-    
-int vnet_add_if(Vnet *vnet, struct net_device *dev){
-    int err = -ENOSYS;
-    return err;
-}
-
-
-int vnet_del_if(Vnet *vnet, struct net_device *dev){
-    int err = 0;
-    return err;
-}
-
-/** Remove the net device for a vnet.
- * Clears the dev field of the vnet.
- * Safe to call if the vnet or its dev are null.
- *
- * @param vnet vnet
- */
-void vnet_dev_remove(Vnet *vnet){
-    if(!vnet) return;
-    dprintf("> vnet=%u\n", vnet->vnet);
-    if(vnet->dev){
-        //dev_put(vnet->dev);
-        dprintf("> unregister_netdev(%s)\n", vnet->dev->name);
-        unregister_netdev(vnet->dev);
-        vnet->dev = NULL;
-    }
-    dprintf("<\n");
-}
-#endif
-//============================================================================
+}
 
 static int vnet_dev_open(struct net_device *dev){
     int err = 0;
@@ -365,6 +166,7 @@
 static int vnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device 
*dev){
     int err = 0;
     Vnet *vnet = dev->priv;
+    int len = 0;
 
     dprintf("> skb=%p\n", skb);
     if(vnet->recursion++) {
@@ -385,12 +187,14 @@
         skb->mac.raw = skb->data;
     }
     //dev->trans_start = jiffies;
-    err = vnet_skb_send(skb, vnet->vnet);
+    len = skb->len;
+    // Must not use skb pointer after vnet_skb_send().
+    err = vnet_skb_send(skb, &vnet->vnet);
     if(err < 0){
         vnet->stats.tx_errors++;
     } else {
         vnet->stats.tx_packets++;
-        vnet->stats.tx_bytes += skb->len;
+        vnet->stats.tx_bytes += len;
     }
   exit:
     vnet->recursion--;
@@ -416,43 +220,48 @@
                                 struct net_device *dev, unsigned short type,
                                 void *daddr, void *saddr, unsigned len){
     int err = 0;
-    dprintf("> skb=%p ethhdr=%p dev=%s len=%u\n",
-            skb, skb->mac.raw, dev->name, len);
-    if(saddr){
-        dprintf("> saddr=" MACFMT "\n", MAC6TUPLE((unsigned char*)saddr));
-    } else {
-        dprintf("> saddr=NULL\n");
-    }
-    if(daddr){
-        dprintf("> daddr=" MACFMT "\n", MAC6TUPLE((unsigned char*)daddr));
-    } else {
-        dprintf("> daddr=NULL\n");
-    }
+
     err = eth_hard_header(skb, dev, type, daddr, saddr, len);
-    dprintf("> eth_hard_header=%d\n", err);
+    if(err) goto exit;
     skb->mac.raw = skb->data;
-    dprintf("> src=" MACFMT " dst=" MACFMT "\n",
-            MAC6TUPLE(skb->mac.ethernet->h_source),
-            MAC6TUPLE(skb->mac.ethernet->h_dest));
-    dprintf("< err=%d\n", err);
+  exit:
+    return err;
+}
+
+void vnet_default_mac(unsigned char *mac)
+{
+    static unsigned val = 1;
+    mac[0] = 0xAA;
+    mac[1] = 0xFF;
+    mac[2] = (unsigned char)((val >> 24) & 0xff);
+    mac[3] = (unsigned char)((val >> 16) & 0xff);
+    mac[4] = (unsigned char)((val >>  8) & 0xff);
+    mac[5] = (unsigned char)((val      ) & 0xff);
+    val++;
+}
+
+int vnet_device_mac(const char *device, unsigned char *mac){
+    int err;
+    struct net_device *dev;
+
+    err = vnet_get_device(device, &dev);
+    if(err) goto exit;
+    memcpy(mac, dev->dev_addr, ETH_ALEN);
+    dev_put(dev);
+  exit:
     return err;
 }
 
 void vnet_dev_mac(unsigned char *mac){
-    static unsigned val = 1;
-    struct net_device *dev;
-
-    if(vnet_get_device(DEVICE, &dev)){
-        mac[0] = 0xAA;
-        mac[1] = 0xFF;
-        mac[2] = (unsigned char)((val >> 24) & 0xff);
-        mac[3] = (unsigned char)((val >> 16) & 0xff);
-        mac[4] = (unsigned char)((val >>  8) & 0xff);
-        mac[5] = (unsigned char)((val      ) & 0xff);
-        val++;
-    } else {
-        memcpy(mac, dev->dev_addr, ETH_ALEN);
-        dev_put(dev);
+    const char *devices[] = { "eth0", "eth1", "eth2", NULL };
+    const char **pdev;
+    int err = -ENODEV;
+
+    for(pdev = devices; err && *pdev; pdev++){
+        err = vnet_device_mac(*pdev, mac);
+    }
+    if(err){
+        vnet_default_mac(mac);
     }
 }
 
@@ -463,7 +272,9 @@
     dprintf(">\n");
     ether_setup(dev);
 
-    if(!eth_hard_header) eth_hard_header = dev->hard_header;
+    if(!eth_hard_header){
+        eth_hard_header = dev->hard_header;
+    }
     dev->hard_header          = vnet_dev_hard_header;
 
     dev->open                 = vnet_dev_open;
@@ -507,7 +318,10 @@
     if(vnet->dev) goto exit;
     vnet->header_n = sizeof(struct iphdr) + sizeof(struct etheriphdr);
     dev = kmalloc(sizeof(struct net_device), GFP_ATOMIC);
-    if(!dev){ err = -ENOMEM; goto exit; }
+    if(!dev){
+        err = -ENOMEM;
+        goto exit;
+    }
     *dev = (struct net_device){};
     dev->priv = vnet;
     vnet->dev = dev;
@@ -515,9 +329,10 @@
     err = vnet_dev_set_name(dev);
     if(err) goto exit;
     vnet_dev_init(dev);
-    dprintf("> name=%s, register_netdev...\n", dev->name);
     err = register_netdev(dev);
-    dprintf("> register_netdev=%d\n", err);
+    if(err){
+        wprintf("> register_netdev(%s) = %d\n", dev->name, err);
+    }
     if(err) goto exit;
     rtnl_lock();
     dev_open(dev);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vnet_dev.h
--- a/tools/vnet/vnet-module/vnet_dev.h Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vnet_dev.h Fri Aug 26 10:52:53 2005
@@ -20,12 +20,9 @@
 #define _VNET_VNET_DEV_H_
 
 struct Vnet;
-struct net_device;
 
 extern int vnet_dev_add(struct Vnet *vnet);
 extern void vnet_dev_remove(struct Vnet *vnet);
 extern int Vnet_create(struct Vnet *info);
-extern int vnet_add_if(struct Vnet *vnet, struct net_device *dev);
-extern int vnet_del_if(struct Vnet *vnet, struct net_device *dev);
 
 #endif
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnet-module/vnet_ioctl.c
--- a/tools/vnet/vnet-module/vnet_ioctl.c       Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnet-module/vnet_ioctl.c       Fri Aug 26 10:52:53 2005
@@ -59,7 +59,7 @@
 on the kernel interface being available to us (it's not exported @!$"%!).
 
 Create a vnet N:
-- create the vnet device vnetifN: using commands to /proc, kernel api
+- create the vnet device vnifN: using commands to /proc, kernel api
 - create the vnet bridge vnetN: using brctl in user-space
 - for best results something should keep track of the mapping vnet id <-> 
bridge name
 
@@ -312,7 +312,6 @@
     err = Parser_input(parser, NULL, 0);
     if(err) goto exit;
     obj = parser->val;
-    objprint(iostdout, obj, 0); IOStream_print(iostdout, "\n");
     for(l = obj; CONSP(l); l = CDR(l)){
         err = eval(CAR(l));
         if(err) break;
@@ -451,6 +450,7 @@
     return err;
 }
 
+#if 0
 static int intof(Sxpr exp, int *v){
     int err = 0;
     char *s;
@@ -473,6 +473,24 @@
     err = intof(val, v);
     return err;
 }
+#endif
+
+static int vnetof(Sxpr exp, VnetId *v){
+    int err = 0;
+    char *s;
+    err = stringof(exp, &s);
+    if(err) goto exit;
+    err = VnetId_aton(s, v);
+  exit:
+    return err;
+}
+
+static int child_vnet(Sxpr exp, Sxpr key, VnetId *v){
+    int err = 0;
+    Sxpr val = sxpr_child_value(exp, key, ONONE);
+    err = vnetof(val, v);
+    return err;
+}
 
 static int macof(Sxpr exp, unsigned char *v){
     int err = 0;
@@ -515,20 +533,27 @@
  * It is an error if a vnet with the same id exists.
  *
  * @param vnet vnet id
+ * @param device vnet device name
  * @param security security level
  * @return 0 on success, error code otherwise
  */
-static int ctrl_vnet_add(int vnet, int security){
+static int ctrl_vnet_add(VnetId *vnet, char *device, int security){
     int err = 0;
     Vnet *vnetinfo = NULL;
+
+    if(strlen(device) >= IFNAMSIZ){
+        err = -EINVAL;
+        goto exit;
+    }
     if(Vnet_lookup(vnet, &vnetinfo) == 0){
         err = -EEXIST;
         goto exit;
     }
     err = Vnet_alloc(&vnetinfo);
     if(err) goto exit;
-    vnetinfo->vnet = vnet;
+    vnetinfo->vnet = *vnet;
     vnetinfo->security = security;
+    strcpy(vnetinfo->device, device);
     err = Vnet_create(vnetinfo);
   exit:
     if(vnetinfo) Vnet_decref(vnetinfo);
@@ -540,9 +565,15 @@
  * @param vnet vnet id
  * @return 0 on success, error code otherwise
  */
-static int ctrl_vnet_del(int vnet){
+static int ctrl_vnet_del(VnetId *vnet){
     int err = -ENOSYS;
     // Can't delete if there are any vifs on the vnet.
+
+    // Need to flush vif entries for the deleted vnet.
+    // Need to flush varp entries for the deleted vnet.
+    // Note that (un)register_netdev() hold rtnl_lock() around
+    // (un)register_netdevice().
+
     //Vnet_del(vnet);
     return err;
 }
@@ -553,7 +584,7 @@
  * @param vmac mac address
  * @return 0 on success, error code otherwise
  */
-static int ctrl_vif_add(int vnet, Vmac *vmac){
+static int ctrl_vif_add(VnetId *vnet, Vmac *vmac){
     int err = 0;
     Vnet *vnetinfo = NULL;
     Vif *vif = NULL;
@@ -561,7 +592,7 @@
     dprintf(">\n");
     err = Vnet_lookup(vnet, &vnetinfo);
     if(err) goto exit;
-    err = vif_add(vnet, vmac, &vif);
+    err = vif_create(vnet, vmac, &vif);
   exit:
     if(vnetinfo) Vnet_decref(vnetinfo);
     if(vif) vif_decref(vif);
@@ -569,46 +600,13 @@
     return err;
 }
 
-/** Add net device 'vifname' to the bridge for 'vnet' and
- * create an entry for a vif with the given vnet and vmac.
- * This is used when device 'vifname' is a virtual device
- * connected to a vif in a vm.
- *
- * @param vifname name of device to bridge
+/** Delete a vif.
+ *
  * @param vnet vnet id
  * @param vmac mac address
  * @return 0 on success, error code otherwise
  */
-static int ctrl_vif_conn(char *vifname, int vnet, Vmac *vmac){
-    int err = 0;
-    Vnet *vnetinfo = NULL;
-    struct net_device *vifdev = NULL;
-    Vif *vif = NULL;
-
-    dprintf("> %s\n", vifname);
-    err = Vnet_lookup(vnet, &vnetinfo);
-    if(err) goto exit;
-    err = vif_add(vnet, vmac, &vif);
-    if(err) goto exit;
-    err = vnet_get_device(vifname, &vifdev);
-    if(err) goto exit;
-    vif->dev = vifdev;
-    err = vnet_add_if(vnetinfo, vifdev);
-  exit:
-    if(vnetinfo) Vnet_decref(vnetinfo);
-    if(vif) vif_decref(vif);
-    if(vifdev) dev_put(vifdev);
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
-/** Delete a vif.
- *
- * @param vnet vnet id
- * @param vmac mac address
- * @return 0 on success, error code otherwise
- */
-static int ctrl_vif_del(int vnet, Vmac *vmac){
+static int ctrl_vif_del(VnetId *vnet, Vmac *vmac){
     int err = 0;
     Vnet *vnetinfo = NULL;
     Vif *vif = NULL;
@@ -618,10 +616,6 @@
     if(err) goto exit;
     err = vif_lookup(vnet, vmac, &vif);
     if(err) goto exit;
-    if(vif->dev){
-        vnet_del_if(vnetinfo, vif->dev);
-        vif->dev = NULL;
-    }
     vif_remove(vnet, vmac);
   exit:
     if(vnetinfo) Vnet_decref(vnetinfo);
@@ -652,21 +646,37 @@
     return err;
 }
 
-/** (vnet.add (id <id>) [(security { none | auth | conf } )] )
+/** (varp.flush)
+ */
+static int eval_varp_flush(Sxpr exp){
+    int err = 0;
+    varp_flush();
+    return err;
+}
+
+/** (vnet.add (id <id>)
+ *            [(vnetif <name>)]
+ *            [(security { none | auth | conf } )]
+ *  )
  */
 static int eval_vnet_add(Sxpr exp){
     int err = 0;
     Sxpr oid = intern("id");
     Sxpr osecurity = intern("security");
+    Sxpr ovnetif = intern("vnetif");
     Sxpr csecurity;
-    int id;
-    char *security;
+    VnetId vnet = {};
+    char *device = NULL;
+    char dev[IFNAMSIZ] = {};
+    char *security = NULL;
     int sec;
-    err = child_int(exp, oid, &id);
-    if(err) goto exit;
-    if(id < VNET_VIF){ 
-        err = -EINVAL;
-        goto exit;
+
+    err = child_vnet(exp, oid, &vnet);
+    if(err) goto exit;
+    child_string(exp, ovnetif, &device);
+    if(!device){
+        snprintf(dev, IFNAMSIZ-1, "vnif%04x", ntohs(vnet.u.vnet16[7]));
+        device = dev;
     }
     csecurity = sxpr_child_value(exp, osecurity, intern("none"));
     err = stringof(csecurity, &security);
@@ -681,8 +691,7 @@
         err = -EINVAL;
         goto exit;
     }
-    dprintf("> vnet id=%d\n", id);
-    err = ctrl_vnet_add(id, sec);
+    err = ctrl_vnet_add(&vnet, device, sec);
  exit:
     dprintf("< err=%d\n", err);
     return err;
@@ -698,11 +707,11 @@
 static int eval_vnet_del(Sxpr exp){
     int err = 0;
     Sxpr oid = intern("id");
-    int id;
-
-    err = child_int(exp, oid, &id);
-    if(err) goto exit;
-    err = ctrl_vnet_del(id);
+    VnetId vnet = {};
+
+    err = child_vnet(exp, oid, &vnet);
+    if(err) goto exit;
+    err = ctrl_vnet_del(&vnet);
   exit:
     return err;
 }
@@ -713,55 +722,32 @@
     int err = 0;
     Sxpr ovnet = intern("vnet");
     Sxpr ovmac = intern("vmac");
-    int vnet;
+    VnetId vnet = {};
     Vmac vmac = {};
 
-    err = child_int(exp, ovnet, &vnet);
+    err = child_vnet(exp, ovnet, &vnet);
     if(err) goto exit;
     err = child_mac(exp, ovmac, vmac.mac);
     if(err) goto exit;
-    err = ctrl_vif_add(vnet, &vmac);
-  exit:
-    return err;
-}
-
-/** (vif.conn (vif <name>) (vnet <id>) (vmac <mac>))
- */
-static int eval_vif_conn(Sxpr exp){
-    int err = 0;
-    Sxpr ovif = intern("vif");
+    err = ctrl_vif_add(&vnet, &vmac);
+  exit:
+    return err;
+}
+
+/** (vif.del (vnet <vnet>) (vmac <macaddr>))
+ */
+static int eval_vif_del(Sxpr exp){
+    int err = 0;
     Sxpr ovnet = intern("vnet");
     Sxpr ovmac = intern("vmac");
-    char *vif = NULL;
-    int vnet = 0;
+    VnetId vnet = {};
     Vmac vmac = {};
 
-    err = child_string(exp, ovif, &vif);
-    if(err) goto exit;
-    err = child_int(exp, ovnet, &vnet);
+    err = child_vnet(exp, ovnet, &vnet);
     if(err) goto exit;
     err = child_mac(exp, ovmac, vmac.mac);
-    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
-    err = ctrl_vif_conn(vif, vnet, &vmac);
- exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
-/** (vif.del (vnet <vnet>) (vmac <macaddr>))
- */
-static int eval_vif_del(Sxpr exp){
-    int err = 0;
-    Sxpr ovnet = intern("vnet");
-    Sxpr ovmac = intern("vmac");
-    int vnet;
-    Vmac vmac = {};
-
-    err = child_int(exp, ovnet, &vnet);
-    if(err) goto exit;
-    err = child_mac(exp, ovmac, vmac.mac);
-    if(err) goto exit;
-    err = ctrl_vif_del(vnet, &vmac);
+    if(err) goto exit;
+    err = ctrl_vif_del(&vnet, &vmac);
   exit:
     return err;
 }
@@ -776,23 +762,23 @@
     SxprEval defs[] = {
         { intern("varp.print"),   eval_varp_print   },
         { intern("varp.mcaddr"),  eval_varp_mcaddr  },
+        { intern("varp.flush"),   eval_varp_flush   },
         { intern("vif.add"),      eval_vif_add      },
-        { intern("vif.conn"),     eval_vif_conn     },
         { intern("vif.del"),      eval_vif_del      },
         { intern("vnet.add"),     eval_vnet_add     },
         { intern("vnet.del"),     eval_vnet_del     },
         { ONONE, NULL } };
     SxprEval *def;
 
-    dprintf(">\n");
-    err = -EINVAL;
+    iprintf("> "); objprint(iostdout, exp, 0); IOStream_print(iostdout, "\n");
+    err = -ENOSYS;
     for(def = defs; !NONEP(def->elt); def++){
         if(sxpr_elementp(exp, def->elt)){
             err = def->fn(exp);
             break;
         }
     }
-    dprintf("< err=%d\n", err);
+    iprintf("< err=%d\n", err);
     return err;
 }
 
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnetd/Makefile
--- a/tools/vnet/vnetd/Makefile Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnetd/Makefile Fri Aug 26 10:52:53 2005
@@ -16,32 +16,29 @@
 # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 #----------------------------------------------------------------------------
 
+VNET_ROOT = $(shell cd .. && pwd)
+include $(VNET_ROOT)/Make.env
+
 all: vnetd
 
 #----------------------------------------------------------------------------
 
-XEN_ROOT  = ../../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 VNETD_INSTALL_DIR = /usr/sbin
 
-LIB_DIR = ../libxutil
-VNET_DIR = ../vnet-module
-
-INCLUDES += -I$(LIB_DIR)
-INCLUDES += -I$(VNET_DIR)
+INCLUDES += -I$(LIBXUTIL_DIR)
+INCLUDES += -I$(VNET_MODULE_DIR)
 
 #----------------------------------------------------------------------------
 # GC.
-GC_DIR:=../gc/install
-GC_INCLUDE:= $(GC_DIR)/include
-GC_LIB_DIR:=$(GC_DIR)/lib
 
 INCLUDES += -I$(GC_INCLUDE)
 #LIBS += -L$(GC_LIB_DIR)
 CPPFLAGS += -D USE_GC
 
 #----------------------------------------------------------------------------
+CFLAGS += -g
 CFLAGS += -Wall
 CFLAGS += $(INCLUDES) $(LIBS)
 
@@ -51,7 +48,7 @@
 CFLAGS += -Wp,-MD,.$(@F).d
 PROG_DEP = .*.d
 
-vpath %.c $(LIB_DIR)
+vpath %.c $(LIBXUTIL_DIR)
 
 IPATHS:=$(INCLUDES:-I=)
 vpath %.h $(IPATHS)
@@ -83,9 +80,9 @@
 
 VNETD_OBJ := $(VNETD_SRC:.c=.o)
 
-#VNETD_LIBS:= $(GC_LIB_DIR)/libgc.so.1.0.2
+#VNETD_LIBS:= $(GC_LIB_SO)
 #VNETD_LIBS:= -lgc
-VNETD_LIBS:= $(GC_LIB_DIR)/libgc.a
+VNETD_LIBS:= $(GC_LIB_A)
 
 vnetd: $(VNETD_OBJ)
        $(CC) $(CFLAGS) -o $@ $^ $(VNETD_LIBS) -ldl -lpthread
@@ -95,8 +92,8 @@
        install -m 0755 vnetd $(DESTDIR)$(VNETD_INSTALL_DIR)
 
 clean:
-       -rm -f *.a *.o *~
-       -rm -f vnetd
-       -rm -f $(PROG_DEP)
+       -@$(RM) *.a *.o *~
+       -@$(RM) vnetd
+       -@$(RM) $(PROG_DEP)
 
 -include $(PROG_DEP)
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnetd/vcache.c
--- a/tools/vnet/vnetd/vcache.c Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnetd/vcache.c Fri Aug 26 10:52:53 2005
@@ -44,6 +44,8 @@
 #undef DEBUG
 #include "debug.h"
 
+#include "varp_util.c"
+
 static VarpCache *vcache = NULL;
 
 void IPMessageQueue_init(IPMessageQueue *queue, int maxlen){
@@ -97,16 +99,20 @@
  * @param vmac vmac (in network order)
  * @return 0 on success, error code otherwise
  */
-int varp_send(Conn *conn, uint16_t opcode, uint32_t vnet, Vmac *vmac, uint32_t 
addr){
+int varp_send(Conn *conn, uint16_t opcode, VnetId *vnet, Vmac *vmac, VarpAddr 
*addr){
     int err = 0;
     int varp_n = sizeof(VarpHdr);
     VarpHdr varph = {};
-
-    varph.vnetmsghdr.id     = htons(VARP_ID);
-    varph.vnetmsghdr.opcode = htons(opcode);
-    varph.vnet              = vnet;
-    varph.vmac              = *vmac;
-    varph.addr              = addr;
+#ifdef DEBUG
+    char vnetbuf[VNET_ID_BUF];
+    char addrbuf[VARP_ADDR_BUF];
+#endif
+
+    varph.hdr.id = htons(VARP_ID);
+    varph.hdr.opcode = htons(opcode);
+    varph.vnet = *vnet;
+    varph.vmac = *vmac;
+    varph.addr = *addr;
 
     if(0){
         struct sockaddr_in self;
@@ -117,8 +123,10 @@
     }
     dprintf("> addr=%s opcode=%d\n",
             inet_ntoa(conn->addr.sin_addr), opcode);
-    dprintf("> vnet=%d vmac=" MACFMT " addr=" IPFMT "\n",
-            ntohl(vnet), MAC6TUPLE(vmac->mac), NIPQUAD(addr));
+    dprintf("> vnet=%s vmac=" MACFMT " addr=%s\n",
+            VnetId_ntoa(vnet, vnetbuf),
+            MAC6TUPLE(vmac->mac),
+            VarpAddr_ntoa(addr, addrbuf));
     err = marshal_bytes(conn->out, &varph, varp_n);
     marshal_flush(conn->out);
     dprintf("< err=%d\n", err);
@@ -157,21 +165,24 @@
  */
 void VCEntry_print(VCEntry *ventry){
     if(ventry){
-        char *c, *d;
+        char *state, *flags;
+        char vnetbuf[VNET_ID_BUF];
+        char addrbuf[VARP_ADDR_BUF];
+
         switch(ventry->state){
-        case VCACHE_STATE_INCOMPLETE: c = "INC"; break;
-        case VCACHE_STATE_REACHABLE:  c = "RCH"; break;
-        case VCACHE_STATE_FAILED:     c = "FLD"; break;
-        default:                      c = "UNK"; break;
-        }
-        d = (VCEntry_get_flags(ventry, VCACHE_FLAG_PROBING) ? "P" : " ");
-
-        printf("VENTRY(%p %s %s vnet=%d vmac=" MACFMT " addr=" IPFMT " 
time=%g)\n",
+        case VCACHE_STATE_INCOMPLETE: state = "INC"; break;
+        case VCACHE_STATE_REACHABLE:  state = "RCH"; break;
+        case VCACHE_STATE_FAILED:     state = "FLD"; break;
+        default:                      state = "UNK"; break;
+        }
+        flags = (VCEntry_get_flags(ventry, VCACHE_FLAG_PROBING) ? "P" : " ");
+
+        printf("VENTRY(%p %s %s vnet=%s vmac=" MACFMT " addr=%s time=%g)\n",
                ventry,
-               c, d,
-               ntohl(ventry->key.vnet),
+               state, flags,
+               VnetId_ntoa(&ventry->key.vnet, vnetbuf),
                MAC6TUPLE(ventry->key.vmac.mac),
-               NIPQUAD(ventry->addr),
+               VarpAddr_ntoa(&ventry->addr, addrbuf),
                ventry->timestamp);
     } else {
         printf("VENTRY: Null!\n");
@@ -239,11 +250,11 @@
  * @param vmac virtual MAC address (copied)
  * @return ventry or null
  */
-VCEntry * VCEntry_new(uint32_t vnet, Vmac *vmac){
+VCEntry * VCEntry_new(VnetId *vnet, Vmac *vmac){
     VCEntry *z = ALLOCATE(VCEntry);
     z->state = VCACHE_STATE_INCOMPLETE;
     z->timestamp = time_now();
-    z->key.vnet = vnet;
+    z->key.vnet = *vnet;
     z->key.vmac = *vmac;
     return z;
 }
@@ -256,15 +267,9 @@
  */
 Hashcode vcache_key_hash_fn(void *k){
     VCKey *key = k;
-    Hashcode h;
-    h = hash_2ul(key->vnet,
-                 (key->vmac.mac[0] << 24) |
-                 (key->vmac.mac[1] << 16) |
-                 (key->vmac.mac[2] <<  8) |
-                 (key->vmac.mac[3]      ));
-    h = hash_hul(h, 
-                 (key->vmac.mac[4] <<   8) |
-                 (key->vmac.mac[5]       ));
+    Hashcode h = 0;
+    h = VnetId_hash(h, &key->vnet);
+    h = Vmac_hash(h, &key->vmac);
     return h;
 }
 
@@ -278,8 +283,8 @@
 int vcache_key_equal_fn(void *k1, void *k2){
     VCKey *key1 = k1;
     VCKey *key2 = k2;
-    return (key1->vnet == key2->vnet)
-        && (memcmp(key1->vmac.mac, key2->vmac.mac, ETH_ALEN) == 0);
+    return (VnetId_eq(&key1->vnet , &key2->vnet) &&
+            Vmac_eq(&key1->vmac, &key2->vmac));
 }
 
 void VarpCache_schedule(VarpCache *z);
@@ -351,7 +356,7 @@
  * @param vmac virtual MAC address (copied)
  * @return new entry or null
  */
-VCEntry * VarpCache_add(VarpCache *z, uint32_t vnet, Vmac *vmac){
+VCEntry * VarpCache_add(VarpCache *z, VnetId *vnet, Vmac *vmac){
     VCEntry *ventry;
     HTEntry *entry;
 
@@ -378,8 +383,8 @@
  * @param vmac virtual MAC addres
  * @return entry found or null
  */
-VCEntry * VarpCache_lookup(VarpCache *z, uint32_t vnet, Vmac *vmac){
-    VCKey key = { .vnet = vnet, .vmac = *vmac };
+VCEntry * VarpCache_lookup(VarpCache *z, VnetId *vnet, Vmac *vmac){
+    VCKey key = { .vnet = *vnet, .vmac = *vmac };
     VCEntry *ventry;
     ventry = HashTable_get(z->table, &key);
     return ventry;
@@ -389,13 +394,15 @@
     dprintf(">\n");
     if(VCEntry_get_flags(ventry, VCACHE_FLAG_LOCAL_PROBE)){
         dprintf("> local probe\n");
-        varp_send(vnetd->bcast_conn, VARP_OP_REQUEST, ventry->key.vnet, 
&ventry->key.vmac, ventry->addr);
+        varp_send(vnetd->bcast_conn, VARP_OP_REQUEST,
+                  &ventry->key.vnet, &ventry->key.vmac, &ventry->addr);
     }
     if(VCEntry_get_flags(ventry, VCACHE_FLAG_REMOTE_PROBE)){
         ConnList *l;
         dprintf("> remote probe\n");
         for(l = vnetd->connections; l; l = l->next){
-            varp_send(l->conn, VARP_OP_REQUEST, ventry->key.vnet, 
&ventry->key.vmac, ventry->addr); 
+            varp_send(l->conn, VARP_OP_REQUEST,
+                      &ventry->key.vnet, &ventry->key.vmac, &ventry->addr); 
         }
                 
     }
@@ -440,7 +447,8 @@
         IPMessage *msg;
         while((msg = IPMessageQueue_pop(&ventry->queue))){
             dprintf("> announce\n");
-            varp_send(msg->conn, VARP_OP_ANNOUNCE, ventry->key.vnet, 
&ventry->key.vmac, ventry->addr);
+            varp_send(msg->conn, VARP_OP_ANNOUNCE,
+                      &ventry->key.vnet, &ventry->key.vmac, &ventry->addr);
         }
     }
   exit:
@@ -459,7 +467,7 @@
     VCEntry *ventry;
 
     dprintf(">\n");
-    ventry = VarpCache_lookup(z, varph->vnet, &varph->vmac);
+    ventry = VarpCache_lookup(z, &varph->vnet, &varph->vmac);
     if(ventry){
         err = VCEntry_update(ventry, msg, varph, state);
     } else {
@@ -503,14 +511,14 @@
  * @param local whether it's local or not
  */
 void vcache_forward_varp(VarpHdr *varph, int local){
-    uint16_t opcode = ntohs(varph->vnetmsghdr.opcode);
+    uint16_t opcode = ntohs(varph->hdr.opcode);
     if(local){
         ConnList *l;
         for(l = vnetd->connections; l; l = l->next){
-            varp_send(l->conn, opcode, varph->vnet, &varph->vmac, 
varph->addr); 
+            varp_send(l->conn, opcode, &varph->vnet, &varph->vmac, 
&varph->addr); 
         }
     } else {
-        varp_send(vnetd->bcast_conn, opcode, varph->vnet, &varph->vmac, 
varph->addr);
+        varp_send(vnetd->bcast_conn, opcode, &varph->vnet, &varph->vmac, 
&varph->addr);
     }
 }
 
@@ -531,13 +539,13 @@
 #else
 int vcache_handle_request(IPMessage *msg, VarpHdr *varph, int local){
     int err = -ENOENT;
-    uint32_t vnet;
+    VnetId *vnet;
     Vmac *vmac;
     VCEntry *ventry = NULL;
     int reply = 0;
 
     dprintf(">\n");
-    vnet = htonl(varph->vnet);
+    vnet = &varph->vnet;
     vmac = &varph->vmac;
     ventry = VarpCache_lookup(vcache, vnet, vmac);
     if(!ventry){
@@ -605,13 +613,18 @@
     VarpHdr *varph = &vmsg->varp.varph;
 
     dprintf(">\n");
-    if(1){
+#ifdef DEBUG
+    {
+        char vnetbuf[VNET_ID_BUF];
         dprintf("> src=%s:%d\n", inet_ntoa(msg->saddr.sin_addr), 
ntohs(msg->saddr.sin_port));
         dprintf("> dst=%s:%d\n", inet_ntoa(msg->daddr.sin_addr), 
ntohs(msg->daddr.sin_port));
-        dprintf("> opcode=%d vnet=%u vmac=" MACFMT "\n",
-                ntohs(varph->opcode), ntohl(varph->vnet), 
MAC6TUPLE(varph->vmac.mac));
-    }
-    switch(ntohs(varph->vnetmsghdr.opcode)){
+        dprintf("> opcode=%d vnet=%s vmac=" MACFMT "\n",
+                ntohs(varph->opcode),
+                VnetId_ntoa(&varph->vnet, vnetbuf),
+                MAC6TUPLE(varph->vmac.mac));
+    }
+#endif
+    switch(ntohs(varph->hdr.opcode)){
     case VARP_OP_REQUEST:
         err = vcache_handle_request(msg, varph, local);
         break;
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnetd/vcache.h
--- a/tools/vnet/vnetd/vcache.h Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnetd/vcache.h Fri Aug 26 10:52:53 2005
@@ -93,7 +93,7 @@
 /** Key for varp cache entries. */
 typedef struct VCKey {
     /** Vnet id (network order). */
-    uint32_t vnet;
+    VnetId vnet;
     /** Virtual MAC address. */
     Vmac vmac;
 } VCKey;
@@ -103,7 +103,7 @@
     VCKey key;
 
     /** Care-of address for the key. */
-    uint32_t addr;
+    VarpAddr addr;
 
     /** Alias coa if we are a gateway. */
     //uint32_t gateway;
@@ -111,7 +111,7 @@
     //uint32_t encaps;
 
     /** Where this entry came from. */
-    uint32_t source;
+    VarpAddr source;
 
     /** Last-updated timestamp. */
     double timestamp;
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnetd/vnetd.c
--- a/tools/vnet/vnetd/vnetd.c  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnetd/vnetd.c  Fri Aug 26 10:52:53 2005
@@ -112,7 +112,6 @@
 #include <sys/wait.h>
 #include <sys/select.h>
 
-//#include </usr/include/linux/ip.h> // For struct iphdr;
 #include <linux/ip.h> // For struct iphdr;
 
 #include <linux/if_ether.h>
@@ -492,22 +491,16 @@
     dprintf("> addr=%s protocol=%d n=%d\n",
             inet_ntoa(conn->addr.sin_addr), protocol, data_n);
     string_stream_init(io, &sdata, buf, sizeof(buf));
-    dprintf("> 10\n");
     err = marshal_uint16(io, VNET_FWD_ID);
     if(err < 0) goto exit;
-    dprintf("> 20\n");
     err = marshal_uint16(io, 0);
     if(err < 0) goto exit;
-    dprintf("> 30\n");
     err = marshal_uint16(io, protocol);
     if(err < 0) goto exit;
-    dprintf("> 40\n");
     err = marshal_uint16(io, data_n);
     if(err < 0) goto exit;
-    dprintf("> 50\n");
     err = marshal_bytes(io, data, data_n);
     if(err < 0) goto exit;
-    dprintf("> 60 bytes=%d\n", IOStream_get_written(io));
     err = IOStream_write(conn->out, buf, IOStream_get_written(io));
     IOStream_flush(conn->out);
   exit:
@@ -978,7 +971,7 @@
     int err = 0;
     uint32_t addr = INADDR_ANY;
     uint16_t port = vnetd->port;
-    int flags = VSOCK_BIND | VSOCK_REUSE;
+    int flags = (VSOCK_BIND | VSOCK_REUSE);
     err = create_socket(SOCK_DGRAM, addr, port, flags, val);
     return err;
 }
@@ -1162,7 +1155,7 @@
     err = vnetd_broadcast_conn(vnetd, &vnetd->bcast_conn);
     if(err < 0) goto exit;
     { 
-        int flags = VSOCK_BROADCAST | VSOCK_MULTICAST;
+        int flags = (VSOCK_BROADCAST | VSOCK_MULTICAST);
         uint32_t mcaddr = vnetd->mcast_addr.sin_addr.s_addr;
 
         err = vnetd_raw_socket(IPPROTO_ETHERIP, flags, mcaddr, 
&vnetd->etherip_sock);
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/vnetd/vnetd.h
--- a/tools/vnet/vnetd/vnetd.h  Fri Aug 26 10:51:10 2005
+++ b/tools/vnet/vnetd/vnetd.h  Fri Aug 26 10:52:53 2005
@@ -20,6 +20,7 @@
 #include <asm/types.h>
 #include <linux/if_ether.h>
 #include "if_varp.h"
+#include "varp_util.h"
 
 #include "connection.h"
 #include "sxpr.h"
diff -r a43cc4e06814 -r 6bad5eb72ce0 tools/vnet/INSTALL
--- a/tools/vnet/INSTALL        Fri Aug 26 10:51:10 2005
+++ /dev/null   Fri Aug 26 10:52:53 2005
@@ -1,31 +0,0 @@
-To compile and install run "make install"; if it fails or you need to 
reinstall 
-run "make clean" first or the build will fail, at least that is what I have 
-found under 2.6.10.
-
-Other important items:
-1)     You will need to have your xen0 kernel compiled with HMAC_SUPPORT 
-       2.6.x = (MAIN MENU: Cryptographic Options -> HMAC Support)
-       BEFORE running "make install".
-
-2)     You will want at least some of the other alogorithms listed under
-       "Cryptographic Options" for the kernel compiled as modules.
-
-3)     You will want the networking IPsec/VLAN options compiled in as modules
-       2.6.x = (MAIN MENU: Device Drivers -> Networking Support -> 
-                               Networking Options ->
-                                       IP: AH transformation
-                                       IP: ESP transformation
-                                       IP: IPComp transformation 
-                                       IP: tunnel transformation
-
-                                       IPsec user configuration interface
-       
-                                       802.1Q VLAN Support
-
-4)     The module (vnet_module) will not properly load from the command line
-       with a "modprobe vnet_module".  Use network-vnet to properly configure
-       your system and load the module for you.
-
-Please refer to the additional documentation found in tools/vnet/doc for
-proper syntax and config file parameters.
-

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Vnet update., Xen patchbot -unstable <=