1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4[[ -z $TC ]] && TC='tc'
5[[ -z $IP ]] && IP='ip'
6
7REDIRECT_USER='./tc_l2_redirect'
8REDIRECT_BPF='./tc_l2_redirect_kern.o'
9
10RP_FILTER=$(< /proc/sys/net/ipv4/conf/all/rp_filter)
11IPV6_FORWARDING=$(< /proc/sys/net/ipv6/conf/all/forwarding)
12
13function config_common {
14	local tun_type=$1
15
16	$IP netns add ns1
17	$IP netns add ns2
18	$IP link add ve1 type veth peer name vens1
19	$IP link add ve2 type veth peer name vens2
20	$IP link set dev ve1 up
21	$IP link set dev ve2 up
22	$IP link set dev ve1 mtu 1500
23	$IP link set dev ve2 mtu 1500
24	$IP link set dev vens1 netns ns1
25	$IP link set dev vens2 netns ns2
26
27	$IP -n ns1 link set dev lo up
28	$IP -n ns1 link set dev vens1 up
29	$IP -n ns1 addr add 10.1.1.101/24 dev vens1
30	$IP -n ns1 addr add 2401:db01::65/64 dev vens1 nodad
31	$IP -n ns1 route add default via 10.1.1.1 dev vens1
32	$IP -n ns1 route add default via 2401:db01::1 dev vens1
33
34	$IP -n ns2 link set dev lo up
35	$IP -n ns2 link set dev vens2 up
36	$IP -n ns2 addr add 10.2.1.102/24 dev vens2
37	$IP -n ns2 addr add 2401:db02::66/64 dev vens2 nodad
38	$IP -n ns2 addr add 10.10.1.102 dev lo
39	$IP -n ns2 addr add 2401:face::66/64 dev lo nodad
40	$IP -n ns2 link add ipt2 type ipip local 10.2.1.102 remote 10.2.1.1
41	$IP -n ns2 link add ip6t2 type ip6tnl mode any local 2401:db02::66 remote 2401:db02::1
42	$IP -n ns2 link set dev ipt2 up
43	$IP -n ns2 link set dev ip6t2 up
44	$IP netns exec ns2 $TC qdisc add dev vens2 clsact
45	$IP netns exec ns2 $TC filter add dev vens2 ingress bpf da obj $REDIRECT_BPF sec drop_non_tun_vip
46	if [[ $tun_type == "ipip" ]]; then
47		$IP -n ns2 route add 10.1.1.0/24 dev ipt2
48		$IP netns exec ns2 sysctl -q -w net.ipv4.conf.all.rp_filter=0
49		$IP netns exec ns2 sysctl -q -w net.ipv4.conf.ipt2.rp_filter=0
50	else
51		$IP -n ns2 route add 10.1.1.0/24 dev ip6t2
52		$IP -n ns2 route add 2401:db01::/64 dev ip6t2
53		$IP netns exec ns2 sysctl -q -w net.ipv4.conf.all.rp_filter=0
54		$IP netns exec ns2 sysctl -q -w net.ipv4.conf.ip6t2.rp_filter=0
55	fi
56
57	$IP addr add 10.1.1.1/24 dev ve1
58	$IP addr add 2401:db01::1/64 dev ve1 nodad
59	$IP addr add 10.2.1.1/24 dev ve2
60	$IP addr add 2401:db02::1/64 dev ve2 nodad
61
62	$TC qdisc add dev ve2 clsact
63	$TC filter add dev ve2 ingress bpf da obj $REDIRECT_BPF sec l2_to_iptun_ingress_forward
64
65	sysctl -q -w net.ipv4.conf.all.rp_filter=0
66	sysctl -q -w net.ipv6.conf.all.forwarding=1
67}
68
69function cleanup {
70	set +e
71	[[ -z $DEBUG ]] || set +x
72	$IP netns delete ns1 >& /dev/null
73	$IP netns delete ns2 >& /dev/null
74	$IP link del ve1 >& /dev/null
75	$IP link del ve2 >& /dev/null
76	$IP link del ipt >& /dev/null
77	$IP link del ip6t >& /dev/null
78	sysctl -q -w net.ipv4.conf.all.rp_filter=$RP_FILTER
79	sysctl -q -w net.ipv6.conf.all.forwarding=$IPV6_FORWARDING
80	rm -f /sys/fs/bpf/tc/globals/tun_iface
81	[[ -z $DEBUG ]] || set -x
82	set -e
83}
84
85function l2_to_ipip {
86	echo -n "l2_to_ipip $1: "
87
88	local dir=$1
89
90	config_common ipip
91
92	$IP link add ipt type ipip external
93	$IP link set dev ipt up
94	sysctl -q -w net.ipv4.conf.ipt.rp_filter=0
95	sysctl -q -w net.ipv4.conf.ipt.forwarding=1
96
97	if [[ $dir == "egress" ]]; then
98		$IP route add 10.10.1.0/24 via 10.2.1.102 dev ve2
99		$TC filter add dev ve2 egress bpf da obj $REDIRECT_BPF sec l2_to_iptun_ingress_redirect
100		sysctl -q -w net.ipv4.conf.ve1.forwarding=1
101	else
102		$TC qdisc add dev ve1 clsact
103		$TC filter add dev ve1 ingress bpf da obj $REDIRECT_BPF sec l2_to_iptun_ingress_redirect
104	fi
105
106	$REDIRECT_USER -U /sys/fs/bpf/tc/globals/tun_iface -i $(< /sys/class/net/ipt/ifindex)
107
108	$IP netns exec ns1 ping -c1 10.10.1.102 >& /dev/null
109
110	if [[ $dir == "egress" ]]; then
111		# test direct egress to ve2 (i.e. not forwarding from
112		# ve1 to ve2).
113		ping -c1 10.10.1.102 >& /dev/null
114	fi
115
116	cleanup
117
118	echo "OK"
119}
120
121function l2_to_ip6tnl {
122	echo -n "l2_to_ip6tnl $1: "
123
124	local dir=$1
125
126	config_common ip6tnl
127
128	$IP link add ip6t type ip6tnl mode any external
129	$IP link set dev ip6t up
130	sysctl -q -w net.ipv4.conf.ip6t.rp_filter=0
131	sysctl -q -w net.ipv4.conf.ip6t.forwarding=1
132
133	if [[ $dir == "egress" ]]; then
134		$IP route add 10.10.1.0/24 via 10.2.1.102 dev ve2
135		$IP route add 2401:face::/64 via 2401:db02::66 dev ve2
136		$TC filter add dev ve2 egress bpf da obj $REDIRECT_BPF sec l2_to_ip6tun_ingress_redirect
137		sysctl -q -w net.ipv4.conf.ve1.forwarding=1
138	else
139		$TC qdisc add dev ve1 clsact
140		$TC filter add dev ve1 ingress bpf da obj $REDIRECT_BPF sec l2_to_ip6tun_ingress_redirect
141	fi
142
143	$REDIRECT_USER -U /sys/fs/bpf/tc/globals/tun_iface -i $(< /sys/class/net/ip6t/ifindex)
144
145	$IP netns exec ns1 ping -c1 10.10.1.102 >& /dev/null
146	$IP netns exec ns1 ping -6 -c1 2401:face::66 >& /dev/null
147
148	if [[ $dir == "egress" ]]; then
149		# test direct egress to ve2 (i.e. not forwarding from
150		# ve1 to ve2).
151		ping -c1 10.10.1.102 >& /dev/null
152		ping -6 -c1 2401:face::66 >& /dev/null
153	fi
154
155	cleanup
156
157	echo "OK"
158}
159
160cleanup
161test_names="l2_to_ipip l2_to_ip6tnl"
162test_dirs="ingress egress"
163if [[ $# -ge 2 ]]; then
164	test_names=$1
165	test_dirs=$2
166elif [[ $# -ge 1 ]]; then
167	test_names=$1
168fi
169
170for t in $test_names; do
171	for d in $test_dirs; do
172		$t $d
173	done
174done
175