Commit | Line | Data |
---|---|---|
94151f5a EB |
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 | */ | |
400031e0 | 42 | __bpf_kfunc int bpf_skb_get_xfrm_info(struct __sk_buff *skb_ctx, struct bpf_xfrm_info *to) |
94151f5a EB |
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 | */ | |
400031e0 | 64 | __bpf_kfunc int bpf_skb_set_xfrm_info(struct __sk_buff *skb_ctx, const struct bpf_xfrm_info *from) |
94151f5a EB |
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 | } |