@@ -258,6 +258,16 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
258258 fib_rules_unregister (net -> ipv6 .mr6_rules_ops );
259259 rtnl_unlock ();
260260}
261+
262+ static int ip6mr_rules_dump (struct net * net , struct notifier_block * nb )
263+ {
264+ return fib_rules_dump (net , nb , RTNL_FAMILY_IP6MR );
265+ }
266+
267+ static unsigned int ip6mr_rules_seq_read (struct net * net )
268+ {
269+ return fib_rules_seq_read (net , RTNL_FAMILY_IP6MR );
270+ }
261271#else
262272#define ip6mr_for_each_table (mrt , net ) \
263273 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
@@ -295,6 +305,16 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
295305 net -> ipv6 .mrt6 = NULL ;
296306 rtnl_unlock ();
297307}
308+
309+ static int ip6mr_rules_dump (struct net * net , struct notifier_block * nb )
310+ {
311+ return 0 ;
312+ }
313+
314+ static unsigned int ip6mr_rules_seq_read (struct net * net )
315+ {
316+ return 0 ;
317+ }
298318#endif
299319
300320static int ip6mr_hash_cmp (struct rhashtable_compare_arg * arg ,
@@ -653,10 +673,25 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
653673}
654674#endif
655675
656- /*
657- * Delete a VIF entry
658- */
676+ static int call_ip6mr_vif_entry_notifiers (struct net * net ,
677+ enum fib_event_type event_type ,
678+ struct vif_device * vif ,
679+ mifi_t vif_index , u32 tb_id )
680+ {
681+ return mr_call_vif_notifiers (net , RTNL_FAMILY_IP6MR , event_type ,
682+ vif , vif_index , tb_id ,
683+ & net -> ipv6 .ipmr_seq );
684+ }
659685
686+ static int call_ip6mr_mfc_entry_notifiers (struct net * net ,
687+ enum fib_event_type event_type ,
688+ struct mfc6_cache * mfc , u32 tb_id )
689+ {
690+ return mr_call_mfc_notifiers (net , RTNL_FAMILY_IP6MR , event_type ,
691+ & mfc -> _c , tb_id , & net -> ipv6 .ipmr_seq );
692+ }
693+
694+ /* Delete a VIF entry */
660695static int mif6_delete (struct mr_table * mrt , int vifi , int notify ,
661696 struct list_head * head )
662697{
@@ -669,6 +704,11 @@ static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
669704
670705 v = & mrt -> vif_table [vifi ];
671706
707+ if (VIF_EXISTS (mrt , vifi ))
708+ call_ip6mr_vif_entry_notifiers (read_pnet (& mrt -> net ),
709+ FIB_EVENT_VIF_DEL , v , vifi ,
710+ mrt -> id );
711+
672712 write_lock_bh (& mrt_lock );
673713 dev = v -> dev ;
674714 v -> dev = NULL ;
@@ -887,6 +927,8 @@ static int mif6_add(struct net *net, struct mr_table *mrt,
887927 if (vifi + 1 > mrt -> maxvif )
888928 mrt -> maxvif = vifi + 1 ;
889929 write_unlock_bh (& mrt_lock );
930+ call_ip6mr_vif_entry_notifiers (net , FIB_EVENT_VIF_ADD ,
931+ v , vifi , mrt -> id );
890932 return 0 ;
891933}
892934
@@ -1175,6 +1217,8 @@ static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
11751217 rhltable_remove (& mrt -> mfc_hash , & c -> _c .mnode , ip6mr_rht_params );
11761218 list_del_rcu (& c -> _c .list );
11771219
1220+ call_ip6mr_mfc_entry_notifiers (read_pnet (& mrt -> net ),
1221+ FIB_EVENT_ENTRY_DEL , c , mrt -> id );
11781222 mr6_netlink_event (mrt , c , RTM_DELROUTE );
11791223 ip6mr_cache_free (c );
11801224 return 0 ;
@@ -1203,21 +1247,63 @@ static int ip6mr_device_event(struct notifier_block *this,
12031247 return NOTIFY_DONE ;
12041248}
12051249
1250+ static unsigned int ip6mr_seq_read (struct net * net )
1251+ {
1252+ ASSERT_RTNL ();
1253+
1254+ return net -> ipv6 .ipmr_seq + ip6mr_rules_seq_read (net );
1255+ }
1256+
1257+ static int ip6mr_dump (struct net * net , struct notifier_block * nb )
1258+ {
1259+ return mr_dump (net , nb , RTNL_FAMILY_IP6MR , ip6mr_rules_dump ,
1260+ ip6mr_mr_table_iter , & mrt_lock );
1261+ }
1262+
12061263static struct notifier_block ip6_mr_notifier = {
12071264 .notifier_call = ip6mr_device_event
12081265};
12091266
1210- /*
1211- * Setup for IP multicast routing
1212- */
1267+ static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1268+ .family = RTNL_FAMILY_IP6MR ,
1269+ .fib_seq_read = ip6mr_seq_read ,
1270+ .fib_dump = ip6mr_dump ,
1271+ .owner = THIS_MODULE ,
1272+ };
1273+
1274+ static int __net_init ip6mr_notifier_init (struct net * net )
1275+ {
1276+ struct fib_notifier_ops * ops ;
1277+
1278+ net -> ipv6 .ipmr_seq = 0 ;
12131279
1280+ ops = fib_notifier_ops_register (& ip6mr_notifier_ops_template , net );
1281+ if (IS_ERR (ops ))
1282+ return PTR_ERR (ops );
1283+
1284+ net -> ipv6 .ip6mr_notifier_ops = ops ;
1285+
1286+ return 0 ;
1287+ }
1288+
1289+ static void __net_exit ip6mr_notifier_exit (struct net * net )
1290+ {
1291+ fib_notifier_ops_unregister (net -> ipv6 .ip6mr_notifier_ops );
1292+ net -> ipv6 .ip6mr_notifier_ops = NULL ;
1293+ }
1294+
1295+ /* Setup for IP multicast routing */
12141296static int __net_init ip6mr_net_init (struct net * net )
12151297{
12161298 int err ;
12171299
1300+ err = ip6mr_notifier_init (net );
1301+ if (err )
1302+ return err ;
1303+
12181304 err = ip6mr_rules_init (net );
12191305 if (err < 0 )
1220- goto fail ;
1306+ goto ip6mr_rules_fail ;
12211307
12221308#ifdef CONFIG_PROC_FS
12231309 err = - ENOMEM ;
@@ -1235,7 +1321,8 @@ static int __net_init ip6mr_net_init(struct net *net)
12351321proc_vif_fail :
12361322 ip6mr_rules_exit (net );
12371323#endif
1238- fail :
1324+ ip6mr_rules_fail :
1325+ ip6mr_notifier_exit (net );
12391326 return err ;
12401327}
12411328
@@ -1246,6 +1333,7 @@ static void __net_exit ip6mr_net_exit(struct net *net)
12461333 remove_proc_entry ("ip6_mr_vif" , net -> proc_net );
12471334#endif
12481335 ip6mr_rules_exit (net );
1336+ ip6mr_notifier_exit (net );
12491337}
12501338
12511339static struct pernet_operations ip6mr_net_ops = {
@@ -1337,6 +1425,8 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
13371425 if (!mrtsock )
13381426 c -> _c .mfc_flags |= MFC_STATIC ;
13391427 write_unlock_bh (& mrt_lock );
1428+ call_ip6mr_mfc_entry_notifiers (net , FIB_EVENT_ENTRY_REPLACE ,
1429+ c , mrt -> id );
13401430 mr6_netlink_event (mrt , c , RTM_NEWROUTE );
13411431 return 0 ;
13421432 }
@@ -1388,6 +1478,8 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
13881478 ip6mr_cache_resolve (net , mrt , uc , c );
13891479 ip6mr_cache_free (uc );
13901480 }
1481+ call_ip6mr_mfc_entry_notifiers (net , FIB_EVENT_ENTRY_ADD ,
1482+ c , mrt -> id );
13911483 mr6_netlink_event (mrt , c , RTM_NEWROUTE );
13921484 return 0 ;
13931485}
@@ -1424,6 +1516,10 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
14241516 spin_lock_bh (& mfc_unres_lock );
14251517 list_for_each_entry_safe (c , tmp , & mrt -> mfc_unres_queue , list ) {
14261518 list_del (& c -> list );
1519+ call_ip6mr_mfc_entry_notifiers (read_pnet (& mrt -> net ),
1520+ FIB_EVENT_ENTRY_DEL ,
1521+ (struct mfc6_cache * )c ,
1522+ mrt -> id );
14271523 mr6_netlink_event (mrt , (struct mfc6_cache * )c ,
14281524 RTM_DELROUTE );
14291525 ip6mr_destroy_unres (mrt , (struct mfc6_cache * )c );
0 commit comments