service: add attribute API

Add APIs that allow an application to query and reset the attributes of
a service lcore.  Add one such new attribute, "loops", which is a
counter that tracks the number of times the service core has looped in
the service runner function.  This is useful to applications that desire
a "liveness" check to make sure a service core is not stuck.

Signed-off-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
Acked-by: Harry van Haaren <harry.van.haaren@intel.com>
This commit is contained in:
Erik Gabriel Carrillo 2018-05-09 11:22:16 -05:00 committed by Thomas Monjalon
parent 56c7ddc138
commit f28f3594de
4 changed files with 153 additions and 1 deletions

View File

@ -363,6 +363,42 @@ int32_t rte_service_attr_get(uint32_t id, uint32_t attr_id,
*/
int32_t rte_service_attr_reset_all(uint32_t id);
/**
* Returns the number of times the service runner has looped.
*/
#define RTE_SERVICE_LCORE_ATTR_LOOPS 0
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Get an attribute from a service core.
*
* @param lcore Id of the service core.
* @param attr_id Id of the attribute to be retrieved.
* @param [out] attr_value Pointer to storage in which to write retrieved value.
* @retval 0 Success, the attribute value has been written to *attr_value*.
* -EINVAL Invalid lcore, attr_id or attr_value was NULL.
* -ENOTSUP lcore is not a service core.
*/
int32_t __rte_experimental
rte_service_lcore_attr_get(uint32_t lcore, uint32_t attr_id,
uint64_t *attr_value);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Reset all attribute values of a service core.
*
* @param lcore The service core to reset all the statistics of
* @retval 0 Successfully reset attributes
* -EINVAL Invalid service id provided
* -ENOTSUP lcore is not a service core.
*/
int32_t __rte_experimental
rte_service_lcore_attr_reset_all(uint32_t lcore);
#ifdef __cplusplus
}
#endif

View File

@ -61,7 +61,7 @@ struct core_state {
uint8_t runstate; /* running or stopped */
uint8_t is_service_core; /* set if core is currently a service core */
/* extreme statistics */
uint64_t loops;
uint64_t calls_per_service[RTE_SERVICE_NUM_MAX];
} __rte_cache_aligned;
@ -422,6 +422,8 @@ rte_service_runner_func(void *arg)
service_run(i, cs, service_mask);
}
cs->loops++;
rte_smp_rmb();
}
@ -729,6 +731,28 @@ rte_service_attr_get(uint32_t id, uint32_t attr_id, uint32_t *attr_value)
}
}
int32_t __rte_experimental
rte_service_lcore_attr_get(uint32_t lcore, uint32_t attr_id,
uint64_t *attr_value)
{
struct core_state *cs;
if (lcore >= RTE_MAX_LCORE || !attr_value)
return -EINVAL;
cs = &lcore_states[lcore];
if (!cs->is_service_core)
return -ENOTSUP;
switch (attr_id) {
case RTE_SERVICE_LCORE_ATTR_LOOPS:
*attr_value = cs->loops;
return 0;
default:
return -EINVAL;
}
}
static void
rte_service_dump_one(FILE *f, struct rte_service_spec_impl *s,
uint64_t all_cycles, uint32_t reset)
@ -764,6 +788,23 @@ rte_service_attr_reset_all(uint32_t id)
return 0;
}
int32_t __rte_experimental
rte_service_lcore_attr_reset_all(uint32_t lcore)
{
struct core_state *cs;
if (lcore >= RTE_MAX_LCORE)
return -EINVAL;
cs = &lcore_states[lcore];
if (!cs->is_service_core)
return -ENOTSUP;
cs->loops = 0;
return 0;
}
static void
service_dump_calls_per_lcore(FILE *f, uint32_t lcore, uint32_t reset)
{

View File

@ -294,6 +294,8 @@ EXPERIMENTAL {
rte_mp_request_sync;
rte_mp_request_async;
rte_mp_sendmsg;
rte_service_lcore_attr_get;
rte_service_lcore_attr_reset_all;
rte_socket_count;
rte_socket_id_by_idx;
rte_vfio_dma_map;

View File

@ -325,6 +325,78 @@ service_attr_get(void)
return unregister_all();
}
/* verify service lcore attr get */
static int
service_lcore_attr_get(void)
{
/* ensure all services unregistered so cycle counts are zero */
unregister_all();
struct rte_service_spec service;
memset(&service, 0, sizeof(struct rte_service_spec));
service.callback = dummy_cb;
snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
uint32_t id;
TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
"Register of service failed");
rte_service_component_runstate_set(id, 1);
TEST_ASSERT_EQUAL(0, rte_service_runstate_set(id, 1),
"Error: Service start returned non-zero");
rte_service_set_stats_enable(id, 1);
uint64_t lcore_attr_value = 0xdead;
uint32_t lcore_attr_id = UINT32_MAX;
/* check error return values */
TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(UINT32_MAX,
lcore_attr_id, &lcore_attr_value),
"Invalid lcore_id didn't return -EINVAL");
TEST_ASSERT_EQUAL(-ENOTSUP, rte_service_lcore_attr_get(rte_lcore_id(),
lcore_attr_id, &lcore_attr_value),
"Non-service core didn't return -ENOTSUP");
/* Start service core to increment loop count */
TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
"Service core add did not return zero");
TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 1),
"Enabling valid service and core failed");
TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id),
"Starting service core failed");
/* wait for the service lcore to run */
rte_delay_ms(200);
lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS;
TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id,
lcore_attr_id, &lcore_attr_value),
"Valid lcore_attr_get() call didn't return success");
int loops_gt_zero = lcore_attr_value > 0;
TEST_ASSERT_EQUAL(1, loops_gt_zero,
"lcore_attr_get() failed to get loops "
"(expected > zero)");
lcore_attr_id++; // invalid lcore attr id
TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(slcore_id,
lcore_attr_id, &lcore_attr_value),
"Invalid lcore attr didn't return -EINVAL");
rte_service_lcore_stop(slcore_id);
TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_reset_all(slcore_id),
"Valid lcore_attr_reset_all() didn't return success");
lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS;
TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id,
lcore_attr_id, &lcore_attr_value),
"Valid lcore_attr_get() call didn't return success");
TEST_ASSERT_EQUAL(0, lcore_attr_value,
"lcore_attr_get() didn't get correct loop count "
"(zero)");
return unregister_all();
}
/* verify service dump */
static int
service_dump(void)
@ -781,6 +853,7 @@ static struct unit_test_suite service_tests = {
TEST_CASE_ST(dummy_register, NULL, service_get_by_name),
TEST_CASE_ST(dummy_register, NULL, service_dump),
TEST_CASE_ST(dummy_register, NULL, service_attr_get),
TEST_CASE_ST(dummy_register, NULL, service_lcore_attr_get),
TEST_CASE_ST(dummy_register, NULL, service_probe_capability),
TEST_CASE_ST(dummy_register, NULL, service_start_stop),
TEST_CASE_ST(dummy_register, NULL, service_lcore_add_del),