1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Unstable XFRM 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/xfrm.h> 14 15 /* bpf_xfrm_info - XFRM metadata information 16 * 17 * Members: 18 * @if_id - XFRM if_id: 19 * Transmit: if_id to be used in policy and state lookups 20 * Receive: if_id of the state matched for the incoming packet 21 * @link - Underlying device ifindex: 22 * Transmit: used as the underlying device in VRF routing 23 * Receive: the device on which the packet had been received 24 */ 25 struct bpf_xfrm_info { 26 u32 if_id; 27 int link; 28 }; 29 30 __diag_push(); 31 __diag_ignore_all("-Wmissing-prototypes", 32 "Global functions as their definitions will be in xfrm_interface BTF"); 33 34 /* bpf_skb_get_xfrm_info - Get XFRM metadata 35 * 36 * Parameters: 37 * @skb_ctx - Pointer to ctx (__sk_buff) in TC program 38 * Cannot be NULL 39 * @to - Pointer to memory to which the metadata will be copied 40 * Cannot be NULL 41 */ 42 __bpf_kfunc int bpf_skb_get_xfrm_info(struct __sk_buff *skb_ctx, struct bpf_xfrm_info *to) 43 { 44 struct sk_buff *skb = (struct sk_buff *)skb_ctx; 45 struct xfrm_md_info *info; 46 47 info = skb_xfrm_md_info(skb); 48 if (!info) 49 return -EINVAL; 50 51 to->if_id = info->if_id; 52 to->link = info->link; 53 return 0; 54 } 55 56 /* bpf_skb_get_xfrm_info - Set XFRM metadata 57 * 58 * Parameters: 59 * @skb_ctx - Pointer to ctx (__sk_buff) in TC program 60 * Cannot be NULL 61 * @from - Pointer to memory from which the metadata will be copied 62 * Cannot be NULL 63 */ 64 __bpf_kfunc int bpf_skb_set_xfrm_info(struct __sk_buff *skb_ctx, const struct bpf_xfrm_info *from) 65 { 66 struct sk_buff *skb = (struct sk_buff *)skb_ctx; 67 struct metadata_dst *md_dst; 68 struct xfrm_md_info *info; 69 70 if (unlikely(skb_metadata_dst(skb))) 71 return -EINVAL; 72 73 if (!xfrm_bpf_md_dst) { 74 struct metadata_dst __percpu *tmp; 75 76 tmp = metadata_dst_alloc_percpu(0, METADATA_XFRM, GFP_ATOMIC); 77 if (!tmp) 78 return -ENOMEM; 79 if (cmpxchg(&xfrm_bpf_md_dst, NULL, tmp)) 80 metadata_dst_free_percpu(tmp); 81 } 82 md_dst = this_cpu_ptr(xfrm_bpf_md_dst); 83 84 info = &md_dst->u.xfrm_info; 85 86 info->if_id = from->if_id; 87 info->link = from->link; 88 skb_dst_force(skb); 89 info->dst_orig = skb_dst(skb); 90 91 dst_hold((struct dst_entry *)md_dst); 92 skb_dst_set(skb, (struct dst_entry *)md_dst); 93 return 0; 94 } 95 96 __diag_pop() 97 98 BTF_SET8_START(xfrm_ifc_kfunc_set) 99 BTF_ID_FLAGS(func, bpf_skb_get_xfrm_info) 100 BTF_ID_FLAGS(func, bpf_skb_set_xfrm_info) 101 BTF_SET8_END(xfrm_ifc_kfunc_set) 102 103 static const struct btf_kfunc_id_set xfrm_interface_kfunc_set = { 104 .owner = THIS_MODULE, 105 .set = &xfrm_ifc_kfunc_set, 106 }; 107 108 int __init register_xfrm_interface_bpf(void) 109 { 110 return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, 111 &xfrm_interface_kfunc_set); 112 } 113