aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/net/vxlan/vxlan_core.c
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@nvidia.com>2025-04-15 15:11:29 +0300
committerPaolo Abeni <pabeni@redhat.com>2025-04-22 11:11:15 +0200
commit804b09be09f8af4eda5346a72361459ba21fcf1b (patch)
tree3d6a6b11aafa4c176d305ea601439b8e0a95eb72 /drivers/net/vxlan/vxlan_core.c
parentMerge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next (diff)
downloadwireguard-linux-804b09be09f8af4eda5346a72361459ba21fcf1b.tar.xz
wireguard-linux-804b09be09f8af4eda5346a72361459ba21fcf1b.zip
vxlan: Add RCU read-side critical sections in the Tx path
The Tx path does not run from an RCU read-side critical section which makes the current lockless accesses to FDB entries invalid. As far as I am aware, this has not been a problem in practice, but traces will be generated once we transition the FDB lookup to rhashtable_lookup(). Add rcu_read_{lock,unlock}() around the handling of FDB entries in the Tx path. Remove the RCU read-side critical section from vxlan_xmit_nh() as now the function is always called from an RCU read-side critical section. Reviewed-by: Petr Machata <petrm@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20250415121143.345227-2-idosch@nvidia.com Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers/net/vxlan/vxlan_core.c')
-rw-r--r--drivers/net/vxlan/vxlan_core.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 56aee539c235..7872b85e890e 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -1916,12 +1916,15 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
goto out;
}
+ rcu_read_lock();
f = vxlan_find_mac(vxlan, n->ha, vni);
if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) {
/* bridge-local neighbor */
neigh_release(n);
+ rcu_read_unlock();
goto out;
}
+ rcu_read_unlock();
reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
n->ha, sha);
@@ -2648,14 +2651,10 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
memset(&nh_rdst, 0, sizeof(struct vxlan_rdst));
hash = skb_get_hash(skb);
- rcu_read_lock();
nh = rcu_dereference(f->nh);
- if (!nh) {
- rcu_read_unlock();
+ if (!nh)
goto drop;
- }
do_xmit = vxlan_fdb_nh_path_select(nh, hash, &nh_rdst);
- rcu_read_unlock();
if (likely(do_xmit))
vxlan_xmit_one(skb, dev, vni, &nh_rdst, did_rsc);
@@ -2782,6 +2781,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
}
eth = eth_hdr(skb);
+ rcu_read_lock();
f = vxlan_find_mac(vxlan, eth->h_dest, vni);
did_rsc = false;
@@ -2804,7 +2804,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
- return NETDEV_TX_OK;
+ goto out;
}
}
@@ -2829,6 +2829,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
}
+out:
+ rcu_read_unlock();
return NETDEV_TX_OK;
}