I recently ran across this question while trying to solve nearly the same problem, albeit wanting to create a SPAN port to mirror all traffic to single port. I solved it by creating a custom "vif-script
" for use in the XEN .cfg
file for the domU.
By example, you need only modify the XEN .cfg
VIF entry to include:
'mac=xx:xx:xx:xx:xx:xx,script=vif-ovs-spanport,bridge=ovsbr0'
On startup, the script will create a new mirror with a unique name combining the bridge and device/vif, add that mirror to the bridge, mirroring all traffic on that switch to the new specified port/VIF. Conversely, on shutdown, the script will remove the mirror from the bridge and as a side-effect, destroy the mirror.
You should be able to modify the script to your specific needs, albeit you'd have to know the names of the ports for all the relevant domUs. You could make use of the vifname=string
directive to ensure you had consistent names for the interfaces, but you'd still likely have an ordering issue w.r.t. which domU is brought up first to ensure that the ports are created before being used.
It might also be possible to use the vif-post.d/*
scripts to accomplish something similar; YMMV.
vif-ovs-spanport
script
#!/bin/bash
#============================================================================
# ${XEN_SCRIPT_DIR}/vif-ovs-spanport
#
# Script for configuring a Open VSwitch (OvS) VIF to be a spanport;
# i.e. on a (new) mirror, sending all traffic on the bridge to the port.
#
# Usage:
# vif-ovs-spanport (add|remove|online|offline)
#
# Requires the same environment as is required by vif-openvswitch.
# Assumes that vif-openvswitch has already added the port to the bridge.
#
# XEN .cfg file recipie: modify VIF entry
# 'mac=xx:xx:xx:xx:xx:xx,script=vif-ovs-spanport,bridge=ovsbr0'
# On startup, the script will create a new mirror with a unique name
# combinging the bridge and device/vif, add that mirror to the bridge,
# mirroring all traffic on that switch to the new specified port/VIF.
#
# On shutdown, the script will remove the mirror from the bridge and
# as a side-effect, destroy the mirror.
#============================================================================
dir=$(dirname "$0")
prg=$(basename "$0")
# We inherit base behavior, and this should add the port to the bridge for us.
. "$dir/vif-openvswitch"
add_ovsmirror () {
local dev=$1
local mirror=$2
local bridge=$3
do_or_die \
ovs-vsctl --timeout=30 \
-- --id=@m create mirror name=${mirror} \
-- add bridge ${bridge} mirrors @m \
-- --id=@p get port ${dev} \
-- set mirror ${mirror} select_all=true output-port=@p
}
remove_ovsmirror () {
local mirror=$1
local bridge=$2
do_without_error \
ovs-vsctl --timeout=30 \
-- --id=@m get mirror ${mirror} \
-- remove bridge ${bridge} mirrors @m
}
#dev= set in environment
bridge="$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")"
# code stolen from vif-openvswitch
if [[ $bridge =~ ^([^.:]+)(\.([[:digit:]]+))?(:([[:digit:]]+(:[[:digit:]]+)*))?$ ]]; then
bridge="${BASH_REMATCH[1]}"
#tag="${BASH_REMATCH[3]}"
#trunk="${BASH_REMATCH[5]//:/,}"
else
fatal "No valid bridge was specified"
fi
mirror="${bridge}-mirror-span-${dev}"
case "$command" in
add|online)
check_tools
log debug "$prg creating $mirror on $bridge, then adding $dev to mirror."
add_ovsmirror $dev $mirror $bridge
;;
remove|offline)
log debug "$prg removing mirror $mirror."
remove_ovsmirror $mirror $bridge
;;
esac
log debug "Successful vif-ovs-spanport $command for $dev on $bridge ($mirror)."
if [ "$type_if" = vif -a "$command" = "online" ]; then
success
fi