Skip to content

Commit a93bfd8

Browse files
bastien-curutchetMartin KaFai Lau
authored andcommitted
selftests/bpf: test_xdp_veth: Add XDP program on egress test
XDP programs loaded on egress is tested by test_xdp_redirect_multi.sh but not by the test_progs framework. Add a test case in test_xdp_veth.c to test the XDP program on egress. Use the same BPF program than test_xdp_redirect_multi.sh that replaces the source MAC address by one provided through a BPF map. Use a BPF program that stores the source MAC of received packets in a map to check the test results. Signed-off-by: Bastien Curutchet (eBPF Foundation) <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Acked-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 1e7e634 commit a93bfd8

File tree

2 files changed

+172
-0
lines changed

2 files changed

+172
-0
lines changed

tools/testing/selftests/bpf/prog_tests/test_xdp_veth.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
* -> echo request received by all except veth11
3535
* - IPv4 ping : BPF_F_BROADCAST
3636
* -> echo request received by all veth
37+
* - [test_xdp_veth_egress]:
38+
* - all src mac should be the magic mac
3739
*
3840
* veth11 veth22 veth33
3941
* (XDP_PASS) (XDP_PASS) (XDP_PASS)
@@ -431,6 +433,124 @@ static void xdp_veth_broadcast_redirect(u32 attach_flags, u64 redirect_flags)
431433
cleanup_network(&net_config);
432434
}
433435

436+
#define VETH_EGRESS_SKEL_NB 3
437+
static void xdp_veth_egress(u32 flags)
438+
{
439+
struct prog_configuration prog_cfg[VETH_PAIRS_COUNT] = {
440+
{
441+
.local_name = "xdp_redirect_map_all_prog",
442+
.remote_name = "xdp_dummy_prog",
443+
.local_flags = flags,
444+
.remote_flags = flags,
445+
},
446+
{
447+
.local_name = "xdp_redirect_map_all_prog",
448+
.remote_name = "store_mac_1",
449+
.local_flags = flags,
450+
.remote_flags = flags,
451+
},
452+
{
453+
.local_name = "xdp_redirect_map_all_prog",
454+
.remote_name = "store_mac_2",
455+
.local_flags = flags,
456+
.remote_flags = flags,
457+
}
458+
};
459+
const char magic_mac[6] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
460+
struct xdp_redirect_multi_kern *xdp_redirect_multi_kern;
461+
struct bpf_object *bpf_objs[VETH_EGRESS_SKEL_NB];
462+
struct xdp_redirect_map *xdp_redirect_map;
463+
struct bpf_devmap_val devmap_val = {};
464+
struct net_configuration net_config;
465+
int mac_map, egress_map, res_map;
466+
struct nstoken *nstoken = NULL;
467+
struct xdp_dummy *xdp_dummy;
468+
int err;
469+
int i;
470+
471+
xdp_dummy = xdp_dummy__open_and_load();
472+
if (!ASSERT_OK_PTR(xdp_dummy, "xdp_dummy__open_and_load"))
473+
return;
474+
475+
xdp_redirect_multi_kern = xdp_redirect_multi_kern__open_and_load();
476+
if (!ASSERT_OK_PTR(xdp_redirect_multi_kern, "xdp_redirect_multi_kern__open_and_load"))
477+
goto destroy_xdp_dummy;
478+
479+
xdp_redirect_map = xdp_redirect_map__open_and_load();
480+
if (!ASSERT_OK_PTR(xdp_redirect_map, "xdp_redirect_map__open_and_load"))
481+
goto destroy_xdp_redirect_multi_kern;
482+
483+
if (!ASSERT_OK(create_network(&net_config), "create network"))
484+
goto destroy_xdp_redirect_map;
485+
486+
mac_map = bpf_map__fd(xdp_redirect_multi_kern->maps.mac_map);
487+
if (!ASSERT_OK_FD(mac_map, "open mac_map"))
488+
goto destroy_xdp_redirect_map;
489+
490+
egress_map = bpf_map__fd(xdp_redirect_multi_kern->maps.map_egress);
491+
if (!ASSERT_OK_FD(egress_map, "open map_egress"))
492+
goto destroy_xdp_redirect_map;
493+
494+
devmap_val.bpf_prog.fd = bpf_program__fd(xdp_redirect_multi_kern->progs.xdp_devmap_prog);
495+
496+
bpf_objs[0] = xdp_dummy->obj;
497+
bpf_objs[1] = xdp_redirect_multi_kern->obj;
498+
bpf_objs[2] = xdp_redirect_map->obj;
499+
500+
nstoken = open_netns(net_config.ns0_name);
501+
if (!ASSERT_OK_PTR(nstoken, "open NS0"))
502+
goto destroy_xdp_redirect_map;
503+
504+
for (i = 0; i < VETH_PAIRS_COUNT; i++) {
505+
int ifindex = if_nametoindex(net_config.veth_cfg[i].local_veth);
506+
507+
SYS(destroy_xdp_redirect_map,
508+
"ip -n %s neigh add %s lladdr 00:00:00:00:00:01 dev %s",
509+
net_config.veth_cfg[i].namespace, IP_NEIGH, net_config.veth_cfg[i].remote_veth);
510+
511+
if (attach_programs_to_veth_pair(bpf_objs, VETH_REDIRECT_SKEL_NB,
512+
&net_config, prog_cfg, i))
513+
goto destroy_xdp_redirect_map;
514+
515+
err = bpf_map_update_elem(mac_map, &ifindex, magic_mac, 0);
516+
if (!ASSERT_OK(err, "bpf_map_update_elem"))
517+
goto destroy_xdp_redirect_map;
518+
519+
devmap_val.ifindex = ifindex;
520+
err = bpf_map_update_elem(egress_map, &ifindex, &devmap_val, 0);
521+
if (!ASSERT_OK(err, "bpf_map_update_elem"))
522+
goto destroy_xdp_redirect_map;
523+
}
524+
525+
SYS_NOFAIL("ip netns exec %s ping %s -i 0.1 -c 4 -W1 > /dev/null ",
526+
net_config.veth_cfg[0].namespace, IP_NEIGH);
527+
528+
res_map = bpf_map__fd(xdp_redirect_map->maps.rx_mac);
529+
if (!ASSERT_OK_FD(res_map, "open rx_map"))
530+
goto destroy_xdp_redirect_map;
531+
532+
for (i = 0; i < 2; i++) {
533+
u32 key = i;
534+
u64 res;
535+
536+
err = bpf_map_lookup_elem(res_map, &key, &res);
537+
if (!ASSERT_OK(err, "get MAC res"))
538+
goto destroy_xdp_redirect_map;
539+
540+
ASSERT_STRNEQ((const char *)&res, magic_mac, ETH_ALEN, "compare mac");
541+
}
542+
543+
destroy_xdp_redirect_map:
544+
close_netns(nstoken);
545+
xdp_redirect_map__destroy(xdp_redirect_map);
546+
destroy_xdp_redirect_multi_kern:
547+
xdp_redirect_multi_kern__destroy(xdp_redirect_multi_kern);
548+
destroy_xdp_dummy:
549+
xdp_dummy__destroy(xdp_dummy);
550+
551+
cleanup_network(&net_config);
552+
}
553+
434554
void test_xdp_veth_redirect(void)
435555
{
436556
if (test__start_subtest("0"))
@@ -465,3 +585,15 @@ void test_xdp_veth_broadcast_redirect(void)
465585
xdp_veth_broadcast_redirect(XDP_FLAGS_SKB_MODE,
466586
BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS);
467587
}
588+
589+
void test_xdp_veth_egress(void)
590+
{
591+
if (test__start_subtest("0/egress"))
592+
xdp_veth_egress(0);
593+
594+
if (test__start_subtest("DRV_MODE/egress"))
595+
xdp_veth_egress(XDP_FLAGS_DRV_MODE);
596+
597+
if (test__start_subtest("SKB_MODE/egress"))
598+
xdp_veth_egress(XDP_FLAGS_SKB_MODE);
599+
}

