DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd
@ 2014-11-27 16:33 Daniel Mrzyglod
  2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 1/2] This patch add support of mode 5 " Daniel Mrzyglod
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Daniel Mrzyglod @ 2014-11-27 16:33 UTC (permalink / raw)
  To: dev

ADD mode 5(tlb) to link bonding pmd

v4 change:
Change description of mode 5 in header.
Add description to cover letter.

v3 change:
Rebase patch version to HEAD of orgin/master.
Unit tests moved to the separate patch v3 2/2.

v2 change:
Add Unit Tests
Modification that updates obytes structure in virtualpmd driver.
change internals->slaves[i].last_obytes to have proper values.
Update codebase to Declan's patches.

v1 change:
Add support for mode 5 (Transmit load balancing) into pmd driver


Daniel Mrzyglod (2):
  This patch add support of mode 5 to link bonding pmd
  Unit tests for Mode 5 of Bonding Transmit Load balancig.

 app/test/test_link_bonding.c               | 499 ++++++++++++++++++++++++++++-
 app/test/virtual_pmd.c                     |   6 +-
 lib/librte_pmd_bond/rte_eth_bond.h         |   6 +
 lib/librte_pmd_bond/rte_eth_bond_args.c    |   1 +
 lib/librte_pmd_bond/rte_eth_bond_pmd.c     | 160 ++++++++-
 lib/librte_pmd_bond/rte_eth_bond_private.h |   2 +-
 6 files changed, 668 insertions(+), 6 deletions(-)

