Loading...
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
3/*
4 * End-to-end eBPF tunnel test suite
5 * The file tests BPF network tunnel implementation.
6 *
7 * Topology:
8 * ---------
9 * root namespace | at_ns0 namespace
10 * |
11 * ----------- | -----------
12 * | tnl dev | | | tnl dev | (overlay network)
13 * ----------- | -----------
14 * metadata-mode | metadata-mode
15 * with bpf | with bpf
16 * |
17 * ---------- | ----------
18 * | veth1 | --------- | veth0 | (underlay network)
19 * ---------- peer ----------
20 *
21 *
22 * Device Configuration
23 * --------------------
24 * root namespace with metadata-mode tunnel + BPF
25 * Device names and addresses:
26 * veth1 IP 1: 172.16.1.200, IPv6: 00::22 (underlay)
27 * IP 2: 172.16.1.20, IPv6: 00::bb (underlay)
28 * tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)
29 *
30 * Namespace at_ns0 with native tunnel
31 * Device names and addresses:
32 * veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
33 * tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)
34 *
35 *
36 * End-to-end ping packet flow
37 * ---------------------------
38 * Most of the tests start by namespace creation, device configuration,
39 * then ping the underlay and overlay network. When doing 'ping 10.1.1.100'
40 * from root namespace, the following operations happen:
41 * 1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
42 * 2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
43 * with local_ip=172.16.1.200, remote_ip=172.16.1.100. BPF program choose
44 * the primary or secondary ip of veth1 as the local ip of tunnel. The
45 * choice is made based on the value of bpf map local_ip_map.
46 * 3) Outer tunnel header is prepended and route the packet to veth1's egress.
47 * 4) veth0's ingress queue receive the tunneled packet at namespace at_ns0.
48 * 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet.
49 * 6) Forward the packet to the overlay tnl dev.
50 */
51
52#include <arpa/inet.h>
53#include <linux/if_link.h>
54#include <linux/if_tun.h>
55#include <linux/limits.h>
56#include <linux/sysctl.h>
57#include <linux/time_types.h>
58#include <linux/net_tstamp.h>
59#include <net/if.h>
60#include <stdbool.h>
61#include <stdio.h>
62#include <sys/stat.h>
63#include <unistd.h>
64
65#include "test_progs.h"
66#include "network_helpers.h"
67#include "test_tunnel_kern.skel.h"
68
69#define IP4_ADDR_VETH0 "172.16.1.100"
70#define IP4_ADDR1_VETH1 "172.16.1.200"
71#define IP4_ADDR2_VETH1 "172.16.1.20"
72#define IP4_ADDR_TUNL_DEV0 "10.1.1.100"
73#define IP4_ADDR_TUNL_DEV1 "10.1.1.200"
74
75#define IP6_ADDR_VETH0 "::11"
76#define IP6_ADDR1_VETH1 "::22"
77#define IP6_ADDR2_VETH1 "::bb"
78
79#define IP4_ADDR1_HEX_VETH1 0xac1001c8
80#define IP4_ADDR2_HEX_VETH1 0xac100114
81#define IP6_ADDR1_HEX_VETH1 0x22
82#define IP6_ADDR2_HEX_VETH1 0xbb
83
84#define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
85#define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
86#define MAC_VETH1 "52:54:00:d9:03:00"
87
88#define VXLAN_TUNL_DEV0 "vxlan00"
89#define VXLAN_TUNL_DEV1 "vxlan11"
90#define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
91#define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
92
93#define IPIP_TUNL_DEV0 "ipip00"
94#define IPIP_TUNL_DEV1 "ipip11"
95
96#define XFRM_AUTH "0x1111111111111111111111111111111111111111"
97#define XFRM_ENC "0x22222222222222222222222222222222"
98#define XFRM_SPI_IN_TO_OUT 0x1
99#define XFRM_SPI_OUT_TO_IN 0x2
100
101#define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
102
103static int config_device(void)
104{
105 SYS(fail, "ip netns add at_ns0");
106 SYS(fail, "ip link add veth0 address " MAC_VETH1 " type veth peer name veth1");
107 SYS(fail, "ip link set veth0 netns at_ns0");
108 SYS(fail, "ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
109 SYS(fail, "ip link set dev veth1 up mtu 1500");
110 SYS(fail, "ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
111 SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
112
113 return 0;
114fail:
115 return -1;
116}
117
118static void cleanup(void)
119{
120 SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
121 SYS_NOFAIL("ip link del veth1");
122 SYS_NOFAIL("ip link del %s", VXLAN_TUNL_DEV1);
123 SYS_NOFAIL("ip link del %s", IP6VXLAN_TUNL_DEV1);
124}
125
126static int add_vxlan_tunnel(void)
127{
128 /* at_ns0 namespace */
129 SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
130 VXLAN_TUNL_DEV0);
131 SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
132 VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
133 SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
134 VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
135 SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
136 IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
137 SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0",
138 IP4_ADDR2_VETH1, MAC_VETH1);
139
140 /* root namespace */
141 SYS(fail, "ip link add dev %s type vxlan external gbp dstport 4789",
142 VXLAN_TUNL_DEV1);
143 SYS(fail, "ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
144 SYS(fail, "ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
145 SYS(fail, "ip neigh add %s lladdr %s dev %s",
146 IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
147
148 return 0;
149fail:
150 return -1;
151}
152
153static void delete_vxlan_tunnel(void)
154{
155 SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
156 VXLAN_TUNL_DEV0);
157 SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
158}
159
160static int add_ip6vxlan_tunnel(void)
161{
162 SYS(fail, "ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
163 IP6_ADDR_VETH0);
164 SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up");
165 SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
166 SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
167 SYS(fail, "ip link set dev veth1 up");
168
169 /* at_ns0 namespace */
170 SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
171 IP6VXLAN_TUNL_DEV0);
172 SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
173 IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
174 SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
175 IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
176
177 /* root namespace */
178 SYS(fail, "ip link add dev %s type vxlan external dstport 4789",
179 IP6VXLAN_TUNL_DEV1);
180 SYS(fail, "ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
181 SYS(fail, "ip link set dev %s address %s up",
182 IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
183
184 return 0;
185fail:
186 return -1;
187}
188
189static void delete_ip6vxlan_tunnel(void)
190{
191 SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
192 IP6_ADDR_VETH0);
193 SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
194 SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
195 SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
196 IP6VXLAN_TUNL_DEV0);
197 SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
198}
199
200enum ipip_encap {
201 NONE = 0,
202 FOU = 1,
203 GUE = 2,
204};
205
206static int set_ipip_encap(const char *ipproto, const char *type)
207{
208 SYS(fail, "ip -n at_ns0 fou add port 5555 %s", ipproto);
209 SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap %s",
210 IPIP_TUNL_DEV0, type);
211 SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap-dport 5555",
212 IPIP_TUNL_DEV0);
213
214 return 0;
215fail:
216 return -1;
217}
218
219static int add_ipip_tunnel(enum ipip_encap encap)
220{
221 int err;
222 const char *ipproto, *type;
223
224 switch (encap) {
225 case FOU:
226 ipproto = "ipproto 4";
227 type = "fou";
228 break;
229 case GUE:
230 ipproto = "gue";
231 type = ipproto;
232 break;
233 default:
234 ipproto = NULL;
235 type = ipproto;
236 }
237
238 /* at_ns0 namespace */
239 SYS(fail, "ip -n at_ns0 link add dev %s type ipip local %s remote %s",
240 IPIP_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
241
242 if (type && ipproto) {
243 err = set_ipip_encap(ipproto, type);
244 if (!ASSERT_OK(err, "set_ipip_encap"))
245 goto fail;
246 }
247
248 SYS(fail, "ip -n at_ns0 link set dev %s up", IPIP_TUNL_DEV0);
249 SYS(fail, "ip -n at_ns0 addr add dev %s %s/24",
250 IPIP_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
251
252 /* root namespace */
253 if (type && ipproto)
254 SYS(fail, "ip fou add port 5555 %s", ipproto);
255 SYS(fail, "ip link add dev %s type ipip external", IPIP_TUNL_DEV1);
256 SYS(fail, "ip link set dev %s up", IPIP_TUNL_DEV1);
257 SYS(fail, "ip addr add dev %s %s/24", IPIP_TUNL_DEV1,
258 IP4_ADDR_TUNL_DEV1);
259
260 return 0;
261fail:
262 return -1;
263}
264
265static void delete_ipip_tunnel(void)
266{
267 SYS_NOFAIL("ip -n at_ns0 link delete dev %s", IPIP_TUNL_DEV0);
268 SYS_NOFAIL("ip -n at_ns0 fou del port 5555");
269 SYS_NOFAIL("ip link delete dev %s", IPIP_TUNL_DEV1);
270 SYS_NOFAIL("ip fou del port 5555");
271}
272
273static int add_xfrm_tunnel(void)
274{
275 /* at_ns0 namespace
276 * at_ns0 -> root
277 */
278 SYS(fail,
279 "ip netns exec at_ns0 "
280 "ip xfrm state add src %s dst %s proto esp "
281 "spi %d reqid 1 mode tunnel replay-window 42 "
282 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
283 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
284 SYS(fail,
285 "ip netns exec at_ns0 "
286 "ip xfrm policy add src %s/32 dst %s/32 dir out "
287 "tmpl src %s dst %s proto esp reqid 1 "
288 "mode tunnel",
289 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
290
291 /* root -> at_ns0 */
292 SYS(fail,
293 "ip netns exec at_ns0 "
294 "ip xfrm state add src %s dst %s proto esp "
295 "spi %d reqid 2 mode tunnel "
296 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
297 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
298 SYS(fail,
299 "ip netns exec at_ns0 "
300 "ip xfrm policy add src %s/32 dst %s/32 dir in "
301 "tmpl src %s dst %s proto esp reqid 2 "
302 "mode tunnel",
303 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
304
305 /* address & route */
306 SYS(fail, "ip netns exec at_ns0 ip addr add dev veth0 %s/32",
307 IP4_ADDR_TUNL_DEV0);
308 SYS(fail, "ip netns exec at_ns0 ip route add %s dev veth0 via %s src %s",
309 IP4_ADDR_TUNL_DEV1, IP4_ADDR1_VETH1, IP4_ADDR_TUNL_DEV0);
310
311 /* root namespace
312 * at_ns0 -> root
313 */
314 SYS(fail,
315 "ip xfrm state add src %s dst %s proto esp "
316 "spi %d reqid 1 mode tunnel replay-window 42 "
317 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
318 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
319 SYS(fail,
320 "ip xfrm policy add src %s/32 dst %s/32 dir in "
321 "tmpl src %s dst %s proto esp reqid 1 "
322 "mode tunnel",
323 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
324
325 /* root -> at_ns0 */
326 SYS(fail,
327 "ip xfrm state add src %s dst %s proto esp "
328 "spi %d reqid 2 mode tunnel "
329 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
330 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
331 SYS(fail,
332 "ip xfrm policy add src %s/32 dst %s/32 dir out "
333 "tmpl src %s dst %s proto esp reqid 2 "
334 "mode tunnel",
335 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
336
337 /* address & route */
338 SYS(fail, "ip addr add dev veth1 %s/32", IP4_ADDR_TUNL_DEV1);
339 SYS(fail, "ip route add %s dev veth1 via %s src %s",
340 IP4_ADDR_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR_TUNL_DEV1);
341
342 return 0;
343fail:
344 return -1;
345}
346
347static void delete_xfrm_tunnel(void)
348{
349 SYS_NOFAIL("ip xfrm policy delete dir out src %s/32 dst %s/32",
350 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0);
351 SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32",
352 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1);
353 SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d",
354 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT);
355 SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d",
356 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN);
357}
358
359static int test_ping(int family, const char *addr)
360{
361 SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
362 return 0;
363fail:
364 return -1;
365}
366
367static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
368{
369 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
370 .priority = 1, .prog_fd = igr_fd);
371 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
372 .priority = 1, .prog_fd = egr_fd);
373 int ret;
374
375 ret = bpf_tc_hook_create(hook);
376 if (!ASSERT_OK(ret, "create tc hook"))
377 return ret;
378
379 if (igr_fd >= 0) {
380 hook->attach_point = BPF_TC_INGRESS;
381 ret = bpf_tc_attach(hook, &opts1);
382 if (!ASSERT_OK(ret, "bpf_tc_attach")) {
383 bpf_tc_hook_destroy(hook);
384 return ret;
385 }
386 }
387
388 if (egr_fd >= 0) {
389 hook->attach_point = BPF_TC_EGRESS;
390 ret = bpf_tc_attach(hook, &opts2);
391 if (!ASSERT_OK(ret, "bpf_tc_attach")) {
392 bpf_tc_hook_destroy(hook);
393 return ret;
394 }
395 }
396
397 return 0;
398}
399
400static void test_vxlan_tunnel(void)
401{
402 struct test_tunnel_kern *skel = NULL;
403 struct nstoken *nstoken;
404 int local_ip_map_fd = -1;
405 int set_src_prog_fd, get_src_prog_fd;
406 int set_dst_prog_fd;
407 int key = 0, ifindex = -1;
408 uint local_ip;
409 int err;
410 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
411 .attach_point = BPF_TC_INGRESS);
412
413 /* add vxlan tunnel */
414 err = add_vxlan_tunnel();
415 if (!ASSERT_OK(err, "add vxlan tunnel"))
416 goto done;
417
418 /* load and attach bpf prog to tunnel dev tc hook point */
419 skel = test_tunnel_kern__open_and_load();
420 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
421 goto done;
422 ifindex = if_nametoindex(VXLAN_TUNL_DEV1);
423 if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex"))
424 goto done;
425 tc_hook.ifindex = ifindex;
426 get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
427 set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
428 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
429 goto done;
430 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
431 goto done;
432 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
433 goto done;
434
435 /* load and attach bpf prog to veth dev tc hook point */
436 ifindex = if_nametoindex("veth1");
437 if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
438 goto done;
439 tc_hook.ifindex = ifindex;
440 set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst);
441 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
442 goto done;
443 if (attach_tc_prog(&tc_hook, set_dst_prog_fd, -1))
444 goto done;
445
446 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
447 nstoken = open_netns("at_ns0");
448 if (!ASSERT_OK_PTR(nstoken, "setns src"))
449 goto done;
450 ifindex = if_nametoindex(VXLAN_TUNL_DEV0);
451 if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex"))
452 goto done;
453 tc_hook.ifindex = ifindex;
454 set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
455 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
456 goto done;
457 if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
458 goto done;
459 close_netns(nstoken);
460
461 /* use veth1 ip 2 as tunnel source ip */
462 local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
463 if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
464 goto done;
465 local_ip = IP4_ADDR2_HEX_VETH1;
466 err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
467 if (!ASSERT_OK(err, "update bpf local_ip_map"))
468 goto done;
469
470 /* ping test */
471 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
472 if (!ASSERT_OK(err, "test_ping"))
473 goto done;
474
475done:
476 /* delete vxlan tunnel */
477 delete_vxlan_tunnel();
478 if (local_ip_map_fd >= 0)
479 close(local_ip_map_fd);
480 if (skel)
481 test_tunnel_kern__destroy(skel);
482}
483
484static void test_ip6vxlan_tunnel(void)
485{
486 struct test_tunnel_kern *skel = NULL;
487 struct nstoken *nstoken;
488 int local_ip_map_fd = -1;
489 int set_src_prog_fd, get_src_prog_fd;
490 int set_dst_prog_fd;
491 int key = 0, ifindex = -1;
492 uint local_ip;
493 int err;
494 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
495 .attach_point = BPF_TC_INGRESS);
496
497 /* add vxlan tunnel */
498 err = add_ip6vxlan_tunnel();
499 if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
500 goto done;
501
502 /* load and attach bpf prog to tunnel dev tc hook point */
503 skel = test_tunnel_kern__open_and_load();
504 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
505 goto done;
506 ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1);
507 if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex"))
508 goto done;
509 tc_hook.ifindex = ifindex;
510 get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
511 set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
512 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
513 goto done;
514 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
515 goto done;
516 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
517 goto done;
518
519 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
520 nstoken = open_netns("at_ns0");
521 if (!ASSERT_OK_PTR(nstoken, "setns src"))
522 goto done;
523 ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0);
524 if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex"))
525 goto done;
526 tc_hook.ifindex = ifindex;
527 set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
528 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
529 goto done;
530 if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
531 goto done;
532 close_netns(nstoken);
533
534 /* use veth1 ip 2 as tunnel source ip */
535 local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
536 if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
537 goto done;
538 local_ip = IP6_ADDR2_HEX_VETH1;
539 err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
540 if (!ASSERT_OK(err, "update bpf local_ip_map"))
541 goto done;
542
543 /* ping test */
544 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
545 if (!ASSERT_OK(err, "test_ping"))
546 goto done;
547
548done:
549 /* delete ipv6 vxlan tunnel */
550 delete_ip6vxlan_tunnel();
551 if (local_ip_map_fd >= 0)
552 close(local_ip_map_fd);
553 if (skel)
554 test_tunnel_kern__destroy(skel);
555}
556
557static void test_ipip_tunnel(enum ipip_encap encap)
558{
559 struct test_tunnel_kern *skel = NULL;
560 struct nstoken *nstoken;
561 int set_src_prog_fd, get_src_prog_fd;
562 int ifindex = -1;
563 int err;
564 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
565 .attach_point = BPF_TC_INGRESS);
566
567 /* add ipip tunnel */
568 err = add_ipip_tunnel(encap);
569 if (!ASSERT_OK(err, "add_ipip_tunnel"))
570 goto done;
571
572 /* load and attach bpf prog to tunnel dev tc hook point */
573 skel = test_tunnel_kern__open_and_load();
574 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
575 goto done;
576 ifindex = if_nametoindex(IPIP_TUNL_DEV1);
577 if (!ASSERT_NEQ(ifindex, 0, "ipip11 ifindex"))
578 goto done;
579 tc_hook.ifindex = ifindex;
580
581 switch (encap) {
582 case FOU:
583 get_src_prog_fd = bpf_program__fd(
584 skel->progs.ipip_encap_get_tunnel);
585 set_src_prog_fd = bpf_program__fd(
586 skel->progs.ipip_fou_set_tunnel);
587 break;
588 case GUE:
589 get_src_prog_fd = bpf_program__fd(
590 skel->progs.ipip_encap_get_tunnel);
591 set_src_prog_fd = bpf_program__fd(
592 skel->progs.ipip_gue_set_tunnel);
593 break;
594 default:
595 get_src_prog_fd = bpf_program__fd(
596 skel->progs.ipip_get_tunnel);
597 set_src_prog_fd = bpf_program__fd(
598 skel->progs.ipip_set_tunnel);
599 }
600
601 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
602 goto done;
603 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
604 goto done;
605 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
606 goto done;
607
608 /* ping from root namespace test */
609 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
610 if (!ASSERT_OK(err, "test_ping"))
611 goto done;
612
613 /* ping from at_ns0 namespace test */
614 nstoken = open_netns("at_ns0");
615 if (!ASSERT_OK_PTR(nstoken, "setns"))
616 goto done;
617 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
618 if (!ASSERT_OK(err, "test_ping"))
619 goto done;
620 close_netns(nstoken);
621
622done:
623 /* delete ipip tunnel */
624 delete_ipip_tunnel();
625 if (skel)
626 test_tunnel_kern__destroy(skel);
627}
628
629static void test_xfrm_tunnel(void)
630{
631 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
632 .attach_point = BPF_TC_INGRESS);
633 LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
634 struct test_tunnel_kern *skel = NULL;
635 struct nstoken *nstoken;
636 int xdp_prog_fd;
637 int tc_prog_fd;
638 int ifindex;
639 int err;
640
641 err = add_xfrm_tunnel();
642 if (!ASSERT_OK(err, "add_xfrm_tunnel"))
643 return;
644
645 skel = test_tunnel_kern__open_and_load();
646 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
647 goto done;
648
649 ifindex = if_nametoindex("veth1");
650 if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
651 goto done;
652
653 /* attach tc prog to tunnel dev */
654 tc_hook.ifindex = ifindex;
655 tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state);
656 if (!ASSERT_GE(tc_prog_fd, 0, "bpf_program__fd"))
657 goto done;
658 if (attach_tc_prog(&tc_hook, tc_prog_fd, -1))
659 goto done;
660
661 /* attach xdp prog to tunnel dev */
662 xdp_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state_xdp);
663 if (!ASSERT_GE(xdp_prog_fd, 0, "bpf_program__fd"))
664 goto done;
665 err = bpf_xdp_attach(ifindex, xdp_prog_fd, XDP_FLAGS_REPLACE, &opts);
666 if (!ASSERT_OK(err, "bpf_xdp_attach"))
667 goto done;
668
669 /* ping from at_ns0 namespace test */
670 nstoken = open_netns("at_ns0");
671 if (!ASSERT_OK_PTR(nstoken, "setns"))
672 goto done;
673 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
674 close_netns(nstoken);
675 if (!ASSERT_OK(err, "test_ping"))
676 goto done;
677
678 if (!ASSERT_EQ(skel->bss->xfrm_reqid, 1, "req_id"))
679 goto done;
680 if (!ASSERT_EQ(skel->bss->xfrm_spi, XFRM_SPI_IN_TO_OUT, "spi"))
681 goto done;
682 if (!ASSERT_EQ(skel->bss->xfrm_remote_ip, 0xac100164, "remote_ip"))
683 goto done;
684 if (!ASSERT_EQ(skel->bss->xfrm_replay_window, 42, "replay_window"))
685 goto done;
686
687done:
688 delete_xfrm_tunnel();
689 if (skel)
690 test_tunnel_kern__destroy(skel);
691}
692
693#define RUN_TEST(name, ...) \
694 ({ \
695 if (test__start_subtest(#name)) { \
696 config_device(); \
697 test_ ## name(__VA_ARGS__); \
698 cleanup(); \
699 } \
700 })
701
702static void *test_tunnel_run_tests(void *arg)
703{
704 RUN_TEST(vxlan_tunnel);
705 RUN_TEST(ip6vxlan_tunnel);
706 RUN_TEST(ipip_tunnel, NONE);
707 RUN_TEST(ipip_tunnel, FOU);
708 RUN_TEST(ipip_tunnel, GUE);
709 RUN_TEST(xfrm_tunnel);
710
711 return NULL;
712}
713
714void test_tunnel(void)
715{
716 pthread_t test_thread;
717 int err;
718
719 /* Run the tests in their own thread to isolate the namespace changes
720 * so they do not affect the environment of other tests.
721 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
722 */
723 err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
724 if (ASSERT_OK(err, "pthread_create"))
725 ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
726}
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
3/*
4 * End-to-end eBPF tunnel test suite
5 * The file tests BPF network tunnel implementation.
6 *
7 * Topology:
8 * ---------
9 * root namespace | at_ns0 namespace
10 * |
11 * ----------- | -----------
12 * | tnl dev | | | tnl dev | (overlay network)
13 * ----------- | -----------
14 * metadata-mode | metadata-mode
15 * with bpf | with bpf
16 * |
17 * ---------- | ----------
18 * | veth1 | --------- | veth0 | (underlay network)
19 * ---------- peer ----------
20 *
21 *
22 * Device Configuration
23 * --------------------
24 * root namespace with metadata-mode tunnel + BPF
25 * Device names and addresses:
26 * veth1 IP 1: 172.16.1.200, IPv6: 00::22 (underlay)
27 * IP 2: 172.16.1.20, IPv6: 00::bb (underlay)
28 * tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)
29 *
30 * Namespace at_ns0 with native tunnel
31 * Device names and addresses:
32 * veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
33 * tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)
34 *
35 *
36 * End-to-end ping packet flow
37 * ---------------------------
38 * Most of the tests start by namespace creation, device configuration,
39 * then ping the underlay and overlay network. When doing 'ping 10.1.1.100'
40 * from root namespace, the following operations happen:
41 * 1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
42 * 2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
43 * with local_ip=172.16.1.200, remote_ip=172.16.1.100. BPF program choose
44 * the primary or secondary ip of veth1 as the local ip of tunnel. The
45 * choice is made based on the value of bpf map local_ip_map.
46 * 3) Outer tunnel header is prepended and route the packet to veth1's egress.
47 * 4) veth0's ingress queue receive the tunneled packet at namespace at_ns0.
48 * 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet.
49 * 6) Forward the packet to the overlay tnl dev.
50 */
51
52#include <arpa/inet.h>
53#include <linux/if_link.h>
54#include <linux/if_tun.h>
55#include <linux/limits.h>
56#include <linux/sysctl.h>
57#include <linux/time_types.h>
58#include <linux/net_tstamp.h>
59#include <net/if.h>
60#include <stdbool.h>
61#include <stdio.h>
62#include <sys/stat.h>
63#include <unistd.h>
64
65#include "test_progs.h"
66#include "network_helpers.h"
67#include "test_tunnel_kern.skel.h"
68
69#define IP4_ADDR_VETH0 "172.16.1.100"
70#define IP4_ADDR1_VETH1 "172.16.1.200"
71#define IP4_ADDR2_VETH1 "172.16.1.20"
72#define IP4_ADDR_TUNL_DEV0 "10.1.1.100"
73#define IP4_ADDR_TUNL_DEV1 "10.1.1.200"
74
75#define IP6_ADDR_VETH0 "::11"
76#define IP6_ADDR1_VETH1 "::22"
77#define IP6_ADDR2_VETH1 "::bb"
78
79#define IP4_ADDR1_HEX_VETH1 0xac1001c8
80#define IP4_ADDR2_HEX_VETH1 0xac100114
81#define IP6_ADDR1_HEX_VETH1 0x22
82#define IP6_ADDR2_HEX_VETH1 0xbb
83
84#define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
85#define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
86#define MAC_VETH1 "52:54:00:d9:03:00"
87
88#define VXLAN_TUNL_DEV0 "vxlan00"
89#define VXLAN_TUNL_DEV1 "vxlan11"
90#define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
91#define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
92
93#define IPIP_TUNL_DEV0 "ipip00"
94#define IPIP_TUNL_DEV1 "ipip11"
95
96#define XFRM_AUTH "0x1111111111111111111111111111111111111111"
97#define XFRM_ENC "0x22222222222222222222222222222222"
98#define XFRM_SPI_IN_TO_OUT 0x1
99#define XFRM_SPI_OUT_TO_IN 0x2
100
101#define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
102
103static int config_device(void)
104{
105 SYS(fail, "ip netns add at_ns0");
106 SYS(fail, "ip link add veth0 address " MAC_VETH1 " type veth peer name veth1");
107 SYS(fail, "ip link set veth0 netns at_ns0");
108 SYS(fail, "ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
109 SYS(fail, "ip link set dev veth1 up mtu 1500");
110 SYS(fail, "ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
111 SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
112
113 return 0;
114fail:
115 return -1;
116}
117
118static void cleanup(void)
119{
120 SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
121 SYS_NOFAIL("ip link del veth1 2> /dev/null");
122 SYS_NOFAIL("ip link del %s 2> /dev/null", VXLAN_TUNL_DEV1);
123 SYS_NOFAIL("ip link del %s 2> /dev/null", IP6VXLAN_TUNL_DEV1);
124}
125
126static int add_vxlan_tunnel(void)
127{
128 /* at_ns0 namespace */
129 SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
130 VXLAN_TUNL_DEV0);
131 SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
132 VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
133 SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
134 VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
135 SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
136 IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
137 SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0",
138 IP4_ADDR2_VETH1, MAC_VETH1);
139
140 /* root namespace */
141 SYS(fail, "ip link add dev %s type vxlan external gbp dstport 4789",
142 VXLAN_TUNL_DEV1);
143 SYS(fail, "ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
144 SYS(fail, "ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
145 SYS(fail, "ip neigh add %s lladdr %s dev %s",
146 IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
147
148 return 0;
149fail:
150 return -1;
151}
152
153static void delete_vxlan_tunnel(void)
154{
155 SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
156 VXLAN_TUNL_DEV0);
157 SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
158}
159
160static int add_ip6vxlan_tunnel(void)
161{
162 SYS(fail, "ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
163 IP6_ADDR_VETH0);
164 SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up");
165 SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
166 SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
167 SYS(fail, "ip link set dev veth1 up");
168
169 /* at_ns0 namespace */
170 SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
171 IP6VXLAN_TUNL_DEV0);
172 SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
173 IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
174 SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
175 IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
176
177 /* root namespace */
178 SYS(fail, "ip link add dev %s type vxlan external dstport 4789",
179 IP6VXLAN_TUNL_DEV1);
180 SYS(fail, "ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
181 SYS(fail, "ip link set dev %s address %s up",
182 IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
183
184 return 0;
185fail:
186 return -1;
187}
188
189static void delete_ip6vxlan_tunnel(void)
190{
191 SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
192 IP6_ADDR_VETH0);
193 SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
194 SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
195 SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
196 IP6VXLAN_TUNL_DEV0);
197 SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
198}
199
200enum ipip_encap {
201 NONE = 0,
202 FOU = 1,
203 GUE = 2,
204};
205
206static int set_ipip_encap(const char *ipproto, const char *type)
207{
208 SYS(fail, "ip -n at_ns0 fou add port 5555 %s", ipproto);
209 SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap %s",
210 IPIP_TUNL_DEV0, type);
211 SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap-dport 5555",
212 IPIP_TUNL_DEV0);
213
214 return 0;
215fail:
216 return -1;
217}
218
219static int add_ipip_tunnel(enum ipip_encap encap)
220{
221 int err;
222 const char *ipproto, *type;
223
224 switch (encap) {
225 case FOU:
226 ipproto = "ipproto 4";
227 type = "fou";
228 break;
229 case GUE:
230 ipproto = "gue";
231 type = ipproto;
232 break;
233 default:
234 ipproto = NULL;
235 type = ipproto;
236 }
237
238 /* at_ns0 namespace */
239 SYS(fail, "ip -n at_ns0 link add dev %s type ipip local %s remote %s",
240 IPIP_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
241
242 if (type && ipproto) {
243 err = set_ipip_encap(ipproto, type);
244 if (!ASSERT_OK(err, "set_ipip_encap"))
245 goto fail;
246 }
247
248 SYS(fail, "ip -n at_ns0 link set dev %s up", IPIP_TUNL_DEV0);
249 SYS(fail, "ip -n at_ns0 addr add dev %s %s/24",
250 IPIP_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
251
252 /* root namespace */
253 if (type && ipproto)
254 SYS(fail, "ip fou add port 5555 %s", ipproto);
255 SYS(fail, "ip link add dev %s type ipip external", IPIP_TUNL_DEV1);
256 SYS(fail, "ip link set dev %s up", IPIP_TUNL_DEV1);
257 SYS(fail, "ip addr add dev %s %s/24", IPIP_TUNL_DEV1,
258 IP4_ADDR_TUNL_DEV1);
259
260 return 0;
261fail:
262 return -1;
263}
264
265static void delete_ipip_tunnel(void)
266{
267 SYS_NOFAIL("ip -n at_ns0 link delete dev %s", IPIP_TUNL_DEV0);
268 SYS_NOFAIL("ip -n at_ns0 fou del port 5555 2> /dev/null");
269 SYS_NOFAIL("ip link delete dev %s", IPIP_TUNL_DEV1);
270 SYS_NOFAIL("ip fou del port 5555 2> /dev/null");
271}
272
273static int add_xfrm_tunnel(void)
274{
275 /* at_ns0 namespace
276 * at_ns0 -> root
277 */
278 SYS(fail,
279 "ip netns exec at_ns0 "
280 "ip xfrm state add src %s dst %s proto esp "
281 "spi %d reqid 1 mode tunnel replay-window 42 "
282 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
283 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
284 SYS(fail,
285 "ip netns exec at_ns0 "
286 "ip xfrm policy add src %s/32 dst %s/32 dir out "
287 "tmpl src %s dst %s proto esp reqid 1 "
288 "mode tunnel",
289 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
290
291 /* root -> at_ns0 */
292 SYS(fail,
293 "ip netns exec at_ns0 "
294 "ip xfrm state add src %s dst %s proto esp "
295 "spi %d reqid 2 mode tunnel "
296 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
297 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
298 SYS(fail,
299 "ip netns exec at_ns0 "
300 "ip xfrm policy add src %s/32 dst %s/32 dir in "
301 "tmpl src %s dst %s proto esp reqid 2 "
302 "mode tunnel",
303 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
304
305 /* address & route */
306 SYS(fail, "ip netns exec at_ns0 ip addr add dev veth0 %s/32",
307 IP4_ADDR_TUNL_DEV0);
308 SYS(fail, "ip netns exec at_ns0 ip route add %s dev veth0 via %s src %s",
309 IP4_ADDR_TUNL_DEV1, IP4_ADDR1_VETH1, IP4_ADDR_TUNL_DEV0);
310
311 /* root namespace
312 * at_ns0 -> root
313 */
314 SYS(fail,
315 "ip xfrm state add src %s dst %s proto esp "
316 "spi %d reqid 1 mode tunnel replay-window 42 "
317 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
318 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
319 SYS(fail,
320 "ip xfrm policy add src %s/32 dst %s/32 dir in "
321 "tmpl src %s dst %s proto esp reqid 1 "
322 "mode tunnel",
323 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
324
325 /* root -> at_ns0 */
326 SYS(fail,
327 "ip xfrm state add src %s dst %s proto esp "
328 "spi %d reqid 2 mode tunnel "
329 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
330 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
331 SYS(fail,
332 "ip xfrm policy add src %s/32 dst %s/32 dir out "
333 "tmpl src %s dst %s proto esp reqid 2 "
334 "mode tunnel",
335 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
336
337 /* address & route */
338 SYS(fail, "ip addr add dev veth1 %s/32", IP4_ADDR_TUNL_DEV1);
339 SYS(fail, "ip route add %s dev veth1 via %s src %s",
340 IP4_ADDR_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR_TUNL_DEV1);
341
342 return 0;
343fail:
344 return -1;
345}
346
347static void delete_xfrm_tunnel(void)
348{
349 SYS_NOFAIL("ip xfrm policy delete dir out src %s/32 dst %s/32 2> /dev/null",
350 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0);
351 SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32 2> /dev/null",
352 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1);
353 SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d 2> /dev/null",
354 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT);
355 SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d 2> /dev/null",
356 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN);
357}
358
359static int test_ping(int family, const char *addr)
360{
361 SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
362 return 0;
363fail:
364 return -1;
365}
366
367static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
368{
369 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
370 .priority = 1, .prog_fd = igr_fd);
371 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
372 .priority = 1, .prog_fd = egr_fd);
373 int ret;
374
375 ret = bpf_tc_hook_create(hook);
376 if (!ASSERT_OK(ret, "create tc hook"))
377 return ret;
378
379 if (igr_fd >= 0) {
380 hook->attach_point = BPF_TC_INGRESS;
381 ret = bpf_tc_attach(hook, &opts1);
382 if (!ASSERT_OK(ret, "bpf_tc_attach")) {
383 bpf_tc_hook_destroy(hook);
384 return ret;
385 }
386 }
387
388 if (egr_fd >= 0) {
389 hook->attach_point = BPF_TC_EGRESS;
390 ret = bpf_tc_attach(hook, &opts2);
391 if (!ASSERT_OK(ret, "bpf_tc_attach")) {
392 bpf_tc_hook_destroy(hook);
393 return ret;
394 }
395 }
396
397 return 0;
398}
399
400static void test_vxlan_tunnel(void)
401{
402 struct test_tunnel_kern *skel = NULL;
403 struct nstoken *nstoken;
404 int local_ip_map_fd = -1;
405 int set_src_prog_fd, get_src_prog_fd;
406 int set_dst_prog_fd;
407 int key = 0, ifindex = -1;
408 uint local_ip;
409 int err;
410 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
411 .attach_point = BPF_TC_INGRESS);
412
413 /* add vxlan tunnel */
414 err = add_vxlan_tunnel();
415 if (!ASSERT_OK(err, "add vxlan tunnel"))
416 goto done;
417
418 /* load and attach bpf prog to tunnel dev tc hook point */
419 skel = test_tunnel_kern__open_and_load();
420 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
421 goto done;
422 ifindex = if_nametoindex(VXLAN_TUNL_DEV1);
423 if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex"))
424 goto done;
425 tc_hook.ifindex = ifindex;
426 get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
427 set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
428 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
429 goto done;
430 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
431 goto done;
432 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
433 goto done;
434
435 /* load and attach bpf prog to veth dev tc hook point */
436 ifindex = if_nametoindex("veth1");
437 if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
438 goto done;
439 tc_hook.ifindex = ifindex;
440 set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst);
441 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
442 goto done;
443 if (attach_tc_prog(&tc_hook, set_dst_prog_fd, -1))
444 goto done;
445
446 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
447 nstoken = open_netns("at_ns0");
448 if (!ASSERT_OK_PTR(nstoken, "setns src"))
449 goto done;
450 ifindex = if_nametoindex(VXLAN_TUNL_DEV0);
451 if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex"))
452 goto done;
453 tc_hook.ifindex = ifindex;
454 set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
455 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
456 goto done;
457 if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
458 goto done;
459 close_netns(nstoken);
460
461 /* use veth1 ip 2 as tunnel source ip */
462 local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
463 if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
464 goto done;
465 local_ip = IP4_ADDR2_HEX_VETH1;
466 err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
467 if (!ASSERT_OK(err, "update bpf local_ip_map"))
468 goto done;
469
470 /* ping test */
471 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
472 if (!ASSERT_OK(err, "test_ping"))
473 goto done;
474
475done:
476 /* delete vxlan tunnel */
477 delete_vxlan_tunnel();
478 if (local_ip_map_fd >= 0)
479 close(local_ip_map_fd);
480 if (skel)
481 test_tunnel_kern__destroy(skel);
482}
483
484static void test_ip6vxlan_tunnel(void)
485{
486 struct test_tunnel_kern *skel = NULL;
487 struct nstoken *nstoken;
488 int local_ip_map_fd = -1;
489 int set_src_prog_fd, get_src_prog_fd;
490 int set_dst_prog_fd;
491 int key = 0, ifindex = -1;
492 uint local_ip;
493 int err;
494 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
495 .attach_point = BPF_TC_INGRESS);
496
497 /* add vxlan tunnel */
498 err = add_ip6vxlan_tunnel();
499 if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
500 goto done;
501
502 /* load and attach bpf prog to tunnel dev tc hook point */
503 skel = test_tunnel_kern__open_and_load();
504 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
505 goto done;
506 ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1);
507 if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex"))
508 goto done;
509 tc_hook.ifindex = ifindex;
510 get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
511 set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
512 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
513 goto done;
514 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
515 goto done;
516 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
517 goto done;
518
519 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
520 nstoken = open_netns("at_ns0");
521 if (!ASSERT_OK_PTR(nstoken, "setns src"))
522 goto done;
523 ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0);
524 if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex"))
525 goto done;
526 tc_hook.ifindex = ifindex;
527 set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
528 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
529 goto done;
530 if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
531 goto done;
532 close_netns(nstoken);
533
534 /* use veth1 ip 2 as tunnel source ip */
535 local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
536 if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
537 goto done;
538 local_ip = IP6_ADDR2_HEX_VETH1;
539 err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
540 if (!ASSERT_OK(err, "update bpf local_ip_map"))
541 goto done;
542
543 /* ping test */
544 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
545 if (!ASSERT_OK(err, "test_ping"))
546 goto done;
547
548done:
549 /* delete ipv6 vxlan tunnel */
550 delete_ip6vxlan_tunnel();
551 if (local_ip_map_fd >= 0)
552 close(local_ip_map_fd);
553 if (skel)
554 test_tunnel_kern__destroy(skel);
555}
556
557static void test_ipip_tunnel(enum ipip_encap encap)
558{
559 struct test_tunnel_kern *skel = NULL;
560 struct nstoken *nstoken;
561 int set_src_prog_fd, get_src_prog_fd;
562 int ifindex = -1;
563 int err;
564 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
565 .attach_point = BPF_TC_INGRESS);
566
567 /* add ipip tunnel */
568 err = add_ipip_tunnel(encap);
569 if (!ASSERT_OK(err, "add_ipip_tunnel"))
570 goto done;
571
572 /* load and attach bpf prog to tunnel dev tc hook point */
573 skel = test_tunnel_kern__open_and_load();
574 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
575 goto done;
576 ifindex = if_nametoindex(IPIP_TUNL_DEV1);
577 if (!ASSERT_NEQ(ifindex, 0, "ipip11 ifindex"))
578 goto done;
579 tc_hook.ifindex = ifindex;
580
581 switch (encap) {
582 case FOU:
583 get_src_prog_fd = bpf_program__fd(
584 skel->progs.ipip_encap_get_tunnel);
585 set_src_prog_fd = bpf_program__fd(
586 skel->progs.ipip_fou_set_tunnel);
587 break;
588 case GUE:
589 get_src_prog_fd = bpf_program__fd(
590 skel->progs.ipip_encap_get_tunnel);
591 set_src_prog_fd = bpf_program__fd(
592 skel->progs.ipip_gue_set_tunnel);
593 break;
594 default:
595 get_src_prog_fd = bpf_program__fd(
596 skel->progs.ipip_get_tunnel);
597 set_src_prog_fd = bpf_program__fd(
598 skel->progs.ipip_set_tunnel);
599 }
600
601 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
602 goto done;
603 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
604 goto done;
605 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
606 goto done;
607
608 /* ping from root namespace test */
609 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
610 if (!ASSERT_OK(err, "test_ping"))
611 goto done;
612
613 /* ping from at_ns0 namespace test */
614 nstoken = open_netns("at_ns0");
615 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
616 if (!ASSERT_OK(err, "test_ping"))
617 goto done;
618 close_netns(nstoken);
619
620done:
621 /* delete ipip tunnel */
622 delete_ipip_tunnel();
623 if (skel)
624 test_tunnel_kern__destroy(skel);
625}
626
627static void test_xfrm_tunnel(void)
628{
629 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
630 .attach_point = BPF_TC_INGRESS);
631 LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
632 struct test_tunnel_kern *skel = NULL;
633 struct nstoken *nstoken;
634 int xdp_prog_fd;
635 int tc_prog_fd;
636 int ifindex;
637 int err;
638
639 err = add_xfrm_tunnel();
640 if (!ASSERT_OK(err, "add_xfrm_tunnel"))
641 return;
642
643 skel = test_tunnel_kern__open_and_load();
644 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
645 goto done;
646
647 ifindex = if_nametoindex("veth1");
648 if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
649 goto done;
650
651 /* attach tc prog to tunnel dev */
652 tc_hook.ifindex = ifindex;
653 tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state);
654 if (!ASSERT_GE(tc_prog_fd, 0, "bpf_program__fd"))
655 goto done;
656 if (attach_tc_prog(&tc_hook, tc_prog_fd, -1))
657 goto done;
658
659 /* attach xdp prog to tunnel dev */
660 xdp_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state_xdp);
661 if (!ASSERT_GE(xdp_prog_fd, 0, "bpf_program__fd"))
662 goto done;
663 err = bpf_xdp_attach(ifindex, xdp_prog_fd, XDP_FLAGS_REPLACE, &opts);
664 if (!ASSERT_OK(err, "bpf_xdp_attach"))
665 goto done;
666
667 /* ping from at_ns0 namespace test */
668 nstoken = open_netns("at_ns0");
669 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
670 close_netns(nstoken);
671 if (!ASSERT_OK(err, "test_ping"))
672 goto done;
673
674 if (!ASSERT_EQ(skel->bss->xfrm_reqid, 1, "req_id"))
675 goto done;
676 if (!ASSERT_EQ(skel->bss->xfrm_spi, XFRM_SPI_IN_TO_OUT, "spi"))
677 goto done;
678 if (!ASSERT_EQ(skel->bss->xfrm_remote_ip, 0xac100164, "remote_ip"))
679 goto done;
680 if (!ASSERT_EQ(skel->bss->xfrm_replay_window, 42, "replay_window"))
681 goto done;
682
683done:
684 delete_xfrm_tunnel();
685 if (skel)
686 test_tunnel_kern__destroy(skel);
687}
688
689#define RUN_TEST(name, ...) \
690 ({ \
691 if (test__start_subtest(#name)) { \
692 config_device(); \
693 test_ ## name(__VA_ARGS__); \
694 cleanup(); \
695 } \
696 })
697
698static void *test_tunnel_run_tests(void *arg)
699{
700 RUN_TEST(vxlan_tunnel);
701 RUN_TEST(ip6vxlan_tunnel);
702 RUN_TEST(ipip_tunnel, NONE);
703 RUN_TEST(ipip_tunnel, FOU);
704 RUN_TEST(ipip_tunnel, GUE);
705 RUN_TEST(xfrm_tunnel);
706
707 return NULL;
708}
709
710void test_tunnel(void)
711{
712 pthread_t test_thread;
713 int err;
714
715 /* Run the tests in their own thread to isolate the namespace changes
716 * so they do not affect the environment of other tests.
717 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
718 */
719 err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
720 if (ASSERT_OK(err, "pthread_create"))
721 ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
722}