Skip to content

Commit 8a8cffa

Browse files
committed
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 <wido@widodh.nl>
1 parent d182cb3 commit 8a8cffa

1 file changed

Lines changed: 79 additions & 171 deletions

File tree

scripts/vm/network/vnet/modifyvxlan.sh

Lines changed: 79 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -6,232 +6,140 @@
66
# to you under the Apache License, Version 2.0 (the
77
# "License"); you may not use this file except in compliance
88
# with the License. You may obtain a copy of the License at
9-
#
9+
#
1010
# http://www.apache.org/licenses/LICENSE-2.0
11-
#
11+
#
1212
# Unless required by applicable law or agreed to in writing,
1313
# software distributed under the License is distributed on an
1414
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1515
# KIND, either express or implied. See the License for the
1616
# specific language governing permissions and limitations
1717
# under the License.
1818

19-
# modifyvxlan.sh -- adds and deletes VXLANs from a Routing Server
20-
# set -x
21-
22-
## TODO(VXLAN): MTU, IPv6 underlying
19+
# modifyvxlan.sh -- Managed VXLAN devices and Bridges on Linux KVM hypervisor
2320

2421
usage() {
25-
printf "Usage: %s: -o <op>(add | delete) -v <vxlan id> -p <pif> -b <bridge name>\n"
22+
echo "Usage: $0: -o <op>(add | delete) -v <vxlan id> -p <pif> -b <bridge name> (-6)"
2623
}
2724

28-
addVxlan() {
29-
local vxlanId=$1
30-
local pif=$2
31-
local vxlanDev=vxlan$vxlanId
32-
local vxlanBr=$3
33-
local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))"
34-
35-
## TODO(VXLAN): $brif (trafficlabel) should be passed from caller because we cannot assume 1:1 mapping between pif and brif.
36-
# lookup bridge interface
37-
local sysfs_dir=/sys/devices/virtual/net/
38-
local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'`
39-
40-
if [[ "$brif " == " " ]]
41-
then
42-
if [[ -d "/sys/class/net/${pif}" ]]
43-
then
44-
# if bridge is not found, but matches a pif, use it
45-
brif=$pif
46-
else
47-
printf "Failed to lookup bridge interface which includes pif: $pif."
48-
return 1
49-
fi
50-
else
51-
# confirm ip address of $brif
52-
ip addr show $brif | grep -w inet
53-
if [[ $? -gt 0 ]]
54-
then
55-
printf "Failed to find vxlan multicast source ip address on brif: $brif."
56-
return 1
57-
fi
58-
fi
59-
60-
# mcast route
61-
## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF?
62-
ip route get $mcastGrp | grep -w "dev $brif"
63-
if [[ $? -gt 0 ]]
64-
then
65-
ip route add $mcastGrp/32 dev $brif
66-
if [[ $? -gt 0 ]]
67-
then
68-
printf "Failed to add vxlan multicast route on brif: $brif."
69-
return 1
70-
fi
71-
fi
72-
73-
if [[ ! -d /sys/class/net/$vxlanDev ]]
74-
then
75-
ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif
76-
if [[ $? -gt 0 ]]
77-
then
78-
# race condition that someone already creates the vxlan
79-
if [[ ! -d /sys/class/net/$vxlanDev ]]
80-
then
81-
printf "Failed to create vxlan $vxlanId on brif: $brif."
82-
return 1
83-
fi
84-
fi
85-
sysctl -w net.ipv6.conf.$vxlanDev.disable_ipv6=1
25+
multicastGroup() {
26+
local VNI=$1
27+
local FAMILY=$2
28+
if [[ -z "$FAMILY" || $FAMILY == "inet" ]]; then
29+
echo "239.$(( (${VNI} >> 16) % 256 )).$(( (${VNI} >> 8) % 256 )).$(( ${VNI} % 256 ))"
8630
fi
8731

88-
# is up?
89-
ip link show $vxlanDev | grep -w UP > /dev/null
90-
if [[ $? -gt 0 ]]
91-
then
92-
ip link set $vxlanDev up > /dev/null
32+
if [[ "$FAMILY" == "inet6" ]]; then
33+
echo "ff05::$(( (${VNI} >> 16) % 256 )):$(( (${VNI} >> 8) % 256 )):$(( ${VNI} % 256 ))"
9334
fi
35+
}
9436

