Whamcloud - gitweb
LU-14662 lnet: set eth routes needed for multi rail
[fs/lustre-release.git] / lustre / scripts / ksocklnd-config
1 #!/bin/sh
2
3 me="${0##*/}"
4
5 # convert number of mask bits to x.x.x.x mask format
6 cidr2mask() {
7         local i mask=""
8         local full_octets=$(($1/8))
9         local partial_octet=$(($1%8))
10
11         for ((i=0;i<4;i+=1)); do
12                 if [ $i -lt $full_octets ]; then
13                         mask+=255
14                 elif [ $i -eq $full_octets ]; then
15                         mask+=$((256 - 2**(8-$partial_octet)))
16                 else
17                         mask+=0
18                 fi
19                 test $i -lt 3 && mask+=.
20         done
21
22         echo $mask
23 }
24
25 # apply netmask (second argument) to ip address (first argument)
26 netcalc() {
27         local ipa=$(echo ${1} | awk -F. '{ print $1 }')
28         local ipb=$(echo ${1} | awk -F. '{ print $2 }')
29         local ipc=$(echo ${1} | awk -F. '{ print $3 }')
30         local ipd=$(echo ${1} | awk -F. '{ print $4 }')
31         local mka=$(echo ${2} | awk -F. '{ print $1 }')
32         local mkb=$(echo ${2} | awk -F. '{ print $2 }')
33         local mkc=$(echo ${2} | awk -F. '{ print $3 }')
34         local mkd=$(echo ${2} | awk -F. '{ print $4 }')
35         local nta="$(( $ipa & $mka ))"
36         local ntb="$(( $ipb & $mkb ))"
37         local ntc="$(( $ipc & $mkc ))"
38         local ntd="$(( $ipd & $mkd ))"
39         echo "$nta.$ntb.$ntc.$ntd"
40 }
41
42 # Check if the user wants to skip setting the routes
43 checkskipcmd=$(cat /sys/module/ksocklnd/parameters/skip_mr_route_setup 2>&-)
44 if [ "$checkskipcmd" == "1" ]; then
45         exit 0
46 fi
47
48 # Extract comma-separated interfaces from the argument
49 j=0
50 declare -a interfaces
51 for i in $(echo $1 | sed "s/,/ /g")
52 do
53         # verify that the interface exists
54         #echo "$i"
55         addr=$(/sbin/ip -o -4 addr list $i 2>&- | awk '{print $4}' | cut -d/ -f1)
56         linelen=$(echo -n $addr | wc -m)
57         if [[ $linelen -eq 0 ]]; then
58                 # there's a problem with this interface, skip it
59                 #echo 'bad!'
60                 continue
61         fi
62         # check if route is already set up for this interface
63         intfroute=$(/sbin/ip route show table $i 2>&-)
64         if [[ ! -z $intfroute ]]; then
65                 # route exists so skip this interface
66                 logcmd=(logger "${me}: skip setting up route for ${i}: don\'t overwrite existing route")
67                 eval "${logcmd[@]}"
68                 continue
69         fi
70         interfaces[$j]=$i
71         j=$((j+1))
72 done
73
74 # this array will contain the interfaces
75 # already listed in rt_tables
76 interfaces_listed=()
77
78 # flush cache for every interface
79 for i in "${interfaces[@]}"
80 do
81         # build command
82         redirect="2>&-"
83         flushcmd=(/sbin/ip route flush table ${i} ${redirect} )
84         # execute command
85         eval "${flushcmd[@]}"
86         logcmd=(logger "${me}: ${flushcmd[@]}")
87         eval "${logcmd[@]}"
88 done
89
90 filename='/etc/iproute2/rt_tables'
91 n=1
92 max_table_num=0
93 while read line; do
94         # reading each line
95         # trim leading and trailing spaces
96         line=`echo $line | sed -e 's/^[[:space:]]*//'`
97         linelen=$(echo -n $line | wc -m)
98         # don't check empty lines
99         if [ $linelen -lt 1 ]; then
100                 continue
101         fi
102         # don't check comments
103         if [[ ${line:0:1} == "#" ]]; then
104                 continue
105         fi
106         # split using space as separator
107         splitline=( $line )
108         # check the table number and update the max
109         if [ $max_table_num -lt ${splitline[0]} ]; then
110                 max_table_num=${splitline[0]}
111         fi
112         # check if any of the interfaces are listed
113         for i in "${interfaces[@]}"
114         do
115                 if [[ " ${splitline[@]} " =~ " ${i} " ]]; then
116                         if [[ " ${interfaces[@]} " =~ " ${i} " ]]; then
117                                 interfaces_listed+=($i)
118                         fi
119                 fi
120         done
121         #echo "Line No. $n : $line: $max_table_num"
122         n=$((n+1))
123 done < $filename
124
125 # add entries for unlisted interfaces
126 for i in "${interfaces[@]}"
127 do
128         if [[ ! " ${interfaces_listed[@]} " =~ " ${i} " ]]; then
129                 max_table_num=$((max_table_num+1))
130                 echo "$max_table_num $i" >> $filename
131         fi
132 done
133
134 # add the routing entries and rules
135 for i in "${interfaces[@]}"
136 do
137         # extract ipv4 address and netmask in cidr format
138         addr=($(/sbin/ip -o -4 addr list $i 2>&- | awk '{print $4}' | cut -d/ -f1))
139         cidrmask=($(/sbin/ip -o -4 addr list $i 2>&- | awk '{print $4}' | cut -d/ -f2))
140         # convert cidr mask to mask in dot format
141         dotmask=$(cidr2mask ${cidrmask[0]})
142         # apply mask to ip addr
143         net=$(netcalc ${addr[0]} $dotmask)
144         # build and execute route commands
145         routecmd=(/sbin/ip route add ${net}/${cidrmask[0]} dev ${i} proto kernel scope link src ${addr[0]} table ${i})
146         ruledelcmd=(/sbin/ip rule del from ${addr[0]} table ${i} '&>/dev/null')
147         ruleaddcmd=(/sbin/ip rule add from ${addr[0]} table ${i})
148         eval ${routecmd[@]}
149         eval ${ruledelcmd[@]}
150         eval ${ruleaddcmd[@]}
151         logcmd1=(logger "${me}: ${routecmd[@]}")
152         logcmd2=(logger "${me}: ${ruledelcmd[@]}")
153         logcmd3=(logger "${me}: ${ruleaddcmd[@]}")
154         eval "${logcmd1[@]}"
155         eval "${logcmd2[@]}"
156         eval "${logcmd3[@]}"
157 done
158
159 # flush arp tables
160 for i in "${interfaces[@]}"
161 do
162         flushcmd=(/sbin/ip neigh flush dev ${i})
163         eval ${flushcmd[@]}
164 done
165