This patch refines the packet duplication handling in netem_enqueue() to ensure that only newly cloned skbs are marked as duplicates. This prevents scenarios where nested netem qdiscs with 100% duplication could cause infinite loops of skb duplication. By ensuring the duplicate flag is properly managed, this patch maintains skb integrity and avoids excessive packet duplication in complex qdisc setups. Now we could also get rid of the ugly temporary overwrite of q->duplicate. Fixes: 0afb51e72855 ("[PKT_SCHED]: netem: reinsert for duplication") Reported-by: William Liu Reported-by: Savino Dicanosa Signed-off-by: Cong Wang --- include/net/sch_generic.h | 1 + net/sched/sch_netem.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 638948be4c50..595b24180d62 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -1067,6 +1067,7 @@ struct tc_skb_cb { u8 post_ct:1; u8 post_ct_snat:1; u8 post_ct_dnat:1; + u8 duplicate:1; }; static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index fdd79d3ccd8c..249095ba7f98 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -460,7 +460,8 @@ 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 (!tc_skb_cb(skb)->duplicate && + q->duplicate >= get_crandom(&q->dup_cor, &q->prng)) ++count; /* Drop packet? */ @@ -538,11 +539,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, */ if (skb2) { struct Qdisc *rootq = qdisc_root_bh(sch); - u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ - q->duplicate = 0; + tc_skb_cb(skb2)->duplicate = 1; rootq->enqueue(skb2, rootq, to_free); - q->duplicate = dupsave; skb2 = NULL; } -- 2.34.1