1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
4 #include "test_xdp.skel.h"
5 #include "test_xdp_bpf2bpf.skel.h"
12 static void on_sample(void *ctx
, int cpu
, void *data
, __u32 size
)
15 struct meta
*meta
= (struct meta
*)data
;
16 struct ipv4_packet
*trace_pkt_v4
= data
+ sizeof(*meta
);
18 if (CHECK(size
< sizeof(pkt_v4
) + sizeof(*meta
),
19 "check_size", "size %u < %zu\n",
20 size
, sizeof(pkt_v4
) + sizeof(*meta
)))
23 if (CHECK(meta
->ifindex
!= if_nametoindex("lo"), "check_meta_ifindex",
24 "meta->ifindex = %d\n", meta
->ifindex
))
27 if (CHECK(meta
->pkt_len
!= sizeof(pkt_v4
), "check_meta_pkt_len",
28 "meta->pkt_len = %zd\n", sizeof(pkt_v4
)))
31 if (CHECK(memcmp(trace_pkt_v4
, &pkt_v4
, sizeof(pkt_v4
)),
32 "check_packet_content", "content not the same\n"))
38 void test_xdp_bpf2bpf(void)
40 __u32 duration
= 0, retval
, size
;
42 int err
, pkt_fd
, map_fd
;
44 struct iphdr
*iph
= (void *)buf
+ sizeof(struct ethhdr
);
45 struct iptnl_info value4
= {.family
= AF_INET
};
46 struct test_xdp
*pkt_skel
= NULL
;
47 struct test_xdp_bpf2bpf
*ftrace_skel
= NULL
;
48 struct vip key4
= {.protocol
= 6, .family
= AF_INET
};
49 struct bpf_program
*prog
;
50 struct perf_buffer
*pb
= NULL
;
51 struct perf_buffer_opts pb_opts
= {};
53 /* Load XDP program to introspect */
54 pkt_skel
= test_xdp__open_and_load();
55 if (CHECK(!pkt_skel
, "pkt_skel_load", "test_xdp skeleton failed\n"))
58 pkt_fd
= bpf_program__fd(pkt_skel
->progs
._xdp_tx_iptunnel
);
60 map_fd
= bpf_map__fd(pkt_skel
->maps
.vip2tnl
);
61 bpf_map_update_elem(map_fd
, &key4
, &value4
, 0);
63 /* Load trace program */
64 ftrace_skel
= test_xdp_bpf2bpf__open();
65 if (CHECK(!ftrace_skel
, "__open", "ftrace skeleton failed\n"))
68 /* Demonstrate the bpf_program__set_attach_target() API rather than
69 * the load with options, i.e. opts.attach_prog_fd.
71 prog
= ftrace_skel
->progs
.trace_on_entry
;
72 bpf_program__set_expected_attach_type(prog
, BPF_TRACE_FENTRY
);
73 bpf_program__set_attach_target(prog
, pkt_fd
, "_xdp_tx_iptunnel");
75 prog
= ftrace_skel
->progs
.trace_on_exit
;
76 bpf_program__set_expected_attach_type(prog
, BPF_TRACE_FEXIT
);
77 bpf_program__set_attach_target(prog
, pkt_fd
, "_xdp_tx_iptunnel");
79 err
= test_xdp_bpf2bpf__load(ftrace_skel
);
80 if (CHECK(err
, "__load", "ftrace skeleton failed\n"))
83 err
= test_xdp_bpf2bpf__attach(ftrace_skel
);
84 if (CHECK(err
, "ftrace_attach", "ftrace attach failed: %d\n", err
))
87 /* Set up perf buffer */
88 pb_opts
.sample_cb
= on_sample
;
89 pb_opts
.ctx
= &passed
;
90 pb
= perf_buffer__new(bpf_map__fd(ftrace_skel
->maps
.perf_buf_map
),
92 if (CHECK(IS_ERR(pb
), "perf_buf__new", "err %ld\n", PTR_ERR(pb
)))
95 /* Run test program */
96 err
= bpf_prog_test_run(pkt_fd
, 1, &pkt_v4
, sizeof(pkt_v4
),
97 buf
, &size
, &retval
, &duration
);
99 if (CHECK(err
|| retval
!= XDP_TX
|| size
!= 74 ||
100 iph
->protocol
!= IPPROTO_IPIP
, "ipv4",
101 "err %d errno %d retval %d size %d\n",
102 err
, errno
, retval
, size
))
105 /* Make sure bpf_xdp_output() was triggered and it sent the expected
106 * data to the perf ring buffer.
108 err
= perf_buffer__poll(pb
, 100);
109 if (CHECK(err
< 0, "perf_buffer__poll", "err %d\n", err
))
114 /* Verify test results */
115 if (CHECK(ftrace_skel
->bss
->test_result_fentry
!= if_nametoindex("lo"),
116 "result", "fentry failed err %llu\n",
117 ftrace_skel
->bss
->test_result_fentry
))
120 CHECK(ftrace_skel
->bss
->test_result_fexit
!= XDP_TX
, "result",
121 "fexit failed err %llu\n", ftrace_skel
->bss
->test_result_fexit
);
125 perf_buffer__free(pb
);
126 test_xdp__destroy(pkt_skel
);
127 test_xdp_bpf2bpf__destroy(ftrace_skel
);