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