Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20251121083256.674562-13-edumazet@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Eric Dumazet and committed by
Paolo Abeni
0170d7f4 4792c3a4

+16 -10
+11
include/net/sch_generic.h
··· 1105 1105 tc_skb_cb(skb)->drop_reason = reason; 1106 1106 } 1107 1107 1108 + static inline void tcf_kfree_skb_list(struct sk_buff *skb) 1109 + { 1110 + while (unlikely(skb)) { 1111 + struct sk_buff *next = skb->next; 1112 + 1113 + prefetch(next); 1114 + kfree_skb_reason(skb, tcf_get_drop_reason(skb)); 1115 + skb = next; 1116 + } 1117 + } 1118 + 1108 1119 /* Instead of calling kfree_skb() while root qdisc lock is held, 1109 1120 * queue the skb for future freeing at end of __dev_xmit_skb() 1110 1121 */
+5 -10
net/core/dev.c
··· 4162 4162 __qdisc_run(q); 4163 4163 qdisc_run_end(q); 4164 4164 4165 - goto no_lock_out; 4165 + goto free_skbs; 4166 4166 } 4167 4167 4168 4168 qdisc_bstats_cpu_update(q, skb); ··· 4176 4176 4177 4177 rc = dev_qdisc_enqueue(skb, q, &to_free, txq); 4178 4178 qdisc_run(q); 4179 - 4180 - no_lock_out: 4181 - if (unlikely(to_free)) 4182 - kfree_skb_list_reason(to_free, 4183 - tcf_get_drop_reason(to_free)); 4184 - return rc; 4179 + goto free_skbs; 4185 4180 } 4186 4181 4187 4182 /* Open code llist_add(&skb->ll_node, &q->defer_list) + queue limit. ··· 4252 4257 } 4253 4258 unlock: 4254 4259 spin_unlock(root_lock); 4255 - if (unlikely(to_free)) 4256 - kfree_skb_list_reason(to_free, 4257 - tcf_get_drop_reason(to_free)); 4260 + 4261 + free_skbs: 4262 + tcf_kfree_skb_list(to_free); 4258 4263 return rc; 4259 4264 } 4260 4265