1f08c3bdfSopenharmony_ci#!/bin/sh
2f08c3bdfSopenharmony_ci# SPDX-License-Identifier: GPL-2.0-or-later
3f08c3bdfSopenharmony_ci# Copyright (c) 2022 Petr Vorel <pvorel@suse.cz>
4f08c3bdfSopenharmony_ci# Copyright (c) Linux Test Project, 2014-2023
5f08c3bdfSopenharmony_ci# Copyright (c) 2015 Red Hat, Inc.
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ciTST_NEEDS_ROOT=1
8f08c3bdfSopenharmony_ciTST_NEEDS_CMDS="ip ping"
9f08c3bdfSopenharmony_ciTST_NEEDS_DRIVERS="veth"
10f08c3bdfSopenharmony_ci
11f08c3bdfSopenharmony_ciTST_OPTS="eI"
12f08c3bdfSopenharmony_ciTST_PARSE_ARGS="netns_parse_args"
13f08c3bdfSopenharmony_ciTST_USAGE="netns_usage"
14f08c3bdfSopenharmony_ciTST_SETUP="${TST_SETUP:-netns_setup}"
15f08c3bdfSopenharmony_ciTST_CLEANUP="${TST_CLEANUP:-netns_cleanup}"
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ciTST_NET_SKIP_VARIABLE_INIT=1
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci# from tst_net_vars.c
20f08c3bdfSopenharmony_ciIPV4_NET16_UNUSED="10.23"
21f08c3bdfSopenharmony_ciIPV6_NET32_UNUSED="fd00:23"
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_ci# Set to "net" for tst_ns_create/tst_ns_exec as their options requires
24f08c3bdfSopenharmony_ci# to specify a namespace type. Empty for ip command.
25f08c3bdfSopenharmony_ciNS_TYPE=
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci# 'ping' or 'ping6'
28f08c3bdfSopenharmony_citping=
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci# Network namespaces handles for manipulating and executing commands inside
31f08c3bdfSopenharmony_ci# namespaces. For 'tst_ns_exec' handles are PIDs of daemonized processes running
32f08c3bdfSopenharmony_ci# in namespaces.
33f08c3bdfSopenharmony_ciNS_HANDLE0=
34f08c3bdfSopenharmony_ciNS_HANDLE1=
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci# Adds "inet6 add" to the 'ifconfig' arguments which is required for the ipv6
37f08c3bdfSopenharmony_ci# version. Always use with 'ifconfig', even if ipv4 version of a test case is
38f08c3bdfSopenharmony_ci# used, in which case IFCONF_IN6_ARG will be empty string. Usage:
39f08c3bdfSopenharmony_ci# ifconfig <device> $IFCONF_IN6_ARG IP/NETMASK
40f08c3bdfSopenharmony_ciIFCONF_IN6_ARG=
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci# Program which will be used to enter and run other commands inside a network namespace.
43f08c3bdfSopenharmony_ci# (tst_ns_exec|ip)
44f08c3bdfSopenharmony_ciNS_EXEC="ip"
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci# Communication type between kernel and user space for basic setup: enabling and
47f08c3bdfSopenharmony_ci# assigning IP addresses to the virtual ethernet devices. (Uses 'ip' command for
48f08c3bdfSopenharmony_ci# netlink and 'ifconfig' for ioctl.)
49f08c3bdfSopenharmony_ci# (netlink|ioctl)
50f08c3bdfSopenharmony_ciCOMM_TYPE="netlink"
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_cido_cleanup=
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cinetns_parse_args()
55f08c3bdfSopenharmony_ci{
56f08c3bdfSopenharmony_ci	case $1 in
57f08c3bdfSopenharmony_ci	e) NS_EXEC="tst_ns_exec" ;;
58f08c3bdfSopenharmony_ci	I) COMM_TYPE="ioctl"; tst_require_cmds ifconfig ;;
59f08c3bdfSopenharmony_ci	esac
60f08c3bdfSopenharmony_ci}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cinetns_usage()
63f08c3bdfSopenharmony_ci{
64f08c3bdfSopenharmony_ci	echo "usage: $0 [ -e ] [ -I ]"
65f08c3bdfSopenharmony_ci	echo "OPTIONS"
66f08c3bdfSopenharmony_ci	echo "-e      Use tst_ns_exec instead of ip"
67f08c3bdfSopenharmony_ci	echo "-I      Test ioctl (with ifconfig) instead of netlink (with ip)"
68f08c3bdfSopenharmony_ci}
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cinetns_setup()
71f08c3bdfSopenharmony_ci{
72f08c3bdfSopenharmony_ci	if [ "$NS_EXEC" = "ip" ]; then
73f08c3bdfSopenharmony_ci		netns_ip_setup
74f08c3bdfSopenharmony_ci	else
75f08c3bdfSopenharmony_ci		NS_TYPE="net"
76f08c3bdfSopenharmony_ci		netns_ns_exec_setup
77f08c3bdfSopenharmony_ci	fi
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	IP0=$(tst_ipaddr_un -c 1)
80f08c3bdfSopenharmony_ci	IP1=$(tst_ipaddr_un -c 2)
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci	if [ "$TST_IPV6" ]; then
83f08c3bdfSopenharmony_ci		IFCONF_IN6_ARG="inet6 add"
84f08c3bdfSopenharmony_ci		NETMASK=64
85f08c3bdfSopenharmony_ci	else
86f08c3bdfSopenharmony_ci		NETMASK=24
87f08c3bdfSopenharmony_ci	fi
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	tping=ping$TST_IPV6
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	netns_set_ip
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ci	tst_res TINFO "testing netns over $COMM_TYPE with $NS_EXEC $PROG"
94f08c3bdfSopenharmony_ci	do_cleanup=1
95f08c3bdfSopenharmony_ci}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_cinetns_cleanup()
98f08c3bdfSopenharmony_ci{
99f08c3bdfSopenharmony_ci	[ "$do_cleanup" ] || return
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci	if [ "$NS_EXEC" = "ip" ]; then
102f08c3bdfSopenharmony_ci		netns_ip_cleanup
103f08c3bdfSopenharmony_ci	else
104f08c3bdfSopenharmony_ci		netns_ns_exec_cleanup
105f08c3bdfSopenharmony_ci	fi
106f08c3bdfSopenharmony_ci}
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_ci# Sets up NS_EXEC to use 'tst_ns_exec', creates two network namespaces and stores
109f08c3bdfSopenharmony_ci# their handles into NS_HANDLE0 and NS_HANDLE1 variables (in this case handles
110f08c3bdfSopenharmony_ci# are PIDs of daemonized processes running in these namespaces). Virtual
111f08c3bdfSopenharmony_ci# ethernet device is then created for each namespace.
112f08c3bdfSopenharmony_cinetns_ns_exec_setup()
113f08c3bdfSopenharmony_ci{
114f08c3bdfSopenharmony_ci	local ret
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_ci	NS_EXEC="tst_ns_exec"
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	NS_HANDLE0=$(tst_ns_create $NS_TYPE)
119f08c3bdfSopenharmony_ci	if [ $? -eq 1 ]; then
120f08c3bdfSopenharmony_ci		tst_res TINFO "$NS_HANDLE0"
121f08c3bdfSopenharmony_ci		tst_brk TBROK "unable to create a new network namespace"
122f08c3bdfSopenharmony_ci	fi
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci	NS_HANDLE1=$(tst_ns_create $NS_TYPE)
125f08c3bdfSopenharmony_ci	if [ $? -eq 1 ]; then
126f08c3bdfSopenharmony_ci		tst_res TINFO "$NS_HANDLE1"
127f08c3bdfSopenharmony_ci		tst_brk TBROK "unable to create a new network namespace"
128f08c3bdfSopenharmony_ci	fi
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ci	$NS_EXEC $NS_HANDLE0 $NS_TYPE ip link add veth0 type veth peer name veth1 || \
131f08c3bdfSopenharmony_ci		tst_brk TBROK "unable to create veth pair devices"
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_ci	$NS_EXEC $NS_HANDLE0 $NS_TYPE tst_ns_ifmove veth1 $NS_HANDLE1
134f08c3bdfSopenharmony_ci	ret=$?
135f08c3bdfSopenharmony_ci	[ $ret -eq 0 ] && return
136f08c3bdfSopenharmony_ci	[ $ret -eq 32 ] && tst_brk TCONF "IFLA_NET_NS_PID not supported"
137f08c3bdfSopenharmony_ci
138f08c3bdfSopenharmony_ci	tst_brk TBROK "unable to add device veth1 to the separate network namespace"
139f08c3bdfSopenharmony_ci}
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci# Sets up NS_EXEC to use 'ip netns exec', creates two network namespaces
142f08c3bdfSopenharmony_ci# and stores their handles into NS_HANDLE0 and NS_HANDLE1 variables. Virtual
143f08c3bdfSopenharmony_ci# ethernet device is then created for each namespace.
144f08c3bdfSopenharmony_cinetns_ip_setup()
145f08c3bdfSopenharmony_ci{
146f08c3bdfSopenharmony_ci	ip netns > /dev/null || \
147f08c3bdfSopenharmony_ci		tst_brk TCONF "ip without netns support (required iproute2 >= ss111010 - v3.0.0)"
148f08c3bdfSopenharmony_ci
149f08c3bdfSopenharmony_ci	NS_EXEC="ip netns exec"
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci	NS_HANDLE0=tst_net_ns0
152f08c3bdfSopenharmony_ci	NS_HANDLE1=tst_net_ns1
153f08c3bdfSopenharmony_ci
154f08c3bdfSopenharmony_ci	ip netns del $NS_HANDLE0 2>/dev/null
155f08c3bdfSopenharmony_ci	ip netns del $NS_HANDLE1 2>/dev/null
156f08c3bdfSopenharmony_ci
157f08c3bdfSopenharmony_ci	ROD ip netns add $NS_HANDLE0
158f08c3bdfSopenharmony_ci	ROD ip netns add $NS_HANDLE1
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_ci	ROD $NS_EXEC $NS_HANDLE0 ip link add veth0 type veth peer name veth1
161f08c3bdfSopenharmony_ci	ROD $NS_EXEC $NS_HANDLE0 ip link set veth1 netns $NS_HANDLE1
162f08c3bdfSopenharmony_ci}
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci# Enables virtual ethernet devices and assigns IP addresses for both
165f08c3bdfSopenharmony_ci# of them (IPv4/IPv6 variant is decided by netns_setup() function).
166f08c3bdfSopenharmony_cinetns_set_ip()
167f08c3bdfSopenharmony_ci{
168f08c3bdfSopenharmony_ci	local cmd="ip"
169f08c3bdfSopenharmony_ci
170f08c3bdfSopenharmony_ci	# This applies only for ipv6 variant:
171f08c3bdfSopenharmony_ci	# Do not accept Router Advertisements (accept_ra) and do not use
172f08c3bdfSopenharmony_ci	# Duplicate Address Detection (accept_dad) which uses Neighbor
173f08c3bdfSopenharmony_ci	# Discovery Protocol - the problem is that until DAD can confirm that
174f08c3bdfSopenharmony_ci	# there is no other host with the same address, the address is
175f08c3bdfSopenharmony_ci	# considered to be "tentative" (attempts to bind() to the address fail
176f08c3bdfSopenharmony_ci	# with EADDRNOTAVAIL) which may cause problems for tests using ipv6.
177f08c3bdfSopenharmony_ci	if [ "$TST_IPV6" ]; then
178f08c3bdfSopenharmony_ci		echo 0 | $NS_EXEC $NS_HANDLE0 $NS_TYPE \
179f08c3bdfSopenharmony_ci			tee /proc/sys/net/ipv6/conf/veth0/accept_dad \
180f08c3bdfSopenharmony_ci			/proc/sys/net/ipv6/conf/veth0/accept_ra >/dev/null
181f08c3bdfSopenharmony_ci		echo 0 | $NS_EXEC $NS_HANDLE1 $NS_TYPE \
182f08c3bdfSopenharmony_ci			tee /proc/sys/net/ipv6/conf/veth1/accept_dad \
183f08c3bdfSopenharmony_ci			/proc/sys/net/ipv6/conf/veth1/accept_ra >/dev/null
184f08c3bdfSopenharmony_ci	fi
185f08c3bdfSopenharmony_ci
186f08c3bdfSopenharmony_ci	[ "$COMM_TYPE" = "ioctl" ] && cmd="ifconfig"
187f08c3bdfSopenharmony_ci
188f08c3bdfSopenharmony_ci	if [ "$COMM_TYPE" = "netlink" ]; then
189f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE0 $NS_TYPE ip address add $IP0/$NETMASK dev veth0
190f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE1 $NS_TYPE ip address add $IP1/$NETMASK dev veth1
191f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE0 $NS_TYPE ip link set veth0 up
192f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE1 $NS_TYPE ip link set veth1 up
193f08c3bdfSopenharmony_ci	else
194f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 $IFCONF_IN6_ARG $IP0/$NETMASK
195f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 $IFCONF_IN6_ARG $IP1/$NETMASK
196f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 up
197f08c3bdfSopenharmony_ci		ROD $NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 up
198f08c3bdfSopenharmony_ci	fi
199f08c3bdfSopenharmony_ci}
200f08c3bdfSopenharmony_ci
201f08c3bdfSopenharmony_cinetns_ns_exec_cleanup()
202f08c3bdfSopenharmony_ci{
203f08c3bdfSopenharmony_ci	[ "$NS_EXEC" ] || return
204f08c3bdfSopenharmony_ci
205f08c3bdfSopenharmony_ci	# removes veth0 device (which also removes the paired veth1 device)
206f08c3bdfSopenharmony_ci	$NS_EXEC $NS_HANDLE0 $NS_TYPE ip link delete veth0
207f08c3bdfSopenharmony_ci
208f08c3bdfSopenharmony_ci	kill -9 $NS_HANDLE0 2>/dev/null
209f08c3bdfSopenharmony_ci	kill -9 $NS_HANDLE1 2>/dev/null
210f08c3bdfSopenharmony_ci}
211f08c3bdfSopenharmony_ci
212f08c3bdfSopenharmony_ci
213f08c3bdfSopenharmony_cinetns_ip_cleanup()
214f08c3bdfSopenharmony_ci{
215f08c3bdfSopenharmony_ci	[ "$NS_EXEC" ] || return
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci	# removes veth0 device (which also removes the paired veth1 device)
218f08c3bdfSopenharmony_ci	$NS_EXEC $NS_HANDLE0 ip link delete veth0
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	ip netns del $NS_HANDLE0 2>/dev/null
221f08c3bdfSopenharmony_ci	ip netns del $NS_HANDLE1 2>/dev/null
222f08c3bdfSopenharmony_ci}
223f08c3bdfSopenharmony_ci
224f08c3bdfSopenharmony_ci. tst_net.sh
225