summaryrefslogtreecommitdiff
path: root/system/xen/openvswitch/vif-openvswitch-extended
diff options
context:
space:
mode:
Diffstat (limited to 'system/xen/openvswitch/vif-openvswitch-extended')
-rw-r--r--system/xen/openvswitch/vif-openvswitch-extended197
1 files changed, 197 insertions, 0 deletions
diff --git a/system/xen/openvswitch/vif-openvswitch-extended b/system/xen/openvswitch/vif-openvswitch-extended
new file mode 100644
index 0000000000..41a70ca906
--- /dev/null
+++ b/system/xen/openvswitch/vif-openvswitch-extended
@@ -0,0 +1,197 @@
+#!/bin/bash
+#============================================================================
+# ${XEN_SCRIPT_DIR}/vif-openvswitch-extended
+#
+# Script for configuring a vif in openvswitch mode, extended to support
+# HTB rate limiting and IP/ARP spoof prevention.
+# Some inspiration drawn from:
+# http://openvswitch.org/support/config-cookbooks/qos-rate-limiting/
+# http://openvswitch.org/pipermail/discuss/2011-May/005178.html
+# Original script modified by Mario Preksavec <mario@slackware.hr>
+#
+# Rate limiting and antispoof config file:
+# XEN_CONFIG_DIR/openvswitch.conf
+#
+# Usage:
+# vif-openvswitch-extended (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"
+
+check_tools()
+{
+ if ! command -v ovs-vsctl > /dev/null 2>&1; then
+ fatal "Unable to find ovs-vsctl tool"
+ fi
+ if ! command -v ip > /dev/null 2>&1; then
+ fatal "Unable to find ip tool"
+ fi
+}
+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)"
+
+ do_or_die ovs-vsctl --timeout=30 \
+ -- --if-exists del-port $dev \
+ -- add-port "$bridge" $dev $tag_arg $trunk_arg $vif_details
+ do_or_die ip link set $dev up
+
+ if [ -f ${XEN_CONFIG_DIR}/openvswitch.conf ]; then
+ declare -A rate ipv4 ipv6
+ . ${XEN_CONFIG_DIR}/openvswitch.conf
+ local frontend_id=$(xenstore_read "$XENBUS_PATH/frontend-id")
+ local name=$(xenstore_read "/local/domain/${frontend_id}/name")
+
+ if [ ! -z ${rate[$name]} ]; then
+ local rate=${rate[$name]}
+ elif [ ! -z ${rate[::default]} ]; then
+ local rate=${rate[::default]}
+ else
+ local rate=0
+ fi
+
+ if [ $rate -gt 0 ]; then
+ local policing_rate=$((rate * 1000))
+ local policing_burst=$((rate * 100))
+ local min_rate=$((rate * 1000000))
+ local max_rate=$((rate * 1000000))
+ local qos_id="@qos_$dev"
+ local que_id="@que_$dev"
+ do_or_die ovs-vsctl -- set interface $dev \
+ ingress_policing_rate=$policing_rate \
+ ingress_policing_burst=$policing_burst \
+ -- set port $dev qos=$qos_id \
+ -- --id=$qos_id create qos type=linux-htb \
+ other-config:max-rate=$max_rate queues=0=$que_id \
+ -- --id=$que_id create queue other-config:min-rate=$min_rate \
+ other-config:max-rate=$max_rate > /dev/null
+ fi
+
+ if [ ! -z ${ipv4[$name]} ]; then
+ local ipv4=${ipv4[$name]}
+ elif [ ! -z ${ipv4[::default]} ]; then
+ local ipv4=${ipv4[::default]}
+ fi
+
+ if [ ! -z ${ipv6[$name]} ]; then
+ local ipv6=${ipv6[$name]}
+ elif [ ! -z ${ipv6[::default]} ]; then
+ local ipv6=${ipv6[::default]}
+ fi
+
+ if [ ! -z "$ipv4" ] || [ ! -z "$ipv6" ]; then
+ local mac=$(xenstore_read "$XENBUS_PATH/mac")
+ local port=$(ovs-vsctl get interface $dev ofport)
+
+ if [ ! -z "$ipv4" ]; then
+ do_or_die ovs-ofctl add-flow $bridge "in_port=$port priority=39000 \
+ dl_type=0x0800 nw_src=$ipv4 dl_src=$mac idle_timeout=0 \
+ action=normal" > /dev/null
+ fi
+
+ if [ ! -z "$ipv6" ]; then
+ do_or_die ovs-ofctl add-flow $bridge "in_port=$port priority=39000 \
+ dl_type=0x86dd ipv6_src=$ipv6 dl_src=$mac idle_timeout=0 \
+ action=normal" > /dev/null
+ fi
+
+ do_or_die ovs-ofctl add-flow $bridge "in_port=$port priority=38500 \
+ dl_type=0x0806 dl_src=$mac idle_timeout=0 action=normal" > /dev/null
+
+ do_or_die ovs-ofctl add-flow $bridge "in_port=$port priority=38000 \
+ idle_timeout=0 action=drop" > /dev/null
+ fi
+ fi
+}
+
+case "$command" in
+ add|online)
+ check_tools
+ setup_virtual_bridge_port $dev
+ add_to_openvswitch $dev
+ ;;
+
+ remove|offline)
+ if [ -f ${XEN_CONFIG_DIR}/openvswitch.conf ]; then
+ bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")
+ queues=$(ovs-vsctl -- --if-exists get qos $dev queues \
+ | sed 's/[0-9]\+=//g;s/[{,}]//g')
+ # Remove flows
+ do_without_error ovs-ofctl del-flows $bridge in_port=$(ovs-vsctl \
+ -- --if-exists get interface $dev ofport)
+ # Remove queues & qos
+ do_without_error ovs-vsctl --timeout=30 \
+ -- --if-exists destroy queue $queues \
+ -- --if-exists destroy qos $dev \
+ -- --if-exists clear port $dev qos
+ fi
+ do_without_error ovs-vsctl --timeout=30 \
+ -- --if-exists del-port $dev
+ do_without_error ip link set $dev down
+ ;;
+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