[dpdk-dev] [PATCH v2] ADD mode 5(tlb) to link bonding pmd

Jiajia, SunX sunx.jiajia at intel.com
Tue Nov 25 10:17:00 CET 2014


Tested-by: Jiajia, SunX <sunx.jiajia at intel.com>
- Tested Commit: f7aaae2fe6f7f9a78eab7313d77e92b934693b5d
- OS: Fedora20 3.11.10-301.fc20.x86_64 and 3.16.6-200.fc20.x86_64
- GCC: gcc version 4.8.2
- CPU: Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz
- NIC: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10fb]
- Default x86_64-native-linuxapp-gcc configuration
- Total 4 cases, 4 passed, 0 failed

TOPO:
Setup#1
* Connections ports between tester/ixia and DUT
  - TESTER(Or IXIA)-------DUT
  - portA------------------port0
  - portB------------------port1
  - portC------------------port2
  - portD------------------port3

Test Case1: Mode 5(Transmit load balance) basic test
============================================================================

Use Setup#1

Create bonded device. Add first slave - port 0. Verify default bonded device has default mode 5. Verify bonded device MAC address is that of primary slave. Add another slaves port 1 and 2 to the bonded device. Verify that their MAC are different.

Bring the primary slave down. Verify if bonding interface reconfigured itself. The next port (in this scenario port 1) should became a primary one but the MAC should not be changed - should still be the MAC of port 0.

Bring a slave of bonding device down. Verify if bonding interface reconfigured itself.

Bring the portA, portB and portC down. Verify the bonded device will link down.

Set bonded device promiscuous mode to be off. Verify only the promiscuous state of primary interface will be off.


Test Case2: Mode 5(Transmit load balance)  TX/RX test
============================================================================

Use Setup#1

Create a bonded device(port4 in this scenario). Add port 0-2 as slaves of bonding port4. Make packets to transmit between port3 and port4. Then start to forward streams.

TX: Prepare a packet stream which will send packets in 5 minutes. Send this stream from portD to port3. Verify that port3 will receive all packets---no missed packets and no error packets. Port 0-2 transmitting packets will be represented as packet0, packet1 and packet2 respectively and their average packets will be represented as mean.  Then verify port 0-2 will meet the situation:
mean = (packet0 + packet1 + packet2)/3, packet0, packet1 and packet2 will be higher than 90% of mean and lower than 110% of mean. Then the test of port0, port1 and port2 balancing are finished positive.

RX: A continuation of TX testing setup. Prepare 3 packet streams and each stream has 100 packets. Respectively, send these streams from portA, portB and portC. Verify only the primary slave port0 will receive 100 packets, and port3 will transmit 100 packets.


Test Case3: Mode 5(Transmit load balance)  Bring one slave link down
============================================================================

Use Setup#1

Create a bonded device(port4 in this scenario). Add port0, port1 and port2 as slaves of bonding port4. Make packets to transmit between port3 and port4. Then start to forward streams.

TX: Prepare a packet stream which will send packets in 5 minutes. Bringing port0 link down in the remote end. Send this stream from portD to port3. After the time of 5 minutes is out, verify that port3 will receive all packets---no missed packets and no error packets. Port 1-2 transmitting packets will be represented as packet1 and packet2 respectively and their average packets will be represented as mean. Then verify port1 and port2 will meet the situation:
mean = (packet1 + packet2)/2, packet1 and packet2 will be higher than 90% of mean and lower than 110% of mean. Then the test of port1 and port2 balancing are finished positive.

RX: Prepare 3 packet streams and each stream has 100 packets. Respectively, send these streams from portA, portB and portC. Verify the primary port(port0 this scenario) will receive 100 packets, and port1 and port2 will receive nothing, and port3 will transmit 100 packets.


Test Case4: Mode 5(Transmit load balance)  Bring all slaves link down
=============================================================================

Use Setup#1

First, set the same setup as case 30. Second, bring all slaves link down.

TX: Prepare 1 packet stream which will have 300 packets. Send this stream from portD to port3. Verify port0, port1 and port2 will transmit nothing.

RX: Prepare 3 packet streams and each stream has 100 packets. Respectively, send these streams from portA, portB and portC. Verify port0, port1 and port2 will receive nothing.