95-
if [[ ! -d /sys/class/net/$vxlanBr ]]
96-
then
97-
brctl addbr $vxlanBr > /dev/null
98-
if [[ $? -gt 0 ]]
99-
then
100-
if [[ ! -d /sys/class/net/$vxlanBr ]]
101-
then
102-
printf "Failed to create br: $vxlanBr"
103-
return 2
104-
fi
105-
fi
106-
sysctl -w net.ipv6.conf.$vxlanBr.disable_ipv6=1
107-
brctl setfd $vxlanBr 0
37+
addVxlan() {
38+
local VNI=$1
39+
local PIF=$2
40+
local VXLAN_BR=$3
41+
local FAMILY=$4
42+
local VXLAN_DEV=vxlan${VNI}
43+
local GROUP=$(multicastGroup ${VNI} ${FAMILY})
44+
45+
echo "multicast ${GROUP} for VNI ${VNI} on ${PIF}"
46+
47+
if [[ ! -d /sys/class/net/${VXLAN_DEV} ]]; then
48+
ip -f ${FAMILY} link add ${VXLAN_DEV} type vxlan id ${VNI} group ${GROUP} ttl 10 dev ${PIF}
49+
ip link set ${VXLAN_DEV} up
50+
ip -f ${FAMILY} route add ${GROUP} dev ${PIF}
51+
sysctl -qw net.ipv6.conf.${VXLAN_DEV}.disable_ipv6=1
10852
fi
10953

110-
#pif is eslaved into vxlanBr?
111-
ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null
112-
if [[ $? -gt 0 ]]
113-
then
114-
brctl addif $vxlanBr $vxlanDev > /dev/null
115-
if [[ $? -gt 0 ]]
116-
then
117-
ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null
118-
if [[ $? -gt 0 ]]
119-
then
120-
printf "Failed to add vxlan: $vxlanDev to $vxlanBr"
121-
return 3
122-
fi
123-
fi
54+
if [[ ! -d /sys/class/net/$VXLAN_BR ]]; then
55+
ip link add name ${VXLAN_BR} type bridge
56+
ip link set ${VXLAN_BR} up
57+
sysctl -qw net.ipv6.conf.${VXLAN_BR}.disable_ipv6=1
12458
fi
12559

126-
# is vxlanBr up?
127-
ip link show $vxlanBr | grep -w UP > /dev/null
128-
if [[ $? -gt 0 ]]
129-
then
130-
ip link set $vxlanBr up
60+
bridge link show|grep ${VXLAN_BR}|awk '{print $2}'|grep "^${VXLAN_DEV}\$" > /dev/null
61+
if [[ $? -gt 0 ]]; then
62+
ip link set ${VXLAN_DEV} master ${VXLAN_BR}
13163
fi
132-
133-
return 0
13464
}
13565

