public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint
@ 2026-02-05 21:21 Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing Jesper Dangaard Brouer
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:21 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

This series refactors qdisc drop reason handling by introducing a dedicated
enum qdisc_drop_reason and trace_qdisc_drop tracepoint, providing qdisc
layer drop diagnostics with direct qdisc context visibility.

Background:
-----------
Identifying which qdisc dropped a packet via skb_drop_reason is difficult.
Normally, the kfree_skb tracepoint caller "location" hints at the dropping
code, but qdisc drops happen at a central point (__dev_queue_xmit), making
this unusable. As a workaround, commits 5765c7f6e317 ("net_sched: sch_fq:
add three drop_reason") and a42d71e322a8 ("net_sched: sch_cake: Add drop
reasons") encoded qdisc names directly in the drop reason enums.

This series provides a cleaner solution by creating a dedicated qdisc
tracepoint that naturally includes qdisc context (handle, parent, kind).

Solution:
---------
Create a new tracepoint trace_qdisc_drop that builds on top of existing
trace_qdisc_enqueue infrastructure. It includes qdisc handle, parent,
qdisc kind (name), and device information directly.

The existing SKB_DROP_REASON_QDISC_DROP is retained for backwards
compatibility via kfree_skb_reason(). The qdisc-specific drop reasons
(QDISC_DROP_*) provide fine-grained detail via the new tracepoint.
The enum uses subsystem encoding (offset by SKB_DROP_REASON_SUBSYS_QDISC)
to catch type mismatches for debugging purposes.

This implements the alternative approach described in:
https://lore.kernel.org/all/6be17a08-f8aa-4f91-9bd0-d9e1f0a92d90@kernel.org/

Changes since RFC v1:
---------------------
- Renamed QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION (Toke)
- Renamed QDISC_DROP_FQ_BAND_LIMIT to QDISC_DROP_BAND_LIMIT
- Renamed QDISC_DROP_FQ_HORIZON_LIMIT to QDISC_DROP_HORIZON_LIMIT
- Added SKB_DROP_REASON_SUBSYS_QDISC subsystem encoding for enum debugging
- Added WARN_ON_ONCE to catch wrong enum type (skb vs qdisc drop reason)
- Updated SKB_DROP_REASON_QDISC_DROP doc to reference qdisc:qdisc_drop
- Split rename changes into separate patches for clarity

Series overview:
----------------
Patch 1: Introduce the qdisc drop reason infrastructure
  - New enum qdisc_drop_reason with subsystem encoding
  - New trace_qdisc_drop tracepoint with qdisc context
  - WARN_ON_ONCE to catch enum type mismatches
  - Convert FQ, FQ_CoDel, CoDel, SFB, pfifo_fast to use new infrastructure

Patch 2: Convert SFQ as example for reviewers
  - Demonstrates how to convert a flow-based qdisc
  - Adds QDISC_DROP_MAXFLOWS for flow table exhaustion

Patch 3: Fix CAKE to use enum qdisc_drop_reason
  - Change cobalt_should_drop() return type for type correctness

Patch 4: Rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION
  - Generic name without embedding qdisc name

Patch 5: Rename QDISC_DROP_FQ_* to generic names
  - QDISC_DROP_FQ_BAND_LIMIT -> QDISC_DROP_BAND_LIMIT
  - QDISC_DROP_FQ_HORIZON_LIMIT -> QDISC_DROP_HORIZON_LIMIT

Patch 6: DualPI2 use qdisc_dequeue_drop() for dequeue drops
  - Demonstrates dequeue-time drop handling with trace_qdisc_drop

---

Jesper Dangaard Brouer (6):
      net: sched: introduce qdisc-specific drop reason tracing
      net: sched: sfq: convert to qdisc drop reasons
      net: sched: sch_cake: use enum qdisc_drop_reason for cobalt_should_drop
      net: sched: rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION
      net: sched: rename QDISC_DROP_FQ_* to generic names
      net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops


 include/net/dropreason-core.h  |  48 ++-------------
 include/net/dropreason-qdisc.h | 106 +++++++++++++++++++++++++++++++++
 include/net/dropreason.h       |   6 ++
 include/net/sch_generic.h      |  36 +++++++----
 include/trace/events/qdisc.h   |  51 ++++++++++++++++
 net/core/dev.c                 |   8 +--
 net/sched/sch_cake.c           |  26 ++++----
 net/sched/sch_codel.c          |   5 +-
 net/sched/sch_dualpi2.c        |  17 +++---
 net/sched/sch_fq.c             |   7 +--
 net/sched/sch_fq_codel.c       |   4 +-
 net/sched/sch_fq_pie.c         |   4 +-
 net/sched/sch_generic.c        |  22 ++++++-
 net/sched/sch_gred.c           |   4 +-
 net/sched/sch_pie.c            |   4 +-
 net/sched/sch_red.c            |   4 +-
 net/sched/sch_sfb.c            |   4 +-
 net/sched/sch_sfq.c            |   8 +--
 18 files changed, 256 insertions(+), 108 deletions(-)
 create mode 100644 include/net/dropreason-qdisc.h

--


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
@ 2026-02-05 21:21 ` Jesper Dangaard Brouer
  2026-02-06  9:31   ` Toke Høiland-Jørgensen
  2026-02-05 21:21 ` [PATCH net-next v2 2/6] net: sched: sfq: convert to qdisc drop reasons Jesper Dangaard Brouer
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:21 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Create new enum qdisc_drop_reason and trace_qdisc_drop tracepoint
for qdisc layer drop diagnostics with direct qdisc context visibility.

The new tracepoint includes qdisc handle, parent, kind (name), and
device information. Existing SKB_DROP_REASON_QDISC_DROP is retained
for backwards compatibility via kfree_skb_reason().

Convert FQ, FQ_CoDel, CoDel, SFB, and pfifo_fast to use the new
infrastructure.

Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
---
 include/net/dropreason-core.h  |   42 ++----------------
 include/net/dropreason-qdisc.h |   94 ++++++++++++++++++++++++++++++++++++++++
 include/net/dropreason.h       |    6 +++
 include/net/sch_generic.h      |   36 ++++++++++-----
 include/trace/events/qdisc.h   |   51 ++++++++++++++++++++++
 net/core/dev.c                 |    8 ++-
 net/sched/sch_cake.c           |    6 +--
 net/sched/sch_codel.c          |    5 +-
 net/sched/sch_dualpi2.c        |    8 +--
 net/sched/sch_fq.c             |    7 +--
 net/sched/sch_fq_codel.c       |    4 +-
 net/sched/sch_fq_pie.c         |    4 +-
 net/sched/sch_generic.c        |   22 +++++++++
 net/sched/sch_gred.c           |    4 +-
 net/sched/sch_pie.c            |    4 +-
 net/sched/sch_red.c            |    4 +-
 net/sched/sch_sfb.c            |    4 +-
 17 files changed, 225 insertions(+), 84 deletions(-)
 create mode 100644 include/net/dropreason-qdisc.h

diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index a7b7abd66e21..3d8d284e05c8 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -68,12 +68,6 @@
 	FN(SECURITY_HOOK)		\
 	FN(QDISC_DROP)			\
 	FN(QDISC_BURST_DROP)		\
-	FN(QDISC_OVERLIMIT)		\
-	FN(QDISC_CONGESTED)		\
-	FN(CAKE_FLOOD)			\
-	FN(FQ_BAND_LIMIT)		\
-	FN(FQ_HORIZON_LIMIT)		\
-	FN(FQ_FLOW_LIMIT)		\
 	FN(CPU_BACKLOG)			\
 	FN(XDP)				\
 	FN(TC_INGRESS)			\
@@ -371,8 +365,10 @@ enum skb_drop_reason {
 	/** @SKB_DROP_REASON_SECURITY_HOOK: dropped due to security HOOK */
 	SKB_DROP_REASON_SECURITY_HOOK,
 	/**
-	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc when packet outputting (
-	 * failed to enqueue to current qdisc)
+	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc during enqueue or
+	 * dequeue. More specific drop reasons are available via the
+	 * qdisc:qdisc_drop tracepoint, which also provides qdisc handle
+	 * and name for identifying the source.
 	 */
 	SKB_DROP_REASON_QDISC_DROP,
 	/**
@@ -380,36 +376,6 @@ enum skb_drop_reason {
 	 * limit is hit.
 	 */
 	SKB_DROP_REASON_QDISC_BURST_DROP,
-	/**
-	 * @SKB_DROP_REASON_QDISC_OVERLIMIT: dropped by qdisc when a qdisc
-	 * instance exceeds its total buffer size limit.
-	 */
-	SKB_DROP_REASON_QDISC_OVERLIMIT,
-	/**
-	 * @SKB_DROP_REASON_QDISC_CONGESTED: dropped by a qdisc AQM algorithm
-	 * due to congestion.
-	 */
-	SKB_DROP_REASON_QDISC_CONGESTED,
-	/**
-	 * @SKB_DROP_REASON_CAKE_FLOOD: dropped by the flood protection part of
-	 * CAKE qdisc AQM algorithm (BLUE).
-	 */
-	SKB_DROP_REASON_CAKE_FLOOD,
-	/**
-	 * @SKB_DROP_REASON_FQ_BAND_LIMIT: dropped by fq qdisc when per band
-	 * limit is reached.
-	 */
-	SKB_DROP_REASON_FQ_BAND_LIMIT,
-	/**
-	 * @SKB_DROP_REASON_FQ_HORIZON_LIMIT: dropped by fq qdisc when packet
-	 * timestamp is too far in the future.
-	 */
-	SKB_DROP_REASON_FQ_HORIZON_LIMIT,
-	/**
-	 * @SKB_DROP_REASON_FQ_FLOW_LIMIT: dropped by fq qdisc when a flow
-	 * exceeds its limits.
-	 */
-	SKB_DROP_REASON_FQ_FLOW_LIMIT,
 	/**
 	 * @SKB_DROP_REASON_CPU_BACKLOG: failed to enqueue the skb to the per CPU
 	 * backlog queue. This can be caused by backlog queue full (see
diff --git a/include/net/dropreason-qdisc.h b/include/net/dropreason-qdisc.h
new file mode 100644
index 000000000000..e1a902e782ef
--- /dev/null
+++ b/include/net/dropreason-qdisc.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _LINUX_DROPREASON_QDISC_H
+#define _LINUX_DROPREASON_QDISC_H
+#include <net/dropreason.h>
+
+#define DEFINE_QDISC_DROP_REASON(FN, FNe)	\
+	FN(UNSPEC)			\
+	FN(GENERIC)			\
+	FN(OVERLIMIT)			\
+	FN(CONGESTED)			\
+	FN(CAKE_FLOOD)			\
+	FN(FQ_BAND_LIMIT)		\
+	FN(FQ_HORIZON_LIMIT)		\
+	FN(FQ_FLOW_LIMIT)		\
+	FNe(MAX)
+
+#undef FN
+#undef FNe
+#define FN(reason)	QDISC_DROP_##reason,
+#define FNe(reason)	QDISC_DROP_##reason
+
+/**
+ * enum qdisc_drop_reason - reason why a qdisc dropped a packet
+ *
+ * Qdisc-specific drop reasons for packet drops that occur within the
+ * traffic control (TC) queueing discipline layer. These reasons provide
+ * detailed diagnostics about why packets were dropped by various qdisc
+ * algorithms, enabling fine-grained monitoring and troubleshooting of
+ * queue behavior.
+ */
+enum qdisc_drop_reason {
+	/**
+	 * @QDISC_DROP_UNSPEC: unspecified qdisc drop reason, used for
+	 * zero-initialized drop_reason fields
+	 */
+	QDISC_DROP_UNSPEC = 0,
+	/**
+	 * @__QDISC_DROP_REASON: subsystem base value for qdisc drop reasons
+	 */
+	__QDISC_DROP_REASON = SKB_DROP_REASON_SUBSYS_QDISC <<
+				SKB_DROP_REASON_SUBSYS_SHIFT,
+	/**
+	 * @QDISC_DROP_GENERIC: generic/default qdisc drop, used when no
+	 * more specific reason applies
+	 */
+	QDISC_DROP_GENERIC,
+	/**
+	 * @QDISC_DROP_OVERLIMIT: packet dropped because the qdisc queue
+	 * length exceeded its configured limit (sch->limit). This typically
+	 * indicates the queue is full and cannot accept more packets.
+	 */
+	QDISC_DROP_OVERLIMIT,
+	/**
+	 * @QDISC_DROP_CONGESTED: packet dropped due to active congestion
+	 * control algorithms (e.g., CoDel, PIE, RED) detecting network
+	 * congestion. The qdisc proactively dropped the packet to signal
+	 * congestion to the sender and prevent bufferbloat.
+	 */
+	QDISC_DROP_CONGESTED,
+	/**
+	 * @QDISC_DROP_CAKE_FLOOD: CAKE qdisc dropped packet due to flood
+	 * protection mechanism (BLUE algorithm). This indicates potential
+	 * DoS/flood attack or unresponsive flow behavior.
+	 */
+	QDISC_DROP_CAKE_FLOOD,
+	/**
+	 * @QDISC_DROP_FQ_BAND_LIMIT: FQ (Fair Queue) dropped packet because
+	 * the priority band's packet limit was reached. Each priority band
+	 * in FQ has its own limit.
+	 */
+	QDISC_DROP_FQ_BAND_LIMIT,
+	/**
+	 * @QDISC_DROP_FQ_HORIZON_LIMIT: FQ dropped packet because its
+	 * timestamp is too far in the future (beyond horizon). This prevents
+	 * packets with unreasonable future timestamps from blocking the queue.
+	 */
+	QDISC_DROP_FQ_HORIZON_LIMIT,
+	/**
+	 * @QDISC_DROP_FQ_FLOW_LIMIT: FQ dropped packet because an individual
+	 * flow exceeded its per-flow packet limit.
+	 */
+	QDISC_DROP_FQ_FLOW_LIMIT,
+	/**
+	 * @QDISC_DROP_MAX: the maximum of qdisc drop reasons, which
+	 * shouldn't be used as a real 'reason' - only for tracing code gen
+	 */
+	QDISC_DROP_MAX,
+};
+
+#undef FN
+#undef FNe
+
+#endif
diff --git a/include/net/dropreason.h b/include/net/dropreason.h
index 7d3b1a2a6fec..1df60645fb27 100644
--- a/include/net/dropreason.h
+++ b/include/net/dropreason.h
@@ -23,6 +23,12 @@ enum skb_drop_reason_subsys {
 	 */
 	SKB_DROP_REASON_SUBSYS_OPENVSWITCH,
 
+	/**
+	 * @SKB_DROP_REASON_SUBSYS_QDISC: TC qdisc drop reasons,
+	 * see include/net/dropreason-qdisc.h
+	 */
+	SKB_DROP_REASON_SUBSYS_QDISC,
+
 	/** @SKB_DROP_REASON_SUBSYS_NUM: number of subsystems defined */
 	SKB_DROP_REASON_SUBSYS_NUM
 };
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c3a7268b567e..f3ee0bd5d0f3 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -20,12 +20,15 @@
 #include <net/rtnetlink.h>
 #include <net/flow_offload.h>
 #include <linux/xarray.h>
+#include <net/dropreason-qdisc.h>
 
 struct Qdisc_ops;
 struct qdisc_walker;
 struct tcf_walker;
 struct module;
 struct bpf_flow_keys;
+struct Qdisc;
+struct netdev_queue;
 
 struct qdisc_rate_table {
 	struct tc_ratespec rate;
@@ -1106,36 +1109,43 @@ static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb)
 	return cb;
 }
 
+/* TC classifier accessors - use enum skb_drop_reason */
 static inline enum skb_drop_reason
 tcf_get_drop_reason(const struct sk_buff *skb)
 {
-	return tc_skb_cb(skb)->drop_reason;
+	return (enum skb_drop_reason)tc_skb_cb(skb)->drop_reason;
 }
 
 static inline void tcf_set_drop_reason(const struct sk_buff *skb,
 				       enum skb_drop_reason reason)
 {
-	tc_skb_cb(skb)->drop_reason = reason;
+	tc_skb_cb(skb)->drop_reason = (enum qdisc_drop_reason)reason;
 }
 
-static inline void tcf_kfree_skb_list(struct sk_buff *skb)
+/* Qdisc accessors - use enum qdisc_drop_reason */
+static inline enum qdisc_drop_reason
+tcf_get_qdisc_drop_reason(const struct sk_buff *skb)
 {
-	while (unlikely(skb)) {
-		struct sk_buff *next = skb->next;
+	return tc_skb_cb(skb)->drop_reason;
+}
 
-		prefetch(next);
-		kfree_skb_reason(skb, tcf_get_drop_reason(skb));
-		skb = next;
-	}
+static inline void tcf_set_qdisc_drop_reason(const struct sk_buff *skb,
+					     enum qdisc_drop_reason reason)
+{
+	tc_skb_cb(skb)->drop_reason = reason;
 }
 
+void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q,
+			struct netdev_queue *txq,
+			struct net_device *dev);
+
 static inline void qdisc_dequeue_drop(struct Qdisc *q, struct sk_buff *skb,
-				      enum skb_drop_reason reason)
+				      enum qdisc_drop_reason reason)
 {
 	DEBUG_NET_WARN_ON_ONCE(!(q->flags & TCQ_F_DEQUEUE_DROPS));
 	DEBUG_NET_WARN_ON_ONCE(q->flags & TCQ_F_NOLOCK);
 
-	tcf_set_drop_reason(skb, reason);
+	tcf_set_qdisc_drop_reason(skb, reason);
 	skb->next = q->to_free;
 	q->to_free = skb;
 }
@@ -1312,9 +1322,9 @@ static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch,
 
 static inline int qdisc_drop_reason(struct sk_buff *skb, struct Qdisc *sch,
 				    struct sk_buff **to_free,
-				    enum skb_drop_reason reason)
+				    enum qdisc_drop_reason reason)
 {
-	tcf_set_drop_reason(skb, reason);
+	tcf_set_qdisc_drop_reason(skb, reason);
 	return qdisc_drop(skb, sch, to_free);
 }
 
diff --git a/include/trace/events/qdisc.h b/include/trace/events/qdisc.h
index ff33f41a9db7..d8a5c2677470 100644
--- a/include/trace/events/qdisc.h
+++ b/include/trace/events/qdisc.h
@@ -74,6 +74,57 @@ TRACE_EVENT(qdisc_enqueue,
 		  __entry->ifindex, __entry->handle, __entry->parent, __entry->skbaddr)
 );
 
+#undef FN
+#undef FNe
+#define FN(reason)	TRACE_DEFINE_ENUM(QDISC_DROP_##reason);
+#define FNe(reason)	TRACE_DEFINE_ENUM(QDISC_DROP_##reason);
+DEFINE_QDISC_DROP_REASON(FN, FNe)
+
+#undef FN
+#undef FNe
+#define FN(reason)	{ QDISC_DROP_##reason, #reason },
+#define FNe(reason)	{ QDISC_DROP_##reason, #reason }
+
+TRACE_EVENT(qdisc_drop,
+
+	TP_PROTO(struct Qdisc *qdisc, const struct netdev_queue *txq,
+		 struct net_device *dev, struct sk_buff *skb,
+		 enum qdisc_drop_reason reason),
+
+	TP_ARGS(qdisc, txq, dev, skb, reason),
+
+	TP_STRUCT__entry(
+		__field(struct Qdisc *, qdisc)
+		__field(const struct netdev_queue *, txq)
+		__field(void *,	skbaddr)
+		__field(int, ifindex)
+		__field(u32, handle)
+		__field(u32, parent)
+		__field(enum qdisc_drop_reason, reason)
+		__string(kind, qdisc->ops->id)
+	),
+
+	TP_fast_assign(
+		__entry->qdisc = qdisc;
+		__entry->txq	 = txq;
+		__entry->skbaddr = skb;
+		__entry->ifindex = dev ? dev->ifindex : 0;
+		__entry->handle	 = qdisc->handle;
+		__entry->parent	 = qdisc->parent;
+		__entry->reason	 = reason;
+		__assign_str(kind);
+	),
+
+	TP_printk("drop ifindex=%d kind=%s handle=0x%X parent=0x%X skbaddr=%p reason=%s",
+		  __entry->ifindex, __get_str(kind), __entry->handle,
+		  __entry->parent, __entry->skbaddr,
+		  __print_symbolic(__entry->reason,
+				   DEFINE_QDISC_DROP_REASON(FN, FNe)))
+);
+
+#undef FN
+#undef FNe
+
 TRACE_EVENT(qdisc_reset,
 
 	TP_PROTO(struct Qdisc *q),
diff --git a/net/core/dev.c b/net/core/dev.c
index 43de5af0d6ec..33262344b751 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4161,7 +4161,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 
 	qdisc_calculate_pkt_len(skb, q);
 
-	tcf_set_drop_reason(skb, SKB_DROP_REASON_QDISC_DROP);
+	tcf_set_qdisc_drop_reason(skb, QDISC_DROP_GENERIC);
 
 	if (q->flags & TCQ_F_NOLOCK) {
 		if (q->flags & TCQ_F_CAN_BYPASS && nolock_qdisc_is_empty(q) &&
@@ -4269,8 +4269,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 	spin_unlock(root_lock);
 
 free_skbs:
-	tcf_kfree_skb_list(to_free);
-	tcf_kfree_skb_list(to_free2);
+	tcf_kfree_skb_list(to_free, q, txq, dev);
+	tcf_kfree_skb_list(to_free2, q, txq, dev);
 	return rc;
 }
 
@@ -5795,7 +5795,7 @@ static __latent_entropy void net_tx_action(void)
 			to_free = qdisc_run(q);
 			if (root_lock)
 				spin_unlock(root_lock);
-			tcf_kfree_skb_list(to_free);
+			tcf_kfree_skb_list(to_free, q, NULL, qdisc_dev(q));
 		}
 
 		rcu_read_unlock();
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index fd56b7d88301..a2d1b292600d 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -548,7 +548,7 @@ static enum skb_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
 	if (next_due && vars->dropping) {
 		/* Use ECN mark if possible, otherwise drop */
 		if (!(vars->ecn_marked = INET_ECN_set_ce(skb)))
-			reason = SKB_DROP_REASON_QDISC_CONGESTED;
+			reason = QDISC_DROP_CONGESTED;
 
 		vars->count++;
 		if (!vars->count)
@@ -573,7 +573,7 @@ static enum skb_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
 	/* Simple BLUE implementation.  Lack of ECN is deliberate. */
 	if (vars->p_drop && reason == SKB_NOT_DROPPED_YET &&
 	    get_random_u32() < vars->p_drop)
-		reason = SKB_DROP_REASON_CAKE_FLOOD;
+		reason = QDISC_DROP_CAKE_FLOOD;
 
 	/* Overload the drop_next field as an activity timeout */
 	if (!vars->count)
@@ -1604,7 +1604,7 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free)
 	if (q->config->rate_flags & CAKE_FLAG_INGRESS)
 		cake_advance_shaper(q, b, skb, now, true);
 
-	qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT);
+	qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
 	sch->q.qlen--;
 
 	cake_heapify(q, 0);
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
index c6551578f1cf..dc2be90666ff 100644
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -52,7 +52,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)
 {
 	struct Qdisc *sch = ctx;
 
-	qdisc_dequeue_drop(sch, skb, SKB_DROP_REASON_QDISC_CONGESTED);
+	qdisc_dequeue_drop(sch, skb, QDISC_DROP_CONGESTED);
 	qdisc_qstats_drop(sch);
 }
 
@@ -86,8 +86,7 @@ static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 	}
 	q = qdisc_priv(sch);
 	q->drop_overlimit++;
-	return qdisc_drop_reason(skb, sch, to_free,
-				 SKB_DROP_REASON_QDISC_OVERLIMIT);
+	return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
 }
 
 static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
diff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c
index 6d7e6389758d..0b6a38704a3b 100644
--- a/net/sched/sch_dualpi2.c
+++ b/net/sched/sch_dualpi2.c
@@ -393,13 +393,11 @@ static int dualpi2_enqueue_skb(struct sk_buff *skb, struct Qdisc *sch,
 		qdisc_qstats_overlimit(sch);
 		if (skb_in_l_queue(skb))
 			qdisc_qstats_overlimit(q->l_queue);
-		return qdisc_drop_reason(skb, sch, to_free,
-					 SKB_DROP_REASON_QDISC_OVERLIMIT);
+		return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
 	}
 
 	if (q->drop_early && must_drop(sch, q, skb)) {
-		qdisc_drop_reason(skb, sch, to_free,
-				  SKB_DROP_REASON_QDISC_CONGESTED);
+		qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_CONGESTED);
 		return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
 	}
 
@@ -593,7 +591,7 @@ static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
 	while ((skb = dequeue_packet(sch, q, &credit_change, now))) {
 		if (!q->drop_early && must_drop(sch, q, skb)) {
 			drop_and_retry(q, skb, sch,
-				       SKB_DROP_REASON_QDISC_CONGESTED);
+				       QDISC_DROP_CONGESTED);
 			continue;
 		}
 
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 6e5f2f4f2415..058801fefca1 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -541,7 +541,7 @@ static bool fq_packet_beyond_horizon(const struct sk_buff *skb,
 	return unlikely((s64)skb->tstamp > (s64)(now + q->horizon));
 }
 
-#define FQDR(reason) SKB_DROP_REASON_FQ_##reason
+#define FQDR(reason) QDISC_DROP_FQ_##reason
 
 static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		      struct sk_buff **to_free)
@@ -554,8 +554,7 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 	band = fq_prio2band(q->prio2band, skb->priority & TC_PRIO_MAX);
 	if (unlikely(q->band_pkt_count[band] >= sch->limit)) {
 		q->stat_band_drops[band]++;
-		return qdisc_drop_reason(skb, sch, to_free,
-					 FQDR(BAND_LIMIT));
+		return qdisc_drop_reason(skb, sch, to_free, FQDR(BAND_LIMIT));
 	}
 
 	now = ktime_get_ns();
@@ -581,7 +580,7 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		if (unlikely(f->qlen >= q->flow_plimit)) {
 			q->stat_flows_plimit++;
 			return qdisc_drop_reason(skb, sch, to_free,
-						 FQDR(FLOW_LIMIT));
+						 QDISC_DROP_FQ_FLOW_LIMIT);
 		}
 
 		if (fq_flow_is_detached(f)) {
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index dc187c7f06b1..3e384a344bc3 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -168,7 +168,7 @@ static unsigned int fq_codel_drop(struct Qdisc *sch, unsigned int max_packets,
 		skb = dequeue_head(flow);
 		len += qdisc_pkt_len(skb);
 		mem += get_codel_cb(skb)->mem_usage;
-		tcf_set_drop_reason(skb, SKB_DROP_REASON_QDISC_OVERLIMIT);
+		tcf_set_qdisc_drop_reason(skb, QDISC_DROP_OVERLIMIT);
 		__qdisc_drop(skb, to_free);
 	} while (++i < max_packets && len < threshold);
 
@@ -275,7 +275,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)
 {
 	struct Qdisc *sch = ctx;
 
-	qdisc_dequeue_drop(sch, skb, SKB_DROP_REASON_QDISC_CONGESTED);
+	qdisc_dequeue_drop(sch, skb, QDISC_DROP_CONGESTED);
 	qdisc_qstats_drop(sch);
 }
 
diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c
index 7b96bc3ff891..9fe997179d78 100644
--- a/net/sched/sch_fq_pie.c
+++ b/net/sched/sch_fq_pie.c
@@ -130,7 +130,7 @@ static inline void flow_queue_add(struct fq_pie_flow *flow,
 static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 				struct sk_buff **to_free)
 {
-	enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
+	enum qdisc_drop_reason reason = QDISC_DROP_OVERLIMIT;
 	struct fq_pie_sched_data *q = qdisc_priv(sch);
 	struct fq_pie_flow *sel_flow;
 	int ret;
@@ -162,7 +162,7 @@ static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		q->overmemory++;
 	}
 
-	reason = SKB_DROP_REASON_QDISC_CONGESTED;
+	reason = QDISC_DROP_CONGESTED;
 
 	if (!pie_drop_early(sch, &q->p_params, &sel_flow->vars,
 			    sel_flow->backlog, skb->len)) {
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 852e603c1755..8bf0fbca541c 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -25,11 +25,11 @@
 #include <linux/skb_array.h>
 #include <linux/if_macvlan.h>
 #include <linux/bpf.h>
+#include <trace/events/qdisc.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
 #include <net/dst.h>
 #include <net/hotdata.h>
-#include <trace/events/qdisc.h>
 #include <trace/events/net.h>
 #include <net/xfrm.h>
 
@@ -37,6 +37,24 @@
 const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
 EXPORT_SYMBOL(default_qdisc_ops);
 
+void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q,
+			struct netdev_queue *txq,
+			struct net_device *dev)
+{
+	while (unlikely(skb)) {
+		struct sk_buff *next = skb->next;
+		enum qdisc_drop_reason reason = tcf_get_qdisc_drop_reason(skb);
+
+		prefetch(next);
+		/* Catch wrong enum: skb_drop_reason vs qdisc_drop_reason */
+		WARN_ON_ONCE(reason && reason < __QDISC_DROP_REASON);
+		trace_qdisc_drop(q, txq, dev, skb, reason);
+		kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_DROP);
+		skb = next;
+	}
+}
+EXPORT_SYMBOL(tcf_kfree_skb_list);
+
 static void qdisc_maybe_clear_missed(struct Qdisc *q,
 				     const struct netdev_queue *txq)
 {
@@ -741,7 +759,7 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
 	err = skb_array_produce(q, skb);
 
 	if (unlikely(err)) {
-		tcf_set_drop_reason(skb, SKB_DROP_REASON_QDISC_OVERLIMIT);
+		tcf_set_qdisc_drop_reason(skb, QDISC_DROP_OVERLIMIT);
 
 		if (qdisc_is_percpu_stats(qdisc))
 			return qdisc_drop_cpu(skb, qdisc, to_free);
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 532fde548b88..66b72a09725f 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -251,10 +251,10 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
 	q->stats.pdrop++;
 drop:
-	return qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT);
+	return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
 
 congestion_drop:
-	qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_CONGESTED);
+	qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_CONGESTED);
 	return NET_XMIT_CN;
 }
 
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index 0a377313b6a9..16f3f629cb8e 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(pie_drop_early);
 static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 			     struct sk_buff **to_free)
 {
-	enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
+	enum qdisc_drop_reason reason = QDISC_DROP_OVERLIMIT;
 	struct pie_sched_data *q = qdisc_priv(sch);
 	bool enqueue = false;
 
@@ -94,7 +94,7 @@ static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		goto out;
 	}
 
-	reason = SKB_DROP_REASON_QDISC_CONGESTED;
+	reason = QDISC_DROP_CONGESTED;
 
 	if (!pie_drop_early(sch, &q->params, &q->vars, sch->qstats.backlog,
 			    skb->len)) {
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 479c42d11083..c8d3d09f15e3 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -70,7 +70,7 @@ static int red_use_nodrop(struct red_sched_data *q)
 static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		       struct sk_buff **to_free)
 {
-	enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_CONGESTED;
+	enum qdisc_drop_reason reason = QDISC_DROP_CONGESTED;
 	struct red_sched_data *q = qdisc_priv(sch);
 	struct Qdisc *child = q->qdisc;
 	unsigned int len;
@@ -108,7 +108,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		break;
 
 	case RED_HARD_MARK:
-		reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
+		reason = QDISC_DROP_OVERLIMIT;
 		qdisc_qstats_overlimit(sch);
 		if (red_use_harddrop(q) || !red_use_ecn(q)) {
 			q->stats.forced_drop++;
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index d2835f1168e1..013738662128 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -280,7 +280,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		       struct sk_buff **to_free)
 {
 
-	enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
+	enum qdisc_drop_reason reason = QDISC_DROP_OVERLIMIT;
 	struct sfb_sched_data *q = qdisc_priv(sch);
 	unsigned int len = qdisc_pkt_len(skb);
 	struct Qdisc *child = q->qdisc;
@@ -381,7 +381,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 	}
 
 	r = get_random_u16() & SFB_MAX_PROB;
-	reason = SKB_DROP_REASON_QDISC_CONGESTED;
+	reason = QDISC_DROP_CONGESTED;
 
 	if (unlikely(r < p_min)) {
 		if (unlikely(p_min > SFB_MAX_PROB / 2)) {



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH net-next v2 2/6] net: sched: sfq: convert to qdisc drop reasons
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing Jesper Dangaard Brouer
@ 2026-02-05 21:21 ` Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 3/6] net: sched: sch_cake: use enum qdisc_drop_reason for cobalt_should_drop Jesper Dangaard Brouer
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:21 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Convert SFQ to use the new qdisc-specific drop reason infrastructure.

