FirstServed Tech Blog - FirstServed and the Art of Server Tuning

Bridging VLAN interfaces in Xen

The init scripts bundled with Xen offer little or no support for VLANs.  One way to configure VLANs is to do it at the DomU level, but that’s a trick that’s only feasible on Linux guests, since on Windows VLAN support for ethernet cards is implemented by proprietary software of the NIC vendor, and there’s certainly no such thing as Windows software for the Xen Virtual NIC.

In case the Dom0 doesn’t need active interfaces on the VLAN bridges, you can follow the solution outlined on this page: Bridging domains to tagged VLANs in Xen.

I found a much simpler solution.  The reason Xen’s network-bridge doesn’t play ball with VLAN interfaces is that at a certain point, /sbin/ifdown is called to bring down the net device – a prerequisite to rename it and reassign it to the bridge.  Ifdown however has the undesirable side effect of removing any configured VLAN’s on the device it’s bringing down, effectively deleting the interface entirely.  So when running the network-bridge script, you’ll get error messages saying the device was not found:

SIOCSIFNAME: No such device

I modified xen-network-common.sh so ifdown is no longer called directly.  Instead of it, the ip address of the interface is flushed manually, then the device’s link is brought down, leaving the vlan configured on the interface intact.  The following script is based on Xen 3.0.3′s xen-network-common.sh script.

if [ -e /etc/SuSE-release ]
then
  preiftransfer()
  {
    eval `/sbin/getcfg -d /etc/sysconfig/network/ -f ifcfg- — $1`
  }
  ifup()
  {
    /sbin/ifup ${HWD_CONFIG_0} $1
  }
elif ! which ifup >/dev/null 2>/dev/null
then
  preiftransfer()
  {
    true
  }
  ifup()
  {
    false
  }
  ifdown()
  {
    false
  }
else
  preiftransfer()
  {
    true
  }
  # do not call ifdown directly
  ifdown()  {
    ip addr flush $1
    ip link set $1 down
    true
  }

fi

first_file()
{
  t="$1"
  shift
  for file in $@
  do
    if [ "$t" "$file" ]
    then
      echo "$file"
      return
    fi
  done
}

find_dhcpd_conf_file()
{
  first_file -f /etc/dhcp3/dhcpd.conf /etc/dhcpd.conf
}

find_dhcpd_init_file()
{
  first_file -x /etc/init.d/{dhcp3-server,dhcp,dhcpd}
}

# configure interfaces which act as pure bridge ports:
#  – make quiet: no arp, no multicast (ipv6 autoconf)
#  – set mac address to fe:ff:ff:ff:ff:ff
setup_bridge_port() {
    local dev="$1"

    # take interface down …
    ip link set ${dev} down

    # … and configure it
    ip link set ${dev} arp off
    ip link set ${dev} multicast off
    ip link set ${dev} addr fe:ff:ff:ff:ff:ff
    ip addr flush ${dev}
}

# Usage: create_bridge bridge
create_bridge () {
    local bridge=$1

    # Don’t create the bridge if it already exists.
    if [ ! -e "/sys/class/net/${bridge}/bridge" ]; then
        brctl addbr ${bridge}
        brctl stp ${bridge} off
        brctl setfd ${bridge} 0
        sysctl -w "net.bridge.bridge-nf-call-arptables=0"
        sysctl -w "net.bridge.bridge-nf-call-ip6tables=0"
        sysctl -w "net.bridge.bridge-nf-call-iptables=0"
        ip link set ${bridge} arp off
        ip link set ${bridge} multicast off
    fi
    # A small MTU disables IPv6 (and therefore IPv6 addrconf).
    mtu=$(ip link show ${bridge} | sed -n ‘s/.* mtu \([0-9]\+\).*/\1/p’)
    ip link set ${bridge} mtu 68
    ip link set ${bridge} up
    ip link set ${bridge} mtu ${mtu:-1500}
}

# Usage: add_to_bridge bridge dev
add_to_bridge () {
    local bridge=$1
    local dev=$2

    # Don’t add $dev to $bridge if it’s already on a bridge.
    if [ -e "/sys/class/net/${bridge}/brif/${dev}" ]; then
        ip link set ${dev} up || true
        return
    fi
    brctl addif ${bridge} ${dev}
    ip link set ${dev} up
}

You can the start up the needed bridges from within your my-network-bridge script – assuming you change (network-script network-bridge) to (network-script my-network-bridge) in xend-config.sxp:

#!/bin/sh
dir=$(dirname "$0")
"$dir/network-bridge" "$@" vifnum=0 netdev=eth0 bridge=xenbr0
"$dir/network-bridge" "$@" vifnum=1 netdev=eth1 bridge=xenbr1
"$dir/network-bridge" "$@" vifnum=2 netdev=eth1.142 bridge=xenbr142
"$dir/network-bridge" "$@" vifnum=3 netdev=eth1.143 bridge=xenbr143

The above example gives you the choice of four different bridges for each domU, some of which are transparently bound to a VLAN.

Leave a Reply

You must be logged in to post a comment.