tools/testing/selftests/bpf/progs/xdp_redirect_map.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,44 @@ int xdp_count_2(struct xdp_md *xdp)
7676
return xdp_count(xdp, 2);
7777
}
7878

79+
struct {
80+
__uint(type, BPF_MAP_TYPE_ARRAY);
81+
__uint(max_entries, 2);
82+
__type(key, __u32);
83+
__type(value, __be64);
84+
} rx_mac SEC(".maps");
85+
86+
static int store_mac(struct xdp_md *xdp, __u32 id)
87+
{
88+
void *data_end = (void *)(long)xdp->data_end;
89+
void *data = (void *)(long)xdp->data;
90+
struct ethhdr *eth = data;
91+
__u32 key = id;
92+
__be64 mac = 0;
93+
94+
if (data + sizeof(*eth) > data_end)
95+
return XDP_DROP;
96+
97+
/* Only store IPv4 MAC to avoid being polluted by IPv6 packets */
98+
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
99+
__builtin_memcpy(&mac, eth->h_source, ETH_ALEN);
100+
bpf_map_update_elem(&rx_mac, &key, &mac, 0);
101+
bpf_printk("%s - %x", __func__, mac);
102+
}
103+
104+
return XDP_PASS;
105+
}
106+
107+
SEC("xdp")
108+
int store_mac_1(struct xdp_md *xdp)
109+
{
110+
return store_mac(xdp, 0);
111+
}
112+
113+
SEC("xdp")
114+
int store_mac_2(struct xdp_md *xdp)
115+
{
116+
return store_mac(xdp, 1);
117+
}
118+
79119
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)