From: Stephen Hemminger <stephen@networkplumber.org>
To: netdev@vger.kernel.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
Jamal Hadi Salim <jhs@mojatatu.com>,
Jiri Pirko <jiri@resnulli.us>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
linux-kernel@vger.kernel.org (open list)
Subject: [PATCH net-next 4/5] net/sched: netem: add per-impairment extended statistics
Date: Fri, 3 Apr 2026 15:52:09 -0700 [thread overview]
Message-ID: <20260403225324.476787-5-stephen@networkplumber.org> (raw)
In-Reply-To: <20260403225324.476787-1-stephen@networkplumber.org>
netem applies several impairments (delay, loss, corruption, duplication,
reordering) but exposes no counters distinguishing which impairment
affected a given packet.
Add a struct tc_netem_xstats reported via TCA_STATS_APP so that
userspace (tc -s qdisc show) can display per-impairment counters.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
include/uapi/linux/pkt_sched.h | 9 +++++++++
net/sched/sch_netem.c | 27 ++++++++++++++++++++++++---
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 66e8072f44df..fada10cb9b7b 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -569,6 +569,15 @@ struct tc_netem_gemodel {
#define NETEM_DIST_SCALE 8192
#define NETEM_DIST_MAX 16384
+struct tc_netem_xstats {
+ __u32 delayed; /* packets delayed */
+ __u32 dropped; /* packets dropped by loss model */
+ __u32 corrupted; /* packets with bit errors injected */
+ __u32 duplicated; /* duplicate packets generated */
+ __u32 reordered; /* packets sent out of order */
+ __u32 ecn_marked; /* packets ECN CE-marked (not dropped)*/
+};
+
/* DRR */
enum {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 76af9bd3ecaa..6dc1ba8e999b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -152,6 +152,9 @@ struct netem_sched_data {
} slot;
struct disttable *slot_dist;
+
+ /* Per-impairment counters */
+ struct tc_netem_xstats xstats;
};
/* Time stamp put into socket buffer control block
@@ -459,17 +462,22 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
skb->prev = NULL;
/* Random duplication */
- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor, &q->prng))
+ if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor, &q->prng)) {
++count;
+ q->xstats.duplicated++;
+ }
/* Drop packet? */
if (loss_event(q)) {
- if (q->ecn && INET_ECN_set_ce(skb))
+ if (q->ecn && INET_ECN_set_ce(skb)) {
qdisc_qstats_drop(sch); /* mark packet */
- else
+ q->xstats.ecn_marked++;
+ } else {
--count;
+ }
}
if (count == 0) {
+ q->xstats.dropped++;
qdisc_qstats_drop(sch);
__qdisc_drop(skb, to_free);
return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
@@ -520,6 +528,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (skb_headlen(skb))
skb->data[get_random_u32_below(skb_headlen(skb))] ^=
1 << get_random_u32_below(8);
+ q->xstats.corrupted++;
}
if (unlikely(q->t_len >= sch->limit)) {
@@ -598,6 +607,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
delay += packet_time_ns(qdisc_pkt_len(skb), q);
}
+ if (delay > 0)
+ q->xstats.delayed++;
+
cb->time_to_send = now + delay;
++q->counter;
tfifo_enqueue(skb, sch);
@@ -610,6 +622,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
q->counter = 0;
__qdisc_enqueue_head(skb, &sch->q);
+ q->xstats.reordered++;
sch->qstats.requeues++;
}
@@ -1296,6 +1309,13 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
return -1;
}
+static int netem_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+ struct netem_sched_data *q = qdisc_priv(sch);
+
+ return gnet_stats_copy_app(d, &q->xstats, sizeof(q->xstats));
+}
+
static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
struct sk_buff *skb, struct tcmsg *tcm)
{
@@ -1358,6 +1378,7 @@ static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
.destroy = netem_destroy,
.change = netem_change,
.dump = netem_dump,
+ .dump_stats = netem_dump_stats,
.owner = THIS_MODULE,
};
MODULE_ALIAS_NET_SCH("netem");
--
2.53.0
next prev parent reply other threads:[~2026-04-03 22:53 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-03 22:52 [PATCH net-next 0/5] net/sched: netem: cleanups and improvements Stephen Hemminger
2026-04-03 22:52 ` [PATCH net-next 1/5] net/sched: netem: replace pr_info with netlink extack error messages Stephen Hemminger
2026-04-03 22:52 ` [PATCH net-next 2/5] net/sched: netem: remove unused loss model fields Stephen Hemminger
2026-04-03 22:52 ` [PATCH net-next 3/5] net/sched: netem: remove useless VERSION Stephen Hemminger
2026-04-03 22:52 ` Stephen Hemminger [this message]
2026-04-09 9:30 ` [PATCH net-next 4/5] net/sched: netem: add per-impairment extended statistics Paolo Abeni
2026-04-11 5:08 ` Stephen Hemminger
2026-04-03 22:52 ` [PATCH net-next 5/5] net/sched: netem: handle multi-segment skb in corruption Stephen Hemminger
2026-04-08 17:10 ` [PATCH net-next 0/5] net/sched: netem: cleanups and improvements Simon Horman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260403225324.476787-5-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jhs@mojatatu.com \
--cc=jiri@resnulli.us \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.