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> 98f256622SPablo Neira Ayuso #include <net/flow_offload.h> 101da177e4SLinus Torvalds 11cd11b164SPaolo Abeni /* TC action not accessible from user space */ 12cd11b164SPaolo Abeni #define TC_ACT_REINSERT (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; 2001683a14SVlad Buslov unsigned long cookie; 218113c095SWANG Cong int (*fn)(struct tcf_proto *, void *node, struct tcf_walker *); 221da177e4SLinus Torvalds }; 231da177e4SLinus Torvalds 245c15257fSJoe Perches int register_tcf_proto_ops(struct tcf_proto_ops *ops); 255c15257fSJoe Perches int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); 261da177e4SLinus Torvalds 278c4083b3SJiri Pirko enum tcf_block_binder_type { 288c4083b3SJiri Pirko TCF_BLOCK_BINDER_TYPE_UNSPEC, 296e40cf2dSJiri Pirko TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS, 306e40cf2dSJiri Pirko TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS, 318c4083b3SJiri Pirko }; 328c4083b3SJiri Pirko 338c4083b3SJiri Pirko struct tcf_block_ext_info { 348c4083b3SJiri Pirko enum tcf_block_binder_type binder_type; 35c7eb7d72SJiri Pirko tcf_chain_head_change_t *chain_head_change; 36c7eb7d72SJiri Pirko void *chain_head_change_priv; 3748617387SJiri Pirko u32 block_index; 388c4083b3SJiri Pirko }; 398c4083b3SJiri Pirko 40acb67442SJiri Pirko struct tcf_block_cb; 41aaa908ffSCong Wang bool tcf_queue_work(struct rcu_work *rwork, work_func_t func); 42acb67442SJiri Pirko 438ae70032SJiri Pirko #ifdef CONFIG_NET_CLS 441f3ed383SJiri Pirko struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, 451f3ed383SJiri Pirko u32 chain_index); 461f3ed383SJiri Pirko void tcf_chain_put_by_act(struct tcf_chain *chain); 47f36fe1c4SJiri Pirko void tcf_block_netif_keep_dst(struct tcf_block *block); 486529eabaSJiri Pirko int tcf_block_get(struct tcf_block **p_block, 498d1a77f9SAlexander Aring struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 508d1a77f9SAlexander Aring struct netlink_ext_ack *extack); 51c7eb7d72SJiri Pirko int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 528d1a77f9SAlexander Aring struct tcf_block_ext_info *ei, 538d1a77f9SAlexander Aring struct netlink_ext_ack *extack); 546529eabaSJiri Pirko void tcf_block_put(struct tcf_block *block); 55c7eb7d72SJiri Pirko void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 568c4083b3SJiri Pirko struct tcf_block_ext_info *ei); 5744186460SJiri Pirko 5848617387SJiri Pirko static inline bool tcf_block_shared(struct tcf_block *block) 5948617387SJiri Pirko { 6048617387SJiri Pirko return block->index; 6148617387SJiri Pirko } 6248617387SJiri Pirko 6344186460SJiri Pirko static inline struct Qdisc *tcf_block_q(struct tcf_block *block) 6444186460SJiri Pirko { 6548617387SJiri Pirko WARN_ON(tcf_block_shared(block)); 6644186460SJiri Pirko return block->q; 6744186460SJiri Pirko } 6844186460SJiri Pirko 69acb67442SJiri Pirko void *tcf_block_cb_priv(struct tcf_block_cb *block_cb); 70acb67442SJiri Pirko struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block, 71acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident); 72acb67442SJiri Pirko void tcf_block_cb_incref(struct tcf_block_cb *block_cb); 73acb67442SJiri Pirko unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb); 74acb67442SJiri Pirko struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block, 75acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident, 7660513bd8SJohn Hurley void *cb_priv, 7760513bd8SJohn Hurley struct netlink_ext_ack *extack); 78acb67442SJiri Pirko int tcf_block_cb_register(struct tcf_block *block, 79acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident, 8060513bd8SJohn Hurley void *cb_priv, struct netlink_ext_ack *extack); 8132636742SJohn Hurley void __tcf_block_cb_unregister(struct tcf_block *block, 8232636742SJohn Hurley struct tcf_block_cb *block_cb); 83acb67442SJiri Pirko void tcf_block_cb_unregister(struct tcf_block *block, 84acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident); 857f76fa36SJohn Hurley int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, 867f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident); 877f76fa36SJohn Hurley int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, 887f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident); 897f76fa36SJohn Hurley void __tc_indr_block_cb_unregister(struct net_device *dev, 907f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident); 917f76fa36SJohn Hurley void tc_indr_block_cb_unregister(struct net_device *dev, 927f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident); 93acb67442SJiri Pirko 9487d83093SJiri Pirko int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, 9587d83093SJiri Pirko struct tcf_result *res, bool compat_mode); 9687d83093SJiri Pirko 978ae70032SJiri Pirko #else 986529eabaSJiri Pirko static inline 996529eabaSJiri Pirko int tcf_block_get(struct tcf_block **p_block, 1003c149091SSudip Mukherjee struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 1013c149091SSudip Mukherjee struct netlink_ext_ack *extack) 1026529eabaSJiri Pirko { 1036529eabaSJiri Pirko return 0; 1046529eabaSJiri Pirko } 1056529eabaSJiri Pirko 1068c4083b3SJiri Pirko static inline 107c7eb7d72SJiri Pirko int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 10833c30a8bSQuentin Monnet struct tcf_block_ext_info *ei, 10933c30a8bSQuentin Monnet struct netlink_ext_ack *extack) 1108c4083b3SJiri Pirko { 1118c4083b3SJiri Pirko return 0; 1128c4083b3SJiri Pirko } 1138c4083b3SJiri Pirko 1146529eabaSJiri Pirko static inline void tcf_block_put(struct tcf_block *block) 1158ae70032SJiri Pirko { 1168ae70032SJiri Pirko } 11787d83093SJiri Pirko 1188c4083b3SJiri Pirko static inline 119c7eb7d72SJiri Pirko void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 1208c4083b3SJiri Pirko struct tcf_block_ext_info *ei) 1218c4083b3SJiri Pirko { 1228c4083b3SJiri Pirko } 1238c4083b3SJiri Pirko 12444186460SJiri Pirko static inline struct Qdisc *tcf_block_q(struct tcf_block *block) 12544186460SJiri Pirko { 12644186460SJiri Pirko return NULL; 12744186460SJiri Pirko } 12844186460SJiri Pirko 129acb67442SJiri Pirko static inline 130acb67442SJiri Pirko int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb, 131acb67442SJiri Pirko void *cb_priv) 132acb67442SJiri Pirko { 133acb67442SJiri Pirko return 0; 134acb67442SJiri Pirko } 135acb67442SJiri Pirko 136acb67442SJiri Pirko static inline 137acb67442SJiri Pirko void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb, 138acb67442SJiri Pirko void *cb_priv) 139acb67442SJiri Pirko { 140acb67442SJiri Pirko } 141acb67442SJiri Pirko 142acb67442SJiri Pirko static inline 143acb67442SJiri Pirko void *tcf_block_cb_priv(struct tcf_block_cb *block_cb) 144acb67442SJiri Pirko { 145acb67442SJiri Pirko return NULL; 146acb67442SJiri Pirko } 147acb67442SJiri Pirko 148acb67442SJiri Pirko static inline 149acb67442SJiri Pirko struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block, 150acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident) 151acb67442SJiri Pirko { 152acb67442SJiri Pirko return NULL; 153acb67442SJiri Pirko } 154acb67442SJiri Pirko 155acb67442SJiri Pirko static inline 156acb67442SJiri Pirko void tcf_block_cb_incref(struct tcf_block_cb *block_cb) 157acb67442SJiri Pirko { 158acb67442SJiri Pirko } 159acb67442SJiri Pirko 160acb67442SJiri Pirko static inline 161acb67442SJiri Pirko unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb) 162acb67442SJiri Pirko { 163acb67442SJiri Pirko return 0; 164acb67442SJiri Pirko } 165acb67442SJiri Pirko 166acb67442SJiri Pirko static inline 167acb67442SJiri Pirko struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block, 168acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident, 16960513bd8SJohn Hurley void *cb_priv, 17060513bd8SJohn Hurley struct netlink_ext_ack *extack) 171acb67442SJiri Pirko { 172acb67442SJiri Pirko return NULL; 173acb67442SJiri Pirko } 174acb67442SJiri Pirko 175acb67442SJiri Pirko static inline 176acb67442SJiri Pirko int tcf_block_cb_register(struct tcf_block *block, 177acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident, 17860513bd8SJohn Hurley void *cb_priv, struct netlink_ext_ack *extack) 179acb67442SJiri Pirko { 180acb67442SJiri Pirko return 0; 181acb67442SJiri Pirko } 182acb67442SJiri Pirko 183acb67442SJiri Pirko static inline 18432636742SJohn Hurley void __tcf_block_cb_unregister(struct tcf_block *block, 18532636742SJohn Hurley struct tcf_block_cb *block_cb) 186acb67442SJiri Pirko { 187acb67442SJiri Pirko } 188acb67442SJiri Pirko 189acb67442SJiri Pirko static inline 190acb67442SJiri Pirko void tcf_block_cb_unregister(struct tcf_block *block, 191acb67442SJiri Pirko tc_setup_cb_t *cb, void *cb_ident) 192acb67442SJiri Pirko { 193acb67442SJiri Pirko } 194acb67442SJiri Pirko 1957f76fa36SJohn Hurley static inline 1967f76fa36SJohn Hurley int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, 1977f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident) 1987f76fa36SJohn Hurley { 1997f76fa36SJohn Hurley return 0; 2007f76fa36SJohn Hurley } 2017f76fa36SJohn Hurley 2027f76fa36SJohn Hurley static inline 2037f76fa36SJohn Hurley int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, 2047f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident) 2057f76fa36SJohn Hurley { 2067f76fa36SJohn Hurley return 0; 2077f76fa36SJohn Hurley } 2087f76fa36SJohn Hurley 2097f76fa36SJohn Hurley static inline 2107f76fa36SJohn Hurley void __tc_indr_block_cb_unregister(struct net_device *dev, 2117f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident) 2127f76fa36SJohn Hurley { 2137f76fa36SJohn Hurley } 2147f76fa36SJohn Hurley 2157f76fa36SJohn Hurley static inline 2167f76fa36SJohn Hurley void tc_indr_block_cb_unregister(struct net_device *dev, 2177f76fa36SJohn Hurley tc_indr_block_bind_cb_t *cb, void *cb_ident) 2187f76fa36SJohn Hurley { 2197f76fa36SJohn Hurley } 2207f76fa36SJohn Hurley 22187d83093SJiri Pirko static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, 22287d83093SJiri Pirko struct tcf_result *res, bool compat_mode) 22387d83093SJiri Pirko { 22487d83093SJiri Pirko return TC_ACT_UNSPEC; 22587d83093SJiri Pirko } 2268ae70032SJiri Pirko #endif 227cf1facdaSJiri Pirko 2281da177e4SLinus Torvalds static inline unsigned long 2291da177e4SLinus Torvalds __cls_set_class(unsigned long *clp, unsigned long cl) 2301da177e4SLinus Torvalds { 231a0efb80cSWANG Cong return xchg(clp, cl); 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds static inline unsigned long 23534e3759cSJiri Pirko cls_set_class(struct Qdisc *q, unsigned long *clp, unsigned long cl) 2361da177e4SLinus Torvalds { 2371da177e4SLinus Torvalds unsigned long old_cl; 2381da177e4SLinus Torvalds 23934e3759cSJiri Pirko sch_tree_lock(q); 2401da177e4SLinus Torvalds old_cl = __cls_set_class(clp, cl); 24134e3759cSJiri Pirko sch_tree_unlock(q); 2421da177e4SLinus Torvalds return old_cl; 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds static inline void 2461da177e4SLinus Torvalds tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base) 2471da177e4SLinus Torvalds { 24834e3759cSJiri Pirko struct Qdisc *q = tp->chain->block->q; 2491da177e4SLinus Torvalds unsigned long cl; 2501da177e4SLinus Torvalds 25134e3759cSJiri Pirko /* Check q as it is not set for shared blocks. In that case, 25234e3759cSJiri Pirko * setting class is not supported. 25334e3759cSJiri Pirko */ 25434e3759cSJiri Pirko if (!q) 25534e3759cSJiri Pirko return; 25634e3759cSJiri Pirko cl = q->ops->cl_ops->bind_tcf(q, base, r->classid); 25734e3759cSJiri Pirko cl = cls_set_class(q, &r->class, cl); 2581da177e4SLinus Torvalds if (cl) 25934e3759cSJiri Pirko q->ops->cl_ops->unbind_tcf(q, cl); 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds static inline void 2631da177e4SLinus Torvalds tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r) 2641da177e4SLinus Torvalds { 26534e3759cSJiri Pirko struct Qdisc *q = tp->chain->block->q; 2661da177e4SLinus Torvalds unsigned long cl; 2671da177e4SLinus Torvalds 26834e3759cSJiri Pirko if (!q) 26934e3759cSJiri Pirko return; 2701da177e4SLinus Torvalds if ((cl = __cls_set_class(&r->class, 0)) != 0) 27134e3759cSJiri Pirko q->ops->cl_ops->unbind_tcf(q, cl); 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds 274fd2c3ef7SEric Dumazet struct tcf_exts { 2751da177e4SLinus Torvalds #ifdef CONFIG_NET_CLS_ACT 27633be6271SWANG Cong __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ 27722dc13c8SWANG Cong int nr_actions; 27822dc13c8SWANG Cong struct tc_action **actions; 279e4b95c41SCong Wang struct net *net; 2801da177e4SLinus Torvalds #endif 2811da177e4SLinus Torvalds /* Map to export classifier specific extension TLV types to the 2821da177e4SLinus Torvalds * generic extensions API. Unsupported extensions must be set to 0. 2831da177e4SLinus Torvalds */ 2841da177e4SLinus Torvalds int action; 2851da177e4SLinus Torvalds int police; 2861da177e4SLinus Torvalds }; 2871da177e4SLinus Torvalds 288b9a24bb7SWANG Cong static inline int tcf_exts_init(struct tcf_exts *exts, int action, int police) 28933be6271SWANG Cong { 29033be6271SWANG Cong #ifdef CONFIG_NET_CLS_ACT 2915da57f42SWANG Cong exts->type = 0; 29222dc13c8SWANG Cong exts->nr_actions = 0; 293e4b95c41SCong Wang exts->net = NULL; 29422dc13c8SWANG Cong exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *), 29522dc13c8SWANG Cong GFP_KERNEL); 296b9a24bb7SWANG Cong if (!exts->actions) 297b9a24bb7SWANG Cong return -ENOMEM; 29833be6271SWANG Cong #endif 2995da57f42SWANG Cong exts->action = action; 3005da57f42SWANG Cong exts->police = police; 301b9a24bb7SWANG Cong return 0; 30233be6271SWANG Cong } 30333be6271SWANG Cong 304e4b95c41SCong Wang /* Return false if the netns is being destroyed in cleanup_net(). Callers 305e4b95c41SCong Wang * need to do cleanup synchronously in this case, otherwise may race with 306e4b95c41SCong Wang * tc_action_net_exit(). Return true for other cases. 307e4b95c41SCong Wang */ 308e4b95c41SCong Wang static inline bool tcf_exts_get_net(struct tcf_exts *exts) 309e4b95c41SCong Wang { 310e4b95c41SCong Wang #ifdef CONFIG_NET_CLS_ACT 311e4b95c41SCong Wang exts->net = maybe_get_net(exts->net); 312e4b95c41SCong Wang return exts->net != NULL; 313e4b95c41SCong Wang #else 314e4b95c41SCong Wang return true; 315e4b95c41SCong Wang #endif 316e4b95c41SCong Wang } 317e4b95c41SCong Wang 318e4b95c41SCong Wang static inline void tcf_exts_put_net(struct tcf_exts *exts) 319e4b95c41SCong Wang { 320e4b95c41SCong Wang #ifdef CONFIG_NET_CLS_ACT 321e4b95c41SCong Wang if (exts->net) 322e4b95c41SCong Wang put_net(exts->net); 323e4b95c41SCong Wang #endif 324e4b95c41SCong Wang } 325e4b95c41SCong Wang 32622dc13c8SWANG Cong #ifdef CONFIG_NET_CLS_ACT 327244cd96aSCong Wang #define tcf_exts_for_each_action(i, a, exts) \ 328244cd96aSCong Wang for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = (exts)->actions[i]); i++) 329244cd96aSCong Wang #else 330244cd96aSCong Wang #define tcf_exts_for_each_action(i, a, exts) \ 331191672caSArnd Bergmann for (; 0; (void)(i), (void)(a), (void)(exts)) 33222dc13c8SWANG Cong #endif 33322dc13c8SWANG Cong 334d897a638SJakub Kicinski static inline void 335d897a638SJakub Kicinski tcf_exts_stats_update(const struct tcf_exts *exts, 336d897a638SJakub Kicinski u64 bytes, u64 packets, u64 lastuse) 337d897a638SJakub Kicinski { 338d897a638SJakub Kicinski #ifdef CONFIG_NET_CLS_ACT 339d897a638SJakub Kicinski int i; 340d897a638SJakub Kicinski 341d897a638SJakub Kicinski preempt_disable(); 342d897a638SJakub Kicinski 343d897a638SJakub Kicinski for (i = 0; i < exts->nr_actions; i++) { 344d897a638SJakub Kicinski struct tc_action *a = exts->actions[i]; 345d897a638SJakub Kicinski 34628169abaSEelco Chaudron tcf_action_stats_update(a, bytes, packets, lastuse, true); 347d897a638SJakub Kicinski } 348d897a638SJakub Kicinski 349d897a638SJakub Kicinski preempt_enable(); 350d897a638SJakub Kicinski #endif 351d897a638SJakub Kicinski } 352d897a638SJakub Kicinski 3531da177e4SLinus Torvalds /** 3543bcc0cecSJiri Pirko * tcf_exts_has_actions - check if at least one action is present 3553bcc0cecSJiri Pirko * @exts: tc filter extensions handle 3563bcc0cecSJiri Pirko * 3573bcc0cecSJiri Pirko * Returns true if at least one action is present. 3583bcc0cecSJiri Pirko */ 3593bcc0cecSJiri Pirko static inline bool tcf_exts_has_actions(struct tcf_exts *exts) 3603bcc0cecSJiri Pirko { 3612734437eSWANG Cong #ifdef CONFIG_NET_CLS_ACT 3623bcc0cecSJiri Pirko return exts->nr_actions; 3633bcc0cecSJiri Pirko #else 3643bcc0cecSJiri Pirko return false; 3653bcc0cecSJiri Pirko #endif 3663bcc0cecSJiri Pirko } 3672734437eSWANG Cong 3683bcc0cecSJiri Pirko /** 3693bcc0cecSJiri Pirko * tcf_exts_has_one_action - check if exactly one action is present 3703bcc0cecSJiri Pirko * @exts: tc filter extensions handle 3713bcc0cecSJiri Pirko * 3723bcc0cecSJiri Pirko * Returns true if exactly one action is present. 3733bcc0cecSJiri Pirko */ 3743bcc0cecSJiri Pirko static inline bool tcf_exts_has_one_action(struct tcf_exts *exts) 3753bcc0cecSJiri Pirko { 3763bcc0cecSJiri Pirko #ifdef CONFIG_NET_CLS_ACT 3773bcc0cecSJiri Pirko return exts->nr_actions == 1; 3783bcc0cecSJiri Pirko #else 3793bcc0cecSJiri Pirko return false; 3803bcc0cecSJiri Pirko #endif 3813bcc0cecSJiri Pirko } 3822734437eSWANG Cong 383244cd96aSCong Wang static inline struct tc_action *tcf_exts_first_action(struct tcf_exts *exts) 384244cd96aSCong Wang { 385244cd96aSCong Wang #ifdef CONFIG_NET_CLS_ACT 386244cd96aSCong Wang return exts->actions[0]; 387244cd96aSCong Wang #else 388244cd96aSCong Wang return NULL; 389244cd96aSCong Wang #endif 390244cd96aSCong Wang } 391244cd96aSCong Wang 392af69afc5SJiri Pirko /** 393af69afc5SJiri Pirko * tcf_exts_exec - execute tc filter extensions 394af69afc5SJiri Pirko * @skb: socket buffer 395af69afc5SJiri Pirko * @exts: tc filter extensions handle 396af69afc5SJiri Pirko * @res: desired result 397af69afc5SJiri Pirko * 398af089e70SJiri Pirko * Executes all configured extensions. Returns TC_ACT_OK on a normal execution, 399af69afc5SJiri Pirko * a negative number if the filter must be considered unmatched or 400af69afc5SJiri Pirko * a positive action code (TC_ACT_*) which must be returned to the 401af69afc5SJiri Pirko * underlying layer. 402af69afc5SJiri Pirko */ 403af69afc5SJiri Pirko static inline int 404af69afc5SJiri Pirko tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, 405af69afc5SJiri Pirko struct tcf_result *res) 406af69afc5SJiri Pirko { 407af69afc5SJiri Pirko #ifdef CONFIG_NET_CLS_ACT 408ec1a9ccaSJiri Pirko return tcf_action_exec(skb, exts->actions, exts->nr_actions, res); 409af69afc5SJiri Pirko #endif 410af089e70SJiri Pirko return TC_ACT_OK; 411af69afc5SJiri Pirko } 412af69afc5SJiri Pirko 4135c15257fSJoe Perches int tcf_exts_validate(struct net *net, struct tcf_proto *tp, 414c1b52739SBenjamin LaHaise struct nlattr **tb, struct nlattr *rate_tlv, 41550a56190SAlexander Aring struct tcf_exts *exts, bool ovr, 41650a56190SAlexander Aring struct netlink_ext_ack *extack); 41718d0264fSWANG Cong void tcf_exts_destroy(struct tcf_exts *exts); 4189b0d4446SJiri Pirko void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); 4195da57f42SWANG Cong int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); 4205da57f42SWANG Cong int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts); 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds /** 4231da177e4SLinus Torvalds * struct tcf_pkt_info - packet information 4241da177e4SLinus Torvalds */ 425fd2c3ef7SEric Dumazet struct tcf_pkt_info { 4261da177e4SLinus Torvalds unsigned char * ptr; 4271da177e4SLinus Torvalds int nexthdr; 4281da177e4SLinus Torvalds }; 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds #ifdef CONFIG_NET_EMATCH 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds struct tcf_ematch_ops; 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds /** 4351da177e4SLinus Torvalds * struct tcf_ematch - extended match (ematch) 4361da177e4SLinus Torvalds * 4371da177e4SLinus Torvalds * @matchid: identifier to allow userspace to reidentify a match 4381da177e4SLinus Torvalds * @flags: flags specifying attributes and the relation to other matches 4391da177e4SLinus Torvalds * @ops: the operations lookup table of the corresponding ematch module 4401da177e4SLinus Torvalds * @datalen: length of the ematch specific configuration data 4411da177e4SLinus Torvalds * @data: ematch specific data 4421da177e4SLinus Torvalds */ 443fd2c3ef7SEric Dumazet struct tcf_ematch { 4441da177e4SLinus Torvalds struct tcf_ematch_ops * ops; 4451da177e4SLinus Torvalds unsigned long data; 4461da177e4SLinus Torvalds unsigned int datalen; 4471da177e4SLinus Torvalds u16 matchid; 4481da177e4SLinus Torvalds u16 flags; 44982a470f1SJohn Fastabend struct net *net; 4501da177e4SLinus Torvalds }; 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds static inline int tcf_em_is_container(struct tcf_ematch *em) 4531da177e4SLinus Torvalds { 4541da177e4SLinus Torvalds return !em->ops; 4551da177e4SLinus Torvalds } 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds static inline int tcf_em_is_simple(struct tcf_ematch *em) 4581da177e4SLinus Torvalds { 4591da177e4SLinus Torvalds return em->flags & TCF_EM_SIMPLE; 4601da177e4SLinus Torvalds } 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds static inline int tcf_em_is_inverted(struct tcf_ematch *em) 4631da177e4SLinus Torvalds { 4641da177e4SLinus Torvalds return em->flags & TCF_EM_INVERT; 4651da177e4SLinus Torvalds } 4661da177e4SLinus Torvalds 4671da177e4SLinus Torvalds static inline int tcf_em_last_match(struct tcf_ematch *em) 4681da177e4SLinus Torvalds { 4691da177e4SLinus Torvalds return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END; 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds static inline int tcf_em_early_end(struct tcf_ematch *em, int result) 4731da177e4SLinus Torvalds { 4741da177e4SLinus Torvalds if (tcf_em_last_match(em)) 4751da177e4SLinus Torvalds return 1; 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds if (result == 0 && em->flags & TCF_EM_REL_AND) 4781da177e4SLinus Torvalds return 1; 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds if (result != 0 && em->flags & TCF_EM_REL_OR) 4811da177e4SLinus Torvalds return 1; 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds return 0; 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds /** 4871da177e4SLinus Torvalds * struct tcf_ematch_tree - ematch tree handle 4881da177e4SLinus Torvalds * 4891da177e4SLinus Torvalds * @hdr: ematch tree header supplied by userspace 4901da177e4SLinus Torvalds * @matches: array of ematches 4911da177e4SLinus Torvalds */ 492fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4931da177e4SLinus Torvalds struct tcf_ematch_tree_hdr hdr; 4941da177e4SLinus Torvalds struct tcf_ematch * matches; 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds }; 4971da177e4SLinus Torvalds 4981da177e4SLinus Torvalds /** 4991da177e4SLinus Torvalds * struct tcf_ematch_ops - ematch module operations 5001da177e4SLinus Torvalds * 5011da177e4SLinus Torvalds * @kind: identifier (kind) of this ematch module 5021da177e4SLinus Torvalds * @datalen: length of expected configuration data (optional) 5031da177e4SLinus Torvalds * @change: called during validation (optional) 5041da177e4SLinus Torvalds * @match: called during ematch tree evaluation, must return 1/0 5051da177e4SLinus Torvalds * @destroy: called during destroyage (optional) 5061da177e4SLinus Torvalds * @dump: called during dumping process (optional) 5071da177e4SLinus Torvalds * @owner: owner, must be set to THIS_MODULE 5081da177e4SLinus Torvalds * @link: link to previous/next ematch module (internal use) 5091da177e4SLinus Torvalds */ 510fd2c3ef7SEric Dumazet struct tcf_ematch_ops { 5111da177e4SLinus Torvalds int kind; 5121da177e4SLinus Torvalds int datalen; 51382a470f1SJohn Fastabend int (*change)(struct net *net, void *, 5141da177e4SLinus Torvalds int, struct tcf_ematch *); 5151da177e4SLinus Torvalds int (*match)(struct sk_buff *, struct tcf_ematch *, 5161da177e4SLinus Torvalds struct tcf_pkt_info *); 51782a470f1SJohn Fastabend void (*destroy)(struct tcf_ematch *); 5181da177e4SLinus Torvalds int (*dump)(struct sk_buff *, struct tcf_ematch *); 5191da177e4SLinus Torvalds struct module *owner; 5201da177e4SLinus Torvalds struct list_head link; 5211da177e4SLinus Torvalds }; 5221da177e4SLinus Torvalds 5235c15257fSJoe Perches int tcf_em_register(struct tcf_ematch_ops *); 5245c15257fSJoe Perches void tcf_em_unregister(struct tcf_ematch_ops *); 5255c15257fSJoe Perches int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *, 5261da177e4SLinus Torvalds struct tcf_ematch_tree *); 52782a470f1SJohn Fastabend void tcf_em_tree_destroy(struct tcf_ematch_tree *); 5285c15257fSJoe Perches int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int); 5295c15257fSJoe Perches int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *, 5301da177e4SLinus Torvalds struct tcf_pkt_info *); 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds /** 5331da177e4SLinus Torvalds * tcf_em_tree_match - evaulate an ematch tree 5341da177e4SLinus Torvalds * 5351da177e4SLinus Torvalds * @skb: socket buffer of the packet in question 5361da177e4SLinus Torvalds * @tree: ematch tree to be used for evaluation 5371da177e4SLinus Torvalds * @info: packet information examined by classifier 5381da177e4SLinus Torvalds * 5391da177e4SLinus Torvalds * This function matches @skb against the ematch tree in @tree by going 5401da177e4SLinus Torvalds * through all ematches respecting their logic relations returning 5411da177e4SLinus Torvalds * as soon as the result is obvious. 5421da177e4SLinus Torvalds * 5431da177e4SLinus Torvalds * Returns 1 if the ematch tree as-one matches, no ematches are configured 5441da177e4SLinus Torvalds * or ematch is not enabled in the kernel, otherwise 0 is returned. 5451da177e4SLinus Torvalds */ 5461da177e4SLinus Torvalds static inline int tcf_em_tree_match(struct sk_buff *skb, 5471da177e4SLinus Torvalds struct tcf_ematch_tree *tree, 5481da177e4SLinus Torvalds struct tcf_pkt_info *info) 5491da177e4SLinus Torvalds { 5501da177e4SLinus Torvalds if (tree->hdr.nmatches) 5511da177e4SLinus Torvalds return __tcf_em_tree_match(skb, tree, info); 5521da177e4SLinus Torvalds else 5531da177e4SLinus Torvalds return 1; 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds 556db3d99c0SPatrick McHardy #define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind)) 557db3d99c0SPatrick McHardy 5581da177e4SLinus Torvalds #else /* CONFIG_NET_EMATCH */ 5591da177e4SLinus Torvalds 560fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 5611da177e4SLinus Torvalds }; 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0) 56482a470f1SJohn Fastabend #define tcf_em_tree_destroy(t) do { (void)(t); } while(0) 5651da177e4SLinus Torvalds #define tcf_em_tree_dump(skb, t, tlv) (0) 5661da177e4SLinus Torvalds #define tcf_em_tree_match(skb, t, info) ((void)(info), 1) 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds #endif /* CONFIG_NET_EMATCH */ 5691da177e4SLinus Torvalds 5701da177e4SLinus Torvalds static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) 5711da177e4SLinus Torvalds { 5721da177e4SLinus Torvalds switch (layer) { 5731da177e4SLinus Torvalds case TCF_LAYER_LINK: 574d3303a65SWolfgang Bumiller return skb_mac_header(skb); 5751da177e4SLinus Torvalds case TCF_LAYER_NETWORK: 576d56f90a7SArnaldo Carvalho de Melo return skb_network_header(skb); 5771da177e4SLinus Torvalds case TCF_LAYER_TRANSPORT: 5789c70220bSArnaldo Carvalho de Melo return skb_transport_header(skb); 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds return NULL; 5821da177e4SLinus Torvalds } 5831da177e4SLinus Torvalds 584eddc9ec5SArnaldo Carvalho de Melo static inline int tcf_valid_offset(const struct sk_buff *skb, 585eddc9ec5SArnaldo Carvalho de Melo const unsigned char *ptr, const int len) 5861da177e4SLinus Torvalds { 587da521b2cSDavid S. Miller return likely((ptr + len) <= skb_tail_pointer(skb) && 588da521b2cSDavid S. Miller ptr >= skb->head && 589da521b2cSDavid S. Miller (ptr <= (ptr + len))); 5901da177e4SLinus Torvalds } 5911da177e4SLinus Torvalds 5921da177e4SLinus Torvalds #ifdef CONFIG_NET_CLS_IND 5930eeb8ffcSDenis V. Lunev #include <net/net_namespace.h> 5940eeb8ffcSDenis V. Lunev 5951da177e4SLinus Torvalds static inline int 5961057c55fSAlexander Aring tcf_change_indev(struct net *net, struct nlattr *indev_tlv, 5971057c55fSAlexander Aring struct netlink_ext_ack *extack) 5981da177e4SLinus Torvalds { 5992519a602SWANG Cong char indev[IFNAMSIZ]; 600c01003c2SPatrick McHardy struct net_device *dev; 601c01003c2SPatrick McHardy 6021057c55fSAlexander Aring if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) { 6031057c55fSAlexander Aring NL_SET_ERR_MSG(extack, "Interface name too long"); 6042519a602SWANG Cong return -EINVAL; 6051057c55fSAlexander Aring } 6062519a602SWANG Cong dev = __dev_get_by_name(net, indev); 6072519a602SWANG Cong if (!dev) 6082519a602SWANG Cong return -ENODEV; 6092519a602SWANG Cong return dev->ifindex; 6101da177e4SLinus Torvalds } 6111da177e4SLinus Torvalds 6122519a602SWANG Cong static inline bool 6132519a602SWANG Cong tcf_match_indev(struct sk_buff *skb, int ifindex) 6142519a602SWANG Cong { 6152519a602SWANG Cong if (!ifindex) 6162519a602SWANG Cong return true; 6172519a602SWANG Cong if (!skb->skb_iif) 6182519a602SWANG Cong return false; 6192519a602SWANG Cong return ifindex == skb->skb_iif; 6201da177e4SLinus Torvalds } 6211da177e4SLinus Torvalds #endif /* CONFIG_NET_CLS_IND */ 6221da177e4SLinus Torvalds 6233a7b6861SPablo Neira Ayuso int tc_setup_flow_action(struct flow_action *flow_action, 6243a7b6861SPablo Neira Ayuso const struct tcf_exts *exts); 625aeb3fecdSCong Wang int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, 626aeb3fecdSCong Wang void *type_data, bool err_stop); 627e3ab786bSPablo Neira Ayuso unsigned int tcf_exts_num_actions(struct tcf_exts *exts); 628717503b9SJiri Pirko 6298c4083b3SJiri Pirko enum tc_block_command { 6308c4083b3SJiri Pirko TC_BLOCK_BIND, 6318c4083b3SJiri Pirko TC_BLOCK_UNBIND, 6328c4083b3SJiri Pirko }; 6338c4083b3SJiri Pirko 6348c4083b3SJiri Pirko struct tc_block_offload { 6358c4083b3SJiri Pirko enum tc_block_command command; 6368c4083b3SJiri Pirko enum tcf_block_binder_type binder_type; 6378c4083b3SJiri Pirko struct tcf_block *block; 63860513bd8SJohn Hurley struct netlink_ext_ack *extack; 6398c4083b3SJiri Pirko }; 6408c4083b3SJiri Pirko 6415fd9fc4eSJiri Pirko struct tc_cls_common_offload { 6425fd9fc4eSJiri Pirko u32 chain_index; 6435fd9fc4eSJiri Pirko __be16 protocol; 644d7c1c8d2SJiri Pirko u32 prio; 6458f0b425aSQuentin Monnet struct netlink_ext_ack *extack; 6465fd9fc4eSJiri Pirko }; 6475fd9fc4eSJiri Pirko 648a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode { 649a1b7c5fdSJohn Fastabend struct tcf_exts *exts; 650068ceb35SJakub Kicinski struct tcf_result *res; 651e014860eSJohn Fastabend struct tc_u32_sel *sel; 652a1b7c5fdSJohn Fastabend u32 handle; 653a1b7c5fdSJohn Fastabend u32 val; 654a1b7c5fdSJohn Fastabend u32 mask; 655a1b7c5fdSJohn Fastabend u32 link_handle; 656e014860eSJohn Fastabend u8 fshift; 657a1b7c5fdSJohn Fastabend }; 658a1b7c5fdSJohn Fastabend 659a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode { 660a1b7c5fdSJohn Fastabend u32 handle; 661a1b7c5fdSJohn Fastabend u32 prio; 662a1b7c5fdSJohn Fastabend unsigned int divisor; 663a1b7c5fdSJohn Fastabend }; 664a1b7c5fdSJohn Fastabend 665a1b7c5fdSJohn Fastabend enum tc_clsu32_command { 666a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_KNODE, 667a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_KNODE, 668a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_KNODE, 669a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_HNODE, 670a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_HNODE, 671a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_HNODE, 672a1b7c5fdSJohn Fastabend }; 673a1b7c5fdSJohn Fastabend 674a1b7c5fdSJohn Fastabend struct tc_cls_u32_offload { 6755fd9fc4eSJiri Pirko struct tc_cls_common_offload common; 676a1b7c5fdSJohn Fastabend /* knode values */ 677a1b7c5fdSJohn Fastabend enum tc_clsu32_command command; 678a1b7c5fdSJohn Fastabend union { 679a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode knode; 680a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode hnode; 681a1b7c5fdSJohn Fastabend }; 682a1b7c5fdSJohn Fastabend }; 683a1b7c5fdSJohn Fastabend 6847b06e8aeSJiri Pirko static inline bool tc_can_offload(const struct net_device *dev) 6856843e7a2SJohn Fastabend { 68670b5aee4SJiri Pirko return dev->features & NETIF_F_HW_TC; 6876843e7a2SJohn Fastabend } 6886843e7a2SJohn Fastabend 689f9eda14fSQuentin Monnet static inline bool tc_can_offload_extack(const struct net_device *dev, 690f9eda14fSQuentin Monnet struct netlink_ext_ack *extack) 691f9eda14fSQuentin Monnet { 692f9eda14fSQuentin Monnet bool can = tc_can_offload(dev); 693f9eda14fSQuentin Monnet 694f9eda14fSQuentin Monnet if (!can) 695f9eda14fSQuentin Monnet NL_SET_ERR_MSG(extack, "TC offload is disabled on net device"); 696f9eda14fSQuentin Monnet 697f9eda14fSQuentin Monnet return can; 698f9eda14fSQuentin Monnet } 699f9eda14fSQuentin Monnet 700878db9f0SJakub Kicinski static inline bool 701878db9f0SJakub Kicinski tc_cls_can_offload_and_chain0(const struct net_device *dev, 702878db9f0SJakub Kicinski struct tc_cls_common_offload *common) 703878db9f0SJakub Kicinski { 704878db9f0SJakub Kicinski if (!tc_can_offload_extack(dev, common->extack)) 705878db9f0SJakub Kicinski return false; 706878db9f0SJakub Kicinski if (common->chain_index) { 707878db9f0SJakub Kicinski NL_SET_ERR_MSG(common->extack, 708878db9f0SJakub Kicinski "Driver supports only offload of chain 0"); 709878db9f0SJakub Kicinski return false; 710878db9f0SJakub Kicinski } 711878db9f0SJakub Kicinski return true; 712878db9f0SJakub Kicinski } 713878db9f0SJakub Kicinski 71455330f05SHadar Hen Zion static inline bool tc_skip_hw(u32 flags) 71555330f05SHadar Hen Zion { 71655330f05SHadar Hen Zion return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; 71755330f05SHadar Hen Zion } 71855330f05SHadar Hen Zion 719d34e3e18SSamudrala, Sridhar static inline bool tc_skip_sw(u32 flags) 720d34e3e18SSamudrala, Sridhar { 721d34e3e18SSamudrala, Sridhar return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false; 722d34e3e18SSamudrala, Sridhar } 723d34e3e18SSamudrala, Sridhar 724d34e3e18SSamudrala, Sridhar /* SKIP_HW and SKIP_SW are mutually exclusive flags. */ 725d34e3e18SSamudrala, Sridhar static inline bool tc_flags_valid(u32 flags) 726d34e3e18SSamudrala, Sridhar { 72781c7288bSMarcelo Ricardo Leitner if (flags & ~(TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW | 72881c7288bSMarcelo Ricardo Leitner TCA_CLS_FLAGS_VERBOSE)) 729d34e3e18SSamudrala, Sridhar return false; 730d34e3e18SSamudrala, Sridhar 73181c7288bSMarcelo Ricardo Leitner flags &= TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW; 732d34e3e18SSamudrala, Sridhar if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW))) 733d34e3e18SSamudrala, Sridhar return false; 734d34e3e18SSamudrala, Sridhar 735d34e3e18SSamudrala, Sridhar return true; 736d34e3e18SSamudrala, Sridhar } 737d34e3e18SSamudrala, Sridhar 738e696028aSOr Gerlitz static inline bool tc_in_hw(u32 flags) 739e696028aSOr Gerlitz { 740e696028aSOr Gerlitz return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; 741e696028aSOr Gerlitz } 742e696028aSOr Gerlitz 74334832e1cSJakub Kicinski static inline void 74434832e1cSJakub Kicinski tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common, 74534832e1cSJakub Kicinski const struct tcf_proto *tp, u32 flags, 74634832e1cSJakub Kicinski struct netlink_ext_ack *extack) 74734832e1cSJakub Kicinski { 74834832e1cSJakub Kicinski cls_common->chain_index = tp->chain->index; 74934832e1cSJakub Kicinski cls_common->protocol = tp->protocol; 75034832e1cSJakub Kicinski cls_common->prio = tp->prio; 75181c7288bSMarcelo Ricardo Leitner if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE) 75234832e1cSJakub Kicinski cls_common->extack = extack; 75334832e1cSJakub Kicinski } 75434832e1cSJakub Kicinski 7555b33f488SAmir Vadai enum tc_fl_command { 7565b33f488SAmir Vadai TC_CLSFLOWER_REPLACE, 7575b33f488SAmir Vadai TC_CLSFLOWER_DESTROY, 75810cbc684SAmir Vadai TC_CLSFLOWER_STATS, 75934738452SJiri Pirko TC_CLSFLOWER_TMPLT_CREATE, 76034738452SJiri Pirko TC_CLSFLOWER_TMPLT_DESTROY, 7615b33f488SAmir Vadai }; 7625b33f488SAmir Vadai 7635b33f488SAmir Vadai struct tc_cls_flower_offload { 7645fd9fc4eSJiri Pirko struct tc_cls_common_offload common; 7655b33f488SAmir Vadai enum tc_fl_command command; 7668208d21bSAmir Vadai unsigned long cookie; 7678f256622SPablo Neira Ayuso struct flow_rule *rule; 7685b33f488SAmir Vadai struct tcf_exts *exts; 769384c181eSAmritha Nambiar u32 classid; 7705b33f488SAmir Vadai }; 7715b33f488SAmir Vadai 7728f256622SPablo Neira Ayuso static inline struct flow_rule * 7738f256622SPablo Neira Ayuso tc_cls_flower_offload_flow_rule(struct tc_cls_flower_offload *tc_flow_cmd) 7748f256622SPablo Neira Ayuso { 7758f256622SPablo Neira Ayuso return tc_flow_cmd->rule; 7768f256622SPablo Neira Ayuso } 7778f256622SPablo Neira Ayuso 778b87f7936SYotam Gigi enum tc_matchall_command { 779b87f7936SYotam Gigi TC_CLSMATCHALL_REPLACE, 780b87f7936SYotam Gigi TC_CLSMATCHALL_DESTROY, 781b87f7936SYotam Gigi }; 782b87f7936SYotam Gigi 783b87f7936SYotam Gigi struct tc_cls_matchall_offload { 7845fd9fc4eSJiri Pirko struct tc_cls_common_offload common; 785b87f7936SYotam Gigi enum tc_matchall_command command; 786b87f7936SYotam Gigi struct tcf_exts *exts; 787b87f7936SYotam Gigi unsigned long cookie; 788b87f7936SYotam Gigi }; 789b87f7936SYotam Gigi 790332ae8e2SJakub Kicinski enum tc_clsbpf_command { 791102740bdSJakub Kicinski TC_CLSBPF_OFFLOAD, 79268d64063SJakub Kicinski TC_CLSBPF_STATS, 793332ae8e2SJakub Kicinski }; 794332ae8e2SJakub Kicinski 795332ae8e2SJakub Kicinski struct tc_cls_bpf_offload { 7965fd9fc4eSJiri Pirko struct tc_cls_common_offload common; 797332ae8e2SJakub Kicinski enum tc_clsbpf_command command; 798332ae8e2SJakub Kicinski struct tcf_exts *exts; 799332ae8e2SJakub Kicinski struct bpf_prog *prog; 800102740bdSJakub Kicinski struct bpf_prog *oldprog; 801332ae8e2SJakub Kicinski const char *name; 802332ae8e2SJakub Kicinski bool exts_integrated; 803332ae8e2SJakub Kicinski }; 804332ae8e2SJakub Kicinski 8054e8b86c0SAmritha Nambiar struct tc_mqprio_qopt_offload { 8064e8b86c0SAmritha Nambiar /* struct tc_mqprio_qopt must always be the first element */ 8074e8b86c0SAmritha Nambiar struct tc_mqprio_qopt qopt; 8084e8b86c0SAmritha Nambiar u16 mode; 8094e8b86c0SAmritha Nambiar u16 shaper; 8104e8b86c0SAmritha Nambiar u32 flags; 8114e8b86c0SAmritha Nambiar u64 min_rate[TC_QOPT_MAX_QUEUE]; 8124e8b86c0SAmritha Nambiar u64 max_rate[TC_QOPT_MAX_QUEUE]; 8134e8b86c0SAmritha Nambiar }; 8141045ba77SJamal Hadi Salim 8151045ba77SJamal Hadi Salim /* This structure holds cookie structure that is passed from user 8161045ba77SJamal Hadi Salim * to the kernel for actions and classifiers 8171045ba77SJamal Hadi Salim */ 8181045ba77SJamal Hadi Salim struct tc_cookie { 8191045ba77SJamal Hadi Salim u8 *data; 8201045ba77SJamal Hadi Salim u32 len; 821eec94fdbSVlad Buslov struct rcu_head rcu; 8221045ba77SJamal Hadi Salim }; 823602f3bafSNogah Frankel 824f34b4aacSNogah Frankel struct tc_qopt_offload_stats { 825f34b4aacSNogah Frankel struct gnet_stats_basic_packed *bstats; 826f34b4aacSNogah Frankel struct gnet_stats_queue *qstats; 827f34b4aacSNogah Frankel }; 828f34b4aacSNogah Frankel 829f971b132SJakub Kicinski enum tc_mq_command { 830f971b132SJakub Kicinski TC_MQ_CREATE, 831f971b132SJakub Kicinski TC_MQ_DESTROY, 83247c669a4SJakub Kicinski TC_MQ_STATS, 833d577a3d2SJakub Kicinski TC_MQ_GRAFT, 834d577a3d2SJakub Kicinski }; 835d577a3d2SJakub Kicinski 836d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params { 837d577a3d2SJakub Kicinski unsigned long queue; 838d577a3d2SJakub Kicinski u32 child_handle; 839f971b132SJakub Kicinski }; 840f971b132SJakub Kicinski 841f971b132SJakub Kicinski struct tc_mq_qopt_offload { 842f971b132SJakub Kicinski enum tc_mq_command command; 843f971b132SJakub Kicinski u32 handle; 844d577a3d2SJakub Kicinski union { 84547c669a4SJakub Kicinski struct tc_qopt_offload_stats stats; 846d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params graft_params; 847d577a3d2SJakub Kicinski }; 848f971b132SJakub Kicinski }; 849f971b132SJakub Kicinski 850602f3bafSNogah Frankel enum tc_red_command { 851602f3bafSNogah Frankel TC_RED_REPLACE, 852602f3bafSNogah Frankel TC_RED_DESTROY, 853602f3bafSNogah Frankel TC_RED_STATS, 854602f3bafSNogah Frankel TC_RED_XSTATS, 855bf2a752bSJakub Kicinski TC_RED_GRAFT, 856602f3bafSNogah Frankel }; 857602f3bafSNogah Frankel 858602f3bafSNogah Frankel struct tc_red_qopt_offload_params { 859602f3bafSNogah Frankel u32 min; 860602f3bafSNogah Frankel u32 max; 861602f3bafSNogah Frankel u32 probability; 862c0b7490bSJakub Kicinski u32 limit; 863602f3bafSNogah Frankel bool is_ecn; 864190852a5SJakub Kicinski bool is_harddrop; 865416ef9b1SJakub Kicinski struct gnet_stats_queue *qstats; 866602f3bafSNogah Frankel }; 867602f3bafSNogah Frankel 868602f3bafSNogah Frankel struct tc_red_qopt_offload { 869602f3bafSNogah Frankel enum tc_red_command command; 870602f3bafSNogah Frankel u32 handle; 871602f3bafSNogah Frankel u32 parent; 872602f3bafSNogah Frankel union { 873602f3bafSNogah Frankel struct tc_red_qopt_offload_params set; 874f34b4aacSNogah Frankel struct tc_qopt_offload_stats stats; 875602f3bafSNogah Frankel struct red_stats *xstats; 876bf2a752bSJakub Kicinski u32 child_handle; 877602f3bafSNogah Frankel }; 878602f3bafSNogah Frankel }; 879602f3bafSNogah Frankel 880890d8d23SJakub Kicinski enum tc_gred_command { 881890d8d23SJakub Kicinski TC_GRED_REPLACE, 882890d8d23SJakub Kicinski TC_GRED_DESTROY, 883e49efd52SJakub Kicinski TC_GRED_STATS, 884890d8d23SJakub Kicinski }; 885890d8d23SJakub Kicinski 886890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params { 887890d8d23SJakub Kicinski bool present; 888890d8d23SJakub Kicinski u32 limit; 889890d8d23SJakub Kicinski u32 prio; 890890d8d23SJakub Kicinski u32 min; 891890d8d23SJakub Kicinski u32 max; 892890d8d23SJakub Kicinski bool is_ecn; 893890d8d23SJakub Kicinski bool is_harddrop; 894890d8d23SJakub Kicinski u32 probability; 895890d8d23SJakub Kicinski /* Only need backlog, see struct tc_prio_qopt_offload_params */ 896890d8d23SJakub Kicinski u32 *backlog; 897890d8d23SJakub Kicinski }; 898890d8d23SJakub Kicinski 899890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params { 900890d8d23SJakub Kicinski bool grio_on; 901890d8d23SJakub Kicinski bool wred_on; 902890d8d23SJakub Kicinski unsigned int dp_cnt; 903890d8d23SJakub Kicinski unsigned int dp_def; 904890d8d23SJakub Kicinski struct gnet_stats_queue *qstats; 905890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params tab[MAX_DPs]; 906890d8d23SJakub Kicinski }; 907890d8d23SJakub Kicinski 908e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats { 909e49efd52SJakub Kicinski struct gnet_stats_basic_packed bstats[MAX_DPs]; 910e49efd52SJakub Kicinski struct gnet_stats_queue qstats[MAX_DPs]; 911e49efd52SJakub Kicinski struct red_stats *xstats[MAX_DPs]; 912e49efd52SJakub Kicinski }; 913e49efd52SJakub Kicinski 914890d8d23SJakub Kicinski struct tc_gred_qopt_offload { 915890d8d23SJakub Kicinski enum tc_gred_command command; 916890d8d23SJakub Kicinski u32 handle; 917890d8d23SJakub Kicinski u32 parent; 918890d8d23SJakub Kicinski union { 919890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params set; 920e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats stats; 921890d8d23SJakub Kicinski }; 922890d8d23SJakub Kicinski }; 923890d8d23SJakub Kicinski 9247fdb61b4SNogah Frankel enum tc_prio_command { 9257fdb61b4SNogah Frankel TC_PRIO_REPLACE, 9267fdb61b4SNogah Frankel TC_PRIO_DESTROY, 9277fdb61b4SNogah Frankel TC_PRIO_STATS, 928b9c7a7acSNogah Frankel TC_PRIO_GRAFT, 9297fdb61b4SNogah Frankel }; 9307fdb61b4SNogah Frankel 9317fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params { 9327fdb61b4SNogah Frankel int bands; 9337fdb61b4SNogah Frankel u8 priomap[TC_PRIO_MAX + 1]; 9347fdb61b4SNogah Frankel /* In case that a prio qdisc is offloaded and now is changed to a 9357fdb61b4SNogah Frankel * non-offloadedable config, it needs to update the backlog & qlen 9367fdb61b4SNogah Frankel * values to negate the HW backlog & qlen values (and only them). 9377fdb61b4SNogah Frankel */ 9387fdb61b4SNogah Frankel struct gnet_stats_queue *qstats; 9397fdb61b4SNogah Frankel }; 9407fdb61b4SNogah Frankel 941b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params { 942b9c7a7acSNogah Frankel u8 band; 943b9c7a7acSNogah Frankel u32 child_handle; 944b9c7a7acSNogah Frankel }; 945b9c7a7acSNogah Frankel 9467fdb61b4SNogah Frankel struct tc_prio_qopt_offload { 9477fdb61b4SNogah Frankel enum tc_prio_command command; 9487fdb61b4SNogah Frankel u32 handle; 9497fdb61b4SNogah Frankel u32 parent; 9507fdb61b4SNogah Frankel union { 9517fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params replace_params; 9527fdb61b4SNogah Frankel struct tc_qopt_offload_stats stats; 953b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params graft_params; 9547fdb61b4SNogah Frankel }; 9557fdb61b4SNogah Frankel }; 956b9c7a7acSNogah Frankel 95798b0e5f6SJakub Kicinski enum tc_root_command { 95898b0e5f6SJakub Kicinski TC_ROOT_GRAFT, 95998b0e5f6SJakub Kicinski }; 96098b0e5f6SJakub Kicinski 96198b0e5f6SJakub Kicinski struct tc_root_qopt_offload { 96298b0e5f6SJakub Kicinski enum tc_root_command command; 96398b0e5f6SJakub Kicinski u32 handle; 96498b0e5f6SJakub Kicinski bool ingress; 96598b0e5f6SJakub Kicinski }; 96698b0e5f6SJakub Kicinski 9671da177e4SLinus Torvalds #endif 968