Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | // SPDX-License-Identifier: GPL-2.0-only /* Unstable XFRM state BPF helpers. * * Note that it is allowed to break compatibility for these functions since the * interface they are exposed through to BPF programs is explicitly unstable. */ #include <linux/bpf.h> #include <linux/btf.h> #include <linux/btf_ids.h> #include <net/xdp.h> #include <net/xfrm.h> /* bpf_xfrm_state_opts - Options for XFRM state lookup helpers * * Members: * @error - Out parameter, set for any errors encountered * Values: * -EINVAL - netns_id is less than -1 * -EINVAL - opts__sz isn't BPF_XFRM_STATE_OPTS_SZ * -ENONET - No network namespace found for netns_id * -ENOENT - No xfrm_state found * @netns_id - Specify the network namespace for lookup * Values: * BPF_F_CURRENT_NETNS (-1) * Use namespace associated with ctx * [0, S32_MAX] * Network Namespace ID * @mark - XFRM mark to match on * @daddr - Destination address to match on * @spi - Security parameter index to match on * @proto - IP protocol to match on (eg. IPPROTO_ESP) * @family - Protocol family to match on (AF_INET/AF_INET6) */ struct bpf_xfrm_state_opts { s32 error; s32 netns_id; u32 mark; xfrm_address_t daddr; __be32 spi; u8 proto; u16 family; }; enum { BPF_XFRM_STATE_OPTS_SZ = sizeof(struct bpf_xfrm_state_opts), }; __bpf_kfunc_start_defs(); /* bpf_xdp_get_xfrm_state - Get XFRM state * * A `struct xfrm_state *`, if found, must be released with a corresponding * bpf_xdp_xfrm_state_release. * * Parameters: * @ctx - Pointer to ctx (xdp_md) in XDP program * Cannot be NULL * @opts - Options for lookup (documented above) * Cannot be NULL * @opts__sz - Length of the bpf_xfrm_state_opts structure * Must be BPF_XFRM_STATE_OPTS_SZ */ __bpf_kfunc struct xfrm_state * bpf_xdp_get_xfrm_state(struct xdp_md *ctx, struct bpf_xfrm_state_opts *opts, u32 opts__sz) { struct xdp_buff *xdp = (struct xdp_buff *)ctx; struct net *net = dev_net(xdp->rxq->dev); struct xfrm_state *x; if (!opts || opts__sz < sizeof(opts->error)) return NULL; if (opts__sz != BPF_XFRM_STATE_OPTS_SZ) { opts->error = -EINVAL; return NULL; } if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) { opts->error = -EINVAL; return NULL; } if (opts->netns_id >= 0) { net = get_net_ns_by_id(net, opts->netns_id); if (unlikely(!net)) { opts->error = -ENONET; return NULL; } } x = xfrm_state_lookup(net, opts->mark, &opts->daddr, opts->spi, opts->proto, opts->family); if (opts->netns_id >= 0) put_net(net); if (!x) opts->error = -ENOENT; return x; } /* bpf_xdp_xfrm_state_release - Release acquired xfrm_state object * * This must be invoked for referenced PTR_TO_BTF_ID, and the verifier rejects * the program if any references remain in the program in all of the explored * states. * * Parameters: * @x - Pointer to referenced xfrm_state object, obtained using * bpf_xdp_get_xfrm_state. */ __bpf_kfunc void bpf_xdp_xfrm_state_release(struct xfrm_state *x) { xfrm_state_put(x); } __bpf_kfunc_end_defs(); BTF_KFUNCS_START(xfrm_state_kfunc_set) BTF_ID_FLAGS(func, bpf_xdp_get_xfrm_state, KF_RET_NULL | KF_ACQUIRE) BTF_ID_FLAGS(func, bpf_xdp_xfrm_state_release, KF_RELEASE) BTF_KFUNCS_END(xfrm_state_kfunc_set) static const struct btf_kfunc_id_set xfrm_state_xdp_kfunc_set = { .owner = THIS_MODULE, .set = &xfrm_state_kfunc_set, }; int __init register_xfrm_state_bpf(void) { return register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &xfrm_state_xdp_kfunc_set); } |