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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/progs/test_assign_reuse.c
Extension
.c
Size
3255 bytes
Lines
143
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

// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Isovalent */
#include <stdbool.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <linux/pkt_cls.h>

char LICENSE[] SEC("license") = "GPL";

__u64 sk_cookie_seen;
__u64 reuseport_executed;
union {
	struct tcphdr tcp;
	struct udphdr udp;
} headers;

const volatile __u16 dest_port;

struct {
	__uint(type, BPF_MAP_TYPE_SOCKMAP);
	__uint(max_entries, 1);
	__type(key, __u32);
	__type(value, __u64);
} sk_map SEC(".maps");

SEC("sk_reuseport")
int reuse_accept(struct sk_reuseport_md *ctx)
{
	reuseport_executed++;

	if (ctx->ip_protocol == IPPROTO_TCP) {
		if (ctx->data + sizeof(headers.tcp) > ctx->data_end)
			return SK_DROP;

		if (__builtin_memcmp(&headers.tcp, ctx->data, sizeof(headers.tcp)) != 0)
			return SK_DROP;
	} else if (ctx->ip_protocol == IPPROTO_UDP) {
		if (ctx->data + sizeof(headers.udp) > ctx->data_end)
			return SK_DROP;

		if (__builtin_memcmp(&headers.udp, ctx->data, sizeof(headers.udp)) != 0)
			return SK_DROP;
	} else {
		return SK_DROP;
	}

	sk_cookie_seen = bpf_get_socket_cookie(ctx->sk);
	return SK_PASS;
}

SEC("sk_reuseport")
int reuse_drop(struct sk_reuseport_md *ctx)
{
	reuseport_executed++;
	sk_cookie_seen = 0;
	return SK_DROP;
}

static int
assign_sk(struct __sk_buff *skb)
{
	int zero = 0, ret = 0;
	struct bpf_sock *sk;

	sk = bpf_map_lookup_elem(&sk_map, &zero);
	if (!sk)
		return TC_ACT_SHOT;
	ret = bpf_sk_assign(skb, sk, 0);
	bpf_sk_release(sk);
	return ret ? TC_ACT_SHOT : TC_ACT_OK;
}

static bool
maybe_assign_tcp(struct __sk_buff *skb, struct tcphdr *th)
{
	if (th + 1 > (void *)(long)(skb->data_end))
		return TC_ACT_SHOT;

	if (!th->syn || th->ack || th->dest != bpf_htons(dest_port))
		return TC_ACT_OK;

	__builtin_memcpy(&headers.tcp, th, sizeof(headers.tcp));
	return assign_sk(skb);

Annotation

Implementation Notes