From 2a52e06d10e9e456dee2dca110895b28a5228046 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 23 Nov 2018 21:10:47 +0100 Subject: [PATCH 1/4] vxlan: Code indentation and styling fixes This script was using TAB instead of 4 spaces and had many blank lines containing whitespace. This commit also fixes some Bash styling, but it does not touch the functionality of the script. Signed-off-by: Wido den Hollander --- scripts/vm/network/vnet/modifyvxlan.sh | 358 ++++++++++++------------- 1 file changed, 177 insertions(+), 181 deletions(-) diff --git a/scripts/vm/network/vnet/modifyvxlan.sh b/scripts/vm/network/vnet/modifyvxlan.sh index f7d08f1d8c4d..67a24c70b7fa 100755 --- a/scripts/vm/network/vnet/modifyvxlan.sh +++ b/scripts/vm/network/vnet/modifyvxlan.sh @@ -26,150 +26,147 @@ usage() { } addVxlan() { - local vxlanId=$1 - local pif=$2 - local vxlanDev=vxlan$vxlanId - local vxlanBr=$3 - local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))" - - ## TODO(VXLAN): $brif (trafficlabel) should be passed from caller because we cannot assume 1:1 mapping between pif and brif. - # lookup bridge interface - local sysfs_dir=/sys/devices/virtual/net/ - local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` - - if [ "$brif " == " " ] - then - if [ -d "/sys/class/net/${pif}" ] - then - # if bridge is not found, but matches a pif, use it - brif=$pif - else - printf "Failed to lookup bridge interface which includes pif: $pif." - return 1 - fi - else - # confirm ip address of $brif - ip addr show $brif | grep -w inet - if [ $? -gt 0 ] - then - printf "Failed to find vxlan multicast source ip address on brif: $brif." - return 1 - fi - fi - - # mcast route - ## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF? - ip route get $mcastGrp | grep -w "dev $brif" - if [ $? -gt 0 ] - then - ip route add $mcastGrp/32 dev $brif - if [ $? -gt 0 ] - then - printf "Failed to add vxlan multicast route on brif: $brif." - return 1 - fi - fi - - if [ ! -d /sys/class/net/$vxlanDev ] - then - ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif - - if [ $? -gt 0 ] - then - # race condition that someone already creates the vxlan - if [ ! -d /sys/class/net/$vxlanDev ] - then - printf "Failed to create vxlan $vxlanId on brif: $brif." - return 1 - fi - fi - fi - - # is up? - ip link show $vxlanDev | grep -w UP > /dev/null - if [ $? -gt 0 ] - then - ip link set $vxlanDev up > /dev/null - fi - - if [ ! -d /sys/class/net/$vxlanBr ] - then - brctl addbr $vxlanBr > /dev/null - - if [ $? -gt 0 ] - then - if [ ! -d /sys/class/net/$vxlanBr ] - then - printf "Failed to create br: $vxlanBr" - return 2 - fi - fi - - brctl setfd $vxlanBr 0 - fi - - #pif is eslaved into vxlanBr? - ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null - if [ $? -gt 0 ] - then - brctl addif $vxlanBr $vxlanDev > /dev/null - if [ $? -gt 0 ] - then - ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null - if [ $? -gt 0 ] - then - printf "Failed to add vxlan: $vxlanDev to $vxlanBr" - return 3 - fi - fi - fi - - # is vxlanBr up? - ip link show $vxlanBr | grep -w UP > /dev/null - if [ $? -gt 0 ] - then - ip link set $vxlanBr up - fi - - return 0 + local vxlanId=$1 + local pif=$2 + local vxlanDev=vxlan$vxlanId + local vxlanBr=$3 + local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))" + + ## TODO(VXLAN): $brif (trafficlabel) should be passed from caller because we cannot assume 1:1 mapping between pif and brif. + # lookup bridge interface + local sysfs_dir=/sys/devices/virtual/net/ + local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` + + if [ "$brif " == " " ] + then + if [ -d "/sys/class/net/${pif}" ] + then + # if bridge is not found, but matches a pif, use it + brif=$pif + else + printf "Failed to lookup bridge interface which includes pif: $pif." + return 1 + fi + else + # confirm ip address of $brif + ip addr show $brif | grep -w inet + if [ $? -gt 0 ] + then + printf "Failed to find vxlan multicast source ip address on brif: $brif." + return 1 + fi + fi + + # mcast route + ## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF? + ip route get $mcastGrp | grep -w "dev $brif" + if [ $? -gt 0 ] + then + ip route add $mcastGrp/32 dev $brif + if [ $? -gt 0 ] + then + printf "Failed to add vxlan multicast route on brif: $brif." + return 1 + fi + fi + + if [ ! -d /sys/class/net/$vxlanDev ] + then + ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif + if [ $? -gt 0 ] + then + # race condition that someone already creates the vxlan + if [ ! -d /sys/class/net/$vxlanDev ] + then + printf "Failed to create vxlan $vxlanId on brif: $brif." + return 1 + fi + fi + fi + + # is up? + ip link show $vxlanDev | grep -w UP > /dev/null + if [ $? -gt 0 ] + then + ip link set $vxlanDev up > /dev/null + fi + + if [ ! -d /sys/class/net/$vxlanBr ] + then + brctl addbr $vxlanBr > /dev/null + if [ $? -gt 0 ] + then + if [ ! -d /sys/class/net/$vxlanBr ] + then + printf "Failed to create br: $vxlanBr" + return 2 + fi + fi + brctl setfd $vxlanBr 0 + fi + + #pif is eslaved into vxlanBr? + ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null + if [ $? -gt 0 ] + then + brctl addif $vxlanBr $vxlanDev > /dev/null + if [ $? -gt 0 ] + then + ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null + if [ $? -gt 0 ] + then + printf "Failed to add vxlan: $vxlanDev to $vxlanBr" + return 3 + fi + fi + fi + + # is vxlanBr up? + ip link show $vxlanBr | grep -w UP > /dev/null + if [ $? -gt 0 ] + then + ip link set $vxlanBr up + fi + + return 0 } deleteVxlan() { - local vxlanId=$1 - local pif=$2 - local vxlanDev=vxlan$vxlanId - local vxlanBr=$3 - local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))" - - local sysfs_dir=/sys/devices/virtual/net/ - local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` - - ip route del $mcastGrp/32 dev $brif - - ip link delete $vxlanDev - - if [ $? -gt 0 ] - then - printf "Failed to del vxlan: $vxlanId" - printf "Continue..." - fi - - ip link set $vxlanBr down - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl delbr $vxlanBr - - if [ $? -gt 0 ] - then - printf "Failed to del bridge $vxlanBr" - return 1 - fi - - return 0 + local vxlanId=$1 + local pif=$2 + local vxlanDev=vxlan$vxlanId + local vxlanBr=$3 + local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))" + + local sysfs_dir=/sys/devices/virtual/net/ + local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` + + ip route del $mcastGrp/32 dev $brif + + ip link delete $vxlanDev + + if [ $? -gt 0 ] + then + printf "Failed to del vxlan: $vxlanId" + printf "Continue..." + fi + + ip link set $vxlanBr down + + if [ $? -gt 0 ] + then + return 1 + fi + + brctl delbr $vxlanBr + + if [ $? -gt 0 ] + then + printf "Failed to del bridge $vxlanBr" + return 1 + fi + + return 0 } op= @@ -179,61 +176,60 @@ option=$@ while getopts 'o:v:p:b:' OPTION do case $OPTION in - o) oflag=1 - op="$OPTARG" - ;; - v) vflag=1 - vxlanId="$OPTARG" - ;; - p) pflag=1 - pif="$OPTARG" - ;; - b) bflag=1 - brName="$OPTARG" - ;; - ?) usage - exit 2 - ;; + o) oflag=1 + op="$OPTARG" + ;; + v) vflag=1 + vxlanId="$OPTARG" + ;; + p) pflag=1 + pif="$OPTARG" + ;; + b) bflag=1 + brName="$OPTARG" + ;; + ?) usage + exit 2 + ;; esac done # Check that all arguments were passed in if [ "$oflag$vflag$pflag$bflag" != "1111" ] then - usage - exit 2 + usage + exit 2 fi # Do we support Vxlan? lsmod|grep ^vxlan >& /dev/null if [ $? -gt 0 ] then - modprobe=`modprobe vxlan 2>&1` - if [ $? -gt 0 ] - then - printf "Failed to load vxlan kernel module: $modprobe" - exit 1 - fi + modprobe=`modprobe vxlan 2>&1` + if [ $? -gt 0 ] + then + printf "Failed to load vxlan kernel module: $modprobe" + exit 1 + fi fi if [ "$op" == "add" ] then - # Add the vxlan - addVxlan $vxlanId $pif $brName - - # If the add fails then return failure - if [ $? -gt 0 ] - then - exit 1 - fi + # Add the vxlan + addVxlan $vxlanId $pif $brName + + # If the add fails then return failure + if [ $? -gt 0 ] + then + exit 1 + fi else - if [ "$op" == "delete" ] - then - # Delete the vxlan - deleteVxlan $vxlanId $pif $brName - - # Always exit with success - exit 0 - fi + if [ "$op" == "delete" ] + then + # Delete the vxlan + deleteVxlan $vxlanId $pif $brName + + # Always exit with success + exit 0 + fi fi - From 9844cf076cab92fc806355af40a4a2985438ece1 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Thu, 29 Nov 2018 17:11:52 +0100 Subject: [PATCH 2/4] vxlan: Improve Bash if-statement logic Bash suggest using double brackets instead of single brackets in if-statement test logic Signed-off-by: Wido den Hollander --- scripts/vm/network/vnet/modifyvxlan.sh | 48 +++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/scripts/vm/network/vnet/modifyvxlan.sh b/scripts/vm/network/vnet/modifyvxlan.sh index 67a24c70b7fa..92cce9afa8ea 100755 --- a/scripts/vm/network/vnet/modifyvxlan.sh +++ b/scripts/vm/network/vnet/modifyvxlan.sh @@ -37,9 +37,9 @@ addVxlan() { local sysfs_dir=/sys/devices/virtual/net/ local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` - if [ "$brif " == " " ] + if [[ "$brif " == " " ]] then - if [ -d "/sys/class/net/${pif}" ] + if [[ -d "/sys/class/net/${pif}" ]] then # if bridge is not found, but matches a pif, use it brif=$pif @@ -50,7 +50,7 @@ addVxlan() { else # confirm ip address of $brif ip addr show $brif | grep -w inet - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then printf "Failed to find vxlan multicast source ip address on brif: $brif." return 1 @@ -60,23 +60,23 @@ addVxlan() { # mcast route ## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF? ip route get $mcastGrp | grep -w "dev $brif" - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then ip route add $mcastGrp/32 dev $brif - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then printf "Failed to add vxlan multicast route on brif: $brif." return 1 fi fi - if [ ! -d /sys/class/net/$vxlanDev ] + if [[ ! -d /sys/class/net/$vxlanDev ]] then ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then # race condition that someone already creates the vxlan - if [ ! -d /sys/class/net/$vxlanDev ] + if [[ ! -d /sys/class/net/$vxlanDev ]] then printf "Failed to create vxlan $vxlanId on brif: $brif." return 1 @@ -86,17 +86,17 @@ addVxlan() { # is up? ip link show $vxlanDev | grep -w UP > /dev/null - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then ip link set $vxlanDev up > /dev/null fi - if [ ! -d /sys/class/net/$vxlanBr ] + if [[ ! -d /sys/class/net/$vxlanBr ]] then brctl addbr $vxlanBr > /dev/null - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then - if [ ! -d /sys/class/net/$vxlanBr ] + if [[ ! -d /sys/class/net/$vxlanBr ]] then printf "Failed to create br: $vxlanBr" return 2 @@ -107,13 +107,13 @@ addVxlan() { #pif is eslaved into vxlanBr? ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then brctl addif $vxlanBr $vxlanDev > /dev/null - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then printf "Failed to add vxlan: $vxlanDev to $vxlanBr" return 3 @@ -123,7 +123,7 @@ addVxlan() { # is vxlanBr up? ip link show $vxlanBr | grep -w UP > /dev/null - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then ip link set $vxlanBr up fi @@ -145,7 +145,7 @@ deleteVxlan() { ip link delete $vxlanDev - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then printf "Failed to del vxlan: $vxlanId" printf "Continue..." @@ -153,14 +153,14 @@ deleteVxlan() { ip link set $vxlanBr down - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then return 1 fi brctl delbr $vxlanBr - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then printf "Failed to del bridge $vxlanBr" return 1 @@ -195,7 +195,7 @@ do done # Check that all arguments were passed in -if [ "$oflag$vflag$pflag$bflag" != "1111" ] +if [[ "$oflag$vflag$pflag$bflag" != "1111" ]] then usage exit 2 @@ -203,17 +203,17 @@ fi # Do we support Vxlan? lsmod|grep ^vxlan >& /dev/null -if [ $? -gt 0 ] +if [[ $? -gt 0 ]] then modprobe=`modprobe vxlan 2>&1` - if [ $? -gt 0 ] + if [[ $? -gt 0 ]] then printf "Failed to load vxlan kernel module: $modprobe" exit 1 fi fi -if [ "$op" == "add" ] +if [[ "$op" == "add" ]] then # Add the vxlan addVxlan $vxlanId $pif $brName @@ -224,7 +224,7 @@ then exit 1 fi else - if [ "$op" == "delete" ] + if [[ "$op" == "delete" ]] then # Delete the vxlan deleteVxlan $vxlanId $pif $brName From d182cb38d178fe2475fd9d68c22e53b97fc9c2c1 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Thu, 29 Nov 2018 17:13:32 +0100 Subject: [PATCH 3/4] vxlan: Disable IPv6 on bridge and VXLAN devices They are only transport devices and should not be interacting in the IPv6 traffic. If IPv6 is enabled Instances can connect to the Hypervisor over Link-Local IPv6 which is a potential security issue. By disabling IPv6 on the Bridge and VXLAN device they still forward Layer 2 packets as intended, but they do not respond on anything. IPv4 and IPv6 traffic towards the Instances is untouched and works as before. Signed-off-by: Wido den Hollander --- scripts/vm/network/vnet/modifyvxlan.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/vm/network/vnet/modifyvxlan.sh b/scripts/vm/network/vnet/modifyvxlan.sh index 92cce9afa8ea..06fbcd6b466b 100755 --- a/scripts/vm/network/vnet/modifyvxlan.sh +++ b/scripts/vm/network/vnet/modifyvxlan.sh @@ -82,6 +82,7 @@ addVxlan() { return 1 fi fi + sysctl -w net.ipv6.conf.$vxlanDev.disable_ipv6=1 fi # is up? @@ -102,6 +103,7 @@ addVxlan() { return 2 fi fi + sysctl -w net.ipv6.conf.$vxlanBr.disable_ipv6=1 brctl setfd $vxlanBr 0 fi From 8a8cffa2e4a1923793052253758ebf6546ceeff9 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Fri, 30 Nov 2018 15:44:22 +0100 Subject: [PATCH 4/4] vxlan: Refactor modifyvxlan.sh for KVM by using only iproute2 This commit refactors the modifyvxlan.sh script by using only iproute2, the 'ip' command for all functions. brctl is deprecated and most bridge functionality can be performed with the 'ip' command. This commit also fixes various Bash coding fixes and removes a lot of exit status checking which was redundant. In addition it add IPv6 underlay for VXLAN transport. If the caller (KVM Agent) adds the '-6' flag it will generate IPv6 multicast groups and routes which will transport the VXLAN encapsulated packaes over IPv6 multicast groups. Signed-off-by: Wido den Hollander --- scripts/vm/network/vnet/modifyvxlan.sh | 250 ++++++++----------------- 1 file changed, 79 insertions(+), 171 deletions(-) diff --git a/scripts/vm/network/vnet/modifyvxlan.sh b/scripts/vm/network/vnet/modifyvxlan.sh index 06fbcd6b466b..3aa19ad424d6 100755 --- a/scripts/vm/network/vnet/modifyvxlan.sh +++ b/scripts/vm/network/vnet/modifyvxlan.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -16,179 +16,92 @@ # specific language governing permissions and limitations # under the License. -# modifyvxlan.sh -- adds and deletes VXLANs from a Routing Server -# set -x - -## TODO(VXLAN): MTU, IPv6 underlying +# modifyvxlan.sh -- Managed VXLAN devices and Bridges on Linux KVM hypervisor usage() { - printf "Usage: %s: -o (add | delete) -v -p -b \n" + echo "Usage: $0: -o (add | delete) -v -p -b (-6)" } -addVxlan() { - local vxlanId=$1 - local pif=$2 - local vxlanDev=vxlan$vxlanId - local vxlanBr=$3 - local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))" - - ## TODO(VXLAN): $brif (trafficlabel) should be passed from caller because we cannot assume 1:1 mapping between pif and brif. - # lookup bridge interface - local sysfs_dir=/sys/devices/virtual/net/ - local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` - - if [[ "$brif " == " " ]] - then - if [[ -d "/sys/class/net/${pif}" ]] - then - # if bridge is not found, but matches a pif, use it - brif=$pif - else - printf "Failed to lookup bridge interface which includes pif: $pif." - return 1 - fi - else - # confirm ip address of $brif - ip addr show $brif | grep -w inet - if [[ $? -gt 0 ]] - then - printf "Failed to find vxlan multicast source ip address on brif: $brif." - return 1 - fi - fi - - # mcast route - ## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF? - ip route get $mcastGrp | grep -w "dev $brif" - if [[ $? -gt 0 ]] - then - ip route add $mcastGrp/32 dev $brif - if [[ $? -gt 0 ]] - then - printf "Failed to add vxlan multicast route on brif: $brif." - return 1 - fi - fi - - if [[ ! -d /sys/class/net/$vxlanDev ]] - then - ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif - if [[ $? -gt 0 ]] - then - # race condition that someone already creates the vxlan - if [[ ! -d /sys/class/net/$vxlanDev ]] - then - printf "Failed to create vxlan $vxlanId on brif: $brif." - return 1 - fi - fi - sysctl -w net.ipv6.conf.$vxlanDev.disable_ipv6=1 +multicastGroup() { + local VNI=$1 + local FAMILY=$2 + if [[ -z "$FAMILY" || $FAMILY == "inet" ]]; then + echo "239.$(( (${VNI} >> 16) % 256 )).$(( (${VNI} >> 8) % 256 )).$(( ${VNI} % 256 ))" fi - # is up? - ip link show $vxlanDev | grep -w UP > /dev/null - if [[ $? -gt 0 ]] - then - ip link set $vxlanDev up > /dev/null + if [[ "$FAMILY" == "inet6" ]]; then + echo "ff05::$(( (${VNI} >> 16) % 256 )):$(( (${VNI} >> 8) % 256 )):$(( ${VNI} % 256 ))" fi +} - if [[ ! -d /sys/class/net/$vxlanBr ]] - then - brctl addbr $vxlanBr > /dev/null - if [[ $? -gt 0 ]] - then - if [[ ! -d /sys/class/net/$vxlanBr ]] - then - printf "Failed to create br: $vxlanBr" - return 2 - fi - fi - sysctl -w net.ipv6.conf.$vxlanBr.disable_ipv6=1 - brctl setfd $vxlanBr 0 +addVxlan() { + local VNI=$1 + local PIF=$2 + local VXLAN_BR=$3 + local FAMILY=$4 + local VXLAN_DEV=vxlan${VNI} + local GROUP=$(multicastGroup ${VNI} ${FAMILY}) + + echo "multicast ${GROUP} for VNI ${VNI} on ${PIF}" + + if [[ ! -d /sys/class/net/${VXLAN_DEV} ]]; then + ip -f ${FAMILY} link add ${VXLAN_DEV} type vxlan id ${VNI} group ${GROUP} ttl 10 dev ${PIF} + ip link set ${VXLAN_DEV} up + ip -f ${FAMILY} route add ${GROUP} dev ${PIF} + sysctl -qw net.ipv6.conf.${VXLAN_DEV}.disable_ipv6=1 fi - #pif is eslaved into vxlanBr? - ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null - if [[ $? -gt 0 ]] - then - brctl addif $vxlanBr $vxlanDev > /dev/null - if [[ $? -gt 0 ]] - then - ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null - if [[ $? -gt 0 ]] - then - printf "Failed to add vxlan: $vxlanDev to $vxlanBr" - return 3 - fi - fi + if [[ ! -d /sys/class/net/$VXLAN_BR ]]; then + ip link add name ${VXLAN_BR} type bridge + ip link set ${VXLAN_BR} up + sysctl -qw net.ipv6.conf.${VXLAN_BR}.disable_ipv6=1 fi - # is vxlanBr up? - ip link show $vxlanBr | grep -w UP > /dev/null - if [[ $? -gt 0 ]] - then - ip link set $vxlanBr up + bridge link show|grep ${VXLAN_BR}|awk '{print $2}'|grep "^${VXLAN_DEV}\$" > /dev/null + if [[ $? -gt 0 ]]; then + ip link set ${VXLAN_DEV} master ${VXLAN_BR} fi - - return 0 } deleteVxlan() { - local vxlanId=$1 - local pif=$2 - local vxlanDev=vxlan$vxlanId - local vxlanBr=$3 - local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))" - - local sysfs_dir=/sys/devices/virtual/net/ - local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'` - - ip route del $mcastGrp/32 dev $brif + local VNI=$1 + local PIF=$2 + local VXLAN_BR=$3 + local FAMILY=$4 + local VXLAN_DEV=vxlan${VNI} + local GROUP=$(multicastGroup ${VNI} ${FAMILY}) - ip link delete $vxlanDev + ip -f ${FAMILY} route del ${GROUP} dev ${PIF} - if [[ $? -gt 0 ]] - then - printf "Failed to del vxlan: $vxlanId" - printf "Continue..." - fi - - ip link set $vxlanBr down - - if [[ $? -gt 0 ]] - then - return 1 - fi + ip link set ${VXLAN_DEV} nomaster + ip link delete ${VXLAN_DEV} - brctl delbr $vxlanBr - - if [[ $? -gt 0 ]] - then - printf "Failed to del bridge $vxlanBr" - return 1 - fi - - return 0 + ip link set ${VXLAN_BR} down + ip link delete ${VXLAN_BR} type bridge } -op= -vxlanId= +OP= +VNI= +FAMILY=inet option=$@ -while getopts 'o:v:p:b:' OPTION +while getopts 'o:v:p:b:6' OPTION do case $OPTION in o) oflag=1 - op="$OPTARG" + OP="$OPTARG" ;; v) vflag=1 - vxlanId="$OPTARG" + VNI="$OPTARG" ;; p) pflag=1 - pif="$OPTARG" + PIF="$OPTARG" ;; b) bflag=1 - brName="$OPTARG" + BRNAME="$OPTARG" + ;; + 6) + FAMILY=inet6 ;; ?) usage exit 2 @@ -196,42 +109,37 @@ do esac done -# Check that all arguments were passed in -if [[ "$oflag$vflag$pflag$bflag" != "1111" ]] -then +if [[ "$oflag$vflag$pflag$bflag" != "1111" ]]; then usage exit 2 fi -# Do we support Vxlan? lsmod|grep ^vxlan >& /dev/null -if [[ $? -gt 0 ]] -then +if [[ $? -gt 0 ]]; then modprobe=`modprobe vxlan 2>&1` - if [[ $? -gt 0 ]] - then - printf "Failed to load vxlan kernel module: $modprobe" + if [[ $? -gt 0 ]]; then + echo "Failed to load vxlan kernel module: $modprobe" exit 1 fi fi -if [[ "$op" == "add" ]] -then - # Add the vxlan - addVxlan $vxlanId $pif $brName - - # If the add fails then return failure - if [ $? -gt 0 ] - then - exit 1 - fi -else - if [[ "$op" == "delete" ]] - then - # Delete the vxlan - deleteVxlan $vxlanId $pif $brName - - # Always exit with success - exit 0 + +# +# Add a lockfile to prevent this script from running twice on the same host +# this can cause a race condition +# + +LOCKFILE=/var/run/cloud/vxlan.lock + +( + flock -x -w 10 200 || exit 1 + if [[ "$OP" == "add" ]]; then + addVxlan ${VNI} ${PIF} ${BRNAME} ${FAMILY} + + if [[ $? -gt 0 ]]; then + exit 1 + fi + elif [[ "$OP" == "delete" ]]; then + deleteVxlan ${VNI} ${PIF} ${BRNAME} ${FAMILY} fi -fi +) 200>${LOCKFILE}