Skip to content

Commit 19a0b58

Browse files
Jiri Pirkodavem330
authored andcommitted
team: allow to enable/disable ports
This patch changes content of hashlist (used to get port struct by computed index (0...en_port_count-1)). Now the hash list contains only enabled ports so userspace will be able to say what ports can be used for tx/rx. This becomes handy when userspace will need to disable ports which does not belong to active aggregator. By default, newly added port is enabled. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4c78bb8 commit 19a0b58

File tree

4 files changed

+45
-25
lines changed

4 files changed

+45
-25
lines changed

drivers/net/team/team.c

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ static int team_change_mode(struct team *team, const char *kind)
559559
* Rx path frame handler
560560
************************/
561561

562+
static bool team_port_enabled(struct team_port *port);
563+
562564
/* note: already called with rcu_read_lock */
563565
static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
564566
{
@@ -575,8 +577,12 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
575577

576578
port = team_port_get_rcu(skb->dev);
577579
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+
}
580586
if (res == RX_HANDLER_ANOTHER) {
581587
struct team_pcpu_stats *pcpu_stats;
582588

@@ -612,25 +618,33 @@ static bool team_port_find(const struct team *team,
612618
return false;
613619
}
614620

621+
static bool team_port_enabled(struct team_port *port)
622+
{
623+
return port->index != -1;
624+
}
625+
615626
/*
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.
618631
*/
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)
621634
{
622-
port->index = team->port_count++;
635+
if (team_port_enabled(port))
636+
return;
637+
port->index = team->en_port_count++;
623638
hlist_add_head_rcu(&port->hlist,
624639
team_port_index_hash(team, port->index));
625-
list_add_tail_rcu(&port->list, &team->port_list);
626640
}
627641

628642
static void __reconstruct_port_hlist(struct team *team, int rm_index)
629643
{
630644
int i;
631645
struct team_port *port;
632646

633-
for (i = rm_index + 1; i < team->port_count; i++) {
647+
for (i = rm_index + 1; i < team->en_port_count; i++) {
634648
port = team_get_port_by_index(team, i);
635649
hlist_del_rcu(&port->hlist);
636650
port->index--;
@@ -639,15 +653,17 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index)
639653
}
640654
}
641655

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)
644658
{
645659
int rm_index = port->index;
646660

661+
if (!team_port_enabled(port))
662+
return;
647663
hlist_del_rcu(&port->hlist);
648-
list_del_rcu(&port->list);
649664
__reconstruct_port_hlist(team, rm_index);
650-
team->port_count--;
665+
team->en_port_count--;
666+
port->index = -1;
651667
}
652668

653669
#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)
800816
goto err_option_port_add;
801817
}
802818

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);
804822
team_adjust_ops(team);
805823
__team_compute_features(team);
806824
__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)
849867

850868
port->removed = true;
851869
__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);
853872
team_adjust_ops(team);
854873
team_option_port_del(team, port);
855874
netdev_rx_handler_unregister(port_dev);
@@ -956,7 +975,7 @@ static int team_init(struct net_device *dev)
956975
return -ENOMEM;
957976

958977
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]);
960979
INIT_LIST_HEAD(&team->port_list);
961980

962981
team_adjust_ops(team);

drivers/net/team/team_mode_loadbalance.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb)
3838
if (unlikely(!fp))
3939
goto drop;
4040
hash = SK_RUN_FILTER(fp, skb);
41-
port_index = hash % team->port_count;
41+
port_index = hash % team->en_port_count;
4242
port = team_get_port_by_index_rcu(team, port_index);
4343
if (unlikely(!port))
4444
goto drop;

drivers/net/team/team_mode_roundrobin.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb)
5050
struct team_port *port;
5151
int port_index;
5252

53-
port_index = rr_priv(team)->sent_packets++ % team->port_count;
53+
port_index = rr_priv(team)->sent_packets++ % team->en_port_count;
5454
port = team_get_port_by_index_rcu(team, port_index);
5555
port = __get_first_port_up(team, port);
5656
if (unlikely(!port))

include/linux/if_team.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ struct team;
2828

2929
struct team_port {
3030
struct net_device *dev;
31-
struct hlist_node hlist; /* node in hash list */
31+
struct hlist_node hlist; /* node in enabled ports hash list */
3232
struct list_head list; /* node in ordinary list */
3333
struct team *team;
34-
int index;
34+
int index; /* index of enabled port. If disabled, it's set to -1 */
3535

3636
bool linkup; /* either state.linkup or user.linkup */
3737

@@ -125,11 +125,12 @@ struct team {
125125
struct mutex lock; /* used for overall locking, e.g. port lists write */
126126

127127
/*
128-
* port lists with port count
128+
* List of enabled ports and their count
129129
*/
130-
int port_count;
131-
struct hlist_head port_hlist[TEAM_PORT_HASHENTRIES];
132-
struct list_head port_list;
130+
int en_port_count;
131+
struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES];
132+
133+
struct list_head port_list; /* list of all ports */
133134

134135
struct list_head option_list;
135136
struct list_head option_inst_list; /* list of option instances */
@@ -142,7 +143,7 @@ struct team {
142143
static inline struct hlist_head *team_port_index_hash(struct team *team,
143144
int port_index)
144145
{
145-
return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
146+
return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
146147
}
147148

148149
static inline struct team_port *team_get_port_by_index(struct team *team,

0 commit comments

Comments
 (0)