bpf,fou: Add bpf_skb_{set,get}_fou_encap kfuncs
Add two new kfuncs that allow a BPF tc-hook, installed on an ipip device in collect-metadata mode, to control FOU encap parameters on a per-packet level. The set of kfuncs is registered with the fou module. The bpf_skb_set_fou_encap kfunc is supposed to be used in tandem and after a successful call to the bpf_skb_set_tunnel_key bpf-helper. UDP source and destination ports can be controlled by passing a struct bpf_fou_encap. A source port of zero will auto-assign a source port. enum bpf_fou_encap_type is used to specify if the egress path should FOU or GUE encap the packet. On the ingress path bpf_skb_get_fou_encap can be used to read UDP source and destination ports from the receiver's point of view and allows for packet multiplexing across different destination ports within a single BPF program and ipip device. Signed-off-by: Christian Ehrig <cehrig@cloudflare.com> Link: https://lore.kernel.org/r/e17c94a646b63e78ce0dbf3f04b2c33dc948a32d.1680874078.git.cehrig@cloudflare.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
ac931d4cde
commit
c50e96099e
|
@ -17,4 +17,6 @@ int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
|
|||
int __gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
|
||||
u8 *protocol, __be16 *sport, int type);
|
||||
|
||||
int register_fou_bpf(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,7 @@ obj-$(CONFIG_IP_MROUTE) += ipmr.o
|
|||
obj-$(CONFIG_IP_MROUTE_COMMON) += ipmr_base.o
|
||||
obj-$(CONFIG_NET_IPIP) += ipip.o
|
||||
gre-y := gre_demux.o
|
||||
fou-y := fou_core.o fou_nl.o
|
||||
fou-y := fou_core.o fou_nl.o fou_bpf.o
|
||||
obj-$(CONFIG_NET_FOU) += fou.o
|
||||
obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
|
||||
obj-$(CONFIG_NET_IPGRE) += ip_gre.o
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Unstable Fou Helpers for TC-BPF hook
|
||||
*
|
||||
* These are called from SCHED_CLS BPF programs. 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_ids.h>
|
||||
|
||||
#include <net/dst_metadata.h>
|
||||
#include <net/fou.h>
|
||||
|
||||
struct bpf_fou_encap {
|
||||
__be16 sport;
|
||||
__be16 dport;
|
||||
};
|
||||
|
||||
enum bpf_fou_encap_type {
|
||||
FOU_BPF_ENCAP_FOU,
|
||||
FOU_BPF_ENCAP_GUE,
|
||||
};
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in BTF");
|
||||
|
||||
/* bpf_skb_set_fou_encap - Set FOU encap parameters
|
||||
*
|
||||
* This function allows for using GUE or FOU encapsulation together with an
|
||||
* ipip device in collect-metadata mode.
|
||||
*
|
||||
* It is meant to be used in BPF tc-hooks and after a call to the
|
||||
* bpf_skb_set_tunnel_key helper, responsible for setting IP addresses.
|
||||
*
|
||||
* Parameters:
|
||||
* @skb_ctx Pointer to ctx (__sk_buff) in TC program. Cannot be NULL
|
||||
* @encap Pointer to a `struct bpf_fou_encap` storing UDP src and
|
||||
* dst ports. If sport is set to 0 the kernel will auto-assign a
|
||||
* port. This is similar to using `encap-sport auto`.
|
||||
* Cannot be NULL
|
||||
* @type Encapsulation type for the packet. Their definitions are
|
||||
* specified in `enum bpf_fou_encap_type`
|
||||
*/
|
||||
__bpf_kfunc int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx,
|
||||
struct bpf_fou_encap *encap, int type)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *)skb_ctx;
|
||||
struct ip_tunnel_info *info = skb_tunnel_info(skb);
|
||||
|
||||
if (unlikely(!encap))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX)))
|
||||
return -EINVAL;
|
||||
|
||||
switch (type) {
|
||||
case FOU_BPF_ENCAP_FOU:
|
||||
info->encap.type = TUNNEL_ENCAP_FOU;
|
||||
break;
|
||||
case FOU_BPF_ENCAP_GUE:
|
||||
info->encap.type = TUNNEL_ENCAP_GUE;
|
||||
break;
|
||||
default:
|
||||
info->encap.type = TUNNEL_ENCAP_NONE;
|
||||
}
|
||||
|
||||
if (info->key.tun_flags & TUNNEL_CSUM)
|
||||
info->encap.flags |= TUNNEL_ENCAP_FLAG_CSUM;
|
||||
|
||||
info->encap.sport = encap->sport;
|
||||
info->encap.dport = encap->dport;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bpf_skb_get_fou_encap - Get FOU encap parameters
|
||||
*
|
||||
* This function allows for reading encap metadata from a packet received
|
||||
* on an ipip device in collect-metadata mode.
|
||||
*
|
||||
* Parameters:
|
||||
* @skb_ctx Pointer to ctx (__sk_buff) in TC program. Cannot be NULL
|
||||
* @encap Pointer to a struct bpf_fou_encap storing UDP source and
|
||||
* destination port. Cannot be NULL
|
||||
*/
|
||||
__bpf_kfunc int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx,
|
||||
struct bpf_fou_encap *encap)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *)skb_ctx;
|
||||
struct ip_tunnel_info *info = skb_tunnel_info(skb);
|
||||
|
||||
if (unlikely(!info))
|
||||
return -EINVAL;
|
||||
|
||||
encap->sport = info->encap.sport;
|
||||
encap->dport = info->encap.dport;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__diag_pop()
|
||||
|
||||
BTF_SET8_START(fou_kfunc_set)
|
||||
BTF_ID_FLAGS(func, bpf_skb_set_fou_encap)
|
||||
BTF_ID_FLAGS(func, bpf_skb_get_fou_encap)
|
||||
BTF_SET8_END(fou_kfunc_set)
|
||||
|
||||
static const struct btf_kfunc_id_set fou_bpf_kfunc_set = {
|
||||
.owner = THIS_MODULE,
|
||||
.set = &fou_kfunc_set,
|
||||
};
|
||||
|
||||
int register_fou_bpf(void)
|
||||
{
|
||||
return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
|
||||
&fou_bpf_kfunc_set);
|
||||
}
|
|
@ -1236,10 +1236,15 @@ static int __init fou_init(void)
|
|||
if (ret < 0)
|
||||
goto unregister;
|
||||
|
||||
ret = register_fou_bpf();
|
||||
if (ret < 0)
|
||||
goto kfunc_failed;
|
||||
|
||||
ret = ip_tunnel_encap_add_fou_ops();
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
kfunc_failed:
|
||||
genl_unregister_family(&fou_nl_family);
|
||||
unregister:
|
||||
unregister_pernet_device(&fou_net_ops);
|
||||
|
|
Loading…
Reference in New Issue