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_KFUNCS_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_KFUNCS_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(prog_type: BPF_PROG_TYPE_SCHED_CLS, |
116 | s: &fou_bpf_kfunc_set); |
117 | } |
118 | |