Add a new rte_telemetry_register_cmd_arg public function to register a telemetry endpoint with a callback that takes an additional private argument.
This will be used in the next commit to protect ethdev endpoints with a lock. Update perform_command() to take a struct callback object copied from the list of callbacks and invoke the correct function pointer. Signed-off-by: Robin Jarry <rja...@redhat.com> --- lib/telemetry/rte_telemetry.h | 46 +++++++++++++++++++++++++++++++++++ lib/telemetry/telemetry.c | 38 +++++++++++++++++++++++------ lib/telemetry/version.map | 3 +++ 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/lib/telemetry/rte_telemetry.h b/lib/telemetry/rte_telemetry.h index cab9daa6fed6..3fbfda138b16 100644 --- a/lib/telemetry/rte_telemetry.h +++ b/lib/telemetry/rte_telemetry.h @@ -336,6 +336,30 @@ rte_tel_data_add_dict_uint_hex(struct rte_tel_data *d, const char *name, typedef int (*telemetry_cb)(const char *cmd, const char *params, struct rte_tel_data *info); +/** + * This telemetry callback is used when registering a telemetry command with + * rte_telemetry_register_cmd_arg(). + * + * It handles getting and formatting information to be returned to telemetry + * when requested. + * + * @param cmd + * The cmd that was requested by the client. + * @param params + * Contains data required by the callback function. + * @param info + * The information to be returned to the caller. + * @param arg + * The opaque value that was passed to rte_telemetry_register_cmd_arg(). + * + * @return + * Length of buffer used on success. + * @return + * Negative integer on error. + */ +typedef int (*telemetry_arg_cb)(const char *cmd, const char *params, + struct rte_tel_data *info, void *arg); + /** * Used for handling data received over a telemetry socket. * @@ -367,6 +391,28 @@ typedef void * (*handler)(void *sock_id); int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn, const char *help); +/** + * Used when registering a command and callback function with telemetry. + * + * @param cmd + * The command to register with telemetry. + * @param fn + * Callback function to be called when the command is requested. + * @param arg + * An opaque value that will be passed to the callback function. + * @param help + * Help text for the command. + * + * @return + * 0 on success. + * @return + * -EINVAL for invalid parameters failure. + * @return + * -ENOMEM for mem allocation failure. + */ +__rte_experimental +int +rte_telemetry_register_cmd_arg(const char *cmd, telemetry_arg_cb fn, void *arg, const char *help); /** * Get a pointer to a container with memory allocated. The container is to be diff --git a/lib/telemetry/telemetry.c b/lib/telemetry/telemetry.c index c4c5a61a5cf8..2fe48d47f886 100644 --- a/lib/telemetry/telemetry.c +++ b/lib/telemetry/telemetry.c @@ -37,6 +37,8 @@ client_handler(void *socket); struct cmd_callback { char cmd[MAX_CMD_LEN]; telemetry_cb fn; + telemetry_arg_cb fn_arg; + void *arg; char help[RTE_TEL_MAX_STRING_LEN]; }; @@ -68,14 +70,15 @@ static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER; static RTE_ATOMIC(uint16_t) v2_clients; #endif /* !RTE_EXEC_ENV_WINDOWS */ -int -rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn, const char *help) +static int +__rte_telemetry_register_cmd(const char *cmd, const char *help, + telemetry_cb fn, telemetry_arg_cb fn_arg, void *arg) { struct cmd_callback *new_callbacks; const char *cmdp = cmd; int i = 0; - if (strlen(cmd) >= MAX_CMD_LEN || fn == NULL || cmd[0] != '/' + if (strlen(cmd) >= MAX_CMD_LEN || (fn == NULL && fn_arg == NULL) || cmd[0] != '/' || strlen(help) >= RTE_TEL_MAX_STRING_LEN) return -EINVAL; @@ -102,6 +105,8 @@ rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn, const char *help) strlcpy(callbacks[i].cmd, cmd, MAX_CMD_LEN); callbacks[i].fn = fn; + callbacks[i].fn_arg = fn_arg; + callbacks[i].arg = arg; strlcpy(callbacks[i].help, help, RTE_TEL_MAX_STRING_LEN); num_callbacks++; rte_spinlock_unlock(&callback_sl); @@ -109,6 +114,18 @@ rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn, const char *help) return 0; } +int +rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn, const char *help) +{ + return __rte_telemetry_register_cmd(cmd, help, fn, NULL, NULL); +} + +int +rte_telemetry_register_cmd_arg(const char *cmd, telemetry_arg_cb fn, void *arg, const char *help) +{ + return __rte_telemetry_register_cmd(cmd, help, NULL, fn, arg); +} + #ifndef RTE_EXEC_ENV_WINDOWS static int @@ -349,11 +366,16 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s) } static void -perform_command(telemetry_cb fn, const char *cmd, const char *param, int s) +perform_command(const struct cmd_callback *cb, const char *cmd, const char *param, int s) { struct rte_tel_data data = {0}; + int ret; + + if (cb->fn_arg != NULL) + ret = cb->fn_arg(cmd, param, &data, cb->arg); + else + ret = cb->fn(cmd, param, &data); - int ret = fn(cmd, param, &data); if (ret < 0) { char out_buf[MAX_CMD_LEN + 10]; int used = snprintf(out_buf, sizeof(out_buf), "{\"%.*s\":null}", @@ -392,19 +414,19 @@ client_handler(void *sock_id) buffer[bytes] = 0; const char *cmd = strtok(buffer, ","); const char *param = strtok(NULL, "\0"); - telemetry_cb fn = unknown_command; + struct cmd_callback cb = {.fn = unknown_command}; int i; if (cmd && strlen(cmd) < MAX_CMD_LEN) { rte_spinlock_lock(&callback_sl); for (i = 0; i < num_callbacks; i++) if (strcmp(cmd, callbacks[i].cmd) == 0) { - fn = callbacks[i].fn; + cb = callbacks[i]; break; } rte_spinlock_unlock(&callback_sl); } - perform_command(fn, cmd, param, s); + perform_command(&cb, cmd, param, s); bytes = read(s, buffer, sizeof(buffer) - 1); } diff --git a/lib/telemetry/version.map b/lib/telemetry/version.map index 2907d28aa03f..8f032bf53230 100644 --- a/lib/telemetry/version.map +++ b/lib/telemetry/version.map @@ -28,6 +28,9 @@ EXPERIMENTAL { rte_tel_data_add_array_uint_hex; rte_tel_data_add_dict_uint_hex; + # added in 24.11 + rte_telemetry_register_cmd_arg; + local: *; }; -- 2.46.2