@@ -442,7 +442,8 @@ static void br_multicast_fwd_src_add(struct net_bridge_group_src *src)
442442 br_multicast_sg_add_exclude_ports (star_mp , sg );
443443}
444444
445- static void br_multicast_fwd_src_remove (struct net_bridge_group_src * src )
445+ static void br_multicast_fwd_src_remove (struct net_bridge_group_src * src ,
446+ bool fastleave )
446447{
447448 struct net_bridge_port_group * p , * pg = src -> pg ;
448449 struct net_bridge_port_group __rcu * * pp ;
@@ -467,6 +468,8 @@ static void br_multicast_fwd_src_remove(struct net_bridge_group_src *src)
467468 (p -> flags & MDB_PG_FLAGS_PERMANENT ))
468469 break ;
469470
471+ if (fastleave )
472+ p -> flags |= MDB_PG_FLAGS_FAST_LEAVE ;
470473 br_multicast_del_pg (mp , p , pp );
471474 break ;
472475 }
@@ -560,11 +563,12 @@ static void br_multicast_destroy_group_src(struct net_bridge_mcast_gc *gc)
560563 kfree_rcu (src , rcu );
561564}
562565
563- void br_multicast_del_group_src (struct net_bridge_group_src * src )
566+ void br_multicast_del_group_src (struct net_bridge_group_src * src ,
567+ bool fastleave )
564568{
565569 struct net_bridge * br = src -> pg -> key .port -> br ;
566570
567- br_multicast_fwd_src_remove (src );
571+ br_multicast_fwd_src_remove (src , fastleave );
568572 hlist_del_init_rcu (& src -> node );
569573 src -> pg -> src_ents -- ;
570574 hlist_add_head (& src -> mcast_gc .gc_node , & br -> mcast_gc_list );
@@ -596,7 +600,7 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
596600 hlist_del_init (& pg -> mglist );
597601 br_multicast_eht_clean_sets (pg );
598602 hlist_for_each_entry_safe (ent , tmp , & pg -> src_list , node )
599- br_multicast_del_group_src (ent );
603+ br_multicast_del_group_src (ent , false );
600604 br_mdb_notify (br -> dev , mp , pg , RTM_DELMDB );
601605 if (!br_multicast_is_star_g (& mp -> addr )) {
602606 rhashtable_remove_fast (& br -> sg_port_tbl , & pg -> rhnode ,
@@ -653,7 +657,7 @@ static void br_multicast_port_group_expired(struct timer_list *t)
653657 pg -> filter_mode = MCAST_INCLUDE ;
654658 hlist_for_each_entry_safe (src_ent , tmp , & pg -> src_list , node ) {
655659 if (!timer_pending (& src_ent -> timer )) {
656- br_multicast_del_group_src (src_ent );
660+ br_multicast_del_group_src (src_ent , false );
657661 changed = true;
658662 }
659663 }
@@ -1080,7 +1084,7 @@ static void br_multicast_group_src_expired(struct timer_list *t)
10801084
10811085 pg = src -> pg ;
10821086 if (pg -> filter_mode == MCAST_INCLUDE ) {
1083- br_multicast_del_group_src (src );
1087+ br_multicast_del_group_src (src , false );
10841088 if (!hlist_empty (& pg -> src_list ))
10851089 goto out ;
10861090 br_multicast_find_del_pg (br , pg );
@@ -1704,7 +1708,7 @@ static int __grp_src_delete_marked(struct net_bridge_port_group *pg)
17041708
17051709 hlist_for_each_entry_safe (ent , tmp , & pg -> src_list , node )
17061710 if (ent -> flags & BR_SGRP_F_DELETE ) {
1707- br_multicast_del_group_src (ent );
1711+ br_multicast_del_group_src (ent , false );
17081712 deleted ++ ;
17091713 }
17101714
@@ -2053,6 +2057,7 @@ static bool br_multicast_toin(struct net_bridge_port_group *pg, void *h_addr,
20532057 }
20542058
20552059 if (br_multicast_eht_should_del_pg (pg )) {
2060+ pg -> flags |= MDB_PG_FLAGS_FAST_LEAVE ;
20562061 br_multicast_find_del_pg (pg -> key .port -> br , pg );
20572062 /* a notification has already been sent and we shouldn't
20582063 * access pg after the delete so we have to return false
@@ -2273,6 +2278,8 @@ static bool br_multicast_block(struct net_bridge_port_group *pg, void *h_addr,
22732278
22742279 if ((pg -> filter_mode == MCAST_INCLUDE && hlist_empty (& pg -> src_list )) ||
22752280 br_multicast_eht_should_del_pg (pg )) {
2281+ if (br_multicast_eht_should_del_pg (pg ))
2282+ pg -> flags |= MDB_PG_FLAGS_FAST_LEAVE ;
22762283 br_multicast_find_del_pg (pg -> key .port -> br , pg );
22772284 /* a notification has already been sent and we shouldn't
22782285 * access pg after the delete so we have to return false
0 commit comments