From patchwork Tue Jul 14 10:14:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 73997 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id C5108A0543; Tue, 14 Jul 2020 12:18:42 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1A68D1C295; Tue, 14 Jul 2020 12:18:42 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id BCA2C1C0B7 for ; Tue, 14 Jul 2020 12:18:40 +0200 (CEST) IronPort-SDR: pdP7mRXTSZQcNU0Y5K1Mz3/F6skrJmB193XFx+1Cn1P1sVacIJpGV1DMqZXoWXCDRae6/ixK/z DpcLmqzKExiQ== X-IronPort-AV: E=McAfee;i="6000,8403,9681"; a="233724399" X-IronPort-AV: E=Sophos;i="5.75,350,1589266800"; d="scan'208";a="233724399" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Jul 2020 03:18:39 -0700 IronPort-SDR: y3AUtu8nC+MAwD0ZHphOj1mvrzw7MAh4233qbe+/GBgKye84Me2EcoAQxY+ynANSjYskxkKS7F 4MbhgmU7EBGg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,350,1589266800"; d="scan'208";a="360342930" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga001.jf.intel.com with ESMTP; 14 Jul 2020 03:18:38 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, bruce.richardson@intel.com, Ciara Power Date: Tue, 14 Jul 2020 11:14:15 +0100 Message-Id: <20200714101415.36890-1-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dpdk-dev] [PATCH] doc: add more detail to telemetry guides X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds examples to the Telemetry HowTo guide, to demonstrate commands that use parameters. The programmer's guide is also modified to include details on writing a callback function for a new command. Signed-off-by: Ciara Power --- doc/guides/howto/telemetry.rst | 45 ++++- doc/guides/prog_guide/telemetry_lib.rst | 230 ++++++++++++++++++++++-- 2 files changed, 250 insertions(+), 25 deletions(-) diff --git a/doc/guides/howto/telemetry.rst b/doc/guides/howto/telemetry.rst index b4a34ed67..39cab99a7 100644 --- a/doc/guides/howto/telemetry.rst +++ b/doc/guides/howto/telemetry.rst @@ -69,12 +69,43 @@ and query information using the telemetry client python script. --> #. The user can now input commands to send across the socket, and receive the - response. + response. Some available commands are shown below. - .. code-block:: console + * List all commands. + + .. code-block:: console + + --> / + {"/": ["/", "/eal/app_params", "/eal/params", "/ethdev/list", + "/ethdev/link_status", "/ethdev/xstats", "/help", "/info"]} + + * Get the list of ethdev ports. + + .. code-block:: console + + --> /ethdev/list + {"/ethdev/list": [0, 1]} + + .. Note:: + + For commands that expect a parameter, use "," to separate the command + and parameter. See examples below. + + * Get extended statistics for an ethdev port. + + .. code-block:: console + + --> /ethdev/xstats,0 + {"/ethdev/xstats": {"rx_good_packets": 0, "tx_good_packets": 0, + "rx_good_bytes": 0, "tx_good_bytes": 0, "rx_missed_errors": 0, + ... + "tx_priority7_xon_to_xoff_packets": 0}} + + * Get the help text for a command. This will indicate what parameters are + required. Pass the command as a parameter. + + .. code-block:: console - --> / - {"/": ["/", "/eal/app_params", "/eal/params", "/ethdev/list", - "/ethdev/link_status", "/ethdev/xstats", "/help", "/info"]} - --> /ethdev/list - {"/ethdev/list": [0, 1]} + --> /help,/ethdev/xstats + {"/help": {"/ethdev/xstats": "Returns the extended stats for a port. + Parameters: int port_id"}} diff --git a/doc/guides/prog_guide/telemetry_lib.rst b/doc/guides/prog_guide/telemetry_lib.rst index 8563a7200..d968f2169 100644 --- a/doc/guides/prog_guide/telemetry_lib.rst +++ b/doc/guides/prog_guide/telemetry_lib.rst @@ -16,6 +16,166 @@ function that will format the library specific stats into the correct data format, when requested. +Creating Callback Functions +--------------------------- + + +Function Type +~~~~~~~~~~~~~ + +When creating a callback function in a library/app, it must be of the following type: + +.. code-block:: c + + typedef int (*telemetry_cb)(const char *cmd, const char *params, + struct rte_tel_data *info); + +For example, the callback for "/ethdev/list" is: + +.. code-block:: c + + static int + handle_port_list(const char *cmd __rte_unused, const char *params __rte_unused, + struct rte_tel_data *d) + +The parameters for a callback function are: + +* **cmd** + + This is the command requested by the client, e.g. "/ethdev/list". + For most callbacks this may be unused, however it will allow for handling + multiple commands in one callback function. An example of this can be seen in + the EAL callback below. + + .. code-block:: c + + #define EAL_PARAM_REQ "/eal/params" + #define EAL_APP_PARAM_REQ "/eal/app_params" + + /* callback handler for telemetry library to report out EAL flags */ + int + handle_eal_info_request(const char *cmd, const char *params __rte_unused, + struct rte_tel_data *d) + { + char **args; + int used = 0; + int i = 0; + + if (strcmp(cmd, EAL_PARAM_REQ) == 0) + args = eal_args; + else + args = eal_app_args; + + rte_tel_data_start_array(d, RTE_TEL_STRING_VAL); + if (args == NULL || args[0] == NULL) + return 0; + + for ( ; args[i] != NULL; i++) + used = rte_tel_data_add_array_string(d, args[i]); + return used; + } + +* **params** + + This will contain any parameters required for the command. For example + when calling "/ethdev/link_status,0", the port ID will be passed to the + callback function in params. An example of this being used is shown below. + +.. code-block:: c + + static int + handle_port_link_status(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) + { + static const char *status_str = "status"; + int ret, port_id; + struct rte_eth_link link; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + port_id = atoi(params); + if (!rte_eth_dev_is_valid_port(port_id)) + return -1; + + ret = rte_eth_link_get(port_id, &link); + if (ret < 0) + return -1; + + rte_tel_data_start_dict(d); + if (!link.link_status) { + rte_tel_data_add_dict_string(d, status_str, "DOWN"); + return 0; + } + rte_tel_data_add_dict_string(d, status_str, "UP"); + rte_tel_data_add_dict_u64(d, "speed", link.link_speed); + rte_tel_data_add_dict_string(d, "duplex", + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + "full-duplex" : "half-duplex"); + return 0; + } + +* **d** + + The rte_tel_data pointer will be used by the callback function to format the + requested data to be returned to Telemetry. The data APIs provided will + enable adding to the struct, examples of this are shown later in this + document. + + +Formatting Data +~~~~~~~~~~~~~~~ + +The callback function provided by the library must format its telemetry +information in the required data format. The Telemetry library provides a data +utilities API to build up the data structure with the required information. +The telemetry library is then responsible for formatting the data structure +into a JSON response before sending to the client. + +* **Array Data** + + Some data will need to be formatted in a list structure. For example, the + ethdev library provides a list of available ethdev ports in a formatted data + response, constructed using the following functions to build up the list: + + .. code-block:: c + + rte_tel_data_start_array(d, RTE_TEL_INT_VAL); + RTE_ETH_FOREACH_DEV(port_id) + rte_tel_data_add_array_int(d, port_id); + + The resulting response to the client shows the port list data provided above + by the handler function in ethdev, placed in a JSON reply by telemetry: + + .. code-block:: console + + {"/ethdev/list": [0, 1]} + +* **Dictionary Data** + + For data that needs to be structured in a dictionary with key/value pairs, + the data utilities API can also be used. For example, telemetry provides an + info command that has multiple key/value pairs, constructed in the callback + function shown below: + + .. code-block:: c + + rte_tel_data_start_dict(d); + rte_tel_data_add_dict_string(d, "version", rte_version()); + rte_tel_data_add_dict_int(d, "pid", getpid()); + rte_tel_data_add_dict_int(d, "max_output_len", MAX_OUTPUT_LEN); + + The resulting response to the client shows the key/value data provided above + by the handler function in telemetry, placed in a JSON reply by telemetry: + + .. code-block:: console + + {"/info": {"version": "DPDK 20.08.0-rc0", "pid": 3838, "max_output_len": 16384}} + +For more information on the range of data functions available in the API, +please refer to the docs. + + Registering Commands -------------------- @@ -35,28 +195,62 @@ command. An example showing ethdev commands being registered is shown below: "Returns the link status for a port. Parameters: int port_id"); -Formatting JSON response ------------------------- +Using Commands +-------------- -The callback function provided by the library must format its telemetry -information in the required data format. The Telemetry library provides a data -utilities API to build up the response. For example, the ethdev library provides a -list of available ethdev ports in a formatted data response, constructed using the -following functions to build up the list: +To use commands, with a DPDK app running (e.g. testpmd), use the +dpdk-telemetry.py script. -.. code-block:: c + .. code-block:: console - rte_tel_data_start_array(d, RTE_TEL_INT_VAL); - RTE_ETH_FOREACH_DEV(port_id) - rte_tel_data_add_array_int(d, port_id); + python usertools/dpdk-telemetry.py -The data structure is then formatted into a JSON response before sending. -The resulting response shows the port list data provided above by the handler -function in ethdev, placed in a JSON reply by telemetry: +When connected, the script displays the following, waiting for input. -.. code-block:: console + .. code-block:: console - {"/ethdev/list": [0, 1]} + Connecting to /var/run/dpdk/rte/dpdk_telemetry.v2 + {"version": "DPDK 20.05.0-rc0", "pid": 60285, "max_output_len": 16384} + --> -For more information on the range of data functions available in the API, -please refer to the docs. +You can now input commands to send across the socket, and receive the +response. Some available commands are shown below. + + * List all commands. + + .. code-block:: console + + --> / + {"/": ["/", "/eal/app_params", "/eal/params", "/ethdev/list", + "/ethdev/link_status", "/ethdev/xstats", "/help", "/info"]} + + * Get the list of ethdev ports. + + .. code-block:: console + + --> /ethdev/list + {"/ethdev/list": [0, 1]} + + .. Note:: + + For commands that expect a parameter, use "," to separate the command + and parameter. See examples below. + + * Get extended statistics for an ethdev port. + + .. code-block:: console + + --> /ethdev/xstats,0 + {"/ethdev/xstats": {"rx_good_packets": 0, "tx_good_packets": 0, + "rx_good_bytes": 0, "tx_good_bytes": 0, "rx_missed_errors": 0, + ... + "tx_priority7_xon_to_xoff_packets": 0}} + + * Get the help text for a command. This will indicate what parameters are + required. Pass the command as a parameter. + + .. code-block:: console + + --> /help,/ethdev/xstats + {"/help": {"/ethdev/xstats": "Returns the extended stats for a port. + Parameters: int port_id"}}