Vnet update.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Fri, 26 Aug 2005 10:52:53 +0000 (10:52 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Fri, 26 Aug 2005 10:52:53 +0000 (10:52 +0000)
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@hp.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
45 files changed:
tools/vnet/00INSTALL
tools/vnet/INSTALL [deleted file]
tools/vnet/Makefile
tools/vnet/doc/vnet-module.txt
tools/vnet/doc/vnet-xend.txt
tools/vnet/examples/Makefile
tools/vnet/examples/network-vnet
tools/vnet/examples/vnet97.sxp
tools/vnet/examples/vnet98.sxp
tools/vnet/examples/vnet99.sxp
tools/vnet/libxutil/Makefile
tools/vnet/libxutil/debug.h
tools/vnet/libxutil/sxpr.c
tools/vnet/libxutil/sxpr.h
tools/vnet/libxutil/sxpr_parser.c
tools/vnet/libxutil/sxpr_parser.h
tools/vnet/libxutil/sys_string.c
tools/vnet/libxutil/sys_string.h
tools/vnet/vnet-module/00README
tools/vnet/vnet-module/Makefile
tools/vnet/vnet-module/Makefile-2.4
tools/vnet/vnet-module/Makefile-2.6
tools/vnet/vnet-module/Makefile.ver
tools/vnet/vnet-module/Makefile.vnet
tools/vnet/vnet-module/etherip.c
tools/vnet/vnet-module/if_etherip.h
tools/vnet/vnet-module/if_varp.h
tools/vnet/vnet-module/skb_util.h
tools/vnet/vnet-module/tunnel.c
tools/vnet/vnet-module/tunnel.h
tools/vnet/vnet-module/varp.c
tools/vnet/vnet-module/varp.h
tools/vnet/vnet-module/varp_socket.c
tools/vnet/vnet-module/vif.c
tools/vnet/vnet-module/vif.h
tools/vnet/vnet-module/vnet.c
tools/vnet/vnet-module/vnet.h
tools/vnet/vnet-module/vnet_dev.c
tools/vnet/vnet-module/vnet_dev.h
tools/vnet/vnet-module/vnet_ioctl.c
tools/vnet/vnetd/Makefile
tools/vnet/vnetd/vcache.c
tools/vnet/vnetd/vcache.h
tools/vnet/vnetd/vnetd.c
tools/vnet/vnetd/vnetd.h

index 1c76986d831cb7761fc0259c9f2ff8da89e7c7b2..bc399bb7d107c216b7e803091007afa27fb8874b 100644 (file)
@@ -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.
+
+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:
 
-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
+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 @@ Other important items:
        
                                        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 --git a/tools/vnet/INSTALL b/tools/vnet/INSTALL
deleted file mode 100644 (file)
index 8ece553..0000000
+++ /dev/null
@@ -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.
-
index a5156c4687cad359a79ef1113a2deced8781ef77..8c80dd3c895b43f28e348994dc346e6524d13729 100644 (file)
@@ -1,19 +1,22 @@
+# -*- 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 @@ gc: gc.tar.gz
        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
+
+submak = $(MAKE) -C $(patsubst %-$(1),%,$(@)) $(1)
+subtgt = $(patsubst %,%-$(1),$(SUBDIRS))
+
+%-all:
+       $(call submak,all)
 
-gc-pristine:
-       -rm -rf gc?.? gc
+%-clean:
+       -$(call submak,clean)
 
-libxutil:
-       $(MAKE) -C libxutil
+%-install:
+       $(call submak,install)
 
-vnetd: gc-install
-       $(MAKE) -C vnetd
+compile: $(call subtgt,all)
 
-vnet-module:
-       $(MAKE) -C vnet-module
+install: DESTDIR=
+install: dist
 
-install: compile
-       $(MAKE) -C libxutil install
-       $(MAKE) -C vnetd install
-       $(MAKE) -C vnet-module install
-       $(MAKE) -C examples install
+dist: compile $(call subtgt,install)
 
-clean:
-       -$(MAKE) -C libxutil clean
-       -$(MAKE) -C vnetd clean
-       -$(MAKE) -C vnet-module clean
-       -rm -rf gc?.? gc
+clean: $(call subtgt,clean)
+       -@$(RM) -r build
 
-pristine: clean gc-pristine
+pristine: clean
+       -@$(RM) gc.tar.gz
index b9c8ac57c3009437c84838cbb94d2b85dec90409..32ac90b4ff69d42b3da9b0a48d2016a1e6da4874 100644 (file)
@@ -1,21 +1,34 @@
 Vnet Module Command Interface
 Mike Wray <mike.wray@hp.com>
-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>))
 
 Delete the vnet with id <id>.
@@ -31,12 +44,18 @@ on vnet <vnetid>.
 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:
 
 echo '(vnet.add (id 11) (security auth))' > /proc/vnet/policy