This patch demonstrates how to convert a flow-based qdisc to use the
new enum qdisc_drop_reason. As part of this conversion:

- Add QDISC_DROP_MAXFLOWS for flow table exhaustion
- Rename FQ_FLOW_LIMIT to generic FLOW_LIMIT, now shared by FQ and SFQ
- Use QDISC_DROP_OVERLIMIT for sfq_drop() when overall limit exceeded
- Use QDISC_DROP_FLOW_LIMIT for per-flow depth limit exceeded

The FLOW_LIMIT reason is now a common drop reason for per-flow limits,
applicable to both FQ and SFQ qdiscs.

Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
---
 include/net/dropreason-qdisc.h |   22 ++++++++++++++++------
 net/sched/sch_fq.c             |    2 +-
 net/sched/sch_sfq.c            |    8 ++++----
 3 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/include/net/dropreason-qdisc.h b/include/net/dropreason-qdisc.h
index e1a902e782ef..f70fe06213b0 100644
--- a/include/net/dropreason-qdisc.h
+++ b/include/net/dropreason-qdisc.h
@@ -9,10 +9,11 @@
 	FN(GENERIC)			\
 	FN(OVERLIMIT)			\
 	FN(CONGESTED)			\
+	FN(FLOW_LIMIT)			\
+	FN(MAXFLOWS)			\
 	FN(CAKE_FLOOD)			\
 	FN(FQ_BAND_LIMIT)		\
 	FN(FQ_HORIZON_LIMIT)		\
