Home | History | Annotate | Download | only in netns
      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