mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-25 12:04:46 +08:00
c50e96099e
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>
120 lines
3.1 KiB
C
120 lines
3.1 KiB
C
// 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);
|
|
}
|