@@ -3566,25 +3566,28 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
3566
3566
{
3567
3567
struct vxlan_net * vn = net_generic (net , vxlan_net_id );
3568
3568
struct vxlan_dev * vxlan = netdev_priv (dev );
3569
+ struct net_device * remote_dev = NULL ;
3569
3570
struct vxlan_fdb * f = NULL ;
3570
3571
bool unregister = false;
3572
+ struct vxlan_rdst * dst ;
3571
3573
int err ;
3572
3574
3575
+ dst = & vxlan -> default_dst ;
3573
3576
err = vxlan_dev_configure (net , dev , conf , false, extack );
3574
3577
if (err )
3575
3578
return err ;
3576
3579
3577
3580
dev -> ethtool_ops = & vxlan_ethtool_ops ;
3578
3581
3579
3582
/* create an fdb entry for a valid default destination */
3580
- if (!vxlan_addr_any (& vxlan -> default_dst . remote_ip )) {
3583
+ if (!vxlan_addr_any (& dst -> remote_ip )) {
3581
3584
err = vxlan_fdb_create (vxlan , all_zeros_mac ,
3582
- & vxlan -> default_dst . remote_ip ,
3585
+ & dst -> remote_ip ,
3583
3586
NUD_REACHABLE | NUD_PERMANENT ,
3584
3587
vxlan -> cfg .dst_port ,
3585
- vxlan -> default_dst . remote_vni ,
3586
- vxlan -> default_dst . remote_vni ,
3587
- vxlan -> default_dst . remote_ifindex ,
3588
+ dst -> remote_vni ,
3589
+ dst -> remote_vni ,
3590
+ dst -> remote_ifindex ,
3588
3591
NTF_SELF , & f );
3589
3592
if (err )
3590
3593
return err ;
@@ -3595,26 +3598,41 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
3595
3598
goto errout ;
3596
3599
unregister = true;
3597
3600
3601
+ if (dst -> remote_ifindex ) {
3602
+ remote_dev = __dev_get_by_index (net , dst -> remote_ifindex );
3603
+ if (!remote_dev )
3604
+ goto errout ;
3605
+
3606
+ err = netdev_upper_dev_link (remote_dev , dev , extack );
3607
+ if (err )
3608
+ goto errout ;
3609
+ }
3610
+
3598
3611
err = rtnl_configure_link (dev , NULL );
3599
3612
if (err )
3600
- goto errout ;
3613
+ goto unlink ;
3601
3614
3602
3615
if (f ) {
3603
- vxlan_fdb_insert (vxlan , all_zeros_mac ,
3604
- vxlan -> default_dst .remote_vni , f );
3616
+ vxlan_fdb_insert (vxlan , all_zeros_mac , dst -> remote_vni , f );
3605
3617
3606
3618
/* notify default fdb entry */
3607
3619
err = vxlan_fdb_notify (vxlan , f , first_remote_rtnl (f ),
3608
3620
RTM_NEWNEIGH , true, extack );
3609
3621
if (err ) {
3610
3622
vxlan_fdb_destroy (vxlan , f , false, false);
3623
+ if (remote_dev )
3624
+ netdev_upper_dev_unlink (remote_dev , dev );
3611
3625
goto unregister ;
3612
3626
}
3613
3627
}
3614
3628
3615
3629
list_add (& vxlan -> next , & vn -> vxlan_list );
3630
+ if (remote_dev )
3631
+ dst -> remote_dev = remote_dev ;
3616
3632
return 0 ;
3617
-
3633
+ unlink :
3634
+ if (remote_dev )
3635
+ netdev_upper_dev_unlink (remote_dev , dev );
3618
3636
errout :
3619
3637
/* unregister_netdevice() destroys the default FDB entry with deletion
3620
3638
* notification. But the addition notification was not sent yet, so
@@ -3932,11 +3950,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3932
3950
struct netlink_ext_ack * extack )
3933
3951
{
3934
3952
struct vxlan_dev * vxlan = netdev_priv (dev );
3935
- struct vxlan_rdst * dst = & vxlan -> default_dst ;
3936
3953
struct net_device * lowerdev ;
3937
3954
struct vxlan_config conf ;
3955
+ struct vxlan_rdst * dst ;
3938
3956
int err ;
3939
3957
3958
+ dst = & vxlan -> default_dst ;
3940
3959
err = vxlan_nl2conf (tb , data , dev , & conf , true, extack );
3941
3960
if (err )
3942
3961
return err ;
@@ -3946,6 +3965,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3946
3965
if (err )
3947
3966
return err ;
3948
3967
3968
+ err = netdev_adjacent_change_prepare (dst -> remote_dev , lowerdev , dev ,
3969
+ extack );
3970
+ if (err )
3971
+ return err ;
3972
+
3949
3973
/* handle default dst entry */
3950
3974
if (!vxlan_addr_equal (& conf .remote_ip , & dst -> remote_ip )) {
3951
3975
u32 hash_index = fdb_head_index (vxlan , all_zeros_mac , conf .vni );
@@ -3962,6 +3986,8 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3962
3986
NTF_SELF , true, extack );
3963
3987
if (err ) {
3964
3988
spin_unlock_bh (& vxlan -> hash_lock [hash_index ]);
3989
+ netdev_adjacent_change_abort (dst -> remote_dev ,
3990
+ lowerdev , dev );
3965
3991
return err ;
3966
3992
}
3967
3993
}
@@ -3979,6 +4005,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
3979
4005
if (conf .age_interval != vxlan -> cfg .age_interval )
3980
4006
mod_timer (& vxlan -> age_timer , jiffies );
3981
4007
4008
+ netdev_adjacent_change_commit (dst -> remote_dev , lowerdev , dev );
4009
+ if (lowerdev && lowerdev != dst -> remote_dev )
4010
+ dst -> remote_dev = lowerdev ;
4011
+
4012
+ netdev_update_lockdep_key (lowerdev );
3982
4013
vxlan_config_apply (dev , & conf , lowerdev , vxlan -> net , true);
3983
4014
return 0 ;
3984
4015
}
@@ -3991,6 +4022,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
3991
4022
3992
4023
list_del (& vxlan -> next );
3993
4024
unregister_netdevice_queue (dev , head );
4025
+ if (vxlan -> default_dst .remote_dev )
4026
+ netdev_upper_dev_unlink (vxlan -> default_dst .remote_dev , dev );
3994
4027
}
3995
4028
3996
4029
static size_t vxlan_get_size (const struct net_device * dev )
0 commit comments