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