[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.