-
Notifications
You must be signed in to change notification settings - Fork 52.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bpf: xfrm: Add bpf_xdp_get_xfrm_state() kfunc
This commit adds an unstable kfunc helper to access internal xfrm_state associated with an SA. This is intended to be used for the upcoming IPsec pcpu work to assign special pcpu SAs to a particular CPU. In other words: for custom software RSS. That being said, the function that this kfunc wraps is fairly generic and used for a lot of xfrm tasks. I'm sure people will find uses elsewhere over time. This commit also adds a corresponding bpf_xdp_xfrm_state_release() kfunc to release the refcnt acquired by bpf_xdp_get_xfrm_state(). The verifier will require that all acquired xfrm_state's are released. Co-developed-by: Antony Antony <antony.antony@secunet.com> Signed-off-by: Antony Antony <antony.antony@secunet.com> Acked-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Daniel Xu <dxu@dxuuu.xyz> Link: https://lore.kernel.org/r/a29699c42f5fad456b875c98dd11c6afc3ffb707.1702593901.git.dxu@dxuuu.xyz Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Showing
4 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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_SET8_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_SET8_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); | ||
} |