1 #!/bin/sh 2 #============================================================================== 3 # Copyright (c) Linux Test Project, 2014 4 # Copyright (c) 2015 Red Hat, Inc. 5 # 6 # This program is free software; you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation; either version 2 of the License, or 9 # (at your option) any later version. 10 # 11 # This program is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 # GNU General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 #============================================================================== 19 20 . test.sh 21 TST_CLEANUP=netns_ns_exec_cleanup 22 23 # Set to 1 only for test cases using ifconfig (ioctl). 24 USE_IFCONFIG=0 25 26 27 ## 28 # Variables which can be used in test cases (set by netns_setup() function): 29 ############################################################################### 30 # Use in test cases to execute commands inside a namespace. Set to 'ns_exec' or 31 # 'ip netns exec' command according to NS_EXEC_PROGRAM argument specified in 32 # netns_setup() function call. 33 NS_EXEC="" 34 35 # Set to "net" for ns_create/ns_exec as their options requires 36 # to specify a namespace type. Empty for ip command. 37 NS_TYPE="" 38 39 # IP addresses of veth0 (IP0) and veth1 (IP1) devices (ipv4/ipv6 variant 40 # is determined according to the IP_VERSION argument specified in netns_setup() 41 # function call. 42 IP0="" 43 IP1="" 44 NETMASK="" 45 46 # 'ping' or 'ping6' according to the IP_VERSION argument specified 47 # in netns_setup() function call. 48 tping="" 49 50 # Network namespaces handles for manipulating and executing commands inside 51 # namespaces. For 'ns_exec' handles are PIDs of daemonized processes running 52 # in namespaces. 53 NS_HANDLE0="" 54 NS_HANDLE1="" 55 56 # Adds "inet6 add" to the 'ifconfig' arguments which is required for the ipv6 57 # version. Always use with 'ifconfig', even if ipv4 version of a test case is 58 # used, in which case IFCONF_IN6_ARG will be empty string. Usage: 59 # ifconfig <device> $IFCONF_IN6_ARG IP/NETMASK 60 IFCONF_IN6_ARG="" 61 ############################################################################### 62 63 64 tst_check_iproute() 65 { 66 local cur_ipver=`ip -V` 67 local spe_ipver=$1 68 69 cur_ipver=${cur_ipver##*s} 70 71 if [ -z $cur_ipver ] || [ -z $spe_ipver ]; then 72 tst_brkm TBROK "don't obtain valid iproute version" 73 fi 74 75 if [ $cur_ipver -lt $spe_ipver ]; then 76 tst_brkm TCONF \ 77 "The commands in iproute tools do not support required objects" 78 fi 79 } 80 81 ## 82 # Sets up global variables which can be used in test cases (documented above), 83 # creates two network namespaces and a pair of virtual ethernet devices, each 84 # device in one namespace. Each device is then enabled and assigned an IP 85 # address according to the function parameters. IFCONF_IN6_ARG variable is set 86 # only if ipv6 variant of test case is used (determined by IP_VERSION argument). 87 # 88 # SYNOPSIS: 89 # netns_setup <NS_EXEC_PROGRAM> <IP_VERSION> <COMM_TYPE> <IP4_VETH0> 90 # <IP4_VETH1> <IP6_VETH0> <IP6_VETH1> 91 # 92 # OPTIONS: 93 # * NS_EXEC_PROGRAM (ns_exec|ip) 94 # Program which will be used to enter and run other commands 95 # inside a network namespace. 96 # * IP_VERSION (ipv4|ipv6) 97 # Version of IP. (ipv4|ipv6) 98 # * COMM_TYPE (netlink|ioctl) 99 # Communication type between kernel and user space 100 # for enabling and assigning IP addresses to the virtual 101 # ethernet devices. Uses 'ip' command for netlink and 'ifconfig' 102 # for ioctl. (If set to ioctl, function also checks the existance 103 # of the 'ifconfig' command.) 104 # * IP4_VETH0, IP4_VETH1 105 # IPv4 addresses for veth0 and veth1 devices. 106 # * IP6_VETH0, IP6_VETH1 107 # IPv6 addresses for veth0 and veth1 devices. 108 # 109 # On success function returns, on error tst_brkm is called and TC is terminated. 110 netns_setup() 111 { 112 tst_require_root 113 tst_check_cmds ip 114 115 case "$1" in 116 ns_exec) 117 setns_check 118 if [ $? -eq 32 ]; then 119 tst_brkm TCONF "setns not supported" 120 fi 121 NS_TYPE="net" 122 netns_ns_exec_setup 123 TST_CLEANUP=netns_ns_exec_cleanup 124 ;; 125 ip) 126 netns_ip_setup 127 TST_CLEANUP=netns_ip_cleanup 128 ;; 129 *) 130 tst_brkm TBROK \ 131 "first argument must be a program used to enter a network namespace (ns_exec|ip)" 132 ;; 133 esac 134 135 case "$3" in 136 netlink) 137 ;; 138 ioctl) 139 USE_IFCONFIG=1 140 tst_check_cmds ifconfig 141 ;; 142 *) 143 tst_brkm TBROK \ 144 "third argument must be a comm. type between kernel and user space (netlink|ioctl)" 145 ;; 146 esac 147 148 if [ -z "$4" ]; then 149 tst_brkm TBROK "fourth argument must be the IPv4 address for veth0" 150 fi 151 if [ -z "$5" ]; then 152 tst_brkm TBROK "fifth argument must be the IPv4 address for veth1" 153 fi 154 if [ -z "$6" ]; then 155 tst_brkm TBROK "sixth argument must be the IPv6 address for veth0" 156 fi 157 if [ -z "$7" ]; then 158 tst_brkm TBROK "seventh argument must be the IPv6 address for veth1" 159 fi 160 161 case "$2" in 162 ipv4) 163 IP0=$4; IP1=$5 164 tping="ping"; NETMASK=24 165 ;; 166 ipv6) 167 IFCONF_IN6_ARG="inet6 add" 168 IP0=$6; IP1=$7; 169 tping="ping6"; NETMASK=64 170 ;; 171 *) 172 tst_brkm TBROK "second argument must be an ip version (ipv4|ipv6)" 173 ;; 174 esac 175 176 netns_set_ip 177 } 178 179 ## 180 # Sets up NS_EXEC to use 'ns_exec', creates two network namespaces and stores 181 # their handles into NS_HANDLE0 and NS_HANDLE1 variables (in this case handles 182 # are PIDs of daemonized processes running in these namespaces). Virtual 183 # ethernet device is then created for each namespace. 184 netns_ns_exec_setup() 185 { 186 NS_EXEC="ns_exec" 187 188 NS_HANDLE0=$(ns_create $NS_TYPE) 189 if [ $? -eq 1 ]; then 190 tst_resm TINFO "$NS_HANDLE0" 191 tst_brkm TBROK "unable to create a new network namespace" 192 fi 193 194 NS_HANDLE1=$(ns_create $NS_TYPE) 195 if [ $? -eq 1 ]; then 196 tst_resm TINFO "$NS_HANDLE1" 197 tst_brkm TBROK "unable to create a new network namespace" 198 fi 199 200 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link add veth0 type veth peer name veth1 || \ 201 tst_brkm TBROK "unable to create veth pair devices" 202 203 $NS_EXEC $NS_HANDLE0 $NS_TYPE ns_ifmove veth1 $NS_HANDLE1 204 ret=$? 205 if [ $ret -eq 0 ]; then 206 return; 207 fi 208 209 if [ $ret -eq 32 ]; then 210 tst_brkm TCONF "IFLA_NET_NS_PID not supported" 211 fi 212 213 tst_brkm TBROK "unable to add device veth1 to the separate network namespace" 214 } 215 216 ## 217 # Sets up NS_EXEC to use 'ip netns exec', creates two network namespaces 218 # and stores their handles into NS_HANDLE0 and NS_HANDLE1 variables. Virtual 219 # ethernet device is then created for each namespace. 220 netns_ip_setup() 221 { 222 tst_check_iproute 111010 223 NS_EXEC="ip netns exec" 224 225 NS_HANDLE0=tst_net_ns0 226 NS_HANDLE1=tst_net_ns1 227 228 ip netns del $NS_HANDLE0 2>/dev/null 229 ip netns del $NS_HANDLE1 2>/dev/null 230 231 ip netns add $NS_HANDLE0 || \ 232 tst_brkm TBROK "unable to create a new network namespace" 233 ip netns add $NS_HANDLE1 || \ 234 tst_brkm TBROK "unable to create a new network namespace" 235 236 $NS_EXEC $NS_HANDLE0 ip link add veth0 type veth peer name veth1 || \ 237 tst_brkm TBROK "unable to create veth pair devices" 238 239 $NS_EXEC $NS_HANDLE0 ip link set veth1 netns $NS_HANDLE1 || \ 240 tst_brkm TBROK "unable to add device veth1 to the separate network namespace" 241 } 242 243 ## 244 # Enables virtual ethernet devices and assigns IP addresses for both 245 # of them (IPv4/IPv6 variant is decided by netns_setup() function). 246 netns_set_ip() 247 { 248 if [ -z "$NS_EXEC" ]; then 249 tst_brkm TBROK "netns_setup() function must be called first" 250 fi 251 252 # This applies only for ipv6 variant: 253 # Do not accept Router Advertisements (accept_ra) and do not use 254 # Duplicate Address Detection (accept_dad) which uses Neighbor 255 # Discovery Protocol - the problem is that until DAD can confirm that 256 # there is no other host with the same address, the address is 257 # considered to be "tentative" (attempts to bind() to the address fail 258 # with EADDRNOTAVAIL) which may cause problems for tests using ipv6. 259 echo 0 | $NS_EXEC $NS_HANDLE0 $NS_TYPE \ 260 tee /proc/sys/net/ipv6/conf/veth0/accept_dad \ 261 /proc/sys/net/ipv6/conf/veth0/accept_ra >/dev/null 262 echo 0 | $NS_EXEC $NS_HANDLE1 $NS_TYPE \ 263 tee /proc/sys/net/ipv6/conf/veth1/accept_dad \ 264 /proc/sys/net/ipv6/conf/veth1/accept_ra >/dev/null 265 266 case $USE_IFCONFIG in 267 1) 268 $NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 $IFCONF_IN6_ARG $IP0/$NETMASK || 269 tst_brkm TBROK "adding address to veth0 failed" 270 $NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 $IFCONF_IN6_ARG $IP1/$NETMASK || 271 tst_brkm TBROK "adding address to veth1 failed" 272 $NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 up || 273 tst_brkm TBROK "enabling veth0 device failed" 274 $NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 up || 275 tst_brkm TBROK "enabling veth1 device failed" 276 ;; 277 *) 278 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip address add $IP0/$NETMASK dev veth0 || 279 tst_brkm TBROK "adding address to veth0 failed" 280 $NS_EXEC $NS_HANDLE1 $NS_TYPE ip address add $IP1/$NETMASK dev veth1 || 281 tst_brkm TBROK "adding address to veth1 failed" 282 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link set veth0 up || 283 tst_brkm TBROK "enabling veth0 device failed" 284 $NS_EXEC $NS_HANDLE1 $NS_TYPE ip link set veth1 up || 285 tst_brkm TBROK "enabling veth1 device failed" 286 ;; 287 esac 288 } 289 290 netns_ns_exec_cleanup() 291 { 292 if [ -z "$NS_EXEC" ]; then 293 return 294 fi 295 296 # removes veth0 device (which also removes the paired veth1 device) 297 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link delete veth0 298 299 kill -9 $NS_HANDLE0 2>/dev/null 300 kill -9 $NS_HANDLE1 2>/dev/null 301 } 302 303 304 netns_ip_cleanup() 305 { 306 if [ -z "$NS_EXEC" ]; then 307 return 308 fi 309 310 # removes veth0 device (which also removes the paired veth1 device) 311 $NS_EXEC $NS_HANDLE0 ip link delete veth0 312 313 ip netns del $NS_HANDLE0 2>/dev/null 314 ip netns del $NS_HANDLE1 2>/dev/null 315 } 316