netfilter: nf_dup_netdev: Move the recursion counter struct netdev_xmit

nf_dup_skb_recursion is a per-CPU variable and relies on disabled BH for its
locking. Without per-CPU locking in local_bh_disable() on PREEMPT_RT
this data structure requires explicit locking.

Move nf_dup_skb_recursion to struct netdev_xmit, provide wrappers.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Sebastian Andrzej Siewior
2025-05-12 12:28:46 +02:00
committed by Pablo Neira Ayuso
parent ba36fada9a
commit f37ad91270
2 changed files with 21 additions and 4 deletions

View File

@@ -11,6 +11,9 @@ struct netdev_xmit {
#if IS_ENABLED(CONFIG_NET_ACT_MIRRED)
u8 sched_mirred_nest;
#endif
#if IS_ENABLED(CONFIG_NF_DUP_NETDEV)
u8 nf_dup_skb_recursion;
#endif
};
#endif

View File

@@ -15,12 +15,26 @@
#define NF_RECURSION_LIMIT 2
static DEFINE_PER_CPU(u8, nf_dup_skb_recursion);
#ifndef CONFIG_PREEMPT_RT
static u8 *nf_get_nf_dup_skb_recursion(void)
{
return this_cpu_ptr(&softnet_data.xmit.nf_dup_skb_recursion);
}
#else
static u8 *nf_get_nf_dup_skb_recursion(void)
{
return &current->net_xmit.nf_dup_skb_recursion;
}
#endif
static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev,
enum nf_dev_hooks hook)
{
if (__this_cpu_read(nf_dup_skb_recursion) > NF_RECURSION_LIMIT)
u8 *nf_dup_skb_recursion = nf_get_nf_dup_skb_recursion();
if (*nf_dup_skb_recursion > NF_RECURSION_LIMIT)
goto err;
if (hook == NF_NETDEV_INGRESS && skb_mac_header_was_set(skb)) {
@@ -32,9 +46,9 @@ static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev,
skb->dev = dev;
skb_clear_tstamp(skb);
__this_cpu_inc(nf_dup_skb_recursion);
(*nf_dup_skb_recursion)++;
dev_queue_xmit(skb);
__this_cpu_dec(nf_dup_skb_recursion);
(*nf_dup_skb_recursion)--;
return;
err:
kfree_skb(skb);