@@ -81,7 +81,7 @@ struct vxlan_fdb {
81
81
u16 flags ; /* see ndm_flags and below */
82
82
struct list_head nh_list ;
83
83
struct nexthop __rcu * nh ;
84
- struct vxlan_dev * vdev ;
84
+ struct vxlan_dev __rcu * vdev ;
85
85
};
86
86
87
87
#define NTF_VXLAN_ADDED_BY_USER 0x100
@@ -837,7 +837,7 @@ static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
837
837
f -> updated = f -> used = jiffies ;
838
838
f -> vni = src_vni ;
839
839
f -> nh = NULL ;
840
- f -> vdev = vxlan ;
840
+ RCU_INIT_POINTER ( f -> vdev , vxlan ) ;
841
841
INIT_LIST_HEAD (& f -> nh_list );
842
842
INIT_LIST_HEAD (& f -> remotes );
843
843
memcpy (f -> eth_addr , mac , ETH_ALEN );
@@ -963,7 +963,7 @@ static void __vxlan_fdb_free(struct vxlan_fdb *f)
963
963
nh = rcu_dereference_raw (f -> nh );
964
964
if (nh ) {
965
965
rcu_assign_pointer (f -> nh , NULL );
966
- list_del_rcu ( & f -> nh_list );
966
+ rcu_assign_pointer ( f -> vdev , NULL );
967
967
nexthop_put (nh );
968
968
}
969
969
@@ -1000,7 +1000,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
1000
1000
}
1001
1001
1002
1002
hlist_del_rcu (& f -> hlist );
1003
- f -> vdev = NULL ;
1003
+ list_del_rcu ( & f -> nh_list ) ;
1004
1004
call_rcu (& f -> rcu , vxlan_fdb_free );
1005
1005
}
1006
1006
@@ -4615,17 +4615,35 @@ static struct notifier_block vxlan_switchdev_notifier_block __read_mostly = {
4615
4615
.notifier_call = vxlan_switchdev_event ,
4616
4616
};
4617
4617
4618
+ static void vxlan_fdb_nh_flush (struct nexthop * nh )
4619
+ {
4620
+ struct vxlan_fdb * fdb ;
4621
+ struct vxlan_dev * vxlan ;
4622
+ u32 hash_index ;
4623
+
4624
+ rcu_read_lock ();
4625
+ list_for_each_entry_rcu (fdb , & nh -> fdb_list , nh_list ) {
4626
+ vxlan = rcu_dereference (fdb -> vdev );
4627
+ WARN_ON (!vxlan );
4628
+ hash_index = fdb_head_index (vxlan , fdb -> eth_addr ,
4629
+ vxlan -> default_dst .remote_vni );
4630
+ spin_lock_bh (& vxlan -> hash_lock [hash_index ]);
4631
+ if (!hlist_unhashed (& fdb -> hlist ))
4632
+ vxlan_fdb_destroy (vxlan , fdb , false, false);
4633
+ spin_unlock_bh (& vxlan -> hash_lock [hash_index ]);
4634
+ }
4635
+ rcu_read_unlock ();
4636
+ }
4637
+
4618
4638
static int vxlan_nexthop_event (struct notifier_block * nb ,
4619
4639
unsigned long event , void * ptr )
4620
4640
{
4621
4641
struct nexthop * nh = ptr ;
4622
- struct vxlan_fdb * fdb , * tmp ;
4623
4642
4624
4643
if (!nh || event != NEXTHOP_EVENT_DEL )
4625
4644
return NOTIFY_DONE ;
4626
4645
4627
- list_for_each_entry_safe (fdb , tmp , & nh -> fdb_list , nh_list )
4628
- vxlan_fdb_destroy (fdb -> vdev , fdb , false, false);
4646
+ vxlan_fdb_nh_flush (nh );
4629
4647
4630
4648
return NOTIFY_DONE ;
4631
4649
}
0 commit comments