@@ -559,6 +559,8 @@ static int team_change_mode(struct team *team, const char *kind)
559
559
* Rx path frame handler
560
560
************************/
561
561
562
+ static bool team_port_enabled (struct team_port * port );
563
+
562
564
/* note: already called with rcu_read_lock */
563
565
static rx_handler_result_t team_handle_frame (struct sk_buff * * pskb )
564
566
{
@@ -575,8 +577,12 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
575
577
576
578
port = team_port_get_rcu (skb -> dev );
577
579
team = port -> team ;
578
-
579
- res = team -> ops .receive (team , port , skb );
580
+ if (!team_port_enabled (port )) {
581
+ /* allow exact match delivery for disabled ports */
582
+ res = RX_HANDLER_EXACT ;
583
+ } else {
584
+ res = team -> ops .receive (team , port , skb );
585
+ }
580
586
if (res == RX_HANDLER_ANOTHER ) {
581
587
struct team_pcpu_stats * pcpu_stats ;
582
588
@@ -612,25 +618,33 @@ static bool team_port_find(const struct team *team,
612
618
return false;
613
619
}
614
620
621
+ static bool team_port_enabled (struct team_port * port )
622
+ {
623
+ return port -> index != -1 ;
624
+ }
625
+
615
626
/*
616
- * Add/delete port to the team port list. Write guarded by rtnl_lock.
617
- * Takes care of correct port->index setup (might be racy).
627
+ * Enable/disable port by adding to enabled port hashlist and setting
628
+ * port->index (Might be racy so reader could see incorrect ifindex when
629
+ * processing a flying packet, but that is not a problem). Write guarded
630
+ * by team->lock.
618
631
*/
619
- static void team_port_list_add_port (struct team * team ,
620
- struct team_port * port )
632
+ static void team_port_enable (struct team * team ,
633
+ struct team_port * port )
621
634
{
622
- port -> index = team -> port_count ++ ;
635
+ if (team_port_enabled (port ))
636
+ return ;
637
+ port -> index = team -> en_port_count ++ ;
623
638
hlist_add_head_rcu (& port -> hlist ,
624
639
team_port_index_hash (team , port -> index ));
625
- list_add_tail_rcu (& port -> list , & team -> port_list );
626
640
}
627
641
628
642
static void __reconstruct_port_hlist (struct team * team , int rm_index )
629
643
{
630
644
int i ;
631
645
struct team_port * port ;
632
646
633
- for (i = rm_index + 1 ; i < team -> port_count ; i ++ ) {
647
+ for (i = rm_index + 1 ; i < team -> en_port_count ; i ++ ) {
634
648
port = team_get_port_by_index (team , i );
635
649
hlist_del_rcu (& port -> hlist );
636
650
port -> index -- ;
@@ -639,15 +653,17 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index)
639
653
}
640
654
}
641
655
642
- static void team_port_list_del_port (struct team * team ,
643
- struct team_port * port )
656
+ static void team_port_disable (struct team * team ,
657
+ struct team_port * port )
644
658
{
645
659
int rm_index = port -> index ;
646
660
661
+ if (!team_port_enabled (port ))
662
+ return ;
647
663
hlist_del_rcu (& port -> hlist );
648
- list_del_rcu (& port -> list );
649
664
__reconstruct_port_hlist (team , rm_index );
650
- team -> port_count -- ;
665
+ team -> en_port_count -- ;
666
+ port -> index = -1 ;
651
667
}
652
668
653
669
#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
@@ -800,7 +816,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
800
816
goto err_option_port_add ;
801
817
}
802
818
803
- team_port_list_add_port (team , port );
819
+ port -> index = -1 ;
820
+ team_port_enable (team , port );
821
+ list_add_tail_rcu (& port -> list , & team -> port_list );
804
822
team_adjust_ops (team );
805
823
__team_compute_features (team );
806
824
__team_port_change_check (port , !!netif_carrier_ok (port_dev ));
@@ -849,7 +867,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
849
867
850
868
port -> removed = true;
851
869
__team_port_change_check (port , false);
852
- team_port_list_del_port (team , port );
870
+ team_port_disable (team , port );
871
+ list_del_rcu (& port -> list );
853
872
team_adjust_ops (team );
854
873
team_option_port_del (team , port );
855
874
netdev_rx_handler_unregister (port_dev );
@@ -956,7 +975,7 @@ static int team_init(struct net_device *dev)
956
975
return - ENOMEM ;
957
976
958
977
for (i = 0 ; i < TEAM_PORT_HASHENTRIES ; i ++ )
959
- INIT_HLIST_HEAD (& team -> port_hlist [i ]);
978
+ INIT_HLIST_HEAD (& team -> en_port_hlist [i ]);
960
979
INIT_LIST_HEAD (& team -> port_list );
961
980
962
981
team_adjust_ops (team );
0 commit comments