@@ -662,6 +662,46 @@ static void team_notify_peers_fini(struct team *team)
662662}
663663
664664
665+ /*******************************
666+ * Send multicast group rejoins
667+ *******************************/
668+
669+ static void team_mcast_rejoin_work (struct work_struct * work )
670+ {
671+ struct team * team ;
672+
673+ team = container_of (work , struct team , mcast_rejoin .dw .work );
674+
675+ if (!rtnl_trylock ()) {
676+ schedule_delayed_work (& team -> mcast_rejoin .dw , 0 );
677+ return ;
678+ }
679+ call_netdevice_notifiers (NETDEV_RESEND_IGMP , team -> dev );
680+ rtnl_unlock ();
681+ if (!atomic_dec_and_test (& team -> mcast_rejoin .count_pending ))
682+ schedule_delayed_work (& team -> mcast_rejoin .dw ,
683+ msecs_to_jiffies (team -> mcast_rejoin .interval ));
684+ }
685+
686+ static void team_mcast_rejoin (struct team * team )
687+ {
688+ if (!team -> mcast_rejoin .count || !netif_running (team -> dev ))
689+ return ;
690+ atomic_set (& team -> mcast_rejoin .count_pending , team -> mcast_rejoin .count );
691+ schedule_delayed_work (& team -> mcast_rejoin .dw , 0 );
692+ }
693+
694+ static void team_mcast_rejoin_init (struct team * team )
695+ {
696+ INIT_DELAYED_WORK (& team -> mcast_rejoin .dw , team_mcast_rejoin_work );
697+ }
698+
699+ static void team_mcast_rejoin_fini (struct team * team )
700+ {
701+ cancel_delayed_work_sync (& team -> mcast_rejoin .dw );
702+ }
703+
704+
665705/************************
666706 * Rx path frame handler
667707 ************************/
@@ -887,6 +927,7 @@ static void team_port_enable(struct team *team,
887927 if (team -> ops .port_enabled )
888928 team -> ops .port_enabled (team , port );
889929 team_notify_peers (team );
930+ team_mcast_rejoin (team );
890931}
891932
892933static void __reconstruct_port_hlist (struct team * team , int rm_index )
@@ -917,6 +958,7 @@ static void team_port_disable(struct team *team,
917958 team_queue_override_port_del (team , port );
918959 team_adjust_ops (team );
919960 team_notify_peers (team );
961+ team_mcast_rejoin (team );
920962}
921963
922964#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
@@ -1275,6 +1317,34 @@ static int team_notify_peers_interval_set(struct team *team,
12751317 return 0 ;
12761318}
12771319
1320+ static int team_mcast_rejoin_count_get (struct team * team ,
1321+ struct team_gsetter_ctx * ctx )
1322+ {
1323+ ctx -> data .u32_val = team -> mcast_rejoin .count ;
1324+ return 0 ;
1325+ }
1326+
1327+ static int team_mcast_rejoin_count_set (struct team * team ,
1328+ struct team_gsetter_ctx * ctx )
1329+ {
1330+ team -> mcast_rejoin .count = ctx -> data .u32_val ;
1331+ return 0 ;
1332+ }
1333+
1334+ static int team_mcast_rejoin_interval_get (struct team * team ,
1335+ struct team_gsetter_ctx * ctx )
1336+ {
1337+ ctx -> data .u32_val = team -> mcast_rejoin .interval ;
1338+ return 0 ;
1339+ }
1340+
1341+ static int team_mcast_rejoin_interval_set (struct team * team ,
1342+ struct team_gsetter_ctx * ctx )
1343+ {
1344+ team -> mcast_rejoin .interval = ctx -> data .u32_val ;
1345+ return 0 ;
1346+ }
1347+
12781348static int team_port_en_option_get (struct team * team ,
12791349 struct team_gsetter_ctx * ctx )
12801350{
@@ -1398,6 +1468,18 @@ static const struct team_option team_options[] = {
13981468 .getter = team_notify_peers_interval_get ,
13991469 .setter = team_notify_peers_interval_set ,
14001470 },
1471+ {
1472+ .name = "mcast_rejoin_count" ,
1473+ .type = TEAM_OPTION_TYPE_U32 ,
1474+ .getter = team_mcast_rejoin_count_get ,
1475+ .setter = team_mcast_rejoin_count_set ,
1476+ },
1477+ {
1478+ .name = "mcast_rejoin_interval" ,
1479+ .type = TEAM_OPTION_TYPE_U32 ,
1480+ .getter = team_mcast_rejoin_interval_get ,
1481+ .setter = team_mcast_rejoin_interval_set ,
1482+ },
14011483 {
14021484 .name = "enabled" ,
14031485 .type = TEAM_OPTION_TYPE_BOOL ,
@@ -1480,6 +1562,7 @@ static int team_init(struct net_device *dev)
14801562 INIT_LIST_HEAD (& team -> option_inst_list );
14811563
14821564 team_notify_peers_init (team );
1565+ team_mcast_rejoin_init (team );
14831566
14841567 err = team_options_register (team , team_options , ARRAY_SIZE (team_options ));
14851568 if (err )
@@ -1491,6 +1574,7 @@ static int team_init(struct net_device *dev)
14911574 return 0 ;
14921575
14931576err_options_register :
1577+ team_mcast_rejoin_fini (team );
14941578 team_notify_peers_fini (team );
14951579 team_queue_override_fini (team );
14961580err_team_queue_override_init :
@@ -1511,6 +1595,7 @@ static void team_uninit(struct net_device *dev)
15111595
15121596 __team_change_mode (team , NULL ); /* cleanup */
15131597 __team_options_unregister (team , team_options , ARRAY_SIZE (team_options ));
1598+ team_mcast_rejoin_fini (team );
15141599 team_notify_peers_fini (team );
15151600 team_queue_override_fini (team );
15161601 mutex_unlock (& team -> lock );
0 commit comments