xref: /linux/tools/testing/selftests/bpf/progs/test_xdp_meta.c (revision 8dd06ef34b6e2f41b29fbf5fc1663780f2524285)
1bd4aed0eSJiong Wang #include <linux/bpf.h>
2bd4aed0eSJiong Wang #include <linux/if_ether.h>
3bd4aed0eSJiong Wang #include <linux/pkt_cls.h>
4bd4aed0eSJiong Wang 
5*3e689141SToke Høiland-Jørgensen #include <bpf/bpf_helpers.h>
6bd4aed0eSJiong Wang 
7bd4aed0eSJiong Wang #define __round_mask(x, y) ((__typeof__(x))((y) - 1))
8bd4aed0eSJiong Wang #define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
9bd4aed0eSJiong Wang #define ctx_ptr(ctx, mem) (void *)(unsigned long)ctx->mem
10bd4aed0eSJiong Wang 
11bd4aed0eSJiong Wang SEC("t")
ing_cls(struct __sk_buff * ctx)12bd4aed0eSJiong Wang int ing_cls(struct __sk_buff *ctx)
13bd4aed0eSJiong Wang {
14bd4aed0eSJiong Wang 	__u8 *data, *data_meta, *data_end;
15bd4aed0eSJiong Wang 	__u32 diff = 0;
16bd4aed0eSJiong Wang 
17bd4aed0eSJiong Wang 	data_meta = ctx_ptr(ctx, data_meta);
18bd4aed0eSJiong Wang 	data_end  = ctx_ptr(ctx, data_end);
19bd4aed0eSJiong Wang 	data      = ctx_ptr(ctx, data);
20bd4aed0eSJiong Wang 
21bd4aed0eSJiong Wang 	if (data + ETH_ALEN > data_end ||
22bd4aed0eSJiong Wang 	    data_meta + round_up(ETH_ALEN, 4) > data)
23bd4aed0eSJiong Wang 		return TC_ACT_SHOT;
24bd4aed0eSJiong Wang 
25bd4aed0eSJiong Wang 	diff |= ((__u32 *)data_meta)[0] ^ ((__u32 *)data)[0];
26bd4aed0eSJiong Wang 	diff |= ((__u16 *)data_meta)[2] ^ ((__u16 *)data)[2];
27bd4aed0eSJiong Wang 
28bd4aed0eSJiong Wang 	return diff ? TC_ACT_SHOT : TC_ACT_OK;
29bd4aed0eSJiong Wang }
30bd4aed0eSJiong Wang 
31bd4aed0eSJiong Wang SEC("x")
ing_xdp(struct xdp_md * ctx)32bd4aed0eSJiong Wang int ing_xdp(struct xdp_md *ctx)
33bd4aed0eSJiong Wang {
34bd4aed0eSJiong Wang 	__u8 *data, *data_meta, *data_end;
35bd4aed0eSJiong Wang 	int ret;
36bd4aed0eSJiong Wang 
37bd4aed0eSJiong Wang 	ret = bpf_xdp_adjust_meta(ctx, -round_up(ETH_ALEN, 4));
38bd4aed0eSJiong Wang 	if (ret < 0)
39bd4aed0eSJiong Wang 		return XDP_DROP;
40bd4aed0eSJiong Wang 
41bd4aed0eSJiong Wang 	data_meta = ctx_ptr(ctx, data_meta);
42bd4aed0eSJiong Wang 	data_end  = ctx_ptr(ctx, data_end);
43bd4aed0eSJiong Wang 	data      = ctx_ptr(ctx, data);
44bd4aed0eSJiong Wang 
45bd4aed0eSJiong Wang 	if (data + ETH_ALEN > data_end ||
46bd4aed0eSJiong Wang 	    data_meta + round_up(ETH_ALEN, 4) > data)
47bd4aed0eSJiong Wang 		return XDP_DROP;
48bd4aed0eSJiong Wang 
49bd4aed0eSJiong Wang 	__builtin_memcpy(data_meta, data, ETH_ALEN);
50bd4aed0eSJiong Wang 	return XDP_PASS;
51bd4aed0eSJiong Wang }
52bd4aed0eSJiong Wang 
53bd4aed0eSJiong Wang char _license[] SEC("license") = "GPL";
54