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