Skip to content

Commit ee63771

Browse files
Mahesh Bandewardavem330
Mahesh Bandewar
authored andcommitted
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 <[email protected]> Signed-off-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d702132 commit ee63771

File tree

5 files changed

+249
-152
lines changed

5 files changed

+249
-152
lines changed

drivers/net/bonding/bond_3ad.c

+53-87
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,20 @@ static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
102102
/* ================= main 802.3ad protocol functions ================== */
103103
static int ad_lacpdu_send(struct port *port);
104104
static int ad_marker_send(struct port *port, struct bond_marker *marker);
105-
static void ad_mux_machine(struct port *port);
105+
static void ad_mux_machine(struct port *port, bool *update_slave_arr);
106106
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
107107
static void ad_tx_machine(struct port *port);
108108
static void ad_periodic_machine(struct port *port);
109-
static void ad_port_selection_logic(struct port *port);
110-
static void ad_agg_selection_logic(struct aggregator *aggregator);
109+
static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
110+
static void ad_agg_selection_logic(struct aggregator *aggregator,
111+
bool *update_slave_arr);
111112
static void ad_clear_agg(struct aggregator *aggregator);
112113
static void ad_initialize_agg(struct aggregator *aggregator);
113114
static void ad_initialize_port(struct port *port, int lacp_fast);
114-
static void ad_enable_collecting_distributing(struct port *port);
115-
static void ad_disable_collecting_distributing(struct port *port);
115+
static void ad_enable_collecting_distributing(struct port *port,
116+
bool *update_slave_arr);
117+
static void ad_disable_collecting_distributing(struct port *port,
118+
bool *update_slave_arr);
116119
static void ad_marker_info_received(struct bond_marker *marker_info,
117120
struct port *port);
118121
static 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)
796799
/**
797800
* ad_mux_machine - handle a port's mux state machine
798801
* @port: the port we're looking at
802+
* @update_slave_arr: Does slave array need update?
799803
*/
800-
static void ad_mux_machine(struct port *port)
804+
static void ad_mux_machine(struct port *port, bool *update_slave_arr)
801805
{
802806
mux_states_t last_state;
803807

@@ -901,7 +905,8 @@ static void ad_mux_machine(struct port *port)
901905
switch (port->sm_mux_state) {
902906
case AD_MUX_DETACHED:
903907
port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
904-
ad_disable_collecting_distributing(port);
908+
ad_disable_collecting_distributing(port,
909+
update_slave_arr);
905910
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
906911
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
907912
port->ntt = true;
@@ -913,13 +918,15 @@ static void ad_mux_machine(struct port *port)
913918
port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
914919
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
915920
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
916-
ad_disable_collecting_distributing(port);
921+
ad_disable_collecting_distributing(port,
922+
update_slave_arr);
917923
port->ntt = true;
918924
break;
919925
case AD_MUX_COLLECTING_DISTRIBUTING:
920926
port->actor_oper_port_state |= AD_STATE_COLLECTING;
921927
port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
922-
ad_enable_collecting_distributing(port);
928+
ad_enable_collecting_distributing(port,
929+
update_slave_arr);
923930
port->ntt = true;
924931
break;
925932
default:
@@ -1187,12 +1194,13 @@ static void ad_periodic_machine(struct port *port)
11871194
/**
11881195
* ad_port_selection_logic - select aggregation groups
11891196
* @port: the port we're looking at
1197+
* @update_slave_arr: Does slave array need update?
11901198
*
11911199
* Select aggregation groups, and assign each port for it's aggregetor. The
11921200
* selection logic is called in the inititalization (after all the handshkes),
11931201
* and after every lacpdu receive (if selected is off).
11941202
*/
1195-
static void ad_port_selection_logic(struct port *port)
1203+
static void ad_port_selection_logic(struct port *port, bool *update_slave_arr)
11961204
{
11971205
struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator;
11981206
struct port *last_port = NULL, *curr_port;
@@ -1347,7 +1355,7 @@ static void ad_port_selection_logic(struct port *port)
13471355
__agg_ports_are_ready(port->aggregator));
13481356

13491357
aggregator = __get_first_agg(port);
1350-
ad_agg_selection_logic(aggregator);
1358+
ad_agg_selection_logic(aggregator, update_slave_arr);
13511359
}
13521360

13531361
/* 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)
14351443
/**
14361444
* ad_agg_selection_logic - select an aggregation group for a team
14371445
* @aggregator: the aggregator we're looking at
1446+
* @update_slave_arr: Does slave array need update?
14381447
*
14391448
* It is assumed that only one aggregator may be selected for a team.
14401449
*
@@ -1457,7 +1466,8 @@ static int agg_device_up(const struct aggregator *agg)
14571466
* __get_active_agg() won't work correctly. This function should be better
14581467
* called with the bond itself, and retrieve the first agg from it.
14591468
*/
1460-
static void ad_agg_selection_logic(struct aggregator *agg)
1469+
static void ad_agg_selection_logic(struct aggregator *agg,
1470+
bool *update_slave_arr)
14611471
{
14621472
struct aggregator *best, *active, *origin;
14631473
struct bonding *bond = agg->slave->bond;
@@ -1550,6 +1560,8 @@ static void ad_agg_selection_logic(struct aggregator *agg)
15501560
__disable_port(port);
15511561
}
15521562
}
1563+
/* Slave array needs update. */
1564+
*update_slave_arr = true;
15531565
}
15541566

