diff options
Diffstat (limited to 'include/net/pkt_cls.h')
-rw-r--r-- | include/net/pkt_cls.h | 113 |
1 files changed, 92 insertions, 21 deletions
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 753ac9361154..87406252f0a3 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h | |||
@@ -29,6 +29,7 @@ struct tcf_block_ext_info { | |||
29 | enum tcf_block_binder_type binder_type; | 29 | enum tcf_block_binder_type binder_type; |
30 | tcf_chain_head_change_t *chain_head_change; | 30 | tcf_chain_head_change_t *chain_head_change; |
31 | void *chain_head_change_priv; | 31 | void *chain_head_change_priv; |
32 | u32 block_index; | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | struct tcf_block_cb; | 35 | struct tcf_block_cb; |
@@ -38,16 +39,25 @@ bool tcf_queue_work(struct work_struct *work); | |||
38 | struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index, | 39 | struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index, |
39 | bool create); | 40 | bool create); |
40 | void tcf_chain_put(struct tcf_chain *chain); | 41 | void tcf_chain_put(struct tcf_chain *chain); |
42 | void tcf_block_netif_keep_dst(struct tcf_block *block); | ||
41 | int tcf_block_get(struct tcf_block **p_block, | 43 | int tcf_block_get(struct tcf_block **p_block, |
42 | struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q); | 44 | struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, |
45 | struct netlink_ext_ack *extack); | ||
43 | int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, | 46 | int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, |
44 | struct tcf_block_ext_info *ei); | 47 | struct tcf_block_ext_info *ei, |
48 | struct netlink_ext_ack *extack); | ||
45 | void tcf_block_put(struct tcf_block *block); | 49 | void tcf_block_put(struct tcf_block *block); |
46 | void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, | 50 | void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, |
47 | struct tcf_block_ext_info *ei); | 51 | struct tcf_block_ext_info *ei); |
48 | 52 | ||
53 | static inline bool tcf_block_shared(struct tcf_block *block) | ||
54 | { | ||
55 | return block->index; | ||
56 | } | ||
57 | |||
49 | static inline struct Qdisc *tcf_block_q(struct tcf_block *block) | 58 | static inline struct Qdisc *tcf_block_q(struct tcf_block *block) |
50 | { | 59 | { |
60 | WARN_ON(tcf_block_shared(block)); | ||
51 | return block->q; | 61 | return block->q; |
52 | } | 62 | } |
53 | 63 | ||
@@ -77,14 +87,16 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, | |||
77 | #else | 87 | #else |
78 | static inline | 88 | static inline |
79 | int tcf_block_get(struct tcf_block **p_block, | 89 | int tcf_block_get(struct tcf_block **p_block, |
80 | struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q) | 90 | struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, |
91 | struct netlink_ext_ack *extack) | ||
81 | { | 92 | { |
82 | return 0; | 93 | return 0; |
83 | } | 94 | } |
84 | 95 | ||
85 | static inline | 96 | static inline |
86 | int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, | 97 | int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, |
87 | struct tcf_block_ext_info *ei) | 98 | struct tcf_block_ext_info *ei, |
99 | struct netlink_ext_ack *extack) | ||
88 | { | 100 | { |
89 | return 0; | 101 | return 0; |
90 | } | 102 | } |
@@ -364,7 +376,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, | |||
364 | 376 | ||
365 | int tcf_exts_validate(struct net *net, struct tcf_proto *tp, | 377 | int tcf_exts_validate(struct net *net, struct tcf_proto *tp, |
366 | struct nlattr **tb, struct nlattr *rate_tlv, | 378 | struct nlattr **tb, struct nlattr *rate_tlv, |
367 | struct tcf_exts *exts, bool ovr); | 379 | struct tcf_exts *exts, bool ovr, |
380 | struct netlink_ext_ack *extack); | ||
368 | void tcf_exts_destroy(struct tcf_exts *exts); | 381 | void tcf_exts_destroy(struct tcf_exts *exts); |
369 | void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); | 382 | void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); |
370 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); | 383 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); |
@@ -544,13 +557,16 @@ static inline int tcf_valid_offset(const struct sk_buff *skb, | |||
544 | #include <net/net_namespace.h> | 557 | #include <net/net_namespace.h> |
545 | 558 | ||
546 | static inline int | 559 | static inline int |
547 | tcf_change_indev(struct net *net, struct nlattr *indev_tlv) | 560 | tcf_change_indev(struct net *net, struct nlattr *indev_tlv, |
561 | struct netlink_ext_ack *extack) | ||
548 | { | 562 | { |
549 | char indev[IFNAMSIZ]; | 563 | char indev[IFNAMSIZ]; |
550 | struct net_device *dev; | 564 | struct net_device *dev; |
551 | 565 | ||
552 | if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) | 566 | if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) { |
567 | NL_SET_ERR_MSG(extack, "Interface name too long"); | ||
553 | return -EINVAL; | 568 | return -EINVAL; |
569 | } | ||
554 | dev = __dev_get_by_name(net, indev); | 570 | dev = __dev_get_by_name(net, indev); |
555 | if (!dev) | 571 | if (!dev) |
556 | return -ENODEV; | 572 | return -ENODEV; |
@@ -586,17 +602,9 @@ struct tc_cls_common_offload { | |||
586 | u32 chain_index; | 602 | u32 chain_index; |
587 | __be16 protocol; | 603 | __be16 protocol; |
588 | u32 prio; | 604 | u32 prio; |
605 | struct netlink_ext_ack *extack; | ||
589 | }; | 606 | }; |
590 | 607 | ||
591 | static inline void | ||
592 | tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common, | ||
593 | const struct tcf_proto *tp) | ||
594 | { | ||
595 | cls_common->chain_index = tp->chain->index; | ||
596 | cls_common->protocol = tp->protocol; | ||
597 | cls_common->prio = tp->prio; | ||
598 | } | ||
599 | |||
600 | struct tc_cls_u32_knode { | 608 | struct tc_cls_u32_knode { |
601 | struct tcf_exts *exts; | 609 | struct tcf_exts *exts; |
602 | struct tc_u32_sel *sel; | 610 | struct tc_u32_sel *sel; |
@@ -637,6 +645,31 @@ static inline bool tc_can_offload(const struct net_device *dev) | |||
637 | return dev->features & NETIF_F_HW_TC; | 645 | return dev->features & NETIF_F_HW_TC; |
638 | } | 646 | } |
639 | 647 | ||
648 | static inline bool tc_can_offload_extack(const struct net_device *dev, | ||
649 | struct netlink_ext_ack *extack) | ||
650 | { | ||
651 | bool can = tc_can_offload(dev); | ||
652 | |||
653 | if (!can) | ||
654 | NL_SET_ERR_MSG(extack, "TC offload is disabled on net device"); | ||
655 | |||
656 | return can; | ||
657 | } | ||
658 | |||
659 | static inline bool | ||
660 | tc_cls_can_offload_and_chain0(const struct net_device *dev, | ||
661 | struct tc_cls_common_offload *common) | ||
662 | { | ||
663 | if (!tc_can_offload_extack(dev, common->extack)) | ||
664 | return false; | ||
665 | if (common->chain_index) { | ||
666 | NL_SET_ERR_MSG(common->extack, | ||
667 | "Driver supports only offload of chain 0"); | ||
668 | return false; | ||
669 | } | ||
670 | return true; | ||
671 | } | ||
672 | |||
640 | static inline bool tc_skip_hw(u32 flags) | 673 | static inline bool tc_skip_hw(u32 flags) |
641 | { | 674 | { |
642 | return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; | 675 | return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; |
@@ -664,6 +697,18 @@ static inline bool tc_in_hw(u32 flags) | |||
664 | return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; | 697 | return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; |
665 | } | 698 | } |
666 | 699 | ||
700 | static inline void | ||
701 | tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common, | ||
702 | const struct tcf_proto *tp, u32 flags, | ||
703 | struct netlink_ext_ack *extack) | ||
704 | { | ||
705 | cls_common->chain_index = tp->chain->index; | ||
706 | cls_common->protocol = tp->protocol; | ||
707 | cls_common->prio = tp->prio; | ||
708 | if (tc_skip_sw(flags)) | ||
709 | cls_common->extack = extack; | ||
710 | } | ||
711 | |||
667 | enum tc_fl_command { | 712 | enum tc_fl_command { |
668 | TC_CLSFLOWER_REPLACE, | 713 | TC_CLSFLOWER_REPLACE, |
669 | TC_CLSFLOWER_DESTROY, | 714 | TC_CLSFLOWER_DESTROY, |
@@ -706,7 +751,6 @@ struct tc_cls_bpf_offload { | |||
706 | struct bpf_prog *oldprog; | 751 | struct bpf_prog *oldprog; |
707 | const char *name; | 752 | const char *name; |
708 | bool exts_integrated; | 753 | bool exts_integrated; |
709 | u32 gen_flags; | ||
710 | }; | 754 | }; |
711 | 755 | ||
712 | struct tc_mqprio_qopt_offload { | 756 | struct tc_mqprio_qopt_offload { |
@@ -727,6 +771,11 @@ struct tc_cookie { | |||
727 | u32 len; | 771 | u32 len; |
728 | }; | 772 | }; |
729 | 773 | ||
774 | struct tc_qopt_offload_stats { | ||
775 | struct gnet_stats_basic_packed *bstats; | ||
776 | struct gnet_stats_queue *qstats; | ||
777 | }; | ||
778 | |||
730 | enum tc_red_command { | 779 | enum tc_red_command { |
731 | TC_RED_REPLACE, | 780 | TC_RED_REPLACE, |
732 | TC_RED_DESTROY, | 781 | TC_RED_DESTROY, |
@@ -739,9 +788,6 @@ struct tc_red_qopt_offload_params { | |||
739 | u32 max; | 788 | u32 max; |
740 | u32 probability; | 789 | u32 probability; |
741 | bool is_ecn; | 790 | bool is_ecn; |
742 | }; | ||
743 | struct tc_red_qopt_offload_stats { | ||
744 | struct gnet_stats_basic_packed *bstats; | ||
745 | struct gnet_stats_queue *qstats; | 791 | struct gnet_stats_queue *qstats; |
746 | }; | 792 | }; |
747 | 793 | ||
@@ -751,9 +797,34 @@ struct tc_red_qopt_offload { | |||
751 | u32 parent; | 797 | u32 parent; |
752 | union { | 798 | union { |
753 | struct tc_red_qopt_offload_params set; | 799 | struct tc_red_qopt_offload_params set; |
754 | struct tc_red_qopt_offload_stats stats; | 800 | struct tc_qopt_offload_stats stats; |
755 | struct red_stats *xstats; | 801 | struct red_stats *xstats; |
756 | }; | 802 | }; |
757 | }; | 803 | }; |
758 | 804 | ||
805 | enum tc_prio_command { | ||
806 | TC_PRIO_REPLACE, | ||
807 | TC_PRIO_DESTROY, | ||
808 | TC_PRIO_STATS, | ||
809 | }; | ||
810 | |||
811 | struct tc_prio_qopt_offload_params { | ||
812 | int bands; | ||
813 | u8 priomap[TC_PRIO_MAX + 1]; | ||
814 | /* In case that a prio qdisc is offloaded and now is changed to a | ||
815 | * non-offloadedable config, it needs to update the backlog & qlen | ||
816 | * values to negate the HW backlog & qlen values (and only them). | ||
817 | */ | ||
818 | struct gnet_stats_queue *qstats; | ||
819 | }; | ||
820 | |||
821 | struct tc_prio_qopt_offload { | ||
822 | enum tc_prio_command command; | ||
823 | u32 handle; | ||
824 | u32 parent; | ||
825 | union { | ||
826 | struct tc_prio_qopt_offload_params replace_params; | ||
827 | struct tc_qopt_offload_stats stats; | ||
828 | }; | ||
829 | }; | ||
759 | #endif | 830 | #endif |