1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# End-to-end ipvs test suite
5# Topology:
6#--------------------------------------------------------------+
7#                      |                                       |
8#         ns0          |         ns1                           |
9#      -----------     |     -----------    -----------        |
10#      | veth01  | --------- | veth10  |    | veth12  |        |
11#      -----------    peer   -----------    -----------        |
12#           |          |                        |              |
13#      -----------     |                        |              |
14#      |  br0    |     |-----------------  peer |--------------|
15#      -----------     |                        |              |
16#           |          |                        |              |
17#      ----------     peer   ----------      -----------       |
18#      |  veth02 | --------- |  veth20 |     | veth21  |       |
19#      ----------      |     ----------      -----------       |
20#                      |         ns2                           |
21#                      |                                       |
22#--------------------------------------------------------------+
23#
24# We assume that all network driver are loaded
25#
26
27source lib.sh
28
29ret=0
30GREEN='\033[0;92m'
31RED='\033[0;31m'
32NC='\033[0m' # No Color
33
34readonly port=8080
35
36readonly vip_v4=207.175.44.110
37readonly cip_v4=10.0.0.2
38readonly gip_v4=10.0.0.1
39readonly dip_v4=172.16.0.1
40readonly rip_v4=172.16.0.2
41readonly sip_v4=10.0.0.3
42
43readonly infile="$(mktemp)"
44readonly outfile="$(mktemp)"
45readonly datalen=32
46
47sysipvsnet="/proc/sys/net/ipv4/vs/"
48if [ ! -d $sysipvsnet ]; then
49	if ! modprobe -q ip_vs; then
50		echo "skip: could not run test without ipvs module"
51		exit $ksft_skip
52	fi
53fi
54
55checktool "ipvsadm -v" "run test without ipvsadm"
56checktool "socat -h" "run test without socat"
57
58setup() {
59	setup_ns ns0 ns1 ns2
60
61	ip link add veth01 netns "${ns0}" type veth peer name veth10 netns "${ns1}"
62	ip link add veth02 netns "${ns0}" type veth peer name veth20 netns "${ns2}"
63	ip link add veth12 netns "${ns1}" type veth peer name veth21 netns "${ns2}"
64
65	ip netns exec "${ns0}" ip link set veth01 up
66	ip netns exec "${ns0}" ip link set veth02 up
67	ip netns exec "${ns0}" ip link add br0 type bridge
68	ip netns exec "${ns0}" ip link set veth01 master br0
69	ip netns exec "${ns0}" ip link set veth02 master br0
70	ip netns exec "${ns0}" ip link set br0 up
71	ip netns exec "${ns0}" ip addr add "${cip_v4}/24" dev br0
72
73	ip netns exec "${ns1}" ip link set veth10 up
74	ip netns exec "${ns1}" ip addr add "${gip_v4}/24" dev veth10
75	ip netns exec "${ns1}" ip link set veth12 up
76	ip netns exec "${ns1}" ip addr add "${dip_v4}/24" dev veth12
77
78	ip netns exec "${ns2}" ip link set veth21 up
79	ip netns exec "${ns2}" ip addr add "${rip_v4}/24" dev veth21
80	ip netns exec "${ns2}" ip link set veth20 up
81	ip netns exec "${ns2}" ip addr add "${sip_v4}/24" dev veth20
82
83	sleep 1
84
85	dd if=/dev/urandom of="${infile}" bs="${datalen}" count=1 status=none
86}
87
88cleanup() {
89	cleanup_all_ns
90
91	if [ -f "${outfile}" ]; then
92		rm "${outfile}"
93	fi
94	if [ -f "${infile}" ]; then
95		rm "${infile}"
96	fi
97}
98
99server_listen() {
100	ip netns exec "$ns2" timeout 5 socat -u -4 TCP-LISTEN:8080,reuseaddr STDOUT > "${outfile}" &
101	server_pid=$!
102	sleep 0.2
103}
104
105client_connect() {
106	ip netns exec "${ns0}" timeout 2 socat -u -4 STDIN TCP:"${vip_v4}":"${port}" < "${infile}"
107}
108
109verify_data() {
110	wait "${server_pid}"
111	cmp "$infile" "$outfile" 2>/dev/null
112}
113
114test_service() {
115	server_listen
116	client_connect
117	verify_data
118}
119
120
121test_dr() {
122	ip netns exec "${ns0}" ip route add "${vip_v4}" via "${gip_v4}" dev br0
123
124	ip netns exec "${ns1}" sysctl -qw net.ipv4.ip_forward=1
125	ip netns exec "${ns1}" ipvsadm -A -t "${vip_v4}:${port}" -s rr
126	ip netns exec "${ns1}" ipvsadm -a -t "${vip_v4}:${port}" -r "${rip_v4}:${port}"
127	ip netns exec "${ns1}" ip addr add "${vip_v4}/32" dev lo:1
128
129	# avoid incorrect arp response
130	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_ignore=1
131	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_announce=2
132	# avoid reverse route lookup
133	ip netns exec "${ns2}" sysctl -qw  net.ipv4.conf.all.rp_filter=0
134	ip netns exec "${ns2}" sysctl -qw  net.ipv4.conf.veth21.rp_filter=0
135	ip netns exec "${ns2}" ip addr add "${vip_v4}/32" dev lo:1
136
137	test_service
138}
139
140test_nat() {
141	ip netns exec "${ns0}" ip route add "${vip_v4}" via "${gip_v4}" dev br0
142
143	ip netns exec "${ns1}" sysctl -qw net.ipv4.ip_forward=1
144	ip netns exec "${ns1}" ipvsadm -A -t "${vip_v4}:${port}" -s rr
145	ip netns exec "${ns1}" ipvsadm -a -m -t "${vip_v4}:${port}" -r "${rip_v4}:${port}"
146	ip netns exec "${ns1}" ip addr add "${vip_v4}/32" dev lo:1
147
148	ip netns exec "${ns2}" ip link del veth20
149	ip netns exec "${ns2}" ip route add default via "${dip_v4}" dev veth21
150
151	test_service
152}
153
154test_tun() {
155	ip netns exec "${ns0}" ip route add "${vip_v4}" via "${gip_v4}" dev br0
156
157	ip netns exec "${ns1}" modprobe -q ipip
158	ip netns exec "${ns1}" ip link set tunl0 up
159	ip netns exec "${ns1}" sysctl -qw net.ipv4.ip_forward=0
160	ip netns exec "${ns1}" sysctl -qw net.ipv4.conf.all.send_redirects=0
161	ip netns exec "${ns1}" sysctl -qw net.ipv4.conf.default.send_redirects=0
162	ip netns exec "${ns1}" ipvsadm -A -t "${vip_v4}:${port}" -s rr
163	ip netns exec "${ns1}" ipvsadm -a -i -t "${vip_v4}:${port}" -r ${rip_v4}:${port}
164	ip netns exec "${ns1}" ip addr add ${vip_v4}/32 dev lo:1
165
166	ip netns exec "${ns2}" modprobe -q ipip
167	ip netns exec "${ns2}" ip link set tunl0 up
168	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_ignore=1
169	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_announce=2
170	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.rp_filter=0
171	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.tunl0.rp_filter=0
172	ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.veth21.rp_filter=0
173	ip netns exec "${ns2}" ip addr add "${vip_v4}/32" dev lo:1
174
175	test_service
176}
177
178run_tests() {
179	local errors=
180
181	echo "Testing DR mode..."
182	cleanup
183	setup
184	test_dr
185	errors=$(( $errors + $? ))
186
187	echo "Testing NAT mode..."
188	cleanup
189	setup
190	test_nat
191	errors=$(( $errors + $? ))
192
193	echo "Testing Tunnel mode..."
194	cleanup
195	setup
196	test_tun
197	errors=$(( $errors + $? ))
198
199	return $errors
200}
201
202trap cleanup EXIT
203
204run_tests
205
206if [ $? -ne 0 ]; then
207	echo -e "$(basename $0): ${RED}FAIL${NC}"
208	exit 1
209fi
210echo -e "$(basename $0): ${GREEN}PASS${NC}"
211exit 0
212