-	FN(FQ_FLOW_LIMIT)		\
 	FNe(MAX)
 
 #undef FN
@@ -58,6 +59,20 @@ enum qdisc_drop_reason {
 	 * congestion to the sender and prevent bufferbloat.
 	 */
 	QDISC_DROP_CONGESTED,
+	/**
+	 * @QDISC_DROP_FLOW_LIMIT: packet dropped because an individual flow
+	 * exceeded its per-flow packet/depth limit. Used by FQ and SFQ qdiscs
+	 * to enforce per-flow fairness and prevent a single flow from
+	 * monopolizing queue resources.
+	 */
+	QDISC_DROP_FLOW_LIMIT,
+	/**
+	 * @QDISC_DROP_MAXFLOWS: packet dropped because the qdisc's flow
+	 * tracking table is full and no free slots are available to allocate
+	 * for a new flow. This indicates flow table exhaustion in flow-based
+	 * qdiscs that maintain per-flow state (e.g., SFQ).
+	 */
+	QDISC_DROP_MAXFLOWS,
 	/**
 	 * @QDISC_DROP_CAKE_FLOOD: CAKE qdisc dropped packet due to flood
 	 * protection mechanism (BLUE algorithm). This indicates potential
@@ -76,11 +91,6 @@ enum qdisc_drop_reason {
 	 * packets with unreasonable future timestamps from blocking the queue.
 	 */
 	QDISC_DROP_FQ_HORIZON_LIMIT,
-	/**
-	 * @QDISC_DROP_FQ_FLOW_LIMIT: FQ dropped packet because an individual
-	 * flow exceeded its per-flow packet limit.
-	 */
-	QDISC_DROP_FQ_FLOW_LIMIT,
 	/**
 	 * @QDISC_DROP_MAX: the maximum of qdisc drop reasons, which
 	 * shouldn't be used as a real 'reason' - only for tracing code gen
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 058801fefca1..ca615d5433db 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -580,7 +580,7 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		if (unlikely(f->qlen >= q->flow_plimit)) {
 			q->stat_flows_plimit++;
 			return qdisc_drop_reason(skb, sch, to_free,
-						 QDISC_DROP_FQ_FLOW_LIMIT);
+						 QDISC_DROP_FLOW_LIMIT);
 		}
 
 		if (fq_flow_is_detached(f)) {
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 96eb2f122973..efb796976a5b 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -302,7 +302,7 @@ static unsigned int sfq_drop(struct Qdisc *sch, struct sk_buff **to_free)
 		sfq_dec(q, x);
 		sch->q.qlen--;
 		qdisc_qstats_backlog_dec(sch, skb);
-		qdisc_drop(skb, sch, to_free);
+		qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
 		return len;
 	}
 
@@ -363,7 +363,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 	if (x == SFQ_EMPTY_SLOT) {
 		x = q->dep[0].next; /* get a free slot */
 		if (x >= SFQ_MAX_FLOWS)
-			return qdisc_drop(skb, sch, to_free);
+			return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_MAXFLOWS);
 		q->ht[hash] = x;
 		slot = &q->slots[x];
 		slot->hash = hash;
