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

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/progs/xdp_features.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/progs/xdp_features.c
Extension
.c
Size
5651 bytes
Lines
269
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct xdp_cpumap_stats {
	unsigned int redirect;
	unsigned int pass;
	unsigned int drop;
};

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__type(key, __u32);
	__type(value, __u32);
	__uint(max_entries, 1);
} stats SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__type(key, __u32);
	__type(value, __u32);
	__uint(max_entries, 1);
} dut_stats SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_CPUMAP);
	__uint(key_size, sizeof(__u32));
	__uint(value_size, sizeof(struct bpf_cpumap_val));
	__uint(max_entries, 1);
} cpu_map SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_DEVMAP);
	__uint(key_size, sizeof(__u32));
	__uint(value_size, sizeof(struct bpf_devmap_val));
	__uint(max_entries, 1);
} dev_map SEC(".maps");

const volatile struct in6_addr tester_addr;
const volatile struct in6_addr dut_addr;

static __always_inline int
xdp_process_echo_packet(struct xdp_md *xdp, bool dut)
{
	void *data_end = (void *)(long)xdp->data_end;
	void *data = (void *)(long)xdp->data;
	struct ethhdr *eh = data;
	struct tlv_hdr *tlv;
	struct udphdr *uh;
	__be16 port;

	if (eh + 1 > (struct ethhdr *)data_end)
		return -EINVAL;

	if (eh->h_proto == bpf_htons(ETH_P_IP)) {
		struct iphdr *ih = (struct iphdr *)(eh + 1);
		__be32 saddr = dut ? tester_addr.s6_addr32[3]
				   : dut_addr.s6_addr32[3];
		__be32 daddr = dut ? dut_addr.s6_addr32[3]
				   : tester_addr.s6_addr32[3];

		ih = (struct iphdr *)(eh + 1);
		if (ih + 1 > (struct iphdr *)data_end)
			return -EINVAL;

		if (saddr != ih->saddr)
			return -EINVAL;

		if (daddr != ih->daddr)
			return -EINVAL;

		if (ih->protocol != IPPROTO_UDP)
			return -EINVAL;

		uh = (struct udphdr *)(ih + 1);
	} else if (eh->h_proto == bpf_htons(ETH_P_IPV6)) {
		struct in6_addr saddr = dut ? tester_addr : dut_addr;
		struct in6_addr daddr = dut ? dut_addr : tester_addr;
		struct ipv6hdr *ih6 = (struct ipv6hdr *)(eh + 1);

		if (ih6 + 1 > (struct ipv6hdr *)data_end)
			return -EINVAL;

		if (!ipv6_addr_equal(saddr, ih6->saddr))
			return -EINVAL;

		if (!ipv6_addr_equal(daddr, ih6->daddr))
			return -EINVAL;

		if (ih6->nexthdr != IPPROTO_UDP)
			return -EINVAL;

		uh = (struct udphdr *)(ih6 + 1);
	} else {

Annotation

Implementation Notes