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 __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 105 BTF_SET8_START(fou_kfunc_set) 106 BTF_ID_FLAGS(func, bpf_skb_set_fou_encap) 107 BTF_ID_FLAGS(func, bpf_skb_get_fou_encap) 108 BTF_SET8_END(fou_kfunc_set) 109 110 static const struct btf_kfunc_id_set fou_bpf_kfunc_set = { 111 .owner = THIS_MODULE, 112 .set = &fou_kfunc_set, 113 }; 114 115 int register_fou_bpf(void) 116 { 117 return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, 118 &fou_bpf_kfunc_set); 119 } 120