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 35acb67442SJiri Pirko struct tcf_block_cb; 36aaa908ffSCong Wang bool tcf_queue_work(struct rcu_work *rwork, work_func_t func); 37acb67442SJiri Pirko 388ae70032SJiri Pirko #ifdef CONFIG_NET_CLS 391f3ed383SJiri Pirko struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, 401f3ed383SJiri Pirko u32 chain_index); 411f3ed383SJiri Pirko void tcf_chain_put_by_act(struct tcf_chain *chain); 42bbf73830SVlad Buslov struct tcf_chain *tcf_get_next_chain(struct tcf_block *block, 43bbf73830SVlad Buslov struct tcf_chain *chain); 44fe2923afSVlad Buslov struct tcf_proto *tcf_get_next_proto(struct tcf_chain *chain, 4512db03b6SVlad Buslov struct tcf_proto *tp, bool rtnl_held); 46f36fe1c4SJiri Pirko void tcf_block_netif_keep_dst(struct tcf_block *block); 476529eabaSJiri Pirko int tcf_block_get(struct tcf_block **p_block, 488d1a77f9SAlexander Aring struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 498d1a77f9SAlexander Aring struct netlink_ext_ack *extack); 50c7eb7d72SJiri Pirko int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 518d1a77f9SAlexander Aring struct tcf_block_ext_info *ei, 528d1a77f9SAlexander Aring struct netlink_ext_ack *extack); 536529eabaSJiri Pirko void tcf_block_put(struct tcf_block *block); 54c7eb7d72SJiri Pirko void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 558c4083b3SJiri Pirko struct tcf_block_ext_info *ei); 5644186460SJiri Pirko 5748617387SJiri Pirko static inline bool tcf_block_shared(struct tcf_block *block) 5848617387SJiri Pirko { 5948617387SJiri Pirko return block->index; 6048617387SJiri Pirko } 6148617387SJiri Pirko 62c1a970d0SVlad Buslov static inline bool tcf_block_non_null_shared(struct tcf_block *block) 63c1a970d0SVlad Buslov { 64c1a970d0SVlad Buslov return block && block->index; 65c1a970d0SVlad Buslov } 66c1a970d0SVlad Buslov 6744186460SJiri Pirko static inline struct Qdisc *tcf_block_q(struct tcf_block *block) 6844186460SJiri Pirko { 6948617387SJiri Pirko WARN_ON(tcf_block_shared(block)); 7044186460SJiri Pirko return block->q; 7144186460SJiri Pirko } 7244186460SJiri Pirko 7387d83093SJiri Pirko int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, 7487d83093SJiri Pirko struct tcf_result *res, bool compat_mode); 757d17c544SPaul Blakey int tcf_classify_ingress(struct sk_buff *skb, 767d17c544SPaul Blakey const struct tcf_block *ingress_block, 777d17c544SPaul Blakey const struct tcf_proto *tp, struct tcf_result *res, 787d17c544SPaul Blakey bool compat_mode); 7987d83093SJiri Pirko 808ae70032SJiri Pirko #else 8188c44a52SPieter Jansen van Vuuren static inline bool tcf_block_shared(struct tcf_block *block) 8288c44a52SPieter Jansen van Vuuren { 8388c44a52SPieter Jansen van Vuuren return false; 8488c44a52SPieter Jansen van Vuuren } 8588c44a52SPieter Jansen van Vuuren 86c1a970d0SVlad Buslov static inline bool tcf_block_non_null_shared(struct tcf_block *block) 87c1a970d0SVlad Buslov { 88c1a970d0SVlad Buslov return false; 89c1a970d0SVlad Buslov } 90c1a970d0SVlad Buslov 916529eabaSJiri Pirko static inline 926529eabaSJiri Pirko int tcf_block_get(struct tcf_block **p_block, 933c149091SSudip Mukherjee struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 943c149091SSudip Mukherjee struct netlink_ext_ack *extack) 956529eabaSJiri Pirko { 966529eabaSJiri Pirko return 0; 976529eabaSJiri Pirko } 986529eabaSJiri Pirko 998c4083b3SJiri Pirko static inline 100c7eb7d72SJiri Pirko int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 10133c30a8bSQuentin Monnet struct tcf_block_ext_info *ei, 10233c30a8bSQuentin Monnet struct netlink_ext_ack *extack) 1038c4083b3SJiri Pirko { 1048c4083b3SJiri Pirko return 0; 1058c4083b3SJiri Pirko } 1068c4083b3SJiri Pirko 1076529eabaSJiri Pirko static inline void tcf_block_put(struct tcf_block *block) 1088ae70032SJiri Pirko { 1098ae70032SJiri Pirko } 11087d83093SJiri Pirko 1118c4083b3SJiri Pirko static inline 112c7eb7d72SJiri Pirko void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 1138c4083b3SJiri Pirko struct tcf_block_ext_info *ei) 1148c4083b3SJiri Pirko { 1158c4083b3SJiri Pirko } 1168c4083b3SJiri Pirko 11744186460SJiri Pirko static inline struct Qdisc *tcf_block_q(struct tcf_block *block) 11844186460SJiri Pirko { 11944186460SJiri Pirko return NULL; 12044186460SJiri Pirko } 12144186460SJiri Pirko 122acb67442SJiri Pirko static inline 123a7323311SPablo Neira Ayuso int tc_setup_cb_block_register(struct tcf_block *block, flow_setup_cb_t *cb, 124acb67442SJiri Pirko void *cb_priv) 125acb67442SJiri Pirko { 126acb67442SJiri Pirko return 0; 127acb67442SJiri Pirko } 128acb67442SJiri Pirko 129acb67442SJiri Pirko static inline 130a7323311SPablo Neira Ayuso void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb, 131acb67442SJiri Pirko void *cb_priv) 132acb67442SJiri Pirko { 133acb67442SJiri Pirko } 134acb67442SJiri Pirko 13587d83093SJiri Pirko static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, 13687d83093SJiri Pirko struct tcf_result *res, bool compat_mode) 13787d83093SJiri Pirko { 13887d83093SJiri Pirko return TC_ACT_UNSPEC; 13987d83093SJiri Pirko } 1409410c940SPaul Blakey 1419410c940SPaul Blakey static inline int tcf_classify_ingress(struct sk_buff *skb, 1427d17c544SPaul Blakey const struct tcf_block *ingress_block, 1439410c940SPaul Blakey const struct tcf_proto *tp, 1449410c940SPaul Blakey struct tcf_result *res, bool compat_mode) 1459410c940SPaul Blakey { 1469410c940SPaul Blakey return TC_ACT_UNSPEC; 1479410c940SPaul Blakey } 1489410c940SPaul Blakey 1498ae70032SJiri Pirko #endif 150cf1facdaSJiri Pirko 1511da177e4SLinus Torvalds static inline unsigned long 1521da177e4SLinus Torvalds __cls_set_class(unsigned long *clp, unsigned long cl) 1531da177e4SLinus Torvalds { 154a0efb80cSWANG Cong return xchg(clp, cl); 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1572e24cd75SCong Wang static inline void 1582e24cd75SCong Wang __tcf_bind_filter(struct Qdisc *q, struct tcf_result *r, unsigned long base) 1591da177e4SLinus Torvalds { 1602e24cd75SCong Wang unsigned long cl; 1611da177e4SLinus Torvalds 1622e24cd75SCong Wang cl = q->ops->cl_ops->bind_tcf(q, base, r->classid); 1632e24cd75SCong Wang cl = __cls_set_class(&r->class, cl); 1642e24cd75SCong Wang if (cl) 1652e24cd75SCong Wang q->ops->cl_ops->unbind_tcf(q, cl); 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds static inline void 1691da177e4SLinus Torvalds tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base) 1701da177e4SLinus Torvalds { 17134e3759cSJiri Pirko struct Qdisc *q = tp->chain->block->q; 1721da177e4SLinus Torvalds 17334e3759cSJiri Pirko /* Check q as it is not set for shared blocks. In that case, 17434e3759cSJiri Pirko * setting class is not supported. 17534e3759cSJiri Pirko */ 17634e3759cSJiri Pirko if (!q) 17734e3759cSJiri Pirko return; 1782e24cd75SCong Wang sch_tree_lock(q); 1792e24cd75SCong Wang __tcf_bind_filter(q, r, base); 1802e24cd75SCong Wang sch_tree_unlock(q); 1812e24cd75SCong Wang } 1822e24cd75SCong Wang 1832e24cd75SCong Wang static inline void 1842e24cd75SCong Wang __tcf_unbind_filter(struct Qdisc *q, struct tcf_result *r) 1852e24cd75SCong Wang { 1862e24cd75SCong Wang unsigned long cl; 1872e24cd75SCong Wang 1882e24cd75SCong Wang if ((cl = __cls_set_class(&r->class, 0)) != 0) 18934e3759cSJiri Pirko q->ops->cl_ops->unbind_tcf(q, cl); 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds static inline void 1931da177e4SLinus Torvalds tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r) 1941da177e4SLinus Torvalds { 19534e3759cSJiri Pirko struct Qdisc *q = tp->chain->block->q; 1961da177e4SLinus Torvalds 19734e3759cSJiri Pirko if (!q) 19834e3759cSJiri Pirko return; 1992e24cd75SCong Wang __tcf_unbind_filter(q, r); 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds 202fd2c3ef7SEric Dumazet struct tcf_exts { 2031da177e4SLinus Torvalds #ifdef CONFIG_NET_CLS_ACT 20433be6271SWANG Cong __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ 20522dc13c8SWANG Cong int nr_actions; 20622dc13c8SWANG Cong struct tc_action **actions; 207e4b95c41SCong Wang struct net *net; 2081da177e4SLinus Torvalds #endif 2091da177e4SLinus Torvalds /* Map to export classifier specific extension TLV types to the 2101da177e4SLinus Torvalds * generic extensions API. Unsupported extensions must be set to 0. 2111da177e4SLinus Torvalds */ 2121da177e4SLinus Torvalds int action; 2131da177e4SLinus Torvalds int police; 2141da177e4SLinus Torvalds }; 2151da177e4SLinus Torvalds 21614215108SCong Wang static inline int tcf_exts_init(struct tcf_exts *exts, struct net *net, 21714215108SCong Wang int action, int police) 21833be6271SWANG Cong { 21933be6271SWANG Cong #ifdef CONFIG_NET_CLS_ACT 2205da57f42SWANG Cong exts->type = 0; 22122dc13c8SWANG Cong exts->nr_actions = 0; 22214215108SCong Wang exts->net = net; 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); 241e4b95c41SCong Wang return exts->net != NULL; 242e4b95c41SCong Wang #else 243e4b95c41SCong Wang return true; 244e4b95c41SCong Wang #endif 245e4b95c41SCong Wang } 246e4b95c41SCong Wang 247e4b95c41SCong Wang static inline void tcf_exts_put_net(struct tcf_exts *exts) 248e4b95c41SCong Wang { 249e4b95c41SCong Wang #ifdef CONFIG_NET_CLS_ACT 250e4b95c41SCong Wang if (exts->net) 251e4b95c41SCong Wang put_net(exts->net); 252e4b95c41SCong Wang #endif 253e4b95c41SCong Wang } 254e4b95c41SCong Wang 25522dc13c8SWANG Cong #ifdef CONFIG_NET_CLS_ACT 256244cd96aSCong Wang #define tcf_exts_for_each_action(i, a, exts) \ 257244cd96aSCong Wang for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = (exts)->actions[i]); i++) 258244cd96aSCong Wang #else 259244cd96aSCong Wang #define tcf_exts_for_each_action(i, a, exts) \ 260191672caSArnd Bergmann for (; 0; (void)(i), (void)(a), (void)(exts)) 26122dc13c8SWANG Cong #endif 26222dc13c8SWANG Cong 263d897a638SJakub Kicinski static inline void 264d897a638SJakub Kicinski tcf_exts_stats_update(const struct tcf_exts *exts, 2654b61d3e8SPo Liu u64 bytes, u64 packets, u64 drops, u64 lastuse, 26693a129ebSJiri Pirko u8 used_hw_stats, bool used_hw_stats_valid) 267d897a638SJakub Kicinski { 268d897a638SJakub Kicinski #ifdef CONFIG_NET_CLS_ACT 269d897a638SJakub Kicinski int i; 270d897a638SJakub Kicinski 271d897a638SJakub Kicinski preempt_disable(); 272d897a638SJakub Kicinski 273d897a638SJakub Kicinski for (i = 0; i < exts->nr_actions; i++) { 274d897a638SJakub Kicinski struct tc_action *a = exts->actions[i]; 275d897a638SJakub Kicinski 2764b61d3e8SPo Liu tcf_action_stats_update(a, bytes, packets, drops, 2774b61d3e8SPo Liu lastuse, true); 27893a129ebSJiri Pirko a->used_hw_stats = used_hw_stats; 27993a129ebSJiri Pirko a->used_hw_stats_valid = used_hw_stats_valid; 280d897a638SJakub Kicinski } 281d897a638SJakub Kicinski 282d897a638SJakub Kicinski preempt_enable(); 283d897a638SJakub Kicinski #endif 284d897a638SJakub Kicinski } 285d897a638SJakub Kicinski 2861da177e4SLinus Torvalds /** 2873bcc0cecSJiri Pirko * tcf_exts_has_actions - check if at least one action is present 2883bcc0cecSJiri Pirko * @exts: tc filter extensions handle 2893bcc0cecSJiri Pirko * 2903bcc0cecSJiri Pirko * Returns true if at least one action is present. 2913bcc0cecSJiri Pirko */ 2923bcc0cecSJiri Pirko static inline bool tcf_exts_has_actions(struct tcf_exts *exts) 2933bcc0cecSJiri Pirko { 2942734437eSWANG Cong #ifdef CONFIG_NET_CLS_ACT 2953bcc0cecSJiri Pirko return exts->nr_actions; 2963bcc0cecSJiri Pirko #else 2973bcc0cecSJiri Pirko return false; 2983bcc0cecSJiri Pirko #endif 2993bcc0cecSJiri Pirko } 3002734437eSWANG Cong 3013bcc0cecSJiri Pirko /** 302af69afc5SJiri Pirko * tcf_exts_exec - execute tc filter extensions 303af69afc5SJiri Pirko * @skb: socket buffer 304af69afc5SJiri Pirko * @exts: tc filter extensions handle 305af69afc5SJiri Pirko * @res: desired result 306af69afc5SJiri Pirko * 307af089e70SJiri Pirko * Executes all configured extensions. Returns TC_ACT_OK on a normal execution, 308af69afc5SJiri Pirko * a negative number if the filter must be considered unmatched or 309af69afc5SJiri Pirko * a positive action code (TC_ACT_*) which must be returned to the 310af69afc5SJiri Pirko * underlying layer. 311af69afc5SJiri Pirko */ 312af69afc5SJiri Pirko static inline int 313af69afc5SJiri Pirko tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, 314af69afc5SJiri Pirko struct tcf_result *res) 315af69afc5SJiri Pirko { 316af69afc5SJiri Pirko #ifdef CONFIG_NET_CLS_ACT 317ec1a9ccaSJiri Pirko return tcf_action_exec(skb, exts->actions, exts->nr_actions, res); 318af69afc5SJiri Pirko #endif 319af089e70SJiri Pirko return TC_ACT_OK; 320af69afc5SJiri Pirko } 321af69afc5SJiri Pirko 3225c15257fSJoe Perches int tcf_exts_validate(struct net *net, struct tcf_proto *tp, 323c1b52739SBenjamin LaHaise struct nlattr **tb, struct nlattr *rate_tlv, 324ec6743a1SVlad Buslov struct tcf_exts *exts, bool ovr, bool rtnl_held, 32550a56190SAlexander Aring struct netlink_ext_ack *extack); 32618d0264fSWANG Cong void tcf_exts_destroy(struct tcf_exts *exts); 3279b0d4446SJiri Pirko void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); 3285da57f42SWANG Cong int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); 329ca44b738SVlad Buslov int tcf_exts_terse_dump(struct sk_buff *skb, struct tcf_exts *exts); 3305da57f42SWANG Cong int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts); 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds /** 3331da177e4SLinus Torvalds * struct tcf_pkt_info - packet information 3341da177e4SLinus Torvalds */ 335fd2c3ef7SEric Dumazet struct tcf_pkt_info { 3361da177e4SLinus Torvalds unsigned char * ptr; 3371da177e4SLinus Torvalds int nexthdr; 3381da177e4SLinus Torvalds }; 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds #ifdef CONFIG_NET_EMATCH 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds struct tcf_ematch_ops; 3431da177e4SLinus Torvalds 3441da177e4SLinus Torvalds /** 3451da177e4SLinus Torvalds * struct tcf_ematch - extended match (ematch) 3461da177e4SLinus Torvalds * 3471da177e4SLinus Torvalds * @matchid: identifier to allow userspace to reidentify a match 3481da177e4SLinus Torvalds * @flags: flags specifying attributes and the relation to other matches 3491da177e4SLinus Torvalds * @ops: the operations lookup table of the corresponding ematch module 3501da177e4SLinus Torvalds * @datalen: length of the ematch specific configuration data 3511da177e4SLinus Torvalds * @data: ematch specific data 3521da177e4SLinus Torvalds */ 353fd2c3ef7SEric Dumazet struct tcf_ematch { 3541da177e4SLinus Torvalds struct tcf_ematch_ops * ops; 3551da177e4SLinus Torvalds unsigned long data; 3561da177e4SLinus Torvalds unsigned int datalen; 3571da177e4SLinus Torvalds u16 matchid; 3581da177e4SLinus Torvalds u16 flags; 35982a470f1SJohn Fastabend struct net *net; 3601da177e4SLinus Torvalds }; 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds static inline int tcf_em_is_container(struct tcf_ematch *em) 3631da177e4SLinus Torvalds { 3641da177e4SLinus Torvalds return !em->ops; 3651da177e4SLinus Torvalds } 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds static inline int tcf_em_is_simple(struct tcf_ematch *em) 3681da177e4SLinus Torvalds { 3691da177e4SLinus Torvalds return em->flags & TCF_EM_SIMPLE; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds static inline int tcf_em_is_inverted(struct tcf_ematch *em) 3731da177e4SLinus Torvalds { 3741da177e4SLinus Torvalds return em->flags & TCF_EM_INVERT; 3751da177e4SLinus Torvalds } 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds static inline int tcf_em_last_match(struct tcf_ematch *em) 3781da177e4SLinus Torvalds { 3791da177e4SLinus Torvalds return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END; 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds static inline int tcf_em_early_end(struct tcf_ematch *em, int result) 3831da177e4SLinus Torvalds { 3841da177e4SLinus Torvalds if (tcf_em_last_match(em)) 3851da177e4SLinus Torvalds return 1; 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds if (result == 0 && em->flags & TCF_EM_REL_AND) 3881da177e4SLinus Torvalds return 1; 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds if (result != 0 && em->flags & TCF_EM_REL_OR) 3911da177e4SLinus Torvalds return 1; 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds return 0; 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds /** 3971da177e4SLinus Torvalds * struct tcf_ematch_tree - ematch tree handle 3981da177e4SLinus Torvalds * 3991da177e4SLinus Torvalds * @hdr: ematch tree header supplied by userspace 4001da177e4SLinus Torvalds * @matches: array of ematches 4011da177e4SLinus Torvalds */ 402fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4031da177e4SLinus Torvalds struct tcf_ematch_tree_hdr hdr; 4041da177e4SLinus Torvalds struct tcf_ematch * matches; 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds }; 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds /** 4091da177e4SLinus Torvalds * struct tcf_ematch_ops - ematch module operations 4101da177e4SLinus Torvalds * 4111da177e4SLinus Torvalds * @kind: identifier (kind) of this ematch module 4121da177e4SLinus Torvalds * @datalen: length of expected configuration data (optional) 4131da177e4SLinus Torvalds * @change: called during validation (optional) 4141da177e4SLinus Torvalds * @match: called during ematch tree evaluation, must return 1/0 4151da177e4SLinus Torvalds * @destroy: called during destroyage (optional) 4161da177e4SLinus Torvalds * @dump: called during dumping process (optional) 4171da177e4SLinus Torvalds * @owner: owner, must be set to THIS_MODULE 4181da177e4SLinus Torvalds * @link: link to previous/next ematch module (internal use) 4191da177e4SLinus Torvalds */ 420fd2c3ef7SEric Dumazet struct tcf_ematch_ops { 4211da177e4SLinus Torvalds int kind; 4221da177e4SLinus Torvalds int datalen; 42382a470f1SJohn Fastabend int (*change)(struct net *net, void *, 4241da177e4SLinus Torvalds int, struct tcf_ematch *); 4251da177e4SLinus Torvalds int (*match)(struct sk_buff *, struct tcf_ematch *, 4261da177e4SLinus Torvalds struct tcf_pkt_info *); 42782a470f1SJohn Fastabend void (*destroy)(struct tcf_ematch *); 4281da177e4SLinus Torvalds int (*dump)(struct sk_buff *, struct tcf_ematch *); 4291da177e4SLinus Torvalds struct module *owner; 4301da177e4SLinus Torvalds struct list_head link; 4311da177e4SLinus Torvalds }; 4321da177e4SLinus Torvalds 4335c15257fSJoe Perches int tcf_em_register(struct tcf_ematch_ops *); 4345c15257fSJoe Perches void tcf_em_unregister(struct tcf_ematch_ops *); 4355c15257fSJoe Perches int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *, 4361da177e4SLinus Torvalds struct tcf_ematch_tree *); 43782a470f1SJohn Fastabend void tcf_em_tree_destroy(struct tcf_ematch_tree *); 4385c15257fSJoe Perches int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int); 4395c15257fSJoe Perches int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *, 4401da177e4SLinus Torvalds struct tcf_pkt_info *); 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds /** 4431da177e4SLinus Torvalds * tcf_em_tree_match - evaulate an ematch tree 4441da177e4SLinus Torvalds * 4451da177e4SLinus Torvalds * @skb: socket buffer of the packet in question 4461da177e4SLinus Torvalds * @tree: ematch tree to be used for evaluation 4471da177e4SLinus Torvalds * @info: packet information examined by classifier 4481da177e4SLinus Torvalds * 4491da177e4SLinus Torvalds * This function matches @skb against the ematch tree in @tree by going 4501da177e4SLinus Torvalds * through all ematches respecting their logic relations returning 4511da177e4SLinus Torvalds * as soon as the result is obvious. 4521da177e4SLinus Torvalds * 4531da177e4SLinus Torvalds * Returns 1 if the ematch tree as-one matches, no ematches are configured 4541da177e4SLinus Torvalds * or ematch is not enabled in the kernel, otherwise 0 is returned. 4551da177e4SLinus Torvalds */ 4561da177e4SLinus Torvalds static inline int tcf_em_tree_match(struct sk_buff *skb, 4571da177e4SLinus Torvalds struct tcf_ematch_tree *tree, 4581da177e4SLinus Torvalds struct tcf_pkt_info *info) 4591da177e4SLinus Torvalds { 4601da177e4SLinus Torvalds if (tree->hdr.nmatches) 4611da177e4SLinus Torvalds return __tcf_em_tree_match(skb, tree, info); 4621da177e4SLinus Torvalds else 4631da177e4SLinus Torvalds return 1; 4641da177e4SLinus Torvalds } 4651da177e4SLinus Torvalds 466db3d99c0SPatrick McHardy #define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind)) 467db3d99c0SPatrick McHardy 4681da177e4SLinus Torvalds #else /* CONFIG_NET_EMATCH */ 4691da177e4SLinus Torvalds 470fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4711da177e4SLinus Torvalds }; 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0) 47482a470f1SJohn Fastabend #define tcf_em_tree_destroy(t) do { (void)(t); } while(0) 4751da177e4SLinus Torvalds #define tcf_em_tree_dump(skb, t, tlv) (0) 4761da177e4SLinus Torvalds #define tcf_em_tree_match(skb, t, info) ((void)(info), 1) 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds #endif /* CONFIG_NET_EMATCH */ 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) 4811da177e4SLinus Torvalds { 4821da177e4SLinus Torvalds switch (layer) { 4831da177e4SLinus Torvalds case TCF_LAYER_LINK: 484d3303a65SWolfgang Bumiller return skb_mac_header(skb); 4851da177e4SLinus Torvalds case TCF_LAYER_NETWORK: 486d56f90a7SArnaldo Carvalho de Melo return skb_network_header(skb); 4871da177e4SLinus Torvalds case TCF_LAYER_TRANSPORT: 4889c70220bSArnaldo Carvalho de Melo return skb_transport_header(skb); 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds 4911da177e4SLinus Torvalds return NULL; 4921da177e4SLinus Torvalds } 4931da177e4SLinus Torvalds 494eddc9ec5SArnaldo Carvalho de Melo static inline int tcf_valid_offset(const struct sk_buff *skb, 495eddc9ec5SArnaldo Carvalho de Melo const unsigned char *ptr, const int len) 4961da177e4SLinus Torvalds { 497da521b2cSDavid S. Miller return likely((ptr + len) <= skb_tail_pointer(skb) && 498da521b2cSDavid S. Miller ptr >= skb->head && 499da521b2cSDavid S. Miller (ptr <= (ptr + len))); 5001da177e4SLinus Torvalds } 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds static inline int 5031057c55fSAlexander Aring tcf_change_indev(struct net *net, struct nlattr *indev_tlv, 5041057c55fSAlexander Aring struct netlink_ext_ack *extack) 5051da177e4SLinus Torvalds { 5062519a602SWANG Cong char indev[IFNAMSIZ]; 507c01003c2SPatrick McHardy struct net_device *dev; 508c01003c2SPatrick McHardy 5091057c55fSAlexander Aring if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) { 510e4a58ef3SGuillaume Nault NL_SET_ERR_MSG_ATTR(extack, indev_tlv, 511e4a58ef3SGuillaume Nault "Interface name too long"); 5122519a602SWANG Cong return -EINVAL; 5131057c55fSAlexander Aring } 5142519a602SWANG Cong dev = __dev_get_by_name(net, indev); 515e4a58ef3SGuillaume Nault if (!dev) { 516e4a58ef3SGuillaume Nault NL_SET_ERR_MSG_ATTR(extack, indev_tlv, 517e4a58ef3SGuillaume Nault "Network device not found"); 5182519a602SWANG Cong return -ENODEV; 519e4a58ef3SGuillaume Nault } 5202519a602SWANG Cong return dev->ifindex; 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds 5232519a602SWANG Cong static inline bool 5242519a602SWANG Cong tcf_match_indev(struct sk_buff *skb, int ifindex) 5252519a602SWANG Cong { 5262519a602SWANG Cong if (!ifindex) 5272519a602SWANG Cong return true; 5282519a602SWANG Cong if (!skb->skb_iif) 5292519a602SWANG Cong return false; 5302519a602SWANG Cong return ifindex == skb->skb_iif; 5311da177e4SLinus Torvalds } 5321da177e4SLinus Torvalds 5333a7b6861SPablo Neira Ayuso int tc_setup_flow_action(struct flow_action *flow_action, 534b15e7a6eSVlad Buslov const struct tcf_exts *exts); 5355a6ff4b1SVlad Buslov void tc_cleanup_flow_action(struct flow_action *flow_action); 5365a6ff4b1SVlad Buslov 537aeb3fecdSCong Wang int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, 53840119211SVlad Buslov void *type_data, bool err_stop, bool rtnl_held); 53940119211SVlad Buslov int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp, 54040119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 54140119211SVlad Buslov u32 *flags, unsigned int *in_hw_count, bool rtnl_held); 54240119211SVlad Buslov int tc_setup_cb_replace(struct tcf_block *block, struct tcf_proto *tp, 54340119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 54440119211SVlad Buslov u32 *old_flags, unsigned int *old_in_hw_count, 54540119211SVlad Buslov u32 *new_flags, unsigned int *new_in_hw_count, 54640119211SVlad Buslov bool rtnl_held); 54740119211SVlad Buslov int tc_setup_cb_destroy(struct tcf_block *block, struct tcf_proto *tp, 54840119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 54940119211SVlad Buslov u32 *flags, unsigned int *in_hw_count, bool rtnl_held); 55040119211SVlad Buslov int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp, 55140119211SVlad Buslov bool add, flow_setup_cb_t *cb, 55240119211SVlad Buslov enum tc_setup_type type, void *type_data, 55340119211SVlad Buslov void *cb_priv, u32 *flags, unsigned int *in_hw_count); 554e3ab786bSPablo Neira Ayuso unsigned int tcf_exts_num_actions(struct tcf_exts *exts); 555717503b9SJiri Pirko 556a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode { 557a1b7c5fdSJohn Fastabend struct tcf_exts *exts; 558068ceb35SJakub Kicinski struct tcf_result *res; 559e014860eSJohn Fastabend struct tc_u32_sel *sel; 560a1b7c5fdSJohn Fastabend u32 handle; 561a1b7c5fdSJohn Fastabend u32 val; 562a1b7c5fdSJohn Fastabend u32 mask; 563a1b7c5fdSJohn Fastabend u32 link_handle; 564e014860eSJohn Fastabend u8 fshift; 565a1b7c5fdSJohn Fastabend }; 566a1b7c5fdSJohn Fastabend 567a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode { 568a1b7c5fdSJohn Fastabend u32 handle; 569a1b7c5fdSJohn Fastabend u32 prio; 570a1b7c5fdSJohn Fastabend unsigned int divisor; 571a1b7c5fdSJohn Fastabend }; 572a1b7c5fdSJohn Fastabend 573a1b7c5fdSJohn Fastabend enum tc_clsu32_command { 574a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_KNODE, 575a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_KNODE, 576a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_KNODE, 577a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_HNODE, 578a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_HNODE, 579a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_HNODE, 580a1b7c5fdSJohn Fastabend }; 581a1b7c5fdSJohn Fastabend 582a1b7c5fdSJohn Fastabend struct tc_cls_u32_offload { 583f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 584a1b7c5fdSJohn Fastabend /* knode values */ 585a1b7c5fdSJohn Fastabend enum tc_clsu32_command command; 586a1b7c5fdSJohn Fastabend union { 587a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode knode; 588a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode hnode; 589a1b7c5fdSJohn Fastabend }; 590a1b7c5fdSJohn Fastabend }; 591a1b7c5fdSJohn Fastabend 5927b06e8aeSJiri Pirko static inline bool tc_can_offload(const struct net_device *dev) 5936843e7a2SJohn Fastabend { 59470b5aee4SJiri Pirko return dev->features & NETIF_F_HW_TC; 5956843e7a2SJohn Fastabend } 5966843e7a2SJohn Fastabend 597f9eda14fSQuentin Monnet static inline bool tc_can_offload_extack(const struct net_device *dev, 598f9eda14fSQuentin Monnet struct netlink_ext_ack *extack) 599f9eda14fSQuentin Monnet { 600f9eda14fSQuentin Monnet bool can = tc_can_offload(dev); 601f9eda14fSQuentin Monnet 602f9eda14fSQuentin Monnet if (!can) 603f9eda14fSQuentin Monnet NL_SET_ERR_MSG(extack, "TC offload is disabled on net device"); 604f9eda14fSQuentin Monnet 605f9eda14fSQuentin Monnet return can; 606f9eda14fSQuentin Monnet } 607f9eda14fSQuentin Monnet 608878db9f0SJakub Kicinski static inline bool 609878db9f0SJakub Kicinski tc_cls_can_offload_and_chain0(const struct net_device *dev, 610f9e30088SPablo Neira Ayuso struct flow_cls_common_offload *common) 611878db9f0SJakub Kicinski { 612878db9f0SJakub Kicinski if (!tc_can_offload_extack(dev, common->extack)) 613878db9f0SJakub Kicinski return false; 614878db9f0SJakub Kicinski if (common->chain_index) { 615878db9f0SJakub Kicinski NL_SET_ERR_MSG(common->extack, 616878db9f0SJakub Kicinski "Driver supports only offload of chain 0"); 617878db9f0SJakub Kicinski return false; 618878db9f0SJakub Kicinski } 619878db9f0SJakub Kicinski return true; 620878db9f0SJakub Kicinski } 621878db9f0SJakub Kicinski 62255330f05SHadar Hen Zion static inline bool tc_skip_hw(u32 flags) 62355330f05SHadar Hen Zion { 62455330f05SHadar Hen Zion return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; 62555330f05SHadar Hen Zion } 62655330f05SHadar Hen Zion 627d34e3e18SSamudrala, Sridhar static inline bool tc_skip_sw(u32 flags) 628d34e3e18SSamudrala, Sridhar { 629d34e3e18SSamudrala, Sridhar return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false; 630d34e3e18SSamudrala, Sridhar } 631d34e3e18SSamudrala, Sridhar 632d34e3e18SSamudrala, Sridhar /* SKIP_HW and SKIP_SW are mutually exclusive flags. */ 633d34e3e18SSamudrala, Sridhar static inline bool tc_flags_valid(u32 flags) 634d34e3e18SSamudrala, Sridhar { 63581c7288bSMarcelo Ricardo Leitner if (flags & ~(TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW | 63681c7288bSMarcelo Ricardo Leitner TCA_CLS_FLAGS_VERBOSE)) 637d34e3e18SSamudrala, Sridhar return false; 638d34e3e18SSamudrala, Sridhar 63981c7288bSMarcelo Ricardo Leitner flags &= TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW; 640d34e3e18SSamudrala, Sridhar if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW))) 641d34e3e18SSamudrala, Sridhar return false; 642d34e3e18SSamudrala, Sridhar 643d34e3e18SSamudrala, Sridhar return true; 644d34e3e18SSamudrala, Sridhar } 645d34e3e18SSamudrala, Sridhar 646e696028aSOr Gerlitz static inline bool tc_in_hw(u32 flags) 647e696028aSOr Gerlitz { 648e696028aSOr Gerlitz return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; 649e696028aSOr Gerlitz } 650e696028aSOr Gerlitz 65134832e1cSJakub Kicinski static inline void 652f9e30088SPablo Neira Ayuso tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common, 65334832e1cSJakub Kicinski const struct tcf_proto *tp, u32 flags, 65434832e1cSJakub Kicinski struct netlink_ext_ack *extack) 65534832e1cSJakub Kicinski { 65634832e1cSJakub Kicinski cls_common->chain_index = tp->chain->index; 65734832e1cSJakub Kicinski cls_common->protocol = tp->protocol; 658ef01adaeSPablo Neira Ayuso cls_common->prio = tp->prio >> 16; 65981c7288bSMarcelo Ricardo Leitner if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE) 66034832e1cSJakub Kicinski cls_common->extack = extack; 66134832e1cSJakub Kicinski } 66234832e1cSJakub Kicinski 663b87f7936SYotam Gigi enum tc_matchall_command { 664b87f7936SYotam Gigi TC_CLSMATCHALL_REPLACE, 665b87f7936SYotam Gigi TC_CLSMATCHALL_DESTROY, 666b7fe4ab8SPieter Jansen van Vuuren TC_CLSMATCHALL_STATS, 667b87f7936SYotam Gigi }; 668b87f7936SYotam Gigi 669b87f7936SYotam Gigi struct tc_cls_matchall_offload { 670f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 671b87f7936SYotam Gigi enum tc_matchall_command command; 672f00cbf19SPieter Jansen van Vuuren struct flow_rule *rule; 673b7fe4ab8SPieter Jansen van Vuuren struct flow_stats stats; 674b87f7936SYotam Gigi unsigned long cookie; 675b87f7936SYotam Gigi }; 676b87f7936SYotam Gigi 677332ae8e2SJakub Kicinski enum tc_clsbpf_command { 678102740bdSJakub Kicinski TC_CLSBPF_OFFLOAD, 67968d64063SJakub Kicinski TC_CLSBPF_STATS, 680332ae8e2SJakub Kicinski }; 681332ae8e2SJakub Kicinski 682332ae8e2SJakub Kicinski struct tc_cls_bpf_offload { 683f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 684332ae8e2SJakub Kicinski enum tc_clsbpf_command command; 685332ae8e2SJakub Kicinski struct tcf_exts *exts; 686332ae8e2SJakub Kicinski struct bpf_prog *prog; 687102740bdSJakub Kicinski struct bpf_prog *oldprog; 688332ae8e2SJakub Kicinski const char *name; 689332ae8e2SJakub Kicinski bool exts_integrated; 690332ae8e2SJakub Kicinski }; 691332ae8e2SJakub Kicinski 6924e8b86c0SAmritha Nambiar struct tc_mqprio_qopt_offload { 6934e8b86c0SAmritha Nambiar /* struct tc_mqprio_qopt must always be the first element */ 6944e8b86c0SAmritha Nambiar struct tc_mqprio_qopt qopt; 6954e8b86c0SAmritha Nambiar u16 mode; 6964e8b86c0SAmritha Nambiar u16 shaper; 6974e8b86c0SAmritha Nambiar u32 flags; 6984e8b86c0SAmritha Nambiar u64 min_rate[TC_QOPT_MAX_QUEUE]; 6994e8b86c0SAmritha Nambiar u64 max_rate[TC_QOPT_MAX_QUEUE]; 7004e8b86c0SAmritha Nambiar }; 7011045ba77SJamal Hadi Salim 7021045ba77SJamal Hadi Salim /* This structure holds cookie structure that is passed from user 7031045ba77SJamal Hadi Salim * to the kernel for actions and classifiers 7041045ba77SJamal Hadi Salim */ 7051045ba77SJamal Hadi Salim struct tc_cookie { 7061045ba77SJamal Hadi Salim u8 *data; 7071045ba77SJamal Hadi Salim u32 len; 708eec94fdbSVlad Buslov struct rcu_head rcu; 7091045ba77SJamal Hadi Salim }; 710602f3bafSNogah Frankel 711f34b4aacSNogah Frankel struct tc_qopt_offload_stats { 712f34b4aacSNogah Frankel struct gnet_stats_basic_packed *bstats; 713f34b4aacSNogah Frankel struct gnet_stats_queue *qstats; 714f34b4aacSNogah Frankel }; 715f34b4aacSNogah Frankel 716f971b132SJakub Kicinski enum tc_mq_command { 717f971b132SJakub Kicinski TC_MQ_CREATE, 718f971b132SJakub Kicinski TC_MQ_DESTROY, 71947c669a4SJakub Kicinski TC_MQ_STATS, 720d577a3d2SJakub Kicinski TC_MQ_GRAFT, 721d577a3d2SJakub Kicinski }; 722d577a3d2SJakub Kicinski 723d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params { 724d577a3d2SJakub Kicinski unsigned long queue; 725d577a3d2SJakub Kicinski u32 child_handle; 726f971b132SJakub Kicinski }; 727f971b132SJakub Kicinski 728f971b132SJakub Kicinski struct tc_mq_qopt_offload { 729f971b132SJakub Kicinski enum tc_mq_command command; 730f971b132SJakub Kicinski u32 handle; 731d577a3d2SJakub Kicinski union { 73247c669a4SJakub Kicinski struct tc_qopt_offload_stats stats; 733d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params graft_params; 734d577a3d2SJakub Kicinski }; 735f971b132SJakub Kicinski }; 736f971b132SJakub Kicinski 737602f3bafSNogah Frankel enum tc_red_command { 738602f3bafSNogah Frankel TC_RED_REPLACE, 739602f3bafSNogah Frankel TC_RED_DESTROY, 740602f3bafSNogah Frankel TC_RED_STATS, 741602f3bafSNogah Frankel TC_RED_XSTATS, 742bf2a752bSJakub Kicinski TC_RED_GRAFT, 743602f3bafSNogah Frankel }; 744602f3bafSNogah Frankel 745602f3bafSNogah Frankel struct tc_red_qopt_offload_params { 746602f3bafSNogah Frankel u32 min; 747602f3bafSNogah Frankel u32 max; 748602f3bafSNogah Frankel u32 probability; 749c0b7490bSJakub Kicinski u32 limit; 750602f3bafSNogah Frankel bool is_ecn; 751190852a5SJakub Kicinski bool is_harddrop; 7520a7fad23SPetr Machata bool is_nodrop; 753416ef9b1SJakub Kicinski struct gnet_stats_queue *qstats; 754602f3bafSNogah Frankel }; 755602f3bafSNogah Frankel 756602f3bafSNogah Frankel struct tc_red_qopt_offload { 757602f3bafSNogah Frankel enum tc_red_command command; 758602f3bafSNogah Frankel u32 handle; 759602f3bafSNogah Frankel u32 parent; 760602f3bafSNogah Frankel union { 761602f3bafSNogah Frankel struct tc_red_qopt_offload_params set; 762f34b4aacSNogah Frankel struct tc_qopt_offload_stats stats; 763602f3bafSNogah Frankel struct red_stats *xstats; 764bf2a752bSJakub Kicinski u32 child_handle; 765602f3bafSNogah Frankel }; 766602f3bafSNogah Frankel }; 767602f3bafSNogah Frankel 768890d8d23SJakub Kicinski enum tc_gred_command { 769890d8d23SJakub Kicinski TC_GRED_REPLACE, 770890d8d23SJakub Kicinski TC_GRED_DESTROY, 771e49efd52SJakub Kicinski TC_GRED_STATS, 772890d8d23SJakub Kicinski }; 773890d8d23SJakub Kicinski 774890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params { 775890d8d23SJakub Kicinski bool present; 776890d8d23SJakub Kicinski u32 limit; 777890d8d23SJakub Kicinski u32 prio; 778890d8d23SJakub Kicinski u32 min; 779890d8d23SJakub Kicinski u32 max; 780890d8d23SJakub Kicinski bool is_ecn; 781890d8d23SJakub Kicinski bool is_harddrop; 782890d8d23SJakub Kicinski u32 probability; 783890d8d23SJakub Kicinski /* Only need backlog, see struct tc_prio_qopt_offload_params */ 784890d8d23SJakub Kicinski u32 *backlog; 785890d8d23SJakub Kicinski }; 786890d8d23SJakub Kicinski 787890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params { 788890d8d23SJakub Kicinski bool grio_on; 789890d8d23SJakub Kicinski bool wred_on; 790890d8d23SJakub Kicinski unsigned int dp_cnt; 791890d8d23SJakub Kicinski unsigned int dp_def; 792890d8d23SJakub Kicinski struct gnet_stats_queue *qstats; 793890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params tab[MAX_DPs]; 794890d8d23SJakub Kicinski }; 795890d8d23SJakub Kicinski 796e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats { 797e49efd52SJakub Kicinski struct gnet_stats_basic_packed bstats[MAX_DPs]; 798e49efd52SJakub Kicinski struct gnet_stats_queue qstats[MAX_DPs]; 799e49efd52SJakub Kicinski struct red_stats *xstats[MAX_DPs]; 800e49efd52SJakub Kicinski }; 801e49efd52SJakub Kicinski 802890d8d23SJakub Kicinski struct tc_gred_qopt_offload { 803890d8d23SJakub Kicinski enum tc_gred_command command; 804890d8d23SJakub Kicinski u32 handle; 805890d8d23SJakub Kicinski u32 parent; 806890d8d23SJakub Kicinski union { 807890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params set; 808e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats stats; 809890d8d23SJakub Kicinski }; 810890d8d23SJakub Kicinski }; 811890d8d23SJakub Kicinski 8127fdb61b4SNogah Frankel enum tc_prio_command { 8137fdb61b4SNogah Frankel TC_PRIO_REPLACE, 8147fdb61b4SNogah Frankel TC_PRIO_DESTROY, 8157fdb61b4SNogah Frankel TC_PRIO_STATS, 816b9c7a7acSNogah Frankel TC_PRIO_GRAFT, 8177fdb61b4SNogah Frankel }; 8187fdb61b4SNogah Frankel 8197fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params { 8207fdb61b4SNogah Frankel int bands; 8217fdb61b4SNogah Frankel u8 priomap[TC_PRIO_MAX + 1]; 8229586a992SPetr Machata /* At the point of un-offloading the Qdisc, the reported backlog and 8239586a992SPetr Machata * qlen need to be reduced by the portion that is in HW. 8247fdb61b4SNogah Frankel */ 8257fdb61b4SNogah Frankel struct gnet_stats_queue *qstats; 8267fdb61b4SNogah Frankel }; 8277fdb61b4SNogah Frankel 828b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params { 829b9c7a7acSNogah Frankel u8 band; 830b9c7a7acSNogah Frankel u32 child_handle; 831b9c7a7acSNogah Frankel }; 832b9c7a7acSNogah Frankel 8337fdb61b4SNogah Frankel struct tc_prio_qopt_offload { 8347fdb61b4SNogah Frankel enum tc_prio_command command; 8357fdb61b4SNogah Frankel u32 handle; 8367fdb61b4SNogah Frankel u32 parent; 8377fdb61b4SNogah Frankel union { 8387fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params replace_params; 8397fdb61b4SNogah Frankel struct tc_qopt_offload_stats stats; 840b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params graft_params; 8417fdb61b4SNogah Frankel }; 8427fdb61b4SNogah Frankel }; 843b9c7a7acSNogah Frankel 84498b0e5f6SJakub Kicinski enum tc_root_command { 84598b0e5f6SJakub Kicinski TC_ROOT_GRAFT, 84698b0e5f6SJakub Kicinski }; 84798b0e5f6SJakub Kicinski 84898b0e5f6SJakub Kicinski struct tc_root_qopt_offload { 84998b0e5f6SJakub Kicinski enum tc_root_command command; 85098b0e5f6SJakub Kicinski u32 handle; 85198b0e5f6SJakub Kicinski bool ingress; 85298b0e5f6SJakub Kicinski }; 85398b0e5f6SJakub Kicinski 854d35eb52bSPetr Machata enum tc_ets_command { 855d35eb52bSPetr Machata TC_ETS_REPLACE, 856d35eb52bSPetr Machata TC_ETS_DESTROY, 857d35eb52bSPetr Machata TC_ETS_STATS, 858d35eb52bSPetr Machata TC_ETS_GRAFT, 859d35eb52bSPetr Machata }; 860d35eb52bSPetr Machata 861d35eb52bSPetr Machata struct tc_ets_qopt_offload_replace_params { 862d35eb52bSPetr Machata unsigned int bands; 863d35eb52bSPetr Machata u8 priomap[TC_PRIO_MAX + 1]; 864d35eb52bSPetr Machata unsigned int quanta[TCQ_ETS_MAX_BANDS]; /* 0 for strict bands. */ 865d35eb52bSPetr Machata unsigned int weights[TCQ_ETS_MAX_BANDS]; 866d35eb52bSPetr Machata struct gnet_stats_queue *qstats; 867d35eb52bSPetr Machata }; 868d35eb52bSPetr Machata 869d35eb52bSPetr Machata struct tc_ets_qopt_offload_graft_params { 870d35eb52bSPetr Machata u8 band; 871d35eb52bSPetr Machata u32 child_handle; 872d35eb52bSPetr Machata }; 873d35eb52bSPetr Machata 874d35eb52bSPetr Machata struct tc_ets_qopt_offload { 875d35eb52bSPetr Machata enum tc_ets_command command; 876d35eb52bSPetr Machata u32 handle; 877d35eb52bSPetr Machata u32 parent; 878d35eb52bSPetr Machata union { 879d35eb52bSPetr Machata struct tc_ets_qopt_offload_replace_params replace_params; 880d35eb52bSPetr Machata struct tc_qopt_offload_stats stats; 881d35eb52bSPetr Machata struct tc_ets_qopt_offload_graft_params graft_params; 882d35eb52bSPetr Machata }; 883d35eb52bSPetr Machata }; 884d35eb52bSPetr Machata 885ef6aadccSPetr Machata enum tc_tbf_command { 886ef6aadccSPetr Machata TC_TBF_REPLACE, 887ef6aadccSPetr Machata TC_TBF_DESTROY, 888ef6aadccSPetr Machata TC_TBF_STATS, 889ef6aadccSPetr Machata }; 890ef6aadccSPetr Machata 891ef6aadccSPetr Machata struct tc_tbf_qopt_offload_replace_params { 892ef6aadccSPetr Machata struct psched_ratecfg rate; 893ef6aadccSPetr Machata u32 max_size; 894ef6aadccSPetr Machata struct gnet_stats_queue *qstats; 895ef6aadccSPetr Machata }; 896ef6aadccSPetr Machata 897ef6aadccSPetr Machata struct tc_tbf_qopt_offload { 898ef6aadccSPetr Machata enum tc_tbf_command command; 899ef6aadccSPetr Machata u32 handle; 900ef6aadccSPetr Machata u32 parent; 901ef6aadccSPetr Machata union { 902ef6aadccSPetr Machata struct tc_tbf_qopt_offload_replace_params replace_params; 903ef6aadccSPetr Machata struct tc_qopt_offload_stats stats; 904ef6aadccSPetr Machata }; 905ef6aadccSPetr Machata }; 906ef6aadccSPetr Machata 907aaca9408SPetr Machata enum tc_fifo_command { 908aaca9408SPetr Machata TC_FIFO_REPLACE, 909aaca9408SPetr Machata TC_FIFO_DESTROY, 910aaca9408SPetr Machata TC_FIFO_STATS, 911aaca9408SPetr Machata }; 912aaca9408SPetr Machata 913aaca9408SPetr Machata struct tc_fifo_qopt_offload { 914aaca9408SPetr Machata enum tc_fifo_command command; 915aaca9408SPetr Machata u32 handle; 916aaca9408SPetr Machata u32 parent; 917aaca9408SPetr Machata union { 918aaca9408SPetr Machata struct tc_qopt_offload_stats stats; 919aaca9408SPetr Machata }; 920aaca9408SPetr Machata }; 921aaca9408SPetr Machata 9221da177e4SLinus Torvalds #endif 923