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