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