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 : 32 : static int _bf_xdp_gen_inline_prologue(struct bf_program *program)
30 : : {
31 : : int r;
32 : :
33 : : bf_assert(program);
34 : :
35 : : // Calculate the packet size and store it into the runtime context
36 [ - + ]: 32 : EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
37 : : offsetof(struct xdp_md, data)));
38 [ - + ]: 32 : EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
39 : : offsetof(struct xdp_md, data_end)));
40 [ - + ]: 32 : EMIT(program, BPF_ALU64_REG(BPF_SUB, BPF_REG_3, BPF_REG_2));
41 [ - + ]: 32 : 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 [ - + ]: 32 : EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
46 : : offsetof(struct xdp_md, ingress_ifindex)));
47 [ - + ]: 32 : EMIT(program,
48 : : BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, BF_PROG_CTX_OFF(ifindex)));
49 : :
50 : 32 : r = bf_stub_make_ctx_xdp_dynptr(program, BPF_REG_1);
51 [ + - ]: 32 : if (r)
52 : : return r;
53 : :
54 : 32 : r = bf_stub_parse_l2_ethhdr(program);
55 [ + - ]: 32 : if (r)
56 : : return r;
57 : :
58 : 32 : r = bf_stub_parse_l3_hdr(program);
59 [ + - ]: 32 : if (r)
60 : : return r;
61 : :
62 : 32 : r = bf_stub_parse_l4_hdr(program);
63 : : if (r)
64 : : return r;
65 : :
66 : : return 0;
67 : : }
68 : :
69 : 32 : static int _bf_xdp_gen_inline_epilogue(struct bf_program *program)
70 : : {
71 : : UNUSED(program);
72 : :
73 : 32 : return 0;
74 : : }
75 : :
76 : 197 : static int _bf_xdp_get_verdict(enum bf_verdict verdict)
77 : : {
78 : : bf_assert(0 <= verdict && verdict < _BF_TERMINAL_VERDICT_MAX);
79 : :
80 : : static const int verdicts[] = {
81 : : [BF_VERDICT_ACCEPT] = XDP_PASS,
82 : : [BF_VERDICT_DROP] = XDP_DROP,
83 : : };
84 : :
85 : : static_assert(ARRAY_SIZE(verdicts) == _BF_TERMINAL_VERDICT_MAX);
86 : :
87 : 197 : return verdicts[verdict];
88 : : }
89 : :
90 : : const struct bf_flavor_ops bf_flavor_ops_xdp = {
91 : : .gen_inline_prologue = _bf_xdp_gen_inline_prologue,
92 : : .gen_inline_epilogue = _bf_xdp_gen_inline_epilogue,
93 : : .get_verdict = _bf_xdp_get_verdict,
94 : : };
|