xref: /linux/net/ipv4/fou_bpf.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1c50e9609SChristian Ehrig // SPDX-License-Identifier: GPL-2.0-only
2c50e9609SChristian Ehrig /* Unstable Fou Helpers for TC-BPF hook
3c50e9609SChristian Ehrig  *
4c50e9609SChristian Ehrig  * These are called from SCHED_CLS BPF programs. Note that it is
5c50e9609SChristian Ehrig  * allowed to break compatibility for these functions since the interface they
6c50e9609SChristian Ehrig  * are exposed through to BPF programs is explicitly unstable.
7c50e9609SChristian Ehrig  */
8c50e9609SChristian Ehrig 
9c50e9609SChristian Ehrig #include <linux/bpf.h>
10c50e9609SChristian Ehrig #include <linux/btf_ids.h>
11c50e9609SChristian Ehrig 
12c50e9609SChristian Ehrig #include <net/dst_metadata.h>
13c50e9609SChristian Ehrig #include <net/fou.h>
14c50e9609SChristian Ehrig 
15c50e9609SChristian Ehrig struct bpf_fou_encap {
16c50e9609SChristian Ehrig 	__be16 sport;
17c50e9609SChristian Ehrig 	__be16 dport;
18c50e9609SChristian Ehrig };
19c50e9609SChristian Ehrig 
20c50e9609SChristian Ehrig enum bpf_fou_encap_type {
21c50e9609SChristian Ehrig 	FOU_BPF_ENCAP_FOU,
22c50e9609SChristian Ehrig 	FOU_BPF_ENCAP_GUE,
23c50e9609SChristian Ehrig };
24c50e9609SChristian Ehrig 
25391145baSDave Marchevsky __bpf_kfunc_start_defs();
26c50e9609SChristian Ehrig 
27c50e9609SChristian Ehrig /* bpf_skb_set_fou_encap - Set FOU encap parameters
28c50e9609SChristian Ehrig  *
29c50e9609SChristian Ehrig  * This function allows for using GUE or FOU encapsulation together with an
30c50e9609SChristian Ehrig  * ipip device in collect-metadata mode.
31c50e9609SChristian Ehrig  *
32c50e9609SChristian Ehrig  * It is meant to be used in BPF tc-hooks and after a call to the
33c50e9609SChristian Ehrig  * bpf_skb_set_tunnel_key helper, responsible for setting IP addresses.
34c50e9609SChristian Ehrig  *
35c50e9609SChristian Ehrig  * Parameters:
36c50e9609SChristian Ehrig  * @skb_ctx	Pointer to ctx (__sk_buff) in TC program. Cannot be NULL
37c50e9609SChristian Ehrig  * @encap	Pointer to a `struct bpf_fou_encap` storing UDP src and
38c50e9609SChristian Ehrig  * 		dst ports. If sport is set to 0 the kernel will auto-assign a
39c50e9609SChristian Ehrig  * 		port. This is similar to using `encap-sport auto`.
40c50e9609SChristian Ehrig  * 		Cannot be NULL
41c50e9609SChristian Ehrig  * @type	Encapsulation type for the packet. Their definitions are
42c50e9609SChristian Ehrig  * 		specified in `enum bpf_fou_encap_type`
43c50e9609SChristian Ehrig  */
bpf_skb_set_fou_encap(struct __sk_buff * skb_ctx,struct bpf_fou_encap * encap,int type)44c50e9609SChristian Ehrig __bpf_kfunc int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx,
45c50e9609SChristian Ehrig 				      struct bpf_fou_encap *encap, int type)
46c50e9609SChristian Ehrig {
47c50e9609SChristian Ehrig 	struct sk_buff *skb = (struct sk_buff *)skb_ctx;
48c50e9609SChristian Ehrig 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
49c50e9609SChristian Ehrig 
50c50e9609SChristian Ehrig 	if (unlikely(!encap))
51c50e9609SChristian Ehrig 		return -EINVAL;
52c50e9609SChristian Ehrig 
53c50e9609SChristian Ehrig 	if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX)))
54c50e9609SChristian Ehrig 		return -EINVAL;
55c50e9609SChristian Ehrig 
56c50e9609SChristian Ehrig 	switch (type) {
57c50e9609SChristian Ehrig 	case FOU_BPF_ENCAP_FOU:
58c50e9609SChristian Ehrig 		info->encap.type = TUNNEL_ENCAP_FOU;
59c50e9609SChristian Ehrig 		break;
60c50e9609SChristian Ehrig 	case FOU_BPF_ENCAP_GUE:
61c50e9609SChristian Ehrig 		info->encap.type = TUNNEL_ENCAP_GUE;
62c50e9609SChristian Ehrig 		break;
63c50e9609SChristian Ehrig 	default:
64c50e9609SChristian Ehrig 		info->encap.type = TUNNEL_ENCAP_NONE;
65c50e9609SChristian Ehrig 	}
66c50e9609SChristian Ehrig 
67*5832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags))
68c50e9609SChristian Ehrig 		info->encap.flags |= TUNNEL_ENCAP_FLAG_CSUM;
69c50e9609SChristian Ehrig 
70c50e9609SChristian Ehrig 	info->encap.sport = encap->sport;
71c50e9609SChristian Ehrig 	info->encap.dport = encap->dport;
72c50e9609SChristian Ehrig 
73c50e9609SChristian Ehrig 	return 0;
74c50e9609SChristian Ehrig }
75c50e9609SChristian Ehrig 
76c50e9609SChristian Ehrig /* bpf_skb_get_fou_encap - Get FOU encap parameters
77c50e9609SChristian Ehrig  *
78c50e9609SChristian Ehrig  * This function allows for reading encap metadata from a packet received
79c50e9609SChristian Ehrig  * on an ipip device in collect-metadata mode.
80c50e9609SChristian Ehrig  *
81c50e9609SChristian Ehrig  * Parameters:
82c50e9609SChristian Ehrig  * @skb_ctx	Pointer to ctx (__sk_buff) in TC program. Cannot be NULL
83c50e9609SChristian Ehrig  * @encap	Pointer to a struct bpf_fou_encap storing UDP source and
84c50e9609SChristian Ehrig  * 		destination port. Cannot be NULL
85c50e9609SChristian Ehrig  */
bpf_skb_get_fou_encap(struct __sk_buff * skb_ctx,struct bpf_fou_encap * encap)86c50e9609SChristian Ehrig __bpf_kfunc int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx,
87c50e9609SChristian Ehrig 				      struct bpf_fou_encap *encap)
88c50e9609SChristian Ehrig {
89c50e9609SChristian Ehrig 	struct sk_buff *skb = (struct sk_buff *)skb_ctx;
90c50e9609SChristian Ehrig 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
91c50e9609SChristian Ehrig 
92c50e9609SChristian Ehrig 	if (unlikely(!info))
93c50e9609SChristian Ehrig 		return -EINVAL;
94c50e9609SChristian Ehrig 
95c50e9609SChristian Ehrig 	encap->sport = info->encap.sport;
96c50e9609SChristian Ehrig 	encap->dport = info->encap.dport;
97c50e9609SChristian Ehrig 
98c50e9609SChristian Ehrig 	return 0;
99c50e9609SChristian Ehrig }
100c50e9609SChristian Ehrig 
101391145baSDave Marchevsky __bpf_kfunc_end_defs();
102c50e9609SChristian Ehrig 
1036f3189f3SDaniel Xu BTF_KFUNCS_START(fou_kfunc_set)
104c50e9609SChristian Ehrig BTF_ID_FLAGS(func, bpf_skb_set_fou_encap)
105c50e9609SChristian Ehrig BTF_ID_FLAGS(func, bpf_skb_get_fou_encap)
1066f3189f3SDaniel Xu BTF_KFUNCS_END(fou_kfunc_set)
107c50e9609SChristian Ehrig 
108c50e9609SChristian Ehrig static const struct btf_kfunc_id_set fou_bpf_kfunc_set = {
109c50e9609SChristian Ehrig 	.owner = THIS_MODULE,
110c50e9609SChristian Ehrig 	.set   = &fou_kfunc_set,
111c50e9609SChristian Ehrig };
112c50e9609SChristian Ehrig 
register_fou_bpf(void)113c50e9609SChristian Ehrig int register_fou_bpf(void)
114c50e9609SChristian Ehrig {
115c50e9609SChristian Ehrig 	return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
116c50e9609SChristian Ehrig 					 &fou_bpf_kfunc_set);
117c50e9609SChristian Ehrig }
118