@@ -420,14 +420,14 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 	if (slot->qlen >= q->maxdepth) {
 congestion_drop:
 		if (!sfq_headdrop(q))
-			return qdisc_drop(skb, sch, to_free);
+			return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_FLOW_LIMIT);
 
 		/* We know we have at least one packet in queue */
 		head = slot_dequeue_head(slot);
 		delta = qdisc_pkt_len(head) - qdisc_pkt_len(skb);
 		sch->qstats.backlog -= delta;
 		slot->backlog -= delta;
-		qdisc_drop(head, sch, to_free);
+		qdisc_drop_reason(head, sch, to_free, QDISC_DROP_FLOW_LIMIT);
 
 		slot_queue_add(slot, skb);
 		qdisc_tree_reduce_backlog(sch, 0, delta);



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH net-next v2 3/6] net: sched: sch_cake: use enum qdisc_drop_reason for cobalt_should_drop
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 2/6] net: sched: sfq: convert to qdisc drop reasons Jesper Dangaard Brouer
@ 2026-02-05 21:21 ` Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 4/6] net: sched: rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION Jesper Dangaard Brouer
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:21 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Change cobalt_should_drop() return type from enum skb_drop_reason to
enum qdisc_drop_reason to fix implicit enum conversion warnings.

Use QDISC_DROP_UNSPEC as the 'not dropped' sentinel instead of
SKB_NOT_DROPPED_YET. Both have the same compiled value (0), so the
comparison logic remains semantically equivalent.

Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
---
 net/sched/sch_cake.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index a2d1b292600d..da3c347574d2 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -497,13 +497,13 @@ static bool cobalt_queue_empty(struct cobalt_vars *vars,
 /* Call this with a freshly dequeued packet for possible congestion marking.
  * Returns true as an instruction to drop the packet, false for delivery.
  */
-static enum skb_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
-					       struct cobalt_params *p,
-					       ktime_t now,
-					       struct sk_buff *skb,
-					       u32 bulk_flows)
+static enum qdisc_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
+						 struct cobalt_params *p,
+						 ktime_t now,
+						 struct sk_buff *skb,
+						 u32 bulk_flows)
 {
-	enum skb_drop_reason reason = SKB_NOT_DROPPED_YET;
+	enum qdisc_drop_reason reason = QDISC_DROP_UNSPEC;
 	bool next_due, over_target;
 	ktime_t schedule;
 	u64 sojourn;
@@ -571,14 +571,14 @@ static enum skb_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
 	}
 
 	/* Simple BLUE implementation.  Lack of ECN is deliberate. */
-	if (vars->p_drop && reason == SKB_NOT_DROPPED_YET &&
+	if (vars->p_drop && reason == QDISC_DROP_UNSPEC &&
 	    get_random_u32() < vars->p_drop)
 		reason = QDISC_DROP_CAKE_FLOOD;
 
 	/* Overload the drop_next field as an activity timeout */
 	if (!vars->count)
 		vars->drop_next = ktime_add_ns(now, p->interval);
-	else if (ktime_to_ns(schedule) > 0 && reason == SKB_NOT_DROPPED_YET)
+	else if (ktime_to_ns(schedule) > 0 && reason == QDISC_DROP_UNSPEC)
 		vars->drop_next = now;
 
 	return reason;
@@ -2004,7 +2004,7 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch)
 {
 	struct cake_sched_data *q = qdisc_priv(sch);
 	struct cake_tin_data *b = &q->tins[q->cur_tin];
-	enum skb_drop_reason reason;
+	enum qdisc_drop_reason reason;
 	ktime_t now = ktime_get();
 	struct cake_flow *flow;
 	struct list_head *head;
@@ -2225,7 +2225,7 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch)
 					     !!(q->config->rate_flags &
 						CAKE_FLAG_INGRESS)));
 		/* Last packet in queue may be marked, shouldn't be dropped */
-		if (reason == SKB_NOT_DROPPED_YET || !flow->head)
+		if (reason == QDISC_DROP_UNSPEC || !flow->head)
 			break;
 
 		/* drop this packet, get another one */



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH net-next v2 4/6] net: sched: rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
                   ` (2 preceding siblings ...)
  2026-02-05 21:21 ` [PATCH net-next v2 3/6] net: sched: sch_cake: use enum qdisc_drop_reason for cobalt_should_drop Jesper Dangaard Brouer
@ 2026-02-05 21:21 ` Jesper Dangaard Brouer
  2026-02-05 21:21 ` [PATCH net-next v2 5/6] net: sched: rename QDISC_DROP_FQ_* to generic names Jesper Dangaard Brouer
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:21 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION to use a
generic name without embedding the qdisc name. This follows the
principle that drop reasons should describe the drop mechanism rather
than being tied to a specific qdisc implementation.

The flood protection drop reason is used by qdiscs implementing
probabilistic drop algorithms (like BLUE) that detect unresponsive
flows indicating potential DoS or flood attacks. CAKE uses this via
its Cobalt AQM component.

Suggested-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
---
 include/net/dropreason-qdisc.h |   11 ++++++-----
 net/sched/sch_cake.c           |    2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/net/dropreason-qdisc.h b/include/net/dropreason-qdisc.h
index f70fe06213b0..3759a801bddd 100644
--- a/include/net/dropreason-qdisc.h
+++ b/include/net/dropreason-qdisc.h
@@ -11,7 +11,7 @@
 	FN(CONGESTED)			\
 	FN(FLOW_LIMIT)			\
 	FN(MAXFLOWS)			\
-	FN(CAKE_FLOOD)			\
+	FN(FLOOD_PROTECTION)		\
 	FN(FQ_BAND_LIMIT)		\
 	FN(FQ_HORIZON_LIMIT)		\
 	FNe(MAX)
@@ -74,11 +74,12 @@ enum qdisc_drop_reason {
 	 */
 	QDISC_DROP_MAXFLOWS,
 	/**
-	 * @QDISC_DROP_CAKE_FLOOD: CAKE qdisc dropped packet due to flood
-	 * protection mechanism (BLUE algorithm). This indicates potential
-	 * DoS/flood attack or unresponsive flow behavior.
+	 * @QDISC_DROP_FLOOD_PROTECTION: packet dropped by flood protection
+	 * mechanism detecting unresponsive flows (potential DoS/flood).
+	 * Used by qdiscs implementing probabilistic drop algorithms like
+	 * BLUE (e.g., CAKE's Cobalt AQM).
 	 */
-	QDISC_DROP_CAKE_FLOOD,
+	QDISC_DROP_FLOOD_PROTECTION,
 	/**
 	 * @QDISC_DROP_FQ_BAND_LIMIT: FQ (Fair Queue) dropped packet because
 	 * the priority band's packet limit was reached. Each priority band
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index da3c347574d2..b08711fa5f97 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -573,7 +573,7 @@ static enum qdisc_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
 	/* Simple BLUE implementation.  Lack of ECN is deliberate. */
 	if (vars->p_drop && reason == QDISC_DROP_UNSPEC &&
 	    get_random_u32() < vars->p_drop)
-		reason = QDISC_DROP_CAKE_FLOOD;
+		reason = QDISC_DROP_FLOOD_PROTECTION;
 
 	/* Overload the drop_next field as an activity timeout */
 	if (!vars->count)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH net-next v2 5/6] net: sched: rename QDISC_DROP_FQ_* to generic names
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
                   ` (3 preceding siblings ...)
  2026-02-05 21:21 ` [PATCH net-next v2 4/6] net: sched: rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION Jesper Dangaard Brouer
@ 2026-02-05 21:21 ` Jesper Dangaard Brouer
  2026-02-05 21:22 ` [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops Jesper Dangaard Brouer
  2026-02-06  8:32 ` [syzbot ci] Re: net: sched: refactor qdisc drop reasons into dedicated tracepoint syzbot ci
  6 siblings, 0 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:21 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Rename FQ-specific drop reasons to generic names:
