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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/progs/bpf_flow.c
Extension
.c
Size
11496 bytes
Lines
438
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 vlan_hdr {
	__be16 h_vlan_TCI;
	__be16 h_vlan_encapsulated_proto;
};

struct gre_hdr {
	__be16 flags;
	__be16 proto;
};

struct frag_hdr {
	__u8 nexthdr;
	__u8 reserved;
	__be16 frag_off;
	__be32 identification;
};

struct {
	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
	__uint(max_entries, MAX_PROG);
	__uint(key_size, sizeof(__u32));
	__uint(value_size, sizeof(__u32));
} jmp_table SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_HASH);
	__uint(max_entries, 1024);
	__type(key, __u32);
	__type(value, struct bpf_flow_keys);
} last_dissection SEC(".maps");

static __always_inline int export_flow_keys(struct bpf_flow_keys *keys,
					    int ret)
{
	__u32 key = (__u32)(keys->sport) << 16 | keys->dport;
	struct bpf_flow_keys val;

	memcpy(&val, keys, sizeof(val));
	bpf_map_update_elem(&last_dissection, &key, &val, BPF_ANY);
	return ret;
}

#define IPV6_FLOWLABEL_MASK		__bpf_constant_htonl(0x000FFFFF)
static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
{
	return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
}

static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb,
							 __u16 hdr_size,
							 void *buffer)
{
	void *data_end = (void *)(long)skb->data_end;
	void *data = (void *)(long)skb->data;
	__u16 thoff = skb->flow_keys->thoff;
	__u8 *hdr;

	/* Verifies this variable offset does not overflow */
	if (thoff > (USHRT_MAX - hdr_size))
		return NULL;

	hdr = data + thoff;
	if (hdr + hdr_size <= data_end)
		return hdr;

	if (bpf_skb_load_bytes(skb, thoff, buffer, hdr_size))
		return NULL;

	return buffer;
}

/* Dispatches on ETHERTYPE */
static __always_inline int parse_eth_proto(struct __sk_buff *skb, __be16 proto)
{
	struct bpf_flow_keys *keys = skb->flow_keys;

	switch (proto) {
	case bpf_htons(ETH_P_IP):
		bpf_tail_call_static(skb, &jmp_table, IP);
		break;
	case bpf_htons(ETH_P_IPV6):
		bpf_tail_call_static(skb, &jmp_table, IPV6);
		break;
	case bpf_htons(ETH_P_MPLS_MC):
	case bpf_htons(ETH_P_MPLS_UC):
		bpf_tail_call_static(skb, &jmp_table, MPLS);
		break;
	case bpf_htons(ETH_P_8021Q):
	case bpf_htons(ETH_P_8021AD):
		bpf_tail_call_static(skb, &jmp_table, VLAN);

Annotation

Implementation Notes