Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : : /*
3 : : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : : */
5 : :
6 : : #include <linux/bpf.h>
7 : : #include <linux/bpf_common.h>
8 : :
9 : : #include <stddef.h>
10 : : #include <stdint.h>
11 : :
12 : : #include <bpfilter/flavor.h>
13 : : #include <bpfilter/helper.h>
14 : : #include <bpfilter/verdict.h>
15 : :
16 : : #include "cgen/program.h"
17 : : #include "cgen/stub.h"
18 : : #include "filter.h"
19 : :
20 : : /**
21 : : * Generate XDP program prologue.
22 : : *
23 : : * @warning @ref bf_stub_parse_l2_ethhdr will check for L3 protocol. If L3 is
24 : : * not IPv4, the program will be terminated.
25 : : *
26 : : * @param program Program to generate the prologue for. Must not be NULL.
27 : : * @return 0 on success, or negative errno value on error.
28 : : */
29 : 34 : static int _bf_xdp_gen_inline_prologue(struct bf_program *program)
30 : : {
31 : : int r;
32 : :
33 : : assert(program);
34 : :
35 : : // Calculate the packet size and store it into the runtime context
36 [ - + ]: 34 : EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
37 : : offsetof(struct xdp_md, data)));
38 [ - + ]: 34 : EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
39 : : offsetof(struct xdp_md, data_end)));
40 [ - + ]: 34 : EMIT(program, BPF_ALU64_REG(BPF_SUB, BPF_REG_3, BPF_REG_2));
41 [ - + ]: 34 : EMIT(program,
42 : : BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_3, BF_PROG_CTX_OFF(pkt_size)));
43 : :
44 : : // Store the ingress ifindex into the runtime context
45 [ - + ]: 34 : EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
46 : : offsetof(struct xdp_md, ingress_ifindex)));
47 [ - + ]: 34 : EMIT(program,
48 : : BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, BF_PROG_CTX_OFF(ifindex)));
49 : :
50 : 34 : r = bf_stub_make_ctx_xdp_dynptr(program, BPF_REG_1);
51 [ + - ]: 34 : if (r)
52 : : return r;
53 : :
54 : 34 : r = bf_stub_parse_l2_ethhdr(program);
55 [ + - ]: 34 : if (r)
56 : : return r;
57 : :
58 : 34 : r = bf_stub_parse_l3_hdr(program);
59 [ + - ]: 34 : if (r)
60 : : return r;
61 : :
62 : 34 : r = bf_stub_parse_l4_hdr(program);
63 : : if (r)
64 : : return r;
65 : :
66 : : return 0;
67 : : }
68 : :
69 : 34 : static int _bf_xdp_gen_inline_epilogue(struct bf_program *program)
70 : : {
71 : : (void)program;
72 : :
73 : 34 : return 0;
74 : : }
75 : :
76 : 207 : static int _bf_xdp_get_verdict(enum bf_verdict verdict)
77 : : {
78 [ + - + ]: 207 : switch (verdict) {
79 : : case BF_VERDICT_ACCEPT:
80 : : return XDP_PASS;
81 : 18 : case BF_VERDICT_DROP:
82 : 18 : return XDP_DROP;
83 : 0 : default:
84 : 0 : return -ENOTSUP;
85 : : }
86 : : }
87 : :
88 : : const struct bf_flavor_ops bf_flavor_ops_xdp = {
89 : : .gen_inline_prologue = _bf_xdp_gen_inline_prologue,
90 : : .gen_inline_epilogue = _bf_xdp_gen_inline_epilogue,
91 : : .get_verdict = _bf_xdp_get_verdict,
92 : : };
|