+test_broadcast_verify_promiscuous_enable_disable(void)
+{
+ int i;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, 4, 1),
+ "Failed to initialise bonded device");
+
+ rte_eth_promiscuous_enable(test_params->bonded_port_id);
+
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ rte_eth_promiscuous_disable(test_params->bonded_port_id);
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0,
+ "Port (%d) promiscuous mode not disabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]), 0,
+ "Port (%d) promiscuous mode not disabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_broadcast_verify_mac_assignment(void)
+{
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr expected_mac_addr_0, expected_mac_addr_1;
+
+ int i;
+
+ rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
+ rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_1);
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, 4, 1),
+ "Failed to initialise bonded device");
+
+ /* Verify that all MACs are the same as first slave added to bonded
+ * device */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_macaddr_get(test_params->slave_port_ids[i], &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[i]);
+ }
+
+ /* change primary and verify that MAC addresses haven't changed */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[2]),
+ "Failed to set bonded port (%d) primary port to (%d)",
+ test_params->bonded_port_id, test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address has changed to that of primary "
+ "port without stop/start toggle of bonded device",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* 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 bonded 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 new primary port",
+ test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_macaddr_get(test_params->slave_port_ids[i], &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 new primary "
+ "port", test_params->slave_port_ids[i]);
+ }
+
+ /* Set explicit MAC address */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id,
+ (struct rte_ether_addr *)bonded_mac),
+ "Failed to set MAC address");
+
+ 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 new primary port",
+ test_params->slave_port_ids[i]);
+
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_macaddr_get(test_params->slave_port_ids[i], &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 new primary "
+ "port", test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define BROADCAST_LINK_STATUS_NUM_OF_SLAVES (4)
+static int
+test_broadcast_verify_slave_link_status_change_behaviour(void)
+{
+ struct rte_mbuf *pkt_burst[BROADCAST_LINK_STATUS_NUM_OF_SLAVES][MAX_PKT_BURST];
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ int i, burst_size, slave_count;
+
+ 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_BROADCAST, 0, BROADCAST_LINK_STATUS_NUM_OF_SLAVES,
+ 1), "Failed to initialise bonded device");
+
+ /* 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).",
+ 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, 4,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 4);
+
+ /* Set 2 slaves link status to down */
+ 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);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 2,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 2);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++)
+ rte_eth_stats_reset(test_params->slave_port_ids[i]);
+
+ /* Verify that pkts are not sent on slaves with link status down */
+ burst_size = 21;
+
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[0][0], burst_size, 0, 0, 1, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ 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_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size * slave_count),
+ "(%d) port_stats.opackets (%d) not as expected (%d)\n",
+ test_params->bonded_port_id, (int)port_stats.opackets,
+ burst_size * slave_count);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[2]);
+
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[3]);
+
+
+ for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[i][0], burst_size, 0, 0, 1, 0, 0),
+ burst_size, "failed to generate packet burst");
+
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &pkt_burst[i][0], burst_size);
+ }
+
+ /* Verify that pkts are not received on slaves with link status down */
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(
+ test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
+ burst_size + burst_size, "rte_eth_rx_burst failed");
+
+
+ /* 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 + burst_size),
+ "(%d) port_stats.ipackets not as expected\n",
+ test_params->bonded_port_id);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_reconfigure_bonded_device(void)
+{
+ test_params->nb_rx_q = 4;
+ test_params->nb_tx_q = 4;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
+ "failed to reconfigure bonded device");
+
+ test_params->nb_rx_q = 2;
+ test_params->nb_tx_q = 2;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
+ "failed to reconfigure bonded device with less rx/tx queues");
+
+ return 0;
+}
+
+
+static int
+test_close_bonded_device(void)
+{
+ rte_eth_dev_close(test_params->bonded_port_id);
+ return 0;
+}
+
+static void
+testsuite_teardown(void)
+{
+ free(test_params->pkt_eth_hdr);
+ test_params->pkt_eth_hdr = NULL;
+
+ /* Clean up and remove slaves from bonded device */
+ remove_slaves_and_stop_bonded_device();
+}
+
+static void
+free_virtualpmd_tx_queue(void)
+{
+ int i, slave_port, to_free_cnt;
+ struct rte_mbuf *pkts_to_free[MAX_PKT_BURST];
+
+ /* Free tx queue of virtual pmd */
+ for (slave_port = 0; slave_port < test_params->bonded_slave_count;
+ slave_port++) {
+ to_free_cnt = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_port],
+ pkts_to_free, MAX_PKT_BURST);
+ for (i = 0; i < to_free_cnt; i++)
+ rte_pktmbuf_free(pkts_to_free[i]);
+ }
+}
+
+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_TLB, 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 bursts of packets */
+ 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 rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPv4, 0, 0);
+ } else {
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)test_params->default_slave_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPv4, 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;
+
+ free_virtualpmd_tx_queue();
+
+ 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");
+
+ /* checking if distribution of packets is balanced over slaves */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT(port_stats[i].obytes > 0 &&
+ port_stats[i].obytes < all_bond_obytes,
+ "Packets are not balanced over slaves");
+ }
+
+ /* 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_TLB,
+ 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)