Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
---|---|
2 | #ifndef __NET_TC_WRAPPER_H |
3 | #define __NET_TC_WRAPPER_H |
4 | |
5 | #include <net/pkt_cls.h> |
6 | |
7 | #if IS_ENABLED(CONFIG_RETPOLINE) |
8 | |
9 | #include <linux/cpufeature.h> |
10 | #include <linux/static_key.h> |
11 | #include <linux/indirect_call_wrapper.h> |
12 | |
13 | #define TC_INDIRECT_SCOPE |
14 | |
15 | extern struct static_key_false tc_skip_wrapper; |
16 | |
17 | /* TC Actions */ |
18 | #ifdef CONFIG_NET_CLS_ACT |
19 | |
20 | #define TC_INDIRECT_ACTION_DECLARE(fname) \ |
21 | INDIRECT_CALLABLE_DECLARE(int fname(struct sk_buff *skb, \ |
22 | const struct tc_action *a, \ |
23 | struct tcf_result *res)) |
24 | |
25 | TC_INDIRECT_ACTION_DECLARE(tcf_bpf_act); |
26 | TC_INDIRECT_ACTION_DECLARE(tcf_connmark_act); |
27 | TC_INDIRECT_ACTION_DECLARE(tcf_csum_act); |
28 | TC_INDIRECT_ACTION_DECLARE(tcf_ct_act); |
29 | TC_INDIRECT_ACTION_DECLARE(tcf_ctinfo_act); |
30 | TC_INDIRECT_ACTION_DECLARE(tcf_gact_act); |
31 | TC_INDIRECT_ACTION_DECLARE(tcf_gate_act); |
32 | TC_INDIRECT_ACTION_DECLARE(tcf_ife_act); |
33 | TC_INDIRECT_ACTION_DECLARE(tcf_ipt_act); |
34 | TC_INDIRECT_ACTION_DECLARE(tcf_mirred_act); |
35 | TC_INDIRECT_ACTION_DECLARE(tcf_mpls_act); |
36 | TC_INDIRECT_ACTION_DECLARE(tcf_nat_act); |
37 | TC_INDIRECT_ACTION_DECLARE(tcf_pedit_act); |
38 | TC_INDIRECT_ACTION_DECLARE(tcf_police_act); |
39 | TC_INDIRECT_ACTION_DECLARE(tcf_sample_act); |
40 | TC_INDIRECT_ACTION_DECLARE(tcf_simp_act); |
41 | TC_INDIRECT_ACTION_DECLARE(tcf_skbedit_act); |
42 | TC_INDIRECT_ACTION_DECLARE(tcf_skbmod_act); |
43 | TC_INDIRECT_ACTION_DECLARE(tcf_vlan_act); |
44 | TC_INDIRECT_ACTION_DECLARE(tunnel_key_act); |
45 | |
46 | static inline int tc_act(struct sk_buff *skb, const struct tc_action *a, |
47 | struct tcf_result *res) |
48 | { |
49 | if (static_branch_likely(&tc_skip_wrapper)) |
50 | goto skip; |
51 | |
52 | #if IS_BUILTIN(CONFIG_NET_ACT_GACT) |
53 | if (a->ops->act == tcf_gact_act) |
54 | return tcf_gact_act(skb, a, res); |
55 | #endif |
56 | #if IS_BUILTIN(CONFIG_NET_ACT_MIRRED) |
57 | if (a->ops->act == tcf_mirred_act) |
58 | return tcf_mirred_act(skb, a, res); |
59 | #endif |
60 | #if IS_BUILTIN(CONFIG_NET_ACT_PEDIT) |
61 | if (a->ops->act == tcf_pedit_act) |
62 | return tcf_pedit_act(skb, a, res); |
63 | #endif |
64 | #if IS_BUILTIN(CONFIG_NET_ACT_SKBEDIT) |
65 | if (a->ops->act == tcf_skbedit_act) |
66 | return tcf_skbedit_act(skb, a, res); |
67 | #endif |
68 | #if IS_BUILTIN(CONFIG_NET_ACT_SKBMOD) |
69 | if (a->ops->act == tcf_skbmod_act) |
70 | return tcf_skbmod_act(skb, a, res); |
71 | #endif |
72 | #if IS_BUILTIN(CONFIG_NET_ACT_POLICE) |
73 | if (a->ops->act == tcf_police_act) |
74 | return tcf_police_act(skb, a, res); |
75 | #endif |
76 | #if IS_BUILTIN(CONFIG_NET_ACT_BPF) |
77 | if (a->ops->act == tcf_bpf_act) |
78 | return tcf_bpf_act(skb, a, res); |
79 | #endif |
80 | #if IS_BUILTIN(CONFIG_NET_ACT_CONNMARK) |
81 | if (a->ops->act == tcf_connmark_act) |
82 | return tcf_connmark_act(skb, a, res); |
83 | #endif |
84 | #if IS_BUILTIN(CONFIG_NET_ACT_CSUM) |
85 | if (a->ops->act == tcf_csum_act) |
86 | return tcf_csum_act(skb, a, res); |
87 | #endif |
88 | #if IS_BUILTIN(CONFIG_NET_ACT_CT) |
89 | if (a->ops->act == tcf_ct_act) |
90 | return tcf_ct_act(skb, a, res); |
91 | #endif |
92 | #if IS_BUILTIN(CONFIG_NET_ACT_CTINFO) |
93 | if (a->ops->act == tcf_ctinfo_act) |
94 | return tcf_ctinfo_act(skb, a, res); |
95 | #endif |
96 | #if IS_BUILTIN(CONFIG_NET_ACT_GATE) |
97 | if (a->ops->act == tcf_gate_act) |
98 | return tcf_gate_act(skb, a, res); |
99 | #endif |
100 | #if IS_BUILTIN(CONFIG_NET_ACT_MPLS) |
101 | if (a->ops->act == tcf_mpls_act) |
102 | return tcf_mpls_act(skb, a, res); |
103 | #endif |
104 | #if IS_BUILTIN(CONFIG_NET_ACT_NAT) |
105 | if (a->ops->act == tcf_nat_act) |
106 | return tcf_nat_act(skb, a, res); |
107 | #endif |
108 | #if IS_BUILTIN(CONFIG_NET_ACT_TUNNEL_KEY) |
109 | if (a->ops->act == tunnel_key_act) |
110 | return tunnel_key_act(skb, a, res); |
111 | #endif |
112 | #if IS_BUILTIN(CONFIG_NET_ACT_VLAN) |
113 | if (a->ops->act == tcf_vlan_act) |
114 | return tcf_vlan_act(skb, a, res); |
115 | #endif |
116 | #if IS_BUILTIN(CONFIG_NET_ACT_IFE) |
117 | if (a->ops->act == tcf_ife_act) |
118 | return tcf_ife_act(skb, a, res); |
119 | #endif |
120 | #if IS_BUILTIN(CONFIG_NET_ACT_IPT) |
121 | if (a->ops->act == tcf_ipt_act) |
122 | return tcf_ipt_act(skb, a, res); |
123 | #endif |
124 | #if IS_BUILTIN(CONFIG_NET_ACT_SIMP) |
125 | if (a->ops->act == tcf_simp_act) |
126 | return tcf_simp_act(skb, a, res); |
127 | #endif |
128 | #if IS_BUILTIN(CONFIG_NET_ACT_SAMPLE) |
129 | if (a->ops->act == tcf_sample_act) |
130 | return tcf_sample_act(skb, a, res); |
131 | #endif |
132 | |
133 | skip: |
134 | return a->ops->act(skb, a, res); |
135 | } |
136 | |
137 | #endif /* CONFIG_NET_CLS_ACT */ |
138 | |
139 | /* TC Filters */ |
140 | #ifdef CONFIG_NET_CLS |
141 | |
142 | #define TC_INDIRECT_FILTER_DECLARE(fname) \ |
143 | INDIRECT_CALLABLE_DECLARE(int fname(struct sk_buff *skb, \ |
144 | const struct tcf_proto *tp, \ |
145 | struct tcf_result *res)) |
146 | |
147 | TC_INDIRECT_FILTER_DECLARE(basic_classify); |
148 | TC_INDIRECT_FILTER_DECLARE(cls_bpf_classify); |
149 | TC_INDIRECT_FILTER_DECLARE(cls_cgroup_classify); |
150 | TC_INDIRECT_FILTER_DECLARE(fl_classify); |
151 | TC_INDIRECT_FILTER_DECLARE(flow_classify); |
152 | TC_INDIRECT_FILTER_DECLARE(fw_classify); |
153 | TC_INDIRECT_FILTER_DECLARE(mall_classify); |
154 | TC_INDIRECT_FILTER_DECLARE(route4_classify); |
155 | TC_INDIRECT_FILTER_DECLARE(u32_classify); |
156 | |
157 | static inline int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
158 | struct tcf_result *res) |
159 | { |
160 | if (static_branch_likely(&tc_skip_wrapper)) |
161 | goto skip; |
162 | |
163 | #if IS_BUILTIN(CONFIG_NET_CLS_BPF) |
164 | if (tp->classify == cls_bpf_classify) |
165 | return cls_bpf_classify(skb, tp, res); |
166 | #endif |
167 | #if IS_BUILTIN(CONFIG_NET_CLS_U32) |
168 | if (tp->classify == u32_classify) |
169 | return u32_classify(skb, tp, res); |
170 | #endif |
171 | #if IS_BUILTIN(CONFIG_NET_CLS_FLOWER) |
172 | if (tp->classify == fl_classify) |
173 | return fl_classify(skb, tp, res); |
174 | #endif |
175 | #if IS_BUILTIN(CONFIG_NET_CLS_FW) |
176 | if (tp->classify == fw_classify) |
177 | return fw_classify(skb, tp, res); |
178 | #endif |
179 | #if IS_BUILTIN(CONFIG_NET_CLS_MATCHALL) |
180 | if (tp->classify == mall_classify) |
181 | return mall_classify(skb, tp, res); |
182 | #endif |
183 | #if IS_BUILTIN(CONFIG_NET_CLS_BASIC) |
184 | if (tp->classify == basic_classify) |
185 | return basic_classify(skb, tp, res); |
186 | #endif |
187 | #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP) |
188 | if (tp->classify == cls_cgroup_classify) |
189 | return cls_cgroup_classify(skb, tp, res); |
190 | #endif |
191 | #if IS_BUILTIN(CONFIG_NET_CLS_FLOW) |
192 | if (tp->classify == flow_classify) |
193 | return flow_classify(skb, tp, res); |
194 | #endif |
195 | #if IS_BUILTIN(CONFIG_NET_CLS_ROUTE4) |
196 | if (tp->classify == route4_classify) |
197 | return route4_classify(skb, tp, res); |
198 | #endif |
199 | |
200 | skip: |
201 | return tp->classify(skb, tp, res); |
202 | } |
203 | |
204 | #endif /* CONFIG_NET_CLS */ |
205 | |
206 | static inline void tc_wrapper_init(void) |
207 | { |
208 | #ifdef CONFIG_X86 |
209 | if (!cpu_feature_enabled(X86_FEATURE_RETPOLINE)) |
210 | static_branch_enable(&tc_skip_wrapper); |
211 | #endif |
212 | } |
213 | |
214 | #else |
215 | |
216 | #define TC_INDIRECT_SCOPE static |
217 | |
218 | static inline int tc_act(struct sk_buff *skb, const struct tc_action *a, |
219 | struct tcf_result *res) |
220 | { |
221 | return a->ops->act(skb, a, res); |
222 | } |
223 | |
224 | static inline int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
225 | struct tcf_result *res) |
226 | { |
227 | return tp->classify(skb, tp, res); |
228 | } |
229 | |
230 | static inline void tc_wrapper_init(void) |
231 | { |
232 | } |
233 | |
234 | #endif |
235 | |
236 | #endif /* __NET_TC_WRAPPER_H */ |
237 |
Warning: This file is not a C or C++ file. It does not have highlighting.