@@ -375,32 +375,38 @@ static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan,
375375 fdb_info -> added_by_user = fdb -> flags & NTF_VXLAN_ADDED_BY_USER ;
376376}
377377
378- static void vxlan_fdb_switchdev_call_notifiers (struct vxlan_dev * vxlan ,
379- struct vxlan_fdb * fdb ,
380- struct vxlan_rdst * rd ,
381- bool adding )
378+ static int vxlan_fdb_switchdev_call_notifiers (struct vxlan_dev * vxlan ,
379+ struct vxlan_fdb * fdb ,
380+ struct vxlan_rdst * rd ,
381+ bool adding )
382382{
383383 struct switchdev_notifier_vxlan_fdb_info info ;
384384 enum switchdev_notifier_type notifier_type ;
385+ int ret ;
385386
386387 if (WARN_ON (!rd ))
387- return ;
388+ return 0 ;
388389
389390 notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE
390391 : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE ;
391392 vxlan_fdb_switchdev_notifier_info (vxlan , fdb , rd , & info );
392- call_switchdev_notifiers (notifier_type , vxlan -> dev ,
393- & info .info );
393+ ret = call_switchdev_notifiers (notifier_type , vxlan -> dev ,
394+ & info .info );
395+ return notifier_to_errno (ret );
394396}
395397
396- static void vxlan_fdb_notify (struct vxlan_dev * vxlan , struct vxlan_fdb * fdb ,
397- struct vxlan_rdst * rd , int type , bool swdev_notify )
398+ static int vxlan_fdb_notify (struct vxlan_dev * vxlan , struct vxlan_fdb * fdb ,
399+ struct vxlan_rdst * rd , int type , bool swdev_notify )
398400{
401+ int err ;
402+
399403 if (swdev_notify ) {
400404 switch (type ) {
401405 case RTM_NEWNEIGH :
402- vxlan_fdb_switchdev_call_notifiers (vxlan , fdb , rd ,
403- true);
406+ err = vxlan_fdb_switchdev_call_notifiers (vxlan , fdb , rd ,
407+ true);
408+ if (err )
409+ return err ;
404410 break ;
405411 case RTM_DELNEIGH :
406412 vxlan_fdb_switchdev_call_notifiers (vxlan , fdb , rd ,
@@ -410,6 +416,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
410416 }
411417
412418 __vxlan_fdb_notify (vxlan , fdb , rd , type );
419+ return 0 ;
413420}
414421
415422static void vxlan_ip_miss (struct net_device * dev , union vxlan_addr * ipa )
@@ -868,7 +875,8 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
868875 struct vxlan_rdst * rd = NULL ;
869876 struct vxlan_rdst oldrd ;
870877 int notify = 0 ;
871- int rc ;
878+ int rc = 0 ;
879+ int err ;
872880
873881 /* Do not allow an externally learned entry to take over an entry added
874882 * by the user.
@@ -915,10 +923,20 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
915923 if (rd == NULL )
916924 rd = first_remote_rtnl (f );
917925
918- vxlan_fdb_notify (vxlan , f , rd , RTM_NEWNEIGH , swdev_notify );
926+ err = vxlan_fdb_notify (vxlan , f , rd , RTM_NEWNEIGH ,
927+ swdev_notify );
928+ if (err )
929+ goto err_notify ;
919930 }
920931
921932 return 0 ;
933+
934+ err_notify :
935+ if ((flags & NLM_F_REPLACE ) && rc )
936+ * rd = oldrd ;
937+ else if ((flags & NLM_F_APPEND ) && rc )
938+ list_del_rcu (& rd -> list );
939+ return err ;
922940}
923941
924942static int vxlan_fdb_update_create (struct vxlan_dev * vxlan ,
@@ -943,9 +961,16 @@ static int vxlan_fdb_update_create(struct vxlan_dev *vxlan,
943961 if (rc < 0 )
944962 return rc ;
945963
946- vxlan_fdb_notify (vxlan , f , first_remote_rtnl (f ), RTM_NEWNEIGH ,
947- swdev_notify );
964+ rc = vxlan_fdb_notify (vxlan , f , first_remote_rtnl (f ), RTM_NEWNEIGH ,
965+ swdev_notify );
966+ if (rc )
967+ goto err_notify ;
968+
948969 return 0 ;
970+
971+ err_notify :
972+ vxlan_fdb_destroy (vxlan , f , false, false);
973+ return rc ;
949974}
950975
951976/* Add new entry to forwarding table -- assumes lock held */
@@ -3515,9 +3540,12 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
35153540 goto errout ;
35163541
35173542 /* notify default fdb entry */
3518- if (f )
3519- vxlan_fdb_notify (vxlan , f , first_remote_rtnl (f ), RTM_NEWNEIGH ,
3520- true);
3543+ if (f ) {
3544+ err = vxlan_fdb_notify (vxlan , f , first_remote_rtnl (f ),
3545+ RTM_NEWNEIGH , true);
3546+ if (err )
3547+ goto errout ;
3548+ }
35213549
35223550 list_add (& vxlan -> next , & vn -> vxlan_list );
35233551 return 0 ;
0 commit comments