> -----Original Message-----
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Doherty, Declan
> Sent: Tuesday, October 07, 2014 4:20 PM
> To: dev at dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2] ADD mode 5(tlb) to link bonding pmd
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Daniel Mrzyglod
> > Sent: Friday, September 26, 2014 4:41 PM
> > To: dev at dpdk.org
> > Subject: [dpdk-dev] [PATCH v2] ADD mode 5(tlb) to link bonding pmd
> >
> >
> > Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod at intel.com>
> > ---
> >  app/test/test_link_bonding.c               |  501
> +++++++++++++++++++++++++++-
> >  app/test/virtual_pmd.c                     |    6 +-
> >  app/test/virtual_pmd.h                     |    7 +
> >  lib/librte_pmd_bond/rte_eth_bond.h         |   23 ++
> >  lib/librte_pmd_bond/rte_eth_bond_args.c    |    1 +
> >  lib/librte_pmd_bond/rte_eth_bond_pmd.c     |  161 ++++++++-
> >  lib/librte_pmd_bond/rte_eth_bond_private.h |    3 +-
> >  7 files changed, 696 insertions(+), 6 deletions(-)
> >
> > diff --git a/app/test/test_link_bonding.c
> b/app/test/test_link_bonding.c
> > index c4fcaf7..77f791f 100644
> > --- a/app/test/test_link_bonding.c
> > +++ b/app/test/test_link_bonding.c
> > @@ -41,7 +41,7 @@
> >  #include <errno.h>
> >  #include <sys/queue.h>
> >  #include <sys/time.h>
> > -
> > +#include <rte_cycles.h>
> >  #include <rte_byteorder.h>
> >  #include <rte_common.h>
> >  #include <rte_debug.h>
> > @@ -3845,6 +3845,500 @@ testsuite_teardown(void)
> >  	return remove_slaves_and_stop_bonded_device();
> >  }
> >
> > +#define NINETY_PERCENT_NUMERAL 90
> > +#define ONE_HUNDRED_PERCENT_DENOMINATOR 100
> > +#define ONE_HUNDRED_PERCENT_AND_TEN_NUMERAL 110
> > +static int
> > +test_tlb_tx_burst(void)
> > +{
> > +	int i, burst_size, nb_tx;
> > +	uint64_t nb_tx2 = 0;
> > +	struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
> > +	struct rte_eth_stats port_stats[32];
> > +	uint64_t sum_ports_opackets = 0, all_bond_opackets = 0,
> > all_bond_obytes = 0;
> > +	uint16_t pktlen;
> > +
> > +	TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves
> > +
> > 	(BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING, 1, 3, 1),
> > +			"Failed to initialise bonded device");
> > +
> > +	burst_size = 20 * test_params->bonded_slave_count;
> > +
> > +	TEST_ASSERT(burst_size < MAX_PKT_BURST,
> > +			"Burst size specified is greater than supported.\n");
> > +
> > +
> > +	/* Generate 400000 test bursts in 2s of packets to transmit  */
> > +	for (i = 0; i < 400000; i++) {
> > +		/*test two types of mac src own(bonding) and others */
> > +		if (i % 2 == 0) {
> > +			initialize_eth_header(test_params->pkt_eth_hdr,
> > +					(struct ether_addr *)src_mac, (struct
> > ether_addr *)dst_mac_0, 0, 0);
> > +		} else {
> > +			initialize_eth_header(test_params->pkt_eth_hdr,
> > +					(struct ether_addr *)test_params-
> > >default_slave_mac,
> > +					(struct ether_addr *)dst_mac_0, 0, 0);
> > +		}
> > +		pktlen = initialize_udp_header(test_params->pkt_udp_hdr,
> > src_port,
> > +				dst_port_0, 16);
> > +		pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr,
> > src_addr,
> > +				dst_addr_0, pktlen);
> > +		generate_packet_burst(test_params->mbuf_pool, pkt_burst,
> > +				test_params->pkt_eth_hdr, 0, test_params-
> > >pkt_ipv4_hdr,
> > +				1, test_params->pkt_udp_hdr, burst_size, 60, 1);
> > +		/* Send burst on bonded port */
> > +		nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0,
> > pkt_burst,
> > +				burst_size);
> > +		nb_tx2 += nb_tx;
> > +
> > +		TEST_ASSERT_EQUAL(nb_tx, burst_size,
> > +				"number of packet not equal burst size");
> > +
> > +		rte_delay_us(5);
> > +	}
> > +
> > +
> > +	/* Verify bonded port tx stats */
> > +	rte_eth_stats_get(test_params->bonded_port_id, &port_stats[0]);
> > +
> > +	all_bond_opackets = port_stats[0].opackets;
> > +	all_bond_obytes = port_stats[0].obytes;
> > +
> > +	TEST_ASSERT_EQUAL(port_stats[0].opackets, (uint64_t)nb_tx2,
> > +			"Bonded Port (%d) opackets value (%u) not as expected
> > (%d)\n",
> > +			test_params->bonded_port_id, (unsigned
> > int)port_stats[0].opackets,
> > +			burst_size);
> > +
> > +
> > +	/* Verify slave ports tx stats */
> > +	for (i = 0; i < test_params->bonded_slave_count; i++) {
> > +		rte_eth_stats_get(test_params->slave_port_ids[i],
> &port_stats[i]);
> > +		sum_ports_opackets += port_stats[i].opackets;
> > +	}
> > +
> > +	TEST_ASSERT_EQUAL(sum_ports_opackets, (uint64_t)all_bond_opackets,
> > +			"Total packets sent by slaves is not equalto packets
> sent by
> > bond interface");
> > +
> > +	for (i = 0; i < test_params->bonded_slave_count; i++) {
> > +		printf("port stats:%"PRIu64"\n", port_stats[i].opackets);
> > +		/* distribution of packets on each slave within +/- 10% of
> the
> > expected value. */
> > +		TEST_ASSERT(port_stats[i].obytes >=
> > ((all_bond_obytes*NINETY_PERCENT_NUMERAL)/
> > +				(test_params-
> > >bonded_slave_count*ONE_HUNDRED_PERCENT_DENOMINATOR)) &&
> > +				port_stats[i].obytes <=
> > ((all_bond_obytes*ONE_HUNDRED_PERCENT_AND_TEN_NUMERAL) /
> > +						(test_params-
> > >bonded_slave_count*ONE_HUNDRED_PERCENT_DENOMINATOR)),
> > +						"Distribution is not even");
> > +	}
> > +	/* Put all slaves down and try and transmit */
> > +	for (i = 0; i < test_params->bonded_slave_count; i++) {
> > +		virtual_ethdev_simulate_link_status_interrupt(
> > +				test_params->slave_port_ids[i], 0);
> > +	}
> > +
> > +	/* Send burst on bonded port */
> > +	nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0,
> pkt_burst,
> > +			burst_size);
> > +	TEST_ASSERT_EQUAL(nb_tx, 0, " bad number of packet in burst");
> > +
> > +	/* Clean ugit checkout masterp and remove slaves from bonded
> device */
> > +	return remove_slaves_and_stop_bonded_device();
> > +}
> > +
> > +#define
> > TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT (4)
> > +
> > +static int
> > +test_tlb_rx_burst(void)
> > +{
> > +	struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
> > +	struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
> > +
> > +	struct rte_eth_stats port_stats;
> > +
> > +	int primary_port;
> > +
> > +	uint16_t i, j, nb_rx, burst_size = 17;
> > +
> > +	/* Initialize bonded device with 4 slaves in transmit load
> balancing mode
> > */
> > +	TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
> > +
> > 	BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING,
> > +
> > 	TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT
> > , 1, 1),
> > +			"Failed to initialize bonded device");
> > +
> > +
> > +	primary_port = rte_eth_bond_primary_get(test_params-
> > >bonded_port_id);
> > +	TEST_ASSERT(primary_port >= 0,
> > +			"failed to get primary slave for bonded port (%d)",
> > +			test_params->bonded_port_id);
> > +
> > +	for (i = 0; i < test_params->bonded_slave_count; i++) {
> > +		/* Generate test bursts of packets to transmit */
> > +		TEST_ASSERT_EQUAL(generate_test_burst(
> > +				&gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0),
> > burst_size,
> > +				"burst generation failed");
> > +
> > +		/* Add rx data to slave */
> > +		virtual_ethdev_add_mbufs_to_rx_queue(test_params-
> > >slave_port_ids[i],
> > +				&gen_pkt_burst[0], burst_size);
> > +
> > +		/* Call rx burst on bonded device */
> > +		nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0,
> > +				&rx_pkt_burst[0], MAX_PKT_BURST);
> > +
> > +		TEST_ASSERT_EQUAL(nb_rx,burst_size,"rte_eth_rx_burst
> > failed\n");
> > +
> > +		if (test_params->slave_port_ids[i] == primary_port) {
> > +			/* Verify bonded device rx count */
> > +			rte_eth_stats_get(test_params->bonded_port_id,
> > &port_stats);
> > +			TEST_ASSERT_EQUAL(port_stats.ipackets,
> > (uint64_t)burst_size,
> > +					"Bonded Port (%d) ipackets value (%u) not
> > as expected (%d)\n",
> > +					test_params->bonded_port_id,
> > +					(unsigned int)port_stats.ipackets,
> > burst_size);
> > +
> > +			/* Verify bonded slave devices rx count */
> > +			for (j = 0; j < test_params->bonded_slave_count; j++)
> {
> > +				rte_eth_stats_get(test_params-
> >slave_port_ids[j],
> > &port_stats);
> > +				if (i == j) {
> > +					TEST_ASSERT_EQUAL(port_stats.ipackets,
> > (uint64_t)burst_size,
> > +							"Slave Port (%d) ipackets
> > value (%u) not as expected (%d)\n",
> > +							test_params-
> > >slave_port_ids[i],
> > +							(unsigned
> > int)port_stats.ipackets, burst_size);
> > +				} else {
> > +					TEST_ASSERT_EQUAL(port_stats.ipackets,
> > (uint64_t)0,
> > +							"Slave Port (%d) ipackets
> > value (%u) not as expected (%d)\n",
> > +							test_params-
> > >slave_port_ids[i],
> > +							(unsigned
> > int)port_stats.ipackets, 0);
> > +				}
> > +			}
> > +		} else {
> > +			for (j = 0; j < test_params->bonded_slave_count; j++)
> {
> > +				rte_eth_stats_get(test_params-
> >slave_port_ids[j],
> > &port_stats);
> > +				TEST_ASSERT_EQUAL(port_stats.ipackets,
> > (uint64_t)0,
> > +						"Slave Port (%d) ipackets value
> > (%u) not as expected (%d)\n",
> > +						test_params->slave_port_ids[i],
> > +						(unsigned int)port_stats.ipackets,
> > 0);
> > +			}
> > +		}
> > +
> > +		/* free mbufs */
> > +		for (i = 0; i < burst_size; i++)
> > +			rte_pktmbuf_free(rx_pkt_burst[i]);
> > +
> > +		/* reset bonded device stats */
> > +		rte_eth_stats_reset(test_params->bonded_port_id);
> > +	}
> > +
> > +	/* Clean up and remove slaves from bonded device */
> > +	return remove_slaves_and_stop_bonded_device();
> > +}
> > +
> > +static int
> > +test_tlb_verify_promiscuous_enable_disable(void)
> > +{
> > +	int i, primary_port, promiscuous_en;
> > +
> > +	/* Initialize bonded device with 4 slaves in transmit load
> balancing mode
> > */
> > +	TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves(
> > +
> > 	BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING, 0, 4, 1),
> > +			"Failed to initialize bonded device");
> > +
> > +	primary_port = rte_eth_bond_primary_get(test_params-
> > >bonded_port_id);
> > +	TEST_ASSERT(primary_port >= 0,
> > +			"failed to get primary slave for bonded port (%d)",
> > +			test_params->bonded_port_id);
> > +
> > +	rte_eth_promiscuous_enable(test_params->bonded_port_id);
> > +
> > +	promiscuous_en = rte_eth_promiscuous_get(test_params-
> > >bonded_port_id);
> > +	TEST_ASSERT_EQUAL(promiscuous_en, (int)1,
> > +			"Port (%d) promiscuous mode not enabled\n",
> > +			test_params->bonded_port_id);
> > +	for (i = 0; i < test_params->bonded_slave_count; i++) {
> > +		promiscuous_en = rte_eth_promiscuous_get(
> > +				test_params->slave_port_ids[i]);
> > +		if (primary_port == test_params->slave_port_ids[i]) {
> > +			TEST_ASSERT_EQUAL(promiscuous_en, (int)1,
> > +					"Port (%d) promiscuous mode not
> > enabled\n",
> > +					test_params->bonded_port_id);
> > +		} else {
> > +			TEST_ASSERT_EQUAL(promiscuous_en, (int)0,
> > +					"Port (%d) promiscuous mode enabled\n",
> > +					test_params->bonded_port_id);
> > +		}
> > +
> > +	}
> > +
> > +	rte_eth_promiscuous_disable(test_params->bonded_port_id);
> > +
> > +	promiscuous_en = rte_eth_promiscuous_get(test_params-
> > >bonded_port_id);
> > +	TEST_ASSERT_EQUAL(promiscuous_en, (int)0,
> > +			"Port (%d) promiscuous mode not disabled\n",
> > +			test_params->bonded_port_id);
> > +
> > +	for (i = 0; i < test_params->bonded_slave_count; i++) {
> > +		promiscuous_en = rte_eth_promiscuous_get(
> > +				test_params->slave_port_ids[i]);
> > +		TEST_ASSERT_EQUAL(promiscuous_en, (int)0,
> > +				"slave port (%d) promiscuous mode not
> > disabled\n",
> > +				test_params->slave_port_ids[i]);
> > +	}
> > +
> > +	/* Clean up and remove slaves from bonded device */
> > +	return remove_slaves_and_stop_bonded_device();
> > +}
> > +
> > +static int
> > +test_tlb_verify_mac_assignment(void)
> > +{
> > +	struct ether_addr read_mac_addr, expected_mac_addr_0,
> > expected_mac_addr_1;
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[0],
> > &expected_mac_addr_0);
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[1],
> > &expected_mac_addr_1);
> > +
> > +	/* Initialize bonded device with 2 slaves in active backup mode
> */
> > +	TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
> > +
> > 	BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING, 0, 2, 1),
> > +			"Failed to initialize bonded device");
> > +
> > +	/* Verify that bonded MACs is that of first slave and that the
> other slave
> > +	 * MAC hasn't been changed */
> > +	rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"bonded port (%d) mac address not set to that of
> primary
> > port",
> > +			test_params->bonded_port_id);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[0],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not set to that of
> primary
> > port",
> > +			test_params->slave_port_ids[0]);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[1],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not as expected",
> > +			test_params->slave_port_ids[1]);
> > +
> > +	/* change primary and verify that MAC addresses haven't changed
> */
> > +	TEST_ASSERT_EQUAL(rte_eth_bond_primary_set(test_params-
> > >bonded_port_id,
> > +			test_params->slave_port_ids[1]), 0,
> > +			"Failed to set bonded port (%d) primary port to (%d)",
> > +			test_params->bonded_port_id, test_params-
> > >slave_port_ids[1]);
> > +
> > +	rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"bonded port (%d) mac address not set to that of
> primary
> > port",
> > +			test_params->bonded_port_id);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[0],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not set to that of
> primary
> > port",
> > +			test_params->slave_port_ids[0]);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[1],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not as expected",
> > +			test_params->slave_port_ids[1]);
> > +
> > +	/* stop / start bonded device and verify that primary MAC address
> is
> > +	 * propagated to bonded device and slaves */
> > +
> > +	rte_eth_dev_stop(test_params->bonded_port_id);
> > +
> > +	TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params-
> > >bonded_port_id),
> > +			"Failed to start device");
> > +
> > +	rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"bonded port (%d) mac address not set to that of
> primary
> > port",
> > +			test_params->bonded_port_id);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[0],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not as expected",
> > +			test_params->slave_port_ids[0]);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[1],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not set to that of
> primary
> > port",
> > +			test_params->slave_port_ids[1]);
> > +
> > +
> > +	/* Set explicit MAC address */
> > +	TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
> > +			test_params->bonded_port_id, (struct ether_addr
> > *)bonded_mac),
> > +			"failed to set MAC addres");
> > +
> > +	rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"bonded port (%d) mac address not set to that of
> bonded
> > port",
> > +			test_params->bonded_port_id);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[0],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0,
> > &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not as expected",
> > +			test_params->slave_port_ids[0]);
> > +
> > +	rte_eth_macaddr_get(test_params->slave_port_ids[1],
> > &read_mac_addr);
> > +	TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
> > +			sizeof(read_mac_addr)),
> > +			"slave port (%d) mac address not set to that of
> bonded
> > port",
> > +			test_params->slave_port_ids[1]);
> > +
> > +	/* Clean up and remove slaves from bonded device */
> > +	return remove_slaves_and_stop_bonded_device();
> > +}
> > +
> > +static int
> > +test_tlb_verify_slave_link_status_change_failover(void)
> > +{
> > +	struct rte_mbuf
> > *pkt_burst[TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_CO
> > UNT][MAX_PKT_BURST];
> > +	struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
> > +	struct rte_eth_stats port_stats;
> > +
> > +	uint8_t slaves[RTE_MAX_ETHPORTS];
> > +
> > +	int i, j, burst_size, slave_count, primary_port;
> > +
> > +	burst_size = 21;
> > +
> > +	memset(pkt_burst, 0, sizeof(pkt_burst));
> > +
> > +
> > +
> > +	/* Initialize bonded device with 4 slaves in round robin mode */
> > +	TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
> > +
> > 	BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING, 0,
> > +
> > 	TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT
> > , 1),
> > +			"Failed to initialize bonded device with slaves");
> > +
> > +	/* Verify Current Slaves Count /Active Slave Count is */
> > +	slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
> > slaves,
> > +			RTE_MAX_ETHPORTS);
> > +	TEST_ASSERT_EQUAL(slave_count, 4,
> > +			"Number of slaves (%d) is not as expected (%d).\n",
> > +			slave_count, 4);
> > +
> > +	slave_count = rte_eth_bond_active_slaves_get(test_params-
> > >bonded_port_id,
> > +			slaves, RTE_MAX_ETHPORTS);
> > +	TEST_ASSERT_EQUAL(slave_count, (int)4,
> > +			"Number of slaves (%d) is not as expected (%d).\n",
> > +			slave_count, 4);
> > +
> > +	primary_port = rte_eth_bond_primary_get(test_params-
> > >bonded_port_id);
> > +	TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0],
> > +			"Primary port not as expected");
> > +
> > +	/* Bring 2 slaves down and verify active slave count */
> > +	virtual_ethdev_simulate_link_status_interrupt(
> > +			test_params->slave_port_ids[1], 0);
> > +	virtual_ethdev_simulate_link_status_interrupt(
> > +			test_params->slave_port_ids[3], 0);
> > +
> > +	TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
> > +			test_params->bonded_port_id, slaves,
> > RTE_MAX_ETHPORTS), 2,
> > +			"Number of active slaves (%d) is not as expected
> (%d).",
> > +			slave_count, 2);
> > +
> > +	virtual_ethdev_simulate_link_status_interrupt(
> > +			test_params->slave_port_ids[1], 1);
> > +	virtual_ethdev_simulate_link_status_interrupt(
> > +			test_params->slave_port_ids[3], 1);
> > +
> > +
> > +	/* Bring primary port down, verify that active slave count is 3
> and primary
> > +	 *  has changed */
> > +	virtual_ethdev_simulate_link_status_interrupt(
> > +			test_params->slave_port_ids[0], 0);
> > +
> > +	TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
> > +			test_params->bonded_port_id, slaves,
> > RTE_MAX_ETHPORTS), 3,
> > +			"Number of active slaves (%d) is not as expected
> (%d).",
> > +			slave_count, 3);
> > +
> > +	primary_port = rte_eth_bond_primary_get(test_params-
> > >bonded_port_id);
> > +	TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[2],
> > +			"Primary port not as expected");
> > +	rte_delay_us(500000);
> > +	/* Verify that pkts are sent on new primary slave */
> > +	for (i = 0; i < 4; i++) {
> > +		TEST_ASSERT_EQUAL(generate_test_burst(
> > +				&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0),
> > burst_size,
> > +				"generate_test_burst failed\n");
> > +		TEST_ASSERT_EQUAL(rte_eth_tx_burst(
> > +				test_params->bonded_port_id, 0,
> > &pkt_burst[0][0], burst_size), burst_size,
> > +				"rte_eth_tx_burst failed\n");
> > +		rte_delay_us(11000);
> > +	}
> > +
> > +	rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
> > +	TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0,
> > +			"(%d) port_stats.opackets not as expected\n",
> > +			test_params->slave_port_ids[2]);
> > +
> > +	rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
> > +	TEST_ASSERT_EQUAL(port_stats.opackets, (int8_t)0,
> > +			"(%d) port_stats.opackets not as expected\n",
> > +			test_params->slave_port_ids[0]);
> > +
> > +	rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
> > +	TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0,
> > +			"(%d) port_stats.opackets not as expected\n",
> > +			test_params->slave_port_ids[1]);
> > +
> > +	rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
> > +	TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0,
> > +			"(%d) port_stats.opackets not as expected\n",
> > +			test_params->slave_port_ids[3]);
> > +
> > +
> > +	/* Generate packet burst for testing */
> > +
> > +	for (i = 0; i <
> > TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT; i++) {
> > +		if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1,
> 0, 0, 0)
> > !=
> > +				burst_size)
> > +			return -1;
> > +
> > +		virtual_ethdev_add_mbufs_to_rx_queue(
> > +				test_params->slave_port_ids[i],
> &pkt_burst[i][0],
> > burst_size);
> > +	}
> > +
> > +	if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
> > +			MAX_PKT_BURST) != burst_size) {
> > +		printf("rte_eth_rx_burst\n");
> > +		return -1;
> > +
> > +	}
> > +
> > +	/* Verify bonded device rx count */
> > +	rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
> > +	TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
> > +			"(%d) port_stats.ipackets not as expected\n",
> > +			test_params->bonded_port_id);
> > +
> > +	/* free mbufs */
> > +
> > +	for (i = 0; i <
> > TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT; i++) {
> > +		for (j = 0; j < MAX_PKT_BURST; j++) {
> > +			if (pkt_burst[i][j] != NULL) {
> > +				rte_pktmbuf_free(pkt_burst[i][j]);
> > +				pkt_burst[i][j] = NULL;
> > +			}
> > +		}
> > +	}
> > +
> > +
> > +	/* Clean up and remove slaves from bonded device */
> > +	return remove_slaves_and_stop_bonded_device();
> > +}
> > +
> >
> >  static struct unit_test_suite link_bonding_test_suite  = {
> >  	.suite_name = "Link Bonding Unit Test Suite",
> > @@ -3898,6 +4392,11 @@ static struct unit_test_suite
> link_bonding_test_suite
> > = {
> >  		TEST_CASE(test_balance_verify_promiscuous_enable_disable),
> >  		TEST_CASE(test_balance_verify_mac_assignment),
> >
> > 	TEST_CASE(test_balance_verify_slave_link_status_change_behaviour),
> > +		TEST_CASE(test_tlb_tx_burst),
> > +		TEST_CASE(test_tlb_rx_burst),
> > +		TEST_CASE(test_tlb_verify_mac_assignment),
> > +		TEST_CASE(test_tlb_verify_promiscuous_enable_disable),
> > +
> 	TEST_CASE(test_tlb_verify_slave_link_status_change_failover),
> >  		TEST_CASE(test_broadcast_tx_burst),
> >  		TEST_CASE(test_broadcast_tx_burst_slave_tx_fail),
> >  		TEST_CASE(test_broadcast_rx_burst),
> > diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
> > index fffaa35..331bec3 100644
> > --- a/app/test/virtual_pmd.c
> > +++ b/app/test/virtual_pmd.c
> > @@ -359,16 +359,18 @@ virtual_ethdev_tx_burst_success(void *queue,
> struct
> > rte_mbuf **bufs,
> >
> >  	struct rte_eth_dev *vrtl_eth_dev;
> >  	struct virtual_ethdev_private *dev_private;
> > -
> > +	uint64_t obytes = 0;
> >  	int i;
> >
> > +	for (i = 0; i < nb_pkts; i++)
> > +		obytes += rte_pktmbuf_pkt_len(bufs[i]);
> >  	vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
> >  	dev_private = vrtl_eth_dev->data->dev_private;
> >
> >  	if (vrtl_eth_dev->data->dev_link.link_status) {
> >  		/* increment opacket count */
> >  		dev_private->eth_stats.opackets += nb_pkts;
> > -
> > +		dev_private->eth_stats.obytes += obytes;
> >  		/* free packets in burst */
> >  		for (i = 0; i < nb_pkts; i++) {
> >  			rte_pktmbuf_free(bufs[i]);
> > diff --git a/app/test/virtual_pmd.h b/app/test/virtual_pmd.h
> > index 2462853..4118e3e 100644
> > --- a/app/test/virtual_pmd.h
> > +++ b/app/test/virtual_pmd.h
> > @@ -94,6 +94,13 @@ void
> >  virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id,
> >  		uint8_t packet_fail_count);
> >
> > +/* if a value greater than zero is set for packet_fail_count then
> virtual
> > + * device tx burst function will fail that many packet from burst or
> all
> > + * packets if packet_fail_count is greater than the number of
> packets in the
> > + * burst */
> > +void virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t
> port_id,
> > +		uint8_t packet_fail_count);
> > +
> >  #ifdef __cplusplus
> >  }
> >  #endif
> > diff --git a/lib/librte_pmd_bond/rte_eth_bond.h
> > b/lib/librte_pmd_bond/rte_eth_bond.h
> > index 6811c7b..682e5c7 100644
> > --- a/lib/librte_pmd_bond/rte_eth_bond.h
> > +++ b/lib/librte_pmd_bond/rte_eth_bond.h
> > @@ -75,6 +75,29 @@ extern "C" {
> >  /**< Broadcast (Mode 3).
> >   * In this mode all transmitted packets will be transmitted on all
> available
> >   * active slaves of the bonded. */
> > +#define BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING	(5)
> > +/**< Broadcast (Mode 5)
> > + * Adaptive transmit load balancing: channel bonding that
> > + * does not require any special switch support.  The
> > + * outgoing traffic is distributed according to the
> > + * current load (computed relative to the speed) on each
> > + * slave.  Incoming traffic is received by the current
> > + * slave.  If the receiving slave fails, another slave
> > + * takes over the MAC address of the failed receiving
> > + * slave.*/
> > +#define BONDING_MODE_ADAPTIVE_LOAD_BALANCING
> > 	(6)
> > +/**
> > + * Adaptive load balancing: includes balance-tlb plus
> > + * receive load balancing (rlb) for IPV4 traffic, and
> > + * does not require any special switch support.  The
> > + * receive load balancing is achieved by ARP negotiation.
> > + * The bonding driver intercepts the ARP Replies sent by
> > + * the local system on their way out and overwrites the
> > + * source hardware address with the unique hardware
> > + * address of one of the slaves in the bond such that
> > + * different peers use different hardware addresses for
> > + * the server. */
> > +
> >
> >  /* Balance Mode Transmit Policies */
> >  #define BALANCE_XMIT_POLICY_LAYER2		(0)
> > diff --git a/lib/librte_pmd_bond/rte_eth_bond_args.c
> > b/lib/librte_pmd_bond/rte_eth_bond_args.c
> > index bbbc69b..7464af5 100644
> > --- a/lib/librte_pmd_bond/rte_eth_bond_args.c
> > +++ b/lib/librte_pmd_bond/rte_eth_bond_args.c
> > @@ -171,6 +171,7 @@ bond_ethdev_parse_slave_mode_kvarg(const char
> *key
> > __rte_unused,
> >  	case BONDING_MODE_ACTIVE_BACKUP:
> >  	case BONDING_MODE_BALANCE:
> >  	case BONDING_MODE_BROADCAST:
> > +	case BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:
> >  		return 0;
> >  	default:
> >  		RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified",
> > value);
> > diff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c
> > b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
> > index 6d0fb1b..db6a934 100644
> > --- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c
> > +++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
> > @@ -30,7 +30,7 @@
> >   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE
> > USE
> >   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> >   */
> > -
> > +#include <stdlib.h>
> >  #include <rte_mbuf.h>
> >  #include <rte_malloc.h>
> >  #include <rte_ethdev.h>
> > @@ -41,10 +41,13 @@
> >  #include <rte_kvargs.h>
> >  #include <rte_dev.h>
> >  #include <rte_alarm.h>
> > +#include <rte_cycles.h>
> >
> >  #include "rte_eth_bond.h"
> >  #include "rte_eth_bond_private.h"
> >
> > +#define REORDER_PERIOD_MS 10
> > +
> >  static uint16_t
> >  bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t
> nb_pkts)
> >  {
> > @@ -287,6 +290,141 @@ xmit_slave_hash(const struct rte_mbuf *buf,
> uint8_t
> > slave_count, uint8_t policy)
> >  	return hash % slave_count;
> >  }
> >
> > +struct bwg_slave {
> > +	uint64_t bwg_left_int;
> > +	uint64_t bwg_left_remainder;
> > +	uint8_t slave;
> > +};
> > +
> > +static int
> > +bandwidth_cmp(const void *a, const void *b)
> > +{
> > +	const struct bwg_slave *bwg_a = a;
> > +	const struct bwg_slave *bwg_b = b;
> > +	int64_t diff = (int64_t)bwg_b->bwg_left_int - (int64_t)bwg_a-
> > >bwg_left_int;
> > +	int64_t diff2 = (int64_t)bwg_b->bwg_left_remainder -
> > +			(int64_t)bwg_a->bwg_left_remainder;
> > +	if (diff > 0)
> > +		return 1;
> > +	else if (diff < 0)
> > +		return -1;
> > +	else if (diff2 > 0)
> > +		return 1;
> > +	else if (diff2 < 0)
> > +		return -1;
> > +	else
> > +		return 0;
> > +}
> > +
> > +static void
> > +bandwidth_left(int port_id, uint64_t load, uint8_t update_idx,
> struct bwg_slave
> > *bwg_slave)
> > +{
> > +	struct rte_eth_link link_status;
> > +
> > +	rte_eth_link_get(port_id, &link_status);
> > +	uint64_t link_bwg = link_status.link_speed * 1000000ULL / 8;
> > +	if (link_bwg == 0)
> > +		return;
> > +	link_bwg = (link_bwg * (update_idx+1) * REORDER_PERIOD_MS);
> > +	bwg_slave->bwg_left_int = (link_bwg - 1000*load) / link_bwg;
> > +	bwg_slave->bwg_left_remainder = (link_bwg - 1000*load) % link_bwg;
> > +}
> > +
> > +static void
> > +bond_ethdev_update_tlb_slave_cb(void *arg)
> > +{
> > +	struct bond_dev_private *internals = arg;
> > +	struct rte_eth_stats slave_stats;
> > +	struct bwg_slave bwg_array[RTE_MAX_ETHPORTS];
> > +	uint8_t slave_count;
> > +	uint64_t tx_bytes;
> > +	uint8_t update_stats = 0;
> > +	int8_t i;
> > +
> > +	internals->slave_update_idx++;
> > +
> > +
> > +	if (internals->slave_update_idx >= REORDER_PERIOD_MS)
> > +		update_stats = 1;
> > +
> > +	for (i = 0; i < internals->active_slave_count; i++) {
> > +		rte_eth_stats_get(internals->active_slaves[i],
> &slave_stats);
> > +		tx_bytes = slave_stats.obytes -
> > +				internals->slaves[i].last_obytes;
> > +		bandwidth_left(internals->active_slaves[i], tx_bytes,
> > +				internals->slave_update_idx, &bwg_array[i]);
> > +		bwg_array[i].slave = internals->active_slaves[i];
> > +
> > +		if (update_stats)
> > +			internals->slaves[i].last_obytes = slave_stats.obytes;
> > +	}
> > +
> > +	if (update_stats == 1)
> > +		internals->slave_update_idx = 0;
> > +
> > +	slave_count = i;
> > +	qsort(bwg_array, slave_count, sizeof(bwg_array[0]),
> bandwidth_cmp);
> > +	for (i = 0; i < slave_count; i++)
> > +		internals->active_slaves[i] = bwg_array[i].slave;
> > +
> > +	rte_eal_alarm_set(REORDER_PERIOD_MS * 1000,
> > bond_ethdev_update_tlb_slave_cb,
> > +			(struct bond_dev_private *)internals);
> > +}
> > +
> > +static uint16_t
> > +bond_ethdev_tx_burst_tlb(void *queue, struct rte_mbuf **bufs,
> uint16_t
> > nb_pkts)
> > +{
> > +	struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
> > +	struct bond_dev_private *internals = bd_tx_q->dev_private;
> > +
> > +	struct rte_eth_dev *primary_port = &rte_eth_devices[internals-
> > >primary_port];
> > +	uint16_t num_tx_total = 0;
> > +	uint8_t i, j;
> > +
> > +	uint8_t num_of_slaves = internals->active_slave_count;
> > +	uint8_t slaves[RTE_MAX_ETHPORTS];
> > +
> > +	struct ether_hdr *ether_hdr;
> > +	struct ether_addr primary_slave_addr;
> > +	struct ether_addr active_slave_addr;
> > +
> > +	if (num_of_slaves < 1)
> > +		return num_tx_total;
> > +
> > +	memcpy(slaves, internals->active_slaves,
> > +				sizeof(internals->active_slaves[0]) *
> > num_of_slaves);
> > +
> > +
> > +	ether_addr_copy(primary_port->data->mac_addrs,
> > &primary_slave_addr);
> > +
> > +	if (nb_pkts > 3) {
> > +		for (i = 0; i < 3; i++)
> > +			rte_prefetch0(rte_pktmbuf_mtod(bufs[i], void*));
> > +	}
> > +
> > +	for (i = 0; i < num_of_slaves; i++) {
> > +		ether_addr_copy(&internals-
> > >slaves[slaves[i]].persisted_mac_addr,
> > +				&active_slave_addr);
> > +
> > +		for (j = num_tx_total; j < nb_pkts; j++) {
> > +			if (j + 3 < nb_pkts)
> > +				rte_prefetch0(rte_pktmbuf_mtod(bufs[j+3],
> > void*));
> > +
> > +			ether_hdr = rte_pktmbuf_mtod(bufs[j], struct
> ether_hdr
> > *);
> > +			if (is_same_ether_addr(&ether_hdr->s_addr,
> > &primary_slave_addr))
> > +				ether_addr_copy(&active_slave_addr,
> > &ether_hdr->s_addr);
> > +		}
> > +
> > +		num_tx_total += rte_eth_tx_burst(slaves[i], bd_tx_q-
> >queue_id,
> > +				bufs + num_tx_total, nb_pkts - num_tx_total);
> > +
> > +		if (num_tx_total == nb_pkts)
> > +			break;
> > +	}
> > +
> > +	return num_tx_total;
> > +}
> > +
> >  static uint16_t
> >  bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,
> >  		uint16_t nb_pkts)
> > @@ -495,6 +633,7 @@ mac_address_slaves_update(struct rte_eth_dev
> > *bonded_eth_dev)
> >  		}
> >  		break;
> >  	case BONDING_MODE_ACTIVE_BACKUP:
> > +	case BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:
> >  	default:
> >  		for (i = 0; i < internals->slave_count; i++) {
> >  			if (internals->slaves[i].port_id ==
> > @@ -544,6 +683,10 @@ bond_ethdev_mode_set(struct rte_eth_dev *eth_dev,
> > int mode)
> >  		eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_broadcast;
> >  		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
> >  		break;
> > +	case BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:
> > +		eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_tlb;
> > +		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;
> > +		break;
> >  	default:
> >  		return -1;
> >  	}
> > @@ -757,6 +900,9 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
> >  				bond_ethdev_slave_link_status_change_monitor,
> >  				(void *)eth_dev);
> >
> > +	if (internals->mode ==
> > BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING) {
> > +		bond_ethdev_update_tlb_slave_cb(internals);
> > +	}
> >  	return 0;
> >  }
> >
> > @@ -765,6 +911,9 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)
> >  {
> >  	struct bond_dev_private *internals = eth_dev->data->dev_private;
> >
> > +	if (internals->mode ==
> > BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING) {
> > +		rte_eal_alarm_cancel(bond_ethdev_update_tlb_slave_cb,
> > internals);
> > +    }
> >  	internals->active_slave_count = 0;
> >  	internals->link_status_polling_enabled = 0;
> >
> > @@ -775,6 +924,12 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)
> >  static void
> >  bond_ethdev_close(struct rte_eth_dev *dev __rte_unused)
> >  {
> > +	struct bond_dev_private *internals = dev->data->dev_private;
> > +
> > +	if (internals->mode ==
> > BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING) {
> > +		rte_eal_alarm_cancel(bond_ethdev_update_tlb_slave_cb,
> > internals);
> > +	}
> > +	internals->active_slave_count = 0;
> >  }
> >
> >  static int
> > @@ -884,7 +1039,7 @@
> bond_ethdev_slave_link_status_change_monitor(void
> > *cb_arg)
> >
> >  	/* If device is currently being configured then don't check
> slaves link
> >  	 * status, wait until next period */
> > -	if (rte_spinlock_trylock(&internals->lock)){
> > +	if (rte_spinlock_trylock(&internals->lock)) {
> >  		for (i = 0; i < internals->slave_count; i++) {
> >  			if (internals->slaves[i].link_status_polling_enabled)
> {
> >  				slave_ethdev = &rte_eth_devices[internals-
> > >slaves[i].port_id];
> > @@ -1004,6 +1159,7 @@ bond_ethdev_promiscuous_enable(struct
> > rte_eth_dev *eth_dev)
> >  		break;
> >  	/* Promiscuous mode is propagated only to primary slave */
> >  	case BONDING_MODE_ACTIVE_BACKUP:
> > +	case BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:
> >  	default:
> >  		rte_eth_promiscuous_enable(internals->current_primary_port);
> >
> > @@ -1028,6 +1184,7 @@ bond_ethdev_promiscuous_disable(struct
> > rte_eth_dev *dev)
> >  		break;
> >  	/* Promiscuous mode is propagated only to primary slave */
> >  	case BONDING_MODE_ACTIVE_BACKUP:
> > +	case BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING:
> >  	default:
> >  		rte_eth_promiscuous_disable(internals-
> >current_primary_port);
> >  	}
> > diff --git a/lib/librte_pmd_bond/rte_eth_bond_private.h
> > b/lib/librte_pmd_bond/rte_eth_bond_private.h
> > index 6db5144..f7186a8 100644
> > --- a/lib/librte_pmd_bond/rte_eth_bond_private.h
> > +++ b/lib/librte_pmd_bond/rte_eth_bond_private.h
> > @@ -89,7 +89,6 @@ struct bond_tx_queue {
> >  	/**< Copy of TX configuration structure for queue */
> >  };
> >
> > -
> >  /** Bonded slave devices structure */
> >  struct bond_ethdev_slave_ports {
> >  	uint8_t slaves[RTE_MAX_ETHPORTS];	/**< Slave port id array */
> > @@ -102,6 +101,7 @@ struct bond_slave_details {
> >  	uint8_t link_status_polling_enabled;
> >  	uint8_t link_status_wait_to_complete;
> >  	uint8_t last_link_status;
> > +	uint64_t last_obytes;
> >
> >  	/**< Port Id of slave eth_dev */
> >  	struct ether_addr persisted_mac_addr;
> > @@ -143,6 +143,7 @@ struct bond_dev_private {
> >  	uint8_t slave_count;			/**< Number of bonded slaves
> */
> >  	struct bond_slave_details slaves[RTE_MAX_ETHPORTS];
> >  	/**< Arary of bonded slaves details */
> > +	uint8_t slave_update_idx;
> >  };
> >
> >  extern struct eth_dev_ops default_dev_ops;
> > --
> > 1.7.9.5
> 
> Acked-by: Declan Doherty <declan.doherty at intel.com>
> 



More information about the dev mailing list