@@ -662,6 +662,46 @@ static void team_notify_peers_fini(struct team *team)
662
662
}
663
663
664
664
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
+
665
705
/************************
666
706
* Rx path frame handler
667
707
************************/
@@ -887,6 +927,7 @@ static void team_port_enable(struct team *team,
887
927
if (team -> ops .port_enabled )
888
928
team -> ops .port_enabled (team , port );
889
929
team_notify_peers (team );
930
+ team_mcast_rejoin (team );
890
931
}
891
932
892
933
static void __reconstruct_port_hlist (struct team * team , int rm_index )
@@ -917,6 +958,7 @@ static void team_port_disable(struct team *team,
917
958
team_queue_override_port_del (team , port );
918
959
team_adjust_ops (team );
919
960
team_notify_peers (team );
961
+ team_mcast_rejoin (team );
920
962
}
921
963
922
964
#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,
1275
1317
return 0 ;
1276
1318
}
1277
1319
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
+
1278
1348
static int team_port_en_option_get (struct team * team ,
1279
1349
struct team_gsetter_ctx * ctx )
1280
1350
{
@@ -1398,6 +1468,18 @@ static const struct team_option team_options[] = {
1398
1468
.getter = team_notify_peers_interval_get ,
1399
1469
.setter = team_notify_peers_interval_set ,
1400
1470
},
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
+ },
1401
1483
{
1402
1484
.name = "enabled" ,
1403
1485
.type = TEAM_OPTION_TYPE_BOOL ,
@@ -1480,6 +1562,7 @@ static int team_init(struct net_device *dev)
1480
1562
INIT_LIST_HEAD (& team -> option_inst_list );
1481
1563
1482
1564
team_notify_peers_init (team );
1565
+ team_mcast_rejoin_init (team );
1483
1566
1484
1567
err = team_options_register (team , team_options , ARRAY_SIZE (team_options ));
1485
1568
if (err )
@@ -1491,6 +1574,7 @@ static int team_init(struct net_device *dev)
1491
1574
return 0 ;
1492
1575
1493
1576
err_options_register :
1577
+ team_mcast_rejoin_fini (team );
1494
1578
team_notify_peers_fini (team );
1495
1579
team_queue_override_fini (team );
1496
1580
err_team_queue_override_init :
@@ -1511,6 +1595,7 @@ static void team_uninit(struct net_device *dev)
1511
1595
1512
1596
__team_change_mode (team , NULL ); /* cleanup */
1513
1597
__team_options_unregister (team , team_options , ARRAY_SIZE (team_options ));
1598
+ team_mcast_rejoin_fini (team );
1514
1599
team_notify_peers_fini (team );
1515
1600
team_queue_override_fini (team );
1516
1601
mutex_unlock (& team -> lock );
0 commit comments