-- 
2.1.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 1/2] This patch add support of mode 5 to link bonding pmd
  2014-11-27 16:33 [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Daniel Mrzyglod
@ 2014-11-27 16:33 ` Daniel Mrzyglod
  2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 2/2] Unit tests for Mode 5 of Bonding Transmit Load balancig Daniel Mrzyglod
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Daniel Mrzyglod @ 2014-11-27 16:33 UTC (permalink / raw)
  To: dev

Add support for mode 5 (Transmit load balancing) into pmd driver

This patch add support for Adaptive transmit load balancing (mode 5) to the
librte_pmd_bond library. This mode provides an adaptive transmit load 
balancing. It dynamically changes the transmitting slave, according to the 
computed load. 

Further details are described here:
https://www.kernel.org/doc/Documentation/networking/bonding.txt
In implementation callback is used for sorting slave order - providing 
statistics for burst function about slave bandwith usage  and sort 
interfaces due to usage.

Difference in this implementation vs Linux implementation:
- We Are trying send all pkts – If one interface hasn’t send packets we are 
trying to send rest of packets by other slaves sorted previously by callback 
function.

Some implementation details:
- Every 100ms is taken obytes statistics from every slave.
- Every 10 ms the slaves in  table are sorted and updated by callback - 
bandwidth and successfully transmitted bytes from previous iteration which 
happens every 100 ms
- There is callback function which updates this statistics for transparency and
for rather intensive computation involved in this mode.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
---
 lib/librte_pmd_bond/rte_eth_bond.h         |   6 ++
 lib/librte_pmd_bond/rte_eth_bond_args.c    |   1 +
 lib/librte_pmd_bond/rte_eth_bond_pmd.c     | 160 ++++++++++++++++++++++++++++-
 lib/librte_pmd_bond/rte_eth_bond_private.h |   2 +-
 4 files changed, 166 insertions(+), 3 deletions(-)

diff --git a/lib/librte_pmd_bond/rte_eth_bond.h b/lib/librte_pmd_bond/rte_eth_bond.h
index 085500b..3831f56 100644
--- a/lib/librte_pmd_bond/rte_eth_bond.h
+++ b/lib/librte_pmd_bond/rte_eth_bond.h
@@ -77,6 +77,12 @@ extern "C" {
  * In this mode all transmitted packets will be transmitted on all available
  * active slaves of the bonded. */
 #endif
+#define BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING	(5)
+/**< Adaptive TLB (Mode 5)
+ * This mode provides an adaptive transmit load balancing. It dynamically
+ * changes the transmitting slave, according to the computed load. Statistics
+ * are collected in 100ms intervals and scheduled every 10ms */
+
 /* Balance Mode Transmit Policies */
 #define BALANCE_XMIT_POLICY_LAYER2		(0)
 /**< Layer 2 (Ethernet MAC) */
diff --git a/lib/librte_pmd_bond/rte_eth_bond_args.c b/lib/librte_pmd_bond/rte_eth_bond_args.c
index d8ce681..2675cf6 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_args.c
+++ b/lib/librte_pmd_bond/rte_eth_bond_args.c
@@ -173,6 +173,7 @@ bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused,
 #ifdef RTE_MBUF_REFCNT
 	case BONDING_MODE_BROADCAST:
 #endif
+	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 cf2fbab..7a5dae6 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,15 @@
 #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
+/* Table for statistics in mode 5 TLB */
+static uint64_t tlb_last_obytets[RTE_MAX_ETHPORTS];
+
 static uint16_t
 bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 {
@@ -288,6 +293,144 @@ 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;
+	uint8_t i, slave_id;
+
+	internals->slave_update_idx++;
+
+
+	if (internals->slave_update_idx >= REORDER_PERIOD_MS)
+		update_stats = 1;
+
+	for (i = 0; i < internals->active_slave_count; i++) {
+		slave_id = internals->active_slaves[i];
+		rte_eth_stats_get(slave_id, &slave_stats);
+		tx_bytes = slave_stats.obytes - tlb_last_obytets[slave_id];
+		bandwidth_left(slave_id, tx_bytes,
+				internals->slave_update_idx, &bwg_array[i]);
+		bwg_array[i].slave = slave_id;
+
+		if (update_stats)
+			tlb_last_obytets[slave_id] = 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)
@@ -500,6 +643,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 ==
@@ -551,6 +695,10 @@ bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode)
 		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
 		break;
 #endif
+	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;
 	}
@@ -676,7 +824,7 @@ slave_add(struct bond_dev_private *internals,
 	}
 
 	slave_details->link_status_wait_to_complete = 0;
-
+	/* clean tlb_last_obytes when adding port for bonding device */
 	memcpy(&(slave_details->persisted_mac_addr), slave_eth_dev->data->mac_addrs,
 			sizeof(struct ether_addr));
 }
@@ -762,6 +910,9 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
 	if (internals->user_defined_primary_port)
 		bond_ethdev_primary_set(internals, internals->primary_port);
 
+	if (internals->mode == BONDING_MODE_ADAPTIVE_TRANSMIT_LOAD_BALANCING)
+		bond_ethdev_update_tlb_slave_cb(internals);
+
 	return 0;
 }
 
@@ -770,6 +921,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;
 
@@ -1016,6 +1170,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);
 
@@ -1042,6 +1197,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 6254c84..2a4e129 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_private.h
+++ b/lib/librte_pmd_bond/rte_eth_bond_private.h
@@ -102,7 +102,6 @@ struct bond_slave_details {
 	uint8_t link_status_poll_enabled;
 	uint8_t link_status_wait_to_complete;
 	uint8_t last_link_status;
-
 	/**< Port Id of slave eth_dev */
 	struct ether_addr persisted_mac_addr;
 };
@@ -145,6 +144,7 @@ struct bond_dev_private {
 	/**< Arary of bonded slaves details */
 
 	struct rte_kvargs *kvlist;
+	uint8_t slave_update_idx;
 };
 
 extern struct eth_dev_ops default_dev_ops;
-- 
2.1.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 2/2] Unit tests for Mode 5 of Bonding Transmit Load balancig.
  2014-11-27 16:33 [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Daniel Mrzyglod
  2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 1/2] This patch add support of mode 5 " Daniel Mrzyglod
@ 2014-11-27 16:33 ` Daniel Mrzyglod
  2014-11-27 16:41 ` [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Thomas Monjalon
  2014-11-27 20:27 ` Thomas Monjalon
  3 siblings, 0 replies; 7+ messages in thread
From: Daniel Mrzyglod @ 2014-11-27 16:33 UTC (permalink / raw)
  To: dev

This Patch add unit tests for mode 5 - tlb - to the oders
link bonding unit tests.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
---
 app/test/test_link_bonding.c | 499 ++++++++++++++++++++++++++++++++++++++++++-
 app/test/virtual_pmd.c       |   6 +-
 2 files changed, 502 insertions(+), 3 deletions(-)

diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 93449af..f62c490 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>
@@ -3856,6 +3856,498 @@ testsuite_teardown(void)
 	return remove_slaves_and_stop_bonded_device();
 }
 
