Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: ca-115293
Fetching contributors…

Cannot retrieve contributors at this time

executable file 327 lines (290 sloc) 11.741 kB
#!/bin/bash
# Copyright (C) 2008,2009 Citrix Systems, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; version 2.1 only. with the special
# exception on linking described in file LICENSE.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
# CA-23900: Warning: when VIFs are added to windows guests with PV drivers the backend vif device is registered,
# unregistered and then registered again. This causes the udev event to fire twice and this script runs twice.
# Since the first invocation of the script races with the device unregistration, spurious errors are possible
# which will be logged but are safe to ignore since the second script invocation should complete the operation.
# Note that each script invocation is run synchronously from udev and so the scripts don't race with each other.
# Keep other-config/ keys in sync with device.ml:vif_udev_keys
BRCTL="/usr/sbin/brctl"
if [ ! -e $BRCTL ] ; then
BRCTL="/sbin/brctl"
fi
IP="/sbin/ip"
vsctl="/usr/bin/ovs-vsctl"
setup_vif_rules="@LIBEXECDIR@/setup-vif-rules"
handle_promiscuous()
{
# other-config keys are optional
local arg=$(xenstore-read "${PRIVATE}/other-config/promiscuous" 2>/dev/null)
if [ $? -eq 0 -a -n "${arg}" ] ; then
case $NETWORK_MODE in
bridge)
case "${arg}" in
true|on) echo 1 > /sys/class/net/${dev}/brport/promisc ;;
*) echo 0 > /sys/class/net/${dev}/brport/promisc ;;
esac
;;
openvswitch)
logger -t script-vif "${dev}: Promiscuous ports are not supported via Open vSwitch."
;;
esac
fi
}
handle_ethtool()
{
local opt=$1
# other-config keys are optional
local arg=$(xenstore-read "${PRIVATE}/other-config/ethtool-${opt}" 2>/dev/null)
if [ $? -eq 0 -a -n "${arg}" ] ; then
case "${arg}" in
true|on) /sbin/ethtool -K "${dev}" "${opt}" on ;;
false|off) /sbin/ethtool -K "${dev}" "${opt}" off ;;
*) logger -t scripts-vif "Unknown ethtool argument ${opt}=${arg} on ${dev}/${VIFUUID}" ;;
esac
fi
}
handle_mtu()
{
local mtu=$(xenstore-read "${PRIVATE}/MTU" 2>/dev/null)
if [ $? -eq 0 -a -n "${mtu}" ]; then
logger -t scripts-vif "Setting ${dev} MTU ${mtu}"
${IP} link set "${dev}" mtu ${mtu} || logger -t scripts-vif "Failed to ip link set ${dev} mtu ${mtu}. Error code $?"
else
logger -t scripts-vif "Failed to read ${PRIVATE}/MTU"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read ${PRIVATE}/MTU"
exit 1
fi
}
set_vif_external_id()
{
local key=$1
local value=$2
logger -t scripts-vif "vif${DOMID}.${DEVID} external-ids:\"${key}\"=\"${value}\""
echo "-- set interface vif${DOMID}.${DEVID} external-ids:\"${key}\"=\"${value}\""
}
handle_vswitch_vif_details()
{
local vm=$(xenstore-read "/local/domain/$DOMID/vm" 2>/dev/null)
if [ $? -eq 0 -a -n "${vm}" ] ; then
local vm_uuid=$(xenstore-read "$vm/uuid" 2>/dev/null)
else
logger -t scripts-vif "Failed to read /local/domain/$DOMID/vm"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read /local/domain/$DOMID/vm"
exit 1
fi
if [ -n "${vm_uuid}" ] ; then
set_vif_external_id "xs-vm-uuid" "${vm_uuid}"
else
logger -t scripts-vif "Failed to read $vm/uuid"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read $vm/uuid"
exit 1
fi
local vif_uuid=$(xenstore-read "${PRIVATE}/vif-uuid" 2>/dev/null)
if [ -n "${vif_uuid}" ] ; then
set_vif_external_id "xs-vif-uuid" "${vif_uuid}"
else
logger -t scripts-vif "Failed to read ${PRIVATE}/vif-uuid"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read ${PRIVATE}/vif-uuid"
exit 1
fi
local vif_details=
local net_uuid=$(xenstore-read "${PRIVATE}/network-uuid" 2>/dev/null)
if [ -n "${net_uuid}" ] ; then
set_vif_external_id "xs-network-uuid" "${net_uuid}"
else
logger -t scripts-vif "Failed to read ${PRIVATE}/network-uuid"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read ${PRIVATE}/network-uuid"
exit 1
fi
local address=$(xenstore-read "/local/domain/$DOMID/device/vif/$DEVID/mac" 2>/dev/null)
if [ -n "${address}" ] ; then
set_vif_external_id "attached-mac" "${address}"
else
logger -t scripts-vif "Failed to read /local/domain/$DOMID/device/vif/$DEVID/mac"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read /local/domain/$DOMID/device/vif/$DEVID/mac"
exit 1
fi
}
add_to_bridge()
{
local address=$(xenstore-read "${PRIVATE}/bridge-MAC")
if [ $? -ne 0 -o -z "${address}" ]; then
logger -t scripts-vif "Failed to read ${PRIVATE}/bridge-MAC from xenstore"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read ${PRIVATE}/bridge-MAC from xenstore"
exit 1
fi
local bridge=$(xenstore-read "${PRIVATE}/bridge")
if [ $? -ne 0 -o -z "${bridge}" ]; then
logger -t scripts-vif "Failed to read ${PRIVATE}/bridge from xenstore"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read ${PRIVATE}/bridge from xenstore"
exit 1
fi
logger -t scripts-vif "Adding ${dev} to ${bridge} with address ${address}"
${IP} link set "${dev}" down || logger -t scripts-vif "Failed to ip link set ${dev} down"
${IP} link set "${dev}" arp off || logger -t scripts-vif "Failed to ip link set ${dev} arp off"
${IP} link set "${dev}" multicast off || logger -t scripts-vif "Failed to ip link set ${dev} multicast off"
${IP} link set "${dev}" address "${address}" || logger -t scripts-vif "Failed to ip link set ${dev} address ${address}"
${IP} addr flush "${dev}" || logger -t scripts-vif "Failed to ip addr flush ${dev}"
case $NETWORK_MODE in
bridge)
${BRCTL} setfd "${bridge}" 0 || logger -t scripts-vif "Failed to brctl setfd ${bridge} 0"
${BRCTL} addif "${bridge}" "${dev}" || logger -t scripts-vif "Failed to brctl addif ${bridge} ${dev}"
;;
openvswitch)
if [ "$TYPE" = "vif" ] ; then
local vif_details=$(handle_vswitch_vif_details $bridge)
fi
$vsctl --timeout=30 -- --if-exists del-port $dev -- add-port $bridge $dev $vif_details
;;
esac
$setup_vif_rules $TYPE $DOMID $DEVID filter || logger -t scripts-vif "Failed to setup-vif-rules $TYPE $DOMID $DEVID filter"
}
remove_from_bridge()
{
$setup_vif_rules $TYPE $DOMID $DEVID clear || logger -t scripts-vif "Failed to setup-vif-rules $TYPE $DOMID $DEVID clear"
case $NETWORK_MODE in
bridge)
# Nothing to do
;;
openvswitch)
# If ovs-brcompatd is running, it might already have deleted the
# port. Use --if-exists to suppress the error that would otherwise
# arise in that case.
$vsctl --timeout=30 -- --if-exists del-port $dev
;;
esac
}
call_hook_script() {
local domid=$1
local action=$2
# Call the VIF hotplug hook if present
if [ -x /etc/xapi.d/vif-hotplug ]; then
local vm=$(xenstore-read "/local/domain/$domid/vm" 2>/dev/null)
if [ $? -eq 0 -a -n "${vm}" ] ; then
local vm_uuid=$(xenstore-read "$vm/uuid" 2>/dev/null)
else
logger -t scripts-vif "Failed to read /local/domain/$domid/vm"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read /local/domain/$domid/vm"
fi
if [ -n "${vm_uuid}" ] ; then
logger -t scripts-vif "VM UUID ${vm_uuid}"
else
logger -t scripts-vif "Failed to read $vm/uuid"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read $vm/uuid"
fi
local vif_uuid=$(xenstore-read "${PRIVATE}/vif-uuid" 2>/dev/null)
if [ -n "${vif_uuid}" ] ; then
logger -t scripts-vif "VIF UUID ${vif_uuid}"
else
logger -t scripts-vif "Failed to read ${PRIVATE}/vif-uuid"
xenstore-write "${HOTPLUG_ERROR}" "Failed to read ${PRIVATE}/vif-uuid"
fi
if [ -n "${vif_uuid}" -a -n "${vm_uuid}" ] ; then
logger -t scripts-vif "Calling VIF hotplug hook for VM ${vm_uuid}, VIF ${vif_uuid}"
/etc/xapi.d/vif-hotplug -action "${action}" -vifuuid "${vif_uuid}" -vmuuid "${vm_uuid}"
fi
fi
}
NETWORK_MODE=$(cat @ETCDIR@/network.conf)
ACTION=$1
# Older versions of XenServer do not pass in the type as an argument
if [[ $# -lt 2 ]]; then
TYPE=vif
else
# This script is invoked by the udev script xen-backend.rules, which
# for XCP/XS lives in xen-api.git. However, there is also a version
# included in the xen repo. For the sake of compatibility we retain
# the format of the xen scripts, for which the format of $2 is something
# like: type_if=vif. In this case, we here set TYPE to 'vif'.
TYPE=`echo $2 | cut -d= -f2`
fi
case $NETWORK_MODE in
bridge|openvswitch) ;;
vswitch) NETWORK_MODE=openvswitch ;;
*)
logger -t scripts-vif "Unknown network mode $NETWORK_MODE"
exit 1
;;
esac
case ${TYPE} in
vif)
if [ -z ${XENBUS_PATH} ]; then
DOMID=$3
DEVID=$4
XENBUS_PATH=/local/domain/$DOMID/device/vif/$DEVID
else
DOMID=`echo ${XENBUS_PATH} | cut -f 3 -d '/'`
DEVID=`echo ${XENBUS_PATH} | cut -f 4 -d '/'`
fi
dev=vif${DOMID}.${DEVID}
;;
tap)
dev=$INTERFACE
DOMID=`echo ${dev#tap} | cut -f 1 -d '.'`
DEVID=`echo ${dev#tap} | cut -f 2 -d '.'`
;;
*)
logger -t scripts-vif "unknown interface type ${TYPE}"
exit 1
;;
esac
XAPI=/xapi/${DOMID}/hotplug/vif/${DEVID}
HOTPLUG=/xapi/${DOMID}/hotplug/vif/${DEVID}
PRIVATE=/xapi/${DOMID}/private/vif/${DEVID}
HOTPLUG_STATUS="${XENBUS_PATH}/hotplug-status"
HOTPLUG_ERROR="${XENBUS_PATH}/hotplug-error"
logger -t scripts-vif "Called as \"$@\" domid:$DOMID devid:$DEVID mode:$NETWORK_MODE"
case "${ACTION}" in
online)
if [ "${TYPE}" = "vif" ] ; then
handle_ethtool rx
handle_ethtool tx
handle_ethtool sg
handle_ethtool tso
handle_ethtool ufo
handle_ethtool gso
handle_mtu
add_to_bridge
handle_promiscuous
# only for the benefit of xenrt test case, see CA-61528
xenstore-write "${HOTPLUG}/vif" "${dev}"
xenstore-write "${HOTPLUG}/hotplug" "online"
logger -t script-vif "${dev}: writing ${HOTPLUG_STATUS}=connected"
xenstore-write "${HOTPLUG_STATUS}" "connected"
call_hook_script $DOMID "${ACTION}"
fi
;;
add)
if [ "${TYPE}" = "tap" ] ; then
add_to_bridge
fi
;;
remove)
if [ "${TYPE}" = "vif" ] ;then
call_hook_script $DOMID "${ACTION}"
# Unclear whether this is necessary, since netback also does it:
logger -t script-vif "${dev}: removing ${HOTPLUG_STATUS}"
xenstore-rm "${HOTPLUG_STATUS}"
logger -t script-vif "${dev}: removing ${HOTPLUG}/hotplug"
# Trigger xapi to clean up:
xenstore-rm "${HOTPLUG}/hotplug"
fi
logger -t scripts-vif "${dev} has been removed"
remove_from_bridge
;;
move)
if [ "${TYPE}" = "vif" ] ;then
add_to_bridge
fi
esac
Jump to Line
Something went wrong with that request. Please try again.