mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
bpf: add helper for getting xfrm states
This commit introduces a helper which allows fetching xfrm state parameters by eBPF programs attached to TC. Prototype: bpf_skb_get_xfrm_state(skb, index, xfrm_state, size, flags) skb: pointer to skb index: the index in the skb xfrm_state secpath array xfrm_state: pointer to 'struct bpf_xfrm_state' size: size of 'struct bpf_xfrm_state' flags: reserved for future extensions The helper returns 0 on success. Non zero if no xfrm state at the index is found - or non exists at all. struct bpf_xfrm_state currently includes the SPI, peer IPv4/IPv6 address and the reqid; it can be further extended by adding elements to its end - indicating the populated fields by the 'size' argument - keeping backwards compatibility. Typical usage: struct bpf_xfrm_state x = {}; bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0); ... Signed-off-by: Eyal Birger <eyal.birger@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
fbcf93ebca
commit
12bed760a7
@ -774,6 +774,15 @@ union bpf_attr {
|
||||
* @xdp_md: pointer to xdp_md
|
||||
* @delta: A negative integer to be added to xdp_md.data_end
|
||||
* Return: 0 on success or negative on error
|
||||
*
|
||||
* int bpf_skb_get_xfrm_state(skb, index, xfrm_state, size, flags)
|
||||
* retrieve XFRM state
|
||||
* @skb: pointer to skb
|
||||
* @index: index of the xfrm state in the secpath
|
||||
* @key: pointer to 'struct bpf_xfrm_state'
|
||||
* @size: size of 'struct bpf_xfrm_state'
|
||||
* @flags: room for future extensions
|
||||
* Return: 0 on success or negative error
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
@ -841,7 +850,8 @@ union bpf_attr {
|
||||
FN(msg_cork_bytes), \
|
||||
FN(msg_pull_data), \
|
||||
FN(bind), \
|
||||
FN(xdp_adjust_tail),
|
||||
FN(xdp_adjust_tail), \
|
||||
FN(skb_get_xfrm_state),
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
@ -947,6 +957,19 @@ struct bpf_tunnel_key {
|
||||
__u32 tunnel_label;
|
||||
};
|
||||
|
||||
/* user accessible mirror of in-kernel xfrm_state.
|
||||
* new fields can only be added to the end of this structure
|
||||
*/
|
||||
struct bpf_xfrm_state {
|
||||
__u32 reqid;
|
||||
__u32 spi; /* Stored in network byte order */
|
||||
__u16 family;
|
||||
union {
|
||||
__u32 remote_ipv4; /* Stored in network byte order */
|
||||
__u32 remote_ipv6[4]; /* Stored in network byte order */
|
||||
};
|
||||
};
|
||||
|
||||
/* Generic BPF return codes which all BPF program types may support.
|
||||
* The values are binary compatible with their TC_ACT_* counter-part to
|
||||
* provide backwards compatibility with existing SCHED_CLS and SCHED_ACT
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <net/sock_reuseport.h>
|
||||
#include <net/busy_poll.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/xfrm.h>
|
||||
#include <linux/bpf_trace.h>
|
||||
|
||||
/**
|
||||
@ -3743,6 +3744,49 @@ static const struct bpf_func_proto bpf_bind_proto = {
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
BPF_CALL_5(bpf_skb_get_xfrm_state, struct sk_buff *, skb, u32, index,
|
||||
struct bpf_xfrm_state *, to, u32, size, u64, flags)
|
||||
{
|
||||
const struct sec_path *sp = skb_sec_path(skb);
|
||||
const struct xfrm_state *x;
|
||||
|
||||
if (!sp || unlikely(index >= sp->len || flags))
|
||||
goto err_clear;
|
||||
|
||||
x = sp->xvec[index];
|
||||
|
||||
if (unlikely(size != sizeof(struct bpf_xfrm_state)))
|
||||
goto err_clear;
|
||||
|
||||
to->reqid = x->props.reqid;
|
||||
to->spi = x->id.spi;
|
||||
to->family = x->props.family;
|
||||
if (to->family == AF_INET6) {
|
||||
memcpy(to->remote_ipv6, x->props.saddr.a6,
|
||||
sizeof(to->remote_ipv6));
|
||||
} else {
|
||||
to->remote_ipv4 = x->props.saddr.a4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_clear:
|
||||
memset(to, 0, size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_skb_get_xfrm_state_proto = {
|
||||
.func = bpf_skb_get_xfrm_state,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
bpf_base_func_proto(enum bpf_func_id func_id)
|
||||
{
|
||||
@ -3884,6 +3928,10 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
return &bpf_get_socket_cookie_proto;
|
||||
case BPF_FUNC_get_socket_uid:
|
||||
return &bpf_get_socket_uid_proto;
|
||||
#ifdef CONFIG_XFRM
|
||||
case BPF_FUNC_skb_get_xfrm_state:
|
||||
return &bpf_skb_get_xfrm_state_proto;
|
||||
#endif
|
||||
default:
|
||||
return bpf_base_func_proto(func_id);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user