aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_3ad.c
diff options
context:
space:
mode:
authorMahesh Bandewar <maheshb@google.com>2014-10-04 20:45:01 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-06 17:13:07 -0400
commitee6377147409a00c071b2da853059a7d59979fbc (patch)
tree82df6bc2bc00711351463081a13785c04b45f773 /drivers/net/bonding/bond_3ad.c
parentd7021325a2ea5aaf4458097341c988f9dc93491f (diff)
bonding: Simplify the xmit function for modes that use xmit_hash
Earlier change to use usable slave array for TLB mode had an additional performance advantage. So extending the same logic to all other modes that use xmit-hash for slave selection (viz 802.3AD, and XOR modes). Also consolidating this with the earlier TLB change. The main idea is to build the usable slaves array in the control path and use that array for slave selection during xmit operation. Measured performance in a setup with a bond of 4x1G NICs with 200 instances of netperf for the modes involved (3ad, xor, tlb) cmd: netperf -t TCP_RR -H <TargetHost> -l 60 -s 5 Mode TPS-Before TPS-After 802.3ad : 468,694 493,101 TLB (lb=0): 392,583 392,965 XOR : 475,696 484,517 Signed-off-by: Mahesh Bandewar <maheshb@google.com> Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_3ad.c')
-rw-r--r--drivers/net/bonding/bond_3ad.c140
1 files changed, 53 insertions, 87 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7e9e522fd476..2110215f3528 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -102,17 +102,20 @@ static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
102/* ================= main 802.3ad protocol functions ================== */ 102/* ================= main 802.3ad protocol functions ================== */
103static int ad_lacpdu_send(struct port *port); 103static int ad_lacpdu_send(struct port *port);
104static int ad_marker_send(struct port *port, struct bond_marker *marker); 104static int ad_marker_send(struct port *port, struct bond_marker *marker);
105static void ad_mux_machine(struct port *port); 105static void ad_mux_machine(struct port *port, bool *update_slave_arr);
106static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port); 106static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
107static void ad_tx_machine(struct port *port); 107static void ad_tx_machine(struct port *port);
108static void ad_periodic_machine(struct port *port); 108static void ad_periodic_machine(struct port *port);
109static void ad_port_selection_logic(struct port *port); 109static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
110static void ad_agg_selection_logic(struct aggregator *aggregator); 110static void ad_agg_selection_logic(struct aggregator *aggregator,
111 bool *update_slave_arr);
111static void ad_clear_agg(struct aggregator *aggregator); 112static void ad_clear_agg(struct aggregator *aggregator);
112static void ad_initialize_agg(struct aggregator *aggregator); 113static void ad_initialize_agg(struct aggregator *aggregator);
113static void ad_initialize_port(struct port *port, int lacp_fast); 114static void ad_initialize_port(struct port *port, int lacp_fast);
114static void ad_enable_collecting_distributing(struct port *port); 115static void ad_enable_collecting_distributing(struct port *port,
115static void ad_disable_collecting_distributing(struct port *port); 116 bool *update_slave_arr);
117static void ad_disable_collecting_distributing(struct port *port,
118 bool *update_slave_arr);
116static void ad_marker_info_received(struct bond_marker *marker_info, 119static void ad_marker_info_received(struct bond_marker *marker_info,
117 struct port *port); 120 struct port *port);
118static void ad_marker_response_received(struct bond_marker *marker, 121static void ad_marker_response_received(struct bond_marker *marker,
@@ -796,8 +799,9 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
796/** 799/**
797 * ad_mux_machine - handle a port's mux state machine 800 * ad_mux_machine - handle a port's mux state machine
798 * @port: the port we're looking at 801 * @port: the port we're looking at
802 * @update_slave_arr: Does slave array need update?
799 */ 803 */
800static void ad_mux_machine(struct port *port) 804static void ad_mux_machine(struct port *port, bool *update_slave_arr)
801{ 805{
802 mux_states_t last_state; 806 mux_states_t last_state;
803 807
@@ -901,7 +905,8 @@ static void ad_mux_machine(struct port *port)
901 switch (port->sm_mux_state) { 905 switch (port->sm_mux_state) {
902 case AD_MUX_DETACHED: 906 case AD_MUX_DETACHED:
903 port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; 907 port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
904 ad_disable_collecting_distributing(port); 908 ad_disable_collecting_distributing(port,
909 update_slave_arr);
905 port->actor_oper_port_state &= ~AD_STATE_COLLECTING; 910 port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
906 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; 911 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
907 port->ntt = true; 912 port->ntt = true;
@@ -913,13 +918,15 @@ static void ad_mux_machine(struct port *port)
913 port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; 918 port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
914 port->actor_oper_port_state &= ~AD_STATE_COLLECTING; 919 port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
915 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; 920 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
916 ad_disable_collecting_distributing(port); 921 ad_disable_collecting_distributing(port,
922 update_slave_arr);
917 port->ntt = true; 923 port->ntt = true;
918 break; 924 break;
919 case AD_MUX_COLLECTING_DISTRIBUTING: 925 case AD_MUX_COLLECTING_DISTRIBUTING:
920 port->actor_oper_port_state |= AD_STATE_COLLECTING; 926 port->actor_oper_port_state |= AD_STATE_COLLECTING;
921 port->actor_oper_port_state |= AD_STATE_DISTRIBUTING; 927 port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
922 ad_enable_collecting_distributing(port); 928 ad_enable_collecting_distributing(port,
929 update_slave_arr);
923 port->ntt = true; 930 port->ntt = true;
924 break; 931 break;
925 default: 932 default:
@@ -1187,12 +1194,13 @@ static void ad_periodic_machine(struct port *port)
1187/** 1194/**
1188 * ad_port_selection_logic - select aggregation groups 1195 * ad_port_selection_logic - select aggregation groups
1189 * @port: the port we're looking at 1196 * @port: the port we're looking at
1197 * @update_slave_arr: Does slave array need update?
1190 * 1198 *
1191 * Select aggregation groups, and assign each port for it's aggregetor. The 1199 * Select aggregation groups, and assign each port for it's aggregetor. The
1192 * selection logic is called in the inititalization (after all the handshkes), 1200 * selection logic is called in the inititalization (after all the handshkes),
1193 * and after every lacpdu receive (if selected is off). 1201 * and after every lacpdu receive (if selected is off).
1194 */ 1202 */
1195static void ad_port_selection_logic(struct port *port) 1203static void ad_port_selection_logic(struct port *port, bool *update_slave_arr)
1196{ 1204{
1197 struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator; 1205 struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator;
1198 struct port *last_port = NULL, *curr_port; 1206 struct port *last_port = NULL, *curr_port;
@@ -1347,7 +1355,7 @@ static void ad_port_selection_logic(struct port *port)
1347 __agg_ports_are_ready(port->aggregator)); 1355 __agg_ports_are_ready(port->aggregator));
1348 1356
1349 aggregator = __get_first_agg(port); 1357 aggregator = __get_first_agg(port);
1350 ad_agg_selection_logic(aggregator); 1358 ad_agg_selection_logic(aggregator, update_slave_arr);
1351} 1359}
1352 1360
1353/* Decide if "agg" is a better choice for the new active aggregator that 1361/* Decide if "agg" is a better choice for the new active aggregator that
@@ -1435,6 +1443,7 @@ static int agg_device_up(const struct aggregator *agg)
1435/** 1443/**
1436 * ad_agg_selection_logic - select an aggregation group for a team 1444 * ad_agg_selection_logic - select an aggregation group for a team
1437 * @aggregator: the aggregator we're looking at 1445 * @aggregator: the aggregator we're looking at
1446 * @update_slave_arr: Does slave array need update?
1438 * 1447 *
1439 * It is assumed that only one aggregator may be selected for a team. 1448 * It is assumed that only one aggregator may be selected for a team.
1440 * 1449 *
@@ -1457,7 +1466,8 @@ static int agg_device_up(const struct aggregator *agg)
1457 * __get_active_agg() won't work correctly. This function should be better 1466 * __get_active_agg() won't work correctly. This function should be better
1458 * called with the bond itself, and retrieve the first agg from it. 1467 * called with the bond itself, and retrieve the first agg from it.
1459 */ 1468 */
1460static void ad_agg_selection_logic(struct aggregator *agg) 1469static void ad_agg_selection_logic(struct aggregator *agg,
1470 bool *update_slave_arr)
1461{ 1471{
1462 struct aggregator *best, *active, *origin; 1472 struct aggregator *best, *active, *origin;
1463 struct bonding *bond = agg->slave->bond; 1473 struct bonding *bond = agg->slave->bond;
@@ -1550,6 +1560,8 @@ static void ad_agg_selection_logic(struct aggregator *agg)
1550 __disable_port(port); 1560 __disable_port(port);
1551 } 1561 }
1552 } 1562 }
1563 /* Slave array needs update. */
1564 *update_slave_arr = true;
1553 } 1565 }
1554 1566
1555 /* if the selected aggregator is of join individuals 1567 /* if the selected aggregator is of join individuals
@@ -1678,24 +1690,30 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
1678/** 1690/**
1679 * ad_enable_collecting_distributing - enable a port's transmit/receive 1691 * ad_enable_collecting_distributing - enable a port's transmit/receive
1680 * @port: the port we're looking at 1692 * @port: the port we're looking at
1693 * @update_slave_arr: Does slave array need update?
1681 * 1694 *
1682 * Enable @port if it's in an active aggregator 1695 * Enable @port if it's in an active aggregator
1683 */ 1696 */
1684static void ad_enable_collecting_distributing(struct port *port) 1697static void ad_enable_collecting_distributing(struct port *port,
1698 bool *update_slave_arr)
1685{ 1699{
1686 if (port->aggregator->is_active) { 1700 if (port->aggregator->is_active) {
1687 pr_debug("Enabling port %d(LAG %d)\n", 1701 pr_debug("Enabling port %d(LAG %d)\n",
1688 port->actor_port_number, 1702 port->actor_port_number,
1689 port->aggregator->aggregator_identifier); 1703 port->aggregator->aggregator_identifier);
1690 __enable_port(port); 1704 __enable_port(port);
1705 /* Slave array needs update */
1706 *update_slave_arr = true;
1691 } 1707 }
1692} 1708}
1693 1709
1694/** 1710/**
1695 * ad_disable_collecting_distributing - disable a port's transmit/receive 1711 * ad_disable_collecting_distributing - disable a port's transmit/receive
1696 * @port: the port we're looking at 1712 * @port: the port we're looking at
1713 * @update_slave_arr: Does slave array need update?
1697 */ 1714 */
1698static void ad_disable_collecting_distributing(struct port *port) 1715static void ad_disable_collecting_distributing(struct port *port,
1716 bool *update_slave_arr)
1699{ 1717{
1700 if (port->aggregator && 1718 if (port->aggregator &&
1701 !MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system), 1719 !MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system),
@@ -1704,6 +1722,8 @@ static void ad_disable_collecting_distributing(struct port *port)
1704 port->actor_port_number, 1722 port->actor_port_number,
1705 port->aggregator->aggregator_identifier); 1723 port->aggregator->aggregator_identifier);
1706 __disable_port(port); 1724 __disable_port(port);
1725 /* Slave array needs an update */
1726 *update_slave_arr = true;
1707 } 1727 }
1708} 1728}
1709 1729
@@ -1868,6 +1888,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
1868 struct bonding *bond = slave->bond; 1888 struct bonding *bond = slave->bond;
1869 struct slave *slave_iter; 1889 struct slave *slave_iter;
1870 struct list_head *iter; 1890 struct list_head *iter;
1891 bool dummy_slave_update; /* Ignore this value as caller updates array */
1871 1892
1872 /* Sync against bond_3ad_state_machine_handler() */ 1893 /* Sync against bond_3ad_state_machine_handler() */
1873 spin_lock_bh(&bond->mode_lock); 1894 spin_lock_bh(&bond->mode_lock);
@@ -1951,7 +1972,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
1951 ad_clear_agg(aggregator); 1972 ad_clear_agg(aggregator);
1952 1973
1953 if (select_new_active_agg) 1974 if (select_new_active_agg)
1954 ad_agg_selection_logic(__get_first_agg(port)); 1975 ad_agg_selection_logic(__get_first_agg(port),
1976 &dummy_slave_update);
1955 } else { 1977 } else {
1956 netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n"); 1978 netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n");
1957 } 1979 }
@@ -1966,7 +1988,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
1966 /* select new active aggregator */ 1988 /* select new active aggregator */
1967 temp_aggregator = __get_first_agg(port); 1989 temp_aggregator = __get_first_agg(port);
1968 if (temp_aggregator) 1990 if (temp_aggregator)
1969 ad_agg_selection_logic(temp_aggregator); 1991 ad_agg_selection_logic(temp_aggregator,
1992 &dummy_slave_update);
1970 } 1993 }
1971 } 1994 }
1972 } 1995 }
@@ -1996,7 +2019,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
1996 if (select_new_active_agg) { 2019 if (select_new_active_agg) {
1997 netdev_info(bond->dev, "Removing an active aggregator\n"); 2020 netdev_info(bond->dev, "Removing an active aggregator\n");
1998 /* select new active aggregator */ 2021 /* select new active aggregator */
1999 ad_agg_selection_logic(__get_first_agg(port)); 2022 ad_agg_selection_logic(__get_first_agg(port),
2023 &dummy_slave_update);
2000 } 2024 }
2001 } 2025 }
2002 break; 2026 break;
@@ -2031,6 +2055,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
2031 struct slave *slave; 2055 struct slave *slave;
2032 struct port *port; 2056 struct port *port;
2033 bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; 2057 bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
2058 bool update_slave_arr = false;
2034 2059
2035 /* Lock to protect data accessed by all (e.g., port->sm_vars) and 2060 /* Lock to protect data accessed by all (e.g., port->sm_vars) and
2036 * against running with bond_3ad_unbind_slave. ad_rx_machine may run 2061 * against running with bond_3ad_unbind_slave. ad_rx_machine may run
@@ -2058,7 +2083,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
2058 } 2083 }
2059 2084
2060 aggregator = __get_first_agg(port); 2085 aggregator = __get_first_agg(port);
2061 ad_agg_selection_logic(aggregator); 2086 ad_agg_selection_logic(aggregator, &update_slave_arr);
2062 } 2087 }
2063 bond_3ad_set_carrier(bond); 2088 bond_3ad_set_carrier(bond);
2064 } 2089 }
@@ -2074,8 +2099,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
2074 2099
2075 ad_rx_machine(NULL, port); 2100 ad_rx_machine(NULL, port);
2076 ad_periodic_machine(port); 2101 ad_periodic_machine(port);
2077 ad_port_selection_logic(port); 2102 ad_port_selection_logic(port, &update_slave_arr);
2078 ad_mux_machine(port); 2103 ad_mux_machine(port, &update_slave_arr);
2079 ad_tx_machine(port); 2104 ad_tx_machine(port);
2080 2105
2081 /* turn off the BEGIN bit, since we already handled it */ 2106 /* turn off the BEGIN bit, since we already handled it */
@@ -2093,6 +2118,9 @@ re_arm:
2093 rcu_read_unlock(); 2118 rcu_read_unlock();
2094 spin_unlock_bh(&bond->mode_lock); 2119 spin_unlock_bh(&bond->mode_lock);
2095 2120
2121 if (update_slave_arr)
2122 bond_slave_arr_work_rearm(bond, 0);
2123
2096 if (should_notify_rtnl && rtnl_trylock()) { 2124 if (should_notify_rtnl && rtnl_trylock()) {
2097 bond_slave_state_notify(bond); 2125 bond_slave_state_notify(bond);
2098 rtnl_unlock(); 2126 rtnl_unlock();
@@ -2283,6 +2311,11 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
2283 port->sm_vars |= AD_PORT_BEGIN; 2311 port->sm_vars |= AD_PORT_BEGIN;
2284 2312
2285 spin_unlock_bh(&slave->bond->mode_lock); 2313 spin_unlock_bh(&slave->bond->mode_lock);
2314
2315 /* RTNL is held and mode_lock is released so it's safe
2316 * to update slave_array here.
2317 */
2318 bond_update_slave_arr(slave->bond, NULL);
2286} 2319}
2287 2320
2288/** 2321/**
@@ -2377,73 +2410,6 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
2377 return ret; 2410 return ret;
2378} 2411}
2379 2412
2380int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
2381{
2382 struct bonding *bond = netdev_priv(dev);
2383 struct slave *slave, *first_ok_slave;
2384 struct aggregator *agg;
2385 struct ad_info ad_info;
2386 struct list_head *iter;
2387 int slaves_in_agg;
2388 int slave_agg_no;
2389 int agg_id;
2390
2391 if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
2392 netdev_dbg(dev, "__bond_3ad_get_active_agg_info failed\n");
2393 goto err_free;
2394 }
2395
2396 slaves_in_agg = ad_info.ports;
2397 agg_id = ad_info.aggregator_id;
2398
2399 if (slaves_in_agg == 0) {
2400 netdev_dbg(dev, "active aggregator is empty\n");
2401 goto err_free;
2402 }
2403
2404 slave_agg_no = bond_xmit_hash(bond, skb) % slaves_in_agg;
2405 first_ok_slave = NULL;
2406
2407 bond_for_each_slave_rcu(bond, slave, iter) {
2408 agg = SLAVE_AD_INFO(slave)->port.aggregator;
2409 if (!agg || agg->aggregator_identifier != agg_id)
2410 continue;
2411
2412 if (slave_agg_no >= 0) {
2413 if (!first_ok_slave && bond_slave_can_tx(slave))
2414 first_ok_slave = slave;
2415 slave_agg_no--;
2416 continue;
2417 }
2418
2419 if (bond_slave_can_tx(slave)) {
2420 bond_dev_queue_xmit(bond, skb, slave->dev);
2421 goto out;
2422 }
2423 }
2424
2425 if (slave_agg_no >= 0) {
2426 netdev_err(dev, "Couldn't find a slave to tx on for aggregator ID %d\n",
2427 agg_id);
2428 goto err_free;
2429 }
2430
2431 /* we couldn't find any suitable slave after the agg_no, so use the
2432 * first suitable found, if found.
2433 */
2434 if (first_ok_slave)
2435 bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
2436 else
2437 goto err_free;
2438
2439out:
2440 return NETDEV_TX_OK;
2441err_free:
2442 /* no suitable interface, frame not sent */
2443 dev_kfree_skb_any(skb);
2444 goto out;
2445}
2446
2447int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, 2413int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
2448 struct slave *slave) 2414 struct slave *slave)
2449{ 2415{