Commit f37ad912 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Pablo Neira Ayuso
Browse files

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: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent ba36fada
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+18 −4
Original line number Diff line number Diff line
@@ -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);