* [Patch net 0/2] net_sched: Fix gso_skb flushing during qdisc change
@ 2025-05-06 0:15 Cong Wang
2025-05-06 0:15 ` [Patch net 1/2] net_sched: Flush gso_skb list too during ->change() Cong Wang
2025-05-06 0:15 ` [Patch net 2/2] selftests/tc-testing: Add qdisc limit trimming tests Cong Wang
0 siblings, 2 replies; 5+ messages in thread
From: Cong Wang @ 2025-05-06 0:15 UTC (permalink / raw)
To: netdev; +Cc: jiri, jhs, willsroot, savy, Cong Wang
This patchset contains a bug fix and its test cases, please check each
patch description for more details. To keep the bug fix minimum, I
intentionally limit the code changes to the cases reported here.
---
Cong Wang (2):
net_sched: Flush gso_skb list too during ->change()
selftests/tc-testing: Add qdisc limit trimming tests
include/net/sch_generic.h | 14 +++++++++++
net/sched/sch_codel.c | 2 +-
net/sched/sch_fq.c | 2 +-
net/sched/sch_fq_codel.c | 2 +-
net/sched/sch_fq_pie.c | 2 +-
net/sched/sch_hhf.c | 2 +-
net/sched/sch_pie.c | 2 +-
.../tc-testing/tc-tests/qdiscs/codel.json | 24 +++++++++++++++++++
.../tc-testing/tc-tests/qdiscs/fq.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/fq_codel.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/fq_pie.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/hhf.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/pie.json | 24 +++++++++++++++++++
13 files changed, 156 insertions(+), 6 deletions(-)
create mode 100644 tools/testing/selftests/tc-testing/tc-tests/qdiscs/pie.json
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch net 1/2] net_sched: Flush gso_skb list too during ->change()
2025-05-06 0:15 [Patch net 0/2] net_sched: Fix gso_skb flushing during qdisc change Cong Wang
@ 2025-05-06 0:15 ` Cong Wang
2025-05-06 14:00 ` Savy
2025-05-06 0:15 ` [Patch net 2/2] selftests/tc-testing: Add qdisc limit trimming tests Cong Wang
1 sibling, 1 reply; 5+ messages in thread
From: Cong Wang @ 2025-05-06 0:15 UTC (permalink / raw)
To: netdev; +Cc: jiri, jhs, willsroot, savy, Cong Wang
Previously, when reducing a qdisc's limit via the ->change() operation, only
the main skb queue was trimmed, potentially leaving packets in the gso_skb
list. This could result in NULL pointer dereference when we only check
sch->q.qlen against sch->limit.
This patch introduces a new helper, qdisc_dequeue_internal(), which ensures
both the gso_skb list and the main queue are properly flushed when trimming
excess packets. All relevant qdiscs (codel, fq, fq_codel, fq_pie, hhf, pie)
are updated to use this helper in their ->change() routines.
Fixes: 76e3cc126bb2 ("codel: Controlled Delay AQM")
Fixes: 4b549a2ef4be ("fq_codel: Fair Queue Codel AQM")
Fixes: afe4fd062416 ("pkt_sched: fq: Fair Queue packet scheduler")
Fixes: ec97ecf1ebe4 ("net: sched: add Flow Queue PIE packet scheduler")
Fixes: 10239edf86f1 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc")
Fixes: d4b36210c2e6 ("net: pkt_sched: PIE AQM scheme")
Reported-by: Will <willsroot@protonmail.com>
Reported-by: Savy <savy@syst3mfailure.io>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/net/sch_generic.h | 14 ++++++++++++++
net/sched/sch_codel.c | 2 +-
net/sched/sch_fq.c | 2 +-
net/sched/sch_fq_codel.c | 2 +-
net/sched/sch_fq_pie.c | 2 +-
net/sched/sch_hhf.c | 2 +-
net/sched/sch_pie.c | 2 +-
7 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index d48c657191cd..81523a4fb01b 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -1031,6 +1031,20 @@ static inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh)
return skb;
}
+static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool direct)
+{
+ struct sk_buff *skb;
+
+ skb = __skb_dequeue(&sch->gso_skb);
+ if (!skb) {
+ if (direct)
+ skb = __qdisc_dequeue_head(&sch->q);
+ else
+ skb = sch->dequeue(sch);
+ }
+ return skb;
+}
+
static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
{
struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
index 12dd71139da3..c93761040c6e 100644
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -144,7 +144,7 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt,
qlen = sch->q.qlen;
while (sch->q.qlen > sch->limit) {
- struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
+ struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
dropped += qdisc_pkt_len(skb);
qdisc_qstats_backlog_dec(sch, skb);
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 2ca5332cfcc5..902ff5470607 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -1136,7 +1136,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
sch_tree_lock(sch);
}
while (sch->q.qlen > sch->limit) {
- struct sk_buff *skb = fq_dequeue(sch);
+ struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
if (!skb)
break;
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 6c9029f71e88..2a0f3a513bfa 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -441,7 +441,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
while (sch->q.qlen > sch->limit ||
q->memory_usage > q->memory_limit) {
- struct sk_buff *skb = fq_codel_dequeue(sch);
+ struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
q->cstats.drop_len += qdisc_pkt_len(skb);
rtnl_kfree_skbs(skb, skb);
diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c
index f3b8203d3e85..a04554d01960 100644
--- a/net/sched/sch_fq_pie.c
+++ b/net/sched/sch_fq_pie.c
@@ -366,7 +366,7 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
/* Drop excess packets if new limit is lower */
while (sch->q.qlen > sch->limit) {
- struct sk_buff *skb = fq_pie_qdisc_dequeue(sch);
+ struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
len_dropped += qdisc_pkt_len(skb);
num_dropped += 1;
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index 44d9efe1a96a..f4c2bebd3780 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -564,7 +564,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
qlen = sch->q.qlen;
prev_backlog = sch->qstats.backlog;
while (sch->q.qlen > sch->limit) {
- struct sk_buff *skb = hhf_dequeue(sch);
+ struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
rtnl_kfree_skbs(skb, skb);
}
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index 3771d000b30d..ff49a6c97033 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -195,7 +195,7 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt,
/* Drop excess packets if new limit is lower */
qlen = sch->q.qlen;
while (sch->q.qlen > sch->limit) {
- struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
+ struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
dropped += qdisc_pkt_len(skb);
qdisc_qstats_backlog_dec(sch, skb);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Patch net 2/2] selftests/tc-testing: Add qdisc limit trimming tests
2025-05-06 0:15 [Patch net 0/2] net_sched: Fix gso_skb flushing during qdisc change Cong Wang
2025-05-06 0:15 ` [Patch net 1/2] net_sched: Flush gso_skb list too during ->change() Cong Wang
@ 2025-05-06 0:15 ` Cong Wang
1 sibling, 0 replies; 5+ messages in thread
From: Cong Wang @ 2025-05-06 0:15 UTC (permalink / raw)
To: netdev; +Cc: jiri, jhs, willsroot, savy, Cong Wang
Added new test cases for FQ, FQ_CODEL, FQ_PIE, and HHF qdiscs to verify queue
trimming behavior when the qdisc limit is dynamically reduced.
Each test injects packets, reduces the qdisc limit, and checks that the new
limit is enforced. This is still best effort since timing qdisc backlog
is not easy.
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
.../tc-testing/tc-tests/qdiscs/codel.json | 24 +++++++++++++++++++
.../tc-testing/tc-tests/qdiscs/fq.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/fq_codel.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/fq_pie.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/hhf.json | 22 +++++++++++++++++
.../tc-testing/tc-tests/qdiscs/pie.json | 24 +++++++++++++++++++
6 files changed, 136 insertions(+)
create mode 100644 tools/testing/selftests/tc-testing/tc-tests/qdiscs/pie.json
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/codel.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/codel.json
index e9469ee71e6f..6d515d0e5ed6 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/codel.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/codel.json
@@ -189,5 +189,29 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "deb1",
+ "name": "CODEL test qdisc limit trimming",
+ "category": ["qdisc", "codel"],
+ "plugins": {
+ "requires": ["nsPlugin", "scapyPlugin"]
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root codel limit 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 10,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)"
+ }
+ ],
+ "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root codel limit 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DEV1",
+ "matchPattern": "qdisc codel 1: root refcnt [0-9]+ limit 1p target 5ms interval 100ms",
+ "matchCount": "1",
+ "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"]
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq.json
index 3a537b2ec4c9..24faf4e12dfa 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq.json
@@ -377,5 +377,27 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "9479",
+ "name": "FQ test qdisc limit trimming",
+ "category": ["qdisc", "fq"],
+ "plugins": {"requires": ["nsPlugin", "scapyPlugin"]},
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root fq limit 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 10,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)"
+ }
+ ],
+ "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root fq limit 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DEV1",
+ "matchPattern": "qdisc fq 1: root refcnt [0-9]+ limit 1p",
+ "matchCount": "1",
+ "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"]
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_codel.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_codel.json
index 9774b1e8801b..4ce62b857fd7 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_codel.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_codel.json
@@ -294,5 +294,27 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "0436",
+ "name": "FQ_CODEL test qdisc limit trimming",
+ "category": ["qdisc", "fq_codel"],
+ "plugins": {"requires": ["nsPlugin", "scapyPlugin"]},
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root fq_codel limit 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 10,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)"
+ }
+ ],
+ "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root fq_codel limit 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DEV1",
+ "matchPattern": "qdisc fq_codel 1: root refcnt [0-9]+ limit 1p flows 1024 quantum.*target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64",
+ "matchCount": "1",
+ "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"]
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_pie.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_pie.json
index d012d88d67fe..229fe1bf4a90 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_pie.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_pie.json
@@ -18,5 +18,27 @@
"matchCount": "1",
"teardown": [
]
+ },
+ {
+ "id": "83bf",
+ "name": "FQ_PIE test qdisc limit trimming",
+ "category": ["qdisc", "fq_pie"],
+ "plugins": {"requires": ["nsPlugin", "scapyPlugin"]},
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root fq_pie limit 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 10,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)"
+ }
+ ],
+ "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root fq_pie limit 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DEV1",
+ "matchPattern": "qdisc fq_pie 1: root refcnt [0-9]+ limit 1p",
+ "matchCount": "1",
+ "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"]
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/hhf.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/hhf.json
index dbef5474b26b..0ca19fac54a5 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/hhf.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/hhf.json
@@ -188,5 +188,27 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "385f",
+ "name": "HHF test qdisc limit trimming",
+ "category": ["qdisc", "hhf"],
+ "plugins": {"requires": ["nsPlugin", "scapyPlugin"]},
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root hhf limit 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 10,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)"
+ }
+ ],
+ "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root hhf limit 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DEV1",
+ "matchPattern": "qdisc hhf 1: root refcnt [0-9]+ limit 1p.*hh_limit 2048 reset_timeout 40ms admit_bytes 128Kb evict_timeout 1s non_hh_weight 2",
+ "matchCount": "1",
+ "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"]
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/pie.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/pie.json
new file mode 100644
index 000000000000..1a98b66e8030
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/pie.json
@@ -0,0 +1,24 @@
+[
+ {
+ "id": "6158",
+ "name": "PIE test qdisc limit trimming",
+ "category": ["qdisc", "pie"],
+ "plugins": {"requires": ["nsPlugin", "scapyPlugin"]},
+ "setup": [
+ "$TC qdisc add dev $DEV1 handle 1: root pie limit 10"
+ ],
+ "scapy": [
+ {
+ "iface": "$DEV0",
+ "count": 10,
+ "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)"
+ }
+ ],
+ "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root pie limit 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DEV1",
+ "matchPattern": "qdisc pie 1: root refcnt [0-9]+ limit 1p",
+ "matchCount": "1",
+ "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"]
+ }
+]
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Patch net 1/2] net_sched: Flush gso_skb list too during ->change()
2025-05-06 0:15 ` [Patch net 1/2] net_sched: Flush gso_skb list too during ->change() Cong Wang
@ 2025-05-06 14:00 ` Savy
2025-05-06 20:40 ` Cong Wang
0 siblings, 1 reply; 5+ messages in thread
From: Savy @ 2025-05-06 14:00 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, jiri, jhs, willsroot
On Tuesday, May 6th, 2025 at 12:15 AM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> the main skb queue was trimmed, potentially leaving packets in the gso_skb
> list. This could result in NULL pointer dereference when we only check
> sch->q.qlen against sch->limit.
>
>
Hi Cong,
With this version of the patch, the null-ptr-deref can still be triggered.
We also need to decrement sch->q.qlen if __skb_dequeue() returns a valid skb.
We will take Codel as an example.
while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
...
}
If sch->q.qlen is 1 and there is a single packet in the gso_skb list,
if sch->limit is dropped to 0 in codel_change, then qdisc_dequeue_internal() -> __skb_dequeue()
will remove the skb from the gso_skb list, leaving sch->q.qlen unaltered.
At this point, the while loop continues, as sch->q.qlen is still 1, but now both the main queue and gso_skb are empty,
so when qdisc_dequeue_internal() is called again, it returns NULL, and the null-ptr-deref occurs.
Something like this can fix the issue (tested with Codel):
static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool direct)
{
struct sk_buff *skb;
skb = __skb_dequeue(&sch->gso_skb);
if (skb) {
sch->q.qlen--;
return skb;
}
if (direct) {
skb = __qdisc_dequeue_head(&sch->q);
} else {
skb = sch->dequeue(sch);
}
return skb;
}
Regards,
Savy
Will
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Patch net 1/2] net_sched: Flush gso_skb list too during ->change()
2025-05-06 14:00 ` Savy
@ 2025-05-06 20:40 ` Cong Wang
0 siblings, 0 replies; 5+ messages in thread
From: Cong Wang @ 2025-05-06 20:40 UTC (permalink / raw)
To: Savy; +Cc: netdev, jiri, jhs, willsroot
On Tue, May 06, 2025 at 02:00:36PM +0000, Savy wrote:
> On Tuesday, May 6th, 2025 at 12:15 AM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> >
> > the main skb queue was trimmed, potentially leaving packets in the gso_skb
> > list. This could result in NULL pointer dereference when we only check
> > sch->q.qlen against sch->limit.
> >
> >
>
> Hi Cong,
>
> With this version of the patch, the null-ptr-deref can still be triggered.
> We also need to decrement sch->q.qlen if __skb_dequeue() returns a valid skb.
>
> We will take Codel as an example.
>
> while (sch->q.qlen > sch->limit) {
> struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
> ...
> }
>
> If sch->q.qlen is 1 and there is a single packet in the gso_skb list,
> if sch->limit is dropped to 0 in codel_change, then qdisc_dequeue_internal() -> __skb_dequeue()
> will remove the skb from the gso_skb list, leaving sch->q.qlen unaltered.
> At this point, the while loop continues, as sch->q.qlen is still 1, but now both the main queue and gso_skb are empty,
> so when qdisc_dequeue_internal() is called again, it returns NULL, and the null-ptr-deref occurs.
Excellent catch!
You are right, I missed qlen--.
Also, actually I accidentally messed up the 2nd boolean parameter for
some Qdisc's.
I will update the patch and send out V2 shortly today.
Thanks!
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-05-06 20:40 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-06 0:15 [Patch net 0/2] net_sched: Fix gso_skb flushing during qdisc change Cong Wang
2025-05-06 0:15 ` [Patch net 1/2] net_sched: Flush gso_skb list too during ->change() Cong Wang
2025-05-06 14:00 ` Savy
2025-05-06 20:40 ` Cong Wang
2025-05-06 0:15 ` [Patch net 2/2] selftests/tc-testing: Add qdisc limit trimming tests Cong Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox