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