xref: /linux-6.15/include/net/tc_wrapper.h (revision aefb2f2e)
17f0e8102SPedro Tammela /* SPDX-License-Identifier: GPL-2.0 */
27f0e8102SPedro Tammela #ifndef __NET_TC_WRAPPER_H
37f0e8102SPedro Tammela #define __NET_TC_WRAPPER_H
47f0e8102SPedro Tammela 
57f0e8102SPedro Tammela #include <net/pkt_cls.h>
67f0e8102SPedro Tammela 
7*aefb2f2eSBreno Leitao #if IS_ENABLED(CONFIG_MITIGATION_RETPOLINE)
87f0e8102SPedro Tammela 
97f0e8102SPedro Tammela #include <linux/cpufeature.h>
107f0e8102SPedro Tammela #include <linux/static_key.h>
117f0e8102SPedro Tammela #include <linux/indirect_call_wrapper.h>
127f0e8102SPedro Tammela 
137f0e8102SPedro Tammela #define TC_INDIRECT_SCOPE
147f0e8102SPedro Tammela 
157f0e8102SPedro Tammela extern struct static_key_false tc_skip_wrapper;
167f0e8102SPedro Tammela 
177f0e8102SPedro Tammela /* TC Actions */
187f0e8102SPedro Tammela #ifdef CONFIG_NET_CLS_ACT
197f0e8102SPedro Tammela 
207f0e8102SPedro Tammela #define TC_INDIRECT_ACTION_DECLARE(fname)                              \
217f0e8102SPedro Tammela 	INDIRECT_CALLABLE_DECLARE(int fname(struct sk_buff *skb,       \
227f0e8102SPedro Tammela 					    const struct tc_action *a, \
237f0e8102SPedro Tammela 					    struct tcf_result *res))
247f0e8102SPedro Tammela 
257f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_bpf_act);
267f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_connmark_act);
277f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_csum_act);
287f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_ct_act);
297f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_ctinfo_act);
307f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_gact_act);
317f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_gate_act);
327f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_ife_act);
337f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_ipt_act);
347f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_mirred_act);
357f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_mpls_act);
367f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_nat_act);
377f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_pedit_act);
387f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_police_act);
397f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_sample_act);
407f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_simp_act);
417f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_skbedit_act);
427f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_skbmod_act);
437f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tcf_vlan_act);
447f0e8102SPedro Tammela TC_INDIRECT_ACTION_DECLARE(tunnel_key_act);
457f0e8102SPedro Tammela 
tc_act(struct sk_buff * skb,const struct tc_action * a,struct tcf_result * res)467f0e8102SPedro Tammela static inline int tc_act(struct sk_buff *skb, const struct tc_action *a,
477f0e8102SPedro Tammela 			   struct tcf_result *res)
487f0e8102SPedro Tammela {
497f0e8102SPedro Tammela 	if (static_branch_likely(&tc_skip_wrapper))
507f0e8102SPedro Tammela 		goto skip;
517f0e8102SPedro Tammela 
527f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_GACT)
537f0e8102SPedro Tammela 	if (a->ops->act == tcf_gact_act)
547f0e8102SPedro Tammela 		return tcf_gact_act(skb, a, res);
557f0e8102SPedro Tammela #endif
567f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_MIRRED)
577f0e8102SPedro Tammela 	if (a->ops->act == tcf_mirred_act)
587f0e8102SPedro Tammela 		return tcf_mirred_act(skb, a, res);
597f0e8102SPedro Tammela #endif
607f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_PEDIT)
617f0e8102SPedro Tammela 	if (a->ops->act == tcf_pedit_act)
627f0e8102SPedro Tammela 		return tcf_pedit_act(skb, a, res);
637f0e8102SPedro Tammela #endif
647f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_SKBEDIT)
657f0e8102SPedro Tammela 	if (a->ops->act == tcf_skbedit_act)
667f0e8102SPedro Tammela 		return tcf_skbedit_act(skb, a, res);
677f0e8102SPedro Tammela #endif
687f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_SKBMOD)
697f0e8102SPedro Tammela 	if (a->ops->act == tcf_skbmod_act)
707f0e8102SPedro Tammela 		return tcf_skbmod_act(skb, a, res);
717f0e8102SPedro Tammela #endif
727f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_POLICE)
737f0e8102SPedro Tammela 	if (a->ops->act == tcf_police_act)
747f0e8102SPedro Tammela 		return tcf_police_act(skb, a, res);
757f0e8102SPedro Tammela #endif
767f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_BPF)
777f0e8102SPedro Tammela 	if (a->ops->act == tcf_bpf_act)
787f0e8102SPedro Tammela 		return tcf_bpf_act(skb, a, res);
797f0e8102SPedro Tammela #endif
807f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_CONNMARK)
817f0e8102SPedro Tammela 	if (a->ops->act == tcf_connmark_act)
827f0e8102SPedro Tammela 		return tcf_connmark_act(skb, a, res);
837f0e8102SPedro Tammela #endif
847f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_CSUM)
857f0e8102SPedro Tammela 	if (a->ops->act == tcf_csum_act)
867f0e8102SPedro Tammela 		return tcf_csum_act(skb, a, res);
877f0e8102SPedro Tammela #endif
887f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_CT)
897f0e8102SPedro Tammela 	if (a->ops->act == tcf_ct_act)
907f0e8102SPedro Tammela 		return tcf_ct_act(skb, a, res);
917f0e8102SPedro Tammela #endif
927f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_CTINFO)
937f0e8102SPedro Tammela 	if (a->ops->act == tcf_ctinfo_act)
947f0e8102SPedro Tammela 		return tcf_ctinfo_act(skb, a, res);
957f0e8102SPedro Tammela #endif
967f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_GATE)
977f0e8102SPedro Tammela 	if (a->ops->act == tcf_gate_act)
987f0e8102SPedro Tammela 		return tcf_gate_act(skb, a, res);
997f0e8102SPedro Tammela #endif
1007f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_MPLS)
1017f0e8102SPedro Tammela 	if (a->ops->act == tcf_mpls_act)
1027f0e8102SPedro Tammela 		return tcf_mpls_act(skb, a, res);
1037f0e8102SPedro Tammela #endif
1047f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_NAT)
1057f0e8102SPedro Tammela 	if (a->ops->act == tcf_nat_act)
1067f0e8102SPedro Tammela 		return tcf_nat_act(skb, a, res);
1077f0e8102SPedro Tammela #endif
1087f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_TUNNEL_KEY)
1097f0e8102SPedro Tammela 	if (a->ops->act == tunnel_key_act)
1107f0e8102SPedro Tammela 		return tunnel_key_act(skb, a, res);
1117f0e8102SPedro Tammela #endif
1127f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_VLAN)
1137f0e8102SPedro Tammela 	if (a->ops->act == tcf_vlan_act)
1147f0e8102SPedro Tammela 		return tcf_vlan_act(skb, a, res);
1157f0e8102SPedro Tammela #endif
1167f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_IFE)
1177f0e8102SPedro Tammela 	if (a->ops->act == tcf_ife_act)
1187f0e8102SPedro Tammela 		return tcf_ife_act(skb, a, res);
1197f0e8102SPedro Tammela #endif
1207f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_SIMP)
1217f0e8102SPedro Tammela 	if (a->ops->act == tcf_simp_act)
1227f0e8102SPedro Tammela 		return tcf_simp_act(skb, a, res);
1237f0e8102SPedro Tammela #endif
1247f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_ACT_SAMPLE)
1257f0e8102SPedro Tammela 	if (a->ops->act == tcf_sample_act)
1267f0e8102SPedro Tammela 		return tcf_sample_act(skb, a, res);
1277f0e8102SPedro Tammela #endif
1287f0e8102SPedro Tammela 
1297f0e8102SPedro Tammela skip:
1307f0e8102SPedro Tammela 	return a->ops->act(skb, a, res);
1317f0e8102SPedro Tammela }
1327f0e8102SPedro Tammela 
1337f0e8102SPedro Tammela #endif /* CONFIG_NET_CLS_ACT */
1347f0e8102SPedro Tammela 
1357f0e8102SPedro Tammela /* TC Filters */
1367f0e8102SPedro Tammela #ifdef CONFIG_NET_CLS
1377f0e8102SPedro Tammela 
1387f0e8102SPedro Tammela #define TC_INDIRECT_FILTER_DECLARE(fname)                               \
1397f0e8102SPedro Tammela 	INDIRECT_CALLABLE_DECLARE(int fname(struct sk_buff *skb,        \
1407f0e8102SPedro Tammela 					    const struct tcf_proto *tp, \
1417f0e8102SPedro Tammela 					    struct tcf_result *res))
1427f0e8102SPedro Tammela 
1437f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(basic_classify);
1447f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(cls_bpf_classify);
1457f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(cls_cgroup_classify);
1467f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(fl_classify);
1477f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(flow_classify);
1487f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(fw_classify);
1497f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(mall_classify);
1507f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(route4_classify);
1517f0e8102SPedro Tammela TC_INDIRECT_FILTER_DECLARE(u32_classify);
1527f0e8102SPedro Tammela 
tc_classify(struct sk_buff * skb,const struct tcf_proto * tp,struct tcf_result * res)1537f0e8102SPedro Tammela static inline int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
1547f0e8102SPedro Tammela 				struct tcf_result *res)
1557f0e8102SPedro Tammela {
1567f0e8102SPedro Tammela 	if (static_branch_likely(&tc_skip_wrapper))
1577f0e8102SPedro Tammela 		goto skip;
1587f0e8102SPedro Tammela 
1597f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_BPF)
1607f0e8102SPedro Tammela 	if (tp->classify == cls_bpf_classify)
1617f0e8102SPedro Tammela 		return cls_bpf_classify(skb, tp, res);
1627f0e8102SPedro Tammela #endif
1637f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_U32)
1647f0e8102SPedro Tammela 	if (tp->classify == u32_classify)
1657f0e8102SPedro Tammela 		return u32_classify(skb, tp, res);
1667f0e8102SPedro Tammela #endif
1677f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_FLOWER)
1687f0e8102SPedro Tammela 	if (tp->classify == fl_classify)
1697f0e8102SPedro Tammela 		return fl_classify(skb, tp, res);
1707f0e8102SPedro Tammela #endif
1717f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_FW)
1727f0e8102SPedro Tammela 	if (tp->classify == fw_classify)
1737f0e8102SPedro Tammela 		return fw_classify(skb, tp, res);
1747f0e8102SPedro Tammela #endif
1757f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_MATCHALL)
1767f0e8102SPedro Tammela 	if (tp->classify == mall_classify)
1777f0e8102SPedro Tammela 		return mall_classify(skb, tp, res);
1787f0e8102SPedro Tammela #endif
1797f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_BASIC)
1807f0e8102SPedro Tammela 	if (tp->classify == basic_classify)
1817f0e8102SPedro Tammela 		return basic_classify(skb, tp, res);
1827f0e8102SPedro Tammela #endif
1837f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
1847f0e8102SPedro Tammela 	if (tp->classify == cls_cgroup_classify)
1857f0e8102SPedro Tammela 		return cls_cgroup_classify(skb, tp, res);
1867f0e8102SPedro Tammela #endif
1877f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_FLOW)
1887f0e8102SPedro Tammela 	if (tp->classify == flow_classify)
1897f0e8102SPedro Tammela 		return flow_classify(skb, tp, res);
1907f0e8102SPedro Tammela #endif
1917f0e8102SPedro Tammela #if IS_BUILTIN(CONFIG_NET_CLS_ROUTE4)
1927f0e8102SPedro Tammela 	if (tp->classify == route4_classify)
1937f0e8102SPedro Tammela 		return route4_classify(skb, tp, res);
1947f0e8102SPedro Tammela #endif
1957f0e8102SPedro Tammela 
1967f0e8102SPedro Tammela skip:
1977f0e8102SPedro Tammela 	return tp->classify(skb, tp, res);
1987f0e8102SPedro Tammela }
1997f0e8102SPedro Tammela 
2007f0e8102SPedro Tammela #endif /* CONFIG_NET_CLS */
2017f0e8102SPedro Tammela 
tc_wrapper_init(void)2027f0e8102SPedro Tammela static inline void tc_wrapper_init(void)
2037f0e8102SPedro Tammela {
20440cab44bSPedro Tammela #ifdef CONFIG_X86
20540cab44bSPedro Tammela 	if (!cpu_feature_enabled(X86_FEATURE_RETPOLINE))
2067f0e8102SPedro Tammela 		static_branch_enable(&tc_skip_wrapper);
2077f0e8102SPedro Tammela #endif
2087f0e8102SPedro Tammela }
2097f0e8102SPedro Tammela 
2107f0e8102SPedro Tammela #else
2117f0e8102SPedro Tammela 
2127f0e8102SPedro Tammela #define TC_INDIRECT_SCOPE static
2137f0e8102SPedro Tammela 
tc_act(struct sk_buff * skb,const struct tc_action * a,struct tcf_result * res)2147f0e8102SPedro Tammela static inline int tc_act(struct sk_buff *skb, const struct tc_action *a,
2157f0e8102SPedro Tammela 			   struct tcf_result *res)
2167f0e8102SPedro Tammela {
2177f0e8102SPedro Tammela 	return a->ops->act(skb, a, res);
2187f0e8102SPedro Tammela }
2197f0e8102SPedro Tammela 
tc_classify(struct sk_buff * skb,const struct tcf_proto * tp,struct tcf_result * res)2207f0e8102SPedro Tammela static inline int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
2217f0e8102SPedro Tammela 				struct tcf_result *res)
2227f0e8102SPedro Tammela {
2237f0e8102SPedro Tammela 	return tp->classify(skb, tp, res);
2247f0e8102SPedro Tammela }
2257f0e8102SPedro Tammela 
tc_wrapper_init(void)2267f0e8102SPedro Tammela static inline void tc_wrapper_init(void)
2277f0e8102SPedro Tammela {
2287f0e8102SPedro Tammela }
2297f0e8102SPedro Tammela 
2307f0e8102SPedro Tammela #endif
2317f0e8102SPedro Tammela 
2327f0e8102SPedro Tammela #endif /* __NET_TC_WRAPPER_H */
2337f0e8102SPedro Tammela