Commit 0170d7f4 authored by Eric Dumazet's avatar Eric Dumazet Committed by Paolo Abeni
Browse files

net_sched: add tcf_kfree_skb_list() helper



Using kfree_skb_list_reason() to free list of skbs from qdisc
operations seems wrong as each skb might have a different drop reason.

Cleanup __dev_xmit_skb() to call tcf_kfree_skb_list() once
in preparation of the following patch.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20251121083256.674562-13-edumazet@google.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 4792c3a4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1105,6 +1105,17 @@ static inline void tcf_set_drop_reason(const struct sk_buff *skb,
	tc_skb_cb(skb)->drop_reason = reason;
}

static inline void tcf_kfree_skb_list(struct sk_buff *skb)
{
	while (unlikely(skb)) {
		struct sk_buff *next = skb->next;

		prefetch(next);
		kfree_skb_reason(skb, tcf_get_drop_reason(skb));
		skb = next;
	}
}

/* Instead of calling kfree_skb() while root qdisc lock is held,
 * queue the skb for future freeing at end of __dev_xmit_skb()
 */
+5 −10
Original line number Diff line number Diff line
@@ -4162,7 +4162,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
				__qdisc_run(q);
				qdisc_run_end(q);

				goto no_lock_out;
				goto free_skbs;
			}

			qdisc_bstats_cpu_update(q, skb);
@@ -4176,12 +4176,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,

		rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
		qdisc_run(q);

no_lock_out:
		if (unlikely(to_free))
			kfree_skb_list_reason(to_free,
					      tcf_get_drop_reason(to_free));
		return rc;
		goto free_skbs;
	}

	/* Open code llist_add(&skb->ll_node, &q->defer_list) + queue limit.
@@ -4257,9 +4252,9 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
	}
unlock:
	spin_unlock(root_lock);
	if (unlikely(to_free))
		kfree_skb_list_reason(to_free,
				      tcf_get_drop_reason(to_free));

free_skbs:
	tcf_kfree_skb_list(to_free);
	return rc;
}