X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest%2Ftest_link_bonding.c;h=32296604d23d363f71e9010b30a37a32ffb76e8f;hb=dd0eedb1cfcf0cb7423d859177c5bc6f931eaf8a;hp=93449aff2f62c215d66c47e86a527ebbac7c89d9;hpb=df468c4937bb90a0552b0e304a148b590b6ab5f6;p=dpdk.git diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c index 93449aff2f..32296604d2 100644 --- a/app/test/test_link_bonding.c +++ b/app/test/test_link_bonding.c @@ -41,7 +41,7 @@ #include #include #include - +#include #include #include #include @@ -57,7 +57,7 @@ #include "test.h" -#define TEST_MAX_NUMBER_OF_PORTS (16) +#define TEST_MAX_NUMBER_OF_PORTS (6) #define RX_RING_SIZE 128 #define RX_FREE_THRESH 32 @@ -75,18 +75,15 @@ ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ ETH_TXQ_FLAGS_NOXSUMTCP) -#define MBUF_PAYLOAD_SIZE (2048) -#define MBUF_SIZE (MBUF_PAYLOAD_SIZE + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) #define MBUF_CACHE_SIZE (250) #define BURST_SIZE (32) -#define DEFAULT_MBUF_DATA_SIZE (2048) #define RTE_TEST_RX_DESC_MAX (2048) #define RTE_TEST_TX_DESC_MAX (2048) #define MAX_PKT_BURST (512) #define DEF_PKT_BURST (16) -#define BONDED_DEV_NAME ("unit_test_bonded_device") +#define BONDED_DEV_NAME ("unit_test_bond_dev") #define INVALID_SOCKET_ID (-1) #define INVALID_PORT_ID (-1) @@ -182,7 +179,6 @@ struct rte_fdir_conf fdir_conf = { .mode = RTE_FDIR_MODE_NONE, .pballoc = RTE_FDIR_PBALLOC_64K, .status = RTE_FDIR_REPORT_STATUS, - .flexbytes_offset = 0x6, .drop_queue = 127, }; @@ -281,10 +277,9 @@ test_setup(void) nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + DEF_PKT_BURST + RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST; if (test_params->mbuf_pool == NULL) { - test_params->mbuf_pool = rte_mempool_create("MBUF_POOL", nb_mbuf_per_pool, - MBUF_SIZE, MBUF_CACHE_SIZE, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, - rte_socket_id(), 0); + test_params->mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", + nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0, + RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); TEST_ASSERT_NOT_NULL(test_params->mbuf_pool, "rte_mempool_create failed"); } @@ -454,7 +449,7 @@ test_remove_slave_from_bonded_device(void) mac_addr = (struct ether_addr *)slave_mac; mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = - test_params->slave_port_ids[test_params->bonded_slave_count-1]; + test_params->bonded_slave_count-1; rte_eth_macaddr_get( test_params->slave_port_ids[test_params->bonded_slave_count-1], @@ -708,9 +703,7 @@ test_set_bonding_mode(void) int bonding_modes[] = { BONDING_MODE_ROUND_ROBIN, BONDING_MODE_ACTIVE_BACKUP, BONDING_MODE_BALANCE, -#ifdef RTE_MBUF_REFCNT BONDING_MODE_BROADCAST -#endif }; /* Test supported link bonding modes */ @@ -810,8 +803,7 @@ test_set_primary_slave(void) test_params->bonded_port_id); expected_mac_addr = (struct ether_addr *)&slave_mac; - expected_mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = - test_params->slave_port_ids[i]; + expected_mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i; /* Check primary slave MAC */ rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); @@ -928,6 +920,192 @@ test_set_explicit_bonded_mac(void) return 0; } +#define BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT (3) + +static int +test_set_bonded_port_initialization_mac_assignment(void) +{ + int i, slave_count, bonded_port_id; + + uint8_t slaves[RTE_MAX_ETHPORTS]; + int slave_port_ids[BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT]; + + struct ether_addr slave_mac_addr, bonded_mac_addr, read_mac_addr; + + /* Initialize default values for MAC addresses */ + memcpy(&slave_mac_addr, slave_mac, sizeof(struct ether_addr)); + memcpy(&bonded_mac_addr, slave_mac, sizeof(struct ether_addr)); + + /* + * 1. a - Create / configure bonded / slave ethdevs + */ + bonded_port_id = rte_eth_bond_create("ethdev_bond_mac_ass_test", + BONDING_MODE_ACTIVE_BACKUP, rte_socket_id()); + TEST_ASSERT(bonded_port_id > 0, "failed to create bonded device"); + + TEST_ASSERT_SUCCESS(configure_ethdev(bonded_port_id, 0, 0), + "Failed to configure bonded ethdev"); + + for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { + char pmd_name[RTE_ETH_NAME_MAX_LEN]; + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = i + 100; + + snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "eth_slave_%d", i); + + slave_port_ids[i] = virtual_ethdev_create(pmd_name, + &slave_mac_addr, rte_socket_id(), 1); + + TEST_ASSERT(slave_port_ids[i] >= 0, + "Failed to create slave ethdev %s", pmd_name); + + TEST_ASSERT_SUCCESS(configure_ethdev(slave_port_ids[i], 1, 0), + "Failed to configure virtual ethdev %s", + pmd_name); + } + + + /* + * 2. Add slave ethdevs to bonded device + */ + for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { + TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(bonded_port_id, + slave_port_ids[i]), + "Failed to add slave (%d) to bonded port (%d).", + slave_port_ids[i], bonded_port_id); + } + + slave_count = rte_eth_bond_slaves_get(bonded_port_id, slaves, + RTE_MAX_ETHPORTS); + TEST_ASSERT_EQUAL(BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT, slave_count, + "Number of slaves (%d) is not as expected (%d)", + slave_count, BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT); + + + /* + * 3. Set explicit MAC address on bonded ethdev + */ + bonded_mac_addr.addr_bytes[ETHER_ADDR_LEN-2] = 0xFF; + bonded_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 0xAA; + + TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( + bonded_port_id, &bonded_mac_addr), + "Failed to set MAC address on bonded port (%d)", + bonded_port_id); + + + /* 4. a - Start bonded ethdev + * b - Enable slave devices + * c - Verify bonded/slaves ethdev MAC addresses + */ + TEST_ASSERT_SUCCESS(rte_eth_dev_start(bonded_port_id), + "Failed to start bonded pmd eth device %d.", + bonded_port_id); + + for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { + virtual_ethdev_simulate_link_status_interrupt( + slave_port_ids[i], 1); + } + + rte_eth_macaddr_get(bonded_port_id, &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "bonded port mac address not as expected"); + + rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 0 mac address not as expected"); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 1 + 100; + rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 1 mac address not as expected"); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 2 + 100; + rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 2 mac address not as expected"); + + + /* 7. a - Change primary port + * b - Stop / Start bonded port + * d - Verify slave ethdev MAC addresses + */ + TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(bonded_port_id, + slave_port_ids[2]), + "failed to set primary port on bonded device."); + + rte_eth_dev_stop(bonded_port_id); + TEST_ASSERT_SUCCESS(rte_eth_dev_start(bonded_port_id), + "Failed to start bonded pmd eth device %d.", + bonded_port_id); + + rte_eth_macaddr_get(bonded_port_id, &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "bonded port mac address not as expected"); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 0 + 100; + rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 0 mac address not as expected"); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 1 + 100; + rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 1 mac address not as expected"); + + rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 2 mac address not as expected"); + + /* 6. a - Stop bonded ethdev + * b - remove slave ethdevs + * c - Verify slave ethdevs MACs are restored + */ + rte_eth_dev_stop(bonded_port_id); + + for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { + TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(bonded_port_id, + slave_port_ids[i]), + "Failed to remove slave %d from bonded port (%d).", + slave_port_ids[i], bonded_port_id); + } + + slave_count = rte_eth_bond_slaves_get(bonded_port_id, slaves, + RTE_MAX_ETHPORTS); + + TEST_ASSERT_EQUAL(slave_count, 0, + "Number of slaves (%d) is great than expected (%d).", + slave_count, 0); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 0 + 100; + rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 0 mac address not as expected"); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 1 + 100; + rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 1 mac address not as expected"); + + slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 2 + 100; + rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr); + TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, + sizeof(read_mac_addr)), + "slave port 2 mac address not as expected"); + + return 0; +} + static int initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t bond_en_isr, @@ -1128,17 +1306,22 @@ generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size, uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac, uint8_t toggle_ip_addr, uint8_t toggle_udp_port) { - uint16_t pktlen, generated_burst_size; + uint16_t pktlen, generated_burst_size, ether_type; void *ip_hdr; + if (ipv4) + ether_type = ETHER_TYPE_IPv4; + else + ether_type = ETHER_TYPE_IPv6; + if (toggle_dst_mac) initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, - vlan, vlan_id); + ether_type, vlan, vlan_id); else initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, - vlan, vlan_id); + ether_type, vlan, vlan_id); if (toggle_udp_port) @@ -1240,7 +1423,6 @@ test_roundrobin_tx_burst(void) return remove_slaves_and_stop_bonded_device(); } -#ifdef RTE_MBUF_REFCNT static int verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val) { @@ -1254,8 +1436,6 @@ verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val) } return 0; } -#endif - static void free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs) @@ -1360,12 +1540,10 @@ test_roundrobin_tx_burst_slave_tx_fail(void) (unsigned int)port_stats.opackets, slave_expected_tx_count); } -#ifdef RTE_MBUF_REFCNT /* Verify that all mbufs have a ref value of zero */ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, 1), "mbufs refcnts not as expected"); -#endif free_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT); /* Clean up and remove slaves from bonded device */ @@ -1909,7 +2087,8 @@ test_activebackup_tx_burst(void) "Failed to initialize bonded device with slaves"); initialize_eth_header(test_params->pkt_eth_hdr, - (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0); + (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, + 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, @@ -2452,7 +2631,8 @@ test_balance_l2_tx_burst(void) "Failed to set balance xmit policy."); initialize_eth_header(test_params->pkt_eth_hdr, - (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0); + (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, + 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, @@ -2466,7 +2646,8 @@ test_balance_l2_tx_burst(void) "failed to generate packet burst"); initialize_eth_header(test_params->pkt_eth_hdr, - (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, 0, 0); + (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, + ETHER_TYPE_IPv4, 0, 0); /* Generate a burst 2 of packets to transmit */ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, &pkts_burst[1][0], @@ -2871,12 +3052,10 @@ test_balance_tx_burst_slave_tx_fail(void) (unsigned int)port_stats.opackets, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2); -#ifdef RTE_MBUF_REFCNT /* Verify that all mbufs have a ref value of zero */ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst_1[tx_count_1], TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, 1), "mbufs refcnts not as expected"); -#endif free_mbufs(&pkts_burst_1[tx_count_1], TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT); @@ -3287,9 +3466,6 @@ test_balance_verify_slave_link_status_change_behaviour(void) return remove_slaves_and_stop_bonded_device(); } -#ifdef RTE_MBUF_REFCNT -/** Broadcast Mode Tests */ - static int test_broadcast_tx_burst(void) { @@ -3303,7 +3479,8 @@ test_broadcast_tx_burst(void) "Failed to intialise bonded device"); initialize_eth_header(test_params->pkt_eth_hdr, - (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0); + (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, + ETHER_TYPE_IPv4, 0, 0); pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_0, 16); @@ -3816,7 +3993,6 @@ test_broadcast_verify_slave_link_status_change_behaviour(void) /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } -#endif static int test_reconfigure_bonded_device(void) @@ -3844,95 +4020,986 @@ test_close_bonded_device(void) return 0; } -static int +static void testsuite_teardown(void) { - if (test_params->pkt_eth_hdr != NULL) { - free(test_params->pkt_eth_hdr); - test_params->pkt_eth_hdr = NULL; - } + free(test_params->pkt_eth_hdr); + test_params->pkt_eth_hdr = NULL; /* Clean up and remove slaves from bonded device */ - return remove_slaves_and_stop_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 struct unit_test_suite link_bonding_test_suite = { - .suite_name = "Link Bonding Unit Test Suite", - .setup = test_setup, - .teardown = testsuite_teardown, - .unit_test_cases = { - TEST_CASE(test_create_bonded_device), - TEST_CASE(test_create_bonded_device_with_invalid_params), - TEST_CASE(test_add_slave_to_bonded_device), - TEST_CASE(test_add_slave_to_invalid_bonded_device), - TEST_CASE(test_remove_slave_from_bonded_device), - TEST_CASE(test_remove_slave_from_invalid_bonded_device), - TEST_CASE(test_get_slaves_from_bonded_device), - TEST_CASE(test_add_already_bonded_slave_to_bonded_device), - TEST_CASE(test_add_remove_multiple_slaves_to_from_bonded_device), - TEST_CASE(test_start_bonded_device), - TEST_CASE(test_stop_bonded_device), - TEST_CASE(test_set_bonding_mode), - TEST_CASE(test_set_primary_slave), - TEST_CASE(test_set_explicit_bonded_mac), - TEST_CASE(test_status_interrupt), - TEST_CASE(test_adding_slave_after_bonded_device_started), - TEST_CASE(test_roundrobin_tx_burst), - TEST_CASE(test_roundrobin_tx_burst_slave_tx_fail), - TEST_CASE(test_roundrobin_rx_burst_on_single_slave), - TEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves), - TEST_CASE(test_roundrobin_verify_promiscuous_enable_disable), - TEST_CASE(test_roundrobin_verify_mac_assignment), - TEST_CASE(test_roundrobin_verify_slave_link_status_change_behaviour), - TEST_CASE(test_roundrobin_verfiy_polling_slave_link_status_change), - TEST_CASE(test_activebackup_tx_burst), - TEST_CASE(test_activebackup_rx_burst), - TEST_CASE(test_activebackup_verify_promiscuous_enable_disable), - TEST_CASE(test_activebackup_verify_mac_assignment), - TEST_CASE(test_activebackup_verify_slave_link_status_change_failover), - TEST_CASE(test_balance_xmit_policy_configuration), - TEST_CASE(test_balance_l2_tx_burst), - TEST_CASE(test_balance_l23_tx_burst_ipv4_toggle_ip_addr), - TEST_CASE(test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr), - TEST_CASE(test_balance_l23_tx_burst_ipv6_toggle_ip_addr), - TEST_CASE(test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr), - TEST_CASE(test_balance_l23_tx_burst_toggle_mac_addr), - TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_ip_addr), - TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_udp_port), - TEST_CASE(test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr), - TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr), - TEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr), - TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port), - TEST_CASE(test_balance_tx_burst_slave_tx_fail), - TEST_CASE(test_balance_rx_burst), - 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), -#ifdef RTE_MBUF_REFCNT - TEST_CASE(test_broadcast_tx_burst), - TEST_CASE(test_broadcast_tx_burst_slave_tx_fail), - TEST_CASE(test_broadcast_rx_burst), - TEST_CASE(test_broadcast_verify_promiscuous_enable_disable), - TEST_CASE(test_broadcast_verify_mac_assignment), - TEST_CASE(test_broadcast_verify_slave_link_status_change_behaviour), -#endif - TEST_CASE(test_reconfigure_bonded_device), - TEST_CASE(test_close_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; + + 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 ether_addr *)src_mac, + (struct ether_addr *)dst_mac_0, ETHER_TYPE_IPv4, 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, 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(); - { NULL, NULL, NULL, NULL, NULL } /**< NULL terminate unit test array */ + 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_link_bonding(void) +test_tlb_rx_burst(void) { - return unit_test_suite_runner(&link_bonding_test_suite); + 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 struct test_command link_bonding_cmd = { - .command = "link_bonding_autotest", - .callback = test_link_bonding, +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_TLB, 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_TLB, 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_TLB, 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[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[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[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(); +} + +#define TEST_ALB_SLAVE_COUNT 2 + +static uint8_t mac_client1[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 1}; +static uint8_t mac_client2[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 2}; +static uint8_t mac_client3[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 3}; +static uint8_t mac_client4[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 4}; + +static uint32_t ip_host = IPV4_ADDR(192, 168, 0, 0); +static uint32_t ip_client1 = IPV4_ADDR(192, 168, 0, 1); +static uint32_t ip_client2 = IPV4_ADDR(192, 168, 0, 2); +static uint32_t ip_client3 = IPV4_ADDR(192, 168, 0, 3); +static uint32_t ip_client4 = IPV4_ADDR(192, 168, 0, 4); + +static int +test_alb_change_mac_in_reply_sent(void) +{ + struct rte_mbuf *pkt; + struct rte_mbuf *pkts_sent[MAX_PKT_BURST]; + + struct ether_hdr *eth_pkt; + struct arp_hdr *arp_pkt; + + int slave_idx, nb_pkts, pkt_idx; + int retval = 0; + + struct ether_addr bond_mac, client_mac; + struct ether_addr *slave_mac1, *slave_mac2; + + TEST_ASSERT_SUCCESS( + initialize_bonded_device_with_slaves(BONDING_MODE_ALB, + 0, TEST_ALB_SLAVE_COUNT, 1), + "Failed to initialize_bonded_device_with_slaves."); + + /* Flush tx queue */ + rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); + for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; + slave_idx++) { + nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( + test_params->slave_port_ids[slave_idx], pkts_sent, + MAX_PKT_BURST); + } + + ether_addr_copy( + rte_eth_devices[test_params->bonded_port_id].data->mac_addrs, + &bond_mac); + + /* + * Generating four packets with different mac and ip addresses and sending + * them through the bonding port. + */ + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client1, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client1, + ARP_OP_REPLY); + rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); + + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client2, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client2, + ARP_OP_REPLY); + rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); + + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client3, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client3, + ARP_OP_REPLY); + rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); + + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client4, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client4, + ARP_OP_REPLY); + rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); + + slave_mac1 = + rte_eth_devices[test_params->slave_port_ids[0]].data->mac_addrs; + slave_mac2 = + rte_eth_devices[test_params->slave_port_ids[1]].data->mac_addrs; + + /* + * Checking if packets are properly distributed on bonding ports. Packets + * 0 and 2 should be sent on port 0 and packets 1 and 3 on port 1. + */ + for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { + nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( + test_params->slave_port_ids[slave_idx], pkts_sent, + MAX_PKT_BURST); + + for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) { + eth_pkt = rte_pktmbuf_mtod(pkts_sent[pkt_idx], struct ether_hdr *); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + + if (slave_idx%2 == 0) { + if (!is_same_ether_addr(slave_mac1, &arp_pkt->arp_data.arp_sha)) { + retval = -1; + goto test_end; + } + } else { + if (!is_same_ether_addr(slave_mac2, &arp_pkt->arp_data.arp_sha)) { + retval = -1; + goto test_end; + } + } + } + } + +test_end: + retval += remove_slaves_and_stop_bonded_device(); + return retval; +} + +static int +test_alb_reply_from_client(void) +{ + struct ether_hdr *eth_pkt; + struct arp_hdr *arp_pkt; + + struct rte_mbuf *pkt; + struct rte_mbuf *pkts_sent[MAX_PKT_BURST]; + + int slave_idx, nb_pkts, pkt_idx, nb_pkts_sum = 0; + int retval = 0; + + struct ether_addr bond_mac, client_mac; + struct ether_addr *slave_mac1, *slave_mac2; + + TEST_ASSERT_SUCCESS( + initialize_bonded_device_with_slaves(BONDING_MODE_ALB, + 0, TEST_ALB_SLAVE_COUNT, 1), + "Failed to initialize_bonded_device_with_slaves."); + + /* Flush tx queue */ + rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); + for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { + nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( + test_params->slave_port_ids[slave_idx], pkts_sent, + MAX_PKT_BURST); + } + + ether_addr_copy( + rte_eth_devices[test_params->bonded_port_id].data->mac_addrs, + &bond_mac); + + /* + * Generating four packets with different mac and ip addresses and placing + * them in the rx queue to be received by the bonding driver on rx_burst. + */ + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client1, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client1, ip_host, + ARP_OP_REPLY); + virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, + 1); + + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client2, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client2, ip_host, + ARP_OP_REPLY); + virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, + 1); + + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client3, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client3, ip_host, + ARP_OP_REPLY); + virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, + 1); + + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client4, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, + 0); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client4, ip_host, + ARP_OP_REPLY); + virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, + 1); + + /* + * Issue rx_burst and tx_burst to force bonding driver to send update ARP + * packets to every client in alb table. + */ + rte_eth_rx_burst(test_params->bonded_port_id, 0, pkts_sent, MAX_PKT_BURST); + rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); + + slave_mac1 = rte_eth_devices[test_params->slave_port_ids[0]].data->mac_addrs; + slave_mac2 = rte_eth_devices[test_params->slave_port_ids[1]].data->mac_addrs; + + /* + * Checking if update ARP packets were properly send on slave ports. + */ + for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { + nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( + test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); + nb_pkts_sum += nb_pkts; + + for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) { + eth_pkt = rte_pktmbuf_mtod(pkts_sent[pkt_idx], struct ether_hdr *); + arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); + + if (slave_idx%2 == 0) { + if (!is_same_ether_addr(slave_mac1, &arp_pkt->arp_data.arp_sha)) { + retval = -1; + goto test_end; + } + } else { + if (!is_same_ether_addr(slave_mac2, &arp_pkt->arp_data.arp_sha)) { + retval = -1; + goto test_end; + } + } + } + } + + /* Check if proper number of packets was send */ + if (nb_pkts_sum < 4) { + retval = -1; + goto test_end; + } + +test_end: + retval += remove_slaves_and_stop_bonded_device(); + return retval; +} + +static int +test_alb_receive_vlan_reply(void) +{ + struct ether_hdr *eth_pkt; + struct vlan_hdr *vlan_pkt; + struct arp_hdr *arp_pkt; + + struct rte_mbuf *pkt; + struct rte_mbuf *pkts_sent[MAX_PKT_BURST]; + + int slave_idx, nb_pkts, pkt_idx; + int retval = 0; + + struct ether_addr bond_mac, client_mac; + + TEST_ASSERT_SUCCESS( + initialize_bonded_device_with_slaves(BONDING_MODE_ALB, + 0, TEST_ALB_SLAVE_COUNT, 1), + "Failed to initialize_bonded_device_with_slaves."); + + /* Flush tx queue */ + rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); + for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { + nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( + test_params->slave_port_ids[slave_idx], pkts_sent, + MAX_PKT_BURST); + } + + ether_addr_copy( + rte_eth_devices[test_params->bonded_port_id].data->mac_addrs, + &bond_mac); + + /* + * Generating packet with double VLAN header and placing it in the rx queue. + */ + pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); + memcpy(client_mac.addr_bytes, mac_client1, ETHER_ADDR_LEN); + eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_VLAN, 0, + 0); + vlan_pkt = (struct vlan_hdr *)((char *)(eth_pkt + 1)); + vlan_pkt->vlan_tci = rte_cpu_to_be_16(1); + vlan_pkt->eth_proto = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + vlan_pkt = vlan_pkt+1; + vlan_pkt->vlan_tci = rte_cpu_to_be_16(2); + vlan_pkt->eth_proto = rte_cpu_to_be_16(ETHER_TYPE_ARP); + arp_pkt = (struct arp_hdr *)((char *)(vlan_pkt + 1)); + initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client1, ip_host, + ARP_OP_REPLY); + virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, + 1); + + rte_eth_rx_burst(test_params->bonded_port_id, 0, pkts_sent, MAX_PKT_BURST); + rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); + + /* + * Checking if VLAN headers in generated ARP Update packet are correct. + */ + for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { + nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( + test_params->slave_port_ids[slave_idx], pkts_sent, + MAX_PKT_BURST); + + for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) { + eth_pkt = rte_pktmbuf_mtod(pkts_sent[pkt_idx], struct ether_hdr *); + vlan_pkt = (struct vlan_hdr *)((char *)(eth_pkt + 1)); + if (vlan_pkt->vlan_tci != rte_cpu_to_be_16(1)) { + retval = -1; + goto test_end; + } + if (vlan_pkt->eth_proto != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { + retval = -1; + goto test_end; + } + vlan_pkt = vlan_pkt+1; + if (vlan_pkt->vlan_tci != rte_cpu_to_be_16(2)) { + retval = -1; + goto test_end; + } + if (vlan_pkt->eth_proto != rte_cpu_to_be_16(ETHER_TYPE_ARP)) { + retval = -1; + goto test_end; + } + } + } + +test_end: + retval += remove_slaves_and_stop_bonded_device(); + return retval; +} + +static int +test_alb_ipv4_tx(void) +{ + int burst_size, retval, pkts_send; + struct rte_mbuf *pkt_burst[MAX_PKT_BURST]; + + retval = 0; + + TEST_ASSERT_SUCCESS( + initialize_bonded_device_with_slaves(BONDING_MODE_ALB, + 0, TEST_ALB_SLAVE_COUNT, 1), + "Failed to initialize_bonded_device_with_slaves."); + + burst_size = 32; + + /* Generate test bursts of packets to transmit */ + if (generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0) != burst_size) { + retval = -1; + goto test_end; + } + + /* + * Checking if ipv4 traffic is transmitted via TLB policy. + */ + pkts_send = rte_eth_tx_burst( + test_params->bonded_port_id, 0, pkt_burst, burst_size); + if (pkts_send != burst_size) { + retval = -1; + goto test_end; + } + +test_end: + retval += remove_slaves_and_stop_bonded_device(); + return retval; +} + +static struct unit_test_suite link_bonding_test_suite = { + .suite_name = "Link Bonding Unit Test Suite", + .setup = test_setup, + .teardown = testsuite_teardown, + .unit_test_cases = { + TEST_CASE(test_create_bonded_device), + TEST_CASE(test_create_bonded_device_with_invalid_params), + TEST_CASE(test_add_slave_to_bonded_device), + TEST_CASE(test_add_slave_to_invalid_bonded_device), + TEST_CASE(test_remove_slave_from_bonded_device), + TEST_CASE(test_remove_slave_from_invalid_bonded_device), + TEST_CASE(test_get_slaves_from_bonded_device), + TEST_CASE(test_add_already_bonded_slave_to_bonded_device), + TEST_CASE(test_add_remove_multiple_slaves_to_from_bonded_device), + TEST_CASE(test_start_bonded_device), + TEST_CASE(test_stop_bonded_device), + TEST_CASE(test_set_bonding_mode), + TEST_CASE(test_set_primary_slave), + TEST_CASE(test_set_explicit_bonded_mac), + TEST_CASE(test_set_bonded_port_initialization_mac_assignment), + TEST_CASE(test_status_interrupt), + TEST_CASE(test_adding_slave_after_bonded_device_started), + TEST_CASE(test_roundrobin_tx_burst), + TEST_CASE(test_roundrobin_tx_burst_slave_tx_fail), + TEST_CASE(test_roundrobin_rx_burst_on_single_slave), + TEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves), + TEST_CASE(test_roundrobin_verify_promiscuous_enable_disable), + TEST_CASE(test_roundrobin_verify_mac_assignment), + TEST_CASE(test_roundrobin_verify_slave_link_status_change_behaviour), + TEST_CASE(test_roundrobin_verfiy_polling_slave_link_status_change), + TEST_CASE(test_activebackup_tx_burst), + TEST_CASE(test_activebackup_rx_burst), + TEST_CASE(test_activebackup_verify_promiscuous_enable_disable), + TEST_CASE(test_activebackup_verify_mac_assignment), + TEST_CASE(test_activebackup_verify_slave_link_status_change_failover), + TEST_CASE(test_balance_xmit_policy_configuration), + TEST_CASE(test_balance_l2_tx_burst), + TEST_CASE(test_balance_l23_tx_burst_ipv4_toggle_ip_addr), + TEST_CASE(test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr), + TEST_CASE(test_balance_l23_tx_burst_ipv6_toggle_ip_addr), + TEST_CASE(test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr), + TEST_CASE(test_balance_l23_tx_burst_toggle_mac_addr), + TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_ip_addr), + TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_udp_port), + TEST_CASE(test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr), + TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr), + TEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr), + TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port), + TEST_CASE(test_balance_tx_burst_slave_tx_fail), + TEST_CASE(test_balance_rx_burst), + 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_alb_change_mac_in_reply_sent), + TEST_CASE(test_alb_reply_from_client), + TEST_CASE(test_alb_receive_vlan_reply), + TEST_CASE(test_alb_ipv4_tx), + TEST_CASE(test_broadcast_tx_burst), + TEST_CASE(test_broadcast_tx_burst_slave_tx_fail), + TEST_CASE(test_broadcast_rx_burst), + TEST_CASE(test_broadcast_verify_promiscuous_enable_disable), + TEST_CASE(test_broadcast_verify_mac_assignment), + TEST_CASE(test_broadcast_verify_slave_link_status_change_behaviour), + TEST_CASE(test_reconfigure_bonded_device), + TEST_CASE(test_close_bonded_device), + + TEST_CASES_END() /**< NULL terminate unit test array */ + } }; -REGISTER_TEST_COMMAND(link_bonding_cmd); + + +static int +test_link_bonding(void) +{ + return unit_test_suite_runner(&link_bonding_test_suite); +} + +REGISTER_TEST_COMMAND(link_bonding_autotest, test_link_bonding);