@@ -622,6 +622,46 @@ static int team_change_mode(struct team *team, const char *kind)
622622}
623623
624624
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+
625665/************************
626666 * Rx path frame handler
627667 ************************/
@@ -846,6 +886,7 @@ static void team_port_enable(struct team *team,
846886 team_queue_override_port_add (team , port );
847887 if (team -> ops .port_enabled )
848888 team -> ops .port_enabled (team , port );
889+ team_notify_peers (team );
849890}
850891
851892static void __reconstruct_port_hlist (struct team * team , int rm_index )
@@ -875,6 +916,7 @@ static void team_port_disable(struct team *team,
875916 team -> en_port_count -- ;
876917 team_queue_override_port_del (team , port );
877918 team_adjust_ops (team );
919+ team_notify_peers (team );
878920}
879921
880922#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
@@ -1205,6 +1247,34 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx)
12051247 return team_change_mode (team , ctx -> data .str_val );
12061248}
12071249
1250+ static int team_notify_peers_count_get (struct team * team ,
1251+ struct team_gsetter_ctx * ctx )
1252+ {
1253+ ctx -> data .u32_val = team -> notify_peers .count ;
1254+ return 0 ;
1255+ }
1256+
1257+ static int team_notify_peers_count_set (struct team * team ,
1258+ struct team_gsetter_ctx * ctx )
1259+ {
1260+ team -> notify_peers .count = ctx -> data .u32_val ;
1261+ return 0 ;
1262+ }
1263+
1264+ static int team_notify_peers_interval_get (struct team * team ,
1265+ struct team_gsetter_ctx * ctx )
1266+ {
1267+ ctx -> data .u32_val = team -> notify_peers .interval ;
1268+ return 0 ;
1269+ }
1270+
1271+ static int team_notify_peers_interval_set (struct team * team ,
1272+ struct team_gsetter_ctx * ctx )
1273+ {
1274+ team -> notify_peers .interval = ctx -> data .u32_val ;
1275+ return 0 ;
1276+ }
1277+
12081278static int team_port_en_option_get (struct team * team ,
12091279 struct team_gsetter_ctx * ctx )
12101280{
@@ -1316,6 +1386,18 @@ static const struct team_option team_options[] = {
13161386 .getter = team_mode_option_get ,
13171387 .setter = team_mode_option_set ,
13181388 },
1389+ {
1390+ .name = "notify_peers_count" ,
1391+ .type = TEAM_OPTION_TYPE_U32 ,
1392+ .getter = team_notify_peers_count_get ,
1393+ .setter = team_notify_peers_count_set ,
1394+ },
1395+ {
1396+ .name = "notify_peers_interval" ,
1397+ .type = TEAM_OPTION_TYPE_U32 ,
1398+ .getter = team_notify_peers_interval_get ,
1399+ .setter = team_notify_peers_interval_set ,
1400+ },
13191401 {
13201402 .name = "enabled" ,
13211403 .type = TEAM_OPTION_TYPE_BOOL ,
@@ -1396,6 +1478,9 @@ static int team_init(struct net_device *dev)
13961478
13971479 INIT_LIST_HEAD (& team -> option_list );
13981480 INIT_LIST_HEAD (& team -> option_inst_list );
1481+
1482+ team_notify_peers_init (team );
1483+
13991484 err = team_options_register (team , team_options , ARRAY_SIZE (team_options ));
14001485 if (err )
14011486 goto err_options_register ;
@@ -1406,6 +1491,7 @@ static int team_init(struct net_device *dev)
14061491 return 0 ;
14071492
14081493err_options_register :
1494+ team_notify_peers_fini (team );
14091495 team_queue_override_fini (team );
14101496err_team_queue_override_init :
14111497 free_percpu (team -> pcpu_stats );
@@ -1425,6 +1511,7 @@ static void team_uninit(struct net_device *dev)
14251511
14261512 __team_change_mode (team , NULL ); /* cleanup */
14271513 __team_options_unregister (team , team_options , ARRAY_SIZE (team_options ));
1514+ team_notify_peers_fini (team );
14281515 team_queue_override_fini (team );
14291516 mutex_unlock (& team -> lock );
14301517}
0 commit comments