From: Eric Dumazet <edumazet@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
Kuniyuki Iwashima <kuniyu@google.com>,
Ido Schimmel <idosch@nvidia.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>
Subject: [PATCH v3 net-next 5/6] vxlan: remove default_dst and use vxlan_config and lowerdev
Date: Fri, 11 Sep 2026 06:21:59 +0000 [thread overview]
Message-ID: <20260911062200.231316-6-edumazet@google.com> (raw)
In-Reply-To: <20260911062200.231316-1-edumazet@google.com>
Now that vxlan->cfg is an RCU-protected pointer, storing default
destination attributes (remote_ip, remote_vni, remote_ifindex) in
vxlan->default_dst is redundant and creates potential data races for
lockless readers.
Furthermore, several fields of struct vxlan_rdst (remote_dev,
remote_port, offloaded, list, rcu, dst_cache) in default_dst were
completely unused. Drop the now-unused remote_dev field from struct
vxlan_rdst.
Replace vxlan->default_dst with a 'struct net_device *lowerdev' pointer
in struct vxlan_dev to track adjacent upper/lower netdev topology under
RTNL, and switch all remaining users over to reading configuration
attributes from vxlan->cfg.
Also update mlx5e_tc_tun_get_remote_ifindex() to read remote_ifindex
from vxlan->cfg under rcu_read_lock().
In vxlan_changelink(), pass lowerdev to vxlan_config_apply() to preserve
needed_headroom and needed_tailroom, and update default FDB entries
(including VNI filter entries) if remote_ifindex changed.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
---
.../mellanox/mlx5/core/en/tc_tun_vxlan.c | 11 +-
drivers/net/vxlan/vxlan_core.c | 163 ++++++++++--------
drivers/net/vxlan/vxlan_mdb.c | 14 +-
drivers/net/vxlan/vxlan_multicast.c | 64 +++----
drivers/net/vxlan/vxlan_private.h | 11 +-
drivers/net/vxlan/vxlan_vnifilter.c | 51 ++++--
include/net/vxlan.h | 3 +-
7 files changed, 178 insertions(+), 139 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
index 7a18a469961db809890d69f7d6d8bc656e560946..467fbe43b89e9bc3d28047a3a17a84495c3875af 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
@@ -241,9 +241,16 @@ static bool mlx5e_tc_tun_encap_info_equal_vxlan(struct mlx5e_encap_key *a,
static int mlx5e_tc_tun_get_remote_ifindex(struct net_device *mirred_dev)
{
const struct vxlan_dev *vxlan = netdev_priv(mirred_dev);
- const struct vxlan_rdst *dst = &vxlan->default_dst;
+ const struct vxlan_config *cfg;
+ int ifindex = 0;
- return dst->remote_ifindex;
+ rcu_read_lock();
+ cfg = rcu_dereference(vxlan->cfg);
+ if (cfg)
+ ifindex = cfg->remote_ifindex;
+ rcu_read_unlock();
+
+ return ifindex;
}
struct mlx5e_tc_tunnel vxlan_tunnel = {
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 338ecddb9542dee1c46e79872b25200d7b249304..8b7558eac049d2f83ab5f68aca2dad62bce9cbc7 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -804,6 +804,7 @@ static int vxlan_fdb_nh_update(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
u32 nhid, struct netlink_ext_ack *extack)
{
struct nexthop *old_nh = rtnl_dereference(fdb->nh);
+ const struct vxlan_config *cfg;
struct nexthop *nh;
int err = -EINVAL;
@@ -832,7 +833,8 @@ static int vxlan_fdb_nh_update(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
}
/* check nexthop group family */
- switch (vxlan->default_dst.remote_ip.sa.sa_family) {
+ cfg = rtnl_dereference(vxlan->cfg);
+ switch (cfg->remote_ip.sa.sa_family) {
case AF_INET:
if (!nexthop_has_v4(nh)) {
err = -EAFNOSUPPORT;
@@ -1249,6 +1251,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
const unsigned char *addr, u16 vid, u16 flags,
bool *notified, struct netlink_ext_ack *extack)
{
+ const struct vxlan_config *cfg;
struct vxlan_dev *vxlan = netdev_priv(dev);
/* struct net *net = dev_net(vxlan->dev); */
union vxlan_addr ip;
@@ -1276,7 +1279,8 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
return -EINVAL;
}
- if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family)
+ cfg = rtnl_dereference(vxlan->cfg);
+ if (cfg->remote_ip.sa.sa_family != ip.sa.sa_family)
return -EAFNOSUPPORT;
spin_lock_bh(&vxlan->hash_lock);
@@ -2318,7 +2322,14 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
skb->dev = dev;
__skb_pull(skb, skb_network_offset(skb));
- if (dst_vxlan->default_dst.remote_ip.sa.sa_family == AF_INET) {
+ rcu_read_lock();
+ dst_cfg = rcu_dereference(dst_vxlan->cfg);
+ if (unlikely(!(dev->flags & IFF_UP))) {
+ kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
+ goto drop;
+ }
+
+ if (dst_cfg->remote_ip.sa.sa_family == AF_INET) {
loopback.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
loopback.sa.sa_family = AF_INET;
#if IS_ENABLED(CONFIG_IPV6)
@@ -2328,13 +2339,6 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
#endif
}
- rcu_read_lock();
- dst_cfg = rcu_dereference(dst_vxlan->cfg);
- if (unlikely(!(dev->flags & IFF_UP))) {
- kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
- goto drop;
- }
-
if ((dst_cfg->flags & VXLAN_F_LEARN) && snoop)
vxlan_snoop(dev, dst_cfg, &loopback, eth_hdr(skb)->h_source, 0, vni);
@@ -2973,10 +2977,14 @@ static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan,
struct vxlan_dev_node *node)
{
- __be32 vni = vxlan->default_dst.remote_vni;
+ const struct vxlan_config *cfg;
+ __be32 vni;
ASSERT_RTNL();
+ cfg = rtnl_dereference(vxlan->cfg);
+ vni = cfg->vni;
+
node->vxlan = vxlan;
hlist_add_head_rcu(&node->hlist, vni_head(vs, vni));
}
@@ -3298,13 +3306,12 @@ static void vxlan_set_multicast_list(struct net_device *dev)
static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_rdst *dst = &vxlan->default_dst;
const struct vxlan_config *cfg;
struct net_device *lowerdev;
cfg = rtnl_dereference(vxlan->cfg);
- lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex);
+ lowerdev = __dev_get_by_index(vxlan->net, cfg->remote_ifindex);
/* This check is different than dev->max_mtu, because it looks at
* the lowerdev->mtu, rather than the static dev->max_mtu
@@ -3633,9 +3640,11 @@ static int vxlan_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_rdst *dst = &vxlan->default_dst;
- struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
- dst->remote_ifindex);
+ const struct vxlan_config *cfg;
+ struct net_device *lowerdev;
+
+ cfg = rtnl_dereference(vxlan->cfg);
+ lowerdev = __dev_get_by_index(vxlan->net, cfg->remote_ifindex);
if (!lowerdev) {
cmd->base.duplex = DUPLEX_UNKNOWN;
@@ -4010,7 +4019,6 @@ static void vxlan_config_apply(struct net_device *dev,
bool changelink)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_rdst *dst = &vxlan->default_dst;
unsigned short needed_headroom = ETH_HLEN;
struct vxlan_config *old_cfg;
int max_mtu = ETH_MAX_MTU;
@@ -4028,13 +4036,7 @@ static void vxlan_config_apply(struct net_device *dev,
vxlan->net = src_net;
}
- dst->remote_vni = new_cfg->vni;
-
- memcpy(&dst->remote_ip, &new_cfg->remote_ip, sizeof(new_cfg->remote_ip));
-
if (lowerdev) {
- dst->remote_ifindex = new_cfg->remote_ifindex;
-
netif_inherit_tso_max(dev, lowerdev);
needed_headroom = lowerdev->hard_header_len;
@@ -4094,10 +4096,8 @@ static int vxlan_dev_create(struct net *net, struct net_device *dev,
struct vxlan_dev *vxlan = netdev_priv(dev);
struct net_device *remote_dev = NULL;
const struct vxlan_config *cfg;
- struct vxlan_rdst *dst;
int err;
- dst = &vxlan->default_dst;
err = vxlan_dev_configure(net, dev, conf, extack);
if (err)
return err;
@@ -4112,8 +4112,8 @@ static int vxlan_dev_create(struct net *net, struct net_device *dev,
return err;
}
- if (dst->remote_ifindex) {
- remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
+ if (cfg->remote_ifindex) {
+ remote_dev = __dev_get_by_index(net, cfg->remote_ifindex);
if (!remote_dev) {
err = -ENODEV;
goto unregister;
@@ -4123,7 +4123,7 @@ static int vxlan_dev_create(struct net *net, struct net_device *dev,
if (err)
goto unregister;
- dst->remote_dev = remote_dev;
+ vxlan->lowerdev = remote_dev;
}
err = rtnl_configure_link(dev, NULL, 0, NULL);
@@ -4131,16 +4131,18 @@ static int vxlan_dev_create(struct net *net, struct net_device *dev,
goto unlink;
/* create an fdb entry for a valid default destination */
- if (!vxlan_addr_any(&dst->remote_ip)) {
+ if (!vxlan_addr_any(&cfg->remote_ip)) {
+ union vxlan_addr rip = cfg->remote_ip;
+
spin_lock_bh(&vxlan->hash_lock);
err = vxlan_fdb_update(vxlan, all_zeros_mac,
- &dst->remote_ip,
+ &rip,
NUD_REACHABLE | NUD_PERMANENT,
NLM_F_EXCL | NLM_F_CREATE,
cfg->dst_port,
- dst->remote_vni,
- dst->remote_vni,
- dst->remote_ifindex,
+ cfg->vni,
+ cfg->vni,
+ cfg->remote_ifindex,
NTF_SELF, 0, true, extack);
spin_unlock_bh(&vxlan->hash_lock);
if (err)
@@ -4552,19 +4554,19 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
{
+ bool lowerdev_changed, rem_ip_changed, change_igmp;
struct vxlan_dev *vxlan = netdev_priv(dev);
- const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
- bool rem_ip_changed, change_igmp;
+ const struct vxlan_config *cfg;
+ struct vxlan_config *new_cfg;
struct net_device *lowerdev;
struct vxlan_config conf;
- struct vxlan_config *new_cfg;
- struct vxlan_rdst *dst;
int err;
+ cfg = rtnl_dereference(vxlan->cfg);
+
if (!rtnl_dev_link_net_capable(dev, vxlan->net))
return -EPERM;
- dst = &vxlan->default_dst;
err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
if (err)
return err;
@@ -4578,23 +4580,23 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
if (!new_cfg)
return -ENOMEM;
- if (dst->remote_dev == lowerdev)
- lowerdev = NULL;
-
- err = netdev_adjacent_change_prepare(dst->remote_dev, lowerdev, dev,
- extack);
- if (err) {
- kfree(new_cfg);
- return err;
+ lowerdev_changed = vxlan->lowerdev != lowerdev;
+ if (lowerdev_changed) {
+ err = netdev_adjacent_change_prepare(vxlan->lowerdev, lowerdev,
+ dev, extack);
+ if (err) {
+ kfree(new_cfg);
+ return err;
+ }
}
- rem_ip_changed = !vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip);
+ rem_ip_changed = !vxlan_addr_equal(&conf.remote_ip, &cfg->remote_ip);
change_igmp = vxlan->dev->flags & IFF_UP &&
(rem_ip_changed ||
- dst->remote_ifindex != conf.remote_ifindex);
+ cfg->remote_ifindex != conf.remote_ifindex);
/* handle default dst entry */
- if (rem_ip_changed) {
+ if (rem_ip_changed || cfg->remote_ifindex != conf.remote_ifindex) {
spin_lock_bh(&vxlan->hash_lock);
if (!vxlan_addr_any(&conf.remote_ip)) {
err = vxlan_fdb_update(vxlan, all_zeros_mac,
@@ -4607,19 +4609,20 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
NTF_SELF, 0, true, extack);
if (err) {
spin_unlock_bh(&vxlan->hash_lock);
- netdev_adjacent_change_abort(dst->remote_dev,
- lowerdev, dev);
+ if (lowerdev_changed)
+ netdev_adjacent_change_abort(vxlan->lowerdev,
+ lowerdev, dev);
kfree(new_cfg);
return err;
}
}
- if (!vxlan_addr_any(&dst->remote_ip))
+ if (!vxlan_addr_any(&cfg->remote_ip))
__vxlan_fdb_delete(vxlan, all_zeros_mac,
- dst->remote_ip,
+ cfg->remote_ip,
cfg->dst_port,
- dst->remote_vni,
- dst->remote_vni,
- dst->remote_ifindex,
+ cfg->vni,
+ cfg->vni,
+ cfg->remote_ifindex,
true);
spin_unlock_bh(&vxlan->hash_lock);
@@ -4627,30 +4630,39 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
* all vnis that were using default remote ip
*/
if (cfg->flags & VXLAN_F_VNIFILTER) {
- err = vxlan_vnilist_update_group(vxlan, &dst->remote_ip,
- &conf.remote_ip, extack);
+ err = vxlan_vnilist_update_group(vxlan, &cfg->remote_ip,
+ &conf.remote_ip,
+ cfg->remote_ifindex,
+ conf.remote_ifindex,
+ extack);
if (err) {
- netdev_adjacent_change_abort(dst->remote_dev,
- lowerdev, dev);
+ if (lowerdev_changed)
+ netdev_adjacent_change_abort(vxlan->lowerdev,
+ lowerdev, dev);
kfree(new_cfg);
return err;
}
}
}
- if (change_igmp && vxlan_addr_multicast(&dst->remote_ip))
+ if (change_igmp && vxlan_addr_multicast(&cfg->remote_ip))
err = vxlan_multicast_leave(vxlan);
if (netif_running(dev) && conf.age_interval != cfg->age_interval)
mod_timer(&vxlan->age_timer, jiffies);
- netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev);
- if (lowerdev && lowerdev != dst->remote_dev)
- dst->remote_dev = lowerdev;
+ if (lowerdev_changed) {
+ if (lowerdev)
+ netdev_adjacent_change_commit(vxlan->lowerdev, lowerdev,
+ dev);
+ else
+ netdev_upper_dev_unlink(vxlan->lowerdev, dev);
+ vxlan->lowerdev = lowerdev;
+ }
vxlan_config_apply(dev, new_cfg, lowerdev, vxlan->net, true);
if (!err && change_igmp &&
- vxlan_addr_multicast(&dst->remote_ip))
+ vxlan_addr_multicast(&new_cfg->remote_ip))
err = vxlan_multicast_join(vxlan);
return err;
@@ -4665,8 +4677,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
list_del(&vxlan->next);
unregister_netdevice_queue(dev, head);
- if (vxlan->default_dst.remote_dev)
- netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev);
+ if (vxlan->lowerdev)
+ netdev_upper_dev_unlink(vxlan->lowerdev, dev);
}
static size_t vxlan_get_size(const struct net_device *dev)
@@ -4710,30 +4722,29 @@ static size_t vxlan_get_size(const struct net_device *dev)
static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
const struct vxlan_dev *vxlan = netdev_priv(dev);
- const struct vxlan_rdst *dst = &vxlan->default_dst;
struct ifla_vxlan_port_range ports;
const struct vxlan_config *cfg;
cfg = rtnl_dereference(vxlan->cfg);
- if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni)))
+ if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(cfg->vni)))
goto nla_put_failure;
- if (!vxlan_addr_any(&dst->remote_ip)) {
- if (dst->remote_ip.sa.sa_family == AF_INET) {
+ if (!vxlan_addr_any(&cfg->remote_ip)) {
+ if (cfg->remote_ip.sa.sa_family == AF_INET) {
if (nla_put_in_addr(skb, IFLA_VXLAN_GROUP,
- dst->remote_ip.sin.sin_addr.s_addr))
+ cfg->remote_ip.sin.sin_addr.s_addr))
goto nla_put_failure;
#if IS_ENABLED(CONFIG_IPV6)
} else {
if (nla_put_in6_addr(skb, IFLA_VXLAN_GROUP6,
- &dst->remote_ip.sin6.sin6_addr))
+ &cfg->remote_ip.sin6.sin6_addr))
goto nla_put_failure;
#endif
}
}
- if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex))
+ if (cfg->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, cfg->remote_ifindex))
goto nla_put_failure;
if (!vxlan_addr_any(&cfg->saddr)) {
@@ -4848,7 +4859,7 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
LIST_HEAD(list_kill);
list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
- struct vxlan_rdst *dst = &vxlan->default_dst;
+ const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
/* In case we created vxlan device with carrier
* and we loose the carrier due to module unload
@@ -4856,7 +4867,7 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
* cases, it's not necessary and remote_ifindex
* is 0 here, so no matches.
*/
- if (dst->remote_ifindex == dev->ifindex)
+ if (cfg->remote_ifindex == dev->ifindex)
vxlan_dellink(vxlan->dev, &list_kill);
}
diff --git a/drivers/net/vxlan/vxlan_mdb.c b/drivers/net/vxlan/vxlan_mdb.c
index 4ae6369ed4e35e307565f91d0706970f460af552..c1a0551990555ce3e1dca81a9b5df7196a2a5fdf 100644
--- a/drivers/net/vxlan/vxlan_mdb.c
+++ b/drivers/net/vxlan/vxlan_mdb.c
@@ -195,7 +195,7 @@ static int vxlan_mdb_entry_info_fill(const struct vxlan_dev *vxlan,
be16_to_cpu(rd->remote_port)))
goto nest_err;
- if (rd->remote_vni != vxlan->default_dst.remote_vni &&
+ if (rd->remote_vni != cfg->vni &&
nla_put_u32(skb, MDBA_MDB_EATTR_VNI, be32_to_cpu(rd->remote_vni)))
goto nest_err;
@@ -620,12 +620,12 @@ static int vxlan_mdb_config_init(struct vxlan_mdb_config *cfg,
memset(cfg, 0, sizeof(*cfg));
cfg->vxlan = vxlan;
- cfg->group.vni = vxlan->default_dst.remote_vni;
+ cfg->group.vni = vcfg->vni;
INIT_LIST_HEAD(&cfg->src_list);
cfg->nlflags = nlmsg_flags;
cfg->filter_mode = MCAST_EXCLUDE;
cfg->rt_protocol = RTPROT_STATIC;
- cfg->remote_vni = vxlan->default_dst.remote_vni;
+ cfg->remote_vni = vcfg->vni;
cfg->remote_port = vcfg->dst_port;
if (entry->ifindex != dev->ifindex) {
@@ -986,7 +986,7 @@ vxlan_mdb_nlmsg_remote_size(const struct vxlan_dev *vxlan,
if (rd->remote_port && rd->remote_port != cfg->dst_port)
nlmsg_size += nla_total_size(sizeof(u16));
/* MDBA_MDB_EATTR_VNI */
- if (rd->remote_vni != vxlan->default_dst.remote_vni)
+ if (rd->remote_vni != cfg->vni)
nlmsg_size += nla_total_size(sizeof(u32));
/* MDBA_MDB_EATTR_IFINDEX */
if (rd->remote_ifindex)
@@ -1488,11 +1488,13 @@ static int vxlan_mdb_get_parse(struct net_device *dev, struct nlattr *tb[],
{
struct br_mdb_entry *entry = nla_data(tb[MDBA_GET_ENTRY]);
struct nlattr *mdbe_attrs[MDBE_ATTR_MAX + 1];
+ const struct vxlan_config *cfg;
struct vxlan_dev *vxlan = netdev_priv(dev);
int err;
+ cfg = rtnl_dereference(vxlan->cfg);
memset(group, 0, sizeof(*group));
- group->vni = vxlan->default_dst.remote_vni;
+ group->vni = cfg->vni;
if (!tb[MDBA_GET_ENTRY_ATTRS]) {
vxlan_mdb_group_set(group, entry, NULL);
@@ -1641,7 +1643,7 @@ struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan,
* entries are stored with the VNI of the VXLAN device.
*/
if (!(cfg->flags & VXLAN_F_COLLECT_METADATA))
- src_vni = vxlan->default_dst.remote_vni;
+ src_vni = cfg->vni;
memset(&group, 0, sizeof(group));
group.vni = src_vni;
diff --git a/drivers/net/vxlan/vxlan_multicast.c b/drivers/net/vxlan/vxlan_multicast.c
index e2cf10da274f1b608d8bb5020d2b87ebfedeff46..6fcc4a36734361c28563d487d4ec108ca22d9e4f 100644
--- a/drivers/net/vxlan/vxlan_multicast.c
+++ b/drivers/net/vxlan/vxlan_multicast.c
@@ -14,11 +14,12 @@
/* Update multicast group membership when first VNI on
* multicast address is brought up
*/
-int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
+int vxlan_igmp_join(struct vxlan_dev *vxlan, const union vxlan_addr *rip,
int rifindex)
{
- union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip);
- int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex);
+ const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
+ const union vxlan_addr *ip = (rip ? : &cfg->remote_ip);
+ int ifindex = (rifindex ? : cfg->remote_ifindex);
int ret = -EINVAL;
struct sock *sk;
@@ -47,11 +48,12 @@ int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
return ret;
}
-int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
+int vxlan_igmp_leave(struct vxlan_dev *vxlan, const union vxlan_addr *rip,
int rifindex)
{
- union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip);
- int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex);
+ const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
+ const union vxlan_addr *ip = (rip ? : &cfg->remote_ip);
+ int ifindex = (rifindex ? : cfg->remote_ifindex);
int ret = -EINVAL;
struct sock *sk;
@@ -80,8 +82,8 @@ int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
return ret;
}
-static bool vxlan_group_used_match(union vxlan_addr *ip, int ifindex,
- union vxlan_addr *rip, int rifindex)
+static bool vxlan_group_used_match(const union vxlan_addr *ip, int ifindex,
+ const union vxlan_addr *rip, int rifindex)
{
if (!vxlan_addr_multicast(rip))
return false;
@@ -96,14 +98,16 @@ static bool vxlan_group_used_match(union vxlan_addr *ip, int ifindex,
}
static bool vxlan_group_used_by_vnifilter(struct vxlan_dev *vxlan,
- union vxlan_addr *ip, int ifindex)
+ const struct vxlan_config *cfg,
+ const union vxlan_addr *ip,
+ int ifindex)
{
struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
struct vxlan_vni_node *v, *tmp;
if (vxlan_group_used_match(ip, ifindex,
- &vxlan->default_dst.remote_ip,
- vxlan->default_dst.remote_ifindex))
+ &cfg->remote_ip,
+ cfg->remote_ifindex))
return true;
list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
@@ -112,7 +116,7 @@ static bool vxlan_group_used_by_vnifilter(struct vxlan_dev *vxlan,
if (vxlan_group_used_match(ip, ifindex,
&v->remote_ip,
- vxlan->default_dst.remote_ifindex))
+ cfg->remote_ifindex))
return true;
}
@@ -121,16 +125,17 @@ static bool vxlan_group_used_by_vnifilter(struct vxlan_dev *vxlan,
/* See if multicast group is already in use by other ID */
bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
- __be32 vni, union vxlan_addr *rip, int rifindex)
+ __be32 vni, const union vxlan_addr *rip, int rifindex)
{
- union vxlan_addr *ip = (rip ? : &dev->default_dst.remote_ip);
- int ifindex = (rifindex ? : dev->default_dst.remote_ifindex);
+ const struct vxlan_config *dev_cfg = rtnl_dereference(dev->cfg);
+ const union vxlan_addr *ip = (rip ? : &dev_cfg->remote_ip);
+ int ifindex = (rifindex ? : dev_cfg->remote_ifindex);
struct vxlan_dev *vxlan;
struct vxlan_sock *sock4;
#if IS_ENABLED(CONFIG_IPV6)
struct vxlan_sock *sock6;
#endif
- unsigned short family = dev->default_dst.remote_ip.sa.sa_family;
+ unsigned short family = dev_cfg->remote_ip.sa.sa_family;
sock4 = rtnl_dereference(dev->vn4_sock);
@@ -163,12 +168,12 @@ bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
cfg = rtnl_dereference(vxlan->cfg);
if (cfg->flags & VXLAN_F_VNIFILTER) {
- if (!vxlan_group_used_by_vnifilter(vxlan, ip, ifindex))
+ if (!vxlan_group_used_by_vnifilter(vxlan, cfg, ip, ifindex))
continue;
} else {
if (!vxlan_group_used_match(ip, ifindex,
- &vxlan->default_dst.remote_ip,
- vxlan->default_dst.remote_ifindex))
+ &cfg->remote_ip,
+ cfg->remote_ifindex))
continue;
}
@@ -178,7 +183,8 @@ bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
return false;
}
-static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan)
+static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan,
+ const struct vxlan_config *cfg)
{
struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
struct vxlan_vni_node *v, *tmp, *vgood = NULL;
@@ -189,7 +195,7 @@ static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan)
continue;
/* skip if address is same as default address */
if (vxlan_addr_equal(&v->remote_ip,
- &vxlan->default_dst.remote_ip))
+ &cfg->remote_ip))
continue;
ret = vxlan_igmp_join(vxlan, &v->remote_ip, 0);
if (ret == -EADDRINUSE)
@@ -204,7 +210,7 @@ static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan)
if (!vxlan_addr_multicast(&v->remote_ip))
continue;
if (vxlan_addr_equal(&v->remote_ip,
- &vxlan->default_dst.remote_ip))
+ &cfg->remote_ip))
continue;
vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
if (v == vgood)
@@ -240,9 +246,9 @@ int vxlan_multicast_join(struct vxlan_dev *vxlan)
const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
int ret = 0;
- if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
- ret = vxlan_igmp_join(vxlan, &vxlan->default_dst.remote_ip,
- vxlan->default_dst.remote_ifindex);
+ if (vxlan_addr_multicast(&cfg->remote_ip)) {
+ ret = vxlan_igmp_join(vxlan, &cfg->remote_ip,
+ cfg->remote_ifindex);
if (ret == -EADDRINUSE)
ret = 0;
if (ret)
@@ -250,7 +256,7 @@ int vxlan_multicast_join(struct vxlan_dev *vxlan)
}
if (cfg->flags & VXLAN_F_VNIFILTER)
- return vxlan_multicast_join_vnigrp(vxlan);
+ return vxlan_multicast_join_vnigrp(vxlan, cfg);
return 0;
}
@@ -261,10 +267,10 @@ int vxlan_multicast_leave(struct vxlan_dev *vxlan)
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
int ret = 0;
- if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
+ if (vxlan_addr_multicast(&cfg->remote_ip) &&
!vxlan_group_used(vn, vxlan, 0, NULL, 0)) {
- ret = vxlan_igmp_leave(vxlan, &vxlan->default_dst.remote_ip,
- vxlan->default_dst.remote_ifindex);
+ ret = vxlan_igmp_leave(vxlan, &cfg->remote_ip,
+ cfg->remote_ifindex);
if (ret)
return ret;
}
diff --git a/drivers/net/vxlan/vxlan_private.h b/drivers/net/vxlan/vxlan_private.h
index ab7216c4e41011b99f8bf72de50fc2230b43c405..6ba0fb6400d102bdb58c2717d0d101e4b11ebb04 100644
--- a/drivers/net/vxlan/vxlan_private.h
+++ b/drivers/net/vxlan/vxlan_private.h
@@ -216,8 +216,9 @@ void vxlan_vs_add_vnigrp(struct vxlan_dev *vxlan,
bool ipv6);
void vxlan_vs_del_vnigrp(struct vxlan_dev *vxlan);
int vxlan_vnilist_update_group(struct vxlan_dev *vxlan,
- union vxlan_addr *old_remote_ip,
- union vxlan_addr *new_remote_ip,
+ const union vxlan_addr *old_remote_ip,
+ const union vxlan_addr *new_remote_ip,
+ u32 old_ifindex, u32 new_ifindex,
struct netlink_ext_ack *extack);
@@ -225,10 +226,10 @@ int vxlan_vnilist_update_group(struct vxlan_dev *vxlan,
int vxlan_multicast_join(struct vxlan_dev *vxlan);
int vxlan_multicast_leave(struct vxlan_dev *vxlan);
bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
- __be32 vni, union vxlan_addr *rip, int rifindex);
-int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
+ __be32 vni, const union vxlan_addr *rip, int rifindex);
+int vxlan_igmp_join(struct vxlan_dev *vxlan, const union vxlan_addr *rip,
int rifindex);
-int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
+int vxlan_igmp_leave(struct vxlan_dev *vxlan, const union vxlan_addr *rip,
int rifindex);
/* vxlan_mdb.c */
diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
index 6a2d0a69d7be18d49015cc8e32d10b9533198b7d..55a07c20e7649d262e9f2c5c649a17da2649e1c5 100644
--- a/drivers/net/vxlan/vxlan_vnifilter.c
+++ b/drivers/net/vxlan/vxlan_vnifilter.c
@@ -487,24 +487,31 @@ static const struct nla_policy vni_filter_policy[VXLAN_VNIFILTER_MAX + 1] = {
};
static int vxlan_update_default_fdb_entry(struct vxlan_dev *vxlan, __be32 vni,
- union vxlan_addr *old_remote_ip,
- union vxlan_addr *remote_ip,
+ const union vxlan_addr *old_remote_ip,
+ const union vxlan_addr *remote_ip,
+ u32 old_ifindex, u32 new_ifindex,
struct netlink_ext_ack *extack)
{
const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
- struct vxlan_rdst *dst = &vxlan->default_dst;
int err = 0;
+ if (old_remote_ip && remote_ip &&
+ vxlan_addr_equal(old_remote_ip, remote_ip) &&
+ old_ifindex == new_ifindex)
+ return 0;
+
spin_lock_bh(&vxlan->hash_lock);
if (remote_ip && !vxlan_addr_any(remote_ip)) {
+ union vxlan_addr rip = *remote_ip;
+
err = vxlan_fdb_update(vxlan, all_zeros_mac,
- remote_ip,
+ &rip,
NUD_REACHABLE | NUD_PERMANENT,
NLM_F_APPEND | NLM_F_CREATE,
cfg->dst_port,
vni,
vni,
- dst->remote_ifindex,
+ new_ifindex,
NTF_SELF, 0, true, extack);
if (err) {
spin_unlock_bh(&vxlan->hash_lock);
@@ -517,7 +524,7 @@ static int vxlan_update_default_fdb_entry(struct vxlan_dev *vxlan, __be32 vni,
*old_remote_ip,
cfg->dst_port,
vni, vni,
- dst->remote_ifindex,
+ old_ifindex,
true);
}
spin_unlock_bh(&vxlan->hash_lock);
@@ -532,8 +539,8 @@ static int vxlan_vni_update_group(struct vxlan_dev *vxlan,
struct netlink_ext_ack *extack)
{
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
- struct vxlan_rdst *dst = &vxlan->default_dst;
- union vxlan_addr *newrip = NULL, *oldrip = NULL;
+ const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
+ const union vxlan_addr *newrip = NULL, *oldrip = NULL;
union vxlan_addr old_remote_ip;
int ret = 0;
@@ -545,8 +552,8 @@ static int vxlan_vni_update_group(struct vxlan_dev *vxlan,
if (group && !vxlan_addr_any(group)) {
newrip = group;
} else {
- if (!vxlan_addr_any(&dst->remote_ip))
- newrip = &dst->remote_ip;
+ if (!vxlan_addr_any(&cfg->remote_ip))
+ newrip = &cfg->remote_ip;
}
/* if old rip exists, and no newrip,
@@ -563,6 +570,8 @@ static int vxlan_vni_update_group(struct vxlan_dev *vxlan,
ret = vxlan_update_default_fdb_entry(vxlan, vninode->vni,
oldrip, newrip,
+ cfg->remote_ifindex,
+ cfg->remote_ifindex,
extack);
if (ret)
goto out;
@@ -574,7 +583,7 @@ static int vxlan_vni_update_group(struct vxlan_dev *vxlan,
if (vxlan_addr_multicast(&old_remote_ip) &&
!vxlan_group_used(vn, vxlan, vninode->vni,
&old_remote_ip,
- vxlan->default_dst.remote_ifindex)) {
+ cfg->remote_ifindex)) {
ret = vxlan_igmp_leave(vxlan, &old_remote_ip,
0);
if (ret)
@@ -598,8 +607,9 @@ static int vxlan_vni_update_group(struct vxlan_dev *vxlan,
}
int vxlan_vnilist_update_group(struct vxlan_dev *vxlan,
- union vxlan_addr *old_remote_ip,
- union vxlan_addr *new_remote_ip,
+ const union vxlan_addr *old_remote_ip,
+ const union vxlan_addr *new_remote_ip,
+ u32 old_ifindex, u32 new_ifindex,
struct netlink_ext_ack *extack)
{
struct list_head *headp, *hpos;
@@ -616,6 +626,8 @@ int vxlan_vnilist_update_group(struct vxlan_dev *vxlan,
ret = vxlan_update_default_fdb_entry(vxlan, vent->vni,
old_remote_ip,
new_remote_ip,
+ old_ifindex,
+ new_ifindex,
extack);
if (ret)
return ret;
@@ -630,20 +642,19 @@ static void vxlan_vni_delete_group(struct vxlan_dev *vxlan,
{
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
const struct vxlan_config *cfg = rtnl_dereference(vxlan->cfg);
- struct vxlan_rdst *dst = &vxlan->default_dst;
/* if per vni remote_ip not present, delete the
* default dst remote_ip previously added for this vni
*/
if (!vxlan_addr_any(&vninode->remote_ip) ||
- !vxlan_addr_any(&dst->remote_ip)) {
+ !vxlan_addr_any(&cfg->remote_ip)) {
spin_lock_bh(&vxlan->hash_lock);
__vxlan_fdb_delete(vxlan, all_zeros_mac,
(vxlan_addr_any(&vninode->remote_ip) ?
- dst->remote_ip : vninode->remote_ip),
+ cfg->remote_ip : vninode->remote_ip),
cfg->dst_port,
vninode->vni, vninode->vni,
- dst->remote_ifindex,
+ cfg->remote_ifindex,
true);
spin_unlock_bh(&vxlan->hash_lock);
}
@@ -652,7 +663,7 @@ static void vxlan_vni_delete_group(struct vxlan_dev *vxlan,
if (vxlan_addr_multicast(&vninode->remote_ip) &&
!vxlan_group_used(vn, vxlan, vninode->vni,
&vninode->remote_ip,
- dst->remote_ifindex)) {
+ cfg->remote_ifindex)) {
vxlan_igmp_leave(vxlan, &vninode->remote_ip, 0);
}
}
@@ -863,6 +874,7 @@ static int vxlan_process_vni_filter(struct vxlan_dev *vxlan,
int cmd, struct netlink_ext_ack *extack)
{
struct nlattr *vattrs[VXLAN_VNIFILTER_ENTRY_MAX + 1];
+ const struct vxlan_config *cfg;
u32 vni_start = 0, vni_end = 0;
union vxlan_addr group;
int err;
@@ -900,7 +912,8 @@ static int vxlan_process_vni_filter(struct vxlan_dev *vxlan,
memset(&group, 0, sizeof(group));
}
- if (vxlan_addr_multicast(&group) && !vxlan->default_dst.remote_ifindex) {
+ cfg = rtnl_dereference(vxlan->cfg);
+ if (vxlan_addr_multicast(&group) && !cfg->remote_ifindex) {
NL_SET_ERR_MSG(extack,
"Local interface required for multicast remote group");
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 7ced743ec8816d412bb14ec7ee7b422e97c38895..c3c9f2ccc3d1bfdf661312482856e0714e9ea3a6 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -204,7 +204,6 @@ struct vxlan_rdst {
u8 offloaded:1;
__be32 remote_vni;
u32 remote_ifindex;
- struct net_device *remote_dev;
struct list_head list;
struct rcu_head rcu;
struct dst_cache dst_cache;
@@ -295,7 +294,7 @@ struct vxlan_dev {
#endif
struct net_device *dev;
struct net *net; /* netns for packet i/o */
- struct vxlan_rdst default_dst; /* default destination */
+ struct net_device *lowerdev;
struct timer_list age_timer;
spinlock_t hash_lock;
--
2.55.0.1007.g17ff1f9808-goog
next prev parent reply other threads:[~2026-09-11 6:22 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 6:21 [PATCH v3 net-next 0/6] vxlan: convert configuration to RCU and enable lockless dumps Eric Dumazet
2026-09-11 6:21 ` [PATCH v3 net-next 1/6] vxlan: vnifilter: use list_for_each_entry_rcu() in vxlan_vnifilter_dump_dev() Eric Dumazet
2026-09-11 6:21 ` [PATCH v3 net-next 2/6] vxlan: pass vxlan_config pointer to helper functions Eric Dumazet
2026-09-11 6:21 ` [PATCH v3 net-next 3/6] vxlan: move VXLAN_F_MDB to struct vxlan_dev flags Eric Dumazet
2026-09-11 6:21 ` [PATCH v3 net-next 4/6] vxlan: convert configuration to RCU protection Eric Dumazet
2026-09-11 6:21 ` Eric Dumazet [this message]
2026-09-11 6:22 ` [PATCH v3 net-next 6/6] vxlan: no longer rely on RTNL in vxlan_fill_info() Eric Dumazet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260911062200.231316-6-edumazet@google.com \
--to=edumazet@google.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.