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