index 35763903343fc8b0b87e660f83cf359d063c7da6..f3ff3b5e4f04fa94e90847ce3298ad10f92bbd30 100644 (file)
@@ -3,11 +3,13 @@ Vnets: Virtual Networks for Virtual Machines
 
 Mike Wray <mike.wray@hp.com>
 
+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 @@ Configure the network script:
 
 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 @@ For example, if vnet97.sxp contains:
 
 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 @@ In sxp:
 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 @@ Here's the full config for a vm on vnet 97, using ip addr 10.0.0.12:
   (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 @@ If you run another vm on the same vnet:
   (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)))
 )
 
index d0cc4a6e57cee787dd5ecf1dfdcdb0fa66c69172..7128678d0161bbd04bf6cde28f75033e17502c0d 100644 (file)
@@ -3,10 +3,13 @@
 
 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
index 4b388bd3f9f501283b88ac8d47a3e4a8731788da..d644a48333a57a5fd0a3337f9cae7e3784a1c00c 100755 (executable)
 #!/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 
-
-# 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
+case ${1} in
     start)
-        op_start
-        ;;
-    
-    stop)
-        op_stop
+        ${scriptdir}/vnet-insert
         ;;
-
-    status)
-        show_status ${netdev} ${bridge}
-       ;;
-
-    *)
-       echo 'Unknown command: ' ${OP}
-       echo 'Valid commands are: start, stop, status'
-       exit 1
 esac
+
+${scriptdir}/network-bridge "$@"
index ef0784369bcbe69b75b7c466422b69cc65d2ae09..d0128988d82803eb18466373edf89d1f2619e6ca 100644 (file)
@@ -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))
index 807d56daaffa69017a89fdbc68ecd5c1ea60f771..89db6f078bac95c13e70dcbcf9e94e345c8f8fa7 100644 (file)
@@ -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))
index ffce1d7fbf906f1b8b0a9e9c455681460837f668..61cd342361fd2ebb3346437af14b5bb56b5e5533 100644 (file)
@@ -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))
index 5e9adaac8b7218fe560bde7a25e769f07a45ff33..40b1be6a6d9462b51b4845ed456def347874d963 100644 (file)
@@ -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 += gzip_stream.c
 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 @@ LIB_OBJS := $(LIB_SRCS:.c=.o)
 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.so.$(MAJOR).$(MINOR)
 LIB      += libxutil.a
 
 all: build
+
 build: check-for-zlib
        $(MAKE) $(LIB)
 
@@ -70,8 +76,8 @@ install: build
        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)
index 1f5a19d54d06ad9d7ab335895099cdfd0ad4b099..78c801d9885e139de6d218abd68520304cadf884 100644 (file)
@@ -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
 
index d264527f25759679817a05c9155b7015ad11f948..e107b9b8b372a82039e14e9fa08946b172f1cef4 100644 (file)
@@ -405,7 +405,6 @@ Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
 #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 atom_new(char *name){
     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);
index c9acd7b25f301aaa599ebc00b52508477e4bc4aa..baca66ac20f2ffe1cb21da97a0e22125ae658311 100644 (file)
@@ -228,7 +228,9 @@ static inline Sxpr OBJP(int ty, void *val){
  *
  * @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 @@ static inline Sxpr OBJP(int ty, void *val){
  * @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.
  *
index f93d3505b2961b9f8ee3db069ac063f23fbcf5ad..c665241f70051b32472f264e1e880accf1496756 100644 (file)
@@ -472,7 +472,14 @@ int Parser_intern(Parser *p){
 }
 
 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);
 }
 
