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