+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;
+	uint64_t floor_obytes = 0, ceiling_obytes = 0;
+
+	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 equal to packets sent by bond interface");
+	/* distribution of packets on each slave within +/- 10% of the expected value. */
+	for (i = 0; i < test_params->bonded_slave_count; i++) {
+
+		floor_obytes = (all_bond_obytes*90)/(test_params->bonded_slave_count*100);
+		ceiling_obytes = (all_bond_obytes*110)/(test_params->bonded_slave_count*100);
+		TEST_ASSERT(port_stats[i].obytes >= floor_obytes &&
+				port_stats[i].obytes <= ceiling_obytes,
+						"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_COUNT][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",
@@ -3909,6 +4401,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),
 #ifdef RTE_MBUF_REFCNT
 		TEST_CASE(test_broadcast_tx_burst),
 		TEST_CASE(test_broadcast_tx_burst_slave_tx_fail),
diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index e7be98b..ade6cb0 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]);
-- 
2.1.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd
  2014-11-27 16:33 [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Daniel Mrzyglod
  2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 1/2] This patch add support of mode 5 " Daniel Mrzyglod
  2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 2/2] Unit tests for Mode 5 of Bonding Transmit Load balancig Daniel Mrzyglod
@ 2014-11-27 16:41 ` Thomas Monjalon
  2014-11-27 16:56   ` Doherty, Declan
  2014-11-27 20:27 ` Thomas Monjalon
  3 siblings, 1 reply; 7+ messages in thread
From: Thomas Monjalon @ 2014-11-27 16:41 UTC (permalink / raw)
  To: Daniel Mrzyglod; +Cc: dev

2014-11-27 16:33, Daniel Mrzyglod:
> ADD mode 5(tlb) to link bonding pmd
> 
> v4 change:
> Change description of mode 5 in header.
> Add description to cover letter.
> 
> v3 change:
> Rebase patch version to HEAD of orgin/master.
> Unit tests moved to the separate patch v3 2/2.
> 
> v2 change:
> Add Unit Tests
> Modification that updates obytes structure in virtualpmd driver.
> change internals->slaves[i].last_obytes to have proper values.
> Update codebase to Declan's patches.
> 
> v1 change:
> Add support for mode 5 (Transmit load balancing) into pmd driver
> 
> 
> Daniel Mrzyglod (2):
>   This patch add support of mode 5 to link bonding pmd
>   Unit tests for Mode 5 of Bonding Transmit Load balancig.

Please help me to understand. Declan just acked the v3 and you are sending
an incomplete v4 (patch 2 is missing).
When a complete patchset will be sent, it will be applied.

-- 
Thomas

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd
  2014-11-27 16:41 ` [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Thomas Monjalon
@ 2014-11-27 16:56   ` Doherty, Declan
  0 siblings, 0 replies; 7+ messages in thread
From: Doherty, Declan @ 2014-11-27 16:56 UTC (permalink / raw)
  To: Thomas Monjalon, Mrzyglod, DanielX T; +Cc: dev

Sorry Thomas, this was my fault, I forgot that Daniel mentioned to me earlier today that he was going to 
submit a new revision of the patch set with updated patch descriptions, but no code changes, due to 
your comments relating to the link bonding mode 4. I will ack the v4 patchset when all patches for v4
are available.

Declan

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Thursday, November 27, 2014 4:42 PM
> To: Mrzyglod, DanielX T
> Cc: dev@dpdk.org; Doherty, Declan
> Subject: Re: [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd
> 
> 2014-11-27 16:33, Daniel Mrzyglod:
> > ADD mode 5(tlb) to link bonding pmd
> >
> > v4 change:
> > Change description of mode 5 in header.
> > Add description to cover letter.
> >
> > v3 change:
> > Rebase patch version to HEAD of orgin/master.
> > Unit tests moved to the separate patch v3 2/2.
> >
> > v2 change:
> > Add Unit Tests
> > Modification that updates obytes structure in virtualpmd driver.
> > change internals->slaves[i].last_obytes to have proper values.
> > Update codebase to Declan's patches.
> >
> > v1 change:
> > Add support for mode 5 (Transmit load balancing) into pmd driver
> >
> >
> > Daniel Mrzyglod (2):
> >   This patch add support of mode 5 to link bonding pmd
> >   Unit tests for Mode 5 of Bonding Transmit Load balancig.
> 
> Please help me to understand. Declan just acked the v3 and you are sending
> an incomplete v4 (patch 2 is missing).
> When a complete patchset will be sent, it will be applied.
> 
> --
> Thomas

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd
  2014-11-27 16:33 [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Daniel Mrzyglod
                   ` (2 preceding siblings ...)
  2014-11-27 16:41 ` [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Thomas Monjalon
@ 2014-11-27 20:27 ` Thomas Monjalon
  3 siblings, 0 replies; 7+ messages in thread
From: Thomas Monjalon @ 2014-11-27 20:27 UTC (permalink / raw)
  To: Daniel Mrzyglod; +Cc: dev

> ADD mode 5(tlb) to link bonding pmd
> 
> v4 change:
> Change description of mode 5 in header.
> Add description to cover letter.
> 
> v3 change:
> Rebase patch version to HEAD of orgin/master.
> Unit tests moved to the separate patch v3 2/2.
> 
> v2 change:
> Add Unit Tests
> Modification that updates obytes structure in virtualpmd driver.
> change internals->slaves[i].last_obytes to have proper values.
> Update codebase to Declan's patches.
> 
> v1 change:
> Add support for mode 5 (Transmit load balancing) into pmd driver
> 
> 
> Daniel Mrzyglod (2):
>   This patch add support of mode 5 to link bonding pmd
>   Unit tests for Mode 5 of Bonding Transmit Load balancig.

Applied

Thanks
-- 
Thomas

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 2/2] Unit tests for Mode 5 of Bonding Transmit Load balancig.
  2014-11-27 16:49 Daniel Mrzyglod
