Skip to content

Commit 0241b83

Browse files
roopa-prabhudavem330
authored andcommitted
vxlan: fix default fdb entry netlink notify ordering during netdev create
Problem: In vxlan_newlink, a default fdb entry is added before register_netdev. The default fdb creation function also notifies user-space of the fdb entry on the vxlan device which user-space does not know about yet. (RTM_NEWNEIGH goes before RTM_NEWLINK for the same ifindex). This patch fixes the user-space netlink notification ordering issue with the following changes: - decouple fdb notify from fdb create. - Move fdb notify after register_netdev. - Call rtnl_configure_link in vxlan newlink handler to notify userspace about the newlink before fdb notify and hence avoiding the user-space race. Fixes: afbd8ba ("vxlan: add implicit fdb entry for default destination") Signed-off-by: Roopa Prabhu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4c2438b commit 0241b83

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

drivers/net/vxlan.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3197,6 +3197,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
31973197
{
31983198
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
31993199
struct vxlan_dev *vxlan = netdev_priv(dev);
3200+
struct vxlan_fdb *f = NULL;
32003201
int err;
32013202

32023203
err = vxlan_dev_configure(net, dev, conf, false, extack);
@@ -3207,27 +3208,38 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
32073208

32083209
/* create an fdb entry for a valid default destination */
32093210
if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
3210-
err = vxlan_fdb_update(vxlan, all_zeros_mac,
3211+
err = vxlan_fdb_create(vxlan, all_zeros_mac,
32113212
&vxlan->default_dst.remote_ip,
32123213
NUD_REACHABLE | NUD_PERMANENT,
3213-
NLM_F_EXCL | NLM_F_CREATE,
32143214
vxlan->cfg.dst_port,
32153215
vxlan->default_dst.remote_vni,
32163216
vxlan->default_dst.remote_vni,
32173217
vxlan->default_dst.remote_ifindex,
3218-
NTF_SELF);
3218+
NTF_SELF, &f);
32193219
if (err)
32203220
return err;
32213221
}
32223222

32233223
err = register_netdevice(dev);
3224+
if (err)
3225+
goto errout;
3226+
3227+
err = rtnl_configure_link(dev, NULL);
32243228
if (err) {
3225-
vxlan_fdb_delete_default(vxlan, vxlan->default_dst.remote_vni);
3226-
return err;
3229+
unregister_netdevice(dev);
3230+
goto errout;
32273231
}
32283232

3233+
/* notify default fdb entry */
3234+
if (f)
3235+
vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH);
3236+
32293237
list_add(&vxlan->next, &vn->vxlan_list);
32303238
return 0;
3239+
errout:
3240+
if (f)
3241+
vxlan_fdb_destroy(vxlan, f, false);
3242+
return err;
32313243
}
32323244

32333245
static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
@@ -3462,6 +3474,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
34623474
struct vxlan_rdst *dst = &vxlan->default_dst;
34633475
struct vxlan_rdst old_dst;
34643476
struct vxlan_config conf;
3477+
struct vxlan_fdb *f = NULL;
34653478
int err;
34663479

34673480
err = vxlan_nl2conf(tb, data,
@@ -3487,19 +3500,19 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
34873500
old_dst.remote_ifindex, 0);
34883501

34893502
if (!vxlan_addr_any(&dst->remote_ip)) {
3490-
err = vxlan_fdb_update(vxlan, all_zeros_mac,
3503+
err = vxlan_fdb_create(vxlan, all_zeros_mac,
34913504
&dst->remote_ip,
34923505
NUD_REACHABLE | NUD_PERMANENT,
3493-
NLM_F_CREATE | NLM_F_APPEND,
34943506
vxlan->cfg.dst_port,
34953507
dst->remote_vni,
34963508
dst->remote_vni,
34973509
dst->remote_ifindex,
3498-
NTF_SELF);
3510+
NTF_SELF, &f);
34993511
if (err) {
35003512
spin_unlock_bh(&vxlan->hash_lock);
35013513
return err;
35023514
}
3515+
vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH);
35033516
}
35043517
spin_unlock_bh(&vxlan->hash_lock);
35053518
}

0 commit comments

Comments
 (0)