#!/bin/bash

#============================================================================
# /etc/xen/vif-route
#
# Script for configuring a vif in routed 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 /etc/xen/xend-config.sxp.  If the script is specified in neither of those
# places, then vif-bridge is the default.
#
# Usage:
# vif-route (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:
# ip     list of IP networks for the vif, space-separated (default given in
#        this script).
#
# This script will set up proxy arp  for any ip addresses that are being routed
# type read to determine if the device is ioemu

#============================================================================
dir=$(dirname "$0")
. "$dir/vif-common.sh"

main_ip=$(dom0_ip)
dev=${dev:-${vif}}

case "$command" in
    online|add)
	ifconfig ${dev} ${main_ip} netmask 255.255.255.255 up
	echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp
	echo 1 >/proc/sys/net/ipv4/conf/${dev}/rp_filter 
	xenstore-write "$XENBUS_PATH/feature-gso-tcpv4" 0
	if [ x${qemu_online} != xyes ]; then
	  ethtool -K ${dev} tx off
	fi
	ipcmd='add'
	ipt_action='-A'
	cmdprefix=''
	;;
    offline|remove)
	do_without_error ifdown ${vif}
	ipcmd='del'
	ipt_action='-D'
	cmdprefix='do_without_error'
	;;
esac

vif_type=$(xenstore_read_default "$XENBUS_PATH/type" "viffront")
if [  ${vif_type} != "ioemu"  -o  x${qemu_online} = xyes ] ; then
    if [ "${ip}" ] ; then
    # If we've been given a list of IP addresses, then add routes from dom0 to
    # the guest using those addresses.
	for addr in ${ip} ; do
	    # When PVHVM is enabled, Xen plugs two interfaces into
	    # HVMs - an emulated tap device and a paravirt vif device.
	    # vif-invirtroute (and vif-route, for that matter!) will
	    # fail when the second one is brought up, because the
	    # second invocation of 'ip route add' is identical to the
	    # first (same source and destination IPs) and the kernel
	    # rejects the new route.
	    #
	    # We work around this by adding the routes with different metrics.
	    # This should work because:
	    #
	    # 1) In the case of a pv-aware guest, the kernel will
	    # unplug the tap interface, which will bring down the tap
	    # interface's route, leaving only the one via the vif (and
	    # so the metric shouldn't matter, because it's the only
	    # route)
	    #
	    # 2) In the case of a non-pv-aware guest, the tap route
	    # (with metric 1) should take precedence over the vif
	    # route and carry all the traffic.

	    src=""
	    if [ $ipcmd == "add" ]; then
		src="src ${main_ip}"
		case $dev in
		    vif*)
			metric="metric 2"
			;;
		    tap*)
			metric="metric 1"
			;;
		esac
	    fi
	    ${cmdprefix} ip route ${ipcmd} ${addr} dev ${dev} ${src} $metric
	    case "$command" in
		online|add)
		    timeout -s KILL 5 arpspoof -i $(invirt-getconf xen.iface) -t ${gateway} ${addr} || :
		    ;;
	    esac
	done 
	if [ -n "$other_ip" ]; then
	    ${cmdprefix} ip route ${ipcmd} ${other_ip} dev ${dev} ${src} $metric
	    iptables -t nat ${ipt_action} PREROUTING -d ${other_ip} -j DNAT --to-destination ${addr}
	    case "$command" in
		online|add)
		    timeout -s KILL 5 arpspoof -i $(invirt-getconf xen.iface) -t ${other_gateway} ${other_ip} || :
		    ;;
	    esac
	fi
    fi
fi

log debug "Successful vif-route $command for $vif."
case "$command" in
    online|add)
	success
	;;
esac