From: "Doherty, Declan" <declan.doherty@intel.com>
To: "dev@dpdk.org" <dev@dpdk.org>
Subject: Re: [dpdk-dev] [PATCH v2] ADD mode 5(tlb) to link bonding pmd
Date: Tue, 7 Oct 2014 08:20:25 +0000 [thread overview]
Message-ID: <345C63BAECC1AD42A2EC8C63AFFC3ADC273BBF75@IRSMSX101.ger.corp.intel.com> (raw)
In-Reply-To: <1411746081-19550-1-git-send-email-danielx.t.mrzyglod@intel.com>
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Daniel Mrzyglod
> Sent: Friday, September 26, 2014 4:41 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2] ADD mode 5(tlb) to link bonding pmd
>
>
> Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@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(ðer_hdr->s_addr,
> &primary_slave_addr))
> + ether_addr_copy(&active_slave_addr,
> ðer_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@intel.com>
next prev parent reply other threads:[~2014-10-07 8:13 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-26 15:41 Daniel Mrzyglod
2014-09-29 12:11 ` Mrzyglod, DanielX T
2014-10-07 8:20 ` Doherty, Declan [this message]
2014-11-25 9:17 ` Jiajia, SunX
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=345C63BAECC1AD42A2EC8C63AFFC3ADC273BBF75@IRSMSX101.ger.corp.intel.com \
--to=declan.doherty@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).