[<prev] [next>] [day] [month] [year] [list]
Message-ID: <176917072608.1186611.11185920960590396939.stgit@firesoul>
Date: Fri, 23 Jan 2026 13:18:46 +0100
From: Jesper Dangaard Brouer <hawk@...nel.org>
To: netdev@...r.kernel.org, Eric Dumazet <eric.dumazet@...il.com>,
"David S. Miller" <davem@...emloft.net>, Paolo Abeni <pabeni@...hat.com>
Cc: Jesper Dangaard Brouer <hawk@...nel.org>, bpf@...r.kernel.org,
Jakub Kicinski <kuba@...nel.org>,
Toke Høiland-Jørgensen <toke@...e.dk>,
horms@...nel.org, jiri@...nulli.us, edumazet@...gle.com,
xiyou.wangcong@...il.com, jhs@...atatu.com, carges@...udflare.com,
kernel-team@...udflare.com
Subject: [PATCH net-next v3] net: sched: sfq: add detailed drop reasons for
monitoring
Add specific drop reasons to SFQ qdisc to improve packet drop
observability and monitoring capabilities. This change replaces
generic qdisc_drop() calls with qdisc_drop_reason() to provide
granular metrics about different drop scenarios in production
environments.
Two new drop reasons are introduced:
- SKB_DROP_REASON_QDISC_SFQ_MAXFLOWS: Used when a new flow cannot
be created because the maximum number of flows (flows parameter)
has been reached and no free flow slots are available.
- SKB_DROP_REASON_QDISC_SFQ_MAXDEPTH: Used when a flow's queue
length exceeds the per-flow depth limit (depth parameter),
triggering either tail drop or head drop depending on headdrop
configuration.
The existing SKB_DROP_REASON_QDISC_OVERLIMIT is used in sfq_drop()
when the overall qdisc limit is exceeded and packets are dropped
from the longest queue.
The naming uses qdisc-specific drop reasons tied to SFQ tunables,
following the pattern established by Eric's FQ commit 5765c7f6e317
("net_sched: sch_fq: add three drop_reason") which introduced
FQ_BAND_LIMIT, FQ_HORIZON_LIMIT, and FQ_FLOW_LIMIT.
The new drop reasons are inserted in the middle of the enum after
SKB_DROP_REASON_QDISC_CONGESTED to group all qdisc-related reasons
together. While drop reason enum values are not UAPI, the enum
names implicitly become UAPI as userspace tools rely on BTF to
resolve names to values. This makes middle-insertion safe as long
as names remain stable.
These detailed drop reasons enable production monitoring systems
to distinguish between different SFQ drop scenarios and generate
specific metrics for:
- Flow table exhaustion (flows exceeded)
- Per-flow congestion (depth limit exceeded)
- Global qdisc congestion (overall limit exceeded)
This granular visibility allows operators to identify capacity
planning needs, detect traffic patterns, and optimize SFQ
configuration based on real-world drop patterns.
Signed-off-by: Jesper Dangaard Brouer <hawk@...nel.org>
---
v3:
- Removed SFQ_DR() macro per upstream feedback
- Use full drop reason names (SKB_DROP_REASON_QDISC_SFQ_*) for easier grepping
- Split long lines to stay under 80 characters
v2:
- Changed to hierarchical naming: QDISC_SFQ_MAXFLOWS and QDISC_SFQ_MAXDEPTH
- Added QDISC_ prefix for pattern matching across qdisc subsystems
- Added rationale paragraph explaining userspace monitoring benefits
v1:
- Initial submission with QDISC_MAXFLOWS and QDISC_MAXDEPTH
---
include/net/dropreason-core.h | 12 ++++++++++++
net/sched/sch_sfq.c | 11 +++++++----
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index a7b7abd66e21..92c99169bb97 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -70,6 +70,8 @@
FN(QDISC_BURST_DROP) \
FN(QDISC_OVERLIMIT) \
FN(QDISC_CONGESTED) \
+ FN(QDISC_SFQ_MAXFLOWS) \
+ FN(QDISC_SFQ_MAXDEPTH) \
FN(CAKE_FLOOD) \
FN(FQ_BAND_LIMIT) \
FN(FQ_HORIZON_LIMIT) \
@@ -390,6 +392,16 @@ enum skb_drop_reason {
* due to congestion.
*/
SKB_DROP_REASON_QDISC_CONGESTED,
+ /**
+ * @SKB_DROP_REASON_QDISC_SFQ_MAXFLOWS: dropped by SFQ qdisc when the
+ * maximum number of flows is exceeded.
+ */
+ SKB_DROP_REASON_QDISC_SFQ_MAXFLOWS,
+ /**
+ * @SKB_DROP_REASON_QDISC_SFQ_MAXDEPTH: dropped by SFQ qdisc when a flow
+ * exceeds its maximum queue depth limit.
+ */
+ SKB_DROP_REASON_QDISC_SFQ_MAXDEPTH,
/**
* @SKB_DROP_REASON_CAKE_FLOOD: dropped by the flood protection part of
* CAKE qdisc AQM algorithm (BLUE).
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 96eb2f122973..ecc1028bdac8 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, SKB_DROP_REASON_QDISC_OVERLIMIT);
return len;
}
@@ -363,7 +363,8 @@ 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,
+ SKB_DROP_REASON_QDISC_SFQ_MAXFLOWS);
q->ht[hash] = x;
slot = &q->slots[x];
slot->hash = hash;
@@ -420,14 +421,16 @@ 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,
+ SKB_DROP_REASON_QDISC_SFQ_MAXDEPTH);
/* 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,
+ SKB_DROP_REASON_QDISC_SFQ_MAXDEPTH);
slot_queue_add(slot, skb);
qdisc_tree_reduce_backlog(sch, 0, delta);
Powered by blists - more mailing lists