aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/team
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2012-04-20 00:42:05 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-21 16:26:33 -0400
commit19a0b58e506b06fd41659d8734bba6a3e87980f4 (patch)
treef9844eaf9d1471c6fcd98c850b1ed6cd57f2bce3 /drivers/net/team
parent4c78bb845bd2aaf1f7136e75314c7d034cfd120f (diff)
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 <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/team')
-rw-r--r--drivers/net/team/team.c51
-rw-r--r--drivers/net/team/team_mode_loadbalance.c2
-rw-r--r--drivers/net/team/team_mode_roundrobin.c2
3 files changed, 37 insertions, 18 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 153a62d03c9..fe7ca40284f 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -559,6 +559,8 @@ static int team_change_mode(struct team *team, const char *kind)
559 * Rx path frame handler 559 * Rx path frame handler
560 ************************/ 560 ************************/
561 561
562static bool team_port_enabled(struct team_port *port);
563
562/* note: already called with rcu_read_lock */ 564/* note: already called with rcu_read_lock */
563static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) 565static 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 port = team_port_get_rcu(skb->dev); 578 port = team_port_get_rcu(skb->dev);
577 team = port->team; 579 team = port->team;
578 580 if (!team_port_enabled(port)) {
579 res = team->ops.receive(team, port, skb); 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 if (res == RX_HANDLER_ANOTHER) { 586 if (res == RX_HANDLER_ANOTHER) {
581 struct team_pcpu_stats *pcpu_stats; 587 struct team_pcpu_stats *pcpu_stats;
582 588
@@ -612,17 +618,25 @@ static bool team_port_find(const struct team *team,
612 return false; 618 return false;
613} 619}
614 620
621static 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. 627 * Enable/disable port by adding to enabled port hashlist and setting
617 * Takes care of correct port->index setup (might be racy). 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 */
619static void team_port_list_add_port(struct team *team, 632static void team_port_enable(struct team *team,
620 struct team_port *port) 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 hlist_add_head_rcu(&port->hlist, 638 hlist_add_head_rcu(&port->hlist,
624 team_port_index_hash(team, port->index)); 639 team_port_index_hash(team, port->index));
625 list_add_tail_rcu(&port->list, &team->port_list);
626} 640}
627 641
628static void __reconstruct_port_hlist(struct team *team, int rm_index) 642static void __reconstruct_port_hlist(struct team *team, int rm_index)
@@ -630,7 +644,7 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index)
630 int i; 644 int i;
631 struct team_port *port; 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 port = team_get_port_by_index(team, i); 648 port = team_get_port_by_index(team, i);
635 hlist_del_rcu(&port->hlist); 649 hlist_del_rcu(&port->hlist);
636 port->index--; 650 port->index--;
@@ -639,15 +653,17 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index)
639 } 653 }
640} 654}
641 655
642static void team_port_list_del_port(struct team *team, 656static void team_port_disable(struct team *team,
643 struct team_port *port) 657 struct team_port *port)
644{ 658{
645 int rm_index = port->index; 659 int rm_index = port->index;
646 660
661 if (!team_port_enabled(port))
662 return;
647 hlist_del_rcu(&port->hlist); 663 hlist_del_rcu(&port->hlist);
648 list_del_rcu(&port->list);
649 __reconstruct_port_hlist(team, rm_index); 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#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ 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 goto err_option_port_add; 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 team_adjust_ops(team); 822 team_adjust_ops(team);
805 __team_compute_features(team); 823 __team_compute_features(team);
806 __team_port_change_check(port, !!netif_carrier_ok(port_dev)); 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 port->removed = true; 868 port->removed = true;
851 __team_port_change_check(port, false); 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 team_adjust_ops(team); 872 team_adjust_ops(team);
854 team_option_port_del(team, port); 873 team_option_port_del(team, port);
855 netdev_rx_handler_unregister(port_dev); 874 netdev_rx_handler_unregister(port_dev);
@@ -956,7 +975,7 @@ static int team_init(struct net_device *dev)
956 return -ENOMEM; 975 return -ENOMEM;
957 976
958 for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) 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 INIT_LIST_HEAD(&team->port_list); 979 INIT_LIST_HEAD(&team->port_list);
961 980
962 team_adjust_ops(team); 981 team_adjust_ops(team);
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index 438d5b87163..86e8183c8e3 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -38,7 +38,7 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb)
38 if (unlikely(!fp)) 38 if (unlikely(!fp))
39 goto drop; 39 goto drop;
40 hash = SK_RUN_FILTER(fp, skb); 40 hash = SK_RUN_FILTER(fp, skb);
41 port_index = hash % team->port_count; 41 port_index = hash % team->en_port_count;
42 port = team_get_port_by_index_rcu(team, port_index); 42 port = team_get_port_by_index_rcu(team, port_index);
43 if (unlikely(!port)) 43 if (unlikely(!port))
44 goto drop; 44 goto drop;
diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c
index a0e8f806331..6abfbdc96be 100644
--- a/drivers/net/team/team_mode_roundrobin.c
+++ b/drivers/net/team/team_mode_roundrobin.c
@@ -50,7 +50,7 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb)
50 struct team_port *port; 50 struct team_port *port;
51 int port_index; 51 int port_index;
52 52
53 port_index = rr_priv(team)->sent_packets++ % team->port_count; 53 port_index = rr_priv(team)->sent_packets++ % team->en_port_count;
54 port = team_get_port_by_index_rcu(team, port_index); 54 port = team_get_port_by_index_rcu(team, port_index);
55 port = __get_first_port_up(team, port); 55 port = __get_first_port_up(team, port);
56 if (unlikely(!port)) 56 if (unlikely(!port))