- QDISC_DROP_FQ_BAND_LIMIT -> QDISC_DROP_BAND_LIMIT
- QDISC_DROP_FQ_HORIZON_LIMIT -> QDISC_DROP_HORIZON_LIMIT

This follows the principle that drop reasons should describe the drop
mechanism rather than being tied to a specific qdisc implementation.
These concepts (priority band limits, timestamp horizon) could apply
to other qdiscs as well.

Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
---
 include/net/dropreason-qdisc.h |   21 +++++++++++----------
 net/sched/sch_fq.c             |    2 +-
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/net/dropreason-qdisc.h b/include/net/dropreason-qdisc.h
index 3759a801bddd..031fd8a0bc8c 100644
--- a/include/net/dropreason-qdisc.h
+++ b/include/net/dropreason-qdisc.h
@@ -12,8 +12,8 @@
 	FN(FLOW_LIMIT)			\
 	FN(MAXFLOWS)			\
 	FN(FLOOD_PROTECTION)		\
-	FN(FQ_BAND_LIMIT)		\
-	FN(FQ_HORIZON_LIMIT)		\
+	FN(BAND_LIMIT)			\
+	FN(HORIZON_LIMIT)		\
 	FNe(MAX)
 
 #undef FN
@@ -81,17 +81,18 @@ enum qdisc_drop_reason {
 	 */
 	QDISC_DROP_FLOOD_PROTECTION,
 	/**
-	 * @QDISC_DROP_FQ_BAND_LIMIT: FQ (Fair Queue) dropped packet because
-	 * the priority band's packet limit was reached. Each priority band
-	 * in FQ has its own limit.
+	 * @QDISC_DROP_BAND_LIMIT: packet dropped because the priority band's
+	 * limit was reached. Used by qdiscs with priority bands that have
+	 * per-band packet limits (e.g., FQ).
 	 */
-	QDISC_DROP_FQ_BAND_LIMIT,
+	QDISC_DROP_BAND_LIMIT,
 	/**
-	 * @QDISC_DROP_FQ_HORIZON_LIMIT: FQ dropped packet because its
-	 * timestamp is too far in the future (beyond horizon). This prevents
-	 * packets with unreasonable future timestamps from blocking the queue.
+	 * @QDISC_DROP_HORIZON_LIMIT: packet dropped because its timestamp
+	 * is too far in the future (beyond horizon). This prevents packets
+	 * with unreasonable future timestamps from occupying queue space.
+	 * Used by qdiscs with time-based scheduling (e.g., FQ).
 	 */
-	QDISC_DROP_FQ_HORIZON_LIMIT,
+	QDISC_DROP_HORIZON_LIMIT,
 	/**
 	 * @QDISC_DROP_MAX: the maximum of qdisc drop reasons, which
 	 * shouldn't be used as a real 'reason' - only for tracing code gen
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index ca615d5433db..a8432b63d496 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -541,7 +541,7 @@ static bool fq_packet_beyond_horizon(const struct sk_buff *skb,
 	return unlikely((s64)skb->tstamp > (s64)(now + q->horizon));
 }
 
-#define FQDR(reason) QDISC_DROP_FQ_##reason
+#define FQDR(reason) QDISC_DROP_##reason
 
 static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		      struct sk_buff **to_free)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
                   ` (4 preceding siblings ...)
  2026-02-05 21:21 ` [PATCH net-next v2 5/6] net: sched: rename QDISC_DROP_FQ_* to generic names Jesper Dangaard Brouer
@ 2026-02-05 21:22 ` Jesper Dangaard Brouer
  2026-02-06  4:09   ` kernel test robot
  2026-02-06  4:50   ` kernel test robot
  2026-02-06  8:32 ` [syzbot ci] Re: net: sched: refactor qdisc drop reasons into dedicated tracepoint syzbot ci
  6 siblings, 2 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-05 21:22 UTC (permalink / raw)
  To: netdev, Eric Dumazet, David S. Miller, Paolo Abeni,
	Toke Høiland-Jørgensen
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

DualPI2 drops packets during dequeue but was using kfree_skb_reason()
directly, bypassing trace_qdisc_drop. Convert to qdisc_dequeue_drop()
and move DUALPI2_STEP_DROP to the qdisc drop reason enum.

- Set TCQ_F_DEQUEUE_DROPS flag in dualpi2_init()
- Use enum qdisc_drop_reason in drop_and_retry()
- Replace kfree_skb_reason() with qdisc_dequeue_drop()

Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
---
 include/net/dropreason-core.h |    6 ------
 net/sched/sch_dualpi2.c       |    9 +++++----
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index 3d8d284e05c8..5c8c2eb3d2c5 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -121,7 +121,6 @@
 	FN(CANFD_RX_INVALID_FRAME)	\
 	FN(CANXL_RX_INVALID_FRAME)	\
 	FN(PFMEMALLOC)	\
-	FN(DUALPI2_STEP_DROP)		\
 	FN(PSP_INPUT)			\
 	FN(PSP_OUTPUT)			\
 	FNe(MAX)
@@ -579,11 +578,6 @@ enum skb_drop_reason {
 	 * reached a path or socket not eligible for use of memory reserves
 	 */
 	SKB_DROP_REASON_PFMEMALLOC,
-	/**
-	 * @SKB_DROP_REASON_DUALPI2_STEP_DROP: dropped by the step drop
-	 * threshold of DualPI2 qdisc.
-	 */
-	SKB_DROP_REASON_DUALPI2_STEP_DROP,
 	/** @SKB_DROP_REASON_PSP_INPUT: PSP input checks failed */
 	SKB_DROP_REASON_PSP_INPUT,
 	/** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */
diff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c
index 0b6a38704a3b..d7a59eefd070 100644
--- a/net/sched/sch_dualpi2.c
+++ b/net/sched/sch_dualpi2.c
@@ -571,11 +571,11 @@ static int do_step_aqm(struct dualpi2_sched_data *q, struct sk_buff *skb,
 }
 
 static void drop_and_retry(struct dualpi2_sched_data *q, struct sk_buff *skb,
-			   struct Qdisc *sch, enum skb_drop_reason reason)
+			   struct Qdisc *sch, enum qdisc_drop_reason reason)
 {
 	++q->deferred_drops_cnt;
 	q->deferred_drops_len += qdisc_pkt_len(skb);
-	kfree_skb_reason(skb, reason);
+	qdisc_dequeue_drop(sch, skb, reason);
 	qdisc_qstats_drop(sch);
 }
 
@@ -597,8 +597,7 @@ static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
 
 		if (skb_in_l_queue(skb) && do_step_aqm(q, skb, now)) {
 			qdisc_qstats_drop(q->l_queue);
-			drop_and_retry(q, skb, sch,
-				       SKB_DROP_REASON_DUALPI2_STEP_DROP);
+			drop_and_retry(q, skb, sch, QDISC_DROP_STEP_DROP);
 			continue;
 		}
 