13666
deleteVxlan() {
137-
local vxlanId=$1
138-
local pif=$2
139-
local vxlanDev=vxlan$vxlanId
140-
local vxlanBr=$3
141-
local mcastGrp="239.$(( ($vxlanId >> 16) % 256 )).$(( ($vxlanId >> 8) % 256 )).$(( $vxlanId % 256 ))"
142-
143-
local sysfs_dir=/sys/devices/virtual/net/
144-
local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'`
145-
146-
ip route del $mcastGrp/32 dev $brif
67+
local VNI=$1
68+
local PIF=$2
69+
local VXLAN_BR=$3
70+
local FAMILY=$4
71+
local VXLAN_DEV=vxlan${VNI}
72+
local GROUP=$(multicastGroup ${VNI} ${FAMILY})
14773

148-
ip link delete $vxlanDev
74+
ip -f ${FAMILY} route del ${GROUP} dev ${PIF}
14975

150-
if [[ $? -gt 0 ]]
151-
then
152-
printf "Failed to del vxlan: $vxlanId"
153-
printf "Continue..."
154-
fi
155-
156-
ip link set $vxlanBr down
157-
158-
if [[ $? -gt 0 ]]
159-
then
160-
return 1
161-
fi
76+
ip link set ${VXLAN_DEV} nomaster
77+
ip link delete ${VXLAN_DEV}
16278

163-
brctl delbr $vxlanBr
164-
165-
if [[ $? -gt 0 ]]
166-
then
167-
printf "Failed to del bridge $vxlanBr"
168-
return 1
169-
fi
170-
171-
return 0
79+
ip link set ${VXLAN_BR} down
80+
ip link delete ${VXLAN_BR} type bridge
17281
}
17382

174-
op=
175-
vxlanId=
83+
OP=
84+
VNI=
85+
FAMILY=inet
17686
option=$@
17787

178-
while getopts 'o:v:p:b:' OPTION
88+
while getopts 'o:v:p:b:6' OPTION
17989
do
18090
case $OPTION in
18191
o) oflag=1
182-
op="$OPTARG"
92+
OP="$OPTARG"
18393
;;
18494
v) vflag=1
185-
vxlanId="$OPTARG"
95+
VNI="$OPTARG"
18696
;;
18797
p) pflag=1
188-
pif="$OPTARG"
98+
PIF="$OPTARG"
18999
;;
190100
b) bflag=1
191-
brName="$OPTARG"
101+
BRNAME="$OPTARG"
102+
;;
103+
6)
104+
FAMILY=inet6
192105
;;
193106
?) usage
194107
exit 2
195108
;;
196109
esac
197110
done
198111

199-
# Check that all arguments were passed in
200-
if [[ "$oflag$vflag$pflag$bflag" != "1111" ]]
201-
then
112+
if [[ "$oflag$vflag$pflag$bflag" != "1111" ]]; then
202113
usage
203114
exit 2
204115
fi
205116

206-
# Do we support Vxlan?
207117
lsmod|grep ^vxlan >& /dev/null
208-
if [[ $? -gt 0 ]]
209-
then
118+
if [[ $? -gt 0 ]]; then
210119
modprobe=`modprobe vxlan 2>&1`
211-
if [[ $? -gt 0 ]]
212-
then
213-
printf "Failed to load vxlan kernel module: $modprobe"
120+
if [[ $? -gt 0 ]]; then
121+
echo "Failed to load vxlan kernel module: $modprobe"
214122
exit 1
215123
fi
216124
fi
217125

218-
if [[ "$op" == "add" ]]
219-
then
220-
# Add the vxlan
221-
addVxlan $vxlanId $pif $brName
222-
223-
# If the add fails then return failure
224-
if [ $? -gt 0 ]
225-
then
226-
exit 1
227-
fi
228-
else
229-
if [[ "$op" == "delete" ]]
230-
then
231-
# Delete the vxlan
232-
deleteVxlan $vxlanId $pif $brName
233-
234-
# Always exit with success
235-
exit 0
126+
127+
#
128+
# Add a lockfile to prevent this script from running twice on the same host
129+
# this can cause a race condition
130+
#
131+
132+
LOCKFILE=/var/run/cloud/vxlan.lock
133+
134+
(
135+
flock -x -w 10 200 || exit 1
136+
if [[ "$OP" == "add" ]]; then
137+
addVxlan ${VNI} ${PIF} ${BRNAME} ${FAMILY}
138+
139+
if [[ $? -gt 0 ]]; then
140+
exit 1
141+
fi
142+
elif [[ "$OP" == "delete" ]]; then
143+
deleteVxlan ${VNI} ${PIF} ${BRNAME} ${FAMILY}
236144
fi
237-
fi
145+
) 200>${LOCKFILE}

0 commit comments

Comments
 (0)