summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeclan Doherty <declan.doherty@intel.com>2014-11-24 16:33:41 +0000
committerThomas Monjalon <thomas.monjalon@6wind.com>2014-11-24 21:44:02 +0100
commita45b288ef21a5ab1da6bbe95a33404006c7cb051 (patch)
tree0b259ae2decdc9540c0db7ead1c39ecbd32c67a5
parent620f98d66f65a13407929b2af2ca26985f1e9d5c (diff)
downloaddpdk-a45b288ef21a5ab1da6bbe95a33404006c7cb051.zip
dpdk-a45b288ef21a5ab1da6bbe95a33404006c7cb051.tar.gz
dpdk-a45b288ef21a5ab1da6bbe95a33404006c7cb051.tar.xz
bond: support link status polling
Signed-off-by: Declan Doherty <declan.doherty@intel.com> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com> Tested-by: SunX Jiajia <sunx.jiajia@intel.com>
-rw-r--r--app/test-pmd/cmdline.c63
-rw-r--r--app/test/test.h7
-rw-r--r--app/test/test_link_bonding.c265
-rw-r--r--app/test/virtual_pmd.c17
-rw-r--r--app/test/virtual_pmd.h48
-rw-r--r--doc/guides/testpmd_app_ug/testpmd_funcs.rst19
-rw-r--r--lib/librte_pmd_bond/rte_eth_bond.h80
-rw-r--r--lib/librte_pmd_bond/rte_eth_bond_api.c315
-rw-r--r--lib/librte_pmd_bond/rte_eth_bond_args.c28
-rw-r--r--lib/librte_pmd_bond/rte_eth_bond_pmd.c393
-rw-r--r--lib/librte_pmd_bond/rte_eth_bond_private.h71
11 files changed, 958 insertions, 348 deletions
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index ef8e9cd..9c6632d 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -462,6 +462,9 @@ static void cmd_help_long_parsed(void *parsed_result,
"set bonding xmit_balance_policy (port_id) (l2|l23|l34)\n"
" Set the transmit balance policy for bonded device running in balance mode.\n\n"
+
+ "set bonding mon_period (port_id) (value)\n"
+ " Set the bonding link status monitoring polling period in ms.\n\n"
#endif
"set link-up port (port_id)\n"
" Set link up for a port.\n\n"
@@ -3738,6 +3741,65 @@ cmdline_parse_inst_t cmd_set_bond_mac_addr = {
}
};
+
+/* *** SET LINK STATUS MONITORING POLLING PERIOD ON BONDED DEVICE *** */
+struct cmd_set_bond_mon_period_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mon_period;
+ uint8_t port_num;
+ uint32_t period_ms;
+};
+
+static void cmd_set_bond_mon_period_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bond_mon_period_result *res = parsed_result;
+ int ret;
+
+ if (res->port_num >= nb_ports) {
+ printf("Port id %d must be less than %d\n", res->port_num, nb_ports);
+ return;
+ }
+
+ ret = rte_eth_bond_link_monitoring_set(res->port_num, res->period_ms);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("set_bond_mac_addr error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_set_bond_mon_period_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_bond_mon_period_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_set_bond_mon_period_mon_period =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ mon_period, "mon_period");
+cmdline_parse_token_num_t cmd_set_bond_mon_period_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ port_num, UINT8);
+cmdline_parse_token_num_t cmd_set_bond_mon_period_period_ms =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ period_ms, UINT32);
+
+cmdline_parse_inst_t cmd_set_bond_mon_period = {
+ .f = cmd_set_bond_mon_period_parsed,
+ .data = (void *) 0,
+ .help_str = "set bonding mon_period (port_id) (period_ms): ",
+ .tokens = {
+ (void *)&cmd_set_bond_mon_period_set,
+ (void *)&cmd_set_bond_mon_period_bonding,
+ (void *)&cmd_set_bond_mon_period_mon_period,
+ (void *)&cmd_set_bond_mon_period_portnum,
+ (void *)&cmd_set_bond_mon_period_period_ms,
+ NULL
+ }
+};
+
#endif /* RTE_LIBRTE_PMD_BOND */
/* *** SET FORWARDING MODE *** */
@@ -7792,6 +7854,7 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *) &cmd_create_bonded_device,
(cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
(cmdline_parse_inst_t *) &cmd_set_balance_xmit_policy,
+ (cmdline_parse_inst_t *) &cmd_set_bond_mon_period,
#endif
(cmdline_parse_inst_t *)&cmd_vlan_offload,
(cmdline_parse_inst_t *)&cmd_vlan_tpid,
diff --git a/app/test/test.h b/app/test/test.h
index bd44a7f..d5b6951 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -62,14 +62,15 @@
#define TEST_ASSERT_SUCCESS(val, msg, ...) do { \
if (!(val == 0)) { \
- printf("TestCase %s() line %d failed: " \
- msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ printf("TestCase %s() line %d failed (err %d): " \
+ msg "\n", __func__, __LINE__, val, \
+ ##__VA_ARGS__); \
return -1; \
} \
} while (0)
#define TEST_ASSERT_FAIL(val, msg, ...) do { \
- if (!(val != -1)) { \
+ if (!(val != 0)) { \
printf("TestCase %s() line %d failed: " \
msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
return -1; \
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index c11a0bc..2411125 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -234,42 +234,34 @@ configure_ethdev(uint8_t port_id, uint8_t start, uint8_t en_isr)
else
default_pmd_conf.intr_conf.lsc = 0;
- if (rte_eth_dev_configure(port_id, test_params->nb_rx_q,
- test_params->nb_tx_q, &default_pmd_conf) != 0) {
- goto error;
- }
+ 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++) {
- if (rte_eth_rx_queue_setup(port_id, q_id, RX_RING_SIZE,
+ 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) < 0) {
- goto error;
- }
- }
+ 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++) {
- if (rte_eth_tx_queue_setup(port_id, q_id, TX_RING_SIZE,
- rte_eth_dev_socket_id(port_id), &tx_conf_default) < 0) {
- printf("Failed to setup tx queue (%d).\n", q_id);
- goto error;
- }
- }
+ 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) {
- if (rte_eth_dev_start(port_id) < 0) {
- printf("Failed to start device (%d).\n", port_id);
- goto error;
- }
- }
- return 0;
+ if (start)
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(port_id),
+ "rte_eth_dev_start for port %d failed", port_id);
-error:
- printf("Failed to configure ethdev %d\n", port_id);
- return -1;
+ 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)
{
@@ -310,7 +302,7 @@ test_setup(void)
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());
+ mac_addr, rte_socket_id(), 1);
if (test_params->slave_port_ids[i] < 0) {
printf("Failed to create virtual virtual ethdev %s\n", pmd_name);
return -1;
@@ -414,34 +406,27 @@ test_create_bonded_device_with_invalid_params(void)
static int
test_add_slave_to_bonded_device(void)
{
- int retval, current_slave_count;
+ int current_slave_count;
uint8_t slaves[RTE_MAX_ETHPORTS];
- retval = rte_eth_bond_slave_add(test_params->bonded_port_id,
- test_params->slave_port_ids[test_params->bonded_slave_count]);
- if (retval != 0) {
- printf("Failed to add slave (%d) to bonded port (%d).\n",
- test_params->bonded_port_id,
- test_params->slave_port_ids[test_params->bonded_slave_count]);
- return -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 (%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);
- if (current_slave_count != test_params->bonded_slave_count + 1) {
- printf("Number of slaves (%d) is greater than expected (%d).\n",
- current_slave_count, test_params->bonded_slave_count + 1);
- return -1;
- }
+ 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);
- if (current_slave_count != 0) {
- printf("Number of active slaves (%d) is not as expected (%d).\n",
- current_slave_count, 0);
- return -1;
- }
+ 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++;
@@ -476,27 +461,23 @@ test_add_slave_to_invalid_bonded_device(void)
static int
test_remove_slave_from_bonded_device(void)
{
- int retval, current_slave_count;
+ int current_slave_count;
struct ether_addr read_mac_addr, *mac_addr;
uint8_t slaves[RTE_MAX_ETHPORTS];
- retval = rte_eth_bond_slave_remove(test_params->bonded_port_id,
- test_params->slave_port_ids[test_params->bonded_slave_count-1]);
- if (retval != 0) {
- printf("\t Failed to remove slave %d from bonded port (%d).\n",
- test_params->slave_port_ids[test_params->bonded_slave_count-1],
- test_params->bonded_port_id);
- return -1;
- }
+ 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);
- if (current_slave_count != test_params->bonded_slave_count - 1) {
- printf("Number of slaves (%d) is great than expected (%d).\n",
- current_slave_count, 0);
- return -1;
- }
+
+ 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;
@@ -506,10 +487,8 @@ test_remove_slave_from_bonded_device(void)
rte_eth_macaddr_get(
test_params->slave_port_ids[test_params->bonded_slave_count-1],
&read_mac_addr);
- if (memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
- printf("bonded port mac address not set to that of primary port\n");
- return -1;
- }
+ 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]);
@@ -891,21 +870,20 @@ test_set_primary_slave(void)
return -1;
}
+ /* Non bonded device */
+ retval = rte_eth_bond_primary_set(test_params->slave_port_ids[i],
+ test_params->slave_port_ids[i]);
+ if (retval == 0) {
+ printf("Expected call to failed as invalid port specified.\n");
+ return -1;
+ }
+
/* 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++) {
-
- /* Non bonded device */
- retval = rte_eth_bond_primary_set(test_params->slave_port_ids[i],
- test_params->slave_port_ids[i]);
- if (retval == 0) {
- printf("Expected call to failed as invalid port specified.\n");
- return -1;
- }
-
retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
test_params->slave_port_ids[i]);
if (retval != 0) {
@@ -929,6 +907,7 @@ test_set_primary_slave(void)
/* stop/start bonded eth dev to apply new MAC */
rte_eth_dev_stop(test_params->bonded_port_id);
+
if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
return -1;
@@ -1093,19 +1072,18 @@ static int
initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t bond_en_isr,
uint8_t number_of_slaves, uint8_t enable_slave)
{
- /* configure bonded device */
+ /* 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);
- while (number_of_slaves > test_params->bonded_slave_count) {
- /* Add slaves to bonded device */
+ /* 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,
@@ -1128,9 +1106,9 @@ test_adding_slave_after_bonded_device_started(void)
{
int i;
- if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 0)
- != 0)
- return -1;
+ 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++) {
@@ -1138,12 +1116,9 @@ test_adding_slave_after_bonded_device_started(void)
test_params->slave_port_ids[i], 1);
}
- if (rte_eth_bond_slave_add(test_params->bonded_port_id,
- test_params->slave_port_ids[test_params->bonded_slave_count]) !=
- 0) {
- printf("\t Failed to add slave to bonded port.\n");
- return -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]);
@@ -1158,8 +1133,6 @@ test_adding_slave_after_bonded_device_started(void)
int test_lsc_interrupt_count;
-static pthread_mutex_t mutex;
-static pthread_cond_t cvar;
static void
test_bonding_lsc_event_callback(uint8_t port_id __rte_unused,
@@ -1183,7 +1156,7 @@ lsc_timeout(int wait_us)
gettimeofday(&tp, NULL);
/* Convert from timeval to timespec */
- ts.tv_sec = tp.tv_sec;
+ ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_nsec += wait_us * 1000;
@@ -1193,6 +1166,9 @@ lsc_timeout(int wait_us)
pthread_mutex_unlock(&mutex);
+ if (retval == 0 && test_lsc_interrupt_count < 1)
+ return -1;
+
return retval;
}
@@ -1202,9 +1178,6 @@ test_status_interrupt(void)
int slave_count;
uint8_t slaves[RTE_MAX_ETHPORTS];
- pthread_mutex_init(&mutex, NULL);
- pthread_cond_init(&cvar, NULL);
-
/* initialized bonding device with T slaves */
if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 1,
TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1) != 0)
@@ -1284,9 +1257,6 @@ test_status_interrupt(void)
RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
&test_params->bonded_port_id);
- pthread_mutex_destroy(&mutex);
- pthread_cond_destroy(&cvar);
-
/* Clean up and remove slaves from bonded device */
return remove_slaves_and_stop_bonded_device();
}
@@ -1419,6 +1389,7 @@ test_roundrobin_tx_burst(void)
return remove_slaves_and_stop_bonded_device();
}
+#ifdef RTE_MBUF_REFCNT
static int
verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
{
@@ -1432,6 +1403,7 @@ verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
}
return 0;
}
+#endif
static void
@@ -1537,11 +1509,12 @@ test_roundrobin_tx_burst_slave_tx_fail(void)
(unsigned int)port_stats.opackets, slave_expected_tx_count);
}
+#ifdef RTE_MBUF_REFCNT
/* Verify that all mbufs have a ref value of zero */
TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkt_burst[tx_count],
TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, 1),
"mbufs refcnts not as expected");
-
+#endif
free_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
/* Clean up and remove slaves from bonded device */
@@ -2028,6 +2001,101 @@ test_roundrobin_verify_slave_link_status_change_behaviour(void)
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 };
+
+#include "unistd.h"
+
+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
@@ -3160,10 +3228,12 @@ test_balance_tx_burst_slave_tx_fail(void)
(unsigned int)port_stats.opackets,
TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
+#ifdef RTE_MBUF_REFCNT
/* Verify that all mbufs have a ref value of zero */
TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst_1[tx_count_1],
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, 1),
"mbufs refcnts not as expected");
+#endif
free_mbufs(&pkts_burst_1[tx_count_1],
TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
@@ -4315,6 +4385,7 @@ static struct unit_test_suite link_bonding_test_suite = {
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),
diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index 81d4be3..e7be98b 100644
--- a/app/test/virtual_pmd.c
+++ b/app/test/virtual_pmd.c
@@ -456,6 +456,14 @@ virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id,
}
void
+virtual_ethdev_set_link_status(uint8_t port_id, uint8_t link_status)
+{
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+ vrtl_eth_dev->data->dev_link.link_status = link_status;
+}
+
+void
virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id,
uint8_t link_status)
{
@@ -503,7 +511,7 @@ get_number_of_sockets(void)
int
virtual_ethdev_create(const char *name, struct ether_addr *mac_addr,
- uint8_t socket_id)
+ uint8_t socket_id, uint8_t isr_support)
{
struct rte_pci_device *pci_dev = NULL;
struct rte_eth_dev *eth_dev = NULL;
@@ -553,7 +561,12 @@ virtual_ethdev_create(const char *name, struct ether_addr *mac_addr,
pci_dev->numa_node = socket_id;
pci_drv->name = virtual_ethdev_driver_name;
pci_drv->id_table = id_table;
- pci_drv->drv_flags = RTE_PCI_DRV_INTR_LSC;
+
+ if (isr_support)
+ pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC;
+ else
+ pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
+
eth_drv->pci_drv = (struct rte_pci_driver)(*pci_drv);
eth_dev->driver = eth_drv;
diff --git a/app/test/virtual_pmd.h b/app/test/virtual_pmd.h
index 3b5c911..2462853 100644
--- a/app/test/virtual_pmd.h
+++ b/app/test/virtual_pmd.h
@@ -40,38 +40,58 @@ extern "C" {
#include <rte_ether.h>
-int virtual_ethdev_init(void);
+int
+virtual_ethdev_init(void);
-int virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, uint8_t socket_id);
+int
+virtual_ethdev_create(const char *name, struct ether_addr *mac_addr,
+ uint8_t socket_id, uint8_t isr_support);
-void virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id, uint8_t link_status);
+void
+virtual_ethdev_set_link_status(uint8_t port_id, uint8_t link_status);
-void virtual_ethdev_add_mbufs_to_rx_queue(uint8_t port_id, struct rte_mbuf **pkts_burst, int burst_length);
+void
+virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id,
+ uint8_t link_status);
+void
+virtual_ethdev_add_mbufs_to_rx_queue(uint8_t port_id,
+ struct rte_mbuf **pkts_burst, int burst_length);
-/** Control methods for the dev_ops functions pointer to control the behavior of the Virtual PMD */
-void virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success);
+/** Control methods for the dev_ops functions pointer to control the behavior
+ * of the Virtual PMD */
-void virtual_ethdev_stop_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success);
-void virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_stop_fn_set_success(uint8_t port_id, uint8_t success);
-void virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success);
-void virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success);
-void virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success);
-void virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success);
-void virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success);
+void
+virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success);
+
+void
+virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success);
/* if a value greater than zero is set for packet_fail_count then virtual
* device tx burst function will fail that many packet from burst or all
* packets if packet_fail_count is greater than the number of packets in the
* burst */
-void virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id,
+void
+virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id,
uint8_t packet_fail_count);
#ifdef __cplusplus
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index c0d0033..93fd3d4 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1479,6 +1479,25 @@ For example, set a Link Bonding device (port 10) to use a balance policy of laye
testpmd> set bonding xmit_balance_policy 10 l34
+
+set bonding mon_period
+~~~~~~~~~~~~~~~~~~~~~~
+
+Set the link status monitoring polling period in milliseconds for a bonding devicie.
+
+This adds support for PMD slave devices which do not support link status interrupts.
+When the mon_period is set to a value greater than 0 then all PMD's which do not support
+link status ISR will be queried every polling interval to check if their link status has changed.
+
+set bonding mon_period (port_id) (value)
+
+For example, to set the link status monitoring polling period of bonded device (port 5) to 150ms
+
+.. code-block:: console
+
+ testpmd> set bonding mon_period 5 150
+
+
show bonding config
~~~~~~~~~~~~~~~~~~~
diff --git a/lib/librte_pmd_bond/rte_eth_bond.h b/lib/librte_pmd_bond/rte_eth_bond.h
index 344ca1e..2ed4f7c 100644
--- a/lib/librte_pmd_bond/rte_eth_bond.h
+++ b/lib/librte_pmd_bond/rte_eth_bond.h
@@ -249,6 +249,86 @@ rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy);
int
rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id);
+/**
+ * Set the link monitoring frequency (in ms) for monitoring the link status of
+ * slave devices
+ *
+ * @param bonded_port_id Port ID of bonded device.
+ * @param internal_ms Monitoring interval in milliseconds
+ *
+ * @return
+ * 0 on success, negative value otherwise.
+ */
+
+int
+rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms);
+
+/**
+ * Get the current link monitoring frequency (in ms) for monitoring of the link
+ * status of slave devices
+ *
+ * @param bonded_port_id Port ID of bonded device.
+ *
+ * @return
+ * Monitoring interval on success, negative value otherwise.
+ */
+int
+rte_eth_bond_link_monitoring_get(uint8_t bonded_port_id);
+
+
+/**
+ * Set the period in milliseconds for delaying the disabling of a bonded link
+ * when the link down status has been detected
+ *
+ * @param bonded_port_id Port ID of bonded device.
+ * @param delay_ms Delay period in milliseconds.
+ *
+ * @return
+ * 0 on success, negative value otherwise.
+ */
+int
+rte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms);
+
+/**
+ * Get the period in milliseconds set for delaying the disabling of a bonded
+ * link when the link down status has been detected
+ *
+ * @param bonded_port_id Port ID of bonded device.
+ * @param delay_ms Delay period in milliseconds.
+ *
+ * @return
+ * Delay period on success, negative value otherwise.
+ */
+int
+rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id);
+
+/**
+ * Set the period in milliseconds for delaying the enabling of a bonded link
+ * when the link up status has been detected
+ *
+ * @param bonded_port_id Port ID of bonded device.
+ * @param delay_ms Delay period in milliseconds.
+ *
+ * @return
+ * 0 on success, negative value otherwise.
+ */
+int
+rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms);
+
+/**
+ * Get the period in milliseconds set for delaying the enabling of a bonded
+ * link when the link up status has been detected
+ *
+ * @param bonded_port_id Port ID of bonded device.
+ * @param delay_ms Delay period in milliseconds.
+ *
+ * @return
+ * Delay period on success, negative value otherwise.
+ */
+int
+rte_eth_bond_link_up_prop_delay_get(uint8_t bonded_port_id);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/librte_pmd_bond/rte_eth_bond_api.c b/lib/librte_pmd_bond/rte_eth_bond_api.c
index dd33119..f146bda 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_api.c
+++ b/lib/librte_pmd_bond/rte_eth_bond_api.c
@@ -39,6 +39,8 @@
#include "rte_eth_bond.h"
#include "rte_eth_bond_private.h"
+#define DEFAULT_POLLING_INTERVAL_10_MS (10)
+
int
valid_bonded_ethdev(struct rte_eth_dev *eth_dev)
{
@@ -63,9 +65,8 @@ valid_port_id(uint8_t port_id)
/* Verify that port id is valid */
int ethdev_count = rte_eth_dev_count();
if (port_id >= ethdev_count) {
- RTE_LOG(ERR, PMD,
- "%s: port Id %d is greater than rte_eth_dev_count %d\n",
- __func__, port_id, ethdev_count);
+ RTE_BOND_LOG(ERR, "Port Id %d is greater than rte_eth_dev_count %d",
+ port_id, ethdev_count);
return -1;
}
@@ -81,9 +82,8 @@ valid_bonded_port_id(uint8_t port_id)
/* Verify that bonded_port_id refers to a bonded port */
if (valid_bonded_ethdev(&rte_eth_devices[port_id])) {
- RTE_LOG(ERR, PMD,
- "%s: Specified port Id %d is not a bonded eth_dev device\n",
- __func__, port_id);
+ RTE_BOND_LOG(ERR, "Specified port Id %d is not a bonded eth_dev device",
+ port_id);
return -1;
}
@@ -136,37 +136,36 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
*/
if (name == NULL) {
- RTE_LOG(ERR, PMD, "Invalid name specified\n");
+ RTE_BOND_LOG(ERR, "Invalid name specified");
goto err;
}
if (socket_id >= number_of_sockets()) {
- RTE_LOG(ERR, PMD,
- "%s: invalid socket id specified to create bonded device on.\n",
- __func__);
+ RTE_BOND_LOG(ERR,
+ "Invalid socket id specified to create bonded device on.");
goto err;
}
pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id);
if (pci_dev == NULL) {
- RTE_LOG(ERR, PMD, "Unable to malloc pci dev on socket\n");
+ RTE_BOND_LOG(ERR, "Unable to malloc pci dev on socket");
goto err;
}
eth_drv = rte_zmalloc_socket(name, sizeof(*eth_drv), 0, socket_id);
if (eth_drv == NULL) {
- RTE_LOG(ERR, PMD, "Unable to malloc eth_drv on socket\n");
+ RTE_BOND_LOG(ERR, "Unable to malloc eth_drv on socket");
goto err;
}
pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id);
if (pci_drv == NULL) {
- RTE_LOG(ERR, PMD, "Unable to malloc pci_drv on socket\n");
+ RTE_BOND_LOG(ERR, "Unable to malloc pci_drv on socket");
goto err;
}
pci_id_table = rte_zmalloc_socket(name, sizeof(*pci_id_table), 0, socket_id);
if (pci_drv == NULL) {
- RTE_LOG(ERR, PMD, "Unable to malloc pci_id_table on socket\n");
+ RTE_BOND_LOG(ERR, "Unable to malloc pci_id_table on socket");
goto err;
}
@@ -181,14 +180,14 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id);
if (internals == NULL) {
- RTE_LOG(ERR, PMD, "Unable to malloc internals on socket\n");
+ RTE_BOND_LOG(ERR, "Unable to malloc internals on socket");
goto err;
}
/* reserve an ethdev entry */
eth_dev = rte_eth_dev_allocate(name);
if (eth_dev == NULL) {
- RTE_LOG(ERR, PMD, "Unable to allocate rte_eth_dev\n");
+ RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev");
goto err;
}
@@ -218,25 +217,31 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
eth_dev->pci_dev = pci_dev;
if (bond_ethdev_mode_set(eth_dev, mode)) {
- RTE_LOG(ERR, PMD,
- "%s: failed to set bonded device %d mode too %d\n",
- __func__, eth_dev->data->port_id, mode);
+ RTE_BOND_LOG(ERR, "Failed to set bonded device %d mode too %d",
+ eth_dev->data->port_id, mode);
goto err;
}
+ rte_spinlock_init(&internals->lock);
+
+ internals->port_id = eth_dev->data->port_id;
internals->current_primary_port = 0;
internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
internals->user_defined_mac = 0;
internals->link_props_set = 0;
+
+ internals->link_status_polling_enabled = 0;
+
+ internals->link_status_polling_interval_ms = DEFAULT_POLLING_INTERVAL_10_MS;
+ internals->link_down_delay_ms = 0;
+ internals->link_up_delay_ms = 0;
+
internals->slave_count = 0;
internals->active_slave_count = 0;
memset(internals->active_slaves, 0, sizeof(internals->active_slaves));
memset(internals->slaves, 0, sizeof(internals->slaves));
- memset(internals->presisted_slaves_conf, 0,
- sizeof(internals->presisted_slaves_conf));
-
return eth_dev->data->port_id;
err:
@@ -253,8 +258,8 @@ err:
return -1;
}
-int
-rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
+static int
+__eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
{
struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
struct bond_dev_private *internals;
@@ -263,56 +268,43 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
int i, j;
- /* Verify that port id's are valid bonded and slave ports */
- if (valid_bonded_port_id(bonded_port_id) != 0)
- goto err_add;
-
if (valid_slave_port_id(slave_port_id) != 0)
- goto err_add;
+ return -1;
+
+ bonded_eth_dev = &rte_eth_devices[bonded_port_id];
+ internals = bonded_eth_dev->data->dev_private;
- /*
- * Verify that new slave device is not already a slave of another bonded
- * device */
+ /* Verify that new slave device is not already a slave of another
+ * bonded device */
for (i = rte_eth_dev_count()-1; i >= 0; i--) {
if (valid_bonded_ethdev(&rte_eth_devices[i]) == 0) {
temp_internals = rte_eth_devices[i].data->dev_private;
+
for (j = 0; j < temp_internals->slave_count; j++) {
/* Device already a slave of a bonded device */
- if (temp_internals->slaves[j] == slave_port_id)
- goto err_add;
+ if (temp_internals->slaves[j].port_id == slave_port_id) {
+ RTE_BOND_LOG(ERR, "Slave port %d is already a slave",
+ slave_port_id);
+ return -1;
+ }
}
}
}
- bonded_eth_dev = &rte_eth_devices[bonded_port_id];
- internals = bonded_eth_dev->data->dev_private;
-
slave_eth_dev = &rte_eth_devices[slave_port_id];
- if (internals->slave_count > 0) {
- /* Check that new slave device is the same type as the other slaves
- * and not repetitive */
- for (i = 0; i < internals->slave_count; i++) {
- if (slave_eth_dev->pci_dev->driver->id_table->device_id !=
- rte_eth_devices[internals->slaves[i]].pci_dev->driver->id_table->device_id ||
- internals->slaves[i] == slave_port_id)
- goto err_add;
- }
- }
-
/* Add slave details to bonded device */
- internals->slaves[internals->slave_count] = slave_port_id;
-
- slave_config_store(internals, slave_eth_dev);
+ slave_add(internals, slave_eth_dev);
if (internals->slave_count < 1) {
- /* if MAC is not user defined then use MAC of first slave add to bonded
- * device */
+ /* if MAC is not user defined then use MAC of first slave add to
+ * bonded device */
if (!internals->user_defined_mac)
mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs);
/* Inherit eth dev link properties from first slave */
- link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link));
+ link_properties_set(bonded_eth_dev,
+ &(slave_eth_dev->data->dev_link));
/* Make primary slave */
internals->primary_port = slave_port_id;
@@ -322,10 +314,10 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
if (internals->link_props_set) {
if (link_properties_valid(&(bonded_eth_dev->data->dev_link),
&(slave_eth_dev->data->dev_link))) {
- RTE_LOG(ERR, PMD,
- "%s: Slave port %d link speed/duplex not supported\n",
- __func__, slave_port_id);
- goto err_add;
+ RTE_BOND_LOG(ERR,
+ "Slave port %d link speed/duplex not supported",
+ slave_port_id);
+ return -1;
}
} else {
link_properties_set(bonded_eth_dev,
@@ -340,9 +332,9 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
if (bonded_eth_dev->data->dev_started) {
if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) {
- RTE_LOG(ERR, PMD, "rte_bond_slaves_configure: port=%d\n",
+ RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d",
slave_port_id);
- goto err_add;
+ return -1;
}
}
@@ -356,65 +348,79 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
if (bonded_eth_dev->data->dev_started) {
rte_eth_link_get_nowait(slave_port_id, &link_props);
- if (link_props.link_status == 1) {
+ if (link_props.link_status == 1)
internals->active_slaves[internals->active_slave_count++] =
slave_port_id;
- }
}
-
return 0;
-err_add:
- RTE_LOG(ERR, PMD, "Failed to add port %d as slave\n", slave_port_id);
- return -1;
-
}
+
int
-rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
+rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
{
+ struct rte_eth_dev *bonded_eth_dev;
struct bond_dev_private *internals;
- struct slave_conf *slave_conf;
- int i;
- int pos = -1;
+ int retval;
/* Verify that port id's are valid bonded and slave ports */
if (valid_bonded_port_id(bonded_port_id) != 0)
- goto err_del;
+ return -1;
+
+ bonded_eth_dev = &rte_eth_devices[bonded_port_id];
+ internals = bonded_eth_dev->data->dev_private;
+
+ rte_spinlock_lock(&internals->lock);
+
+ retval = __eth_bond_slave_add_lock_free(bonded_port_id, slave_port_id);
+
+ rte_spinlock_unlock(&internals->lock);
+
+ return retval;
+}
+
+
+static int
+__eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
+{
+ struct bond_dev_private *internals;
+
+ int i, slave_idx = -1;
if (valid_slave_port_id(slave_port_id) != 0)
- goto err_del;
+ return -1;
internals = rte_eth_devices[bonded_port_id].data->dev_private;
/* first remove from active slave list */
for (i = 0; i < internals->active_slave_count; i++) {
if (internals->active_slaves[i] == slave_port_id)
- pos = i;
+ slave_idx = i;
/* shift active slaves up active array list */
- if (pos >= 0 && i < (internals->active_slave_count - 1))
+ if (slave_idx >= 0 && i < (internals->active_slave_count - 1))
internals->active_slaves[i] = internals->active_slaves[i+1];
}
- if (pos >= 0)
+ if (slave_idx >= 0)
internals->active_slave_count--;
- pos = -1;
- /* now remove from slave list */
- for (i = 0; i < internals->slave_count; i++) {
- if (internals->slaves[i] == slave_port_id)
- pos = i;
+ slave_idx = -1;
+ /* now find in slave list */
+ for (i = 0; i < internals->slave_count; i++)
+ if (internals->slaves[i].port_id == slave_port_id) {
+ slave_idx = i;
+ break;
+ }
- /* shift slaves up list */
- if (pos >= 0 && i < internals->slave_count)
- internals->slaves[i] = internals->slaves[i+1];
+ if (slave_idx < 0) {
+ RTE_BOND_LOG(ERR, "Couldn't find slave in port list, slave count %d",
+ internals->slave_count);
+ return -1;
}
- if (pos < 0)
- goto err_del;
-
/* Un-register link status change callback with bonded device pointer as
* argument*/
rte_eth_dev_callback_unregister(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
@@ -422,13 +428,10 @@ rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
&rte_eth_devices[bonded_port_id].data->port_id);
/* Restore original MAC address of slave device */
- slave_conf = slave_config_get(internals, slave_port_id);
+ mac_address_set(&rte_eth_devices[slave_port_id],
+ &(internals->slaves[slave_idx].persisted_mac_addr));
- mac_address_set(&rte_eth_devices[slave_port_id], &(slave_conf->mac_addr));
-
- slave_config_clear(internals, &rte_eth_devices[slave_port_id]);
-
- internals->slave_count--;
+ slave_remove(internals, &rte_eth_devices[slave_port_id]);
/* first slave in the active list will be the primary by default,
* otherwise use first device in list */
@@ -436,7 +439,7 @@ rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
if (internals->active_slave_count > 0)
internals->current_primary_port = internals->active_slaves[0];
else if (internals->slave_count > 0)
- internals->current_primary_port = internals->slaves[0];
+ internals->current_primary_port = internals->slaves[0].port_id;
else
internals->primary_port = 0;
}
@@ -454,12 +457,28 @@ rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
}
return 0;
+}
-err_del:
- RTE_LOG(ERR, PMD,
- "Cannot remove slave device (not present in bonded device)\n");
- return -1;
+int
+rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
+{
+ struct rte_eth_dev *bonded_eth_dev;
+ struct bond_dev_private *internals;
+ int retval;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ bonded_eth_dev = &rte_eth_devices[bonded_port_id];
+ internals = bonded_eth_dev->data->dev_private;
+
+ rte_spinlock_lock(&internals->lock);
+
+ retval = __eth_bond_slave_remove_lock_free(bonded_port_id, slave_port_id);
+
+ rte_spinlock_unlock(&internals->lock);
+ return retval;
}
int
@@ -524,6 +543,7 @@ int
rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len)
{
struct bond_dev_private *internals;
+ int i;
if (valid_bonded_port_id(bonded_port_id) != 0)
return -1;
@@ -536,10 +556,10 @@ rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len)
if (internals->slave_count > len)
return -1;
- memcpy(slaves, internals->slaves, internals->slave_count);
+ for (i = 0; i < internals->slave_count; i++)
+ slaves[i] = internals->slaves[i].port_id;
return internals->slave_count;
-
}
int
@@ -605,13 +625,13 @@ rte_eth_bond_mac_address_reset(uint8_t bonded_port_id)
internals->user_defined_mac = 0;
if (internals->slave_count > 0) {
- struct slave_conf *conf;
- conf = slave_config_get(internals, internals->primary_port);
-
/* Set MAC Address of Bonded Device */
- if (mac_address_set(bonded_eth_dev, &conf->mac_addr) != 0)
+ if (mac_address_set(bonded_eth_dev,
+ &internals->slaves[internals->primary_port].persisted_mac_addr)
+ != 0) {
+ RTE_BOND_LOG(ERR, "Failed to set MAC address on bonded device");
return -1;
-
+ }
/* Update all slave devices MAC addresses */
return mac_address_slaves_update(bonded_eth_dev);
}
@@ -654,3 +674,88 @@ rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id)
return internals->balance_xmit_policy;
}
+
+
+int
+rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms)
+{
+ struct bond_dev_private *internals;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ internals = rte_eth_devices[bonded_port_id].data->dev_private;
+ internals->link_status_polling_interval_ms = internal_ms;
+
+ return 0;
+}
+
+int
+rte_eth_bond_link_monitoring_get(uint8_t bonded_port_id)
+{
+ struct bond_dev_private *internals;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ internals = rte_eth_devices[bonded_port_id].data->dev_private;
+
+ return internals->link_status_polling_interval_ms;
+}
+
+int
+rte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms)
+
+{
+ struct bond_dev_private *internals;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ internals = rte_eth_devices[bonded_port_id].data->dev_private;
+ internals->link_down_delay_ms = delay_ms;
+
+ return 0;
+}
+
+int
+rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id)
+{
+ struct bond_dev_private *internals;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ internals = rte_eth_devices[bonded_port_id].data->dev_private;
+
+ return internals->link_down_delay_ms;
+}
+
+
+int
+rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms)
+
+{
+ struct bond_dev_private *internals;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ internals = rte_eth_devices[bonded_port_id].data->dev_private;
+ internals->link_up_delay_ms = delay_ms;
+
+ return 0;
+}
+
+int
+rte_eth_bond_link_up_prop_delay_get(uint8_t bonded_port_id)
+{
+ struct bond_dev_private *internals;
+
+ if (valid_bonded_port_id(bonded_port_id) != 0)
+ return -1;
+
+ internals = rte_eth_devices[bonded_port_id].data->dev_private;
+
+ return internals->link_up_delay_ms;
+}
diff --git a/lib/librte_pmd_bond/rte_eth_bond_args.c b/lib/librte_pmd_bond/rte_eth_bond_args.c
index 05a2b07..d8ce681 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_args.c
+++ b/lib/librte_pmd_bond/rte_eth_bond_args.c
@@ -118,7 +118,7 @@ parse_port_id(const char *port_str)
}
if (port_id < 0 || port_id > RTE_MAX_ETHPORTS) {
- RTE_LOG(ERR, PMD, "Invalid slave port value (%s) specified.\n",
+ RTE_BOND_LOG(ERR, "Slave port specified (%s) outside expected range",
port_str);
return -1;
}
@@ -138,9 +138,10 @@ bond_ethdev_parse_slave_port_kvarg(const char *key __rte_unused,
if (strcmp(key, PMD_BOND_SLAVE_PORT_KVARG) == 0) {
int port_id = parse_port_id(value);
- if (port_id < 0)
+ if (port_id < 0) {
+ RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified", value);
return -1;
- else
+ } else
slave_ports->slaves[slave_ports->slave_count++] =
(uint8_t)port_id;
}
@@ -174,6 +175,7 @@ bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused,
#endif
return 0;
default:
+ RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified", value);
return -1;
}
}
@@ -252,3 +254,23 @@ bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused,
/* Parse MAC */
return cmdline_parse_etheraddr(NULL, value, extra_args);
}
+
+int
+bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused,
+ const char *value, void *extra_args)
+{
+ uint32_t time_ms;
+ char *endptr;
+
+ if (value == NULL || extra_args == NULL)
+ return -1;
+
+ errno = 0;
+ time_ms = (uint32_t)strtol(value, &endptr, 10);
+ if (*endptr != 0 || errno != 0)
+ return -1;
+
+ *(uint32_t *)extra_args = time_ms;
+
+ return 0;
+}
diff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
index 2a86402..cf2fbab 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c
+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
@@ -40,6 +40,7 @@
#include <rte_devargs.h>
#include <rte_kvargs.h>
#include <rte_dev.h>
+#include <rte_alarm.h>
#include "rte_eth_bond.h"
#include "rte_eth_bond_private.h"
@@ -457,16 +458,16 @@ mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr)
mac_addr = eth_dev->data->mac_addrs;
if (eth_dev == NULL) {
- RTE_LOG(ERR, PMD, "%s: NULL pointer eth_dev specified\n", __func__);
+ RTE_BOND_LOG(ERR, "NULL pointer eth_dev specified");
return -1;
}
if (new_mac_addr == NULL) {
- RTE_LOG(ERR, PMD, "%s: NULL pointer MAC specified\n", __func__);
+ RTE_BOND_LOG(ERR, "NULL pointer MAC specified");
return -1;
}
- /* if new MAC is different to current MAC then update */
+ /* If new MAC is different to current MAC then update */
if (memcmp(mac_addr, new_mac_addr, sizeof(*mac_addr)) != 0)
memcpy(mac_addr, new_mac_addr, sizeof(*mac_addr));
@@ -490,11 +491,10 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
case BONDING_MODE_BROADCAST:
#endif
for (i = 0; i < internals->slave_count; i++) {
- if (mac_address_set(&rte_eth_devices[internals->slaves[i]],
+ if (mac_address_set(&rte_eth_devices[internals->slaves[i].port_id],
bonded_eth_dev->data->mac_addrs)) {
- RTE_LOG(ERR, PMD,
- "%s: Failed to update port Id %d MAC address\n",
- __func__, internals->slaves[i]);
+ RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
+ internals->slaves[i].port_id);
return -1;
}
}
@@ -502,23 +502,20 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
case BONDING_MODE_ACTIVE_BACKUP:
default:
for (i = 0; i < internals->slave_count; i++) {
- if (internals->slaves[i] == internals->current_primary_port) {
+ if (internals->slaves[i].port_id ==
+ internals->current_primary_port) {
if (mac_address_set(&rte_eth_devices[internals->primary_port],
bonded_eth_dev->data->mac_addrs)) {
- RTE_LOG(ERR, PMD,
- "%s: Failed to update port Id %d MAC address\n",
- __func__, internals->current_primary_port);
+ RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
+ internals->current_primary_port);
+ return -1;
}
} else {
- struct slave_conf *conf =
- slave_config_get(internals, internals->slaves[i]);
-
- if (mac_address_set(&rte_eth_devices[internals->slaves[i]],
- &conf->mac_addr)) {
- RTE_LOG(ERR, PMD,
- "%s: Failed to update port Id %d MAC address\n",
- __func__, internals->slaves[i]);
-
+ if (mac_address_set(
+ &rte_eth_devices[internals->slaves[i].port_id],
+ &internals->slaves[i].persisted_mac_addr)) {
+ RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
+ internals->slaves[i].port_id);
return -1;
}
}
@@ -570,34 +567,39 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
struct bond_rx_queue *bd_rx_q;
struct bond_tx_queue *bd_tx_q;
- int q_id;
+ int errval, q_id;
/* Stop slave */
rte_eth_dev_stop(slave_eth_dev->data->port_id);
- /* Enable interrupts on slave device */
- slave_eth_dev->data->dev_conf.intr_conf.lsc = 1;
+ /* Enable interrupts on slave device if supported */
+ if (slave_eth_dev->driver->pci_drv.drv_flags & RTE_PCI_DRV_INTR_LSC)
+ slave_eth_dev->data->dev_conf.intr_conf.lsc = 1;
- if (rte_eth_dev_configure(slave_eth_dev->data->port_id,
+ /* Configure device */
+ errval = rte_eth_dev_configure(slave_eth_dev->data->port_id,
bonded_eth_dev->data->nb_rx_queues,
bonded_eth_dev->data->nb_tx_queues,
- &(slave_eth_dev->data->dev_conf)) != 0) {
- RTE_LOG(ERR, PMD, "Cannot configure slave device: port=%u\n",
- slave_eth_dev->data->port_id);
- return -1;
+ &(slave_eth_dev->data->dev_conf));
+ if (errval != 0) {
+ RTE_BOND_LOG(ERR, "Cannot configure slave device: port %u , err (%d)",
+ slave_eth_dev->data->port_id, errval);
+ return errval;
}
/* Setup Rx Queues */
for (q_id = 0; q_id < bonded_eth_dev->data->nb_rx_queues; q_id++) {
bd_rx_q = (struct bond_rx_queue *)bonded_eth_dev->data->rx_queues[q_id];
- if (rte_eth_rx_queue_setup(slave_eth_dev->data->port_id, q_id,
+ errval = rte_eth_rx_queue_setup(slave_eth_dev->data->port_id, q_id,
bd_rx_q->nb_rx_desc,
rte_eth_dev_socket_id(slave_eth_dev->data->port_id),
- &(bd_rx_q->rx_conf), bd_rx_q->mb_pool) != 0) {
- RTE_LOG(ERR, PMD, "rte_eth_rx_queue_setup: port=%d queue_id %d\n",
- slave_eth_dev->data->port_id, q_id);
- return -1;
+ &(bd_rx_q->rx_conf), bd_rx_q->mb_pool);
+ if (errval != 0) {
+ RTE_BOND_LOG(ERR,
+ "rte_eth_rx_queue_setup: port=%d queue_id %d, err (%d)",
+ slave_eth_dev->data->port_id, q_id, errval);
+ return errval;
}
}
@@ -605,69 +607,77 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
for (q_id = 0; q_id < bonded_eth_dev->data->nb_tx_queues; q_id++) {
bd_tx_q = (struct bond_tx_queue *)bonded_eth_dev->data->tx_queues[q_id];
- if (rte_eth_tx_queue_setup(slave_eth_dev->data->port_id, q_id,
+ errval = rte_eth_tx_queue_setup(slave_eth_dev->data->port_id, q_id,
bd_tx_q->nb_tx_desc,
rte_eth_dev_socket_id(slave_eth_dev->data->port_id),
- &bd_tx_q->tx_conf) != 0) {
- RTE_LOG(ERR, PMD, "rte_eth_tx_queue_setup: port=%d queue_id %d\n",
- slave_eth_dev->data->port_id, q_id);
- return -1;
+ &bd_tx_q->tx_conf);
+ if (errval != 0) {
+ RTE_BOND_LOG(ERR,
+ "rte_eth_tx_queue_setup: port=%d queue_id %d, err (%d)",
+ slave_eth_dev->data->port_id, q_id, errval);
+ return errval;
}
}
/* Start device */
- if (rte_eth_dev_start(slave_eth_dev->data->port_id) != 0) {
- RTE_LOG(ERR, PMD, "rte_eth_dev_start: port=%u\n",
- slave_eth_dev->data->port_id);
+ errval = rte_eth_dev_start(slave_eth_dev->data->port_id);
+ if (errval != 0) {
+ RTE_BOND_LOG(ERR, "rte_eth_dev_start: port=%u, err (%d)",
+ slave_eth_dev->data->port_id, errval);
return -1;
}
return 0;
}
-struct slave_conf *
-slave_config_get(struct bond_dev_private *internals, uint8_t slave_port_id)
-{
- int i;
-
- for (i = 0; i < internals->slave_count; i++) {
- if (internals->presisted_slaves_conf[i].port_id == slave_port_id)
- return &internals->presisted_slaves_conf[i];
- }
- return NULL;
-}
-
void
-slave_config_clear(struct bond_dev_private *internals,
+slave_remove(struct bond_dev_private *internals,
struct rte_eth_dev *slave_eth_dev)
{
int i, found = 0;
for (i = 0; i < internals->slave_count; i++) {
- if (internals->presisted_slaves_conf[i].port_id ==
- slave_eth_dev->data->port_id) {
+ if (internals->slaves[i].port_id == slave_eth_dev->data->port_id)
found = 1;
- memset(&internals->presisted_slaves_conf[i], 0,
- sizeof(internals->presisted_slaves_conf[i]));
- }
- if (found && i < (internals->slave_count - 1)) {
- memcpy(&internals->presisted_slaves_conf[i],
- &internals->presisted_slaves_conf[i+1],
- sizeof(internals->presisted_slaves_conf[i]));
- }
+
+ if (found && i < (internals->slave_count - 1))
+ memcpy(&internals->slaves[i], &internals->slaves[i+1],
+ sizeof(internals->slaves[i]));
}
+
+ internals->slave_count--;
}
+static void
+bond_ethdev_slave_link_status_change_monitor(void *cb_arg);
+
void
-slave_config_store(struct bond_dev_private *internals,
+slave_add(struct bond_dev_private *internals,
struct rte_eth_dev *slave_eth_dev)
{
- struct slave_conf *presisted_slave_conf =
- &internals->presisted_slaves_conf[internals->slave_count];
+ struct bond_slave_details *slave_details =
+ &internals->slaves[internals->slave_count];
+
+ slave_details->port_id = slave_eth_dev->data->port_id;
+ slave_details->last_link_status = 0;
+
+ /* If slave device doesn't support interrupts then we need to enabled
+ * polling to monitor link status */
+ if (!(slave_eth_dev->pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) {
+ slave_details->link_status_poll_enabled = 1;
+
+ if (!internals->link_status_polling_enabled) {
+ internals->link_status_polling_enabled = 1;
- presisted_slave_conf->port_id = slave_eth_dev->data->port_id;
+ rte_eal_alarm_set(internals->link_status_polling_interval_ms * 1000,
+ bond_ethdev_slave_link_status_change_monitor,
+ (void *)&rte_eth_devices[internals->port_id]);
+ }
+ }
- memcpy(&(presisted_slave_conf->mac_addr), slave_eth_dev->data->mac_addrs,
+ slave_details->link_status_wait_to_complete = 0;
+
+ memcpy(&(slave_details->persisted_mac_addr), slave_eth_dev->data->mac_addrs,
sizeof(struct ether_addr));
}
@@ -698,31 +708,33 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
/* slave eth dev will be started by bonded device */
if (valid_bonded_ethdev(eth_dev)) {
- RTE_LOG(ERR, PMD,
- "%s: user tried to explicitly start a slave eth_dev (%d) of the bonded eth_dev\n",
- __func__, eth_dev->data->port_id);
+ RTE_BOND_LOG(ERR, "User tried to explicitly start a slave eth_dev (%d)",
+ eth_dev->data->port_id);
return -1;
}
- eth_dev->data->dev_link.link_status = 1;
+ eth_dev->data->dev_link.link_status = 0;
eth_dev->data->dev_started = 1;
internals = eth_dev->data->dev_private;
if (internals->slave_count == 0) {
- RTE_LOG(ERR, PMD,
- "%s: Cannot start port since there are no slave devices\n",
- __func__);
+ RTE_BOND_LOG(ERR, "Cannot start port since there are no slave devices");
return -1;
}
if (internals->user_defined_mac == 0) {
- struct slave_conf *conf = slave_config_get(internals,
- internals->primary_port);
+ struct ether_addr *new_mac_addr = NULL;
+
+ for (i = 0; i < internals->slave_count; i++)
+ if (internals->slaves[i].port_id == internals->primary_port)
+ new_mac_addr = &internals->slaves[i].persisted_mac_addr;
+
+ if (new_mac_addr == NULL)
+ return -1;
- if (mac_address_set(eth_dev, &(conf->mac_addr)) != 0) {
- RTE_LOG(ERR, PMD,
- "bonded port (%d) failed to update mac address",
+ if (mac_address_set(eth_dev, new_mac_addr) != 0) {
+ RTE_BOND_LOG(ERR, "bonded port (%d) failed to update MAC address",
eth_dev->data->port_id);
return -1;
}
@@ -738,11 +750,11 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
/* Reconfigure each slave device if starting bonded device */
for (i = 0; i < internals->slave_count; i++) {
- if (slave_configure(eth_dev, &(rte_eth_devices[internals->slaves[i]]))
- != 0) {
- RTE_LOG(ERR, PMD, "bonded port "
- "(%d) failed to reconfigure slave device (%d)\n)",
- eth_dev->data->port_id, internals->slaves[i]);
+ if (slave_configure(eth_dev,
+ &(rte_eth_devices[internals->slaves[i].port_id])) != 0) {
+ RTE_BOND_LOG(ERR,
+ "bonded port (%d) failed to reconfigure slave device (%d)",
+ eth_dev->data->port_id, internals->slaves[i].port_id);
return -1;
}
}
@@ -759,6 +771,7 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)
struct bond_dev_private *internals = eth_dev->data->dev_private;
internals->active_slave_count = 0;
+ internals->link_status_polling_enabled = 0;
eth_dev->data->dev_link.link_status = 0;
eth_dev->data->dev_started = 0;
@@ -852,6 +865,65 @@ bond_ethdev_tx_queue_release(void *queue)
rte_free(queue);
}
+
+static void
+bond_ethdev_slave_link_status_change_monitor(void *cb_arg)
+{
+ struct rte_eth_dev *bonded_ethdev, *slave_ethdev;
+ struct bond_dev_private *internals;
+
+ /* Default value for polling slave found is true as we don't want to
+ * disable the polling thread if we cannot get the lock */
+ int i, polling_slave_found = 1;
+
+ if (cb_arg == NULL)
+ return;
+
+ bonded_ethdev = (struct rte_eth_dev *)cb_arg;
+ internals = (struct bond_dev_private *)bonded_ethdev->data->dev_private;
+
+ if (!bonded_ethdev->data->dev_started ||
+ !internals->link_status_polling_enabled)
+ return;
+
+ /* If device is currently being configured then don't check slaves link
+ * status, wait until next period */
+ if (rte_spinlock_trylock(&internals->lock)) {
+ if (internals->slave_count > 0)
+ polling_slave_found = 0;
+
+ for (i = 0; i < internals->slave_count; i++) {
+ if (!internals->slaves[i].link_status_poll_enabled)
+ continue;
+
+ slave_ethdev = &rte_eth_devices[internals->slaves[i].port_id];
+ polling_slave_found = 1;
+
+ /* Update slave link status */
+ (*slave_ethdev->dev_ops->link_update)(slave_ethdev,
+ internals->slaves[i].link_status_wait_to_complete);
+
+ /* if link status has changed since last checked then call lsc
+ * event callback */
+ if (slave_ethdev->data->dev_link.link_status !=
+ internals->slaves[i].last_link_status) {
+ internals->slaves[i].last_link_status =
+ slave_ethdev->data->dev_link.link_status;
+
+ bond_ethdev_lsc_event_callback(internals->slaves[i].port_id,
+ RTE_ETH_EVENT_INTR_LSC,
+ &bonded_ethdev->data->port_id);
+ }
+ }
+ rte_spinlock_unlock(&internals->lock);
+ }
+
+ if (polling_slave_found)
+ /* Set alarm to continue monitoring link status of slave ethdev's */
+ rte_eal_alarm_set(internals->link_status_polling_interval_ms * 1000,
+ bond_ethdev_slave_link_status_change_monitor, cb_arg);
+}
+
static int
bond_ethdev_link_update(struct rte_eth_dev *bonded_eth_dev,
int wait_to_complete)
@@ -895,7 +967,7 @@ bond_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
memset(stats, 0, sizeof(*stats));
for (i = 0; i < internals->slave_count; i++) {
- rte_eth_stats_get(internals->slaves[i], &slave_stats);
+ rte_eth_stats_get(internals->slaves[i].port_id, &slave_stats);
stats->ipackets += slave_stats.ipackets;
stats->opackets += slave_stats.opackets;
@@ -921,7 +993,7 @@ bond_ethdev_stats_reset(struct rte_eth_dev *dev)
int i;
for (i = 0; i < internals->slave_count; i++)
- rte_eth_stats_reset(internals->slaves[i]);
+ rte_eth_stats_reset(internals->slaves[i].port_id);
}
static void
@@ -940,7 +1012,7 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
case BONDING_MODE_BROADCAST:
#endif
for (i = 0; i < internals->slave_count; i++)
- rte_eth_promiscuous_enable(internals->slaves[i]);
+ rte_eth_promiscuous_enable(internals->slaves[i].port_id);
break;
/* Promiscuous mode is propagated only to primary slave */
case BONDING_MODE_ACTIVE_BACKUP:
@@ -966,7 +1038,7 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
case BONDING_MODE_BROADCAST:
#endif
for (i = 0; i < internals->slave_count; i++)
- rte_eth_promiscuous_disable(internals->slaves[i]);
+ rte_eth_promiscuous_disable(internals->slaves[i].port_id);
break;
/* Promiscuous mode is propagated only to primary slave */
case BONDING_MODE_ACTIVE_BACKUP:
@@ -975,6 +1047,16 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
}
}
+static void
+bond_ethdev_delayed_lsc_propagation(void *arg)
+{
+ if (arg == NULL)
+ return;
+
+ _rte_eth_dev_callback_process((struct rte_eth_dev *)arg,
+ RTE_ETH_EVENT_INTR_LSC);
+}
+
void
bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
void *param)
@@ -1003,7 +1085,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
/* verify that port_id is a valid slave of bonded port */
for (i = 0; i < internals->slave_count; i++) {
- if (internals->slaves[i] == port_id) {
+ if (internals->slaves[i].port_id == port_id) {
valid_slave = 1;
break;
}
@@ -1072,8 +1154,32 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
}
}
- if (lsc_flag)
- _rte_eth_dev_callback_process(bonded_eth_dev, RTE_ETH_EVENT_INTR_LSC);
+ if (lsc_flag) {
+ /* Cancel any possible outstanding interrupts if delays are enabled */
+ if (internals->link_up_delay_ms > 0 ||
+ internals->link_down_delay_ms > 0)
+ rte_eal_alarm_cancel(bond_ethdev_delayed_lsc_propagation,
+ bonded_eth_dev);
+
+ if (bonded_eth_dev->data->dev_link.link_status) {
+ if (internals->link_up_delay_ms > 0)
+ rte_eal_alarm_set(internals->link_up_delay_ms * 1000,
+ bond_ethdev_delayed_lsc_propagation,
+ (void *)bonded_eth_dev);
+ else
+ _rte_eth_dev_callback_process(bonded_eth_dev,
+ RTE_ETH_EVENT_INTR_LSC);
+
+ } else {
+ if (internals->link_down_delay_ms > 0)
+ rte_eal_alarm_set(internals->link_down_delay_ms * 1000,
+ bond_ethdev_delayed_lsc_propagation,
+ (void *)bonded_eth_dev);
+ else
+ _rte_eth_dev_callback_process(bonded_eth_dev,
+ RTE_ETH_EVENT_INTR_LSC);
+ }
+ }
}
struct eth_dev_ops default_dev_ops = {
@@ -1223,8 +1329,8 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
}
} else if (arg_count > 1) {
RTE_LOG(ERR, EAL,
- "Transmit policy can be specified only once for bonded device %s\n",
- name);
+ "Transmit policy can be specified only once for bonded device"
+ " %s\n", name);
return -1;
}
@@ -1266,8 +1372,8 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
&bond_ethdev_parse_primary_slave_port_id_kvarg,
&primary_slave_port_id) < 0) {
RTE_LOG(INFO, EAL,
- "Invalid primary slave port id specified for bonded device %s\n",
- name);
+ "Invalid primary slave port id specified for bonded device"
+ " %s\n", name);
return -1;
}
@@ -1281,8 +1387,97 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
}
} else if (arg_count > 1) {
RTE_LOG(INFO, EAL,
- "Primary slave can be specified only once for bonded device %s\n",
- name);
+ "Primary slave can be specified only once for bonded device"
+ " %s\n", name);
+ return -1;
+ }
+
+ /* Parse link status monitor polling interval */
+ arg_count = rte_kvargs_count(kvlist, PMD_BOND_LSC_POLL_PERIOD_KVARG);
+ if (arg_count == 1) {
+ uint32_t lsc_poll_interval_ms;
+
+ if (rte_kvargs_process(kvlist,
+ PMD_BOND_LSC_POLL_PERIOD_KVARG,
+ &bond_ethdev_parse_time_ms_kvarg,
+ &lsc_poll_interval_ms) < 0) {
+ RTE_LOG(INFO, EAL,
+ "Invalid lsc polling interval value specified for bonded"
+ " device %s\n", name);
+ return -1;
+ }
+
+ if (rte_eth_bond_link_monitoring_set(port_id, lsc_poll_interval_ms)
+ != 0) {
+ RTE_LOG(ERR, EAL,
+ "Failed to set lsc monitor polling interval (%u ms) on"
+ " bonded device %s\n", lsc_poll_interval_ms, name);
+ return -1;
+ }
+ } else if (arg_count > 1) {
+ RTE_LOG(INFO, EAL,
+ "LSC polling interval can be specified only once for bonded"
+ " device %s\n", name);
+ return -1;
+ }
+
+ /* Parse link up interrupt propagation delay */
+ arg_count = rte_kvargs_count(kvlist, PMD_BOND_LINK_UP_PROP_DELAY_KVARG);
+ if (arg_count == 1) {
+ uint32_t link_up_delay_ms;
+
+ if (rte_kvargs_process(kvlist,
+ PMD_BOND_LINK_UP_PROP_DELAY_KVARG,
+ &bond_ethdev_parse_time_ms_kvarg,
+ &link_up_delay_ms) < 0) {
+ RTE_LOG(INFO, EAL,
+ "Invalid link up propagation delay value specified for"
+ " bonded device %s\n", name);
+ return -1;
+ }
+
+ /* Set balance mode transmit policy*/
+ if (rte_eth_bond_link_up_prop_delay_set(port_id, link_up_delay_ms)
+ != 0) {
+ RTE_LOG(ERR, EAL,
+ "Failed to set link up propagation delay (%u ms) on bonded"
+ " device %s\n", link_up_delay_ms, name);
+ return -1;
+ }
+ } else if (arg_count > 1) {
+ RTE_LOG(INFO, EAL,
+ "Link up propagation delay can be specified only once for"
+ " bonded device %s\n", name);
+ return -1;
+ }
+
+ /* Parse link down interrupt propagation delay */
+ arg_count = rte_kvargs_count(kvlist, PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG);
+ if (arg_count == 1) {
+ uint32_t link_down_delay_ms;
+
+ if (rte_kvargs_process(kvlist,
+ PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG,
+ &bond_ethdev_parse_time_ms_kvarg,
+ &link_down_delay_ms) < 0) {
+ RTE_LOG(INFO, EAL,
+ "Invalid link down propagation delay value specified for"
+ " bonded device %s\n", name);
+ return -1;
+ }
+
+ /* Set balance mode transmit policy*/
+ if (rte_eth_bond_link_down_prop_delay_set(port_id, link_down_delay_ms)
+ != 0) {
+ RTE_LOG(ERR, EAL,
+ "Failed to set link down propagation delay (%u ms) on"
+ " bonded device %s\n", link_down_delay_ms, name);
+ return -1;
+ }
+ } else if (arg_count > 1) {
+ RTE_LOG(INFO, EAL,
+ "Link down propagation delay can be specified only once for"
+ " bonded device %s\n", name);
return -1;
}
diff --git a/lib/librte_pmd_bond/rte_eth_bond_private.h b/lib/librte_pmd_bond/rte_eth_bond_private.h
index 1db6e4d..6254c84 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_private.h
+++ b/lib/librte_pmd_bond/rte_eth_bond_private.h
@@ -39,20 +39,27 @@ extern "C" {
#endif
#include <rte_ethdev.h>
+#include <rte_spinlock.h>
#include "rte_eth_bond.h"
-#define PMD_BOND_SLAVE_PORT_KVARG ("slave")
-#define PMD_BOND_PRIMARY_SLAVE_KVARG ("primary")
-#define PMD_BOND_MODE_KVARG ("mode")
-#define PMD_BOND_XMIT_POLICY_KVARG ("xmit_policy")
-#define PMD_BOND_SOCKET_ID_KVARG ("socket_id")
-#define PMD_BOND_MAC_ADDR_KVARG ("mac")
+#define PMD_BOND_SLAVE_PORT_KVARG ("slave")
+#define PMD_BOND_PRIMARY_SLAVE_KVARG ("primary")
+#define PMD_BOND_MODE_KVARG ("mode")
+#define PMD_BOND_XMIT_POLICY_KVARG ("xmit_policy")
+#define PMD_BOND_SOCKET_ID_KVARG ("socket_id")
+#define PMD_BOND_MAC_ADDR_KVARG ("mac")
+#define PMD_BOND_LSC_POLL_PERIOD_KVARG ("lsc_poll_period_ms")
+#define PMD_BOND_LINK_UP_PROP_DELAY_KVARG ("up_delay")
+#define PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG ("down_delay")
#define PMD_BOND_XMIT_POLICY_LAYER2_KVARG ("l2")
#define PMD_BOND_XMIT_POLICY_LAYER23_KVARG ("l23")
#define PMD_BOND_XMIT_POLICY_LAYER34_KVARG ("l34")
+#define RTE_BOND_LOG(lvl, msg, ...) \
+ RTE_LOG(lvl, PMD, "%s(%d) - " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
+
extern const char *pmd_bond_init_valid_arguments[];
extern const char *driver_name;
@@ -82,27 +89,36 @@ struct bond_tx_queue {
/**< Copy of TX configuration structure for queue */
};
-/** Persisted Slave Configuration Structure */
-struct slave_conf {
- uint8_t port_id;
- /**< Port Id of slave eth_dev */
- struct ether_addr mac_addr;
- /**< Slave eth_dev original MAC address */
-};
+
/** Bonded slave devices structure */
struct bond_ethdev_slave_ports {
uint8_t slaves[RTE_MAX_ETHPORTS]; /**< Slave port id array */
uint8_t slave_count; /**< Number of slaves */
};
+struct bond_slave_details {
+ uint8_t port_id;
+
+ uint8_t link_status_poll_enabled;
+ uint8_t link_status_wait_to_complete;
+ uint8_t last_link_status;
+
+ /**< Port Id of slave eth_dev */
+ struct ether_addr persisted_mac_addr;
+};
+
/** Link Bonding PMD device private configuration Structure */
struct bond_dev_private {
+ uint8_t port_id; /**< Port Id of Bonded Port */
uint8_t mode; /**< Link Bonding Mode */
+ rte_spinlock_t lock;
+
uint8_t primary_port; /**< Primary Slave Port */
uint8_t current_primary_port; /**< Primary Slave Port */
uint8_t user_defined_primary_port;
/**< Flag for whether primary port is user defined or not */
+
uint8_t balance_xmit_policy;
/**< Transmit policy - l2 / l23 / l34 for operation in balance mode */
uint8_t user_defined_mac;
@@ -110,19 +126,23 @@ struct bond_dev_private {
uint8_t promiscuous_en;
/**< Enabled/disable promiscuous mode on slave devices */
uint8_t link_props_set;
- /**< Bonded eth_dev link properties set */
+ /**< flag to denote if the link properties are set */
+
+ uint8_t link_status_polling_enabled;
+ uint32_t link_status_polling_interval_ms;
+
+ uint32_t link_down_delay_ms;
+ uint32_t link_up_delay_ms;
uint16_t nb_rx_queues; /**< Total number of rx queues */
uint16_t nb_tx_queues; /**< Total number of tx queues*/
- uint8_t slave_count; /**< Number of active slaves */
- uint8_t active_slave_count; /**< Number of slaves */
-
+ uint8_t active_slave_count; /**< Number of active slaves */
uint8_t active_slaves[RTE_MAX_ETHPORTS]; /**< Active slave list */
- uint8_t slaves[RTE_MAX_ETHPORTS]; /**< Slave list */
- /** Persisted configuration of slaves */
- struct slave_conf presisted_slaves_conf[RTE_MAX_ETHPORTS];
+ uint8_t slave_count; /**< Number of bonded slaves */
+ struct bond_slave_details slaves[RTE_MAX_ETHPORTS];
+ /**< Arary of bonded slaves details */
struct rte_kvargs *kvlist;
};
@@ -168,16 +188,13 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
struct rte_eth_dev *slave_eth_dev);
void
-slave_config_clear(struct bond_dev_private *internals,
+slave_remove(struct bond_dev_private *internals,
struct rte_eth_dev *slave_eth_dev);
void
-slave_config_store(struct bond_dev_private *internals,
+slave_add(struct bond_dev_private *internals,
struct rte_eth_dev *slave_eth_dev);
-struct slave_conf *
-slave_config_get(struct bond_dev_private *internals, uint8_t slave_port_id);
-
void
bond_ethdev_primary_set(struct bond_dev_private *internals,
uint8_t slave_port_id);
@@ -210,6 +227,10 @@ int
bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused,
const char *value, void *extra_args);
+int
+bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused,
+ const char *value, void *extra_args);
+
#ifdef __cplusplus
}
#endif