diff options
Diffstat (limited to 'system/xen/openvswitch/vif-openvswitch-extended')
-rw-r--r-- | system/xen/openvswitch/vif-openvswitch-extended | 197 |
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 000000000000..41a70ca906ec --- /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 |