numam-dpdk/app/test/test_link_bonding.c
Bruce Richardson a9de470cc7 test: move to app directory
Since all other apps have been moved to the "app" folder, the autotest app
remains alone in the test folder. Rather than having an entire top-level
folder for this, we can move it back to where it all started in early
versions of DPDK - the "app/" folder.

This move has a couple of advantages:
* This reduces clutter at the top level of the project, due to one less
  folder.
* It eliminates the separate build task necessary for building the
  autotests using make "make test-build" which means that developers are
  less likely to miss something in their own compilation tests
* It re-aligns the final location of the test binary in the app folder when
  building with make with it's location in the source tree.

For meson builds, the autotest app is different from the other apps in that
it needs a series of different test cases defined for it for use by "meson
test". Therefore, it does not get built as part of the main loop in the
app folder, but gets built separately at the end.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
2019-02-26 15:29:27 +01:00

4907 lines
165 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation
*/
#include "unistd.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#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>
#include <rte_ethdev.h>
#include <rte_ethdev_driver.h>
#include <rte_log.h>
#include <rte_lcore.h>
#include <rte_memory.h>
#include <rte_string_fns.h>
#include <rte_eth_bond.h>
#include "virtual_pmd.h"
#include "packet_burst_generator.h"
#include "test.h"
#define TEST_MAX_NUMBER_OF_PORTS (6)
#define RX_RING_SIZE 1024
#define RX_FREE_THRESH 32
#define RX_PTHRESH 8
#define RX_HTHRESH 8
#define RX_WTHRESH 0
#define TX_RING_SIZE 1024
#define TX_FREE_THRESH 32
#define TX_PTHRESH 32
#define TX_HTHRESH 0
#define TX_WTHRESH 0
#define TX_RSBIT_THRESH 32
#define MBUF_CACHE_SIZE (250)
#define BURST_SIZE (32)
#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 ("net_bonding_ut")
#define INVALID_SOCKET_ID (-1)
#define INVALID_PORT_ID (-1)
#define INVALID_BONDING_MODE (-1)
uint8_t slave_mac[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 };
uint8_t bonded_mac[] = {0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
struct link_bonding_unittest_params {
int16_t bonded_port_id;
int16_t slave_port_ids[TEST_MAX_NUMBER_OF_PORTS];
uint16_t bonded_slave_count;
uint8_t bonding_mode;
uint16_t nb_rx_q;
uint16_t nb_tx_q;
struct rte_mempool *mbuf_pool;
struct ether_addr *default_slave_mac;
struct ether_addr *default_bonded_mac;
/* Packet Headers */
struct ether_hdr *pkt_eth_hdr;
struct ipv4_hdr *pkt_ipv4_hdr;
struct ipv6_hdr *pkt_ipv6_hdr;
struct udp_hdr *pkt_udp_hdr;
};
static struct ipv4_hdr pkt_ipv4_hdr;
static struct ipv6_hdr pkt_ipv6_hdr;
static struct udp_hdr pkt_udp_hdr;
static struct link_bonding_unittest_params default_params = {
.bonded_port_id = -1,
.slave_port_ids = { -1 },
.bonded_slave_count = 0,
.bonding_mode = BONDING_MODE_ROUND_ROBIN,
.nb_rx_q = 1,
.nb_tx_q = 1,
.mbuf_pool = NULL,
.default_slave_mac = (struct ether_addr *)slave_mac,
.default_bonded_mac = (struct ether_addr *)bonded_mac,
.pkt_eth_hdr = NULL,
.pkt_ipv4_hdr = &pkt_ipv4_hdr,
.pkt_ipv6_hdr = &pkt_ipv6_hdr,
.pkt_udp_hdr = &pkt_udp_hdr
};
static struct link_bonding_unittest_params *test_params = &default_params;
static uint8_t src_mac[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
static uint8_t dst_mac_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
static uint8_t dst_mac_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAB };
static uint32_t src_addr = IPV4_ADDR(192, 168, 1, 98);
static uint32_t dst_addr_0 = IPV4_ADDR(192, 168, 1, 98);
static uint32_t dst_addr_1 = IPV4_ADDR(193, 166, 10, 97);
static uint8_t src_ipv6_addr[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA };
static uint8_t dst_ipv6_addr_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA, 0xFF, 0xAA };
static uint8_t dst_ipv6_addr_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA , 0xFF, 0xAB };
static uint16_t src_port = 1024;
static uint16_t dst_port_0 = 1024;
static uint16_t dst_port_1 = 2024;
static uint16_t vlan_id = 0x100;
static struct rte_eth_conf default_pmd_conf = {
.rxmode = {
.mq_mode = ETH_MQ_RX_NONE,
.split_hdr_size = 0,
.max_rx_pkt_len = ETHER_MAX_LEN,
},
.txmode = {
.mq_mode = ETH_MQ_TX_NONE,
},
.lpbk_mode = 0,
};
static const struct rte_eth_rxconf rx_conf_default = {
.rx_thresh = {
.pthresh = RX_PTHRESH,
.hthresh = RX_HTHRESH,
.wthresh = RX_WTHRESH,
},
.rx_free_thresh = RX_FREE_THRESH,
.rx_drop_en = 0,
};
static struct rte_eth_txconf tx_conf_default = {
.tx_thresh = {
.pthresh = TX_PTHRESH,
.hthresh = TX_HTHRESH,
.wthresh = TX_WTHRESH,
},
.tx_free_thresh = TX_FREE_THRESH,
.tx_rs_thresh = TX_RSBIT_THRESH,
};
static void free_virtualpmd_tx_queue(void);
static int
configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
{
int q_id;
if (en_isr)
default_pmd_conf.intr_conf.lsc = 1;
else
default_pmd_conf.intr_conf.lsc = 0;
TEST_ASSERT_SUCCESS(rte_eth_dev_configure(port_id, test_params->nb_rx_q,
test_params->nb_tx_q, &default_pmd_conf),
"rte_eth_dev_configure for port %d failed", port_id);
for (q_id = 0; q_id < test_params->nb_rx_q; q_id++)
TEST_ASSERT_SUCCESS(rte_eth_rx_queue_setup(port_id, q_id, RX_RING_SIZE,
rte_eth_dev_socket_id(port_id), &rx_conf_default,
test_params->mbuf_pool) ,
"rte_eth_rx_queue_setup for port %d failed", port_id);
for (q_id = 0; q_id < test_params->nb_tx_q; q_id++)
TEST_ASSERT_SUCCESS(rte_eth_tx_queue_setup(port_id, q_id, TX_RING_SIZE,
rte_eth_dev_socket_id(port_id), &tx_conf_default),
"rte_eth_tx_queue_setup for port %d failed", port_id);
if (start)
TEST_ASSERT_SUCCESS(rte_eth_dev_start(port_id),
"rte_eth_dev_start for port %d failed", port_id);
return 0;
}
static int slaves_initialized;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
static int
test_setup(void)
{
int i, nb_mbuf_per_pool;
struct ether_addr *mac_addr = (struct ether_addr *)slave_mac;
/* Allocate ethernet packet header with space for VLAN header */
if (test_params->pkt_eth_hdr == NULL) {
test_params->pkt_eth_hdr = malloc(sizeof(struct ether_hdr) +
sizeof(struct vlan_hdr));
TEST_ASSERT_NOT_NULL(test_params->pkt_eth_hdr,
"Ethernet header struct allocation failed!");
}
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_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");
}
/* Create / Initialize virtual eth devs */
if (!slaves_initialized) {
for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) {
char pmd_name[RTE_ETH_NAME_MAX_LEN];
mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i;
snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_%d", i);
test_params->slave_port_ids[i] = virtual_ethdev_create(pmd_name,
mac_addr, rte_socket_id(), 1);
TEST_ASSERT(test_params->slave_port_ids[i] >= 0,
"Failed to create virtual virtual ethdev %s", pmd_name);
TEST_ASSERT_SUCCESS(configure_ethdev(
test_params->slave_port_ids[i], 1, 0),
"Failed to configure virtual ethdev %s", pmd_name);
}
slaves_initialized = 1;
}
return 0;
}
static int
test_create_bonded_device(void)
{
int current_slave_count;
uint16_t slaves[RTE_MAX_ETHPORTS];
/* Don't try to recreate bonded device if re-running test suite*/
if (test_params->bonded_port_id == -1) {
test_params->bonded_port_id = rte_eth_bond_create(BONDED_DEV_NAME,
test_params->bonding_mode, rte_socket_id());
TEST_ASSERT(test_params->bonded_port_id >= 0,
"Failed to create bonded ethdev %s", BONDED_DEV_NAME);
TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
"Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
}
TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
test_params->bonding_mode), "Failed to set ethdev %d to mode %d",
test_params->bonded_port_id, test_params->bonding_mode);
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, 0,
"Number of slaves %d is great than expected %d.",
current_slave_count, 0);
current_slave_count = rte_eth_bond_active_slaves_get(
test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, 0,
"Number of active slaves %d is great than expected %d.",
current_slave_count, 0);
return 0;
}
static int
test_create_bonded_device_with_invalid_params(void)
{
int port_id;
test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN;
/* Invalid name */
port_id = rte_eth_bond_create(NULL, test_params->bonding_mode,
rte_socket_id());
TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly");
test_params->bonding_mode = INVALID_BONDING_MODE;
/* Invalid bonding mode */
port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode,
rte_socket_id());
TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly.");
test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN;
/* Invalid socket id */
port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode,
INVALID_SOCKET_ID);
TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly.");
return 0;
}
static int
test_add_slave_to_bonded_device(void)
{
int current_slave_count;
uint16_t slaves[RTE_MAX_ETHPORTS];
TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
test_params->slave_port_ids[test_params->bonded_slave_count]),
"Failed to add slave (%d) to bonded port (%d).",
test_params->slave_port_ids[test_params->bonded_slave_count],
test_params->bonded_port_id);
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count + 1,
"Number of slaves (%d) is greater than expected (%d).",
current_slave_count, test_params->bonded_slave_count + 1);
current_slave_count = rte_eth_bond_active_slaves_get(
test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, 0,
"Number of active slaves (%d) is not as expected (%d).\n",
current_slave_count, 0);
test_params->bonded_slave_count++;
return 0;
}
static int
test_add_slave_to_invalid_bonded_device(void)
{
/* Invalid port ID */
TEST_ASSERT_FAIL(rte_eth_bond_slave_add(test_params->bonded_port_id + 5,
test_params->slave_port_ids[test_params->bonded_slave_count]),
"Expected call to failed as invalid port specified.");
/* Non bonded device */
TEST_ASSERT_FAIL(rte_eth_bond_slave_add(test_params->slave_port_ids[0],
test_params->slave_port_ids[test_params->bonded_slave_count]),
"Expected call to failed as invalid port specified.");
return 0;
}
static int
test_remove_slave_from_bonded_device(void)
{
int current_slave_count;
struct ether_addr read_mac_addr, *mac_addr;
uint16_t slaves[RTE_MAX_ETHPORTS];
TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(test_params->bonded_port_id,
test_params->slave_port_ids[test_params->bonded_slave_count-1]),
"Failed to remove slave %d from bonded port (%d).",
test_params->slave_port_ids[test_params->bonded_slave_count-1],
test_params->bonded_port_id);
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count - 1,
"Number of slaves (%d) is great than expected (%d).\n",
current_slave_count, test_params->bonded_slave_count - 1);
mac_addr = (struct ether_addr *)slave_mac;
mac_addr->addr_bytes[ETHER_ADDR_LEN-1] =
test_params->bonded_slave_count-1;
rte_eth_macaddr_get(
test_params->slave_port_ids[test_params->bonded_slave_count-1],
&read_mac_addr);
TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)),
"bonded port mac address not set to that of primary port\n");
rte_eth_stats_reset(
test_params->slave_port_ids[test_params->bonded_slave_count-1]);
virtual_ethdev_simulate_link_status_interrupt(test_params->bonded_port_id,
0);
test_params->bonded_slave_count--;
return 0;
}
static int
test_remove_slave_from_invalid_bonded_device(void)
{
/* Invalid port ID */
TEST_ASSERT_FAIL(rte_eth_bond_slave_remove(
test_params->bonded_port_id + 5,
test_params->slave_port_ids[test_params->bonded_slave_count - 1]),
"Expected call to failed as invalid port specified.");
/* Non bonded device */
TEST_ASSERT_FAIL(rte_eth_bond_slave_remove(
test_params->slave_port_ids[0],
test_params->slave_port_ids[test_params->bonded_slave_count - 1]),
"Expected call to failed as invalid port specified.");
return 0;
}
static int bonded_id = 2;
static int
test_add_already_bonded_slave_to_bonded_device(void)
{
int port_id, current_slave_count;
uint16_t slaves[RTE_MAX_ETHPORTS];
char pmd_name[RTE_ETH_NAME_MAX_LEN];
test_add_slave_to_bonded_device();
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, 1,
"Number of slaves (%d) is not that expected (%d).",
current_slave_count, 1);
snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "%s_%d", BONDED_DEV_NAME, ++bonded_id);
port_id = rte_eth_bond_create(pmd_name, test_params->bonding_mode,
rte_socket_id());
TEST_ASSERT(port_id >= 0, "Failed to create bonded device.");
TEST_ASSERT(rte_eth_bond_slave_add(port_id,
test_params->slave_port_ids[test_params->bonded_slave_count - 1])
< 0,
"Added slave (%d) to bonded port (%d) unexpectedly.",
test_params->slave_port_ids[test_params->bonded_slave_count-1],
port_id);
return test_remove_slave_from_bonded_device();
}
static int
test_get_slaves_from_bonded_device(void)
{
int current_slave_count;
uint16_t slaves[RTE_MAX_ETHPORTS];
TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
"Failed to add slave to bonded device");
/* Invalid port id */
current_slave_count = rte_eth_bond_slaves_get(INVALID_PORT_ID, slaves,
RTE_MAX_ETHPORTS);
TEST_ASSERT(current_slave_count < 0,
"Invalid port id unexpectedly succeeded");
current_slave_count = rte_eth_bond_active_slaves_get(INVALID_PORT_ID,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT(current_slave_count < 0,
"Invalid port id unexpectedly succeeded");
/* Invalid slaves pointer */
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
NULL, RTE_MAX_ETHPORTS);
TEST_ASSERT(current_slave_count < 0,
"Invalid slave array unexpectedly succeeded");
current_slave_count = rte_eth_bond_active_slaves_get(
test_params->bonded_port_id, NULL, RTE_MAX_ETHPORTS);
TEST_ASSERT(current_slave_count < 0,
"Invalid slave array unexpectedly succeeded");
/* non bonded device*/
current_slave_count = rte_eth_bond_slaves_get(
test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS);
TEST_ASSERT(current_slave_count < 0,
"Invalid port id unexpectedly succeeded");
current_slave_count = rte_eth_bond_active_slaves_get(
test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS);
TEST_ASSERT(current_slave_count < 0,
"Invalid port id unexpectedly succeeded");
TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(),
"Failed to remove slaves from bonded device");
return 0;
}
static int
test_add_remove_multiple_slaves_to_from_bonded_device(void)
{
int i;
for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++)
TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
"Failed to add slave to bonded device");
for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++)
TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(),
"Failed to remove slaves from bonded device");
return 0;
}
static void
enable_bonded_slaves(void)
{
int i;
for (i = 0; i < test_params->bonded_slave_count; i++) {
virtual_ethdev_tx_burst_fn_set_success(test_params->slave_port_ids[i],
1);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[i], 1);
}
}
static int
test_start_bonded_device(void)
{
struct rte_eth_link link_status;
int current_slave_count, current_bonding_mode, primary_port;
uint16_t slaves[RTE_MAX_ETHPORTS];
/* Add slave to bonded device*/
TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
"Failed to add slave to bonded device");
TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
"Failed to start bonded pmd eth device %d.",
test_params->bonded_port_id);
/* Change link status of virtual pmd so it will be added to the active
* slave list of the bonded device*/
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[test_params->bonded_slave_count-1], 1);
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count,
"Number of slaves (%d) is not expected value (%d).",
current_slave_count, test_params->bonded_slave_count);
current_slave_count = rte_eth_bond_active_slaves_get(
test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count,
"Number of active slaves (%d) is not expected value (%d).",
current_slave_count, test_params->bonded_slave_count);
current_bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
TEST_ASSERT_EQUAL(current_bonding_mode, test_params->bonding_mode,
"Bonded device mode (%d) is not expected value (%d).\n",
current_bonding_mode, test_params->bonding_mode);
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 (%d) is not expected value (%d).",
primary_port, test_params->slave_port_ids[0]);
rte_eth_link_get(test_params->bonded_port_id, &link_status);
TEST_ASSERT_EQUAL(link_status.link_status, 1,
"Bonded port (%d) status (%d) is not expected value (%d).\n",
test_params->bonded_port_id, link_status.link_status, 1);
return 0;
}
static int
test_stop_bonded_device(void)
{
int current_slave_count;
uint16_t slaves[RTE_MAX_ETHPORTS];
struct rte_eth_link link_status;
rte_eth_dev_stop(test_params->bonded_port_id);
rte_eth_link_get(test_params->bonded_port_id, &link_status);
TEST_ASSERT_EQUAL(link_status.link_status, 0,
"Bonded port (%d) status (%d) is not expected value (%d).",
test_params->bonded_port_id, link_status.link_status, 0);
current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count,
"Number of slaves (%d) is not expected value (%d).",
current_slave_count, test_params->bonded_slave_count);
current_slave_count = rte_eth_bond_active_slaves_get(
test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(current_slave_count, 0,
"Number of active slaves (%d) is not expected value (%d).",
current_slave_count, 0);
return 0;
}
static int
remove_slaves_and_stop_bonded_device(void)
{
/* Clean up and remove slaves from bonded device */
free_virtualpmd_tx_queue();
while (test_params->bonded_slave_count > 0)
TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(),
"test_remove_slave_from_bonded_device failed");
rte_eth_dev_stop(test_params->bonded_port_id);
rte_eth_stats_reset(test_params->bonded_port_id);
rte_eth_bond_mac_address_reset(test_params->bonded_port_id);
return 0;
}
static int
test_set_bonding_mode(void)
{
int i, bonding_mode;
int bonding_modes[] = { BONDING_MODE_ROUND_ROBIN,
BONDING_MODE_ACTIVE_BACKUP,
BONDING_MODE_BALANCE,
BONDING_MODE_BROADCAST
};
/* Test supported link bonding modes */
for (i = 0; i < (int)RTE_DIM(bonding_modes); i++) {
/* Invalid port ID */
TEST_ASSERT_FAIL(rte_eth_bond_mode_set(INVALID_PORT_ID,
bonding_modes[i]),
"Expected call to failed as invalid port (%d) specified.",
INVALID_PORT_ID);
/* Non bonded device */
TEST_ASSERT_FAIL(rte_eth_bond_mode_set(test_params->slave_port_ids[0],
bonding_modes[i]),
"Expected call to failed as invalid port (%d) specified.",
test_params->slave_port_ids[0]);
TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
bonding_modes[i]),
"Failed to set link bonding mode on port (%d) to (%d).",
test_params->bonded_port_id, bonding_modes[i]);
bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
TEST_ASSERT_EQUAL(bonding_mode, bonding_modes[i],
"Link bonding mode (%d) of port (%d) is not expected value (%d).",
bonding_mode, test_params->bonded_port_id,
bonding_modes[i]);
/* Invalid port ID */
bonding_mode = rte_eth_bond_mode_get(INVALID_PORT_ID);
TEST_ASSERT(bonding_mode < 0,
"Expected call to failed as invalid port (%d) specified.",
INVALID_PORT_ID);
/* Non bonded device */
bonding_mode = rte_eth_bond_mode_get(test_params->slave_port_ids[0]);
TEST_ASSERT(bonding_mode < 0,
"Expected call to failed as invalid port (%d) specified.",
test_params->slave_port_ids[0]);
}
return remove_slaves_and_stop_bonded_device();
}
static int
test_set_primary_slave(void)
{
int i, j, retval;
struct ether_addr read_mac_addr;
struct ether_addr *expected_mac_addr;
/* Add 4 slaves to bonded device */
for (i = test_params->bonded_slave_count; i < 4; i++)
TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
"Failed to add slave to bonded device.");
TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
BONDING_MODE_ROUND_ROBIN),
"Failed to set link bonding mode on port (%d) to (%d).",
test_params->bonded_port_id, BONDING_MODE_ROUND_ROBIN);
/* Invalid port ID */
TEST_ASSERT_FAIL(rte_eth_bond_primary_set(INVALID_PORT_ID,
test_params->slave_port_ids[i]),
"Expected call to failed as invalid port specified.");
/* Non bonded device */
TEST_ASSERT_FAIL(rte_eth_bond_primary_set(test_params->slave_port_ids[i],
test_params->slave_port_ids[i]),
"Expected call to failed as invalid port specified.");
/* Set slave as primary
* Verify slave it is now primary slave
* Verify that MAC address of bonded device is that of primary slave
* Verify that MAC address of all bonded slaves are that of primary slave
*/
for (i = 0; i < 4; i++) {
TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id,
test_params->slave_port_ids[i]),
"Failed to set bonded port (%d) primary port to (%d)",
test_params->bonded_port_id, test_params->slave_port_ids[i]);
retval = rte_eth_bond_primary_get(test_params->bonded_port_id);
TEST_ASSERT(retval >= 0,
"Failed to read primary port from bonded port (%d)\n",
test_params->bonded_port_id);
TEST_ASSERT_EQUAL(retval, test_params->slave_port_ids[i],
"Bonded port (%d) primary port (%d) not expected value (%d)\n",
test_params->bonded_port_id, retval,
test_params->slave_port_ids[i]);
/* stop/start bonded eth dev to apply new MAC */
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 port %d",
test_params->bonded_port_id);
expected_mac_addr = (struct ether_addr *)&slave_mac;
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);
TEST_ASSERT_SUCCESS(memcmp(expected_mac_addr, &read_mac_addr,
sizeof(read_mac_addr)),
"bonded port mac address not set to that of primary port\n");
/* Check bonded MAC */
rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
TEST_ASSERT_SUCCESS(memcmp(&read_mac_addr, &read_mac_addr,
sizeof(read_mac_addr)),
"bonded port mac address not set to that of primary port\n");
/* Check other slaves MACs */
for (j = 0; j < 4; j++) {
if (j != i) {
rte_eth_macaddr_get(test_params->slave_port_ids[j],
&read_mac_addr);
TEST_ASSERT_SUCCESS(memcmp(expected_mac_addr, &read_mac_addr,
sizeof(read_mac_addr)),
"slave port mac address not set to that of primary "
"port");
}
}
}
/* Test with none existent port */
TEST_ASSERT_FAIL(rte_eth_bond_primary_get(test_params->bonded_port_id + 10),
"read primary port from expectedly");
/* Test with slave port */
TEST_ASSERT_FAIL(rte_eth_bond_primary_get(test_params->slave_port_ids[0]),
"read primary port from expectedly\n");
TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
"Failed to stop and remove slaves from bonded device");
/* No slaves */
TEST_ASSERT(rte_eth_bond_primary_get(test_params->bonded_port_id) < 0,
"read primary port from expectedly\n");
return 0;
}
static int
test_set_explicit_bonded_mac(void)
{
int i;
struct ether_addr read_mac_addr;
struct ether_addr *mac_addr;
uint8_t explicit_bonded_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01 };
mac_addr = (struct ether_addr *)explicit_bonded_mac;
/* Invalid port ID */
TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(INVALID_PORT_ID, mac_addr),
"Expected call to failed as invalid port specified.");
/* Non bonded device */
TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(
test_params->slave_port_ids[0], mac_addr),
"Expected call to failed as invalid port specified.");
/* NULL MAC address */
TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(
test_params->bonded_port_id, NULL),
"Expected call to failed as NULL MAC specified");
TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
test_params->bonded_port_id, mac_addr),
"Failed to set MAC address on bonded port (%d)",
test_params->bonded_port_id);
/* Add 4 slaves to bonded device */
for (i = test_params->bonded_slave_count; i < 4; i++) {
TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
"Failed to add slave to bonded device.\n");
}
/* Check bonded MAC */
rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)),
"bonded port mac address not set to that of primary port");
/* Check other slaves MACs */
for (i = 0; i < 4; i++) {
rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr,
sizeof(read_mac_addr)),
"slave port mac address not set to that of primary port");
}
/* test resetting mac address on bonded device */
TEST_ASSERT_SUCCESS(
rte_eth_bond_mac_address_reset(test_params->bonded_port_id),
"Failed to reset MAC address on bonded port (%d)",
test_params->bonded_port_id);
TEST_ASSERT_FAIL(
rte_eth_bond_mac_address_reset(test_params->slave_port_ids[0]),
"Reset MAC address on bonded port (%d) unexpectedly",
test_params->slave_port_ids[1]);
/* test resetting mac address on bonded device with no slaves */
TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
"Failed to remove slaves and stop bonded device");
TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_reset(test_params->bonded_port_id),
"Failed to reset MAC address on bonded port (%d)",
test_params->bonded_port_id);
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;
uint16_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("net_bonding_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,
uint16_t number_of_slaves, uint8_t enable_slave)
{
/* Configure bonded device */
TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0,
bond_en_isr), "Failed to configure bonding port (%d) in mode %d "
"with (%d) slaves.", test_params->bonded_port_id, bonding_mode,
number_of_slaves);
/* Add slaves to bonded device */
while (number_of_slaves > test_params->bonded_slave_count)
TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
"Failed to add slave (%d to bonding port (%d).",
test_params->bonded_slave_count - 1,
test_params->bonded_port_id);
/* Set link bonding mode */
TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
bonding_mode),
"Failed to set link bonding mode on port (%d) to (%d).",
test_params->bonded_port_id, bonding_mode);
TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
"Failed to start bonded pmd eth device %d.",
test_params->bonded_port_id);
if (enable_slave)
enable_bonded_slaves();
return 0;
}
static int
test_adding_slave_after_bonded_device_started(void)
{
int i;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, 4, 0),
"Failed to add slaves to bonded device");
/* Enabled slave devices */
for (i = 0; i < test_params->bonded_slave_count + 1; i++) {
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[i], 1);
}
TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
test_params->slave_port_ids[test_params->bonded_slave_count]),
"Failed to add slave to bonded port.\n");
rte_eth_stats_reset(
test_params->slave_port_ids[test_params->bonded_slave_count]);
test_params->bonded_slave_count++;
return remove_slaves_and_stop_bonded_device();
}
#define TEST_STATUS_INTERRUPT_SLAVE_COUNT 4
#define TEST_LSC_WAIT_TIMEOUT_MS 500
int test_lsc_interrupt_count;
static int
test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
enum rte_eth_event_type type __rte_unused,
void *param __rte_unused,
void *ret_param __rte_unused)
{
pthread_mutex_lock(&mutex);
test_lsc_interrupt_count++;
pthread_cond_signal(&cvar);
pthread_mutex_unlock(&mutex);
return 0;
}
static inline int
lsc_timeout(int wait_us)
{
int retval = 0;
struct timespec ts;
struct timeval tp;
gettimeofday(&tp, NULL);
/* Convert from timeval to timespec */
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_nsec += wait_us * 1000;
pthread_mutex_lock(&mutex);
if (test_lsc_interrupt_count < 1)
retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
pthread_mutex_unlock(&mutex);
if (retval == 0 && test_lsc_interrupt_count < 1)
return -1;
return retval;
}
static int
test_status_interrupt(void)
{
int slave_count;
uint16_t slaves[RTE_MAX_ETHPORTS];
/* initialized bonding device with T slaves */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 1,
TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1),
"Failed to initialise bonded device");
test_lsc_interrupt_count = 0;
/* register link status change interrupt callback */
rte_eth_dev_callback_register(test_params->bonded_port_id,
RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
&test_params->bonded_port_id);
slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT,
"Number of active slaves (%d) is not as expected (%d)",
slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT);
/* Bring all 4 slaves link status to down and test that we have received a
* lsc interrupts */
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[0], 0);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[1], 0);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[2], 0);
TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0,
"Received a link status change interrupt unexpectedly");
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[3], 0);
TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
"timed out waiting for interrupt");
TEST_ASSERT(test_lsc_interrupt_count > 0,
"Did not receive link status change interrupt");
slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(slave_count, 0,
"Number of active slaves (%d) is not as expected (%d)",
slave_count, 0);
/* bring one slave port up so link status will change */
test_lsc_interrupt_count = 0;
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[0], 1);
TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
"timed out waiting for interrupt");
/* test that we have received another lsc interrupt */
TEST_ASSERT(test_lsc_interrupt_count > 0,
"Did not receive link status change interrupt");
/* Verify that calling the same slave lsc interrupt doesn't cause another
* lsc interrupt from bonded device */
test_lsc_interrupt_count = 0;
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[0], 1);
TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) != 0,
"received unexpected interrupt");
TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0,
"Did not receive link status change interrupt");
/* unregister lsc callback before exiting */
rte_eth_dev_callback_unregister(test_params->bonded_port_id,
RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
&test_params->bonded_port_id);
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
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, uint16_t toggle_udp_port)
{
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,
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,
ether_type, vlan, vlan_id);
if (toggle_udp_port)
pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
dst_port_1, 64);
else
pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
dst_port_0, 64);
if (ipv4) {
if (toggle_ip_addr)
pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
dst_addr_1, pktlen);
else
pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
dst_addr_0, pktlen);
ip_hdr = test_params->pkt_ipv4_hdr;
} else {
if (toggle_ip_addr)
pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
(uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_1,
pktlen);
else
pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
(uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_0,
pktlen);
ip_hdr = test_params->pkt_ipv6_hdr;
}
/* Generate burst of packets to transmit */
generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
pkts_burst, test_params->pkt_eth_hdr, vlan, ip_hdr, ipv4,
test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN_128,
1);
TEST_ASSERT_EQUAL(generated_burst_size, burst_size,
"Failed to generate packet burst");
return generated_burst_size;
}
/** Round Robin Mode Tests */
static int
test_roundrobin_tx_burst(void)
{
int i, burst_size;
struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
struct rte_eth_stats port_stats;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, 2, 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.");
/* Generate test bursts of packets to transmit */
TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0),
burst_size, "failed to generate test burst");
/* Send burst on bonded port */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, pkt_burst, burst_size), burst_size,
"tx burst failed");
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
"Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
test_params->bonded_port_id, (unsigned int)port_stats.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);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)burst_size / test_params->bonded_slave_count,
"Slave Port (%d) opackets value (%u) not as expected (%d)\n",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
burst_size / test_params->bonded_slave_count);
}
/* 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 */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
pkt_burst, burst_size), 0,
"tx burst return unexpected value");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
{
int i, refcnt;
for (i = 0; i < nb_mbufs; i++) {
refcnt = rte_mbuf_refcnt_read(mbufs[i]);
TEST_ASSERT_EQUAL(refcnt, val,
"mbuf ref count (%d)is not the expected value (%d)",
refcnt, val);
}
return 0;
}
static void
free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs)
{
int i;
for (i = 0; i < nb_mbufs; i++)
rte_pktmbuf_free(mbufs[i]);
}
#define TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT (2)
#define TEST_RR_SLAVE_TX_FAIL_BURST_SIZE (64)
#define TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT (22)
#define TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (1)
static int
test_roundrobin_tx_burst_slave_tx_fail(void)
{
struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
struct rte_mbuf *expected_tx_fail_pkts[MAX_PKT_BURST];
struct rte_eth_stats port_stats;
int i, first_fail_idx, tx_count;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0,
TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
"Failed to initialise bonded device");
/* Generate test bursts of packets to transmit */
TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst,
TEST_RR_SLAVE_TX_FAIL_BURST_SIZE, 0, 1, 0, 0, 0),
TEST_RR_SLAVE_TX_FAIL_BURST_SIZE,
"Failed to generate test packet burst");
/* Copy references to packets which we expect not to be transmitted */
first_fail_idx = (TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
(TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT *
TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)) +
TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX;
for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
expected_tx_fail_pkts[i] = pkt_burst[first_fail_idx +
(i * TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)];
}
/* Set virtual slave to only fail transmission of
* TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT packets in burst */
virtual_ethdev_tx_burst_fn_set_success(
test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
0);
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
TEST_RR_SLAVE_TX_FAIL_BURST_SIZE);
TEST_ASSERT_EQUAL(tx_count, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,
"Transmitted (%d) an unexpected (%d) number of packets", tx_count,
TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Verify that failed packet are expected failed packets */
for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
TEST_ASSERT_EQUAL(expected_tx_fail_pkts[i], pkt_burst[i + tx_count],
"expected mbuf (%d) pointer %p not expected pointer %p",
i, expected_tx_fail_pkts[i], pkt_burst[i + tx_count]);
}
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Verify slave ports tx stats */
for (i = 0; i < test_params->bonded_slave_count; i++) {
int slave_expected_tx_count;
rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
slave_expected_tx_count = TEST_RR_SLAVE_TX_FAIL_BURST_SIZE /
test_params->bonded_slave_count;
if (i == TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX)
slave_expected_tx_count = slave_expected_tx_count -
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT;
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)slave_expected_tx_count,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[i],
(unsigned int)port_stats.opackets, slave_expected_tx_count);
}
/* 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");
free_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
test_roundrobin_rx_burst_on_single_slave(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 i, j, burst_size = 25;
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
"Failed to initialize bonded device with slaves");
/* Generate test bursts of packets to transmit */
TEST_ASSERT_EQUAL(generate_test_burst(
gen_pkt_burst, burst_size, 0, 1, 0, 0, 0), burst_size,
"burst generation failed");
for (i = 0; i < test_params->bonded_slave_count; i++) {
/* 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 */
/* Send burst on bonded port */
TEST_ASSERT_EQUAL(rte_eth_rx_burst(
test_params->bonded_port_id, 0, rx_pkt_burst,
MAX_PKT_BURST), burst_size,
"round-robin 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,
"Bonded Port (%d) ipackets value (%u) not as expected (%d)",
test_params->bonded_port_id,
(unsigned int)port_stats.ipackets, burst_size);
/* Verify bonded slave devices rx count */
/* Verify slave ports tx stats */
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)", test_params->slave_port_ids[i],
(unsigned int)port_stats.ipackets, burst_size);
} else {
TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
"Slave Port (%d) ipackets value (%u) not as expected"
" (%d)", test_params->slave_port_ids[i],
(unsigned int)port_stats.ipackets, 0);
}
/* Reset bonded slaves stats */
rte_eth_stats_reset(test_params->slave_port_ids[j]);
}
/* reset bonded device stats */
rte_eth_stats_reset(test_params->bonded_port_id);
}
/* free mbufs */
for (i = 0; i < MAX_PKT_BURST; i++) {
if (rx_pkt_burst[i] != NULL)
rte_pktmbuf_free(rx_pkt_burst[i]);
}
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT (3)
static int
test_roundrobin_rx_burst_on_multiple_slaves(void)
{
struct rte_mbuf *gen_pkt_burst[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
struct rte_eth_stats port_stats;
int burst_size[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT] = { 15, 13, 36 };
int i, nb_rx;
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
"Failed to initialize bonded device with slaves");
/* Generate test bursts of packets to transmit */
for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
TEST_ASSERT_EQUAL(generate_test_burst(
&gen_pkt_burst[i][0], burst_size[i], 0, 1, 0, 0, 0),
burst_size[i], "burst generation failed");
}
/* Add rx data to slaves */
for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
&gen_pkt_burst[i][0], burst_size[i]);
}
/* Call rx burst on bonded device */
/* Send burst on bonded port */
nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
MAX_PKT_BURST);
TEST_ASSERT_EQUAL(nb_rx , burst_size[0] + burst_size[1] + burst_size[2],
"round-robin rx burst failed (%d != %d)\n", nb_rx,
burst_size[0] + burst_size[1] + burst_size[2]);
/* 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[0] + burst_size[1] + burst_size[2]),
"Bonded Port (%d) ipackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
burst_size[0] + burst_size[1] + burst_size[2]);
/* Verify bonded slave devices rx counts */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0],
(unsigned int)port_stats.ipackets, burst_size[0]);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[1], (unsigned int)port_stats.ipackets,
burst_size[1]);
rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[2],
(unsigned int)port_stats.ipackets, burst_size[2]);
rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[3],
(unsigned int)port_stats.ipackets, 0);
/* free mbufs */
for (i = 0; i < MAX_PKT_BURST; i++) {
if (rx_pkt_burst[i] != NULL)
rte_pktmbuf_free(rx_pkt_burst[i]);
}
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
test_roundrobin_verify_mac_assignment(void)
{
struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_2;
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_2);
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
"Failed to initialize bonded device with slaves");
/* Verify that all MACs are the same as first slave added to bonded dev */
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
* propagate 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_2, &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_2, &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 ether_addr *)bonded_mac),
"Failed to set MAC");
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\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_roundrobin_verify_promiscuous_enable_disable(void)
{
int i, promiscuous_en;
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
"Failed to initialize bonded device with slaves");
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, 1,
"Port (%d) promiscuous mode not enabled",
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, 1,
"slave port (%d) promiscuous mode not enabled",
test_params->slave_port_ids[i]);
}
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, 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, 0,
"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();
}
#define TEST_RR_LINK_STATUS_SLAVE_COUNT (4)
#define TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT (2)
static int
test_roundrobin_verify_slave_link_status_change_behaviour(void)
{
struct rte_mbuf *tx_pkt_burst[MAX_PKT_BURST] = { NULL };
struct rte_mbuf *gen_pkt_burst[TEST_RR_LINK_STATUS_SLAVE_COUNT][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;
/* NULL all pointers in array to simplify cleanup */
memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
/* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves
* in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ROUND_ROBIN, 0, TEST_RR_LINK_STATUS_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, TEST_RR_LINK_STATUS_SLAVE_COUNT,
"Number of slaves (%d) is not as expected (%d).",
slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT);
slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT,
"Number of active slaves (%d) is not as expected (%d).",
slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT);
/* Set 2 slaves eth_devs 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,
TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT,
"Number of active slaves (%d) is not as expected (%d).\n",
slave_count, TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT);
burst_size = 20;
/* Verify that pkts are not sent on slaves with link status down:
*
* 1. Generate test burst of traffic
* 2. Transmit burst on bonded eth_dev
* 3. Verify stats for bonded eth_dev (opackets = burst_size)
* 4. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
*/
TEST_ASSERT_EQUAL(
generate_test_burst(tx_pkt_burst, burst_size, 0, 1, 0, 0, 0),
burst_size, "generate_test_burst failed");
rte_eth_stats_reset(test_params->bonded_port_id);
TEST_ASSERT_EQUAL(
rte_eth_tx_burst(test_params->bonded_port_id, 0, tx_pkt_burst,
burst_size), burst_size, "rte_eth_tx_burst failed");
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
"Port (%d) opackets stats (%d) not expected (%d) value",
test_params->bonded_port_id, (int)port_stats.opackets,
burst_size);
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
"Port (%d) opackets stats (%d) not expected (%d) value",
test_params->slave_port_ids[0], (int)port_stats.opackets, 10);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
"Port (%d) opackets stats (%d) not expected (%d) value",
test_params->slave_port_ids[1], (int)port_stats.opackets, 0);
rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
"Port (%d) opackets stats (%d) not expected (%d) value",
test_params->slave_port_ids[2], (int)port_stats.opackets, 10);
rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
"Port (%d) opackets stats (%d) not expected (%d) value",
test_params->slave_port_ids[3], (int)port_stats.opackets, 0);
/* Verify that pkts are not sent on slaves with link status down:
*
* 1. Generate test bursts of traffic
* 2. Add bursts on to virtual eth_devs
* 3. Rx burst on bonded eth_dev, expected (burst_ size *
* TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) received
* 4. Verify stats for bonded eth_dev
* 6. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
*/
for (i = 0; i < TEST_RR_LINK_STATUS_SLAVE_COUNT; i++) {
TEST_ASSERT_EQUAL(generate_test_burst(
&gen_pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0),
burst_size, "failed to generate packet burst");
virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
&gen_pkt_burst[i][0], burst_size);
}
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);
/* free mbufs */
for (i = 0; i < MAX_PKT_BURST; i++) {
if (rx_pkt_burst[i] != NULL)
rte_pktmbuf_free(rx_pkt_burst[i]);
}
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT (2)
uint8_t polling_slave_mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00 };
int polling_test_slaves[TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT] = { -1, -1 };
static int
test_roundrobin_verfiy_polling_slave_link_status_change(void)
{
struct ether_addr *mac_addr = (struct ether_addr *)polling_slave_mac;
char slave_name[RTE_ETH_NAME_MAX_LEN];
int i;
for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) {
/* Generate slave name / MAC address */
snprintf(slave_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_poll_%d", i);
mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i;
/* Create slave devices with no ISR Support */
if (polling_test_slaves[i] == -1) {
polling_test_slaves[i] = virtual_ethdev_create(slave_name, mac_addr,
rte_socket_id(), 0);
TEST_ASSERT(polling_test_slaves[i] >= 0,
"Failed to create virtual virtual ethdev %s\n", slave_name);
/* Configure slave */
TEST_ASSERT_SUCCESS(configure_ethdev(polling_test_slaves[i], 0, 0),
"Failed to configure virtual ethdev %s(%d)", slave_name,
polling_test_slaves[i]);
}
/* Add slave to bonded device */
TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
polling_test_slaves[i]),
"Failed to add slave %s(%d) to bonded device %d",
slave_name, polling_test_slaves[i],
test_params->bonded_port_id);
}
/* Initialize bonded device */
TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 1, 1),
"Failed to configure bonded device %d",
test_params->bonded_port_id);
/* Register link status change interrupt callback */
rte_eth_dev_callback_register(test_params->bonded_port_id,
RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
&test_params->bonded_port_id);
/* link status change callback for first slave link up */
test_lsc_interrupt_count = 0;
virtual_ethdev_set_link_status(polling_test_slaves[0], 1);
TEST_ASSERT_SUCCESS(lsc_timeout(15000), "timed out waiting for interrupt");
/* no link status change callback for second slave link up */
test_lsc_interrupt_count = 0;
virtual_ethdev_set_link_status(polling_test_slaves[1], 1);
TEST_ASSERT_FAIL(lsc_timeout(15000), "unexpectedly succeeded");
/* link status change callback for both slave links down */
test_lsc_interrupt_count = 0;
virtual_ethdev_set_link_status(polling_test_slaves[0], 0);
virtual_ethdev_set_link_status(polling_test_slaves[1], 0);
TEST_ASSERT_SUCCESS(lsc_timeout(20000), "timed out waiting for interrupt");
/* Un-Register link status change interrupt callback */
rte_eth_dev_callback_unregister(test_params->bonded_port_id,
RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
&test_params->bonded_port_id);
/* Clean up and remove slaves from bonded device */
for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) {
TEST_ASSERT_SUCCESS(
rte_eth_bond_slave_remove(test_params->bonded_port_id,
polling_test_slaves[i]),
"Failed to remove slave %d from bonded port (%d)",
polling_test_slaves[i], test_params->bonded_port_id);
}
return remove_slaves_and_stop_bonded_device();
}
/** Active Backup Mode Tests */
static int
test_activebackup_tx_burst(void)
{
int i, pktlen, primary_port, burst_size;
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
struct rte_eth_stats port_stats;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ACTIVE_BACKUP, 0, 1, 1),
"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,
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);
burst_size = 20 * test_params->bonded_slave_count;
TEST_ASSERT(burst_size < MAX_PKT_BURST,
"Burst size specified is greater than supported.");
/* Generate a burst of packets to transmit */
TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, pkts_burst,
test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN, 1),
burst_size, "failed to generate burst correctly");
/* Send burst on bonded port */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
burst_size), burst_size, "tx burst failed");
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
burst_size);
primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
/* 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);
if (test_params->slave_port_ids[i] == primary_port) {
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id,
(unsigned int)port_stats.opackets,
burst_size / test_params->bonded_slave_count);
} else {
TEST_ASSERT_EQUAL(port_stats.opackets, 0,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id,
(unsigned int)port_stats.opackets, 0);
}
}
/* 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 */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
pkts_burst, burst_size), 0, "Sending empty burst failed");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT (4)
static int
test_activebackup_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;
int i, j, burst_size = 17;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ACTIVE_BACKUP, 0,
TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1),
"Failed to initialize bonded device with slaves");
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 */
TEST_ASSERT_EQUAL(rte_eth_rx_burst(test_params->bonded_port_id, 0,
&rx_pkt_burst[0], MAX_PKT_BURST), burst_size,
"rte_eth_rx_burst failed");
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)",
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)", test_params->slave_port_ids[i],
(unsigned int)port_stats.ipackets, burst_size);
} else {
TEST_ASSERT_EQUAL(port_stats.ipackets, 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, 0,
"Slave Port (%d) ipackets value (%u) not as expected "
"(%d)", test_params->slave_port_ids[i],
(unsigned int)port_stats.ipackets, 0);
}
}
/* free mbufs */
for (i = 0; i < MAX_PKT_BURST; i++) {
if (rx_pkt_burst[i] != NULL) {
rte_pktmbuf_free(rx_pkt_burst[i]);
rx_pkt_burst[i] = NULL;
}
}
/* 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_activebackup_verify_promiscuous_enable_disable(void)
{
int i, primary_port, promiscuous_en;
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ACTIVE_BACKUP, 0, 4, 1),
"Failed to initialize bonded device with slaves");
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);
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++) {
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, 1,
"slave port (%d) promiscuous mode not enabled",
test_params->slave_port_ids[i]);
} else {
TEST_ASSERT_EQUAL(promiscuous_en, 0,
"slave port (%d) promiscuous mode 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\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, 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_activebackup_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_ACTIVE_BACKUP, 0, 2, 1),
"Failed to initialize bonded device with slaves");
/* 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 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 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_activebackup_verify_slave_link_status_change_failover(void)
{
struct rte_mbuf *pkt_burst[TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT][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, primary_port;
burst_size = 21;
memset(pkt_burst, 0, sizeof(pkt_burst));
/* Generate packet burst for testing */
TEST_ASSERT_EQUAL(generate_test_burst(
&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size,
"generate_test_burst failed");
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ACTIVE_BACKUP, 0,
TEST_ACTIVE_BACKUP_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).",
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);
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");
/* Verify that pkts are sent on new primary slave */
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");
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[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, 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_EQUAL(port_stats.opackets, 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_EQUAL(port_stats.opackets, 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_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) {
TEST_ASSERT_EQUAL(generate_test_burst(
&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0), burst_size,
"generate_test_burst failed");
virtual_ethdev_add_mbufs_to_rx_queue(
test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size);
}
TEST_ASSERT_EQUAL(rte_eth_rx_burst(
test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
burst_size, "rte_eth_rx_burst\n");
/* 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",
test_params->bonded_port_id);
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[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, 0,
"(%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[3], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, 0,
"(%d) port_stats.opackets not as expected",
test_params->slave_port_ids[3]);
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
/** Balance Mode Tests */
static int
test_balance_xmit_policy_configuration(void)
{
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1),
"Failed to initialize_bonded_device_with_slaves.");
/* Invalid port id */
TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_set(
INVALID_PORT_ID, BALANCE_XMIT_POLICY_LAYER2),
"Expected call to failed as invalid port specified.");
/* Set xmit policy on non bonded device */
TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_set(
test_params->slave_port_ids[0], BALANCE_XMIT_POLICY_LAYER2),
"Expected call to failed as invalid port specified.");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
"Failed to set balance xmit policy.");
TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id),
BALANCE_XMIT_POLICY_LAYER2, "balance xmit policy not as expected.");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER23),
"Failed to set balance xmit policy.");
TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id),
BALANCE_XMIT_POLICY_LAYER23,
"balance xmit policy not as expected.");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER34),
"Failed to set balance xmit policy.");
TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id),
BALANCE_XMIT_POLICY_LAYER34,
"balance xmit policy not as expected.");
/* Invalid port id */
TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_get(INVALID_PORT_ID),
"Expected call to failed as invalid port specified.");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT (2)
static int
test_balance_l2_tx_burst(void)
{
struct rte_mbuf *pkts_burst[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
int burst_size[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT] = { 10, 15 };
uint16_t pktlen;
int i;
struct rte_eth_stats port_stats;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BALANCE, 0, TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1),
"Failed to initialize_bonded_device_with_slaves.");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
"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,
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 a burst 1 of packets to transmit */
TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, &pkts_burst[0][0],
test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
test_params->pkt_udp_hdr, burst_size[0],
PACKET_BURST_GEN_PKT_LEN, 1), burst_size[0],
"failed to generate packet burst");
initialize_eth_header(test_params->pkt_eth_hdr,
(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],
test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
test_params->pkt_udp_hdr, burst_size[1],
PACKET_BURST_GEN_PKT_LEN, 1), burst_size[1],
"failed to generate packet burst");
/* Send burst 1 on bonded port */
for (i = 0; i < TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT; i++) {
TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
&pkts_burst[i][0], burst_size[i]),
burst_size[i], "Failed to transmit packet burst");
}
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)(burst_size[0] + burst_size[1]),
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
burst_size[0] + burst_size[1]);
/* Verify slave ports tx stats */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size[0],
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0], (unsigned int)port_stats.opackets,
burst_size[0]);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size[1],
"Slave Port (%d) opackets value (%u) not as expected (%d)\n",
test_params->slave_port_ids[1], (unsigned int)port_stats.opackets,
burst_size[1]);
/* 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 */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, &pkts_burst[0][0], burst_size[0]),
0, "Expected zero packet");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
uint8_t toggle_mac_addr, uint8_t toggle_ip_addr)
{
int i, burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
struct rte_eth_stats port_stats;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BALANCE, 0, 2, 1),
"Failed to initialize_bonded_device_with_slaves.");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER23),
"Failed to set balance xmit policy.");
burst_size_1 = 20;
burst_size_2 = 10;
TEST_ASSERT(burst_size_1 < MAX_PKT_BURST || burst_size_2 < MAX_PKT_BURST,
"Burst size specified is greater than supported.");
/* Generate test bursts of packets to transmit */
TEST_ASSERT_EQUAL(generate_test_burst(
pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0, 0, 0),
burst_size_1, "failed to generate packet burst");
TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4,
toggle_mac_addr, toggle_ip_addr, 0), burst_size_2,
"failed to generate packet burst");
/* Send burst 1 on bonded port */
nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
burst_size_1);
TEST_ASSERT_EQUAL(nb_tx_1, burst_size_1, "tx burst failed");
/* Send burst 2 on bonded port */
nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
burst_size_2);
TEST_ASSERT_EQUAL(nb_tx_2, burst_size_2, "tx burst failed");
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(nb_tx_1 + nb_tx_2),
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
nb_tx_1 + nb_tx_2);
/* Verify slave ports tx stats */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_1,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0], (unsigned int)port_stats.opackets,
nb_tx_1);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_2,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[1], (unsigned int)port_stats.opackets,
nb_tx_2);
/* 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 */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, pkts_burst_1,
burst_size_1), 0, "Expected zero packet");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
test_balance_l23_tx_burst_ipv4_toggle_ip_addr(void)
{
return balance_l23_tx_burst(0, 1, 0, 1);
}
static int
test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr(void)
{
return balance_l23_tx_burst(1, 1, 0, 1);
}
static int
test_balance_l23_tx_burst_ipv6_toggle_ip_addr(void)
{
return balance_l23_tx_burst(0, 0, 0, 1);
}
static int
test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr(void)
{
return balance_l23_tx_burst(1, 0, 0, 1);
}
static int
test_balance_l23_tx_burst_toggle_mac_addr(void)
{
return balance_l23_tx_burst(0, 0, 1, 0);
}
static int
balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
uint8_t toggle_mac_addr, uint8_t toggle_ip_addr,
uint8_t toggle_udp_port)
{
int i, burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
struct rte_eth_stats port_stats;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BALANCE, 0, 2, 1),
"Failed to initialize_bonded_device_with_slaves.");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER34),
"Failed to set balance xmit policy.");
burst_size_1 = 20;
burst_size_2 = 10;
TEST_ASSERT(burst_size_1 < MAX_PKT_BURST || burst_size_2 < MAX_PKT_BURST,
"Burst size specified is greater than supported.");
/* Generate test bursts of packets to transmit */
TEST_ASSERT_EQUAL(generate_test_burst(
pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0, 0, 0),
burst_size_1, "failed to generate burst");
TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, burst_size_2,
vlan_enabled, ipv4, toggle_mac_addr, toggle_ip_addr,
toggle_udp_port), burst_size_2, "failed to generate burst");
/* Send burst 1 on bonded port */
nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
burst_size_1);
TEST_ASSERT_EQUAL(nb_tx_1, burst_size_1, "tx burst failed");
/* Send burst 2 on bonded port */
nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
burst_size_2);
TEST_ASSERT_EQUAL(nb_tx_2, burst_size_2, "tx burst failed");
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(nb_tx_1 + nb_tx_2),
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
nb_tx_1 + nb_tx_2);
/* Verify slave ports tx stats */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_1,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0], (unsigned int)port_stats.opackets,
nb_tx_1);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_2,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[1], (unsigned int)port_stats.opackets,
nb_tx_2);
/* 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 */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, pkts_burst_1,
burst_size_1), 0, "Expected zero packet");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
test_balance_l34_tx_burst_ipv4_toggle_ip_addr(void)
{
return balance_l34_tx_burst(0, 1, 0, 1, 0);
}
static int
test_balance_l34_tx_burst_ipv4_toggle_udp_port(void)
{
return balance_l34_tx_burst(0, 1, 0, 0, 1);
}
static int
test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr(void)
{
return balance_l34_tx_burst(1, 1, 0, 1, 0);
}
static int
test_balance_l34_tx_burst_ipv6_toggle_ip_addr(void)
{
return balance_l34_tx_burst(0, 0, 0, 1, 0);
}
static int
test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr(void)
{
return balance_l34_tx_burst(1, 0, 0, 1, 0);
}
static int
test_balance_l34_tx_burst_ipv6_toggle_udp_port(void)
{
return balance_l34_tx_burst(0, 0, 0, 0, 1);
}
#define TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT (2)
#define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 (40)
#define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2 (20)
#define TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT (25)
#define TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (0)
static int
test_balance_tx_burst_slave_tx_fail(void)
{
struct rte_mbuf *pkts_burst_1[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1];
struct rte_mbuf *pkts_burst_2[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2];
struct rte_mbuf *expected_fail_pkts[TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT];
struct rte_eth_stats port_stats;
int i, first_tx_fail_idx, tx_count_1, tx_count_2;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BALANCE, 0,
TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
"Failed to initialise bonded device");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
"Failed to set balance xmit policy.");
/* Generate test bursts for transmission */
TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_1,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1, 0, 0, 0, 0, 0),
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1,
"Failed to generate test packet burst 1");
first_tx_fail_idx = TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT;
/* copy mbuf referneces for expected transmission failures */
for (i = 0; i < TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT; i++)
expected_fail_pkts[i] = pkts_burst_1[i + first_tx_fail_idx];
TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, 0, 0, 1, 0, 0),
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
"Failed to generate test packet burst 2");
/* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail
* transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */
virtual_ethdev_tx_burst_fn_set_success(
test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
0);
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Transmit burst 1 */
tx_count_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1);
TEST_ASSERT_EQUAL(tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,
"Transmitted (%d) packets, expected to transmit (%d) packets",
tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Verify that failed packet are expected failed packets */
for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst_1[i + tx_count_1],
"expected mbuf (%d) pointer %p not expected pointer %p",
i, expected_fail_pkts[i], pkts_burst_1[i + tx_count_1]);
}
/* Transmit burst 2 */
tx_count_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
TEST_ASSERT_EQUAL(tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
"Transmitted (%d) packets, expected to transmit (%d) packets",
tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)((TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2),
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
(TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
/* Verify slave ports tx stats */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0],
(unsigned int)port_stats.opackets,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
"Slave Port (%d) opackets value (%u) not as expected (%d)",
test_params->slave_port_ids[1],
(unsigned int)port_stats.opackets,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
/* 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");
free_mbufs(&pkts_burst_1[tx_count_1],
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define TEST_BALANCE_RX_BURST_SLAVE_COUNT (3)
static int
test_balance_rx_burst(void)
{
struct rte_mbuf *gen_pkt_burst[TEST_BALANCE_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
struct rte_eth_stats port_stats;
int burst_size[TEST_BALANCE_RX_BURST_SLAVE_COUNT] = { 10, 5, 30 };
int i, j;
memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BALANCE, 0, 3, 1),
"Failed to initialise bonded device");
/* Generate test bursts of packets to transmit */
for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
TEST_ASSERT_EQUAL(generate_test_burst(
&gen_pkt_burst[i][0], burst_size[i], 0, 0, 1,
0, 0), burst_size[i],
"failed to generate packet burst");
}
/* Add rx data to slaves */
for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
&gen_pkt_burst[i][0], burst_size[i]);
}
/* Call rx burst on bonded device */
/* Send burst on bonded port */
TEST_ASSERT_EQUAL(rte_eth_rx_burst(test_params->bonded_port_id, 0,
rx_pkt_burst, MAX_PKT_BURST),
burst_size[0] + burst_size[1] + burst_size[2],
"balance rx burst failed\n");
/* 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[0] + burst_size[1] + burst_size[2]),
"Bonded Port (%d) ipackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
burst_size[0] + burst_size[1] + burst_size[2]);
/* Verify bonded slave devices rx counts */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0],
(unsigned int)port_stats.ipackets, burst_size[0]);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[1], (unsigned int)port_stats.ipackets,
burst_size[1]);
rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets,
burst_size[2]);
rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets,
0);
/* free mbufs */
for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
for (j = 0; j < MAX_PKT_BURST; j++) {
if (gen_pkt_burst[i][j] != NULL) {
rte_pktmbuf_free(gen_pkt_burst[i][j]);
gen_pkt_burst[i][j] = NULL;
}
}
}
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
test_balance_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_BALANCE, 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_balance_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_BALANCE, 0, 2, 1),
"Failed to initialise 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_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[1]);
/* 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[1]),
"Failed to set bonded port (%d) primary port to (%d)\n",
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_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[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 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 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_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[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");
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(&bonded_mac, &read_mac_addr,
sizeof(read_mac_addr)),
"slave port (%d) mac address not as expected\n",
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();
}
#define TEST_BALANCE_LINK_STATUS_SLAVE_COUNT (4)
static int
test_balance_verify_slave_link_status_change_behaviour(void)
{
struct rte_mbuf *pkt_burst[TEST_BALANCE_LINK_STATUS_SLAVE_COUNT][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_BALANCE, 0, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1),
"Failed to initialise bonded device");
TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
"Failed to set balance xmit policy.");
/* 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, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT,
"Number of slaves (%d) is not as expected (%d).",
slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
slaves, RTE_MAX_ETHPORTS);
TEST_ASSERT_EQUAL(slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT,
"Number of active slaves (%d) is not as expected (%d).",
slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
/* 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);
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);
/* Send to sets of packet burst and verify that they are balanced across
* slaves */
burst_size = 21;
TEST_ASSERT_EQUAL(generate_test_burst(
&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size,
"generate_test_burst failed");
TEST_ASSERT_EQUAL(generate_test_burst(
&pkt_burst[1][0], burst_size, 0, 1, 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");
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, &pkt_burst[1][0], burst_size),
burst_size, "rte_eth_tx_burst failed");
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size),
"(%d) port_stats.opackets (%d) not as expected (%d).",
test_params->bonded_port_id, (int)port_stats.opackets,
burst_size + burst_size);
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 (%d) not as expected (%d).",
test_params->slave_port_ids[0], (int)port_stats.opackets,
burst_size);
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 (%d) not as expected (%d).",
test_params->slave_port_ids[2], (int)port_stats.opackets,
burst_size);
/* verify that all packets get send on primary slave when no other slaves
* are available */
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[2], 0);
TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 1,
"Number of active slaves (%d) is not as expected (%d).",
slave_count, 1);
TEST_ASSERT_EQUAL(generate_test_burst(
&pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0), burst_size,
"generate_test_burst failed");
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, &pkt_burst[1][0], burst_size),
burst_size, "rte_eth_tx_burst failed");
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)(burst_size + burst_size + burst_size),
"(%d) port_stats.opackets (%d) not as expected (%d).\n",
test_params->bonded_port_id, (int)port_stats.opackets,
burst_size + burst_size + burst_size);
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size),
"(%d) port_stats.opackets (%d) not as expected (%d).",
test_params->slave_port_ids[0], (int)port_stats.opackets,
burst_size + burst_size);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[0], 0);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[1], 1);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[2], 1);
virtual_ethdev_simulate_link_status_interrupt(
test_params->slave_port_ids[3], 1);
for (i = 0; i < TEST_BALANCE_LINK_STATUS_SLAVE_COUNT; i++) {
TEST_ASSERT_EQUAL(generate_test_burst(
&pkt_burst[i][0], burst_size, 0, 1, 0, 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 */
rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
MAX_PKT_BURST);
/* 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 * 3),
"(%d) port_stats.ipackets (%d) not as expected (%d)\n",
test_params->bonded_port_id, (int)port_stats.ipackets,
burst_size * 3);
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
test_broadcast_tx_burst(void)
{
int i, pktlen, burst_size;
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
struct rte_eth_stats port_stats;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BROADCAST, 0, 2, 1),
"Failed to initialise bonded device");
initialize_eth_header(test_params->pkt_eth_hdr,
(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,
dst_addr_0, pktlen);
burst_size = 20 * test_params->bonded_slave_count;
TEST_ASSERT(burst_size < MAX_PKT_BURST,
"Burst size specified is greater than supported.");
/* Generate a burst of packets to transmit */
TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool,
pkts_burst, test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
1, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN,
1), burst_size, "Failed to generate packet burst");
/* Send burst on bonded port */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
pkts_burst, burst_size), burst_size,
"Bonded Port (%d) rx burst failed, packets transmitted value "
"not as expected (%d)",
test_params->bonded_port_id, burst_size);
/* Verify bonded port tx stats */
rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)burst_size * test_params->bonded_slave_count,
"Bonded Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.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);
TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
"Slave Port (%d) opackets value (%u) not as expected (%d)\n",
test_params->bonded_port_id,
(unsigned int)port_stats.opackets, burst_size);
}
/* 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 */
TEST_ASSERT_EQUAL(rte_eth_tx_burst(
test_params->bonded_port_id, 0, pkts_burst, burst_size), 0,
"transmitted an unexpected number of packets");
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT (3)
#define TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE (40)
#define TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT (15)
#define TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT (10)
static int
test_broadcast_tx_burst_slave_tx_fail(void)
{
struct rte_mbuf *pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE];
struct rte_mbuf *expected_fail_pkts[TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT];
struct rte_eth_stats port_stats;
int i, tx_count;
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BROADCAST, 0,
TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
"Failed to initialise bonded device");
/* Generate test bursts for transmission */
TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst,
TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE, 0, 0, 0, 0, 0),
TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE,
"Failed to generate test packet burst");
for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {
expected_fail_pkts[i] = pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT + i];
}
/* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail
* transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */
virtual_ethdev_tx_burst_fn_set_success(
test_params->slave_port_ids[0],
0);
virtual_ethdev_tx_burst_fn_set_success(
test_params->slave_port_ids[1],
0);
virtual_ethdev_tx_burst_fn_set_success(
test_params->slave_port_ids[2],
0);
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
test_params->slave_port_ids[0],
TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
test_params->slave_port_ids[1],
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
test_params->slave_port_ids[2],
TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
/* Transmit burst */
tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE);
TEST_ASSERT_EQUAL(tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,
"Transmitted (%d) packets, expected to transmit (%d) packets",
tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
/* Verify that failed packet are expected failed packets */
for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {
TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst[i + tx_count],
"expected mbuf (%d) pointer %p not expected pointer %p",
i, expected_fail_pkts[i], pkts_burst[i + tx_count]);
}
/* Verify slave ports tx stats */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,
"Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,
"Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
TEST_ASSERT_EQUAL(port_stats.opackets,
(uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,
"Port (%d) opackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.opackets,
TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
/* Verify that all mbufs who transmission failed have a ref value of one */
TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst[tx_count],
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, 1),
"mbufs refcnts not as expected");
free_mbufs(&pkts_burst[tx_count],
TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
#define BROADCAST_RX_BURST_NUM_OF_SLAVES (3)
static int
test_broadcast_rx_burst(void)
{
struct rte_mbuf *gen_pkt_burst[BROADCAST_RX_BURST_NUM_OF_SLAVES][MAX_PKT_BURST];
struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
struct rte_eth_stats port_stats;
int burst_size[BROADCAST_RX_BURST_NUM_OF_SLAVES] = { 10, 5, 30 };
int i, j;
memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
/* Initialize bonded device with 4 slaves in round robin mode */
TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
BONDING_MODE_BROADCAST, 0, 3, 1),
"Failed to initialise bonded device");
/* Generate test bursts of packets to transmit */
for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
TEST_ASSERT_EQUAL(generate_test_burst(
&gen_pkt_burst[i][0], burst_size[i], 0, 0, 1, 0, 0),
burst_size[i], "failed to generate packet burst");
}
/* Add rx data to slave 0 */
for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
&gen_pkt_burst[i][0], burst_size[i]);
}
/* Call rx burst on bonded device */
/* Send burst on bonded port */
TEST_ASSERT_EQUAL(rte_eth_rx_burst(
test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
burst_size[0] + burst_size[1] + burst_size[2],
"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[0] + burst_size[1] + burst_size[2]),
"Bonded Port (%d) ipackets value (%u) not as expected (%d)",
test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
burst_size[0] + burst_size[1] + burst_size[2]);
/* Verify bonded slave devices rx counts */
rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets,
burst_size[0]);
rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets,
burst_size[1]);
rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2],
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets,
burst_size[2]);
rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
"Slave Port (%d) ipackets value (%u) not as expected (%d)",
test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets,
0);
/* free mbufs allocate for rx testing */
for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
for (j = 0; j < MAX_PKT_BURST; j++) {
if (gen_pkt_burst[i][j] != NULL) {
rte_pktmbuf_free(gen_pkt_burst[i][j]);
gen_pkt_burst[i][j] = NULL;
}
}
}
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
static int
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 ether_addr read_mac_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 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 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();
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)
{
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 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 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;
uint16_t slaves[RTE_MAX_ETHPORTS];
int i, 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);
/* 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 */
}
};
static int
test_link_bonding(void)
{
return unit_test_suite_runner(&link_bonding_test_suite);
}
REGISTER_TEST_COMMAND(link_bonding_autotest, test_link_bonding);