* [PATCH net v2 00/10] netem: fixes and selftests
@ 2026-03-15 0:14 Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 01/10] Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree" Stephen Hemminger
` (10 more replies)
0 siblings, 11 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
The check_netem_in_tree() restriction added for CVE-2024-45016 rejects
valid configurations such as HTB or HFSC trees with netem on multiple
branches -- including examples from the netem documentation itself.
This has been an open issue for over a year (kernel.org bug #220774).
This series replaces it with a per-CPU recursion guard, restructures
dequeue to fix the HFSC eltree corruption, and addresses several
additional bugs found during a code audit.
01/10 Revert check_netem_in_tree()
02/10 Per-CPU recursion guard for duplication
03/10 Update tdc tests for the revert
04/10 Restructure dequeue to fix HFSC re-entrancy
(CVE-2025-37890, CVE-2025-38001)
05/10 Fix probability gaps in 4-state loss model
06/10 Fix slot delay overflow for ranges > 2.1s
07/10 Include reordered packets in queue limit check
08/10 Null-terminate tfifo linear queue tail
09/10 Only reseed PRNG when explicitly provided
10/10 Add netem configuration and traffic tests
Tested with tdc on 7.0.0-rc3: all netem tests pass.
v2 - merge new tests into tc-testing
- fixes only in this patch series
Stephen Hemminger (10):
Revert "net/sched: Restrict conditions for adding duplicating netems
to qdisc tree"
net/sched: netem: add per-CPU recursion guard for duplication
selftests/tc-testing: update netem tests after check_netem_in_tree
revert
net/sched: netem: restructure dequeue to avoid re-entrancy with child
qdisc
net/sched: netem: fix probability gaps in 4-state loss model
net/sched: netem: fix slot delay calculation overflow
net/sched: netem: fix queue limit check to include reordered packets
net/sched: netem: null-terminate tfifo linear queue tail
net/sched: netem: only reseed PRNG when seed is explicitly provided
selftests/tc-testing: add netem configuration and traffic tests
net/sched/sch_netem.c | 164 ++---
.../tc-testing/tc-tests/qdiscs/netem.json | 610 +++++++++++++++++-
2 files changed, 689 insertions(+), 85 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net v2 01/10] Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree"
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 02/10] net/sched: netem: add per-CPU recursion guard for duplication Stephen Hemminger
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Ji-Soo Chung, Gerlinde, stable, Cong Wang
This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
The restriction breaks valid uses of netem such as using different
netem values on different branches of HTB. This even broke some
of the examples in the netem documentation.
The intent of blocking recursion is handled in next patch.
Fixes: ec8e0e3d7adef ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
Reported-by: Ji-Soo Chung <jschung2@proton.me>
Reported-by: Gerlinde <lrGerlinde@mailfence.com>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=220774
Cc: stable@vger.kernel.org
Originally-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 40 ----------------------------------------
1 file changed, 40 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5de1c932944a..0ccf74a9cb82 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -974,41 +974,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
return 0;
}
-static const struct Qdisc_class_ops netem_class_ops;
-
-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
- struct netlink_ext_ack *extack)
-{
- struct Qdisc *root, *q;
- unsigned int i;
-
- root = qdisc_root_sleeping(sch);
-
- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
- if (duplicates ||
- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
- goto err;
- }
-
- if (!qdisc_dev(root))
- return 0;
-
- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
- if (duplicates ||
- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
- goto err;
- }
- }
-
- return 0;
-
-err:
- NL_SET_ERR_MSG(extack,
- "netem: cannot mix duplicating netems with other netems in tree");
- return -EINVAL;
-}
-
/* Parse netlink message to set options */
static int netem_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
@@ -1067,11 +1032,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
q->gap = qopt->gap;
q->counter = 0;
q->loss = qopt->loss;
-
- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
- if (ret)
- goto unlock;
-
q->duplicate = qopt->duplicate;
/* for compatibility with earlier versions.
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 02/10] net/sched: netem: add per-CPU recursion guard for duplication
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 01/10] Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree" Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 03/10] selftests/tc-testing: update netem tests after check_netem_in_tree revert Stephen Hemminger
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, stable, William Liu, Savino Dicanosa
Add a per-CPU recursion depth counter to netem_enqueue(). When netem
duplicates a packet, the clone is re-enqueued at the root qdisc. If
the tree contains other netem instances, this can recurse without
bound, causing soft lockups and OOM.
This approach was previously considered but rejected on the grounds
that netem_dequeue calling enqueue on a child netem could bypass the
depth check. That concern does not apply: the child netem's
netem_enqueue() increments the same per-CPU counter, so the total
nesting depth across all netem instances in the call chain is tracked
correctly.
A depth limit of 4 is generous for any legitimate configuration.
Fixes: 0afb51e72855 ("[PKT_SCHED]: netem: reinsert for duplication")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=220774
Cc: stable@vger.kernel.org
Reported-by: William Liu <will@willsroot.io>
Reported-by: Savino Dicanosa <savy@syst3mfailure.io>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 0ccf74a9cb82..085fa3ad6f83 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -21,6 +21,7 @@
#include <linux/rtnetlink.h>
#include <linux/reciprocal_div.h>
#include <linux/rbtree.h>
+#include <linux/percpu.h>
#include <net/gso.h>
#include <net/netlink.h>
@@ -29,6 +30,15 @@
#define VERSION "1.3"
+/*
+ * Limit for recursion from duplication.
+ * Duplicated packets are re-enqueued at the root qdisc, which may
+ * reach this or another netem instance, causing nested calls to
+ * netem_enqueue(). This per-CPU counter limits the total depth.
+ */
+static DEFINE_PER_CPU(unsigned int, netem_enqueue_depth);
+#define NETEM_RECURSION_LIMIT 4
+
/* Network Emulation Queuing algorithm.
====================================
@@ -460,6 +470,14 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* Do not fool qdisc_drop_all() */
skb->prev = NULL;
+ /* Guard against recursion from duplication re-injection. */
+ if (unlikely(this_cpu_inc_return(netem_enqueue_depth) >
+ NETEM_RECURSION_LIMIT)) {
+ this_cpu_dec(netem_enqueue_depth);
+ qdisc_drop(skb, sch, to_free);
+ return NET_XMIT_DROP;
+ }
+
/* Random duplication */
if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor, &q->prng))
++count;
@@ -474,6 +492,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (count == 0) {
qdisc_qstats_drop(sch);
__qdisc_drop(skb, to_free);
+ this_cpu_dec(netem_enqueue_depth);
return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
}
@@ -529,6 +548,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
qdisc_drop_all(skb, sch, to_free);
if (skb2)
__qdisc_drop(skb2, to_free);
+ this_cpu_dec(netem_enqueue_depth);
return NET_XMIT_DROP;
}
@@ -643,8 +663,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* Parent qdiscs accounted for 1 skb of size @prev_len */
qdisc_tree_reduce_backlog(sch, -(nb - 1), -(len - prev_len));
} else if (!skb) {
+ this_cpu_dec(netem_enqueue_depth);
return NET_XMIT_DROP;
}
+ this_cpu_dec(netem_enqueue_depth);
return NET_XMIT_SUCCESS;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 03/10] selftests/tc-testing: update netem tests after check_netem_in_tree revert
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 01/10] Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree" Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 02/10] net/sched: netem: add per-CPU recursion guard for duplication Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 04/10] net/sched: netem: restructure dequeue to avoid re-entrancy with child qdisc Stephen Hemminger
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, stable
Update four tdc tests (d34d, b33f, cafe, 1337) to reflect that
nested/sibling netem configurations are no longer rejected.
Adjust expected exit codes and match counts accordingly.
Fixes: ecdec65ec78d ("selftests/tc-testing: Add tests for restrictions on netem duplication")
Cc: stable@kernel.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
.../tc-testing/tc-tests/qdiscs/netem.json | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json
index 718d2df2aafa..7985b5215853 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json
@@ -339,7 +339,7 @@
},
{
"id": "d34d",
- "name": "NETEM test qdisc duplication restriction in qdisc tree in netem_change root",
+ "name": "NETEM allow duplication with nested netem via change",
"category": ["qdisc", "netem"],
"plugins": {
"requires": "nsPlugin"
@@ -349,7 +349,7 @@
"$TC qdisc add dev $DUMMY parent 1: handle 2: netem limit 1"
],
"cmdUnderTest": "$TC qdisc change dev $DUMMY handle 1: netem duplicate 50%",
- "expExitCode": "2",
+ "expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "qdisc netem",
"matchCount": "2",
@@ -359,7 +359,7 @@
},
{
"id": "b33f",
- "name": "NETEM test qdisc duplication restriction in qdisc tree in netem_change non-root",
+ "name": "NETEM allow duplication on child netem via change",
"category": ["qdisc", "netem"],
"plugins": {
"requires": "nsPlugin"
@@ -369,7 +369,7 @@
"$TC qdisc add dev $DUMMY parent 1: handle 2: netem limit 1"
],
"cmdUnderTest": "$TC qdisc change dev $DUMMY handle 2: netem duplicate 50%",
- "expExitCode": "2",
+ "expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "qdisc netem",
"matchCount": "2",
@@ -379,7 +379,7 @@
},
{
"id": "cafe",
- "name": "NETEM test qdisc duplication restriction in qdisc tree",
+ "name": "NETEM allow adding child netem when parent duplicates",
"category": ["qdisc", "netem"],
"plugins": {
"requires": "nsPlugin"
@@ -388,17 +388,17 @@
"$TC qdisc add dev $DUMMY root handle 1: netem limit 1 duplicate 100%"
],
"cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1: handle 2: netem duplicate 100%",
- "expExitCode": "2",
+ "expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "qdisc netem",
- "matchCount": "1",
+ "matchCount": "2",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1:0 root"
]
},
{
"id": "1337",
- "name": "NETEM test qdisc duplication restriction in qdisc tree across branches",
+ "name": "NETEM allow duplicating netem on separate HFSC branches",
"category": ["qdisc", "netem"],
"plugins": {
"requires": "nsPlugin"
@@ -410,10 +410,10 @@
"$TC class add dev $DUMMY parent 1:0 classid 1:2 hfsc rt m2 10Mbit"
],
"cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:2 handle 3:0 netem duplicate 100%",
- "expExitCode": "2",
+ "expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "qdisc netem",
- "matchCount": "1",
+ "matchCount": "2",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1:0 root"
]
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 04/10] net/sched: netem: restructure dequeue to avoid re-entrancy with child qdisc
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (2 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 03/10] selftests/tc-testing: update netem tests after check_netem_in_tree revert Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 05/10] net/sched: netem: fix probability gaps in 4-state loss model Stephen Hemminger
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, stable
netem_dequeue() currently enqueues time-ready packets into the child
qdisc during the dequeue call path. This creates several problems:
1. Parent qdiscs like HFSC track class active/inactive state based on
qlen transitions. The child enqueue during netem's dequeue can cause
qlen to increase while the parent is mid-dequeue, leading to
double-insertion in HFSC's eltree (CVE-2025-37890, CVE-2025-38001).
2. If the child qdisc is non-work-conserving (e.g., TBF), it may refuse
to release packets during its dequeue even though they were just
enqueued. The parent then sees netem returning NULL despite having
backlog, violating the work-conserving contract and causing stalls
with parents like DRR that deactivate classes in this case.
Restructure netem_dequeue so that when a child qdisc is present, all
time-ready packets are transferred from the tfifo to the child in a
batch before asking the child for output. This ensures the child only
receives packets whose delay has already elapsed. The no-child path
(tfifo direct dequeue) is unchanged.
Fixes: 50612537e9ab ("netem: fix classful handling")
Cc: stable@vger.kernel.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 79 +++++++++++++++++++++++++++++--------------
1 file changed, 54 insertions(+), 25 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 085fa3ad6f83..7488ff9f2933 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -726,7 +726,6 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
struct netem_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
-tfifo_dequeue:
skb = __qdisc_dequeue_head(&sch->q);
if (skb) {
deliver:
@@ -734,24 +733,28 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
qdisc_bstats_update(sch, skb);
return skb;
}
- skb = netem_peek(q);
- if (skb) {
- u64 time_to_send;
+
+ /* If we have a child qdisc, transfer all time-ready packets
+ * from the tfifo into the child, then dequeue from the child.
+ * This avoids enqueueing into the child during the parent's
+ * dequeue callback, which can confuse parents that track
+ * active/inactive state based on qlen transitions (HFSC).
+ */
+ if (q->qdisc) {
u64 now = ktime_get_ns();
- /* if more time remaining? */
- time_to_send = netem_skb_cb(skb)->time_to_send;
- if (q->slot.slot_next && q->slot.slot_next < time_to_send)
- get_slot_next(q, now);
+ while ((skb = netem_peek(q)) != NULL) {
+ u64 t = netem_skb_cb(skb)->time_to_send;
+
+ if (t > now)
+ break;
+ if (q->slot.slot_next && q->slot.slot_next > now)
+ break;
- if (time_to_send <= now && q->slot.slot_next <= now) {
netem_erase_head(q, skb);
q->t_len--;
skb->next = NULL;
skb->prev = NULL;
- /* skb->dev shares skb->rbnode area,
- * we need to restore its value.
- */
skb->dev = qdisc_dev(sch);
if (q->slot.slot_next) {
@@ -762,7 +765,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
get_slot_next(q, now);
}
- if (q->qdisc) {
+ {
unsigned int pkt_len = qdisc_pkt_len(skb);
struct sk_buff *to_free = NULL;
int err;
@@ -776,32 +779,58 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
sch->q.qlen--;
qdisc_tree_reduce_backlog(sch, 1, pkt_len);
}
- goto tfifo_dequeue;
}
+ }
+
+ skb = q->qdisc->ops->dequeue(q->qdisc);
+ if (skb) {
sch->q.qlen--;
goto deliver;
}
-
- if (q->qdisc) {
- skb = q->qdisc->ops->dequeue(q->qdisc);
- if (skb) {
+ } else {
+ /* No child qdisc: dequeue directly from tfifo */
+ skb = netem_peek(q);
+ if (skb) {
+ u64 time_to_send;
+ u64 now = ktime_get_ns();
+
+ time_to_send = netem_skb_cb(skb)->time_to_send;
+ if (q->slot.slot_next &&
+ q->slot.slot_next < time_to_send)
+ get_slot_next(q, now);
+
+ if (time_to_send <= now &&
+ q->slot.slot_next <= now) {
+ netem_erase_head(q, skb);
+ q->t_len--;
+ skb->next = NULL;
+ skb->prev = NULL;
+ skb->dev = qdisc_dev(sch);
+
+ if (q->slot.slot_next) {
+ q->slot.packets_left--;
+ q->slot.bytes_left -=
+ qdisc_pkt_len(skb);
+ if (q->slot.packets_left <= 0 ||
+ q->slot.bytes_left <= 0)
+ get_slot_next(q, now);
+ }
sch->q.qlen--;
goto deliver;
}
}
+ }
+
+ /* Schedule watchdog for next time-ready packet */
+ skb = netem_peek(q);
+ if (skb) {
+ u64 time_to_send = netem_skb_cb(skb)->time_to_send;
qdisc_watchdog_schedule_ns(&q->watchdog,
max(time_to_send,
q->slot.slot_next));
}
- if (q->qdisc) {
- skb = q->qdisc->ops->dequeue(q->qdisc);
- if (skb) {
- sch->q.qlen--;
- goto deliver;
- }
- }
return NULL;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 05/10] net/sched: netem: fix probability gaps in 4-state loss model
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (3 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 04/10] net/sched: netem: restructure dequeue to avoid re-entrancy with child qdisc Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 06/10] net/sched: netem: fix slot delay calculation overflow Stephen Hemminger
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
The 4-state Markov chain in loss_4state() has gaps at the boundaries
between transition probability ranges. The comparisons use:
if (rnd < a4)
else if (a4 < rnd && rnd < a1 + a4)
When rnd equals a boundary value exactly, neither branch matches and
no state transition occurs. The redundant lower-bound check (a4 < rnd)
is already implied by being in the else branch.
Remove the unnecessary lower-bound comparisons so the ranges are
contiguous and every random value produces a transition, matching
the GI (General and Intuitive) loss model specification.
This bug goes back to original implementation of this model.
Fixes: 661b79725fea ("netem: revised correlated loss generator")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 7488ff9f2933..3b2211fc03df 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -237,7 +237,7 @@ static bool loss_4state(struct netem_sched_data *q)
if (rnd < clg->a4) {
clg->state = LOST_IN_GAP_PERIOD;
return true;
- } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
+ } else if (rnd < clg->a1 + clg->a4) {
clg->state = LOST_IN_BURST_PERIOD;
return true;
} else if (clg->a1 + clg->a4 < rnd) {
@@ -257,7 +257,7 @@ static bool loss_4state(struct netem_sched_data *q)
case LOST_IN_BURST_PERIOD:
if (rnd < clg->a3)
clg->state = TX_IN_BURST_PERIOD;
- else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
+ else if (rnd < clg->a2 + clg->a3) {
clg->state = TX_IN_GAP_PERIOD;
} else if (clg->a2 + clg->a3 < rnd) {
clg->state = LOST_IN_BURST_PERIOD;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 06/10] net/sched: netem: fix slot delay calculation overflow
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (4 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 05/10] net/sched: netem: fix probability gaps in 4-state loss model Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 07/10] net/sched: netem: fix queue limit check to include reordered packets Stephen Hemminger
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
get_slot_next() computes a random delay between min_delay and
max_delay using:
get_random_u32() * (max_delay - min_delay) >> 32
This overflows signed 64-bit arithmetic when the delay range exceeds
approximately 2.1 seconds (2^31 nanoseconds), producing a negative
result that effectively disables slot-based pacing. This is a
realistic configuration for WAN emulation (e.g., slot 1s 5s).
Use mul_u64_u32_shr() which handles the widening multiply without
overflow.
Fixes: 0a9fe5c375b5 ("netem: slotting with non-uniform distribution")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3b2211fc03df..aa0d578b5f0e 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -21,6 +21,7 @@
#include <linux/rtnetlink.h>
#include <linux/reciprocal_div.h>
#include <linux/rbtree.h>
+#include <linux/math64.h>
#include <linux/percpu.h>
#include <net/gso.h>
@@ -680,9 +681,8 @@ static void get_slot_next(struct netem_sched_data *q, u64 now)
if (!q->slot_dist)
next_delay = q->slot_config.min_delay +
- (get_random_u32() *
- (q->slot_config.max_delay -
- q->slot_config.min_delay) >> 32);
+ mul_u64_u32_shr(q->slot_config.max_delay - q->slot_config.min_delay,
+ get_random_u32(), 32);
else
next_delay = tabledist(q->slot_config.dist_delay,
(s32)(q->slot_config.dist_jitter),
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 07/10] net/sched: netem: fix queue limit check to include reordered packets
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (5 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 06/10] net/sched: netem: fix slot delay calculation overflow Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 08/10] net/sched: netem: null-terminate tfifo linear queue tail Stephen Hemminger
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
The queue limit check in netem_enqueue() uses q->t_len which only
counts packets in the internal tfifo. Packets placed in sch->q by
the reorder path (__qdisc_enqueue_head) are not counted, allowing
the total queue occupancy to exceed sch->limit under reordering.
Include sch->q.qlen in the limit check.
Fixes: 50612537e9ab ("netem: fix classful handling")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index aa0d578b5f0e..6a91693bd89b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -543,7 +543,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
1<<get_random_u32_below(8);
}
- if (unlikely(q->t_len >= sch->limit)) {
+ if (unlikely(sch->q.qlen >= sch->limit)) {
/* re-link segs, so that qdisc_drop_all() frees them all */
skb->next = segs;
qdisc_drop_all(skb, sch, to_free);
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 08/10] net/sched: netem: null-terminate tfifo linear queue tail
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (6 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 07/10] net/sched: netem: fix queue limit check to include reordered packets Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 09/10] net/sched: netem: only reseed PRNG when seed is explicitly provided Stephen Hemminger
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
When tfifo_enqueue() appends a packet to the linear queue tail,
nskb->next is never set to NULL. The list terminates correctly
only by accident if the skb arrived with next already NULL.
Explicitly null-terminate the tail to prevent list corruption.
Fixes: d66280b12bd7 ("net: netem: use a list in addition to rbtree")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 6a91693bd89b..3bed25f494d3 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -409,6 +409,7 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
q->t_tail->next = nskb;
else
q->t_head = nskb;
+ nskb->next = NULL;
q->t_tail = nskb;
} else {
struct rb_node **p = &q->t_root.rb_node, *parent = NULL;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 09/10] net/sched: netem: only reseed PRNG when seed is explicitly provided
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (7 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 08/10] net/sched: netem: null-terminate tfifo linear queue tail Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 10/10] selftests/tc-testing: add netem configuration and traffic tests Stephen Hemminger
2026-03-15 15:19 ` [PATCH net v2 00/10] netem: fixes and selftests Jakub Kicinski
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
netem_change() unconditionally reseeds the PRNG on every tc change
command. If TCA_NETEM_PRNG_SEED is not specified, a new random seed
is generated, destroying reproducibility for users who set a
deterministic seed on a previous change.
Move the initial random seed generation to netem_init() and only
reseed in netem_change() when TCA_NETEM_PRNG_SEED is explicitly
provided by the user.
Fixes: 4072d97ddc44 ("netem: add prng attribute to netem_sched_data")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3bed25f494d3..46f57828ee1c 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -1123,11 +1123,10 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
/* capping jitter to the range acceptable by tabledist() */
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
- if (tb[TCA_NETEM_PRNG_SEED])
+ if (tb[TCA_NETEM_PRNG_SEED]) {
q->prng.seed = nla_get_u64(tb[TCA_NETEM_PRNG_SEED]);
- else
- q->prng.seed = get_random_u64();
- prandom_seed_state(&q->prng.prng_state, q->prng.seed);
+ prandom_seed_state(&q->prng.prng_state, q->prng.seed);
+ }
unlock:
sch_tree_unlock(sch);
@@ -1150,6 +1149,9 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt,
return -EINVAL;
q->loss_model = CLG_RANDOM;
+ q->prng.seed = get_random_u64();
+ prandom_seed_state(&q->prng.prng_state, q->prng.seed);
+
ret = netem_change(sch, opt, extack);
if (ret)
pr_info("netem: change failed\n");
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net v2 10/10] selftests/tc-testing: add netem configuration and traffic tests
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (8 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 09/10] net/sched: netem: only reseed PRNG when seed is explicitly provided Stephen Hemminger
@ 2026-03-15 0:14 ` Stephen Hemminger
2026-03-15 15:19 ` [PATCH net v2 00/10] netem: fixes and selftests Jakub Kicinski
10 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 0:14 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
Add tests for netem topologies that were previously untested.
Configuration tests (nsPlugin only) verify tc commands succeed:
- HTB/HFSC roots with multiple netem leaves
- netem with pfifo, TBF, SFQ child qdiscs
- HTB -> netem -> TBF three-level chain
- netem nested inside netem
- all impairments combined in a single qdisc
Traffic tests (scapyPlugin) verify packets flow through:
- basic delay, duplication, loss, corrupt
- HTB with two duplicating netem leaves
- HFSC with duplicating netem child
- nested netem with duplication
- netem with TBF child
- all impairments combined
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
.../tc-testing/tc-tests/qdiscs/netem.json | 590 ++++++++++++++++++
1 file changed, 590 insertions(+)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json
index 7985b5215853..01011cd05f55 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/netem.json
@@ -417,5 +417,595 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1:0 root"
]
+ },
+ {
+ "id": "a1b2",
+ "name": "NETEM with pfifo child qdisc",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 10: pfifo limit 50",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc pfifo 10:",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "c2d3",
+ "name": "NETEM under HTB with two netem leaves",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: htb default 10",
+ "$TC class add dev $DUMMY parent 1: classid 1:10 htb rate 10mbit",
+ "$TC class add dev $DUMMY parent 1: classid 1:20 htb rate 10mbit",
+ "$TC qdisc add dev $DUMMY parent 1:10 handle 10: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:20 handle 20: netem delay 20ms",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "d4e5",
+ "name": "NETEM under HTB with duplication on one leaf",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: htb default 10",
+ "$TC class add dev $DUMMY parent 1: classid 1:10 htb rate 10mbit",
+ "$TC class add dev $DUMMY parent 1: classid 1:20 htb rate 10mbit",
+ "$TC qdisc add dev $DUMMY parent 1:10 handle 10: netem delay 10ms duplicate 25%"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:20 handle 20: netem delay 20ms",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "e5f6",
+ "name": "NETEM under HTB with duplication on both leaves",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: htb default 10",
+ "$TC class add dev $DUMMY parent 1: classid 1:10 htb rate 10mbit",
+ "$TC class add dev $DUMMY parent 1: classid 1:20 htb rate 10mbit",
+ "$TC qdisc add dev $DUMMY parent 1:10 handle 10: netem delay 10ms duplicate 25%"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:20 handle 20: netem delay 10ms duplicate 25%",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "f6a7",
+ "name": "NETEM under HFSC class",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: hfsc default 1",
+ "$TC class add dev $DUMMY parent 1: classid 1:1 hfsc rt m2 10mbit"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 10: netem delay 10ms",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem 10:",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "a7b8",
+ "name": "NETEM with duplication under HFSC class",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: hfsc default 1",
+ "$TC class add dev $DUMMY parent 1: classid 1:1 hfsc rt m2 10mbit"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 10: netem delay 10ms duplicate 50%",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem 10:.*duplicate 50%",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "b8c9",
+ "name": "NETEM under two HFSC classes",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: hfsc default 1",
+ "$TC class add dev $DUMMY parent 1: classid 1:1 hfsc rt m2 10mbit",
+ "$TC class add dev $DUMMY parent 1: classid 1:2 hfsc rt m2 10mbit",
+ "$TC qdisc add dev $DUMMY parent 1:1 handle 10: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:2 handle 20: netem delay 20ms duplicate 25%",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "c9d0",
+ "name": "NETEM with TBF child qdisc",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 10: tbf rate 1mbit burst 10kb latency 50ms",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc tbf 10:",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "d0e1",
+ "name": "NETEM with SFQ child qdisc",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 10: sfq perturb 10",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc sfq 10:",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "e1f2",
+ "name": "NETEM under HTB with TBF chain",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: htb default 10",
+ "$TC class add dev $DUMMY parent 1: classid 1:10 htb rate 10mbit",
+ "$TC qdisc add dev $DUMMY parent 1:10 handle 10: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 10:1 handle 100: tbf rate 1mbit burst 10kb latency 50ms",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc tbf 100:",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "f2a3",
+ "name": "NETEM nested inside netem",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DUMMY root handle 1: netem delay 10ms"
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent 1:1 handle 10: netem delay 5ms duplicate 10%",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "a3b4",
+ "name": "NETEM with all impairments combined",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ ],
+ "cmdUnderTest": "$TC qdisc add dev $DUMMY handle 1: root netem delay 50ms 10ms distribution normal loss 5% duplicate 10% corrupt 1% reorder 25% 50% gap 5 rate 10mbit",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "qdisc netem 1: root refcnt [0-9]+ .*delay 50ms",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DUMMY handle 1: root"
+ ]
+ },
+ {
+ "id": "7a01",
+ "name": "NETEM passes traffic with delay",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7b02",
+ "name": "NETEM passes traffic with duplication",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms duplicate 50%"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7c03",
+ "name": "NETEM passes traffic with loss",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms loss 30%"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7d04",
+ "name": "NETEM passes traffic with corrupt",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms corrupt 10%"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7e05",
+ "name": "NETEM passes traffic under HTB with two netem leaves",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 root handle 1: htb default 10",
+ "$TC class add dev $DEV1 parent 1: classid 1:10 htb rate 10mbit",
+ "$TC class add dev $DEV1 parent 1: classid 1:20 htb rate 10mbit",
+ "$TC qdisc add dev $DEV1 parent 1:10 handle 10: netem delay 1ms duplicate 25%",
+ "$TC qdisc add dev $DEV1 parent 1:20 handle 20: netem delay 1ms duplicate 25%"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7f06",
+ "name": "NETEM passes traffic under HFSC with duplication",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 root handle 1: hfsc default 1",
+ "$TC class add dev $DEV1 parent 1: classid 1:1 hfsc rt m2 10mbit",
+ "$TC qdisc add dev $DEV1 parent 1:1 handle 10: netem delay 1ms duplicate 25%"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7a07",
+ "name": "NETEM passes traffic with nested netem",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 root handle 1: netem delay 1ms",
+ "$TC qdisc add dev $DEV1 parent 1:1 handle 10: netem delay 1ms duplicate 10%"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7b08",
+ "name": "NETEM passes traffic with TBF child",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 root handle 1: netem delay 1ms",
+ "$TC qdisc add dev $DEV1 parent 1:1 handle 10: tbf rate 1mbit burst 10kb latency 50ms"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7c09",
+ "name": "NETEM passes traffic with all impairments",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms 500us distribution normal loss 5% duplicate 10% corrupt 1% reorder 25% 50% gap 5"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 50,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7d0a",
+ "name": "NETEM passes traffic with reorder",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 10ms reorder 25% 50% gap 5"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 30,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7e0b",
+ "name": "NETEM passes traffic with slot pacing",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms slot 20ms 40ms packets 5 bytes 1500"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7f0c",
+ "name": "NETEM passes traffic with rate limiting",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root netem delay 1ms rate 1mbit"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
+ },
+ {
+ "id": "7a0d",
+ "name": "NETEM passes traffic with SFQ child",
+ "category": ["qdisc", "netem"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 root handle 1: netem delay 1ms",
+ "$TC qdisc add dev $DEV1 parent 1:1 handle 10: sfq perturb 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 20,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/UDP(sport=5000,dport=5001)/Raw('X'*64)"
+ }
+ ],
+ "cmdUnderTest": "sleep 0.5",
+ "expExitCode": "0",
+ "verifyCmd": "$TC -s qdisc show dev $DEV1",
+ "matchPattern": "Sent [1-9][0-9]* bytes [1-9][0-9]* pkt",
+ "matchCount": "2",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 handle 1: root"
+ ]
}
]
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH net v2 00/10] netem: fixes and selftests
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
` (9 preceding siblings ...)
2026-03-15 0:14 ` [PATCH net v2 10/10] selftests/tc-testing: add netem configuration and traffic tests Stephen Hemminger
@ 2026-03-15 15:19 ` Jakub Kicinski
2026-03-15 16:09 ` Stephen Hemminger
10 siblings, 1 reply; 13+ messages in thread
From: Jakub Kicinski @ 2026-03-15 15:19 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
On Sat, 14 Mar 2026 17:14:04 -0700 Stephen Hemminger wrote:
> The check_netem_in_tree() restriction added for CVE-2024-45016 rejects
> valid configurations such as HTB or HFSC trees with netem on multiple
> branches -- including examples from the netem documentation itself.
> This has been an open issue for over a year (kernel.org bug #220774).
>
> This series replaces it with a per-CPU recursion guard, restructures
> dequeue to fix the HFSC eltree corruption, and addresses several
> additional bugs found during a code audit.
# not ok 379 7a01 - NETEM passes traffic with delay
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 151499771072372938
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 380 7b02 - NETEM passes traffic with duplication
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms duplicate 50% seed 4449138859105539433
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 381 7c03 - NETEM passes traffic with loss
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms loss 30% seed 17755509090945397811
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 382 7d04 - NETEM passes traffic with corrupt
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms corrupt 10% seed 15571003730150948945
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 383 7e05 - NETEM passes traffic under HTB with two netem leaves
# Could not match regex pattern. Verify command output:
# qdisc htb 1: root refcnt 33 r2q 10 default 0x10 direct_packets_stat 0 direct_qlen 1000
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
# qdisc netem 10: parent 1:10 limit 1000 delay 1ms duplicate 25% seed 7229481943258718053
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
# qdisc netem 20: parent 1:20 limit 1000 delay 1ms duplicate 25% seed 2614650852791982394
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 384 7f06 - NETEM passes traffic under HFSC with duplication
# Could not match regex pattern. Verify command output:
# qdisc hfsc 1: root refcnt 33 default 0x1
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
# qdisc netem 10: parent 1:1 limit 1000 delay 1ms duplicate 25% seed 1742473429681626986
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 385 7a07 - NETEM passes traffic with nested netem
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 959619114654116267
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
# qdisc netem 10: parent 1:1 limit 1000 delay 1ms duplicate 10% seed 1402527459214356892
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 386 7b08 - NETEM passes traffic with TBF child
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 3026058286388988065
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
# qdisc tbf 10: parent 1:1 rate 1Mbit burst 10Kb lat 50ms
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 387 7c09 - NETEM passes traffic with all impairments
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms 500us loss 5% duplicate 10% reorder 25% 50% corrupt 1% seed 4173999615992747611 gap 5
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 388 7d0a - NETEM passes traffic with reorder
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 10ms reorder 25% 50% seed 16878270064950901169 gap 5
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 389 7e0b - NETEM passes traffic with slot pacing
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms slot 20ms 40ms packets 5 bytes 1500 seed 12148330044418512905
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 390 7f0c - NETEM passes traffic with rate limiting
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms rate 1Mbit seed 17545598048030611383
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
# not ok 391 7a0d - NETEM passes traffic with SFQ child
# Could not match regex pattern. Verify command output:
# qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 7568266806072117190
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
# qdisc sfq 10: parent 1:1 limit 127p quantum 1514b depth 127 divisor 1024 perturb 10sec
# Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
# backlog 0b 0p requeues 0
#
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v2 00/10] netem: fixes and selftests
2026-03-15 15:19 ` [PATCH net v2 00/10] netem: fixes and selftests Jakub Kicinski
@ 2026-03-15 16:09 ` Stephen Hemminger
0 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2026-03-15 16:09 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev
On Sun, 15 Mar 2026 08:19:53 -0700
Jakub Kicinski <kuba@kernel.org> wrote:
> On Sat, 14 Mar 2026 17:14:04 -0700 Stephen Hemminger wrote:
> > The check_netem_in_tree() restriction added for CVE-2024-45016 rejects
> > valid configurations such as HTB or HFSC trees with netem on multiple
> > branches -- including examples from the netem documentation itself.
> > This has been an open issue for over a year (kernel.org bug #220774).
> >
> > This series replaces it with a per-CPU recursion guard, restructures
> > dequeue to fix the HFSC eltree corruption, and addresses several
> > additional bugs found during a code audit.
>
> # not ok 379 7a01 - NETEM passes traffic with delay
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 151499771072372938
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 380 7b02 - NETEM passes traffic with duplication
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms duplicate 50% seed 4449138859105539433
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 381 7c03 - NETEM passes traffic with loss
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms loss 30% seed 17755509090945397811
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 382 7d04 - NETEM passes traffic with corrupt
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms corrupt 10% seed 15571003730150948945
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 383 7e05 - NETEM passes traffic under HTB with two netem leaves
> # Could not match regex pattern. Verify command output:
> # qdisc htb 1: root refcnt 33 r2q 10 default 0x10 direct_packets_stat 0 direct_qlen 1000
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> # qdisc netem 10: parent 1:10 limit 1000 delay 1ms duplicate 25% seed 7229481943258718053
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> # qdisc netem 20: parent 1:20 limit 1000 delay 1ms duplicate 25% seed 2614650852791982394
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 384 7f06 - NETEM passes traffic under HFSC with duplication
> # Could not match regex pattern. Verify command output:
> # qdisc hfsc 1: root refcnt 33 default 0x1
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> # qdisc netem 10: parent 1:1 limit 1000 delay 1ms duplicate 25% seed 1742473429681626986
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 385 7a07 - NETEM passes traffic with nested netem
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 959619114654116267
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> # qdisc netem 10: parent 1:1 limit 1000 delay 1ms duplicate 10% seed 1402527459214356892
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 386 7b08 - NETEM passes traffic with TBF child
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 3026058286388988065
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> # qdisc tbf 10: parent 1:1 rate 1Mbit burst 10Kb lat 50ms
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 387 7c09 - NETEM passes traffic with all impairments
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms 500us loss 5% duplicate 10% reorder 25% 50% corrupt 1% seed 4173999615992747611 gap 5
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 388 7d0a - NETEM passes traffic with reorder
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 10ms reorder 25% 50% seed 16878270064950901169 gap 5
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 389 7e0b - NETEM passes traffic with slot pacing
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms slot 20ms 40ms packets 5 bytes 1500 seed 12148330044418512905
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 390 7f0c - NETEM passes traffic with rate limiting
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms rate 1Mbit seed 17545598048030611383
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
> # not ok 391 7a0d - NETEM passes traffic with SFQ child
> # Could not match regex pattern. Verify command output:
> # qdisc netem 1: root refcnt 33 limit 1000 delay 1ms seed 7568266806072117190
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> # qdisc sfq 10: parent 1:1 limit 127p quantum 1514b depth 127 divisor 1024 perturb 10sec
> # Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> # backlog 0b 0p requeues 0
> #
The new tests use scapy like the other qdisc tests, looks like CI is not
setting up the interfaces the same as local test. Is there something needed
elsewhere? The codel test does similar things.
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-03-15 16:09 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-15 0:14 [PATCH net v2 00/10] netem: fixes and selftests Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 01/10] Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree" Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 02/10] net/sched: netem: add per-CPU recursion guard for duplication Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 03/10] selftests/tc-testing: update netem tests after check_netem_in_tree revert Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 04/10] net/sched: netem: restructure dequeue to avoid re-entrancy with child qdisc Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 05/10] net/sched: netem: fix probability gaps in 4-state loss model Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 06/10] net/sched: netem: fix slot delay calculation overflow Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 07/10] net/sched: netem: fix queue limit check to include reordered packets Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 08/10] net/sched: netem: null-terminate tfifo linear queue tail Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 09/10] net/sched: netem: only reseed PRNG when seed is explicitly provided Stephen Hemminger
2026-03-15 0:14 ` [PATCH net v2 10/10] selftests/tc-testing: add netem configuration and traffic tests Stephen Hemminger
2026-03-15 15:19 ` [PATCH net v2 00/10] netem: fixes and selftests Jakub Kicinski
2026-03-15 16:09 ` Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox