tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
Extension
.c
Size
21082 bytes
Lines
823
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 test_case {
	char *name;
	enum bpf_prog_type prog_type;
	enum bpf_attach_type expected_attach_type;
	int field_offset;
	int field_sz;
	/* Program generated for BPF_ST_MEM uses value 42 by default,
	 * this field allows to specify custom value.
	 */
	struct {
		bool use;
		int value;
	} st_value;
	/* Pattern for BPF_LDX_MEM(field_sz, dst, ctx, field_offset) */
	char *read;
	/* Pattern for BPF_STX_MEM(field_sz, ctx, src, field_offset) and
	 *             BPF_ST_MEM (field_sz, ctx, src, field_offset)
	 */
	char *write;
	/* Pattern for BPF_ST_MEM(field_sz, ctx, src, field_offset),
	 * takes priority over `write`.
	 */
	char *write_st;
	/* Pattern for BPF_STX_MEM (field_sz, ctx, src, field_offset),
	 * takes priority over `write`.
	 */
	char *write_stx;
};

#define N(_prog_type, type, field, name_extra...)	\
	.name = #_prog_type "." #field name_extra,	\
	.prog_type = BPF_PROG_TYPE_##_prog_type,	\
	.field_offset = offsetof(type, field),		\
	.field_sz = sizeof(typeof(((type *)NULL)->field))

static struct test_case test_cases[] = {
/* Sign extension on s390 changes the pattern */
#if defined(__x86_64__) || defined(__aarch64__)
	{
		N(SCHED_CLS, struct __sk_buff, tstamp),
		.read  = "r12 = *(u8 *)($ctx + sk_buff::__mono_tc_offset);"
			 "if w12 & 0x4 goto pc+1;"
			 "goto pc+4;"
			 "if w12 & 0x3 goto pc+1;"
			 "goto pc+2;"
			 "$dst = 0;"
			 "goto pc+1;"
			 "$dst = *(u64 *)($ctx + sk_buff::tstamp);",
		.write = "r12 = *(u8 *)($ctx + sk_buff::__mono_tc_offset);"
			 "if w12 & 0x4 goto pc+1;"
			 "goto pc+2;"
			 "w12 &= -4;"
			 "*(u8 *)($ctx + sk_buff::__mono_tc_offset) = r12;"
			 "*(u64 *)($ctx + sk_buff::tstamp) = $src;",
	},
#endif
	{
		N(SCHED_CLS, struct __sk_buff, priority),
		.read  = "$dst = *(u32 *)($ctx + sk_buff::priority);",
		.write = "*(u32 *)($ctx + sk_buff::priority) = $src;",
	},
	{
		N(SCHED_CLS, struct __sk_buff, mark),
		.read  = "$dst = *(u32 *)($ctx + sk_buff::mark);",
		.write = "*(u32 *)($ctx + sk_buff::mark) = $src;",
	},
	{
		N(SCHED_CLS, struct __sk_buff, cb[0]),
		.read  = "$dst = *(u32 *)($ctx + $(sk_buff::cb + qdisc_skb_cb::data));",
		.write = "*(u32 *)($ctx + $(sk_buff::cb + qdisc_skb_cb::data)) = $src;",
	},
	{
		N(SCHED_CLS, struct __sk_buff, tc_classid),
		.read  = "$dst = *(u16 *)($ctx + $(sk_buff::cb + qdisc_skb_cb::tc_classid));",
		.write = "*(u16 *)($ctx + $(sk_buff::cb + qdisc_skb_cb::tc_classid)) = $src;",
	},
	{
		N(SCHED_CLS, struct __sk_buff, tc_index),
		.read  = "$dst = *(u16 *)($ctx + sk_buff::tc_index);",
		.write = "*(u16 *)($ctx + sk_buff::tc_index) = $src;",
	},
	{
		N(SCHED_CLS, struct __sk_buff, queue_mapping),
		.read      = "$dst = *(u16 *)($ctx + sk_buff::queue_mapping);",
		.write_stx = "if $src >= 0xffff goto pc+1;"
			     "*(u16 *)($ctx + sk_buff::queue_mapping) = $src;",
		.write_st  = "*(u16 *)($ctx + sk_buff::queue_mapping) = $src;",
	},
	{
		/* This is a corner case in filter.c:bpf_convert_ctx_access() */

Annotation

Implementation Notes