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