15551567
/* if the selected aggregator is of join individuals
@@ -1678,24 +1690,30 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
16781690
/**
16791691
* ad_enable_collecting_distributing - enable a port's transmit/receive
16801692
* @port: the port we're looking at
1693+
* @update_slave_arr: Does slave array need update?
16811694
*
16821695
* Enable @port if it's in an active aggregator
16831696
*/
1684-
static void ad_enable_collecting_distributing(struct port *port)
1697+
static void ad_enable_collecting_distributing(struct port *port,
1698+
bool *update_slave_arr)
16851699
{
16861700
if (port->aggregator->is_active) {
16871701
pr_debug("Enabling port %d(LAG %d)\n",
16881702
port->actor_port_number,
16891703
port->aggregator->aggregator_identifier);
16901704
__enable_port(port);
1705+
/* Slave array needs update */
1706+
*update_slave_arr = true;
16911707
}
16921708
}
16931709

16941710
/**
16951711
* ad_disable_collecting_distributing - disable a port's transmit/receive
16961712
* @port: the port we're looking at
1713+
* @update_slave_arr: Does slave array need update?
16971714
*/
1698-
static void ad_disable_collecting_distributing(struct port *port)
1715+
static void ad_disable_collecting_distributing(struct port *port,
1716+
bool *update_slave_arr)
16991717
{
17001718
if (port->aggregator &&
17011719
!MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system),
@@ -1704,6 +1722,8 @@ static void ad_disable_collecting_distributing(struct port *port)
17041722
port->actor_port_number,
17051723
port->aggregator->aggregator_identifier);
17061724
__disable_port(port);
1725+
/* Slave array needs an update */
1726+
*update_slave_arr = true;
17071727
}
17081728
}
17091729

@@ -1868,6 +1888,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
18681888
struct bonding *bond = slave->bond;
18691889
struct slave *slave_iter;
18701890
struct list_head *iter;
1891+
bool dummy_slave_update; /* Ignore this value as caller updates array */
18711892

18721893
/* Sync against bond_3ad_state_machine_handler() */
18731894
spin_lock_bh(&bond->mode_lock);
@@ -1951,7 +1972,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
19511972
ad_clear_agg(aggregator);
19521973

19531974
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);
19551977
} else {
19561978
netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n");
19571979
}
@@ -1966,7 +1988,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
19661988
/* select new active aggregator */
19671989
temp_aggregator = __get_first_agg(port);
19681990
if (temp_aggregator)
1969-
ad_agg_selection_logic(temp_aggregator);
1991+
ad_agg_selection_logic(temp_aggregator,
1992+
&dummy_slave_update);
19701993
}
19711994
}
19721995
}
@@ -1996,7 +2019,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
19962019
if (select_new_active_agg) {
19972020
netdev_info(bond->dev, "Removing an active aggregator\n");
19982021
/* 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);
20002024
}
20012025
}
20022026
break;
@@ -2031,6 +2055,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
20312055
struct slave *slave;
20322056
struct port *port;
20332057
bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
2058+
bool update_slave_arr = false;
20342059

20352060
/* Lock to protect data accessed by all (e.g., port->sm_vars) and
20362061
* 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)
20582083
}
20592084

20602085
aggregator = __get_first_agg(port);
2061-
ad_agg_selection_logic(aggregator);
2086+
ad_agg_selection_logic(aggregator, &update_slave_arr);
20622087
}
20632088
bond_3ad_set_carrier(bond);
20642089
}
@@ -2074,8 +2099,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
20742099

20752100
ad_rx_machine(NULL, port);
20762101
ad_periodic_machine(port);
2077-
ad_port_selection_logic(port);
2078-
ad_mux_machine(port);
2102+
ad_port_selection_logic(port, &update_slave_arr);
2103+
ad_mux_machine(port, &update_slave_arr);
20792104
ad_tx_machine(port);
20802105

20812106
/* turn off the BEGIN bit, since we already handled it */
@@ -2093,6 +2118,9 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
20932118
rcu_read_unlock();
20942119
spin_unlock_bh(&bond->mode_lock);
20952120

2121+
if (update_slave_arr)
2122+
bond_slave_arr_work_rearm(bond, 0);
2123+
20962124
if (should_notify_rtnl && rtnl_trylock()) {
20972125
bond_slave_state_notify(bond);
20982126
rtnl_unlock();
@@ -2283,6 +2311,11 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
22832311
port->sm_vars |= AD_PORT_BEGIN;
22842312

22852313
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);
22862319
}
22872320

22882321
/**
@@ -2377,73 +2410,6 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
23772410
return ret;
23782411
}
23792412

2380-
int 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-
2439-
out:
2440-
return NETDEV_TX_OK;
2441-
err_free:
2442-
/* no suitable interface, frame not sent */
2443-
dev_kfree_skb_any(skb);
2444-
goto out;
2445-
}
2446-
24472413
int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
24482414
struct slave *slave)
24492415
{

0 commit comments

Comments
 (0)