commit 5e819049c270f4771bb990db13d75f8ec88f6227 Author: Victor Nogueira Date: Mon Apr 15 12:10:40 2024 +0000 Mirred nested loop fix diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 76db6be16083..f561dfb79743 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -117,6 +117,7 @@ struct Qdisc { struct qdisc_skb_head q; struct gnet_stats_basic_sync bstats; struct gnet_stats_queue qstats; + int owner; unsigned long state; unsigned long state2; /* must be written under qdisc spinlock */ struct Qdisc *next_sched; diff --git a/net/core/dev.c b/net/core/dev.c index 854a3a28a8d8..f6c6e494f0a9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3808,6 +3808,10 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, return rc; } + if (unlikely(READ_ONCE(q->owner) == smp_processor_id())) { + kfree_skb_reason(skb, SKB_DROP_REASON_TC_RECLASSIFY_LOOP); + return NET_XMIT_DROP; + } /* * Heuristic to force contended enqueues to serialize on a * separate lock before trying to get qdisc main lock. @@ -3847,7 +3851,9 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, qdisc_run_end(q); rc = NET_XMIT_SUCCESS; } else { + WRITE_ONCE(q->owner, smp_processor_id()); rc = dev_qdisc_enqueue(skb, q, &to_free, txq); + WRITE_ONCE(q->owner, -1); if (qdisc_run_begin(q)) { if (unlikely(contended)) { spin_unlock(&q->busylock); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 60239378d43f..15c715c16247 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1376,6 +1376,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev, } } + sch->owner = -1; qdisc_hash_add(sch, false); trace_qdisc_create(ops, dev, parent);