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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/progs/xdp_flowtable.c
Extension
.c
Size
3490 bytes
Lines
152
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 bpf_flowtable_opts___local {
	s32 error;
};

struct flow_offload_tuple_rhash___local {
};

struct flow_offload_tuple_rhash___local *
bpf_xdp_flow_lookup(struct xdp_md *, struct bpf_fib_lookup *,
		    struct bpf_flowtable_opts___local *, u32) __ksym;

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

static bool xdp_flowtable_offload_check_iphdr(struct iphdr *iph)
{
	/* ip fragmented traffic */
	if (iph->frag_off & bpf_htons(IP_MF | IP_OFFSET))
		return false;

	/* ip options */
	if (iph->ihl * 4 != sizeof(*iph))
		return false;

	if (iph->ttl <= 1)
		return false;

	return true;
}

static bool xdp_flowtable_offload_check_tcp_state(void *ports, void *data_end,
						  u8 proto)
{
	if (proto == IPPROTO_TCP) {
		struct tcphdr *tcph = ports;

		if (tcph + 1 > data_end)
			return false;

		if (tcph->fin || tcph->rst)
			return false;
	}

	return true;
}

struct flow_ports___local {
	__be16 source, dest;
} __attribute__((preserve_access_index));

SEC("xdp.frags")
int xdp_flowtable_do_lookup(struct xdp_md *ctx)
{
	void *data_end = (void *)(long)ctx->data_end;
	struct bpf_flowtable_opts___local opts = {};
	struct flow_offload_tuple_rhash___local *tuplehash;
	struct bpf_fib_lookup tuple = {
		.ifindex = ctx->ingress_ifindex,
	};
	void *data = (void *)(long)ctx->data;
	struct ethhdr *eth = data;
	struct flow_ports___local *ports;
	__u32 *val, key = 0;

	if (eth + 1 > data_end)
		return XDP_DROP;

	switch (eth->h_proto) {
	case bpf_htons(ETH_P_IP): {
		struct iphdr *iph = data + sizeof(*eth);

		ports = (struct flow_ports___local *)(iph + 1);
		if (ports + 1 > data_end)
			return XDP_PASS;

		/* sanity check on ip header */
		if (!xdp_flowtable_offload_check_iphdr(iph))
			return XDP_PASS;

		if (!xdp_flowtable_offload_check_tcp_state(ports, data_end,
							   iph->protocol))
			return XDP_PASS;

		tuple.family		= AF_INET;
		tuple.tos		= iph->tos;
		tuple.l4_protocol	= iph->protocol;

Annotation

Implementation Notes