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 | ||
391145ba | 30 | __bpf_kfunc_start_defs(); |
94151f5a EB |
31 | |
32 | /* bpf_skb_get_xfrm_info - Get XFRM metadata | |
33 | * | |
34 | * Parameters: | |
35 | * @skb_ctx - Pointer to ctx (__sk_buff) in TC program | |
36 | * Cannot be NULL | |
37 | * @to - Pointer to memory to which the metadata will be copied | |
38 | * Cannot be NULL | |
39 | */ | |
400031e0 | 40 | __bpf_kfunc int bpf_skb_get_xfrm_info(struct __sk_buff *skb_ctx, struct bpf_xfrm_info *to) |
94151f5a EB |
41 | { |
42 | struct sk_buff *skb = (struct sk_buff *)skb_ctx; | |
43 | struct xfrm_md_info *info; | |
44 | ||
45 | info = skb_xfrm_md_info(skb); | |
46 | if (!info) | |
47 | return -EINVAL; | |
48 | ||
49 | to->if_id = info->if_id; | |
50 | to->link = info->link; | |
51 | return 0; | |
52 | } | |
53 | ||
54 | /* bpf_skb_get_xfrm_info - Set XFRM metadata | |
55 | * | |
56 | * Parameters: | |
57 | * @skb_ctx - Pointer to ctx (__sk_buff) in TC program | |
58 | * Cannot be NULL | |
59 | * @from - Pointer to memory from which the metadata will be copied | |
60 | * Cannot be NULL | |
61 | */ | |
400031e0 | 62 | __bpf_kfunc int bpf_skb_set_xfrm_info(struct __sk_buff *skb_ctx, const struct bpf_xfrm_info *from) |
94151f5a EB |
63 | { |
64 | struct sk_buff *skb = (struct sk_buff *)skb_ctx; | |
65 | struct metadata_dst *md_dst; | |
66 | struct xfrm_md_info *info; | |
67 | ||
68 | if (unlikely(skb_metadata_dst(skb))) | |
69 | return -EINVAL; | |
70 | ||
71 | if (!xfrm_bpf_md_dst) { | |
72 | struct metadata_dst __percpu *tmp; | |
73 | ||
74 | tmp = metadata_dst_alloc_percpu(0, METADATA_XFRM, GFP_ATOMIC); | |
75 | if (!tmp) | |
76 | return -ENOMEM; | |
77 | if (cmpxchg(&xfrm_bpf_md_dst, NULL, tmp)) | |
78 | metadata_dst_free_percpu(tmp); | |
79 | } | |
80 | md_dst = this_cpu_ptr(xfrm_bpf_md_dst); | |
81 | ||
82 | info = &md_dst->u.xfrm_info; | |
83 | ||
84 | info->if_id = from->if_id; | |
85 | info->link = from->link; | |
86 | skb_dst_force(skb); | |
87 | info->dst_orig = skb_dst(skb); | |
88 | ||
89 | dst_hold((struct dst_entry *)md_dst); | |
90 | skb_dst_set(skb, (struct dst_entry *)md_dst); | |
91 | return 0; | |
92 | } | |
93 | ||
391145ba | 94 | __bpf_kfunc_end_defs(); |
94151f5a EB |
95 | |
96 | BTF_SET8_START(xfrm_ifc_kfunc_set) | |
97 | BTF_ID_FLAGS(func, bpf_skb_get_xfrm_info) | |
98 | BTF_ID_FLAGS(func, bpf_skb_set_xfrm_info) | |
99 | BTF_SET8_END(xfrm_ifc_kfunc_set) | |
100 | ||
101 | static const struct btf_kfunc_id_set xfrm_interface_kfunc_set = { | |
102 | .owner = THIS_MODULE, | |
103 | .set = &xfrm_ifc_kfunc_set, | |
104 | }; | |
105 | ||
106 | int __init register_xfrm_interface_bpf(void) | |
107 | { | |
108 | return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, | |
109 | &xfrm_interface_kfunc_set); | |
110 | } |