• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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