@@ -915,6 +914,8 @@ static int dualpi2_init(struct Qdisc *sch, struct nlattr *opt,
 	struct dualpi2_sched_data *q = qdisc_priv(sch);
 	int err;
 
+	sch->flags |= TCQ_F_DEQUEUE_DROPS;
+
 	q->l_queue = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
 				       TC_H_MAKE(sch->handle, 1), extack);
 	if (!q->l_queue)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops
  2026-02-05 21:22 ` [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops Jesper Dangaard Brouer
@ 2026-02-06  4:09   ` kernel test robot
  2026-02-06  4:50   ` kernel test robot
  1 sibling, 0 replies; 14+ messages in thread
From: kernel test robot @ 2026-02-06  4:09 UTC (permalink / raw)
  To: Jesper Dangaard Brouer, netdev, Eric Dumazet, David S. Miller,
	Paolo Abeni, Toke Høiland-Jørgensen
  Cc: llvm, oe-kbuild-all, Jesper Dangaard Brouer, bpf, Jakub Kicinski,
	horms, jiri, edumazet, xiyou.wangcong, jhs, atenart, carges,
	kernel-team

Hi Jesper,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Jesper-Dangaard-Brouer/net-sched-introduce-qdisc-specific-drop-reason-tracing/20260206-052816
base:   net-next/main
patch link:    https://lore.kernel.org/r/177032652354.1975497.2269771162710918590.stgit%40firesoul
patch subject: [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops
config: sparc64-randconfig-002-20260206 (https://download.01.org/0day-ci/archive/20260206/202602061240.CRDtcOeX-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260206/202602061240.CRDtcOeX-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602061240.CRDtcOeX-lkp@intel.com/

All errors (new ones prefixed by >>):

>> net/sched/sch_dualpi2.c:600:32: error: use of undeclared identifier 'QDISC_DROP_STEP_DROP'; did you mean 'QDISC_DROP_GENERIC'?
     600 |                         drop_and_retry(q, skb, sch, QDISC_DROP_STEP_DROP);
         |                                                     ^~~~~~~~~~~~~~~~~~~~
         |                                                     QDISC_DROP_GENERIC
   include/net/dropreason-qdisc.h:48:2: note: 'QDISC_DROP_GENERIC' declared here
      48 |         QDISC_DROP_GENERIC,
         |         ^
   1 error generated.


vim +600 net/sched/sch_dualpi2.c

   581	
   582	static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
   583	{
   584		struct dualpi2_sched_data *q = qdisc_priv(sch);
   585		struct sk_buff *skb;
   586		int credit_change;
   587		u64 now;
   588	
   589		now = ktime_get_ns();
   590	
   591		while ((skb = dequeue_packet(sch, q, &credit_change, now))) {
   592			if (!q->drop_early && must_drop(sch, q, skb)) {
   593				drop_and_retry(q, skb, sch,
   594					       QDISC_DROP_CONGESTED);
   595				continue;
   596			}
   597	
   598			if (skb_in_l_queue(skb) && do_step_aqm(q, skb, now)) {
   599				qdisc_qstats_drop(q->l_queue);
 > 600				drop_and_retry(q, skb, sch, QDISC_DROP_STEP_DROP);
   601				continue;
   602			}
   603	
   604			q->c_protection_credit += credit_change;
   605			qdisc_bstats_update(sch, skb);
   606			break;
   607		}
   608	
   609		if (q->deferred_drops_cnt) {
   610			qdisc_tree_reduce_backlog(sch, q->deferred_drops_cnt,
   611						  q->deferred_drops_len);
   612			q->deferred_drops_cnt = 0;
   613			q->deferred_drops_len = 0;
   614		}
   615		return skb;
   616	}
   617	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops
  2026-02-05 21:22 ` [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops Jesper Dangaard Brouer
  2026-02-06  4:09   ` kernel test robot
@ 2026-02-06  4:50   ` kernel test robot
  1 sibling, 0 replies; 14+ messages in thread
From: kernel test robot @ 2026-02-06  4:50 UTC (permalink / raw)
  To: Jesper Dangaard Brouer, netdev, Eric Dumazet, David S. Miller,
	Paolo Abeni, Toke Høiland-Jørgensen
  Cc: oe-kbuild-all, Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms,
	jiri, edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Hi Jesper,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Jesper-Dangaard-Brouer/net-sched-introduce-qdisc-specific-drop-reason-tracing/20260206-052816
base:   net-next/main
patch link:    https://lore.kernel.org/r/177032652354.1975497.2269771162710918590.stgit%40firesoul
patch subject: [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20260206/202602061245.hvInrQwP-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260206/202602061245.hvInrQwP-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602061245.hvInrQwP-lkp@intel.com/

All errors (new ones prefixed by >>):

   net/sched/sch_dualpi2.c: In function 'dualpi2_qdisc_dequeue':
>> net/sched/sch_dualpi2.c:600:53: error: 'QDISC_DROP_STEP_DROP' undeclared (first use in this function); did you mean 'QDISC_DROP_GENERIC'?
     600 |                         drop_and_retry(q, skb, sch, QDISC_DROP_STEP_DROP);
         |                                                     ^~~~~~~~~~~~~~~~~~~~
         |                                                     QDISC_DROP_GENERIC
   net/sched/sch_dualpi2.c:600:53: note: each undeclared identifier is reported only once for each function it appears in


vim +600 net/sched/sch_dualpi2.c

   581	
   582	static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)
   583	{
   584		struct dualpi2_sched_data *q = qdisc_priv(sch);
   585		struct sk_buff *skb;
   586		int credit_change;
   587		u64 now;
   588	
   589		now = ktime_get_ns();
   590	
   591		while ((skb = dequeue_packet(sch, q, &credit_change, now))) {
   592			if (!q->drop_early && must_drop(sch, q, skb)) {
   593				drop_and_retry(q, skb, sch,
   594					       QDISC_DROP_CONGESTED);
   595				continue;
   596			}
   597	
   598			if (skb_in_l_queue(skb) && do_step_aqm(q, skb, now)) {
   599				qdisc_qstats_drop(q->l_queue);
 > 600				drop_and_retry(q, skb, sch, QDISC_DROP_STEP_DROP);
   601				continue;
   602			}
   603	
   604			q->c_protection_credit += credit_change;
   605			qdisc_bstats_update(sch, skb);
   606			break;
   607		}
   608	
   609		if (q->deferred_drops_cnt) {
   610			qdisc_tree_reduce_backlog(sch, q->deferred_drops_cnt,
   611						  q->deferred_drops_len);
   612			q->deferred_drops_cnt = 0;
   613			q->deferred_drops_len = 0;
   614		}
   615		return skb;
   616	}
   617	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [syzbot ci] Re: net: sched: refactor qdisc drop reasons into dedicated tracepoint
  2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
                   ` (5 preceding siblings ...)
  2026-02-05 21:22 ` [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops Jesper Dangaard Brouer
@ 2026-02-06  8:32 ` syzbot ci
  6 siblings, 0 replies; 14+ messages in thread
From: syzbot ci @ 2026-02-06  8:32 UTC (permalink / raw)
  To: atenart, bpf, carges, davem, edumazet, eric.dumazet, hawk, horms,
	jhs, jiri, kernel-team, kuba, netdev, pabeni, toke,
	xiyou.wangcong
  Cc: syzbot, syzkaller-bugs

syzbot ci has tested the following series

[v2] net: sched: refactor qdisc drop reasons into dedicated tracepoint
https://lore.kernel.org/all/177032644012.1975497.16411100029657607833.stgit@firesoul
* [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing
* [PATCH net-next v2 2/6] net: sched: sfq: convert to qdisc drop reasons
* [PATCH net-next v2 3/6] net: sched: sch_cake: use enum qdisc_drop_reason for cobalt_should_drop
* [PATCH net-next v2 4/6] net: sched: rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION
* [PATCH net-next v2 5/6] net: sched: rename QDISC_DROP_FQ_* to generic names
* [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops

and found the following issue:
WARNING in __dev_queue_xmit

Full report is available here:
https://ci.syzbot.org/series/51381d54-6fc9-4542-a8cd-eac656a11965

***

WARNING in __dev_queue_xmit

tree:      net-next
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net-next.git
base:      7a4cd71fa4514cd85df39b3cf99da8142660cdcd
arch:      amd64
compiler:  Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
config:    https://ci.syzbot.org/builds/17bc5e9e-8ccc-4afb-a291-312bbc43df20/config
C repro:   https://ci.syzbot.org/findings/20939160-05e8-4589-a6d5-6a253d5e39b0/c_repro
syz repro: https://ci.syzbot.org/findings/20939160-05e8-4589-a6d5-6a253d5e39b0/syz_repro

syzkaller0: entered promiscuous mode
syzkaller0: entered allmulticast mode
------------[ cut here ]------------
reason && reason < __QDISC_DROP_REASON
WARNING: net/sched/sch_generic.c:50 at tcf_kfree_skb_list+0xd6/0x100 net/sched/sch_generic.c:50, CPU#0: syz.0.17/5949
Modules linked in:
CPU: 0 UID: 0 PID: 5949 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:tcf_kfree_skb_list+0xd6/0x100 net/sched/sch_generic.c:50
Code: 89 e8 e8 5d 00 00 00 31 ff 4c 89 e6 ba 40 00 00 00 e8 be e6 d6 ff 4c 8b 24 24 4d 85 e4 74 27 e9 6e ff ff ff e8 1b f3 50 f8 90 <0f> 0b 90 eb c4 44 89 e9 80 e1 07 80 c1 03 38 c1 7c 96 4c 89 ef e8
RSP: 0018:ffffc90003e67360 EFLAGS: 00010293
RAX: ffffffff89718645 RBX: ffff8881133cc000 RCX: ffff8881738b9d40
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 000000000002ffff
RBP: 0000000000000001 R08: ffff88811571195b R09: 1ffff11022ae232b
R10: dffffc0000000000 R11: ffffed1022ae232c R12: ffff88810a9bca80
R13: 0000000000000002 R14: ffff888109569400 R15: ffff888115711800
FS:  000055558d217500(0000) GS:ffff88818e31a000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000001410 CR3: 0000000166b9c000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 __dev_xmit_skb net/core/dev.c:4272 [inline]
 __dev_queue_xmit+0x18e5/0x3180 net/core/dev.c:4797
 packet_snd net/packet/af_packet.c:3077 [inline]
 packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3109
 sock_sendmsg_nosec net/socket.c:727 [inline]
 __sock_sendmsg+0x21c/0x270 net/socket.c:742
 ____sys_sendmsg+0x4d7/0x810 net/socket.c:2592
 ___sys_sendmsg+0x2a5/0x360 net/socket.c:2646
 __sys_sendmsg net/socket.c:2678 [inline]
 __do_sys_sendmsg net/socket.c:2683 [inline]
 __se_sys_sendmsg net/socket.c:2681 [inline]
 __x64_sys_sendmsg+0x1bd/0x2a0 net/socket.c:2681
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f6544b9acb9
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffc871586c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00007f6544e15fa0 RCX: 00007f6544b9acb9
RDX: 0000000000000004 RSI: 00002000000000c0 RDI: 0000000000000008
RBP: 00007f6544c08bf7 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f6544e15fac R14: 00007f6544e15fa0 R15: 00007f6544e15fa0
 </TASK>


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing
  2026-02-05 21:21 ` [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing Jesper Dangaard Brouer
@ 2026-02-06  9:31   ` Toke Høiland-Jørgensen
  2026-02-06 14:14     ` Jesper Dangaard Brouer
  0 siblings, 1 reply; 14+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-02-06  9:31 UTC (permalink / raw)
  To: Jesper Dangaard Brouer, netdev, Eric Dumazet, David S. Miller,
	Paolo Abeni
  Cc: Jesper Dangaard Brouer, bpf, Jakub Kicinski, horms, jiri,
	edumazet, xiyou.wangcong, jhs, atenart, carges, kernel-team

Jesper Dangaard Brouer <hawk@kernel.org> writes:

> Create new enum qdisc_drop_reason and trace_qdisc_drop tracepoint
> for qdisc layer drop diagnostics with direct qdisc context visibility.
>
> The new tracepoint includes qdisc handle, parent, kind (name), and
> device information. Existing SKB_DROP_REASON_QDISC_DROP is retained
> for backwards compatibility via kfree_skb_reason().
>
> Convert FQ, FQ_CoDel, CoDel, SFB, and pfifo_fast to use the new
> infrastructure.
>
> Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
> ---
>  include/net/dropreason-core.h  |   42 ++----------------
>  include/net/dropreason-qdisc.h |   94 ++++++++++++++++++++++++++++++++++++++++
>  include/net/dropreason.h       |    6 +++
>  include/net/sch_generic.h      |   36 ++++++++++-----
>  include/trace/events/qdisc.h   |   51 ++++++++++++++++++++++
>  net/core/dev.c                 |    8 ++-
>  net/sched/sch_cake.c           |    6 +--
>  net/sched/sch_codel.c          |    5 +-
>  net/sched/sch_dualpi2.c        |    8 +--
>  net/sched/sch_fq.c             |    7 +--
>  net/sched/sch_fq_codel.c       |    4 +-
>  net/sched/sch_fq_pie.c         |    4 +-
>  net/sched/sch_generic.c        |   22 +++++++++
>  net/sched/sch_gred.c           |    4 +-
>  net/sched/sch_pie.c            |    4 +-
>  net/sched/sch_red.c            |    4 +-
>  net/sched/sch_sfb.c            |    4 +-
>  17 files changed, 225 insertions(+), 84 deletions(-)
>  create mode 100644 include/net/dropreason-qdisc.h
>
> diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
> index a7b7abd66e21..3d8d284e05c8 100644
> --- a/include/net/dropreason-core.h
> +++ b/include/net/dropreason-core.h
> @@ -68,12 +68,6 @@
>  	FN(SECURITY_HOOK)		\
>  	FN(QDISC_DROP)			\
>  	FN(QDISC_BURST_DROP)		\
> -	FN(QDISC_OVERLIMIT)		\
> -	FN(QDISC_CONGESTED)		\
> -	FN(CAKE_FLOOD)			\
> -	FN(FQ_BAND_LIMIT)		\
> -	FN(FQ_HORIZON_LIMIT)		\
> -	FN(FQ_FLOW_LIMIT)		\
>  	FN(CPU_BACKLOG)			\
>  	FN(XDP)				\
>  	FN(TC_INGRESS)			\
> @@ -371,8 +365,10 @@ enum skb_drop_reason {
>  	/** @SKB_DROP_REASON_SECURITY_HOOK: dropped due to security HOOK */
>  	SKB_DROP_REASON_SECURITY_HOOK,
>  	/**
> -	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc when packet outputting (
> -	 * failed to enqueue to current qdisc)
> +	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc during enqueue or
> +	 * dequeue. More specific drop reasons are available via the
> +	 * qdisc:qdisc_drop tracepoint, which also provides qdisc handle
> +	 * and name for identifying the source.

IIUC, this is not needed, see below:

[...]

> @@ -37,6 +37,24 @@
>  const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
>  EXPORT_SYMBOL(default_qdisc_ops);
>  
> +void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q,
> +			struct netdev_queue *txq,
> +			struct net_device *dev)
> +{
> +	while (unlikely(skb)) {
> +		struct sk_buff *next = skb->next;
> +		enum qdisc_drop_reason reason = tcf_get_qdisc_drop_reason(skb);
> +
> +		prefetch(next);
> +		/* Catch wrong enum: skb_drop_reason vs qdisc_drop_reason */
> +		WARN_ON_ONCE(reason && reason < __QDISC_DROP_REASON);
> +		trace_qdisc_drop(q, txq, dev, skb, reason);
> +		kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_DROP);

AFAIU, the idea here is that you just pass the same 'reason' value to
kfree_skb_reason(). Because of the subsys shift and offset, these will
all be unique values, so anyone just watching the old tracepoint will
get QDISC_DROP_* reasons with no context, and if you want the context
you listen to the qdisc_drop tracepoint.

-Toke


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing
  2026-02-06  9:31   ` Toke Høiland-Jørgensen
@ 2026-02-06 14:14     ` Jesper Dangaard Brouer
  2026-02-06 16:31       ` Toke Høiland-Jørgensen
  0 siblings, 1 reply; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-06 14:14 UTC (permalink / raw)
  To: atenart, Toke Høiland-Jørgensen, netdev, Eric Dumazet,
	Paolo Abeni
  Cc: bpf, Jakub Kicinski, horms, jiri, edumazet, xiyou.wangcong, jhs,
	carges, kernel-team, David S. Miller



On 06/02/2026 10.31, Toke Høiland-Jørgensen wrote:
> Jesper Dangaard Brouer <hawk@kernel.org> writes:
> 
>> Create new enum qdisc_drop_reason and trace_qdisc_drop tracepoint
>> for qdisc layer drop diagnostics with direct qdisc context visibility.
>>
>> The new tracepoint includes qdisc handle, parent, kind (name), and
>> device information. Existing SKB_DROP_REASON_QDISC_DROP is retained
>> for backwards compatibility via kfree_skb_reason().
>>
>> Convert FQ, FQ_CoDel, CoDel, SFB, and pfifo_fast to use the new
>> infrastructure.
>>
>> Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
[...]
>> diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
>> index a7b7abd66e21..3d8d284e05c8 100644
>> --- a/include/net/dropreason-core.h
>> +++ b/include/net/dropreason-core.h
>> @@ -68,12 +68,6 @@
>>   	FN(SECURITY_HOOK)		\
>>   	FN(QDISC_DROP)			\
>>   	FN(QDISC_BURST_DROP)		\
>> -	FN(QDISC_OVERLIMIT)		\
>> -	FN(QDISC_CONGESTED)		\
>> -	FN(CAKE_FLOOD)			\
>> -	FN(FQ_BAND_LIMIT)		\
>> -	FN(FQ_HORIZON_LIMIT)		\
>> -	FN(FQ_FLOW_LIMIT)		\
>>   	FN(CPU_BACKLOG)			\
>>   	FN(XDP)				\
>>   	FN(TC_INGRESS)			\
>> @@ -371,8 +365,10 @@ enum skb_drop_reason {
>>   	/** @SKB_DROP_REASON_SECURITY_HOOK: dropped due to security HOOK */
>>   	SKB_DROP_REASON_SECURITY_HOOK,
>>   	/**
>> -	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc when packet outputting (
>> -	 * failed to enqueue to current qdisc)
>> +	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc during enqueue or
>> +	 * dequeue. More specific drop reasons are available via the
>> +	 * qdisc:qdisc_drop tracepoint, which also provides qdisc handle
>> +	 * and name for identifying the source.
> 
> IIUC, this is not needed, see below:
> 
> [...]
> 
>> @@ -37,6 +37,24 @@
>>   const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
>>   EXPORT_SYMBOL(default_qdisc_ops);
>>   
>> +void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q,
>> +			struct netdev_queue *txq,
>> +			struct net_device *dev)
>> +{
>> +	while (unlikely(skb)) {
>> +		struct sk_buff *next = skb->next;
>> +		enum qdisc_drop_reason reason = tcf_get_qdisc_drop_reason(skb);
>> +
>> +		prefetch(next);
>> +		/* Catch wrong enum: skb_drop_reason vs qdisc_drop_reason */
>> +		WARN_ON_ONCE(reason && reason < __QDISC_DROP_REASON);
>> +		trace_qdisc_drop(q, txq, dev, skb, reason);
>> +		kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_DROP);
> 
> AFAIU, the idea here is that you just pass the same 'reason' value to
> kfree_skb_reason(). Because of the subsys shift and offset, these will
> all be unique values, so anyone just watching the old tracepoint will
> get QDISC_DROP_* reasons with no context, and if you want the context
> you listen to the qdisc_drop tracepoint.

I'm already changing this code in V3, as syzbot revealed that some
existing skb_drop_reason's do arrive here, which is the TC filter drop
reasons (SKB_DROP_REASON_TC_*).  We primarily need subsys encoding as
we share the SKB->cb area.

This is the new code, that pass 'reason' through:

  /* TC classifier and qdisc share drop_reason storage.
   * Check subsystem mask to identify qdisc drop reasons,
   * else pass through skb_drop_reason set by TC classifier.
   */
  if ((reason & SKB_DROP_REASON_SUBSYS_MASK) == __QDISC_DROP_REASON) {
  	trace_qdisc_drop(q, txq, dev, skb, reason);
  	skb_reason = SKB_DROP_REASON_QDISC_DROP;
  } else {
  	skb_reason = (enum skb_drop_reason)reason;
  }
  kfree_skb_reason(skb, skb_reason);

I do realize that the reason is now a unique value, that in principle
could be passed through, *BUT* that will break existing userspace
tools.  E.g. the `perf trace -e skb:kfree_skb` cannot decode these to
strings. (The net/core/drop_monitor.c also need special handling.)
I actually want to give userspace a *single* SKB_DROP_REASON_QDISC_DROP
reason (that existing tools already knows).

Leaking extra qdisc drop reasons is not helpful to consume as it is not
actionable without knowing the qdisc. A QDISC_DROP_OVERLIMIT from FQ is
very different from one in CAKE - knowing just the reason without the
qdisc type/config is insufficient for debugging. The trace_qdisc_drop
tracepoint provides both the reason AND the qdisc context together

I've talked to our "consumer" tool developers and our plan is to try
attach to new tracepoint, if that is successful we change the existing
SKB_DROP_REASON_QDISC_DROP sampling rate to be zero.


--Jesper

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing
  2026-02-06 14:14     ` Jesper Dangaard Brouer
@ 2026-02-06 16:31       ` Toke Høiland-Jørgensen
  2026-02-09 13:45         ` Jesper Dangaard Brouer
  0 siblings, 1 reply; 14+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-02-06 16:31 UTC (permalink / raw)
  To: Jesper Dangaard Brouer, atenart, netdev, Eric Dumazet,
	Paolo Abeni
  Cc: bpf, Jakub Kicinski, horms, jiri, edumazet, xiyou.wangcong, jhs,
	carges, kernel-team, David S. Miller

Jesper Dangaard Brouer <hawk@kernel.org> writes:

> On 06/02/2026 10.31, Toke Høiland-Jørgensen wrote:
>> Jesper Dangaard Brouer <hawk@kernel.org> writes:
>> 
>>> Create new enum qdisc_drop_reason and trace_qdisc_drop tracepoint
>>> for qdisc layer drop diagnostics with direct qdisc context visibility.
>>>
>>> The new tracepoint includes qdisc handle, parent, kind (name), and
>>> device information. Existing SKB_DROP_REASON_QDISC_DROP is retained
>>> for backwards compatibility via kfree_skb_reason().
>>>
>>> Convert FQ, FQ_CoDel, CoDel, SFB, and pfifo_fast to use the new
>>> infrastructure.
>>>
>>> Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
> [...]
>>> diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
>>> index a7b7abd66e21..3d8d284e05c8 100644
>>> --- a/include/net/dropreason-core.h
>>> +++ b/include/net/dropreason-core.h
>>> @@ -68,12 +68,6 @@
>>>   	FN(SECURITY_HOOK)		\
>>>   	FN(QDISC_DROP)			\
>>>   	FN(QDISC_BURST_DROP)		\
>>> -	FN(QDISC_OVERLIMIT)		\
>>> -	FN(QDISC_CONGESTED)		\
>>> -	FN(CAKE_FLOOD)			\
>>> -	FN(FQ_BAND_LIMIT)		\
>>> -	FN(FQ_HORIZON_LIMIT)		\
>>> -	FN(FQ_FLOW_LIMIT)		\
>>>   	FN(CPU_BACKLOG)			\
>>>   	FN(XDP)				\
>>>   	FN(TC_INGRESS)			\
>>> @@ -371,8 +365,10 @@ enum skb_drop_reason {
>>>   	/** @SKB_DROP_REASON_SECURITY_HOOK: dropped due to security HOOK */
>>>   	SKB_DROP_REASON_SECURITY_HOOK,
>>>   	/**
>>> -	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc when packet outputting (
>>> -	 * failed to enqueue to current qdisc)
>>> +	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc during enqueue or
>>> +	 * dequeue. More specific drop reasons are available via the
>>> +	 * qdisc:qdisc_drop tracepoint, which also provides qdisc handle
>>> +	 * and name for identifying the source.
>> 
>> IIUC, this is not needed, see below:
>> 
>> [...]
>> 
>>> @@ -37,6 +37,24 @@
>>>   const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
>>>   EXPORT_SYMBOL(default_qdisc_ops);
>>>   
>>> +void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q,
>>> +			struct netdev_queue *txq,
>>> +			struct net_device *dev)
>>> +{
>>> +	while (unlikely(skb)) {
>>> +		struct sk_buff *next = skb->next;
>>> +		enum qdisc_drop_reason reason = tcf_get_qdisc_drop_reason(skb);
>>> +
>>> +		prefetch(next);
>>> +		/* Catch wrong enum: skb_drop_reason vs qdisc_drop_reason */
>>> +		WARN_ON_ONCE(reason && reason < __QDISC_DROP_REASON);
>>> +		trace_qdisc_drop(q, txq, dev, skb, reason);
>>> +		kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_DROP);
>> 
>> AFAIU, the idea here is that you just pass the same 'reason' value to
>> kfree_skb_reason(). Because of the subsys shift and offset, these will
>> all be unique values, so anyone just watching the old tracepoint will
>> get QDISC_DROP_* reasons with no context, and if you want the context
>> you listen to the qdisc_drop tracepoint.
>
> I'm already changing this code in V3, as syzbot revealed that some
> existing skb_drop_reason's do arrive here, which is the TC filter drop
> reasons (SKB_DROP_REASON_TC_*).  We primarily need subsys encoding as
> we share the SKB->cb area.
>
> This is the new code, that pass 'reason' through:
>
>   /* TC classifier and qdisc share drop_reason storage.
>    * Check subsystem mask to identify qdisc drop reasons,
>    * else pass through skb_drop_reason set by TC classifier.
>    */
>   if ((reason & SKB_DROP_REASON_SUBSYS_MASK) == __QDISC_DROP_REASON) {
>   	trace_qdisc_drop(q, txq, dev, skb, reason);
>   	skb_reason = SKB_DROP_REASON_QDISC_DROP;
>   } else {
>   	skb_reason = (enum skb_drop_reason)reason;
>   }
>   kfree_skb_reason(skb, skb_reason);
>
> I do realize that the reason is now a unique value, that in principle
> could be passed through, *BUT* that will break existing userspace
> tools.  E.g. the `perf trace -e skb:kfree_skb` cannot decode these to
> strings. (The net/core/drop_monitor.c also need special handling.)

Ah, that's a bit unfortunate. I assumed the tools would handle these
correctly automatically :(

> I actually want to give userspace a *single* SKB_DROP_REASON_QDISC_DROP
> reason (that existing tools already knows).
>
> Leaking extra qdisc drop reasons is not helpful to consume as it is not
> actionable without knowing the qdisc. A QDISC_DROP_OVERLIMIT from FQ is
> very different from one in CAKE - knowing just the reason without the
> qdisc type/config is insufficient for debugging. The trace_qdisc_drop
> tracepoint provides both the reason AND the qdisc context together

Depends; if you only have one of those installed on your system it'll do
just fine :)

In any case we're changing things here (removing reasons, or changing
them). I would lean towards having more information available (i.e.,
passing through the reason), but if common tools can't decode them,
that's a bit of a bummer.

I suppose it'll be too much churn to start out with the single reason,
then fix the tools to understand subsystem drop reasons, then change it
again?

-Toke


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing
  2026-02-06 16:31       ` Toke Høiland-Jørgensen
@ 2026-02-09 13:45         ` Jesper Dangaard Brouer
  0 siblings, 0 replies; 14+ messages in thread
From: Jesper Dangaard Brouer @ 2026-02-09 13:45 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, atenart, netdev, Eric Dumazet,
	Paolo Abeni
  Cc: bpf, Jakub Kicinski, horms, jiri, edumazet, xiyou.wangcong, jhs,
	carges, kernel-team, David S. Miller



On 06/02/2026 17.31, Toke Høiland-Jørgensen wrote:
> Jesper Dangaard Brouer <hawk@kernel.org> writes:
> 
>> On 06/02/2026 10.31, Toke Høiland-Jørgensen wrote:
>>> Jesper Dangaard Brouer <hawk@kernel.org> writes:
>>>
>>>> Create new enum qdisc_drop_reason and trace_qdisc_drop tracepoint
>>>> for qdisc layer drop diagnostics with direct qdisc context visibility.
>>>>
>>>> The new tracepoint includes qdisc handle, parent, kind (name), and
>>>> device information. Existing SKB_DROP_REASON_QDISC_DROP is retained
>>>> for backwards compatibility via kfree_skb_reason().
>>>>
>>>> Convert FQ, FQ_CoDel, CoDel, SFB, and pfifo_fast to use the new
>>>> infrastructure.
>>>>
>>>> Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
>> [...]
>>>> diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
>>>> index a7b7abd66e21..3d8d284e05c8 100644
>>>> --- a/include/net/dropreason-core.h
>>>> +++ b/include/net/dropreason-core.h
>>>> @@ -68,12 +68,6 @@
>>>>    	FN(SECURITY_HOOK)		\
>>>>    	FN(QDISC_DROP)			\
>>>>    	FN(QDISC_BURST_DROP)		\
>>>> -	FN(QDISC_OVERLIMIT)		\
>>>> -	FN(QDISC_CONGESTED)		\
>>>> -	FN(CAKE_FLOOD)			\
>>>> -	FN(FQ_BAND_LIMIT)		\
>>>> -	FN(FQ_HORIZON_LIMIT)		\
>>>> -	FN(FQ_FLOW_LIMIT)		\
>>>>    	FN(CPU_BACKLOG)			\
>>>>    	FN(XDP)				\
>>>>    	FN(TC_INGRESS)			\
>>>> @@ -371,8 +365,10 @@ enum skb_drop_reason {
>>>>    	/** @SKB_DROP_REASON_SECURITY_HOOK: dropped due to security HOOK */
>>>>    	SKB_DROP_REASON_SECURITY_HOOK,
>>>>    	/**
>>>> -	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc when packet outputting (
>>>> -	 * failed to enqueue to current qdisc)
>>>> +	 * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc during enqueue or
>>>> +	 * dequeue. More specific drop reasons are available via the
>>>> +	 * qdisc:qdisc_drop tracepoint, which also provides qdisc handle
>>>> +	 * and name for identifying the source.
>>>
>>> IIUC, this is not needed, see below:
>>>
>>> [...]
>>>
>>>> @@ -37,6 +37,24 @@
>>>>    const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
>>>>    EXPORT_SYMBOL(default_qdisc_ops);
>>>>    
>>>> +void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q,
>>>> +			struct netdev_queue *txq,
>>>> +			struct net_device *dev)
>>>> +{
>>>> +	while (unlikely(skb)) {
>>>> +		struct sk_buff *next = skb->next;
>>>> +		enum qdisc_drop_reason reason = tcf_get_qdisc_drop_reason(skb);
>>>> +
>>>> +		prefetch(next);
>>>> +		/* Catch wrong enum: skb_drop_reason vs qdisc_drop_reason */
>>>> +		WARN_ON_ONCE(reason && reason < __QDISC_DROP_REASON);
>>>> +		trace_qdisc_drop(q, txq, dev, skb, reason);
>>>> +		kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_DROP);
>>>
>>> AFAIU, the idea here is that you just pass the same 'reason' value to
>>> kfree_skb_reason(). Because of the subsys shift and offset, these will
>>> all be unique values, so anyone just watching the old tracepoint will
>>> get QDISC_DROP_* reasons with no context, and if you want the context
>>> you listen to the qdisc_drop tracepoint.
>>
>> I'm already changing this code in V3, as syzbot revealed that some
>> existing skb_drop_reason's do arrive here, which is the TC filter drop
>> reasons (SKB_DROP_REASON_TC_*).  We primarily need subsys encoding as
>> we share the SKB->cb area.
>>
>> This is the new code, that pass 'reason' through:
>>
>>    /* TC classifier and qdisc share drop_reason storage.
>>     * Check subsystem mask to identify qdisc drop reasons,
>>     * else pass through skb_drop_reason set by TC classifier.
>>     */
>>    if ((reason & SKB_DROP_REASON_SUBSYS_MASK) == __QDISC_DROP_REASON) {
>>    	trace_qdisc_drop(q, txq, dev, skb, reason);
>>    	skb_reason = SKB_DROP_REASON_QDISC_DROP;
>>    } else {
>>    	skb_reason = (enum skb_drop_reason)reason;
>>    }
>>    kfree_skb_reason(skb, skb_reason);
>>
>> I do realize that the reason is now a unique value, that in principle
>> could be passed through, *BUT* that will break existing userspace
>> tools.  E.g. the `perf trace -e skb:kfree_skb` cannot decode these to
>> strings. (The net/core/drop_monitor.c also need special handling.)
> 
> Ah, that's a bit unfortunate. I assumed the tools would handle these
> correctly automatically :(
> 

I've sent a [v3] with this code change:
  [v3] 
https://lore.kernel.org/all/177039500964.2258217.2989656069254156812.stgit@firesoul/

>> I actually want to give userspace a *single* SKB_DROP_REASON_QDISC_DROP
>> reason (that existing tools already knows).
>>
>> Leaking extra qdisc drop reasons is not helpful to consume as it is not
>> actionable without knowing the qdisc. A QDISC_DROP_OVERLIMIT from FQ is
>> very different from one in CAKE - knowing just the reason without the
>> qdisc type/config is insufficient for debugging. The trace_qdisc_drop
>> tracepoint provides both the reason AND the qdisc context together
> 
> Depends; if you only have one of those installed on your system it'll do
> just fine :)
> 
> In any case we're changing things here (removing reasons, or changing
> them). I would lean towards having more information available (i.e.,
> passing through the reason), but if common tools can't decode them,
> that's a bit of a bummer.
> 
> I suppose it'll be too much churn to start out with the single reason,
> then fix the tools to understand subsystem drop reasons, then change it
> again?

IMHO it makes sense to merge this patchset, and then we can work on
adding support on tools to understand subsystem drop reasons. (After
which we can let these subsystem drop reasons fall-through.)

If I let "reason" fall-through (in above code) this "perf script" shows
this (0x30004) when listening to the current skb:kfree_skb tracepoint:

  skb:kfree_skb: skbaddr=0xffff8a9a54864ee8 rx_sk=(nil) protocol=2048 
location=tcf_kfree_skb_list+0x53 reason: 0x30004

The new qdisc tracepoint gets decodes (same event) like this:

  qdisc:qdisc_drop: drop ifindex=8 kind=sfq handle=0x10000 
parent=0xFFFFFFFF skbaddr=0xffff8a9a5f751ae8 reason=FLOW_LIMIT


--Jesper






^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-02-09 13:46 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-05 21:21 [PATCH net-next v2 0/6] net: sched: refactor qdisc drop reasons into dedicated tracepoint Jesper Dangaard Brouer
2026-02-05 21:21 ` [PATCH net-next v2 1/6] net: sched: introduce qdisc-specific drop reason tracing Jesper Dangaard Brouer
2026-02-06  9:31   ` Toke Høiland-Jørgensen
2026-02-06 14:14     ` Jesper Dangaard Brouer
2026-02-06 16:31       ` Toke Høiland-Jørgensen
2026-02-09 13:45         ` Jesper Dangaard Brouer
2026-02-05 21:21 ` [PATCH net-next v2 2/6] net: sched: sfq: convert to qdisc drop reasons Jesper Dangaard Brouer
2026-02-05 21:21 ` [PATCH net-next v2 3/6] net: sched: sch_cake: use enum qdisc_drop_reason for cobalt_should_drop Jesper Dangaard Brouer
2026-02-05 21:21 ` [PATCH net-next v2 4/6] net: sched: rename QDISC_DROP_CAKE_FLOOD to QDISC_DROP_FLOOD_PROTECTION Jesper Dangaard Brouer
2026-02-05 21:21 ` [PATCH net-next v2 5/6] net: sched: rename QDISC_DROP_FQ_* to generic names Jesper Dangaard Brouer
2026-02-05 21:22 ` [PATCH net-next v2 6/6] net: sched: sch_dualpi2: use qdisc_dequeue_drop() for dequeue drops Jesper Dangaard Brouer
2026-02-06  4:09   ` kernel test robot
2026-02-06  4:50   ` kernel test robot
2026-02-06  8:32 ` [syzbot ci] Re: net: sched: refactor qdisc drop reasons into dedicated tracepoint syzbot ci

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox