1#!/bin/bash
2#============================================================================
3# ${XEN_SCRIPT_DIR}/vif-openvswitch
4#
5# Script for configuring a vif in openvswitch mode.
6#
7# Usage:
8# vif-openvswitch (add|remove|online|offline)
9#
10# Environment vars:
11# vif         vif interface name (required).
12# XENBUS_PATH path to this device's details in the XenStore (required).
13#
14# Read from the store:
15# bridge  openvswitch to add the vif to (required).
16# ip      list of IP networks for the vif, space-separated (optional).
17#
18# up:
19# Enslaves the vif interface to the bridge and adds iptables rules
20# for its ip addresses (if any).
21#
22# down:
23# Removes the vif interface from the bridge and removes the iptables
24# rules for its ip addresses (if any).
25#============================================================================
26
27dir=$(dirname "$0")
28. "$dir/vif-common.sh"
29
30check_tools()
31{
32    if ! command -v ovs-vsctl > /dev/null 2>&1; then
33        fatal "Unable to find ovs-vsctl tool"
34    fi
35    if ! command -v ip > /dev/null 2>&1; then
36        fatal "Unable to find ip tool"
37    fi
38}
39openvswitch_external_id() {
40    local dev=$1
41    local key=$2
42    local value=$3
43
44    echo "-- set interface $dev external-ids:\"$key\"=\"$value\""
45}
46
47openvswitch_external_id_all() {
48    local dev=$1
49    local frontend_id=$(xenstore_read "$XENBUS_PATH/frontend-id")
50    local vm_path=$(xenstore_read "/local/domain/${frontend_id}/vm")
51    local name=$(xenstore_read "${vm_path}/name")
52    openvswitch_external_id $dev "xen-vm-name" "$name"
53    local uuid=$(xenstore_read "${vm_path}/uuid")
54    openvswitch_external_id $dev "xen-vm-uuid" "$uuid"
55    local mac=$(xenstore_read "$XENBUS_PATH/mac")
56    openvswitch_external_id $dev "attached-mac" "$mac"
57}
58
59add_to_openvswitch () {
60    local dev=$1
61    local bridge="$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")"
62    local tag trunk
63
64    if [[ $bridge =~ ^([^.:]+)(\.([[:digit:]]+))?(:([[:digit:]]+(:[[:digit:]]+)*))?$ ]]; then
65        bridge="${BASH_REMATCH[1]}"
66        tag="${BASH_REMATCH[3]}"
67        trunk="${BASH_REMATCH[5]//:/,}"
68    else
69        fatal "No valid bridge was specified"
70    fi
71
72    if [ $trunk ]; then
73        local trunk_arg="trunk=$trunk"
74    fi
75
76    if [ $tag ]; then
77        local tag_arg="tag=$tag"
78    fi
79
80    local vif_details="$(openvswitch_external_id_all $dev)"
81
82    do_or_die ovs-vsctl --timeout=30 \
83        -- --if-exists del-port $dev \
84        -- add-port "$bridge" $dev $tag_arg $trunk_arg $vif_details
85    do_or_die ip link set $dev up
86}
87
88case "$command" in
89    add|online)
90        check_tools
91        setup_virtual_bridge_port $dev
92        add_to_openvswitch $dev
93        ;;
94
95    remove|offline)
96        do_without_error ovs-vsctl --timeout=30 \
97            -- --if-exists del-port $dev
98        do_without_error ip link set $dev down
99        ;;
100esac
101
102if [ "$type_if" = vif ]; then
103    handle_iptable
104fi
105
106log debug "Successful vif-openvswitch $command for $dev."
107if [ "$type_if" = vif -a "$command" = "online" ]; then
108    success
109fi
110