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:
parent
56c7ddc138
commit
f28f3594de
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user