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 21TST_CLEANUP=netns_ns_exec_cleanup 22 23# Set to 1 only for test cases using ifconfig (ioctl). 24USE_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. 33NS_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. 37NS_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. 42IP0="" 43IP1="" 44NETMASK="" 45 46# 'ping' or 'ping6' according to the IP_VERSION argument specified 47# in netns_setup() function call. 48tping="" 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. 53NS_HANDLE0="" 54NS_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 60IFCONF_IN6_ARG="" 61############################################################################### 62 63 64tst_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. 110netns_setup() 111{ 112 tst_require_root 113 tst_require_cmds ip modprobe 114 115 modprobe veth > /dev/null 2>&1 116 117 case "$1" in 118 ns_exec) 119 setns_check 120 if [ $? -eq 32 ]; then 121 tst_brkm TCONF "setns not supported" 122 fi 123 NS_TYPE="net" 124 netns_ns_exec_setup 125 TST_CLEANUP=netns_ns_exec_cleanup 126 ;; 127 ip) 128 netns_ip_setup 129 TST_CLEANUP=netns_ip_cleanup 130 ;; 131 *) 132 tst_brkm TBROK \ 133 "first argument must be a program used to enter a network namespace (ns_exec|ip)" 134 ;; 135 esac 136 137 case "$3" in 138 netlink) 139 ;; 140 ioctl) 141 USE_IFCONFIG=1 142 tst_require_cmds ifconfig 143 ;; 144 *) 145 tst_brkm TBROK \ 146 "third argument must be a comm. type between kernel and user space (netlink|ioctl)" 147 ;; 148 esac 149 150 if [ -z "$4" ]; then 151 tst_brkm TBROK "fourth argument must be the IPv4 address for veth0" 152 fi 153 if [ -z "$5" ]; then 154 tst_brkm TBROK "fifth argument must be the IPv4 address for veth1" 155 fi 156 if [ -z "$6" ]; then 157 tst_brkm TBROK "sixth argument must be the IPv6 address for veth0" 158 fi 159 if [ -z "$7" ]; then 160 tst_brkm TBROK "seventh argument must be the IPv6 address for veth1" 161 fi 162 163 case "$2" in 164 ipv4) 165 IP0=$4; IP1=$5 166 tping="ping"; NETMASK=24 167 ;; 168 ipv6) 169 IFCONF_IN6_ARG="inet6 add" 170 IP0=$6; IP1=$7; 171 if which ping6 >/dev/null 2>&1; then 172 tping="ping6" 173 else 174 tping="ping -6" 175 fi 176 NETMASK=64 177 ;; 178 *) 179 tst_brkm TBROK "second argument must be an ip version (ipv4|ipv6)" 180 ;; 181 esac 182 183 netns_set_ip 184} 185 186## 187# Sets up NS_EXEC to use 'ns_exec', creates two network namespaces and stores 188# their handles into NS_HANDLE0 and NS_HANDLE1 variables (in this case handles 189# are PIDs of daemonized processes running in these namespaces). Virtual 190# ethernet device is then created for each namespace. 191netns_ns_exec_setup() 192{ 193 NS_EXEC="ns_exec" 194 195 NS_HANDLE0=$(ns_create $NS_TYPE) 196 if [ $? -eq 1 ]; then 197 tst_resm TINFO "$NS_HANDLE0" 198 tst_brkm TBROK "unable to create a new network namespace" 199 fi 200 201 NS_HANDLE1=$(ns_create $NS_TYPE) 202 if [ $? -eq 1 ]; then 203 tst_resm TINFO "$NS_HANDLE1" 204 tst_brkm TBROK "unable to create a new network namespace" 205 fi 206 207 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link add veth0 type veth peer name veth1 || \ 208 tst_brkm TBROK "unable to create veth pair devices" 209 210 $NS_EXEC $NS_HANDLE0 $NS_TYPE ns_ifmove veth1 $NS_HANDLE1 211 ret=$? 212 if [ $ret -eq 0 ]; then 213 return; 214 fi 215 216 if [ $ret -eq 32 ]; then 217 tst_brkm TCONF "IFLA_NET_NS_PID not supported" 218 fi 219 220 tst_brkm TBROK "unable to add device veth1 to the separate network namespace" 221} 222 223## 224# Sets up NS_EXEC to use 'ip netns exec', creates two network namespaces 225# and stores their handles into NS_HANDLE0 and NS_HANDLE1 variables. Virtual 226# ethernet device is then created for each namespace. 227netns_ip_setup() 228{ 229 tst_check_iproute 111010 230 NS_EXEC="ip netns exec" 231 232 NS_HANDLE0=tst_net_ns0 233 NS_HANDLE1=tst_net_ns1 234 235 ip netns del $NS_HANDLE0 2>/dev/null 236 ip netns del $NS_HANDLE1 2>/dev/null 237 238 ip netns add $NS_HANDLE0 || \ 239 tst_brkm TBROK "unable to create a new network namespace" 240 ip netns add $NS_HANDLE1 || \ 241 tst_brkm TBROK "unable to create a new network namespace" 242 243 $NS_EXEC $NS_HANDLE0 ip link add veth0 type veth peer name veth1 || \ 244 tst_brkm TBROK "unable to create veth pair devices" 245 246 $NS_EXEC $NS_HANDLE0 ip link set veth1 netns $NS_HANDLE1 || \ 247 tst_brkm TBROK "unable to add device veth1 to the separate network namespace" 248} 249 250## 251# Enables virtual ethernet devices and assigns IP addresses for both 252# of them (IPv4/IPv6 variant is decided by netns_setup() function). 253netns_set_ip() 254{ 255 if [ -z "$NS_EXEC" ]; then 256 tst_brkm TBROK "netns_setup() function must be called first" 257 fi 258 259 # This applies only for ipv6 variant: 260 # Do not accept Router Advertisements (accept_ra) and do not use 261 # Duplicate Address Detection (accept_dad) which uses Neighbor 262 # Discovery Protocol - the problem is that until DAD can confirm that 263 # there is no other host with the same address, the address is 264 # considered to be "tentative" (attempts to bind() to the address fail 265 # with EADDRNOTAVAIL) which may cause problems for tests using ipv6. 266 echo 0 | $NS_EXEC $NS_HANDLE0 $NS_TYPE \ 267 tee /proc/sys/net/ipv6/conf/veth0/accept_dad \ 268 /proc/sys/net/ipv6/conf/veth0/accept_ra >/dev/null 269 echo 0 | $NS_EXEC $NS_HANDLE1 $NS_TYPE \ 270 tee /proc/sys/net/ipv6/conf/veth1/accept_dad \ 271 /proc/sys/net/ipv6/conf/veth1/accept_ra >/dev/null 272 273 case $USE_IFCONFIG in 274 1) 275 $NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 $IFCONF_IN6_ARG $IP0/$NETMASK || 276 tst_brkm TBROK "adding address to veth0 failed" 277 $NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 $IFCONF_IN6_ARG $IP1/$NETMASK || 278 tst_brkm TBROK "adding address to veth1 failed" 279 $NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 up || 280 tst_brkm TBROK "enabling veth0 device failed" 281 $NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 up || 282 tst_brkm TBROK "enabling veth1 device failed" 283 ;; 284 *) 285 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip address add $IP0/$NETMASK dev veth0 || 286 tst_brkm TBROK "adding address to veth0 failed" 287 $NS_EXEC $NS_HANDLE1 $NS_TYPE ip address add $IP1/$NETMASK dev veth1 || 288 tst_brkm TBROK "adding address to veth1 failed" 289 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link set veth0 up || 290 tst_brkm TBROK "enabling veth0 device failed" 291 $NS_EXEC $NS_HANDLE1 $NS_TYPE ip link set veth1 up || 292 tst_brkm TBROK "enabling veth1 device failed" 293 ;; 294 esac 295} 296 297netns_ns_exec_cleanup() 298{ 299 if [ -z "$NS_EXEC" ]; then 300 return 301 fi 302 303 # removes veth0 device (which also removes the paired veth1 device) 304 $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link delete veth0 305 306 kill -9 $NS_HANDLE0 2>/dev/null 307 kill -9 $NS_HANDLE1 2>/dev/null 308} 309 310 311netns_ip_cleanup() 312{ 313 if [ -z "$NS_EXEC" ]; then 314 return 315 fi 316 317 # removes veth0 device (which also removes the paired veth1 device) 318 $NS_EXEC $NS_HANDLE0 ip link delete veth0 319 320 ip netns del $NS_HANDLE0 2>/dev/null 321 ip netns del $NS_HANDLE1 2>/dev/null 322} 323