Based on Waldi''s RFC at http://lists.xen.org/archives/html/xen-devel/2012-09/msg00943.html To use it set vif.default.script="vif-openvswitch" in /etc/xen/xl.conf or use script=vif-openvswitch in the vif configuration. Appears to do the right thing for PV and HVM guests (including tap devices) and with stubdomains. In order to support VLAN tagging and trunking the "bridge" specified in the configuration can have a special syntax, that is: BRIDGE_NAME[.VLAN][:TRUNK:TRUNK] e.g. - xenbr0.99 add the VIF to VLAN99 on xenbr0 - xenbr0:99:100:101 add the VIF to xenbr0 as a trunk port receiving VLANs 99, 100 & 101 Waldi, can you confirm if I have correctly reverse engineered the syntax from the regexp please ;-) Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Bastian Blank <waldi@debian.org> Cc: dev@openvswitch.org --- v3: Handle the remove case as well to properly support tap devices v2: Correct syntax description in commitlog. Remove erroneous xl.conf change. Added Bastian''s S-o-b. Agreed with Ben Pfaff that the Xen tree is a good home for this script. --- tools/hotplug/Linux/Makefile | 1 + tools/hotplug/Linux/vif-openvswitch | 99 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 0 deletions(-) create mode 100644 tools/hotplug/Linux/vif-openvswitch diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile index 0605559..99bf87f 100644 --- a/tools/hotplug/Linux/Makefile +++ b/tools/hotplug/Linux/Makefile @@ -13,6 +13,7 @@ XENCOMMONS_SYSCONFIG = init.d/sysconfig.xencommons XEN_SCRIPTS = network-bridge vif-bridge XEN_SCRIPTS += network-route vif-route XEN_SCRIPTS += network-nat vif-nat +XEN_SCRIPTS += vif-openvswitch XEN_SCRIPTS += vif2 XEN_SCRIPTS += vif-setup XEN_SCRIPTS += block diff --git a/tools/hotplug/Linux/vif-openvswitch b/tools/hotplug/Linux/vif-openvswitch new file mode 100644 index 0000000..f30e78c --- /dev/null +++ b/tools/hotplug/Linux/vif-openvswitch @@ -0,0 +1,99 @@ +#!/bin/bash +#===========================================================================+# ${XEN_SCRIPT_DIR}/vif-openvswitch +# +# Script for configuring a vif in openvswitch mode. +# The hotplugging system will call this script if it is specified either in +# the device configuration given to Xend, or the default Xend configuration +# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in +# neither of those places, then this script is the default. +# +# Usage: +# vif-openvswitch (add|remove|online|offline) +# +# Environment vars: +# vif vif interface name (required). +# XENBUS_PATH path to this device''s details in the XenStore (required). +# +# Read from the store: +# bridge openvswitch to add the vif to (required). +# ip list of IP networks for the vif, space-separated (optional). +# +# up: +# Enslaves the vif interface to the bridge and adds iptables rules +# for its ip addresses (if any). +# +# down: +# Removes the vif interface from the bridge and removes the iptables +# rules for its ip addresses (if any). +#===========================================================================+ +dir=$(dirname "$0") +. "$dir/vif-common.sh" + +openvswitch_external_id() { + local dev=$1 + local key=$2 + local value=$3 + + echo "-- set interface $dev external-ids:\"$key\"=\"$value\"" +} + +openvswitch_external_id_all() { + local dev=$1 + local frontend_id=$(xenstore_read "$XENBUS_PATH/frontend-id") + local vm_path=$(xenstore_read "/local/domain/${frontend_id}/vm") + local name=$(xenstore_read "${vm_path}/name") + openvswitch_external_id $dev "xen-vm-name" "$name" + local uuid=$(xenstore_read "${vm_path}/uuid") + openvswitch_external_id $dev "xen-vm-uuid" "$uuid" + local mac=$(xenstore_read "$XENBUS_PATH/mac") + openvswitch_external_id $dev "attached-mac" "$mac" +} + +add_to_openvswitch () { + local dev=$1 + local bridge="$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")" + local tag trunk + + 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 + + if [ $trunk ]; then + local trunk_arg="trunk=$trunk" + fi + + if [ $tag ]; then + local tag_arg="tag=$tag" + fi + + local vif_details="$(openvswitch_external_id_all $dev)" + + ovs-vsctl --timeout=30 -- --if-exists del-port $dev -- add-port "$bridge" $dev $tag_arg $trunk_arg $vif_details + ip link set $dev up +} + +case "$command" in + add|online) + setup_virtual_bridge_port $dev + add_to_openvswitch $dev + ;; + + remove|offline) + ovs-vsctl --timeout=30 -- --if-exists del-port $dev + ;; +esac + +if [ "$type_if" = vif ]; then + handle_iptable +fi + +log debug "Successful vif-openvswitch $command for $dev." +if [ "$type_if" = vif -a "$command" = "online" ]; then + success +fi -- 1.7.2.5
On 23/04/13 10:22, Ian Campbell wrote:> Based on Waldi''s RFC at > http://lists.xen.org/archives/html/xen-devel/2012-09/msg00943.html > > To use it set vif.default.script="vif-openvswitch" in /etc/xen/xl.conf or use > script=vif-openvswitch in the vif configuration. > > Appears to do the right thing for PV and HVM guests (including tap devices) > and with stubdomains. > > In order to support VLAN tagging and trunking the "bridge" specified in the > configuration can have a special syntax, that is: > > BRIDGE_NAME[.VLAN][:TRUNK:TRUNK] > > e.g. > - xenbr0.99 > add the VIF to VLAN99 on xenbr0 > - xenbr0:99:100:101 > add the VIF to xenbr0 as a trunk port receiving VLANs 99, 100 & 101 > > Waldi, can you confirm if I have correctly reverse engineered the syntax from > the regexp please ;-) > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > Signed-off-by: Bastian Blank <waldi@debian.org> > Cc: dev@openvswitch.org > --- > v3: Handle the remove case as well to properly support tap devices > v2: Correct syntax description in commitlog. > Remove erroneous xl.conf change. > Added Bastian''s S-o-b. > Agreed with Ben Pfaff that the Xen tree is a good home for this script. > --- > tools/hotplug/Linux/Makefile | 1 + > tools/hotplug/Linux/vif-openvswitch | 99 +++++++++++++++++++++++++++++++++++ > 2 files changed, 100 insertions(+), 0 deletions(-) > create mode 100644 tools/hotplug/Linux/vif-openvswitch > > diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile > index 0605559..99bf87f 100644 > --- a/tools/hotplug/Linux/Makefile > +++ b/tools/hotplug/Linux/Makefile > @@ -13,6 +13,7 @@ XENCOMMONS_SYSCONFIG = init.d/sysconfig.xencommons > XEN_SCRIPTS = network-bridge vif-bridge > XEN_SCRIPTS += network-route vif-route > XEN_SCRIPTS += network-nat vif-nat > +XEN_SCRIPTS += vif-openvswitch > XEN_SCRIPTS += vif2 > XEN_SCRIPTS += vif-setup > XEN_SCRIPTS += block > diff --git a/tools/hotplug/Linux/vif-openvswitch b/tools/hotplug/Linux/vif-openvswitch > new file mode 100644 > index 0000000..f30e78c > --- /dev/null > +++ b/tools/hotplug/Linux/vif-openvswitch > @@ -0,0 +1,99 @@ > +#!/bin/bash > +#===========================================================================> +# ${XEN_SCRIPT_DIR}/vif-openvswitch > +# > +# Script for configuring a vif in openvswitch mode. > +# The hotplugging system will call this script if it is specified either in > +# the device configuration given to Xend, or the default Xend configuration > +# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in > +# neither of those places, then this script is the default. > +# > +# Usage: > +# vif-openvswitch (add|remove|online|offline) > +# > +# Environment vars: > +# vif vif interface name (required). > +# XENBUS_PATH path to this device''s details in the XenStore (required). > +# > +# Read from the store: > +# bridge openvswitch to add the vif to (required). > +# ip list of IP networks for the vif, space-separated (optional). > +# > +# up: > +# Enslaves the vif interface to the bridge and adds iptables rules > +# for its ip addresses (if any). > +# > +# down: > +# Removes the vif interface from the bridge and removes the iptables > +# rules for its ip addresses (if any). > +#===========================================================================> + > +dir=$(dirname "$0") > +. "$dir/vif-common.sh" > + > +openvswitch_external_id() { > + local dev=$1 > + local key=$2 > + local value=$3 > + > + echo "-- set interface $dev external-ids:\"$key\"=\"$value\"" > +} > + > +openvswitch_external_id_all() { > + local dev=$1 > + local frontend_id=$(xenstore_read "$XENBUS_PATH/frontend-id") > + local vm_path=$(xenstore_read "/local/domain/${frontend_id}/vm") > + local name=$(xenstore_read "${vm_path}/name") > + openvswitch_external_id $dev "xen-vm-name" "$name" > + local uuid=$(xenstore_read "${vm_path}/uuid") > + openvswitch_external_id $dev "xen-vm-uuid" "$uuid" > + local mac=$(xenstore_read "$XENBUS_PATH/mac") > + openvswitch_external_id $dev "attached-mac" "$mac" > +} > + > +add_to_openvswitch () { > + local dev=$1 > + local bridge="$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")" > + local tag trunk > + > + 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 > + > + if [ $trunk ]; then > + local trunk_arg="trunk=$trunk" > + fi > + > + if [ $tag ]; then > + local tag_arg="tag=$tag" > + fi > + > + local vif_details="$(openvswitch_external_id_all $dev)" > + > + ovs-vsctl --timeout=30 -- --if-exists del-port $dev -- add-port "$bridge" $dev $tag_arg $trunk_arg $vif_details > + ip link set $dev upShould we check the return value of this two calls, so we can print a nice error message if something fails?> +} > + > +case "$command" in > + add|online) > + setup_virtual_bridge_port $dev > + add_to_openvswitch $dev > + ;; > + > + remove|offline) > + ovs-vsctl --timeout=30 -- --if-exists del-port $devSame here.> + ;; > +esac > + > +if [ "$type_if" = vif ]; then > + handle_iptable > +fi > + > +log debug "Successful vif-openvswitch $command for $dev." > +if [ "$type_if" = vif -a "$command" = "online" ]; then > + success > +fi >
On 23/04/13 10:22, Ian Campbell wrote:> Based on Waldi''s RFC at > http://lists.xen.org/archives/html/xen-devel/2012-09/msg00943.html > > To use it set vif.default.script="vif-openvswitch" in /etc/xen/xl.conf or use > script=vif-openvswitch in the vif configuration. > > Appears to do the right thing for PV and HVM guests (including tap devices) > and with stubdomains. > > In order to support VLAN tagging and trunking the "bridge" specified in the > configuration can have a special syntax, that is: > > BRIDGE_NAME[.VLAN][:TRUNK:TRUNK] > > e.g. > - xenbr0.99 > add the VIF to VLAN99 on xenbr0 > - xenbr0:99:100:101 > add the VIF to xenbr0 as a trunk port receiving VLANs 99, 100 & 101 > > Waldi, can you confirm if I have correctly reverse engineered the syntax from > the regexp please ;-) > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > Signed-off-by: Bastian Blank <waldi@debian.org> > Cc: dev@openvswitch.org > --- > v3: Handle the remove case as well to properly support tap devices > v2: Correct syntax description in commitlog. > Remove erroneous xl.conf change. > Added Bastian''s S-o-b. > Agreed with Ben Pfaff that the Xen tree is a good home for this script. > --- > tools/hotplug/Linux/Makefile | 1 + > tools/hotplug/Linux/vif-openvswitch | 99 +++++++++++++++++++++++++++++++++++ > 2 files changed, 100 insertions(+), 0 deletions(-) > create mode 100644 tools/hotplug/Linux/vif-openvswitch > > diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile > index 0605559..99bf87f 100644 > --- a/tools/hotplug/Linux/Makefile > +++ b/tools/hotplug/Linux/Makefile > @@ -13,6 +13,7 @@ XENCOMMONS_SYSCONFIG = init.d/sysconfig.xencommons > XEN_SCRIPTS = network-bridge vif-bridge > XEN_SCRIPTS += network-route vif-route > XEN_SCRIPTS += network-nat vif-nat > +XEN_SCRIPTS += vif-openvswitch > XEN_SCRIPTS += vif2 > XEN_SCRIPTS += vif-setup > XEN_SCRIPTS += block > diff --git a/tools/hotplug/Linux/vif-openvswitch b/tools/hotplug/Linux/vif-openvswitch > new file mode 100644 > index 0000000..f30e78c > --- /dev/null > +++ b/tools/hotplug/Linux/vif-openvswitch > @@ -0,0 +1,99 @@ > +#!/bin/bash > +#===========================================================================> +# ${XEN_SCRIPT_DIR}/vif-openvswitch > +# > +# Script for configuring a vif in openvswitch mode. > +# The hotplugging system will call this script if it is specified either in > +# the device configuration given to Xend, or the default Xend configuration > +# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in > +# neither of those places, then this script is the default. > +# > +# Usage: > +# vif-openvswitch (add|remove|online|offline) > +# > +# Environment vars: > +# vif vif interface name (required). > +# XENBUS_PATH path to this device''s details in the XenStore (required). > +# > +# Read from the store: > +# bridge openvswitch to add the vif to (required). > +# ip list of IP networks for the vif, space-separated (optional). > +# > +# up: > +# Enslaves the vif interface to the bridge and adds iptables rules > +# for its ip addresses (if any). > +# > +# down: > +# Removes the vif interface from the bridge and removes the iptables > +# rules for its ip addresses (if any). > +#===========================================================================Also, it might be interesting to add something like: check_tools() { if ! type ovs-vsctl > /dev/null 2>&1; then fatal "Unable to find ovs-vsctl tool" fi if ! type ip > /dev/null 2>&1; then fatal "Unable to find ip tool" fi } In order to check that the needed external tools are there.> +dir=$(dirname "$0") > +. "$dir/vif-common.sh" > + > +openvswitch_external_id() { > + local dev=$1 > + local key=$2 > + local value=$3 > + > + echo "-- set interface $dev external-ids:\"$key\"=\"$value\"" > +} > + > +openvswitch_external_id_all() { > + local dev=$1 > + local frontend_id=$(xenstore_read "$XENBUS_PATH/frontend-id") > + local vm_path=$(xenstore_read "/local/domain/${frontend_id}/vm") > + local name=$(xenstore_read "${vm_path}/name") > + openvswitch_external_id $dev "xen-vm-name" "$name" > + local uuid=$(xenstore_read "${vm_path}/uuid") > + openvswitch_external_id $dev "xen-vm-uuid" "$uuid" > + local mac=$(xenstore_read "$XENBUS_PATH/mac") > + openvswitch_external_id $dev "attached-mac" "$mac" > +} > + > +add_to_openvswitch () { > + local dev=$1 > + local bridge="$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")" > + local tag trunk > + > + 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 > + > + if [ $trunk ]; then > + local trunk_arg="trunk=$trunk" > + fi > + > + if [ $tag ]; then > + local tag_arg="tag=$tag" > + fi > + > + local vif_details="$(openvswitch_external_id_all $dev)" > + > + ovs-vsctl --timeout=30 -- --if-exists del-port $dev -- add-port "$bridge" $dev $tag_arg $trunk_arg $vif_details > + ip link set $dev up > +} > + > +case "$command" in > + add|online) > + setup_virtual_bridge_port $dev > + add_to_openvswitch $dev > + ;; > + > + remove|offline) > + ovs-vsctl --timeout=30 -- --if-exists del-port $dev > + ;; > +esac > + > +if [ "$type_if" = vif ]; then > + handle_iptable > +fi > + > +log debug "Successful vif-openvswitch $command for $dev." > +if [ "$type_if" = vif -a "$command" = "online" ]; then > + success > +fi >
On Tue, 2013-04-23 at 09:46 +0100, Roger Pau Monne wrote:> > + ovs-vsctl --timeout=30 -- --if-exists del-port $dev -- add-port "$bridge" $dev $tag_arg $trunk_arg $vif_details > > + ip link set $dev up > > Should we check the return value of this two calls, so we can print a > nice error message if something fails?The bridge variant doesn''t, but I suppose that''s not much of an argument. There''s a do_or_die helper in xen-hotplug-common.sh which logs on failure, I suppose that would be a good thing to use?> > +} > > + > > +case "$command" in > > + add|online) > > + setup_virtual_bridge_port $dev > > + add_to_openvswitch $dev > > + ;; > > + > > + remove|offline) > > + ovs-vsctl --timeout=30 -- --if-exists del-port $dev > > Same here.I think this one wants to be a non-fatal error on failure, do allow as much cleanup as possible to go ahead (e.g. the iptables rule below). I think do_without_error is the right answer for this one. I also noticed that we don''t set the link down here. Probably the device is about to go away but I added it for consistency with the up case, and with the bridge script... Ian.
On Tue, 2013-04-23 at 09:56 +0100, Roger Pau Monne wrote:> Also, it might be interesting to add something like: > > check_tools() > { > if ! type ovs-vsctl > /dev/null 2>&1; thenI think type is a bash-ism but I don''t know the portable alternative and this script uses #!/bin/bash anyhow.> fatal "Unable to find ovs-vsctl tool" > fi > if ! type ip > /dev/null 2>&1; then > fatal "Unable to find ip tool" > fi > } > > In order to check that the needed external tools are there.Can''t hurt I suppose. I made it check only in the online case, since like I said before I''d like remove to try to do as much as it can.
On Tue, Apr 23, 2013 at 10:42:15AM +0100, Ian Campbell wrote:> On Tue, 2013-04-23 at 09:56 +0100, Roger Pau Monne wrote: > > Also, it might be interesting to add something like: > > if ! type ovs-vsctl > /dev/null 2>&1; then > I think type is a bash-ism but I don''t know the portable alternative and > this script uses #!/bin/bash anyhow.You may want to use "command -v $bla > /dev/null", it is a bit more portable. Bastian -- Star Trek Lives!
On Tue, 2013-04-23 at 10:58 +0100, Bastian Blank wrote:> On Tue, Apr 23, 2013 at 10:42:15AM +0100, Ian Campbell wrote: > > On Tue, 2013-04-23 at 09:56 +0100, Roger Pau Monne wrote: > > > Also, it might be interesting to add something like: > > > if ! type ovs-vsctl > /dev/null 2>&1; then > > I think type is a bash-ism but I don''t know the portable alternative and > > this script uses #!/bin/bash anyhow. > > You may want to use "command -v $bla > /dev/null", it is a bit more > portable.Thanks for the hint, V4 incoming... Ian.