Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-sched-tc-drop-reason'

Victor Nogueira says:

====================
net: sched: Make tc-related drop reason more flexible for remaining qdiscs

This patch builds on Daniel's patch[1] to add initial support of tc drop
reason. The main goal is to distinguish between policy and error drops for
the remainder of the egress qdiscs (other than clsact).
The drop reason is set by cls_api and act_api in the tc skb cb in case
any error occurred in the data path.

Also add new skb drop reasons that are idiosyncratic to TC.

[1] https://lore.kernel.org/all/20231009092655.22025-1-daniel@iogearbox.net

Changes in V5:
- Drop "EXT_" from cookie error's drop reason name in doc

Changes in V4:
- Condense all the cookie drop reasons into one

Changes in V3:
- Removed duplicate assignment
- Rename function tc_skb_cb_drop_reason to tcf_get_drop_reason
- Move zone field upwards in struct tc_skb_cb to move hole to the end of
the struct

Changes in V2:
- Dropped RFC tag
- Removed check for drop reason being overwritten by filter in cls_api.c
- Simplified logic and removed function tcf_init_drop_reason
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+70 -49
+15 -3
include/net/dropreason-core.h
··· 85 85 FN(IPV6_NDISC_BAD_OPTIONS) \ 86 86 FN(IPV6_NDISC_NS_OTHERHOST) \ 87 87 FN(QUEUE_PURGE) \ 88 - FN(TC_ERROR) \ 88 + FN(TC_COOKIE_ERROR) \ 89 89 FN(PACKET_SOCK_ERROR) \ 90 + FN(TC_CHAIN_NOTFOUND) \ 91 + FN(TC_RECLASSIFY_LOOP) \ 90 92 FNe(MAX) 91 93 92 94 /** ··· 379 377 SKB_DROP_REASON_IPV6_NDISC_NS_OTHERHOST, 380 378 /** @SKB_DROP_REASON_QUEUE_PURGE: bulk free. */ 381 379 SKB_DROP_REASON_QUEUE_PURGE, 382 - /** @SKB_DROP_REASON_TC_ERROR: generic internal tc error. */ 383 - SKB_DROP_REASON_TC_ERROR, 380 + /** 381 + * @SKB_DROP_REASON_TC_COOKIE_ERROR: An error occurred whilst 382 + * processing a tc ext cookie. 383 + */ 384 + SKB_DROP_REASON_TC_COOKIE_ERROR, 384 385 /** 385 386 * @SKB_DROP_REASON_PACKET_SOCK_ERROR: generic packet socket errors 386 387 * after its filter matches an incoming packet. 387 388 */ 388 389 SKB_DROP_REASON_PACKET_SOCK_ERROR, 390 + /** @SKB_DROP_REASON_TC_CHAIN_NOTFOUND: tc chain lookup failed. */ 391 + SKB_DROP_REASON_TC_CHAIN_NOTFOUND, 392 + /** 393 + * @SKB_DROP_REASON_TC_RECLASSIFY_LOOP: tc exceeded max reclassify loop 394 + * iterations. 395 + */ 396 + SKB_DROP_REASON_TC_RECLASSIFY_LOOP, 389 397 /** 390 398 * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which 391 399 * shouldn't be used as a real 'reason' - only for tracing code gen
-6
include/net/pkt_cls.h
··· 154 154 return xchg(clp, cl); 155 155 } 156 156 157 - static inline void tcf_set_drop_reason(struct tcf_result *res, 158 - enum skb_drop_reason reason) 159 - { 160 - res->drop_reason = reason; 161 - } 162 - 163 157 static inline void 164 158 __tcf_bind_filter(struct Qdisc *q, struct tcf_result *r, unsigned long base) 165 159 {
-18
include/net/pkt_sched.h
··· 275 275 skb->tstamp = ktime_set(0, 0); 276 276 } 277 277 278 - struct tc_skb_cb { 279 - struct qdisc_skb_cb qdisc_cb; 280 - 281 - u16 mru; 282 - u8 post_ct:1; 283 - u8 post_ct_snat:1; 284 - u8 post_ct_dnat:1; 285 - u16 zone; /* Only valid if post_ct = true */ 286 - }; 287 - 288 - static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb) 289 - { 290 - struct tc_skb_cb *cb = (struct tc_skb_cb *)skb->cb; 291 - 292 - BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb)); 293 - return cb; 294 - } 295 - 296 278 static inline bool tc_qdisc_stats_dump(struct Qdisc *sch, 297 279 unsigned long cl, 298 280 struct qdisc_walker *arg)
+31 -1
include/net/sch_generic.h
··· 332 332 }; 333 333 const struct tcf_proto *goto_tp; 334 334 }; 335 - enum skb_drop_reason drop_reason; 336 335 }; 337 336 338 337 struct tcf_chain; ··· 1034 1035 } 1035 1036 1036 1037 return skb; 1038 + } 1039 + 1040 + struct tc_skb_cb { 1041 + struct qdisc_skb_cb qdisc_cb; 1042 + u32 drop_reason; 1043 + 1044 + u16 zone; /* Only valid if post_ct = true */ 1045 + u16 mru; 1046 + u8 post_ct:1; 1047 + u8 post_ct_snat:1; 1048 + u8 post_ct_dnat:1; 1049 + }; 1050 + 1051 + static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb) 1052 + { 1053 + struct tc_skb_cb *cb = (struct tc_skb_cb *)skb->cb; 1054 + 1055 + BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb)); 1056 + return cb; 1057 + } 1058 + 1059 + static inline enum skb_drop_reason 1060 + tcf_get_drop_reason(const struct sk_buff *skb) 1061 + { 1062 + return tc_skb_cb(skb)->drop_reason; 1063 + } 1064 + 1065 + static inline void tcf_set_drop_reason(const struct sk_buff *skb, 1066 + enum skb_drop_reason reason) 1067 + { 1068 + tc_skb_cb(skb)->drop_reason = reason; 1037 1069 } 1038 1070 1039 1071 /* Instead of calling kfree_skb() while root qdisc lock is held,
+7 -4
net/core/dev.c
··· 3753 3753 3754 3754 qdisc_calculate_pkt_len(skb, q); 3755 3755 3756 + tcf_set_drop_reason(skb, SKB_DROP_REASON_QDISC_DROP); 3757 + 3756 3758 if (q->flags & TCQ_F_NOLOCK) { 3757 3759 if (q->flags & TCQ_F_CAN_BYPASS && nolock_qdisc_is_empty(q) && 3758 3760 qdisc_run_begin(q)) { ··· 3784 3782 no_lock_out: 3785 3783 if (unlikely(to_free)) 3786 3784 kfree_skb_list_reason(to_free, 3787 - SKB_DROP_REASON_QDISC_DROP); 3785 + tcf_get_drop_reason(to_free)); 3788 3786 return rc; 3789 3787 } 3790 3788 ··· 3839 3837 } 3840 3838 spin_unlock(root_lock); 3841 3839 if (unlikely(to_free)) 3842 - kfree_skb_list_reason(to_free, SKB_DROP_REASON_QDISC_DROP); 3840 + kfree_skb_list_reason(to_free, 3841 + tcf_get_drop_reason(to_free)); 3843 3842 if (unlikely(contended)) 3844 3843 spin_unlock(&q->busylock); 3845 3844 return rc; ··· 3926 3923 3927 3924 tc_skb_cb(skb)->mru = 0; 3928 3925 tc_skb_cb(skb)->post_ct = false; 3929 - res.drop_reason = *drop_reason; 3926 + tcf_set_drop_reason(skb, *drop_reason); 3930 3927 3931 3928 mini_qdisc_bstats_cpu_update(miniq, skb); 3932 3929 ret = tcf_classify(skb, miniq->block, miniq->filter_list, &res, false); 3933 3930 /* Only tcf related quirks below. */ 3934 3931 switch (ret) { 3935 3932 case TC_ACT_SHOT: 3936 - *drop_reason = res.drop_reason; 3933 + *drop_reason = tcf_get_drop_reason(skb); 3937 3934 mini_qdisc_qstats_cpu_drop(miniq); 3938 3935 break; 3939 3936 case TC_ACT_OK:
+2 -1
net/sched/act_api.c
··· 1119 1119 } 1120 1120 } else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) { 1121 1121 if (unlikely(!rcu_access_pointer(a->goto_chain))) { 1122 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1122 + tcf_set_drop_reason(skb, 1123 + SKB_DROP_REASON_TC_CHAIN_NOTFOUND); 1123 1124 return TC_ACT_SHOT; 1124 1125 } 1125 1126 tcf_action_goto_chain_exec(a, res);
+15 -16
net/sched/cls_api.c
··· 1657 1657 int act_index, 1658 1658 u32 *last_executed_chain) 1659 1659 { 1660 - u32 orig_reason = res->drop_reason; 1661 1660 #ifdef CONFIG_NET_CLS_ACT 1662 1661 const int max_reclassify_loop = 16; 1663 1662 const struct tcf_proto *first_tp; ··· 1681 1682 */ 1682 1683 if (unlikely(n->tp != tp || n->tp->chain != n->chain || 1683 1684 !tp->ops->get_exts)) { 1684 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1685 + tcf_set_drop_reason(skb, 1686 + SKB_DROP_REASON_TC_COOKIE_ERROR); 1685 1687 return TC_ACT_SHOT; 1686 1688 } 1687 1689 1688 1690 exts = tp->ops->get_exts(tp, n->handle); 1689 1691 if (unlikely(!exts || n->exts != exts)) { 1690 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1692 + tcf_set_drop_reason(skb, 1693 + SKB_DROP_REASON_TC_COOKIE_ERROR); 1691 1694 return TC_ACT_SHOT; 1692 1695 } 1693 1696 ··· 1713 1712 goto reset; 1714 1713 } 1715 1714 #endif 1716 - if (err >= 0) { 1717 - /* Policy drop or drop reason is over-written by 1718 - * classifiers with a bogus value(0) */ 1719 - if (err == TC_ACT_SHOT && 1720 - res->drop_reason == SKB_NOT_DROPPED_YET) 1721 - tcf_set_drop_reason(res, orig_reason); 1715 + if (err >= 0) 1722 1716 return err; 1723 - } 1724 1717 } 1725 1718 1726 1719 if (unlikely(n)) { 1727 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1720 + tcf_set_drop_reason(skb, 1721 + SKB_DROP_REASON_TC_COOKIE_ERROR); 1728 1722 return TC_ACT_SHOT; 1729 1723 } 1730 1724 ··· 1731 1735 tp->chain->block->index, 1732 1736 tp->prio & 0xffff, 1733 1737 ntohs(tp->protocol)); 1734 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1738 + tcf_set_drop_reason(skb, 1739 + SKB_DROP_REASON_TC_RECLASSIFY_LOOP); 1735 1740 return TC_ACT_SHOT; 1736 1741 } 1737 1742 ··· 1770 1773 n = tcf_exts_miss_cookie_lookup(ext->act_miss_cookie, 1771 1774 &act_index); 1772 1775 if (!n) { 1773 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1776 + tcf_set_drop_reason(skb, 1777 + SKB_DROP_REASON_TC_COOKIE_ERROR); 1774 1778 return TC_ACT_SHOT; 1775 1779 } 1776 1780 ··· 1782 1784 1783 1785 fchain = tcf_chain_lookup_rcu(block, chain); 1784 1786 if (!fchain) { 1785 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1787 + tcf_set_drop_reason(skb, 1788 + SKB_DROP_REASON_TC_CHAIN_NOTFOUND); 1789 + 1786 1790 return TC_ACT_SHOT; 1787 1791 } 1788 1792 ··· 1806 1806 1807 1807 ext = tc_skb_ext_alloc(skb); 1808 1808 if (WARN_ON_ONCE(!ext)) { 1809 - tcf_set_drop_reason(res, SKB_DROP_REASON_TC_ERROR); 1809 + tcf_set_drop_reason(skb, SKB_DROP_REASON_NOMEM); 1810 1810 return TC_ACT_SHOT; 1811 1811 } 1812 - 1813 1812 ext->chain = last_executed_chain; 1814 1813 ext->mru = cb->mru; 1815 1814 ext->post_ct = cb->post_ct;