@@ -622,6 +622,86 @@ static int team_change_mode(struct team *team, const char *kind)
622
622
}
623
623
624
624
625
+ /*********************
626
+ * Peers notification
627
+ *********************/
628
+
629
+ static void team_notify_peers_work (struct work_struct * work )
630
+ {
631
+ struct team * team ;
632
+
633
+ team = container_of (work , struct team , notify_peers .dw .work );
634
+
635
+ if (!rtnl_trylock ()) {
636
+ schedule_delayed_work (& team -> notify_peers .dw , 0 );
637
+ return ;
638
+ }
639
+ call_netdevice_notifiers (NETDEV_NOTIFY_PEERS , team -> dev );
640
+ rtnl_unlock ();
641
+ if (!atomic_dec_and_test (& team -> notify_peers .count_pending ))
642
+ schedule_delayed_work (& team -> notify_peers .dw ,
643
+ msecs_to_jiffies (team -> notify_peers .interval ));
644
+ }
645
+
646
+ static void team_notify_peers (struct team * team )
647
+ {
648
+ if (!team -> notify_peers .count || !netif_running (team -> dev ))
649
+ return ;
650
+ atomic_set (& team -> notify_peers .count_pending , team -> notify_peers .count );
651
+ schedule_delayed_work (& team -> notify_peers .dw , 0 );
652
+ }
653
+
654
+ static void team_notify_peers_init (struct team * team )
655
+ {
656
+ INIT_DELAYED_WORK (& team -> notify_peers .dw , team_notify_peers_work );
657
+ }
658
+
659
+ static void team_notify_peers_fini (struct team * team )
660
+ {
661
+ cancel_delayed_work_sync (& team -> notify_peers .dw );
662
+ }
663
+
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
+
625
705
/************************
626
706
* Rx path frame handler
627
707
************************/
@@ -846,6 +926,8 @@ static void team_port_enable(struct team *team,
846
926
team_queue_override_port_add (team , port );
847
927
if (team -> ops .port_enabled )
848
928
team -> ops .port_enabled (team , port );
929
+ team_notify_peers (team );
930
+ team_mcast_rejoin (team );
849
931
}
850
932
851
933
static void __reconstruct_port_hlist (struct team * team , int rm_index )
@@ -875,6 +957,8 @@ static void team_port_disable(struct team *team,
875
957
team -> en_port_count -- ;
876
958
team_queue_override_port_del (team , port );
877
959
team_adjust_ops (team );
960
+ team_notify_peers (team );
961
+ team_mcast_rejoin (team );
878
962
}
879
963
880
964
#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
@@ -1205,6 +1289,62 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx)
1205
1289
return team_change_mode (team , ctx -> data .str_val );
1206
1290
}
1207
1291
1292
+ static int team_notify_peers_count_get (struct team * team ,
1293
+ struct team_gsetter_ctx * ctx )
1294
+ {
1295
+ ctx -> data .u32_val = team -> notify_peers .count ;
1296
+ return 0 ;
1297
+ }
1298
+
1299
+ static int team_notify_peers_count_set (struct team * team ,
1300
+ struct team_gsetter_ctx * ctx )
1301
+ {
1302
+ team -> notify_peers .count = ctx -> data .u32_val ;
1303
+ return 0 ;
1304
+ }
1305
+
1306
+ static int team_notify_peers_interval_get (struct team * team ,
1307
+ struct team_gsetter_ctx * ctx )
1308
+ {
1309
+ ctx -> data .u32_val = team -> notify_peers .interval ;
1310
+ return 0 ;
1311
+ }
1312
+
1313
+ static int team_notify_peers_interval_set (struct team * team ,
1314
+ struct team_gsetter_ctx * ctx )
1315
+ {
1316
+ team -> notify_peers .interval = ctx -> data .u32_val ;
1317
+ return 0 ;
1318
+ }
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
+
1208
1348
static int team_port_en_option_get (struct team * team ,
1209
1349
struct team_gsetter_ctx * ctx )
1210
1350
{
@@ -1316,6 +1456,30 @@ static const struct team_option team_options[] = {
1316
1456
.getter = team_mode_option_get ,
1317
1457
.setter = team_mode_option_set ,
1318
1458
},
1459
+ {
1460
+ .name = "notify_peers_count" ,
1461
+ .type = TEAM_OPTION_TYPE_U32 ,
1462
+ .getter = team_notify_peers_count_get ,
1463
+ .setter = team_notify_peers_count_set ,
1464
+ },
1465
+ {
1466
+ .name = "notify_peers_interval" ,
1467
+ .type = TEAM_OPTION_TYPE_U32 ,
1468
+ .getter = team_notify_peers_interval_get ,
1469
+ .setter = team_notify_peers_interval_set ,
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
+ },
1319
1483
{
1320
1484
.name = "enabled" ,
1321
1485
.type = TEAM_OPTION_TYPE_BOOL ,
@@ -1396,6 +1560,10 @@ static int team_init(struct net_device *dev)
1396
1560
1397
1561
INIT_LIST_HEAD (& team -> option_list );
1398
1562
INIT_LIST_HEAD (& team -> option_inst_list );
1563
+
1564
+ team_notify_peers_init (team );
1565
+ team_mcast_rejoin_init (team );
1566
+
1399
1567
err = team_options_register (team , team_options , ARRAY_SIZE (team_options ));
1400
1568
if (err )
1401
1569
goto err_options_register ;
@@ -1406,6 +1574,8 @@ static int team_init(struct net_device *dev)
1406
1574
return 0 ;
1407
1575
1408
1576
err_options_register :
1577
+ team_mcast_rejoin_fini (team );
1578
+ team_notify_peers_fini (team );
1409
1579
team_queue_override_fini (team );
1410
1580
err_team_queue_override_init :
1411
1581
free_percpu (team -> pcpu_stats );
@@ -1425,6 +1595,8 @@ static void team_uninit(struct net_device *dev)
1425
1595
1426
1596
__team_change_mode (team , NULL ); /* cleanup */
1427
1597
__team_options_unregister (team , team_options , ARRAY_SIZE (team_options ));
1598
+ team_mcast_rejoin_fini (team );
1599
+ team_notify_peers_fini (team );
1428
1600
team_queue_override_fini (team );
1429
1601
mutex_unlock (& team -> lock );
1430
1602
}
@@ -2698,6 +2870,10 @@ static int team_device_event(struct notifier_block *unused,
2698
2870
case NETDEV_PRE_TYPE_CHANGE :
2699
2871
/* Forbid to change type of underlaying device */
2700
2872
return NOTIFY_BAD ;
2873
+ case NETDEV_RESEND_IGMP :
2874
+ /* Propagate to master device */
2875
+ call_netdevice_notifiers (event , port -> team -> dev );
2876
+ break ;
2701
2877
}
2702
2878
return NOTIFY_DONE ;
2703
2879
}
0 commit comments