1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds #ifndef __NET_PKT_CLS_H 31da177e4SLinus Torvalds #define __NET_PKT_CLS_H 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds #include <linux/pkt_cls.h> 67aa0045dSCong Wang #include <linux/workqueue.h> 71da177e4SLinus Torvalds #include <net/sch_generic.h> 81da177e4SLinus Torvalds #include <net/act_api.h> 9a5148626SJiri Pirko #include <net/net_namespace.h> 101da177e4SLinus Torvalds 11cd11b164SPaolo Abeni /* TC action not accessible from user space */ 12720f22feSJohn Hurley #define TC_ACT_CONSUMED (TC_ACT_VALUE_MAX + 1) 13cd11b164SPaolo Abeni 141da177e4SLinus Torvalds /* Basic packet classifier frontend definitions. */ 151da177e4SLinus Torvalds 16fd2c3ef7SEric Dumazet struct tcf_walker { 171da177e4SLinus Torvalds int stop; 181da177e4SLinus Torvalds int skip; 191da177e4SLinus Torvalds int count; 206676d5e4SVlad Buslov bool nonempty; 2101683a14SVlad Buslov unsigned long cookie; 228113c095SWANG Cong int (*fn)(struct tcf_proto *, void *node, struct tcf_walker *); 231da177e4SLinus Torvalds }; 241da177e4SLinus Torvalds 255c15257fSJoe Perches int register_tcf_proto_ops(struct tcf_proto_ops *ops); 265c15257fSJoe Perches int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); 271da177e4SLinus Torvalds 288c4083b3SJiri Pirko struct tcf_block_ext_info { 2932f8c409SPablo Neira Ayuso enum flow_block_binder_type binder_type; 30c7eb7d72SJiri Pirko tcf_chain_head_change_t *chain_head_change; 31c7eb7d72SJiri Pirko void *chain_head_change_priv; 3248617387SJiri Pirko u32 block_index; 338c4083b3SJiri Pirko }; 348c4083b3SJiri Pirko 353625750fSPetr Machata struct tcf_qevent { 363625750fSPetr Machata struct tcf_block *block; 373625750fSPetr Machata struct tcf_block_ext_info info; 383625750fSPetr Machata struct tcf_proto __rcu *filter_chain; 393625750fSPetr Machata }; 403625750fSPetr Machata 41acb67442SJiri Pirko struct tcf_block_cb; 42aaa908ffSCong Wang bool tcf_queue_work(struct rcu_work *rwork, work_func_t func); 43acb67442SJiri Pirko 448ae70032SJiri Pirko #ifdef CONFIG_NET_CLS 451f3ed383SJiri Pirko struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, 461f3ed383SJiri Pirko u32 chain_index); 471f3ed383SJiri Pirko void tcf_chain_put_by_act(struct tcf_chain *chain); 48bbf73830SVlad Buslov struct tcf_chain *tcf_get_next_chain(struct tcf_block *block, 49bbf73830SVlad Buslov struct tcf_chain *chain); 50fe2923afSVlad Buslov struct tcf_proto *tcf_get_next_proto(struct tcf_chain *chain, 510fca55edSVlad Buslov struct tcf_proto *tp); 52f36fe1c4SJiri Pirko void tcf_block_netif_keep_dst(struct tcf_block *block); 536529eabaSJiri Pirko int tcf_block_get(struct tcf_block **p_block, 548d1a77f9SAlexander Aring struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 558d1a77f9SAlexander Aring struct netlink_ext_ack *extack); 56c7eb7d72SJiri Pirko int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 578d1a77f9SAlexander Aring struct tcf_block_ext_info *ei, 588d1a77f9SAlexander Aring struct netlink_ext_ack *extack); 596529eabaSJiri Pirko void tcf_block_put(struct tcf_block *block); 60c7eb7d72SJiri Pirko void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 618c4083b3SJiri Pirko struct tcf_block_ext_info *ei); 6244186460SJiri Pirko 6348617387SJiri Pirko static inline bool tcf_block_shared(struct tcf_block *block) 6448617387SJiri Pirko { 6548617387SJiri Pirko return block->index; 6648617387SJiri Pirko } 6748617387SJiri Pirko 68c1a970d0SVlad Buslov static inline bool tcf_block_non_null_shared(struct tcf_block *block) 69c1a970d0SVlad Buslov { 70c1a970d0SVlad Buslov return block && block->index; 71c1a970d0SVlad Buslov } 72c1a970d0SVlad Buslov 7344186460SJiri Pirko static inline struct Qdisc *tcf_block_q(struct tcf_block *block) 7444186460SJiri Pirko { 7548617387SJiri Pirko WARN_ON(tcf_block_shared(block)); 7644186460SJiri Pirko return block->q; 7744186460SJiri Pirko } 7844186460SJiri Pirko 793aa26055SDavide Caratti int tcf_classify(struct sk_buff *skb, 803aa26055SDavide Caratti const struct tcf_block *block, 817d17c544SPaul Blakey const struct tcf_proto *tp, struct tcf_result *res, 827d17c544SPaul Blakey bool compat_mode); 8387d83093SJiri Pirko 848ae70032SJiri Pirko #else 8588c44a52SPieter Jansen van Vuuren static inline bool tcf_block_shared(struct tcf_block *block) 8688c44a52SPieter Jansen van Vuuren { 8788c44a52SPieter Jansen van Vuuren return false; 8888c44a52SPieter Jansen van Vuuren } 8988c44a52SPieter Jansen van Vuuren 90c1a970d0SVlad Buslov static inline bool tcf_block_non_null_shared(struct tcf_block *block) 91c1a970d0SVlad Buslov { 92c1a970d0SVlad Buslov return false; 93c1a970d0SVlad Buslov } 94c1a970d0SVlad Buslov 956529eabaSJiri Pirko static inline 966529eabaSJiri Pirko int tcf_block_get(struct tcf_block **p_block, 973c149091SSudip Mukherjee struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 983c149091SSudip Mukherjee struct netlink_ext_ack *extack) 996529eabaSJiri Pirko { 1006529eabaSJiri Pirko return 0; 1016529eabaSJiri Pirko } 1026529eabaSJiri Pirko 1038c4083b3SJiri Pirko static inline 104c7eb7d72SJiri Pirko int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 10533c30a8bSQuentin Monnet struct tcf_block_ext_info *ei, 10633c30a8bSQuentin Monnet struct netlink_ext_ack *extack) 1078c4083b3SJiri Pirko { 1088c4083b3SJiri Pirko return 0; 1098c4083b3SJiri Pirko } 1108c4083b3SJiri Pirko 1116529eabaSJiri Pirko static inline void tcf_block_put(struct tcf_block *block) 1128ae70032SJiri Pirko { 1138ae70032SJiri Pirko } 11487d83093SJiri Pirko 1158c4083b3SJiri Pirko static inline 116c7eb7d72SJiri Pirko void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 1178c4083b3SJiri Pirko struct tcf_block_ext_info *ei) 1188c4083b3SJiri Pirko { 1198c4083b3SJiri Pirko } 1208c4083b3SJiri Pirko 12144186460SJiri Pirko static inline struct Qdisc *tcf_block_q(struct tcf_block *block) 12244186460SJiri Pirko { 12344186460SJiri Pirko return NULL; 12444186460SJiri Pirko } 12544186460SJiri Pirko 126acb67442SJiri Pirko static inline 127a7323311SPablo Neira Ayuso int tc_setup_cb_block_register(struct tcf_block *block, flow_setup_cb_t *cb, 128acb67442SJiri Pirko void *cb_priv) 129acb67442SJiri Pirko { 130acb67442SJiri Pirko return 0; 131acb67442SJiri Pirko } 132acb67442SJiri Pirko 133acb67442SJiri Pirko static inline 134a7323311SPablo Neira Ayuso void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb, 135acb67442SJiri Pirko void *cb_priv) 136acb67442SJiri Pirko { 137acb67442SJiri Pirko } 138acb67442SJiri Pirko 1393aa26055SDavide Caratti static inline int tcf_classify(struct sk_buff *skb, 1403aa26055SDavide Caratti const struct tcf_block *block, 1419410c940SPaul Blakey const struct tcf_proto *tp, 1429410c940SPaul Blakey struct tcf_result *res, bool compat_mode) 1439410c940SPaul Blakey { 1449410c940SPaul Blakey return TC_ACT_UNSPEC; 1459410c940SPaul Blakey } 1469410c940SPaul Blakey 1478ae70032SJiri Pirko #endif 148cf1facdaSJiri Pirko 1491da177e4SLinus Torvalds static inline unsigned long 1501da177e4SLinus Torvalds __cls_set_class(unsigned long *clp, unsigned long cl) 1511da177e4SLinus Torvalds { 152a0efb80cSWANG Cong return xchg(clp, cl); 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 1552e24cd75SCong Wang static inline void 1562e24cd75SCong Wang __tcf_bind_filter(struct Qdisc *q, struct tcf_result *r, unsigned long base) 1571da177e4SLinus Torvalds { 1582e24cd75SCong Wang unsigned long cl; 1591da177e4SLinus Torvalds 1602e24cd75SCong Wang cl = q->ops->cl_ops->bind_tcf(q, base, r->classid); 1612e24cd75SCong Wang cl = __cls_set_class(&r->class, cl); 1622e24cd75SCong Wang if (cl) 1632e24cd75SCong Wang q->ops->cl_ops->unbind_tcf(q, cl); 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds static inline void 1671da177e4SLinus Torvalds tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base) 1681da177e4SLinus Torvalds { 16934e3759cSJiri Pirko struct Qdisc *q = tp->chain->block->q; 1701da177e4SLinus Torvalds 17134e3759cSJiri Pirko /* Check q as it is not set for shared blocks. In that case, 17234e3759cSJiri Pirko * setting class is not supported. 17334e3759cSJiri Pirko */ 17434e3759cSJiri Pirko if (!q) 17534e3759cSJiri Pirko return; 1762e24cd75SCong Wang sch_tree_lock(q); 1772e24cd75SCong Wang __tcf_bind_filter(q, r, base); 1782e24cd75SCong Wang sch_tree_unlock(q); 1792e24cd75SCong Wang } 1802e24cd75SCong Wang 1812e24cd75SCong Wang static inline void 1822e24cd75SCong Wang __tcf_unbind_filter(struct Qdisc *q, struct tcf_result *r) 1832e24cd75SCong Wang { 1842e24cd75SCong Wang unsigned long cl; 1852e24cd75SCong Wang 1862e24cd75SCong Wang if ((cl = __cls_set_class(&r->class, 0)) != 0) 18734e3759cSJiri Pirko q->ops->cl_ops->unbind_tcf(q, cl); 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds static inline void 1911da177e4SLinus Torvalds tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r) 1921da177e4SLinus Torvalds { 19334e3759cSJiri Pirko struct Qdisc *q = tp->chain->block->q; 1941da177e4SLinus Torvalds 19534e3759cSJiri Pirko if (!q) 19634e3759cSJiri Pirko return; 1972e24cd75SCong Wang __tcf_unbind_filter(q, r); 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds 200fd2c3ef7SEric Dumazet struct tcf_exts { 2011da177e4SLinus Torvalds #ifdef CONFIG_NET_CLS_ACT 20233be6271SWANG Cong __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ 20322dc13c8SWANG Cong int nr_actions; 20422dc13c8SWANG Cong struct tc_action **actions; 205e4b95c41SCong Wang struct net *net; 206dbdcda63SEric Dumazet netns_tracker ns_tracker; 2071da177e4SLinus Torvalds #endif 2081da177e4SLinus Torvalds /* Map to export classifier specific extension TLV types to the 2091da177e4SLinus Torvalds * generic extensions API. Unsupported extensions must be set to 0. 2101da177e4SLinus Torvalds */ 2111da177e4SLinus Torvalds int action; 2121da177e4SLinus Torvalds int police; 2131da177e4SLinus Torvalds }; 2141da177e4SLinus Torvalds 21514215108SCong Wang static inline int tcf_exts_init(struct tcf_exts *exts, struct net *net, 21614215108SCong Wang int action, int police) 21733be6271SWANG Cong { 21833be6271SWANG Cong #ifdef CONFIG_NET_CLS_ACT 2195da57f42SWANG Cong exts->type = 0; 22022dc13c8SWANG Cong exts->nr_actions = 0; 22114215108SCong Wang exts->net = net; 222dbdcda63SEric Dumazet netns_tracker_alloc(net, &exts->ns_tracker, GFP_KERNEL); 22322dc13c8SWANG Cong exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *), 22422dc13c8SWANG Cong GFP_KERNEL); 225b9a24bb7SWANG Cong if (!exts->actions) 226b9a24bb7SWANG Cong return -ENOMEM; 22733be6271SWANG Cong #endif 2285da57f42SWANG Cong exts->action = action; 2295da57f42SWANG Cong exts->police = police; 230b9a24bb7SWANG Cong return 0; 23133be6271SWANG Cong } 23233be6271SWANG Cong 233e4b95c41SCong Wang /* Return false if the netns is being destroyed in cleanup_net(). Callers 234e4b95c41SCong Wang * need to do cleanup synchronously in this case, otherwise may race with 235e4b95c41SCong Wang * tc_action_net_exit(). Return true for other cases. 236e4b95c41SCong Wang */ 237e4b95c41SCong Wang static inline bool tcf_exts_get_net(struct tcf_exts *exts) 238e4b95c41SCong Wang { 239e4b95c41SCong Wang #ifdef CONFIG_NET_CLS_ACT 240e4b95c41SCong Wang exts->net = maybe_get_net(exts->net); 241dbdcda63SEric Dumazet if (exts->net) 242dbdcda63SEric Dumazet netns_tracker_alloc(exts->net, &exts->ns_tracker, GFP_KERNEL); 243e4b95c41SCong Wang return exts->net != NULL; 244e4b95c41SCong Wang #else 245e4b95c41SCong Wang return true; 246e4b95c41SCong Wang #endif 247e4b95c41SCong Wang } 248e4b95c41SCong Wang 249e4b95c41SCong Wang static inline void tcf_exts_put_net(struct tcf_exts *exts) 250e4b95c41SCong Wang { 251e4b95c41SCong Wang #ifdef CONFIG_NET_CLS_ACT 252e4b95c41SCong Wang if (exts->net) 253dbdcda63SEric Dumazet put_net_track(exts->net, &exts->ns_tracker); 254e4b95c41SCong Wang #endif 255e4b95c41SCong Wang } 256e4b95c41SCong Wang 25722dc13c8SWANG Cong #ifdef CONFIG_NET_CLS_ACT 258244cd96aSCong Wang #define tcf_exts_for_each_action(i, a, exts) \ 259244cd96aSCong Wang for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = (exts)->actions[i]); i++) 260244cd96aSCong Wang #else 261244cd96aSCong Wang #define tcf_exts_for_each_action(i, a, exts) \ 262191672caSArnd Bergmann for (; 0; (void)(i), (void)(a), (void)(exts)) 26322dc13c8SWANG Cong #endif 26422dc13c8SWANG Cong 265*8cbfe939SBaowen Zheng #define tcf_act_for_each_action(i, a, actions) \ 266*8cbfe939SBaowen Zheng for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = actions[i]); i++) 267*8cbfe939SBaowen Zheng 268d897a638SJakub Kicinski static inline void 269d897a638SJakub Kicinski tcf_exts_stats_update(const struct tcf_exts *exts, 2704b61d3e8SPo Liu u64 bytes, u64 packets, u64 drops, u64 lastuse, 27193a129ebSJiri Pirko u8 used_hw_stats, bool used_hw_stats_valid) 272d897a638SJakub Kicinski { 273d897a638SJakub Kicinski #ifdef CONFIG_NET_CLS_ACT 274d897a638SJakub Kicinski int i; 275d897a638SJakub Kicinski 276d897a638SJakub Kicinski preempt_disable(); 277d897a638SJakub Kicinski 278d897a638SJakub Kicinski for (i = 0; i < exts->nr_actions; i++) { 279d897a638SJakub Kicinski struct tc_action *a = exts->actions[i]; 280d897a638SJakub Kicinski 2814b61d3e8SPo Liu tcf_action_stats_update(a, bytes, packets, drops, 2824b61d3e8SPo Liu lastuse, true); 28393a129ebSJiri Pirko a->used_hw_stats = used_hw_stats; 28493a129ebSJiri Pirko a->used_hw_stats_valid = used_hw_stats_valid; 285d897a638SJakub Kicinski } 286d897a638SJakub Kicinski 287d897a638SJakub Kicinski preempt_enable(); 288d897a638SJakub Kicinski #endif 289d897a638SJakub Kicinski } 290d897a638SJakub Kicinski 2911da177e4SLinus Torvalds /** 2923bcc0cecSJiri Pirko * tcf_exts_has_actions - check if at least one action is present 2933bcc0cecSJiri Pirko * @exts: tc filter extensions handle 2943bcc0cecSJiri Pirko * 2953bcc0cecSJiri Pirko * Returns true if at least one action is present. 2963bcc0cecSJiri Pirko */ 2973bcc0cecSJiri Pirko static inline bool tcf_exts_has_actions(struct tcf_exts *exts) 2983bcc0cecSJiri Pirko { 2992734437eSWANG Cong #ifdef CONFIG_NET_CLS_ACT 3003bcc0cecSJiri Pirko return exts->nr_actions; 3013bcc0cecSJiri Pirko #else 3023bcc0cecSJiri Pirko return false; 3033bcc0cecSJiri Pirko #endif 3043bcc0cecSJiri Pirko } 3052734437eSWANG Cong 3063bcc0cecSJiri Pirko /** 307af69afc5SJiri Pirko * tcf_exts_exec - execute tc filter extensions 308af69afc5SJiri Pirko * @skb: socket buffer 309af69afc5SJiri Pirko * @exts: tc filter extensions handle 310af69afc5SJiri Pirko * @res: desired result 311af69afc5SJiri Pirko * 312af089e70SJiri Pirko * Executes all configured extensions. Returns TC_ACT_OK on a normal execution, 313af69afc5SJiri Pirko * a negative number if the filter must be considered unmatched or 314af69afc5SJiri Pirko * a positive action code (TC_ACT_*) which must be returned to the 315af69afc5SJiri Pirko * underlying layer. 316af69afc5SJiri Pirko */ 317af69afc5SJiri Pirko static inline int 318af69afc5SJiri Pirko tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, 319af69afc5SJiri Pirko struct tcf_result *res) 320af69afc5SJiri Pirko { 321af69afc5SJiri Pirko #ifdef CONFIG_NET_CLS_ACT 322ec1a9ccaSJiri Pirko return tcf_action_exec(skb, exts->actions, exts->nr_actions, res); 323af69afc5SJiri Pirko #endif 324af089e70SJiri Pirko return TC_ACT_OK; 325af69afc5SJiri Pirko } 326af69afc5SJiri Pirko 3275c15257fSJoe Perches int tcf_exts_validate(struct net *net, struct tcf_proto *tp, 328c1b52739SBenjamin LaHaise struct nlattr **tb, struct nlattr *rate_tlv, 329695176bfSCong Wang struct tcf_exts *exts, u32 flags, 33050a56190SAlexander Aring struct netlink_ext_ack *extack); 33118d0264fSWANG Cong void tcf_exts_destroy(struct tcf_exts *exts); 3329b0d4446SJiri Pirko void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); 3335da57f42SWANG Cong int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); 334ca44b738SVlad Buslov int tcf_exts_terse_dump(struct sk_buff *skb, struct tcf_exts *exts); 3355da57f42SWANG Cong int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts); 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds /** 3381da177e4SLinus Torvalds * struct tcf_pkt_info - packet information 3390161d151SBijie Xu * 3400161d151SBijie Xu * @ptr: start of the pkt data 3410161d151SBijie Xu * @nexthdr: offset of the next header 3421da177e4SLinus Torvalds */ 343fd2c3ef7SEric Dumazet struct tcf_pkt_info { 3441da177e4SLinus Torvalds unsigned char * ptr; 3451da177e4SLinus Torvalds int nexthdr; 3461da177e4SLinus Torvalds }; 3471da177e4SLinus Torvalds 3481da177e4SLinus Torvalds #ifdef CONFIG_NET_EMATCH 3491da177e4SLinus Torvalds 3501da177e4SLinus Torvalds struct tcf_ematch_ops; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds /** 3531da177e4SLinus Torvalds * struct tcf_ematch - extended match (ematch) 3541da177e4SLinus Torvalds * 3551da177e4SLinus Torvalds * @matchid: identifier to allow userspace to reidentify a match 3561da177e4SLinus Torvalds * @flags: flags specifying attributes and the relation to other matches 3571da177e4SLinus Torvalds * @ops: the operations lookup table of the corresponding ematch module 3581da177e4SLinus Torvalds * @datalen: length of the ematch specific configuration data 3591da177e4SLinus Torvalds * @data: ematch specific data 3600161d151SBijie Xu * @net: the network namespace 3611da177e4SLinus Torvalds */ 362fd2c3ef7SEric Dumazet struct tcf_ematch { 3631da177e4SLinus Torvalds struct tcf_ematch_ops * ops; 3641da177e4SLinus Torvalds unsigned long data; 3651da177e4SLinus Torvalds unsigned int datalen; 3661da177e4SLinus Torvalds u16 matchid; 3671da177e4SLinus Torvalds u16 flags; 36882a470f1SJohn Fastabend struct net *net; 3691da177e4SLinus Torvalds }; 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds static inline int tcf_em_is_container(struct tcf_ematch *em) 3721da177e4SLinus Torvalds { 3731da177e4SLinus Torvalds return !em->ops; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds static inline int tcf_em_is_simple(struct tcf_ematch *em) 3771da177e4SLinus Torvalds { 3781da177e4SLinus Torvalds return em->flags & TCF_EM_SIMPLE; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds static inline int tcf_em_is_inverted(struct tcf_ematch *em) 3821da177e4SLinus Torvalds { 3831da177e4SLinus Torvalds return em->flags & TCF_EM_INVERT; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds static inline int tcf_em_last_match(struct tcf_ematch *em) 3871da177e4SLinus Torvalds { 3881da177e4SLinus Torvalds return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END; 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds static inline int tcf_em_early_end(struct tcf_ematch *em, int result) 3921da177e4SLinus Torvalds { 3931da177e4SLinus Torvalds if (tcf_em_last_match(em)) 3941da177e4SLinus Torvalds return 1; 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds if (result == 0 && em->flags & TCF_EM_REL_AND) 3971da177e4SLinus Torvalds return 1; 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds if (result != 0 && em->flags & TCF_EM_REL_OR) 4001da177e4SLinus Torvalds return 1; 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds return 0; 4031da177e4SLinus Torvalds } 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds /** 4061da177e4SLinus Torvalds * struct tcf_ematch_tree - ematch tree handle 4071da177e4SLinus Torvalds * 4081da177e4SLinus Torvalds * @hdr: ematch tree header supplied by userspace 4091da177e4SLinus Torvalds * @matches: array of ematches 4101da177e4SLinus Torvalds */ 411fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4121da177e4SLinus Torvalds struct tcf_ematch_tree_hdr hdr; 4131da177e4SLinus Torvalds struct tcf_ematch * matches; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds }; 4161da177e4SLinus Torvalds 4171da177e4SLinus Torvalds /** 4181da177e4SLinus Torvalds * struct tcf_ematch_ops - ematch module operations 4191da177e4SLinus Torvalds * 4201da177e4SLinus Torvalds * @kind: identifier (kind) of this ematch module 4211da177e4SLinus Torvalds * @datalen: length of expected configuration data (optional) 4221da177e4SLinus Torvalds * @change: called during validation (optional) 4231da177e4SLinus Torvalds * @match: called during ematch tree evaluation, must return 1/0 4241da177e4SLinus Torvalds * @destroy: called during destroyage (optional) 4251da177e4SLinus Torvalds * @dump: called during dumping process (optional) 4261da177e4SLinus Torvalds * @owner: owner, must be set to THIS_MODULE 4271da177e4SLinus Torvalds * @link: link to previous/next ematch module (internal use) 4281da177e4SLinus Torvalds */ 429fd2c3ef7SEric Dumazet struct tcf_ematch_ops { 4301da177e4SLinus Torvalds int kind; 4311da177e4SLinus Torvalds int datalen; 43282a470f1SJohn Fastabend int (*change)(struct net *net, void *, 4331da177e4SLinus Torvalds int, struct tcf_ematch *); 4341da177e4SLinus Torvalds int (*match)(struct sk_buff *, struct tcf_ematch *, 4351da177e4SLinus Torvalds struct tcf_pkt_info *); 43682a470f1SJohn Fastabend void (*destroy)(struct tcf_ematch *); 4371da177e4SLinus Torvalds int (*dump)(struct sk_buff *, struct tcf_ematch *); 4381da177e4SLinus Torvalds struct module *owner; 4391da177e4SLinus Torvalds struct list_head link; 4401da177e4SLinus Torvalds }; 4411da177e4SLinus Torvalds 4425c15257fSJoe Perches int tcf_em_register(struct tcf_ematch_ops *); 4435c15257fSJoe Perches void tcf_em_unregister(struct tcf_ematch_ops *); 4445c15257fSJoe Perches int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *, 4451da177e4SLinus Torvalds struct tcf_ematch_tree *); 44682a470f1SJohn Fastabend void tcf_em_tree_destroy(struct tcf_ematch_tree *); 4475c15257fSJoe Perches int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int); 4485c15257fSJoe Perches int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *, 4491da177e4SLinus Torvalds struct tcf_pkt_info *); 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds /** 4521da177e4SLinus Torvalds * tcf_em_tree_match - evaulate an ematch tree 4531da177e4SLinus Torvalds * 4541da177e4SLinus Torvalds * @skb: socket buffer of the packet in question 4551da177e4SLinus Torvalds * @tree: ematch tree to be used for evaluation 4561da177e4SLinus Torvalds * @info: packet information examined by classifier 4571da177e4SLinus Torvalds * 4581da177e4SLinus Torvalds * This function matches @skb against the ematch tree in @tree by going 4591da177e4SLinus Torvalds * through all ematches respecting their logic relations returning 4601da177e4SLinus Torvalds * as soon as the result is obvious. 4611da177e4SLinus Torvalds * 4621da177e4SLinus Torvalds * Returns 1 if the ematch tree as-one matches, no ematches are configured 4631da177e4SLinus Torvalds * or ematch is not enabled in the kernel, otherwise 0 is returned. 4641da177e4SLinus Torvalds */ 4651da177e4SLinus Torvalds static inline int tcf_em_tree_match(struct sk_buff *skb, 4661da177e4SLinus Torvalds struct tcf_ematch_tree *tree, 4671da177e4SLinus Torvalds struct tcf_pkt_info *info) 4681da177e4SLinus Torvalds { 4691da177e4SLinus Torvalds if (tree->hdr.nmatches) 4701da177e4SLinus Torvalds return __tcf_em_tree_match(skb, tree, info); 4711da177e4SLinus Torvalds else 4721da177e4SLinus Torvalds return 1; 4731da177e4SLinus Torvalds } 4741da177e4SLinus Torvalds 475db3d99c0SPatrick McHardy #define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind)) 476db3d99c0SPatrick McHardy 4771da177e4SLinus Torvalds #else /* CONFIG_NET_EMATCH */ 4781da177e4SLinus Torvalds 479fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4801da177e4SLinus Torvalds }; 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0) 48382a470f1SJohn Fastabend #define tcf_em_tree_destroy(t) do { (void)(t); } while(0) 4841da177e4SLinus Torvalds #define tcf_em_tree_dump(skb, t, tlv) (0) 4851da177e4SLinus Torvalds #define tcf_em_tree_match(skb, t, info) ((void)(info), 1) 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds #endif /* CONFIG_NET_EMATCH */ 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) 4901da177e4SLinus Torvalds { 4911da177e4SLinus Torvalds switch (layer) { 4921da177e4SLinus Torvalds case TCF_LAYER_LINK: 493d3303a65SWolfgang Bumiller return skb_mac_header(skb); 4941da177e4SLinus Torvalds case TCF_LAYER_NETWORK: 495d56f90a7SArnaldo Carvalho de Melo return skb_network_header(skb); 4961da177e4SLinus Torvalds case TCF_LAYER_TRANSPORT: 4979c70220bSArnaldo Carvalho de Melo return skb_transport_header(skb); 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds return NULL; 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds 503eddc9ec5SArnaldo Carvalho de Melo static inline int tcf_valid_offset(const struct sk_buff *skb, 504eddc9ec5SArnaldo Carvalho de Melo const unsigned char *ptr, const int len) 5051da177e4SLinus Torvalds { 506da521b2cSDavid S. Miller return likely((ptr + len) <= skb_tail_pointer(skb) && 507da521b2cSDavid S. Miller ptr >= skb->head && 508da521b2cSDavid S. Miller (ptr <= (ptr + len))); 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds static inline int 5121057c55fSAlexander Aring tcf_change_indev(struct net *net, struct nlattr *indev_tlv, 5131057c55fSAlexander Aring struct netlink_ext_ack *extack) 5141da177e4SLinus Torvalds { 5152519a602SWANG Cong char indev[IFNAMSIZ]; 516c01003c2SPatrick McHardy struct net_device *dev; 517c01003c2SPatrick McHardy 518872f6903SFrancis Laniel if (nla_strscpy(indev, indev_tlv, IFNAMSIZ) < 0) { 519e4a58ef3SGuillaume Nault NL_SET_ERR_MSG_ATTR(extack, indev_tlv, 520e4a58ef3SGuillaume Nault "Interface name too long"); 5212519a602SWANG Cong return -EINVAL; 5221057c55fSAlexander Aring } 5232519a602SWANG Cong dev = __dev_get_by_name(net, indev); 524e4a58ef3SGuillaume Nault if (!dev) { 525e4a58ef3SGuillaume Nault NL_SET_ERR_MSG_ATTR(extack, indev_tlv, 526e4a58ef3SGuillaume Nault "Network device not found"); 5272519a602SWANG Cong return -ENODEV; 528e4a58ef3SGuillaume Nault } 5292519a602SWANG Cong return dev->ifindex; 5301da177e4SLinus Torvalds } 5311da177e4SLinus Torvalds 5322519a602SWANG Cong static inline bool 5332519a602SWANG Cong tcf_match_indev(struct sk_buff *skb, int ifindex) 5342519a602SWANG Cong { 5352519a602SWANG Cong if (!ifindex) 5362519a602SWANG Cong return true; 5372519a602SWANG Cong if (!skb->skb_iif) 5382519a602SWANG Cong return false; 5392519a602SWANG Cong return ifindex == skb->skb_iif; 5401da177e4SLinus Torvalds } 5411da177e4SLinus Torvalds 5429c1c0e12SBaowen Zheng int tc_setup_offload_action(struct flow_action *flow_action, 543b15e7a6eSVlad Buslov const struct tcf_exts *exts); 5449c1c0e12SBaowen Zheng void tc_cleanup_offload_action(struct flow_action *flow_action); 545*8cbfe939SBaowen Zheng int tc_setup_action(struct flow_action *flow_action, 546*8cbfe939SBaowen Zheng struct tc_action *actions[]); 5475a6ff4b1SVlad Buslov 548aeb3fecdSCong Wang int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, 54940119211SVlad Buslov void *type_data, bool err_stop, bool rtnl_held); 55040119211SVlad Buslov int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp, 55140119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 55240119211SVlad Buslov u32 *flags, unsigned int *in_hw_count, bool rtnl_held); 55340119211SVlad Buslov int tc_setup_cb_replace(struct tcf_block *block, struct tcf_proto *tp, 55440119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 55540119211SVlad Buslov u32 *old_flags, unsigned int *old_in_hw_count, 55640119211SVlad Buslov u32 *new_flags, unsigned int *new_in_hw_count, 55740119211SVlad Buslov bool rtnl_held); 55840119211SVlad Buslov int tc_setup_cb_destroy(struct tcf_block *block, struct tcf_proto *tp, 55940119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 56040119211SVlad Buslov u32 *flags, unsigned int *in_hw_count, bool rtnl_held); 56140119211SVlad Buslov int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp, 56240119211SVlad Buslov bool add, flow_setup_cb_t *cb, 56340119211SVlad Buslov enum tc_setup_type type, void *type_data, 56440119211SVlad Buslov void *cb_priv, u32 *flags, unsigned int *in_hw_count); 565e3ab786bSPablo Neira Ayuso unsigned int tcf_exts_num_actions(struct tcf_exts *exts); 566717503b9SJiri Pirko 5673625750fSPetr Machata #ifdef CONFIG_NET_CLS_ACT 5683625750fSPetr Machata int tcf_qevent_init(struct tcf_qevent *qe, struct Qdisc *sch, 5693625750fSPetr Machata enum flow_block_binder_type binder_type, 5703625750fSPetr Machata struct nlattr *block_index_attr, 5713625750fSPetr Machata struct netlink_ext_ack *extack); 5723625750fSPetr Machata void tcf_qevent_destroy(struct tcf_qevent *qe, struct Qdisc *sch); 5733625750fSPetr Machata int tcf_qevent_validate_change(struct tcf_qevent *qe, struct nlattr *block_index_attr, 5743625750fSPetr Machata struct netlink_ext_ack *extack); 5753625750fSPetr Machata struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, struct sk_buff *skb, 57655f656cdSPetr Machata struct sk_buff **to_free, int *ret); 5773625750fSPetr Machata int tcf_qevent_dump(struct sk_buff *skb, int attr_name, struct tcf_qevent *qe); 5783625750fSPetr Machata #else 5793625750fSPetr Machata static inline int tcf_qevent_init(struct tcf_qevent *qe, struct Qdisc *sch, 5803625750fSPetr Machata enum flow_block_binder_type binder_type, 5813625750fSPetr Machata struct nlattr *block_index_attr, 5823625750fSPetr Machata struct netlink_ext_ack *extack) 5833625750fSPetr Machata { 5843625750fSPetr Machata return 0; 5853625750fSPetr Machata } 5863625750fSPetr Machata 5873625750fSPetr Machata static inline void tcf_qevent_destroy(struct tcf_qevent *qe, struct Qdisc *sch) 5883625750fSPetr Machata { 5893625750fSPetr Machata } 5903625750fSPetr Machata 5913625750fSPetr Machata static inline int tcf_qevent_validate_change(struct tcf_qevent *qe, struct nlattr *block_index_attr, 5923625750fSPetr Machata struct netlink_ext_ack *extack) 5933625750fSPetr Machata { 5943625750fSPetr Machata return 0; 5953625750fSPetr Machata } 5963625750fSPetr Machata 5973625750fSPetr Machata static inline struct sk_buff * 5983625750fSPetr Machata tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, struct sk_buff *skb, 59955f656cdSPetr Machata struct sk_buff **to_free, int *ret) 6003625750fSPetr Machata { 6013625750fSPetr Machata return skb; 6023625750fSPetr Machata } 6033625750fSPetr Machata 6043625750fSPetr Machata static inline int tcf_qevent_dump(struct sk_buff *skb, int attr_name, struct tcf_qevent *qe) 6053625750fSPetr Machata { 6063625750fSPetr Machata return 0; 6073625750fSPetr Machata } 6083625750fSPetr Machata #endif 6093625750fSPetr Machata 610a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode { 611a1b7c5fdSJohn Fastabend struct tcf_exts *exts; 612068ceb35SJakub Kicinski struct tcf_result *res; 613e014860eSJohn Fastabend struct tc_u32_sel *sel; 614a1b7c5fdSJohn Fastabend u32 handle; 615a1b7c5fdSJohn Fastabend u32 val; 616a1b7c5fdSJohn Fastabend u32 mask; 617a1b7c5fdSJohn Fastabend u32 link_handle; 618e014860eSJohn Fastabend u8 fshift; 619a1b7c5fdSJohn Fastabend }; 620a1b7c5fdSJohn Fastabend 621a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode { 622a1b7c5fdSJohn Fastabend u32 handle; 623a1b7c5fdSJohn Fastabend u32 prio; 624a1b7c5fdSJohn Fastabend unsigned int divisor; 625a1b7c5fdSJohn Fastabend }; 626a1b7c5fdSJohn Fastabend 627a1b7c5fdSJohn Fastabend enum tc_clsu32_command { 628a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_KNODE, 629a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_KNODE, 630a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_KNODE, 631a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_HNODE, 632a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_HNODE, 633a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_HNODE, 634a1b7c5fdSJohn Fastabend }; 635a1b7c5fdSJohn Fastabend 636a1b7c5fdSJohn Fastabend struct tc_cls_u32_offload { 637f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 638a1b7c5fdSJohn Fastabend /* knode values */ 639a1b7c5fdSJohn Fastabend enum tc_clsu32_command command; 640a1b7c5fdSJohn Fastabend union { 641a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode knode; 642a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode hnode; 643a1b7c5fdSJohn Fastabend }; 644a1b7c5fdSJohn Fastabend }; 645a1b7c5fdSJohn Fastabend 6467b06e8aeSJiri Pirko static inline bool tc_can_offload(const struct net_device *dev) 6476843e7a2SJohn Fastabend { 64870b5aee4SJiri Pirko return dev->features & NETIF_F_HW_TC; 6496843e7a2SJohn Fastabend } 6506843e7a2SJohn Fastabend 651f9eda14fSQuentin Monnet static inline bool tc_can_offload_extack(const struct net_device *dev, 652f9eda14fSQuentin Monnet struct netlink_ext_ack *extack) 653f9eda14fSQuentin Monnet { 654f9eda14fSQuentin Monnet bool can = tc_can_offload(dev); 655f9eda14fSQuentin Monnet 656f9eda14fSQuentin Monnet if (!can) 657f9eda14fSQuentin Monnet NL_SET_ERR_MSG(extack, "TC offload is disabled on net device"); 658f9eda14fSQuentin Monnet 659f9eda14fSQuentin Monnet return can; 660f9eda14fSQuentin Monnet } 661f9eda14fSQuentin Monnet 662878db9f0SJakub Kicinski static inline bool 663878db9f0SJakub Kicinski tc_cls_can_offload_and_chain0(const struct net_device *dev, 664f9e30088SPablo Neira Ayuso struct flow_cls_common_offload *common) 665878db9f0SJakub Kicinski { 666878db9f0SJakub Kicinski if (!tc_can_offload_extack(dev, common->extack)) 667878db9f0SJakub Kicinski return false; 668878db9f0SJakub Kicinski if (common->chain_index) { 669878db9f0SJakub Kicinski NL_SET_ERR_MSG(common->extack, 670878db9f0SJakub Kicinski "Driver supports only offload of chain 0"); 671878db9f0SJakub Kicinski return false; 672878db9f0SJakub Kicinski } 673878db9f0SJakub Kicinski return true; 674878db9f0SJakub Kicinski } 675878db9f0SJakub Kicinski 67655330f05SHadar Hen Zion static inline bool tc_skip_hw(u32 flags) 67755330f05SHadar Hen Zion { 67855330f05SHadar Hen Zion return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; 67955330f05SHadar Hen Zion } 68055330f05SHadar Hen Zion 681d34e3e18SSamudrala, Sridhar static inline bool tc_skip_sw(u32 flags) 682d34e3e18SSamudrala, Sridhar { 683d34e3e18SSamudrala, Sridhar return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false; 684d34e3e18SSamudrala, Sridhar } 685d34e3e18SSamudrala, Sridhar 686d34e3e18SSamudrala, Sridhar /* SKIP_HW and SKIP_SW are mutually exclusive flags. */ 687d34e3e18SSamudrala, Sridhar static inline bool tc_flags_valid(u32 flags) 688d34e3e18SSamudrala, Sridhar { 68981c7288bSMarcelo Ricardo Leitner if (flags & ~(TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW | 69081c7288bSMarcelo Ricardo Leitner TCA_CLS_FLAGS_VERBOSE)) 691d34e3e18SSamudrala, Sridhar return false; 692d34e3e18SSamudrala, Sridhar 69381c7288bSMarcelo Ricardo Leitner flags &= TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW; 694d34e3e18SSamudrala, Sridhar if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW))) 695d34e3e18SSamudrala, Sridhar return false; 696d34e3e18SSamudrala, Sridhar 697d34e3e18SSamudrala, Sridhar return true; 698d34e3e18SSamudrala, Sridhar } 699d34e3e18SSamudrala, Sridhar 700e696028aSOr Gerlitz static inline bool tc_in_hw(u32 flags) 701e696028aSOr Gerlitz { 702e696028aSOr Gerlitz return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; 703e696028aSOr Gerlitz } 704e696028aSOr Gerlitz 70534832e1cSJakub Kicinski static inline void 706f9e30088SPablo Neira Ayuso tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common, 70734832e1cSJakub Kicinski const struct tcf_proto *tp, u32 flags, 70834832e1cSJakub Kicinski struct netlink_ext_ack *extack) 70934832e1cSJakub Kicinski { 71034832e1cSJakub Kicinski cls_common->chain_index = tp->chain->index; 71134832e1cSJakub Kicinski cls_common->protocol = tp->protocol; 712ef01adaeSPablo Neira Ayuso cls_common->prio = tp->prio >> 16; 71381c7288bSMarcelo Ricardo Leitner if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE) 71434832e1cSJakub Kicinski cls_common->extack = extack; 71534832e1cSJakub Kicinski } 71634832e1cSJakub Kicinski 7179453d45eSVlad Buslov #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) 7189453d45eSVlad Buslov static inline struct tc_skb_ext *tc_skb_ext_alloc(struct sk_buff *skb) 7199453d45eSVlad Buslov { 7209453d45eSVlad Buslov struct tc_skb_ext *tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT); 7219453d45eSVlad Buslov 7229453d45eSVlad Buslov if (tc_skb_ext) 7239453d45eSVlad Buslov memset(tc_skb_ext, 0, sizeof(*tc_skb_ext)); 7249453d45eSVlad Buslov return tc_skb_ext; 7259453d45eSVlad Buslov } 7269453d45eSVlad Buslov #endif 7279453d45eSVlad Buslov 728b87f7936SYotam Gigi enum tc_matchall_command { 729b87f7936SYotam Gigi TC_CLSMATCHALL_REPLACE, 730b87f7936SYotam Gigi TC_CLSMATCHALL_DESTROY, 731b7fe4ab8SPieter Jansen van Vuuren TC_CLSMATCHALL_STATS, 732b87f7936SYotam Gigi }; 733b87f7936SYotam Gigi 734b87f7936SYotam Gigi struct tc_cls_matchall_offload { 735f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 736b87f7936SYotam Gigi enum tc_matchall_command command; 737f00cbf19SPieter Jansen van Vuuren struct flow_rule *rule; 738b7fe4ab8SPieter Jansen van Vuuren struct flow_stats stats; 739b87f7936SYotam Gigi unsigned long cookie; 740b87f7936SYotam Gigi }; 741b87f7936SYotam Gigi 742332ae8e2SJakub Kicinski enum tc_clsbpf_command { 743102740bdSJakub Kicinski TC_CLSBPF_OFFLOAD, 74468d64063SJakub Kicinski TC_CLSBPF_STATS, 745332ae8e2SJakub Kicinski }; 746332ae8e2SJakub Kicinski 747332ae8e2SJakub Kicinski struct tc_cls_bpf_offload { 748f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 749332ae8e2SJakub Kicinski enum tc_clsbpf_command command; 750332ae8e2SJakub Kicinski struct tcf_exts *exts; 751332ae8e2SJakub Kicinski struct bpf_prog *prog; 752102740bdSJakub Kicinski struct bpf_prog *oldprog; 753332ae8e2SJakub Kicinski const char *name; 754332ae8e2SJakub Kicinski bool exts_integrated; 755332ae8e2SJakub Kicinski }; 756332ae8e2SJakub Kicinski 7574e8b86c0SAmritha Nambiar struct tc_mqprio_qopt_offload { 7584e8b86c0SAmritha Nambiar /* struct tc_mqprio_qopt must always be the first element */ 7594e8b86c0SAmritha Nambiar struct tc_mqprio_qopt qopt; 7604e8b86c0SAmritha Nambiar u16 mode; 7614e8b86c0SAmritha Nambiar u16 shaper; 7624e8b86c0SAmritha Nambiar u32 flags; 7634e8b86c0SAmritha Nambiar u64 min_rate[TC_QOPT_MAX_QUEUE]; 7644e8b86c0SAmritha Nambiar u64 max_rate[TC_QOPT_MAX_QUEUE]; 7654e8b86c0SAmritha Nambiar }; 7661045ba77SJamal Hadi Salim 7671045ba77SJamal Hadi Salim /* This structure holds cookie structure that is passed from user 7681045ba77SJamal Hadi Salim * to the kernel for actions and classifiers 7691045ba77SJamal Hadi Salim */ 7701045ba77SJamal Hadi Salim struct tc_cookie { 7711045ba77SJamal Hadi Salim u8 *data; 7721045ba77SJamal Hadi Salim u32 len; 773eec94fdbSVlad Buslov struct rcu_head rcu; 7741045ba77SJamal Hadi Salim }; 775602f3bafSNogah Frankel 776f34b4aacSNogah Frankel struct tc_qopt_offload_stats { 77750dc9a85SAhmed S. Darwish struct gnet_stats_basic_sync *bstats; 778f34b4aacSNogah Frankel struct gnet_stats_queue *qstats; 779f34b4aacSNogah Frankel }; 780f34b4aacSNogah Frankel 781f971b132SJakub Kicinski enum tc_mq_command { 782f971b132SJakub Kicinski TC_MQ_CREATE, 783f971b132SJakub Kicinski TC_MQ_DESTROY, 78447c669a4SJakub Kicinski TC_MQ_STATS, 785d577a3d2SJakub Kicinski TC_MQ_GRAFT, 786d577a3d2SJakub Kicinski }; 787d577a3d2SJakub Kicinski 788d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params { 789d577a3d2SJakub Kicinski unsigned long queue; 790d577a3d2SJakub Kicinski u32 child_handle; 791f971b132SJakub Kicinski }; 792f971b132SJakub Kicinski 793f971b132SJakub Kicinski struct tc_mq_qopt_offload { 794f971b132SJakub Kicinski enum tc_mq_command command; 795f971b132SJakub Kicinski u32 handle; 796d577a3d2SJakub Kicinski union { 79747c669a4SJakub Kicinski struct tc_qopt_offload_stats stats; 798d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params graft_params; 799d577a3d2SJakub Kicinski }; 800f971b132SJakub Kicinski }; 801f971b132SJakub Kicinski 802d03b195bSMaxim Mikityanskiy enum tc_htb_command { 803d03b195bSMaxim Mikityanskiy /* Root */ 804d03b195bSMaxim Mikityanskiy TC_HTB_CREATE, /* Initialize HTB offload. */ 805d03b195bSMaxim Mikityanskiy TC_HTB_DESTROY, /* Destroy HTB offload. */ 806d03b195bSMaxim Mikityanskiy 807d03b195bSMaxim Mikityanskiy /* Classes */ 808d03b195bSMaxim Mikityanskiy /* Allocate qid and create leaf. */ 809d03b195bSMaxim Mikityanskiy TC_HTB_LEAF_ALLOC_QUEUE, 810d03b195bSMaxim Mikityanskiy /* Convert leaf to inner, preserve and return qid, create new leaf. */ 811d03b195bSMaxim Mikityanskiy TC_HTB_LEAF_TO_INNER, 812d03b195bSMaxim Mikityanskiy /* Delete leaf, while siblings remain. */ 813d03b195bSMaxim Mikityanskiy TC_HTB_LEAF_DEL, 814d03b195bSMaxim Mikityanskiy /* Delete leaf, convert parent to leaf, preserving qid. */ 815d03b195bSMaxim Mikityanskiy TC_HTB_LEAF_DEL_LAST, 816d03b195bSMaxim Mikityanskiy /* TC_HTB_LEAF_DEL_LAST, but delete driver data on hardware errors. */ 817d03b195bSMaxim Mikityanskiy TC_HTB_LEAF_DEL_LAST_FORCE, 818d03b195bSMaxim Mikityanskiy /* Modify parameters of a node. */ 819d03b195bSMaxim Mikityanskiy TC_HTB_NODE_MODIFY, 820d03b195bSMaxim Mikityanskiy 821d03b195bSMaxim Mikityanskiy /* Class qdisc */ 822d03b195bSMaxim Mikityanskiy TC_HTB_LEAF_QUERY_QUEUE, /* Query qid by classid. */ 823d03b195bSMaxim Mikityanskiy }; 824d03b195bSMaxim Mikityanskiy 825d03b195bSMaxim Mikityanskiy struct tc_htb_qopt_offload { 826d03b195bSMaxim Mikityanskiy struct netlink_ext_ack *extack; 827d03b195bSMaxim Mikityanskiy enum tc_htb_command command; 828d03b195bSMaxim Mikityanskiy u32 parent_classid; 829ca49bfd9SMaxim Mikityanskiy u16 classid; 830d03b195bSMaxim Mikityanskiy u16 qid; 831d03b195bSMaxim Mikityanskiy u64 rate; 832d03b195bSMaxim Mikityanskiy u64 ceil; 833d03b195bSMaxim Mikityanskiy }; 834d03b195bSMaxim Mikityanskiy 835d03b195bSMaxim Mikityanskiy #define TC_HTB_CLASSID_ROOT U32_MAX 836d03b195bSMaxim Mikityanskiy 837602f3bafSNogah Frankel enum tc_red_command { 838602f3bafSNogah Frankel TC_RED_REPLACE, 839602f3bafSNogah Frankel TC_RED_DESTROY, 840602f3bafSNogah Frankel TC_RED_STATS, 841602f3bafSNogah Frankel TC_RED_XSTATS, 842bf2a752bSJakub Kicinski TC_RED_GRAFT, 843602f3bafSNogah Frankel }; 844602f3bafSNogah Frankel 845602f3bafSNogah Frankel struct tc_red_qopt_offload_params { 846602f3bafSNogah Frankel u32 min; 847602f3bafSNogah Frankel u32 max; 848602f3bafSNogah Frankel u32 probability; 849c0b7490bSJakub Kicinski u32 limit; 850602f3bafSNogah Frankel bool is_ecn; 851190852a5SJakub Kicinski bool is_harddrop; 8520a7fad23SPetr Machata bool is_nodrop; 853416ef9b1SJakub Kicinski struct gnet_stats_queue *qstats; 854602f3bafSNogah Frankel }; 855602f3bafSNogah Frankel 856602f3bafSNogah Frankel struct tc_red_qopt_offload { 857602f3bafSNogah Frankel enum tc_red_command command; 858602f3bafSNogah Frankel u32 handle; 859602f3bafSNogah Frankel u32 parent; 860602f3bafSNogah Frankel union { 861602f3bafSNogah Frankel struct tc_red_qopt_offload_params set; 862f34b4aacSNogah Frankel struct tc_qopt_offload_stats stats; 863602f3bafSNogah Frankel struct red_stats *xstats; 864bf2a752bSJakub Kicinski u32 child_handle; 865602f3bafSNogah Frankel }; 866602f3bafSNogah Frankel }; 867602f3bafSNogah Frankel 868890d8d23SJakub Kicinski enum tc_gred_command { 869890d8d23SJakub Kicinski TC_GRED_REPLACE, 870890d8d23SJakub Kicinski TC_GRED_DESTROY, 871e49efd52SJakub Kicinski TC_GRED_STATS, 872890d8d23SJakub Kicinski }; 873890d8d23SJakub Kicinski 874890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params { 875890d8d23SJakub Kicinski bool present; 876890d8d23SJakub Kicinski u32 limit; 877890d8d23SJakub Kicinski u32 prio; 878890d8d23SJakub Kicinski u32 min; 879890d8d23SJakub Kicinski u32 max; 880890d8d23SJakub Kicinski bool is_ecn; 881890d8d23SJakub Kicinski bool is_harddrop; 882890d8d23SJakub Kicinski u32 probability; 883890d8d23SJakub Kicinski /* Only need backlog, see struct tc_prio_qopt_offload_params */ 884890d8d23SJakub Kicinski u32 *backlog; 885890d8d23SJakub Kicinski }; 886890d8d23SJakub Kicinski 887890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params { 888890d8d23SJakub Kicinski bool grio_on; 889890d8d23SJakub Kicinski bool wred_on; 890890d8d23SJakub Kicinski unsigned int dp_cnt; 891890d8d23SJakub Kicinski unsigned int dp_def; 892890d8d23SJakub Kicinski struct gnet_stats_queue *qstats; 893890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params tab[MAX_DPs]; 894890d8d23SJakub Kicinski }; 895890d8d23SJakub Kicinski 896e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats { 89750dc9a85SAhmed S. Darwish struct gnet_stats_basic_sync bstats[MAX_DPs]; 898e49efd52SJakub Kicinski struct gnet_stats_queue qstats[MAX_DPs]; 899e49efd52SJakub Kicinski struct red_stats *xstats[MAX_DPs]; 900e49efd52SJakub Kicinski }; 901e49efd52SJakub Kicinski 902890d8d23SJakub Kicinski struct tc_gred_qopt_offload { 903890d8d23SJakub Kicinski enum tc_gred_command command; 904890d8d23SJakub Kicinski u32 handle; 905890d8d23SJakub Kicinski u32 parent; 906890d8d23SJakub Kicinski union { 907890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params set; 908e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats stats; 909890d8d23SJakub Kicinski }; 910890d8d23SJakub Kicinski }; 911890d8d23SJakub Kicinski 9127fdb61b4SNogah Frankel enum tc_prio_command { 9137fdb61b4SNogah Frankel TC_PRIO_REPLACE, 9147fdb61b4SNogah Frankel TC_PRIO_DESTROY, 9157fdb61b4SNogah Frankel TC_PRIO_STATS, 916b9c7a7acSNogah Frankel TC_PRIO_GRAFT, 9177fdb61b4SNogah Frankel }; 9187fdb61b4SNogah Frankel 9197fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params { 9207fdb61b4SNogah Frankel int bands; 9217fdb61b4SNogah Frankel u8 priomap[TC_PRIO_MAX + 1]; 9229586a992SPetr Machata /* At the point of un-offloading the Qdisc, the reported backlog and 9239586a992SPetr Machata * qlen need to be reduced by the portion that is in HW. 9247fdb61b4SNogah Frankel */ 9257fdb61b4SNogah Frankel struct gnet_stats_queue *qstats; 9267fdb61b4SNogah Frankel }; 9277fdb61b4SNogah Frankel 928b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params { 929b9c7a7acSNogah Frankel u8 band; 930b9c7a7acSNogah Frankel u32 child_handle; 931b9c7a7acSNogah Frankel }; 932b9c7a7acSNogah Frankel 9337fdb61b4SNogah Frankel struct tc_prio_qopt_offload { 9347fdb61b4SNogah Frankel enum tc_prio_command command; 9357fdb61b4SNogah Frankel u32 handle; 9367fdb61b4SNogah Frankel u32 parent; 9377fdb61b4SNogah Frankel union { 9387fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params replace_params; 9397fdb61b4SNogah Frankel struct tc_qopt_offload_stats stats; 940b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params graft_params; 9417fdb61b4SNogah Frankel }; 9427fdb61b4SNogah Frankel }; 943b9c7a7acSNogah Frankel 94498b0e5f6SJakub Kicinski enum tc_root_command { 94598b0e5f6SJakub Kicinski TC_ROOT_GRAFT, 94698b0e5f6SJakub Kicinski }; 94798b0e5f6SJakub Kicinski 94898b0e5f6SJakub Kicinski struct tc_root_qopt_offload { 94998b0e5f6SJakub Kicinski enum tc_root_command command; 95098b0e5f6SJakub Kicinski u32 handle; 95198b0e5f6SJakub Kicinski bool ingress; 95298b0e5f6SJakub Kicinski }; 95398b0e5f6SJakub Kicinski 954d35eb52bSPetr Machata enum tc_ets_command { 955d35eb52bSPetr Machata TC_ETS_REPLACE, 956d35eb52bSPetr Machata TC_ETS_DESTROY, 957d35eb52bSPetr Machata TC_ETS_STATS, 958d35eb52bSPetr Machata TC_ETS_GRAFT, 959d35eb52bSPetr Machata }; 960d35eb52bSPetr Machata 961d35eb52bSPetr Machata struct tc_ets_qopt_offload_replace_params { 962d35eb52bSPetr Machata unsigned int bands; 963d35eb52bSPetr Machata u8 priomap[TC_PRIO_MAX + 1]; 964d35eb52bSPetr Machata unsigned int quanta[TCQ_ETS_MAX_BANDS]; /* 0 for strict bands. */ 965d35eb52bSPetr Machata unsigned int weights[TCQ_ETS_MAX_BANDS]; 966d35eb52bSPetr Machata struct gnet_stats_queue *qstats; 967d35eb52bSPetr Machata }; 968d35eb52bSPetr Machata 969d35eb52bSPetr Machata struct tc_ets_qopt_offload_graft_params { 970d35eb52bSPetr Machata u8 band; 971d35eb52bSPetr Machata u32 child_handle; 972d35eb52bSPetr Machata }; 973d35eb52bSPetr Machata 974d35eb52bSPetr Machata struct tc_ets_qopt_offload { 975d35eb52bSPetr Machata enum tc_ets_command command; 976d35eb52bSPetr Machata u32 handle; 977d35eb52bSPetr Machata u32 parent; 978d35eb52bSPetr Machata union { 979d35eb52bSPetr Machata struct tc_ets_qopt_offload_replace_params replace_params; 980d35eb52bSPetr Machata struct tc_qopt_offload_stats stats; 981d35eb52bSPetr Machata struct tc_ets_qopt_offload_graft_params graft_params; 982d35eb52bSPetr Machata }; 983d35eb52bSPetr Machata }; 984d35eb52bSPetr Machata 985ef6aadccSPetr Machata enum tc_tbf_command { 986ef6aadccSPetr Machata TC_TBF_REPLACE, 987ef6aadccSPetr Machata TC_TBF_DESTROY, 988ef6aadccSPetr Machata TC_TBF_STATS, 9896b3efbfaSPetr Machata TC_TBF_GRAFT, 990ef6aadccSPetr Machata }; 991ef6aadccSPetr Machata 992ef6aadccSPetr Machata struct tc_tbf_qopt_offload_replace_params { 993ef6aadccSPetr Machata struct psched_ratecfg rate; 994ef6aadccSPetr Machata u32 max_size; 995ef6aadccSPetr Machata struct gnet_stats_queue *qstats; 996ef6aadccSPetr Machata }; 997ef6aadccSPetr Machata 998ef6aadccSPetr Machata struct tc_tbf_qopt_offload { 999ef6aadccSPetr Machata enum tc_tbf_command command; 1000ef6aadccSPetr Machata u32 handle; 1001ef6aadccSPetr Machata u32 parent; 1002ef6aadccSPetr Machata union { 1003ef6aadccSPetr Machata struct tc_tbf_qopt_offload_replace_params replace_params; 1004ef6aadccSPetr Machata struct tc_qopt_offload_stats stats; 10056b3efbfaSPetr Machata u32 child_handle; 1006ef6aadccSPetr Machata }; 1007ef6aadccSPetr Machata }; 1008ef6aadccSPetr Machata 1009aaca9408SPetr Machata enum tc_fifo_command { 1010aaca9408SPetr Machata TC_FIFO_REPLACE, 1011aaca9408SPetr Machata TC_FIFO_DESTROY, 1012aaca9408SPetr Machata TC_FIFO_STATS, 1013aaca9408SPetr Machata }; 1014aaca9408SPetr Machata 1015aaca9408SPetr Machata struct tc_fifo_qopt_offload { 1016aaca9408SPetr Machata enum tc_fifo_command command; 1017aaca9408SPetr Machata u32 handle; 1018aaca9408SPetr Machata u32 parent; 1019aaca9408SPetr Machata union { 1020aaca9408SPetr Machata struct tc_qopt_offload_stats stats; 1021aaca9408SPetr Machata }; 1022aaca9408SPetr Machata }; 1023aaca9408SPetr Machata 10241da177e4SLinus Torvalds #endif 1025