VXLAN_F_MDB is an internal runtime state flag indicating whether any MDB entries are configured on the device, rather than a netlink configuration attribute. In preparation for converting vxlan->cfg to an RCU-protected pointer, move VXLAN_F_MDB from struct vxlan_config to a dedicated 'flags' field in struct vxlan_dev as VXLAN_DEV_F_MDB, using atomic bitops (set_bit(), clear_bit(), test_bit()) to avoid KCSAN data races between the TX path and RTNL operations. This avoids having to dynamically reallocate and publish a new vxlan_config structure via RCU whenever the first MDB entry is added or the last one is removed, and prevents potential memory allocation failures during MDB teardown under memory pressure. mlxsw validates cfg->flags against a deny-by-default mask, so VXLAN_F_MDB used to make mlxsw_sp_nve_vxlan_can_offload() reject a device with MDB entries as carrying an unsupported flag. Add an explicit VXLAN_DEV_F_MDB test there to keep that rejection, with a message naming the actual reason. Signed-off-by: Eric Dumazet Reviewed-by: Kuniyuki Iwashima --- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c | 5 +++++ drivers/net/vxlan/vxlan_core.c | 2 +- drivers/net/vxlan/vxlan_mdb.c | 6 +++--- include/net/vxlan.h | 6 +++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index 52c2fe3644d4b9b27f1d589d9f7f597748339782..b78aff31c98f2d8aedfdf36bbfc1cb61e1066edf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -92,6 +92,11 @@ static bool mlxsw_sp_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, return false; } + if (test_bit(VXLAN_DEV_F_MDB, &vxlan->flags)) { + NL_SET_ERR_MSG_MOD(extack, "VxLAN: MDB entries are not supported"); + return false; + } + switch (cfg->saddr.sa.sa_family) { case AF_INET: if (!mlxsw_sp_nve_vxlan_ipv4_flags_check(cfg, extack)) diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index a0c2a480701188506ca2f7f00d1890edf8662ced..411768cd97d3d4f5c71d7c6ff1933aecbfa46d80 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2824,7 +2824,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) if (nhid) return vxlan_xmit_nhid(skb, dev, nhid, vni, cfg); - if (flags & VXLAN_F_MDB) { + if (test_bit(VXLAN_DEV_F_MDB, &vxlan->flags)) { struct vxlan_mdb_entry *mdb_entry; rcu_read_lock(); diff --git a/drivers/net/vxlan/vxlan_mdb.c b/drivers/net/vxlan/vxlan_mdb.c index 56ca9283283307d8b1231c3b26724474e6c838d6..cf606256d0929c4dd356ec8aa343150c10edfb82 100644 --- a/drivers/net/vxlan/vxlan_mdb.c +++ b/drivers/net/vxlan/vxlan_mdb.c @@ -1219,7 +1219,7 @@ vxlan_mdb_entry_get(struct vxlan_dev *vxlan, goto err_free_entry; if (hlist_is_singular_node(&mdb_entry->mdb_node, &vxlan->mdb_list)) - vxlan->cfg.flags |= VXLAN_F_MDB; + set_bit(VXLAN_DEV_F_MDB, &vxlan->flags); return mdb_entry; @@ -1236,7 +1236,7 @@ static void vxlan_mdb_entry_put(struct vxlan_dev *vxlan, return; if (hlist_is_singular_node(&mdb_entry->mdb_node, &vxlan->mdb_list)) - vxlan->cfg.flags &= ~VXLAN_F_MDB; + clear_bit(VXLAN_DEV_F_MDB, &vxlan->flags); rhashtable_remove_fast(&vxlan->mdb_tbl, &mdb_entry->rhnode, vxlan_mdb_rht_params); @@ -1762,7 +1762,7 @@ void vxlan_mdb_fini(struct vxlan_dev *vxlan) struct vxlan_mdb_flush_desc desc = {}; vxlan_mdb_flush(vxlan, &desc); - WARN_ON_ONCE(vxlan->cfg.flags & VXLAN_F_MDB); + WARN_ON_ONCE(test_bit(VXLAN_DEV_F_MDB, &vxlan->flags)); rhashtable_free_and_destroy(&vxlan->mdb_tbl, vxlan_mdb_check_empty, NULL); } diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 7b82075055237058d231d636698f640c75c521af..d323f91af2364822e148310297c978fec7664010 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -300,6 +300,7 @@ struct vxlan_dev { spinlock_t hash_lock; unsigned int addrcnt; struct gro_cells gro_cells; + unsigned long flags; struct vxlan_config cfg; @@ -313,6 +314,10 @@ struct vxlan_dev { unsigned int mdb_seq; }; +enum vxlan_dev_flags { + VXLAN_DEV_F_MDB, +}; + #define VXLAN_F_LEARN 0x01 #define VXLAN_F_PROXY 0x02 #define VXLAN_F_RSC 0x04 @@ -331,7 +336,6 @@ struct vxlan_dev { #define VXLAN_F_IPV6_LINKLOCAL 0x8000 #define VXLAN_F_TTL_INHERIT 0x10000 #define VXLAN_F_VNIFILTER 0x20000 -#define VXLAN_F_MDB 0x40000 #define VXLAN_F_LOCALBYPASS 0x80000 #define VXLAN_F_MC_ROUTE 0x100000 -- 2.55.0.1032.g73a4cd73de-goog