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, 26593a129ebSJiri Pirko u64 bytes, u64 packets, 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 27628169abaSEelco Chaudron tcf_action_stats_update(a, bytes, packets, lastuse, true); 27793a129ebSJiri Pirko a->used_hw_stats = used_hw_stats; 27893a129ebSJiri Pirko a->used_hw_stats_valid = used_hw_stats_valid; 279d897a638SJakub Kicinski } 280d897a638SJakub Kicinski 281d897a638SJakub Kicinski preempt_enable(); 282d897a638SJakub Kicinski #endif 283d897a638SJakub Kicinski } 284d897a638SJakub Kicinski 2851da177e4SLinus Torvalds /** 2863bcc0cecSJiri Pirko * tcf_exts_has_actions - check if at least one action is present 2873bcc0cecSJiri Pirko * @exts: tc filter extensions handle 2883bcc0cecSJiri Pirko * 2893bcc0cecSJiri Pirko * Returns true if at least one action is present. 2903bcc0cecSJiri Pirko */ 2913bcc0cecSJiri Pirko static inline bool tcf_exts_has_actions(struct tcf_exts *exts) 2923bcc0cecSJiri Pirko { 2932734437eSWANG Cong #ifdef CONFIG_NET_CLS_ACT 2943bcc0cecSJiri Pirko return exts->nr_actions; 2953bcc0cecSJiri Pirko #else 2963bcc0cecSJiri Pirko return false; 2973bcc0cecSJiri Pirko #endif 2983bcc0cecSJiri Pirko } 2992734437eSWANG Cong 3003bcc0cecSJiri Pirko /** 301af69afc5SJiri Pirko * tcf_exts_exec - execute tc filter extensions 302af69afc5SJiri Pirko * @skb: socket buffer 303af69afc5SJiri Pirko * @exts: tc filter extensions handle 304af69afc5SJiri Pirko * @res: desired result 305af69afc5SJiri Pirko * 306af089e70SJiri Pirko * Executes all configured extensions. Returns TC_ACT_OK on a normal execution, 307af69afc5SJiri Pirko * a negative number if the filter must be considered unmatched or 308af69afc5SJiri Pirko * a positive action code (TC_ACT_*) which must be returned to the 309af69afc5SJiri Pirko * underlying layer. 310af69afc5SJiri Pirko */ 311af69afc5SJiri Pirko static inline int 312af69afc5SJiri Pirko tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, 313af69afc5SJiri Pirko struct tcf_result *res) 314af69afc5SJiri Pirko { 315af69afc5SJiri Pirko #ifdef CONFIG_NET_CLS_ACT 316ec1a9ccaSJiri Pirko return tcf_action_exec(skb, exts->actions, exts->nr_actions, res); 317af69afc5SJiri Pirko #endif 318af089e70SJiri Pirko return TC_ACT_OK; 319af69afc5SJiri Pirko } 320af69afc5SJiri Pirko 3215c15257fSJoe Perches int tcf_exts_validate(struct net *net, struct tcf_proto *tp, 322c1b52739SBenjamin LaHaise struct nlattr **tb, struct nlattr *rate_tlv, 323ec6743a1SVlad Buslov struct tcf_exts *exts, bool ovr, bool rtnl_held, 32450a56190SAlexander Aring struct netlink_ext_ack *extack); 32518d0264fSWANG Cong void tcf_exts_destroy(struct tcf_exts *exts); 3269b0d4446SJiri Pirko void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); 3275da57f42SWANG Cong int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); 3285da57f42SWANG Cong int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts); 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds /** 3311da177e4SLinus Torvalds * struct tcf_pkt_info - packet information 3321da177e4SLinus Torvalds */ 333fd2c3ef7SEric Dumazet struct tcf_pkt_info { 3341da177e4SLinus Torvalds unsigned char * ptr; 3351da177e4SLinus Torvalds int nexthdr; 3361da177e4SLinus Torvalds }; 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds #ifdef CONFIG_NET_EMATCH 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds struct tcf_ematch_ops; 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds /** 3431da177e4SLinus Torvalds * struct tcf_ematch - extended match (ematch) 3441da177e4SLinus Torvalds * 3451da177e4SLinus Torvalds * @matchid: identifier to allow userspace to reidentify a match 3461da177e4SLinus Torvalds * @flags: flags specifying attributes and the relation to other matches 3471da177e4SLinus Torvalds * @ops: the operations lookup table of the corresponding ematch module 3481da177e4SLinus Torvalds * @datalen: length of the ematch specific configuration data 3491da177e4SLinus Torvalds * @data: ematch specific data 3501da177e4SLinus Torvalds */ 351fd2c3ef7SEric Dumazet struct tcf_ematch { 3521da177e4SLinus Torvalds struct tcf_ematch_ops * ops; 3531da177e4SLinus Torvalds unsigned long data; 3541da177e4SLinus Torvalds unsigned int datalen; 3551da177e4SLinus Torvalds u16 matchid; 3561da177e4SLinus Torvalds u16 flags; 35782a470f1SJohn Fastabend struct net *net; 3581da177e4SLinus Torvalds }; 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds static inline int tcf_em_is_container(struct tcf_ematch *em) 3611da177e4SLinus Torvalds { 3621da177e4SLinus Torvalds return !em->ops; 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds static inline int tcf_em_is_simple(struct tcf_ematch *em) 3661da177e4SLinus Torvalds { 3671da177e4SLinus Torvalds return em->flags & TCF_EM_SIMPLE; 3681da177e4SLinus Torvalds } 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds static inline int tcf_em_is_inverted(struct tcf_ematch *em) 3711da177e4SLinus Torvalds { 3721da177e4SLinus Torvalds return em->flags & TCF_EM_INVERT; 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds static inline int tcf_em_last_match(struct tcf_ematch *em) 3761da177e4SLinus Torvalds { 3771da177e4SLinus Torvalds return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END; 3781da177e4SLinus Torvalds } 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds static inline int tcf_em_early_end(struct tcf_ematch *em, int result) 3811da177e4SLinus Torvalds { 3821da177e4SLinus Torvalds if (tcf_em_last_match(em)) 3831da177e4SLinus Torvalds return 1; 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds if (result == 0 && em->flags & TCF_EM_REL_AND) 3861da177e4SLinus Torvalds return 1; 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds if (result != 0 && em->flags & TCF_EM_REL_OR) 3891da177e4SLinus Torvalds return 1; 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds return 0; 3921da177e4SLinus Torvalds } 3931da177e4SLinus Torvalds 3941da177e4SLinus Torvalds /** 3951da177e4SLinus Torvalds * struct tcf_ematch_tree - ematch tree handle 3961da177e4SLinus Torvalds * 3971da177e4SLinus Torvalds * @hdr: ematch tree header supplied by userspace 3981da177e4SLinus Torvalds * @matches: array of ematches 3991da177e4SLinus Torvalds */ 400fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4011da177e4SLinus Torvalds struct tcf_ematch_tree_hdr hdr; 4021da177e4SLinus Torvalds struct tcf_ematch * matches; 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds }; 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds /** 4071da177e4SLinus Torvalds * struct tcf_ematch_ops - ematch module operations 4081da177e4SLinus Torvalds * 4091da177e4SLinus Torvalds * @kind: identifier (kind) of this ematch module 4101da177e4SLinus Torvalds * @datalen: length of expected configuration data (optional) 4111da177e4SLinus Torvalds * @change: called during validation (optional) 4121da177e4SLinus Torvalds * @match: called during ematch tree evaluation, must return 1/0 4131da177e4SLinus Torvalds * @destroy: called during destroyage (optional) 4141da177e4SLinus Torvalds * @dump: called during dumping process (optional) 4151da177e4SLinus Torvalds * @owner: owner, must be set to THIS_MODULE 4161da177e4SLinus Torvalds * @link: link to previous/next ematch module (internal use) 4171da177e4SLinus Torvalds */ 418fd2c3ef7SEric Dumazet struct tcf_ematch_ops { 4191da177e4SLinus Torvalds int kind; 4201da177e4SLinus Torvalds int datalen; 42182a470f1SJohn Fastabend int (*change)(struct net *net, void *, 4221da177e4SLinus Torvalds int, struct tcf_ematch *); 4231da177e4SLinus Torvalds int (*match)(struct sk_buff *, struct tcf_ematch *, 4241da177e4SLinus Torvalds struct tcf_pkt_info *); 42582a470f1SJohn Fastabend void (*destroy)(struct tcf_ematch *); 4261da177e4SLinus Torvalds int (*dump)(struct sk_buff *, struct tcf_ematch *); 4271da177e4SLinus Torvalds struct module *owner; 4281da177e4SLinus Torvalds struct list_head link; 4291da177e4SLinus Torvalds }; 4301da177e4SLinus Torvalds 4315c15257fSJoe Perches int tcf_em_register(struct tcf_ematch_ops *); 4325c15257fSJoe Perches void tcf_em_unregister(struct tcf_ematch_ops *); 4335c15257fSJoe Perches int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *, 4341da177e4SLinus Torvalds struct tcf_ematch_tree *); 43582a470f1SJohn Fastabend void tcf_em_tree_destroy(struct tcf_ematch_tree *); 4365c15257fSJoe Perches int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int); 4375c15257fSJoe Perches int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *, 4381da177e4SLinus Torvalds struct tcf_pkt_info *); 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds /** 4411da177e4SLinus Torvalds * tcf_em_tree_match - evaulate an ematch tree 4421da177e4SLinus Torvalds * 4431da177e4SLinus Torvalds * @skb: socket buffer of the packet in question 4441da177e4SLinus Torvalds * @tree: ematch tree to be used for evaluation 4451da177e4SLinus Torvalds * @info: packet information examined by classifier 4461da177e4SLinus Torvalds * 4471da177e4SLinus Torvalds * This function matches @skb against the ematch tree in @tree by going 4481da177e4SLinus Torvalds * through all ematches respecting their logic relations returning 4491da177e4SLinus Torvalds * as soon as the result is obvious. 4501da177e4SLinus Torvalds * 4511da177e4SLinus Torvalds * Returns 1 if the ematch tree as-one matches, no ematches are configured 4521da177e4SLinus Torvalds * or ematch is not enabled in the kernel, otherwise 0 is returned. 4531da177e4SLinus Torvalds */ 4541da177e4SLinus Torvalds static inline int tcf_em_tree_match(struct sk_buff *skb, 4551da177e4SLinus Torvalds struct tcf_ematch_tree *tree, 4561da177e4SLinus Torvalds struct tcf_pkt_info *info) 4571da177e4SLinus Torvalds { 4581da177e4SLinus Torvalds if (tree->hdr.nmatches) 4591da177e4SLinus Torvalds return __tcf_em_tree_match(skb, tree, info); 4601da177e4SLinus Torvalds else 4611da177e4SLinus Torvalds return 1; 4621da177e4SLinus Torvalds } 4631da177e4SLinus Torvalds 464db3d99c0SPatrick McHardy #define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind)) 465db3d99c0SPatrick McHardy 4661da177e4SLinus Torvalds #else /* CONFIG_NET_EMATCH */ 4671da177e4SLinus Torvalds 468fd2c3ef7SEric Dumazet struct tcf_ematch_tree { 4691da177e4SLinus Torvalds }; 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0) 47282a470f1SJohn Fastabend #define tcf_em_tree_destroy(t) do { (void)(t); } while(0) 4731da177e4SLinus Torvalds #define tcf_em_tree_dump(skb, t, tlv) (0) 4741da177e4SLinus Torvalds #define tcf_em_tree_match(skb, t, info) ((void)(info), 1) 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds #endif /* CONFIG_NET_EMATCH */ 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) 4791da177e4SLinus Torvalds { 4801da177e4SLinus Torvalds switch (layer) { 4811da177e4SLinus Torvalds case TCF_LAYER_LINK: 482d3303a65SWolfgang Bumiller return skb_mac_header(skb); 4831da177e4SLinus Torvalds case TCF_LAYER_NETWORK: 484d56f90a7SArnaldo Carvalho de Melo return skb_network_header(skb); 4851da177e4SLinus Torvalds case TCF_LAYER_TRANSPORT: 4869c70220bSArnaldo Carvalho de Melo return skb_transport_header(skb); 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds return NULL; 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds 492eddc9ec5SArnaldo Carvalho de Melo static inline int tcf_valid_offset(const struct sk_buff *skb, 493eddc9ec5SArnaldo Carvalho de Melo const unsigned char *ptr, const int len) 4941da177e4SLinus Torvalds { 495da521b2cSDavid S. Miller return likely((ptr + len) <= skb_tail_pointer(skb) && 496da521b2cSDavid S. Miller ptr >= skb->head && 497da521b2cSDavid S. Miller (ptr <= (ptr + len))); 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds static inline int 5011057c55fSAlexander Aring tcf_change_indev(struct net *net, struct nlattr *indev_tlv, 5021057c55fSAlexander Aring struct netlink_ext_ack *extack) 5031da177e4SLinus Torvalds { 5042519a602SWANG Cong char indev[IFNAMSIZ]; 505c01003c2SPatrick McHardy struct net_device *dev; 506c01003c2SPatrick McHardy 5071057c55fSAlexander Aring if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) { 508e4a58ef3SGuillaume Nault NL_SET_ERR_MSG_ATTR(extack, indev_tlv, 509e4a58ef3SGuillaume Nault "Interface name too long"); 5102519a602SWANG Cong return -EINVAL; 5111057c55fSAlexander Aring } 5122519a602SWANG Cong dev = __dev_get_by_name(net, indev); 513e4a58ef3SGuillaume Nault if (!dev) { 514e4a58ef3SGuillaume Nault NL_SET_ERR_MSG_ATTR(extack, indev_tlv, 515e4a58ef3SGuillaume Nault "Network device not found"); 5162519a602SWANG Cong return -ENODEV; 517e4a58ef3SGuillaume Nault } 5182519a602SWANG Cong return dev->ifindex; 5191da177e4SLinus Torvalds } 5201da177e4SLinus Torvalds 5212519a602SWANG Cong static inline bool 5222519a602SWANG Cong tcf_match_indev(struct sk_buff *skb, int ifindex) 5232519a602SWANG Cong { 5242519a602SWANG Cong if (!ifindex) 5252519a602SWANG Cong return true; 5262519a602SWANG Cong if (!skb->skb_iif) 5272519a602SWANG Cong return false; 5282519a602SWANG Cong return ifindex == skb->skb_iif; 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds 5313a7b6861SPablo Neira Ayuso int tc_setup_flow_action(struct flow_action *flow_action, 532b15e7a6eSVlad Buslov const struct tcf_exts *exts); 5335a6ff4b1SVlad Buslov void tc_cleanup_flow_action(struct flow_action *flow_action); 5345a6ff4b1SVlad Buslov 535aeb3fecdSCong Wang int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, 53640119211SVlad Buslov void *type_data, bool err_stop, bool rtnl_held); 53740119211SVlad Buslov int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp, 53840119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 53940119211SVlad Buslov u32 *flags, unsigned int *in_hw_count, bool rtnl_held); 54040119211SVlad Buslov int tc_setup_cb_replace(struct tcf_block *block, struct tcf_proto *tp, 54140119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 54240119211SVlad Buslov u32 *old_flags, unsigned int *old_in_hw_count, 54340119211SVlad Buslov u32 *new_flags, unsigned int *new_in_hw_count, 54440119211SVlad Buslov bool rtnl_held); 54540119211SVlad Buslov int tc_setup_cb_destroy(struct tcf_block *block, struct tcf_proto *tp, 54640119211SVlad Buslov enum tc_setup_type type, void *type_data, bool err_stop, 54740119211SVlad Buslov u32 *flags, unsigned int *in_hw_count, bool rtnl_held); 54840119211SVlad Buslov int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp, 54940119211SVlad Buslov bool add, flow_setup_cb_t *cb, 55040119211SVlad Buslov enum tc_setup_type type, void *type_data, 55140119211SVlad Buslov void *cb_priv, u32 *flags, unsigned int *in_hw_count); 552e3ab786bSPablo Neira Ayuso unsigned int tcf_exts_num_actions(struct tcf_exts *exts); 553717503b9SJiri Pirko 554a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode { 555a1b7c5fdSJohn Fastabend struct tcf_exts *exts; 556068ceb35SJakub Kicinski struct tcf_result *res; 557e014860eSJohn Fastabend struct tc_u32_sel *sel; 558a1b7c5fdSJohn Fastabend u32 handle; 559a1b7c5fdSJohn Fastabend u32 val; 560a1b7c5fdSJohn Fastabend u32 mask; 561a1b7c5fdSJohn Fastabend u32 link_handle; 562e014860eSJohn Fastabend u8 fshift; 563a1b7c5fdSJohn Fastabend }; 564a1b7c5fdSJohn Fastabend 565a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode { 566a1b7c5fdSJohn Fastabend u32 handle; 567a1b7c5fdSJohn Fastabend u32 prio; 568a1b7c5fdSJohn Fastabend unsigned int divisor; 569a1b7c5fdSJohn Fastabend }; 570a1b7c5fdSJohn Fastabend 571a1b7c5fdSJohn Fastabend enum tc_clsu32_command { 572a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_KNODE, 573a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_KNODE, 574a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_KNODE, 575a1b7c5fdSJohn Fastabend TC_CLSU32_NEW_HNODE, 576a1b7c5fdSJohn Fastabend TC_CLSU32_REPLACE_HNODE, 577a1b7c5fdSJohn Fastabend TC_CLSU32_DELETE_HNODE, 578a1b7c5fdSJohn Fastabend }; 579a1b7c5fdSJohn Fastabend 580a1b7c5fdSJohn Fastabend struct tc_cls_u32_offload { 581f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 582a1b7c5fdSJohn Fastabend /* knode values */ 583a1b7c5fdSJohn Fastabend enum tc_clsu32_command command; 584a1b7c5fdSJohn Fastabend union { 585a1b7c5fdSJohn Fastabend struct tc_cls_u32_knode knode; 586a1b7c5fdSJohn Fastabend struct tc_cls_u32_hnode hnode; 587a1b7c5fdSJohn Fastabend }; 588a1b7c5fdSJohn Fastabend }; 589a1b7c5fdSJohn Fastabend 5907b06e8aeSJiri Pirko static inline bool tc_can_offload(const struct net_device *dev) 5916843e7a2SJohn Fastabend { 59270b5aee4SJiri Pirko return dev->features & NETIF_F_HW_TC; 5936843e7a2SJohn Fastabend } 5946843e7a2SJohn Fastabend 595f9eda14fSQuentin Monnet static inline bool tc_can_offload_extack(const struct net_device *dev, 596f9eda14fSQuentin Monnet struct netlink_ext_ack *extack) 597f9eda14fSQuentin Monnet { 598f9eda14fSQuentin Monnet bool can = tc_can_offload(dev); 599f9eda14fSQuentin Monnet 600f9eda14fSQuentin Monnet if (!can) 601f9eda14fSQuentin Monnet NL_SET_ERR_MSG(extack, "TC offload is disabled on net device"); 602f9eda14fSQuentin Monnet 603f9eda14fSQuentin Monnet return can; 604f9eda14fSQuentin Monnet } 605f9eda14fSQuentin Monnet 606878db9f0SJakub Kicinski static inline bool 607878db9f0SJakub Kicinski tc_cls_can_offload_and_chain0(const struct net_device *dev, 608f9e30088SPablo Neira Ayuso struct flow_cls_common_offload *common) 609878db9f0SJakub Kicinski { 610878db9f0SJakub Kicinski if (!tc_can_offload_extack(dev, common->extack)) 611878db9f0SJakub Kicinski return false; 612878db9f0SJakub Kicinski if (common->chain_index) { 613878db9f0SJakub Kicinski NL_SET_ERR_MSG(common->extack, 614878db9f0SJakub Kicinski "Driver supports only offload of chain 0"); 615878db9f0SJakub Kicinski return false; 616878db9f0SJakub Kicinski } 617878db9f0SJakub Kicinski return true; 618878db9f0SJakub Kicinski } 619878db9f0SJakub Kicinski 62055330f05SHadar Hen Zion static inline bool tc_skip_hw(u32 flags) 62155330f05SHadar Hen Zion { 62255330f05SHadar Hen Zion return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; 62355330f05SHadar Hen Zion } 62455330f05SHadar Hen Zion 625d34e3e18SSamudrala, Sridhar static inline bool tc_skip_sw(u32 flags) 626d34e3e18SSamudrala, Sridhar { 627d34e3e18SSamudrala, Sridhar return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false; 628d34e3e18SSamudrala, Sridhar } 629d34e3e18SSamudrala, Sridhar 630d34e3e18SSamudrala, Sridhar /* SKIP_HW and SKIP_SW are mutually exclusive flags. */ 631d34e3e18SSamudrala, Sridhar static inline bool tc_flags_valid(u32 flags) 632d34e3e18SSamudrala, Sridhar { 63381c7288bSMarcelo Ricardo Leitner if (flags & ~(TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW | 63481c7288bSMarcelo Ricardo Leitner TCA_CLS_FLAGS_VERBOSE)) 635d34e3e18SSamudrala, Sridhar return false; 636d34e3e18SSamudrala, Sridhar 63781c7288bSMarcelo Ricardo Leitner flags &= TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW; 638d34e3e18SSamudrala, Sridhar if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW))) 639d34e3e18SSamudrala, Sridhar return false; 640d34e3e18SSamudrala, Sridhar 641d34e3e18SSamudrala, Sridhar return true; 642d34e3e18SSamudrala, Sridhar } 643d34e3e18SSamudrala, Sridhar 644e696028aSOr Gerlitz static inline bool tc_in_hw(u32 flags) 645e696028aSOr Gerlitz { 646e696028aSOr Gerlitz return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; 647e696028aSOr Gerlitz } 648e696028aSOr Gerlitz 64934832e1cSJakub Kicinski static inline void 650f9e30088SPablo Neira Ayuso tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common, 65134832e1cSJakub Kicinski const struct tcf_proto *tp, u32 flags, 65234832e1cSJakub Kicinski struct netlink_ext_ack *extack) 65334832e1cSJakub Kicinski { 65434832e1cSJakub Kicinski cls_common->chain_index = tp->chain->index; 65534832e1cSJakub Kicinski cls_common->protocol = tp->protocol; 656ef01adaeSPablo Neira Ayuso cls_common->prio = tp->prio >> 16; 65781c7288bSMarcelo Ricardo Leitner if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE) 65834832e1cSJakub Kicinski cls_common->extack = extack; 65934832e1cSJakub Kicinski } 66034832e1cSJakub Kicinski 661b87f7936SYotam Gigi enum tc_matchall_command { 662b87f7936SYotam Gigi TC_CLSMATCHALL_REPLACE, 663b87f7936SYotam Gigi TC_CLSMATCHALL_DESTROY, 664b7fe4ab8SPieter Jansen van Vuuren TC_CLSMATCHALL_STATS, 665b87f7936SYotam Gigi }; 666b87f7936SYotam Gigi 667b87f7936SYotam Gigi struct tc_cls_matchall_offload { 668f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 669b87f7936SYotam Gigi enum tc_matchall_command command; 670f00cbf19SPieter Jansen van Vuuren struct flow_rule *rule; 671b7fe4ab8SPieter Jansen van Vuuren struct flow_stats stats; 672b87f7936SYotam Gigi unsigned long cookie; 673b87f7936SYotam Gigi }; 674b87f7936SYotam Gigi 675332ae8e2SJakub Kicinski enum tc_clsbpf_command { 676102740bdSJakub Kicinski TC_CLSBPF_OFFLOAD, 67768d64063SJakub Kicinski TC_CLSBPF_STATS, 678332ae8e2SJakub Kicinski }; 679332ae8e2SJakub Kicinski 680332ae8e2SJakub Kicinski struct tc_cls_bpf_offload { 681f9e30088SPablo Neira Ayuso struct flow_cls_common_offload common; 682332ae8e2SJakub Kicinski enum tc_clsbpf_command command; 683332ae8e2SJakub Kicinski struct tcf_exts *exts; 684332ae8e2SJakub Kicinski struct bpf_prog *prog; 685102740bdSJakub Kicinski struct bpf_prog *oldprog; 686332ae8e2SJakub Kicinski const char *name; 687332ae8e2SJakub Kicinski bool exts_integrated; 688332ae8e2SJakub Kicinski }; 689332ae8e2SJakub Kicinski 6904e8b86c0SAmritha Nambiar struct tc_mqprio_qopt_offload { 6914e8b86c0SAmritha Nambiar /* struct tc_mqprio_qopt must always be the first element */ 6924e8b86c0SAmritha Nambiar struct tc_mqprio_qopt qopt; 6934e8b86c0SAmritha Nambiar u16 mode; 6944e8b86c0SAmritha Nambiar u16 shaper; 6954e8b86c0SAmritha Nambiar u32 flags; 6964e8b86c0SAmritha Nambiar u64 min_rate[TC_QOPT_MAX_QUEUE]; 6974e8b86c0SAmritha Nambiar u64 max_rate[TC_QOPT_MAX_QUEUE]; 6984e8b86c0SAmritha Nambiar }; 6991045ba77SJamal Hadi Salim 7001045ba77SJamal Hadi Salim /* This structure holds cookie structure that is passed from user 7011045ba77SJamal Hadi Salim * to the kernel for actions and classifiers 7021045ba77SJamal Hadi Salim */ 7031045ba77SJamal Hadi Salim struct tc_cookie { 7041045ba77SJamal Hadi Salim u8 *data; 7051045ba77SJamal Hadi Salim u32 len; 706eec94fdbSVlad Buslov struct rcu_head rcu; 7071045ba77SJamal Hadi Salim }; 708602f3bafSNogah Frankel 709f34b4aacSNogah Frankel struct tc_qopt_offload_stats { 710f34b4aacSNogah Frankel struct gnet_stats_basic_packed *bstats; 711f34b4aacSNogah Frankel struct gnet_stats_queue *qstats; 712f34b4aacSNogah Frankel }; 713f34b4aacSNogah Frankel 714f971b132SJakub Kicinski enum tc_mq_command { 715f971b132SJakub Kicinski TC_MQ_CREATE, 716f971b132SJakub Kicinski TC_MQ_DESTROY, 71747c669a4SJakub Kicinski TC_MQ_STATS, 718d577a3d2SJakub Kicinski TC_MQ_GRAFT, 719d577a3d2SJakub Kicinski }; 720d577a3d2SJakub Kicinski 721d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params { 722d577a3d2SJakub Kicinski unsigned long queue; 723d577a3d2SJakub Kicinski u32 child_handle; 724f971b132SJakub Kicinski }; 725f971b132SJakub Kicinski 726f971b132SJakub Kicinski struct tc_mq_qopt_offload { 727f971b132SJakub Kicinski enum tc_mq_command command; 728f971b132SJakub Kicinski u32 handle; 729d577a3d2SJakub Kicinski union { 73047c669a4SJakub Kicinski struct tc_qopt_offload_stats stats; 731d577a3d2SJakub Kicinski struct tc_mq_opt_offload_graft_params graft_params; 732d577a3d2SJakub Kicinski }; 733f971b132SJakub Kicinski }; 734f971b132SJakub Kicinski 735602f3bafSNogah Frankel enum tc_red_command { 736602f3bafSNogah Frankel TC_RED_REPLACE, 737602f3bafSNogah Frankel TC_RED_DESTROY, 738602f3bafSNogah Frankel TC_RED_STATS, 739602f3bafSNogah Frankel TC_RED_XSTATS, 740bf2a752bSJakub Kicinski TC_RED_GRAFT, 741602f3bafSNogah Frankel }; 742602f3bafSNogah Frankel 743602f3bafSNogah Frankel struct tc_red_qopt_offload_params { 744602f3bafSNogah Frankel u32 min; 745602f3bafSNogah Frankel u32 max; 746602f3bafSNogah Frankel u32 probability; 747c0b7490bSJakub Kicinski u32 limit; 748602f3bafSNogah Frankel bool is_ecn; 749190852a5SJakub Kicinski bool is_harddrop; 7500a7fad23SPetr Machata bool is_nodrop; 751416ef9b1SJakub Kicinski struct gnet_stats_queue *qstats; 752602f3bafSNogah Frankel }; 753602f3bafSNogah Frankel 754602f3bafSNogah Frankel struct tc_red_qopt_offload { 755602f3bafSNogah Frankel enum tc_red_command command; 756602f3bafSNogah Frankel u32 handle; 757602f3bafSNogah Frankel u32 parent; 758602f3bafSNogah Frankel union { 759602f3bafSNogah Frankel struct tc_red_qopt_offload_params set; 760f34b4aacSNogah Frankel struct tc_qopt_offload_stats stats; 761602f3bafSNogah Frankel struct red_stats *xstats; 762bf2a752bSJakub Kicinski u32 child_handle; 763602f3bafSNogah Frankel }; 764602f3bafSNogah Frankel }; 765602f3bafSNogah Frankel 766890d8d23SJakub Kicinski enum tc_gred_command { 767890d8d23SJakub Kicinski TC_GRED_REPLACE, 768890d8d23SJakub Kicinski TC_GRED_DESTROY, 769e49efd52SJakub Kicinski TC_GRED_STATS, 770890d8d23SJakub Kicinski }; 771890d8d23SJakub Kicinski 772890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params { 773890d8d23SJakub Kicinski bool present; 774890d8d23SJakub Kicinski u32 limit; 775890d8d23SJakub Kicinski u32 prio; 776890d8d23SJakub Kicinski u32 min; 777890d8d23SJakub Kicinski u32 max; 778890d8d23SJakub Kicinski bool is_ecn; 779890d8d23SJakub Kicinski bool is_harddrop; 780890d8d23SJakub Kicinski u32 probability; 781890d8d23SJakub Kicinski /* Only need backlog, see struct tc_prio_qopt_offload_params */ 782890d8d23SJakub Kicinski u32 *backlog; 783890d8d23SJakub Kicinski }; 784890d8d23SJakub Kicinski 785890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params { 786890d8d23SJakub Kicinski bool grio_on; 787890d8d23SJakub Kicinski bool wred_on; 788890d8d23SJakub Kicinski unsigned int dp_cnt; 789890d8d23SJakub Kicinski unsigned int dp_def; 790890d8d23SJakub Kicinski struct gnet_stats_queue *qstats; 791890d8d23SJakub Kicinski struct tc_gred_vq_qopt_offload_params tab[MAX_DPs]; 792890d8d23SJakub Kicinski }; 793890d8d23SJakub Kicinski 794e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats { 795e49efd52SJakub Kicinski struct gnet_stats_basic_packed bstats[MAX_DPs]; 796e49efd52SJakub Kicinski struct gnet_stats_queue qstats[MAX_DPs]; 797e49efd52SJakub Kicinski struct red_stats *xstats[MAX_DPs]; 798e49efd52SJakub Kicinski }; 799e49efd52SJakub Kicinski 800890d8d23SJakub Kicinski struct tc_gred_qopt_offload { 801890d8d23SJakub Kicinski enum tc_gred_command command; 802890d8d23SJakub Kicinski u32 handle; 803890d8d23SJakub Kicinski u32 parent; 804890d8d23SJakub Kicinski union { 805890d8d23SJakub Kicinski struct tc_gred_qopt_offload_params set; 806e49efd52SJakub Kicinski struct tc_gred_qopt_offload_stats stats; 807890d8d23SJakub Kicinski }; 808890d8d23SJakub Kicinski }; 809890d8d23SJakub Kicinski 8107fdb61b4SNogah Frankel enum tc_prio_command { 8117fdb61b4SNogah Frankel TC_PRIO_REPLACE, 8127fdb61b4SNogah Frankel TC_PRIO_DESTROY, 8137fdb61b4SNogah Frankel TC_PRIO_STATS, 814b9c7a7acSNogah Frankel TC_PRIO_GRAFT, 8157fdb61b4SNogah Frankel }; 8167fdb61b4SNogah Frankel 8177fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params { 8187fdb61b4SNogah Frankel int bands; 8197fdb61b4SNogah Frankel u8 priomap[TC_PRIO_MAX + 1]; 8209586a992SPetr Machata /* At the point of un-offloading the Qdisc, the reported backlog and 8219586a992SPetr Machata * qlen need to be reduced by the portion that is in HW. 8227fdb61b4SNogah Frankel */ 8237fdb61b4SNogah Frankel struct gnet_stats_queue *qstats; 8247fdb61b4SNogah Frankel }; 8257fdb61b4SNogah Frankel 826b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params { 827b9c7a7acSNogah Frankel u8 band; 828b9c7a7acSNogah Frankel u32 child_handle; 829b9c7a7acSNogah Frankel }; 830b9c7a7acSNogah Frankel 8317fdb61b4SNogah Frankel struct tc_prio_qopt_offload { 8327fdb61b4SNogah Frankel enum tc_prio_command command; 8337fdb61b4SNogah Frankel u32 handle; 8347fdb61b4SNogah Frankel u32 parent; 8357fdb61b4SNogah Frankel union { 8367fdb61b4SNogah Frankel struct tc_prio_qopt_offload_params replace_params; 8377fdb61b4SNogah Frankel struct tc_qopt_offload_stats stats; 838b9c7a7acSNogah Frankel struct tc_prio_qopt_offload_graft_params graft_params; 8397fdb61b4SNogah Frankel }; 8407fdb61b4SNogah Frankel }; 841b9c7a7acSNogah Frankel 84298b0e5f6SJakub Kicinski enum tc_root_command { 84398b0e5f6SJakub Kicinski TC_ROOT_GRAFT, 84498b0e5f6SJakub Kicinski }; 84598b0e5f6SJakub Kicinski 84698b0e5f6SJakub Kicinski struct tc_root_qopt_offload { 84798b0e5f6SJakub Kicinski enum tc_root_command command; 84898b0e5f6SJakub Kicinski u32 handle; 84998b0e5f6SJakub Kicinski bool ingress; 85098b0e5f6SJakub Kicinski }; 85198b0e5f6SJakub Kicinski 852d35eb52bSPetr Machata enum tc_ets_command { 853d35eb52bSPetr Machata TC_ETS_REPLACE, 854d35eb52bSPetr Machata TC_ETS_DESTROY, 855d35eb52bSPetr Machata TC_ETS_STATS, 856d35eb52bSPetr Machata TC_ETS_GRAFT, 857d35eb52bSPetr Machata }; 858d35eb52bSPetr Machata 859d35eb52bSPetr Machata struct tc_ets_qopt_offload_replace_params { 860d35eb52bSPetr Machata unsigned int bands; 861d35eb52bSPetr Machata u8 priomap[TC_PRIO_MAX + 1]; 862d35eb52bSPetr Machata unsigned int quanta[TCQ_ETS_MAX_BANDS]; /* 0 for strict bands. */ 863d35eb52bSPetr Machata unsigned int weights[TCQ_ETS_MAX_BANDS]; 864d35eb52bSPetr Machata struct gnet_stats_queue *qstats; 865d35eb52bSPetr Machata }; 866d35eb52bSPetr Machata 867d35eb52bSPetr Machata struct tc_ets_qopt_offload_graft_params { 868d35eb52bSPetr Machata u8 band; 869d35eb52bSPetr Machata u32 child_handle; 870d35eb52bSPetr Machata }; 871d35eb52bSPetr Machata 872d35eb52bSPetr Machata struct tc_ets_qopt_offload { 873d35eb52bSPetr Machata enum tc_ets_command command; 874d35eb52bSPetr Machata u32 handle; 875d35eb52bSPetr Machata u32 parent; 876d35eb52bSPetr Machata union { 877d35eb52bSPetr Machata struct tc_ets_qopt_offload_replace_params replace_params; 878d35eb52bSPetr Machata struct tc_qopt_offload_stats stats; 879d35eb52bSPetr Machata struct tc_ets_qopt_offload_graft_params graft_params; 880d35eb52bSPetr Machata }; 881d35eb52bSPetr Machata }; 882d35eb52bSPetr Machata 883ef6aadccSPetr Machata enum tc_tbf_command { 884ef6aadccSPetr Machata TC_TBF_REPLACE, 885ef6aadccSPetr Machata TC_TBF_DESTROY, 886ef6aadccSPetr Machata TC_TBF_STATS, 887ef6aadccSPetr Machata }; 888ef6aadccSPetr Machata 889ef6aadccSPetr Machata struct tc_tbf_qopt_offload_replace_params { 890ef6aadccSPetr Machata struct psched_ratecfg rate; 891ef6aadccSPetr Machata u32 max_size; 892ef6aadccSPetr Machata struct gnet_stats_queue *qstats; 893ef6aadccSPetr Machata }; 894ef6aadccSPetr Machata 895ef6aadccSPetr Machata struct tc_tbf_qopt_offload { 896ef6aadccSPetr Machata enum tc_tbf_command command; 897ef6aadccSPetr Machata u32 handle; 898ef6aadccSPetr Machata u32 parent; 899ef6aadccSPetr Machata union { 900ef6aadccSPetr Machata struct tc_tbf_qopt_offload_replace_params replace_params; 901ef6aadccSPetr Machata struct tc_qopt_offload_stats stats; 902ef6aadccSPetr Machata }; 903ef6aadccSPetr Machata }; 904ef6aadccSPetr Machata 905aaca9408SPetr Machata enum tc_fifo_command { 906aaca9408SPetr Machata TC_FIFO_REPLACE, 907aaca9408SPetr Machata TC_FIFO_DESTROY, 908aaca9408SPetr Machata TC_FIFO_STATS, 909aaca9408SPetr Machata }; 910aaca9408SPetr Machata 911aaca9408SPetr Machata struct tc_fifo_qopt_offload { 912aaca9408SPetr Machata enum tc_fifo_command command; 913aaca9408SPetr Machata u32 handle; 914aaca9408SPetr Machata u32 parent; 915aaca9408SPetr Machata union { 916aaca9408SPetr Machata struct tc_qopt_offload_stats stats; 917aaca9408SPetr Machata }; 918aaca9408SPetr Machata }; 919aaca9408SPetr Machata 9201da177e4SLinus Torvalds #endif 921