index 591ed955727013222bb4f9a59600d1c7ed443721..68efcc8ed2f3979cefad52e21d526925864356ce 100644 (file)
@@ -89,15 +89,17 @@ typedef enum {
 
 
 /** 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 @@ inline static void Parser_flags_raise(Parser *in, int flags){
  * @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,10 +116,14 @@ inline static void Parser_flags_lower(Parser *in, int flags){
  *
  * @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);
 extern Parser * Parser_new(void);
 extern int Parser_input(Parser *p, char *buf, int buf_n);
index 22a8ae3688ab16e0287d5cc2989e45556c224bba..46db2a3226d1a4167b7d0661892401ece356b9db 100644 (file)
 #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.
  *
index 88d9d8db6173ae9ee224a66091d8c6480d5c52a8..b4cd506998c553c44379380f93bfc67853a200f4 100644 (file)
@@ -32,6 +32,8 @@
 #include <stdarg.h>
 #include "allocate.h"
 
+extern char *strerror(int err);
+
 #if 0
 static inline int tolower(int c){
     return (c>='A' && c<='Z' ? (c-'A')+'a' : c);
index 3a798985b3bc9e0c47852460a03248224fb75c5a..651164ca9f8963cb28a07b3b1335c104be299d08 100644 (file)
@@ -6,11 +6,11 @@ The vnet module can be compiled for 2.4 or 2.6 series kernels.
 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
 
index 9d33c70981f1f657d86056896e46ac6cf56de4ff..417ce8866ce0b245bdb6574db82820815905a64c 100644 (file)
 # 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 @@ vnet_module-objs += $(VNET_LIB_OBJ)
 # 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_srcs = $(foreach file,$(VNET_LIB_SRC),$(src)/$(file))
 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
index 5781fca09710d994afd021fd52c042a9b2f30116..7ece1c51f530bf40e27850a0b44a36a399812a12 100644 (file)
@@ -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 @@ VNET_OBJ += $(VNET_LIB_OBJ)
 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-trigraphs
 CFLAGS += -Wno-unused-function
 CFLAGS += -Wno-unused-parameter 
 
+CFLAGS += -g
 CFLAGS += -O2
 CFLAGS += -fno-strict-aliasing 
 CFLAGS += -fno-common 
@@ -90,8 +91,8 @@ TAGS:
 
 .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)
index 053391e572f0daab1d8e01db966e11106a33eb28..b4115af3c143a659c7b7154014280fd1d0c771bf 100644 (file)
@@ -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 @@ module modules:
 
 .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
index 586c26ee8e6dc4a0bda9b9738c4dec2c583d89c4..ff01be10e112c3d054ea8dce36e6fd588c94d17a 100644 (file)
 # 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)
index 2bc07b8f9201a7b1c7f3273cca983d12a03ee853..af36db8a55d1dc6b1d00050ee623030e5b21c82e 100644 (file)
@@ -24,8 +24,6 @@ else
 SRC_DIR=$(src)/
 endif
 
-LIB_DIR := $(SRC_DIR)../libxutil
-
 VNET_SRC :=
 VNET_SRC += esp.c
 VNET_SRC += etherip.c
index 05486ed5a23ed33d9584a97fcc538c4de1fab062..25481070baf057152e79b6da4ee2029cc8c5c20e 100644 (file)
@@ -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"
  * 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)
-#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)
+ * @@param vnet (in net order)
  */
-int etheriphdr_get_vnet(struct etheriphdr *hdr){
+void etheriphdr_get_vnet(struct etheriphdr *hdr, VnetId *vnet){
 #ifdef CONFIG_ETHERIP_EXT
-    return ntohl(hdr->vnet);
+    *vnet = *(VnetId*)hdr->vnet;
 #else
-    return hdr->reserved;
+    *vnet = (VnetId){};
+    vnet->u.vnet16[7] = (unsigned short)hdr->reserved;
+    
 #endif
 }
 
@@ -76,15 +73,15 @@ int etheriphdr_get_vnet(struct etheriphdr *hdr){
  * Also sets the etherip version.
  *
  * @param hdr header
- * @param vnet vnet label (in host order)
+ * @param vnet vnet label (in net order)
  */
-void etheriphdr_set_vnet(struct etheriphdr *hdr, int vnet){
+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 @@ static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
     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 @@ static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
     //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 @@ static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
     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 @@ static int etherip_protocol_recv(struct sk_buff *skb){
     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 @@ static int etherip_protocol_recv(struct sk_buff *skb){
         // 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 @@ static int etherip_protocol_recv(struct sk_buff *skb){
     }
     // Assume skb->data points at etherip header.
     etheriph = (void*)skb->data;
+    if(etheriph->version != ETHERIP_VERSION){
+        wprintf("> Bad etherip version=%d src=%u.%u.%u.%u\n",
+                etheriph->version,
+                NIPQUAD(saddr));
+        err = -EINVAL;
+        goto exit;
+    }
     if(!pskb_may_pull(skb, etherip_n)){
-        wprintf("> Malformed skb\n");
+        wprintf("> Malformed skb (etherip) src=%u.%u.%u.%u\n",
+                NIPQUAD(saddr));
         err = -EINVAL;
         goto exit;
     }
-    vnet = etheriphdr_get_vnet(etheriph);
-    dprintf("> Rcvd skb=%p vnet=%d\n", skb, vnet);
+    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 @@ static int etherip_protocol_recv(struct sk_buff *skb){
     // 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 @@ static int etherip_protocol_recv(struct sk_buff *skb){
 #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 @@ static int etherip_protocol_recv(struct sk_buff *skb){
         }
         dst_release(skb->dst);
         skb->dst = NULL;
+
 #ifdef CONFIG_NETFILTER
         nf_conntrack_put(skb->nfct);
         skb->nfct = NULL;
@@ -321,7 +345,7 @@ static int etherip_protocol_recv(struct sk_buff *skb){
 
     //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);
index 272c345d781e5b9710ae04f57ca7075e511260be..43194cc4ba41b81cf494d173e5afaa818212fa7a 100644 (file)
  */
 #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 @@ struct etheriphdr
 };
 #endif
 
+
 #ifndef IPPROTO_ETHERIP
 #define IPPROTO_ETHERIP 97
 #endif
 
-/*----------------------------------------------------------------------------*/
-
 #endif /* ! _VNET_IF_ETHERIP_H_ */
index c4b752ac49db63eeb90a86043bf8a594789d3dde..e37c3d439401e009852be4cad9ba6da570d643a9 100644 (file)
 #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,24 +38,40 @@ enum {
     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
 
 /** UDP port to use for varp protocol. */
 #define VARP_PORT           1798
 
-
-
-#endif  /* ! _VNET_IF_VARP_H */
+#endif /* ! _VNET_IF_VARP_H */
index d3e9a1e6d90909c45b489f3a054e3da6e1519df5..7f31cb5dbd7a5b05cf903fc73e0162fff1592fcc 100644 (file)
@@ -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 int skb_scatterlist(struct sk_buff *skb, struct scatterlist *sg,
 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
index 2ea261bf6fbb85dd3bcd256a20c04b9643d8654a..f9af9a3e2eef067cdd0a2a18109d13f7c8950b54 100644 (file)
@@ -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 @@ void Tunnel_print(Tunnel *tunnel){
     }
 }
 
-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 @@ int Tunnel_create(TunnelType *type, u32 vnet, u32 addr, Tunnel *base, Tunnel **v
         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 @@ int Tunnel_create(TunnelType *type, u32 vnet, u32 addr, Tunnel *base, Tunnel **v
     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 @@ HashTable *tunnel_table = NULL;
 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 @@ int Tunnel_init(void){
  * @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_del(Tunnel *tunnel){
  */
 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);
-        err = tunnel->type->send(tunnel, skb);
         // Must not refer to skb after sending - might have been freed.
+        err = tunnel->type->send(tunnel, skb);
         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 @@ int __init tunnel_module_init(void){
 }
 
 void __exit tunnel_module_exit(void){
+    if(tunnel_table){
+        HashTable_free(tunnel_table);
+        tunnel_table = NULL;
+    }
 }
index e2241e82d4e273a446f65927bd4193578a501f5f..b98f35407a18bb18ada77cb9feec80b69f7242d5 100644 (file)
@@ -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 @@ typedef struct TunnelStats {
 } TunnelStats;
 
 typedef struct TunnelKey {
-    u32 vnet;
-    u32 addr;
+    VnetId vnet;
+    VarpAddr addr;
 } TunnelKey;
 
 typedef struct Tunnel {
@@ -87,13 +88,15 @@ static inline void Tunnel_incref(Tunnel *tunnel){
 }
 
 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);
index f7bdf81d9703d708d115564f7ac19f39cb684e49..5de3d332546da8830615e3d217b9346b437ccbe4 100644 (file)
 #include <tunnel.h>
 #include <vnet.h>
 #include <vif.h>
-#include <varp.h>
 #include <if_varp.h>
+#include <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.
  *
  * Handles virtual ARP requests for vnet/vmac.
@@ -121,8 +115,8 @@ enum {
 
 /** 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 @@ typedef struct VarpEntry {
     /** 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 @@ typedef struct VarpEntry {
     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 @@ static char *varp_mcaddr = NULL;
 /** 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,8 +187,11 @@ char *varp_device = DEVICE;
 #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).
  */
 void varp_dprint(void){
@@ -209,14 +200,53 @@ void varp_dprint(void){
 #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,19 +276,44 @@ int vnet_get_device_address(struct net_device *dev, u32 *addr){
     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;
 }
 
+#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
 #define LL_RESERVED_SPACE(dev) \
@@ -270,12 +325,12 @@ int vnet_get_device_address(struct net_device *dev, u32 *addr){
  * @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 @@ int varp_send(u16 opcode, struct net_device *dev, struct sk_buff *skbin,
     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;
+#if defined(DEBUG)
+    char vnetbuf[VNET_ID_BUF];
+#endif
 
-    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;
+    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;
-        sport = skbin->h.uh->dest;
         daddr = skbin->nh.iph->saddr;
-        //dport = skbin->h.uh->source;
-        dport = varp_port;
+        dmac = eth_hdr(skbin)->h_source;
+        sport = skbin->h.uh->dest;
     } 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 @@ int varp_send(u16 opcode, struct net_device *dev, struct sk_buff *skbin,
     // 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 @@ int varp_send(u16 opcode, struct net_device *dev, struct sk_buff *skbin,
 /** 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 varp_solicit(struct sk_buff *skb, VnetId *vnet){
     int err = 0;
-    dprintf("> skb=%p\n", skb);
-    varp_dprint();
     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 @@ int VarpEntry_set_flags(VarpEntry *z, int flags, int set){
  */
 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" : " ");
+        flags = (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",
+        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_free(VarpEntry *z){
 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_incref(VarpEntry *z){
  */
 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 @@ void VarpEntry_error(VarpEntry *ventry){
 
 /** 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 @@ static void varp_timer_fn(unsigned long arg){
                 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 @@ static void varp_error_fn(VarpEntry *ventry, struct sk_buff *skb){
  * @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 @@ VarpEntry * VarpEntry_new(u32 vnet, Vmac *vmac){
         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 @@ VarpEntry * VarpEntry_new(u32 vnet, Vmac *vmac){
  */
 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 @@ Hashcode varp_key_hash_fn(void *k){
 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 @@ void VarpTable_schedule(VarpTable *z){
  */
 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 @@ void VarpTable_print(VarpTable *z){
     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 @@ void VarpTable_print(VarpTable *z){
         VarpEntry_unlock(ventry, vflags);
     }
     VarpTable_read_unlock(z, flags);
-    //dprintf("<\n");
 }
 
 /** Create a varp table.
@@ -735,7 +787,7 @@ VarpTable * VarpTable_new(void){
  * @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 @@ VarpEntry * VarpTable_add(VarpTable *z, u32 vnet, Vmac *vmac){
 
     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 @@ int VarpTable_remove(VarpTable *z, VarpEntry *ventry){
  * @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);
-    VarpTable_read_unlock(z, flags);
     if(ventry) VarpEntry_incref(ventry);
+    VarpTable_read_unlock(z, flags);
     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 @@ VarpEntry * VarpTable_lookup(VarpTable *z, u32 vnet, Vmac *vmac){
 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 @@ int VarpEntry_send(VarpEntry *ventry, struct sk_buff *skb){
  * 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 VarpEntry_resolve(VarpEntry *ventry, struct sk_buff *skb){
     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 @@ int VarpEntry_resolve(VarpEntry *ventry, struct sk_buff *skb){
         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 @@ int VarpEntry_resolve(VarpEntry *ventry, struct sk_buff *skb){
             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 @@ void VarpEntry_process_queue(VarpEntry *ventry){
  * @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 @@ int VarpTable_update(VarpTable *z, int vnet, Vmac *vmac, u32 addr,
  * @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);
+    return VarpTable_update(z, &varph->vnet, &varph->vmac, &varph->addr, state, 0);
 }
 
-int varp_update(int vnet, unsigned char *vmac, u32 addr){
+int varp_update(VnetId *vnet, unsigned char *vmac, VarpAddr *addr){
     if(!varp_table){
         return -ENOSYS;
     }
@@ -971,7 +1030,6 @@ void VarpTable_sweep(VarpTable *z, int all){
     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 @@ void VarpTable_sweep(VarpTable *z, int all){
         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 @@ void VarpTable_sweep(VarpTable *z, int all){
  */
 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 @@ int varp_announce_vif(struct net_device *dev, Vif *vif){
         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 @@ int varp_handle_message(struct sk_buff *skb){
        (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 @@ int varp_handle_message(struct sk_buff *skb){
         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 @@ int varp_handle_message(struct sk_buff *skb){
         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 @@ int varp_handle_message(struct sk_buff *skb){
 /** 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 varp_set_mcast_addr(uint32_t addr){
     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 @@ static void varp_init_mcast_addr(char *s){
  */
 int varp_init(void){
     int err = 0;
-    struct net_device *dev = NULL;
     
     dprintf(">\n");
     varp_table = VarpTable_new();
@@ -1200,18 +1293,10 @@ int varp_init(void){
         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;
 }
index 4aab7fc522aee9bf868e89b041bbefee6b86c2aa..21a6e9c9abe3b5ec40c8e2956c2bfaf6bebfa922 100644 (file)
 
 #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,30 +30,27 @@ struct net_device;
 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.
  */
index 339d42b776c7995bf5e6784aab4e7c781ee3e3d1..13a70f970dc739ac06a85382aab2df188eb1ad12 100644 (file)
@@ -177,7 +177,7 @@ int getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len){
 
 /*============================================================================*/
 /** Socket flags. */
-enum {
+enum VsockFlag {
     VSOCK_REUSE     =  1,
     VSOCK_BIND      =  2,
     VSOCK_CONNECT   =  4,
@@ -256,28 +256,13 @@ int setsock_broadcast(int sock, int bcast){
  */
 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 @@ int setsock_multicast_ttl(int sock, uint8_t ttl){
 }
 
 /** 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 @@ int create_socket(int socktype, uint32_t saddr, uint32_t port, int flags, int *v
 /** 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 @@ int varp_mcast_open(uint32_t mcaddr, uint32_t saddr, uint16_t port, int *val){
         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_mcast_open(uint32_t mcaddr, uint32_t saddr, uint16_t port, int *val){
  */
 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 @@ int varp_main(void *arg){
     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 @@ void varp_close(void){
 /** 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;
index 43d864c1a116d9f9e5ea340c9b5a9efe1916d342..d3ee321fd15fb31c06ed6dec8770d1293229e6f7 100644 (file)
@@ -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>
 #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"
 
 /** 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,19 +96,12 @@ void vif_incref(Vif *vif){
  */
 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 @@ Hashcode vif_key_hash_fn(void *k){
 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 @@ static void vif_entry_free_fn(HashTable *table, HTEntry *entry){
  * @param mac MAC address
  * @return 0 on success, -ENOENT otherwise
  */
-int vif_lookup(int vnet, Vmac *vmac, Vif **vif){
+int vif_lookup(VnetId *vnet, Vmac *vmac, Vif **vif){
     int err = 0;
-    VifKey key = {};
+    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 @@ int vif_lookup(int vnet, Vmac *vmac, Vif **vif){
         *vif = NULL;
         err = -ENOENT;
     }
-    //dprintf("< err=%d addr=" IPFMT "\n", err, NIPQUAD(*coaddr));
+    vif_read_unlock(flags);
     return err;
 }
 
@@ -143,10 +162,12 @@ int vif_lookup(int vnet, Vmac *vmac, Vif **vif){
  * @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 @@ int vif_add(int vnet, Vmac *vmac, Vif **val){
         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 @@ int vif_add(int vnet, Vmac *vmac, Vif **val){
  * @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));
-    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 vif_remove(VnetId *vnet, Vmac *vmac){
     int err = 0;
+    VifKey key = { .vnet = *vnet, .vmac = *vmac };
+    unsigned long flags;
 
-    err = vif_lookup(vnet, vmac, vif);
-    if(err && create){
-        err = vif_add(vnet, vmac, vif);
-    }
+    vif_write_lock(flags);
+    err = HashTable_remove(vif_table, &key);
+    vif_write_unlock(flags);
     return err;
 }
 
@@ -200,15 +215,15 @@ void vif_purge(void){
     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 @@ int vif_create(int vnet, Vmac *vmac, Vif **vif){
     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 @@ int vif_init(void){
         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;
+    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");
   exit:
     if(err < 0) wprintf("< err=%d\n", err);
     dprintf("< err=%d\n", err);
index 379725189ccc928211e8335652b39b2ba4eef0df..d43a868f86d71b963187bfb5226bbe0e96b1f8f7 100644 (file)
@@ -24,12 +24,12 @@ struct net_device;
 
 /** 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 @@ typedef struct Vif {
 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);
index 6027cd66045671171e90cc84be7e5b53b332439b..0d3e1673f1399300497575a5370220df1eb78826 100644 (file)
@@ -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 @@ int vnet_security_default = SA_AUTH ; //| SA_CONF;
 /** 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 @@ static HashTable *vnet_table = NULL;
 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);
     }
@@ -103,6 +103,28 @@ void Vnet_incref(Vnet *info){
     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.
  *
  * @param info return parameter for vnet
@@ -129,7 +151,7 @@ int Vnet_add(Vnet *info){
     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 @@ int Vnet_add(Vnet *info){
  * @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 @@ int Vnet_del(vnetid_t vnet){
  * @param info return parameter for vnet
  * @return 0 on sucess, -ENOENT if no vnet found
  */
-int Vnet_lookup(vnetid_t vnet, Vnet **info){
+int Vnet_lookup(VnetId *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));
+    *info = HashTable_get(vnet_table, vnet);
     if(*info){
         Vnet_incref(*info);
     } else {
         err = -ENOENT;
     }
-    dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -191,24 +210,35 @@ static void vnet_entry_free_fn(HashTable *table, HTEntry *entry){
  */
 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;
 }
 
+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.
  *
  * @return 0 on success, error code otherwise
@@ -216,18 +246,18 @@ static int vnet_setup(void){
 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 @@ int vnet_init(void){
     if(err) goto exit;
     err = vif_init();
   exit:
-    if(err < 0) wprintf("< err=%d\n", err);
     return err;
 }
 
@@ -248,50 +277,28 @@ void vnet_exit(void){
     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 @@ inline int skb_xmit(struct sk_buff *skb){
  *
  * @todo fixme
  */
-int vnet_skb_send(struct sk_buff *skb, u32 vnet){
+int vnet_skb_send(struct sk_buff *skb, VnetId *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);
-        }
+    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 @@ int vnet_skb_send(struct sk_buff *skb, u32 vnet){
  * @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 @@ int vnet_sa_create(u32 spi, int protocol, u32 addr, SAState **sa){
  *
  * @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 @@ int vnet_check_context(int vnet, SkbContext *context, Vnet **val){
         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 int sa_tunnel_open(Tunnel *tunnel){
  */
 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 void sa_tunnel_close(Tunnel *tunnel){
 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 @@ static int sa_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
     }
     err = SAState_send(sa, skb, tunnel->base);
   exit:
-    //dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -638,7 +509,7 @@ TunnelType *sa_tunnel_type = &_sa_tunnel_type;
  * @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 @@ int vnet_tunnel_open(u32 vnet, u32 addr, Tunnel **tunnel){
     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 @@ int vnet_tunnel_open(u32 vnet, u32 addr, Tunnel **tunnel){
     } else {
         *tunnel = etherip_tunnel;
     }
-    dprintf("< err=%d\n", err);
     return err;
 }
 
@@ -685,14 +552,12 @@ int vnet_tunnel_open(u32 vnet, u32 addr, Tunnel **tunnel){
  * @param tunnel return parameter
  * @return 0 on success, error code otherwise
  */
-int vnet_tunnel_lookup(u32 vnet, u32 addr, Tunnel **tunnel){
+int vnet_tunnel_lookup(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){
     int err = 0;
-    dprintf("> vnet=%d addr=" IPFMT "\n", vnet, NIPQUAD(addr));
     *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 @@ int vnet_tunnel_lookup(u32 vnet, u32 addr, Tunnel **tunnel){
  * @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 @@ static void __exit vnet_module_exit(void){
     vnet_exit();
     esp_module_exit();
     etherip_module_exit();
-    tunnel_module_init();
+    tunnel_module_exit();
     random_module_exit();
 }
 
@@ -753,12 +616,13 @@ static int __init vnet_module_init(void){
     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();
+        wprintf("< err=%d\n", err);
     }
-    if(err < 0) wprintf("< err=%d\n", err);
     return err;
 }
 
index 3cee13bbd768cb4248ab6afe8f4f900f28141ae3..5eace96de3cd94ae81699b9468c413efabbe14f7 100644 (file)
@@ -29,17 +29,15 @@ struct Vmac;
 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,31 +49,29 @@ typedef struct Vnet {
     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;
 extern int vnet_sa_create(u32 spi, int protocol, u32 addr, struct SAState **sa);
index 3836606b4f13570185bc30892a5b494b3297aa91..d61eda93f83da1f7bc64c45e8761b0ac4ce50832 100644 (file)
 #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");
     dev->open                 = NULL;
@@ -113,190 +107,15 @@ static int vnet_dev_set_name(struct net_device *dev){
     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.
- *
- * @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_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.
- *
- * @param vnet vnet
- */
-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
@@ -305,27 +124,13 @@ void vnet_dev_remove(Vnet *vnet){
 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.
@@ -334,17 +139,13 @@ int vnet_del_if(Vnet *vnet, struct net_device *dev){
  */
 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_stop(struct net_device *dev){
 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 @@ static int vnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
         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 @@ static int vnet_dev_hard_header(struct sk_buff *skb,
                                 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_dev_mac(unsigned char *mac){
+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;
 
-    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);
+    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){
+    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 @@ static int vnet_dev_init(struct net_device *dev){
     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 @@ int vnet_dev_add(Vnet *vnet){
     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 @@ int vnet_dev_add(Vnet *vnet){
     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);
index 168f50c91b0bb2e97ede35c5bbf6cd7da2237b70..fd6f2cff0c4d6ece837a2db3ab96229aaba788dc 100644 (file)
 #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
index 5f9f16b2e6b6dc88b66cd01b6b636b357f1115b4..7631b15ebabbf6fbfab675841987bfb25f13ab7b 100644 (file)
@@ -59,7 +59,7 @@ Have to rely on ethernet bridging being configured - but we can't rely
 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 @@ static int proc_release_fn(Inode *inode, File *file){
     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 @@ static int child_string(Sxpr exp, Sxpr key, char **s){
     return err;
 }
 
+#if 0
 static int intof(Sxpr exp, int *v){
     int err = 0;
     char *s;
@@ -473,6 +473,24 @@ static int child_int(Sxpr exp, Sxpr key, int *v){
     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 @@ static int child_addr(Sxpr exp, Sxpr key, uint32_t *v){
  * 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 @@ static int ctrl_vnet_add(int vnet, int security){
  * @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 @@ static int ctrl_vnet_del(int vnet){
  * @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,43 +592,10 @@ static int ctrl_vif_add(int vnet, Vmac *vmac){
     dprintf(">\n");
     err = Vnet_lookup(vnet, &vnetinfo);
     if(err) goto exit;
-    err = vif_add(vnet, vmac, &vif);
-  exit:
-    if(vnetinfo) Vnet_decref(vnetinfo);
-    if(vif) vif_decref(vif);
-    dprintf("< err=%d\n", err);
-    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
- * @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);
+    err = vif_create(vnet, vmac, &vif);
   exit:
     if(vnetinfo) Vnet_decref(vnetinfo);
     if(vif) vif_decref(vif);
-    if(vifdev) dev_put(vifdev);
     dprintf("< err=%d\n", err);
     return err;
 }
@@ -608,7 +606,7 @@ static int ctrl_vif_conn(char *vifname, int vnet, Vmac *vmac){
  * @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 @@ static int ctrl_vif_del(int vnet, Vmac *vmac){
     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 @@ static int eval_varp_mcaddr(Sxpr exp){
     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);
+
+    err = child_vnet(exp, oid, &vnet);
     if(err) goto exit;
-    if(id < VNET_VIF){ 
-        err = -EINVAL;
-        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 @@ static int eval_vnet_add(Sxpr exp){
         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_add(Sxpr exp){
 static int eval_vnet_del(Sxpr exp){
     int err = 0;
     Sxpr oid = intern("id");
-    int id;
+    VnetId vnet = {};
 
-    err = child_int(exp, oid, &id);
+    err = child_vnet(exp, oid, &vnet);
     if(err) goto exit;
-    err = ctrl_vnet_del(id);
+    err = ctrl_vnet_del(&vnet);
   exit:
     return err;
 }
@@ -713,55 +722,32 @@ static int eval_vif_add(Sxpr exp){
     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);
+    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");
-    Sxpr ovnet = intern("vnet");
-    Sxpr ovmac = intern("vmac");
-    char *vif = NULL;
-    int vnet = 0;
-    Vmac vmac = {};
-
-    err = child_string(exp, ovif, &vif);
-    if(err) goto exit;
-    err = child_int(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;
+    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_del(vnet, &vmac);
+    err = ctrl_vif_del(&vnet, &vmac);
   exit:
     return err;
 }
@@ -776,23 +762,23 @@ static int eval(Sxpr exp){
     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;
 }
 
index a7afa94384e0c69f8a0246e56c52aa76152b0e2c..650fdedc794931de84612131678ee30cc6f3b425 100644 (file)
 # 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 @@ LDFLAGS += $(LIBS)
 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_SRC+=$(LIB_SRC)
 
 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: vnetd
        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)
index 1ea81ba29254600724b0aac8ddbf303f5d2e135d..3822b50f1e1b17f8d78de82e5a68d2058835c655 100644 (file)
@@ -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 @@ void VarpCache_sweep(VarpCache *z, int all);
  * @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 = {};
+#ifdef DEBUG
+    char vnetbuf[VNET_ID_BUF];
+    char addrbuf[VARP_ADDR_BUF];
+#endif
 
-    varph.vnetmsghdr.id     = htons(VARP_ID);
-    varph.vnetmsghdr.opcode = htons(opcode);
-    varph.vnet              = vnet;
-    varph.vmac              = *vmac;
-    varph.addr              = addr;
+    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 @@ int varp_send(Conn *conn, uint16_t opcode, uint32_t vnet, Vmac *vmac, uint32_t a
     }
     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 @@ int VCEntry_set_flags(VCEntry *z, int flags, int set){
  */
 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;
+        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;
         }
-        d = (VCEntry_get_flags(ventry, VCACHE_FLAG_PROBING) ? "P" : " ");
+        flags = (VCEntry_get_flags(ventry, VCACHE_FLAG_PROBING) ? "P" : " ");
 
-        printf("VENTRY(%p %s %s vnet=%d vmac=" MACFMT " addr=" IPFMT " time=%g)\n",
+        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 @@ int VCEntry_schedule(VCEntry *ventry){
  * @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 @@ VCEntry * VCEntry_new(uint32_t vnet, Vmac *vmac){
  */
 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 @@ Hashcode vcache_key_hash_fn(void *k){
 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 @@ VarpCache * VarpCache_new(void){
  * @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 @@ int VarpCache_remove(VarpCache *z, VCEntry *ventry){
  * @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 @@ void VCEntry_solicit(VCEntry *ventry){
     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 @@ int VCEntry_update(VCEntry *ventry, IPMessage *msg, VarpHdr *varph, int state){
         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 @@ int VarpCache_update(VarpCache *z, IPMessage *msg, VarpHdr *varph, int state){
     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 @@ void VarpCache_sweep(VarpCache *z, int all){
  * @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 @@ int vcache_handle_request(IPMessage *msg, VarpHdr *varph, int local){
 #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 @@ int vcache_handle_message(IPMessage *msg, int local){
     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));
+        dprintf("> opcode=%d vnet=%s vmac=" MACFMT "\n",
+                ntohs(varph->opcode),
+                VnetId_ntoa(&varph->vnet, vnetbuf),
+                MAC6TUPLE(varph->vmac.mac));
     }
-    switch(ntohs(varph->vnetmsghdr.opcode)){
+#endif
+    switch(ntohs(varph->hdr.opcode)){
     case VARP_OP_REQUEST:
         err = vcache_handle_request(msg, varph, local);
         break;
index 1b0f492f83d81f42bc1245d44dbe432e69af487f..2811a8b1e358fb8dcd6f4e0280cc11a50b085376 100644 (file)
@@ -93,7 +93,7 @@ typedef struct IPMessageQueue {
 /** 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 @@ typedef struct VCEntry {
     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 @@ typedef struct VCEntry {
     //uint32_t encaps;
 
     /** Where this entry came from. */
-    uint32_t source;
+    VarpAddr source;
 
     /** Last-updated timestamp. */
     double timestamp;
index 5a37e160ef79cefe6786a9124b825cd4e52293f5..e5a1c26d8e15a7a163f54df6d963d02b14ab9a45 100644 (file)
 #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 @@ int vnetd_forward_peer(Conn *conn, int protocol, void *data, int data_n){
     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 vnetd_udp_conn(Vnetd *vnetd, Conn **val){
     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 @@ int vnetd_main(Vnetd *vnetd){
     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);
index 757b003b505ac9093334bbecacd11b4231a14b28..00234c6287ac3146fc1edcd7b60e4771a73bc215 100644 (file)
@@ -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"