@ 2014-11-27 16:49 ` Daniel Mrzyglod
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Mrzyglod @ 2014-11-27 16:49 UTC (permalink / raw)
  To: dev

This Patch add unit tests for mode 5 - tlb - to the oders
link bonding unit tests.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
---
 app/test/test_link_bonding.c | 499 ++++++++++++++++++++++++++++++++++++++++++-
 app/test/virtual_pmd.c       |   6 +-
 2 files changed, 502 insertions(+), 3 deletions(-)

diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 93449af..f62c490 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>
@@ -3856,6 +3856,498 @@ testsuite_teardown(void)
 	return remove_slaves_and_stop_bonded_device();
 }
 
+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;
+	uint64_t floor_obytes = 0, ceiling_obytes = 0;
+
+	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 equal to packets sent by bond interface");
+	/* distribution of packets on each slave within +/- 10% of the expected value. */
+	for (i = 0; i < test_params->bonded_slave_count; i++) {
+
+		floor_obytes = (all_bond_obytes*90)/(test_params->bonded_slave_count*100);
+		ceiling_obytes = (all_bond_obytes*110)/(test_params->bonded_slave_count*100);
+		TEST_ASSERT(port_stats[i].obytes >= floor_obytes &&
+				port_stats[i].obytes <= ceiling_obytes,
+						"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_COUNT][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",
@@ -3909,6 +4401,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),
 #ifdef RTE_MBUF_REFCNT
 		TEST_CASE(test_broadcast_tx_burst),
 		TEST_CASE(test_broadcast_tx_burst_slave_tx_fail),
diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index e7be98b..ade6cb0 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]);
-- 
2.1.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-11-27 20:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-27 16:33 [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Daniel Mrzyglod
2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 1/2] This patch add support of mode 5 " Daniel Mrzyglod
2014-11-27 16:33 ` [dpdk-dev] [PATCH v4 2/2] Unit tests for Mode 5 of Bonding Transmit Load balancig Daniel Mrzyglod
2014-11-27 16:41 ` [dpdk-dev] [PATCH v4 0/2] ADD mode 5(tlb) to link bonding pmd Thomas Monjalon
2014-11-27 16:56   ` Doherty, Declan
2014-11-27 20:27 ` Thomas Monjalon
2014-11-27 16:49 Daniel Mrzyglod
2014-11-27 16:49 ` [dpdk-dev] [PATCH v4 2/2] Unit tests for Mode 5 of Bonding Transmit Load balancig Daniel Mrzyglod

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).