Sync some patchs from upstreaming, includind some bugfixes, hns3 pmd flow rule priority feature, hns3 pmd outer VLAN flow match feature, and support dump reigser names and filter. This patch set is modified as follows: - net/hns3: fix cannot fully use hardware flow director table - net/hns3: fix error code for repeatedly create counter - net/hns3: support flow rule priority - common/nfp: use new kvargs process API - net/tap: use new kvargs process API - net/sfc: use new kvargs process API - kvargs: rework process API - net/hns3: fix variable type - net/hns3: fix pointer offset - net/hns3: fix error log - net/hns3: support filtering registers by module names - net/hns3: support reporting names of registers - net/hns3: refactor register dump - net/hns3: remove separators between register module - net/hns3: fix dump counter of registers - net/hns3: remove some basic address dump - telemetry: register command with private argument - ethdev: fix race on ports in telemetry endpoints - ethdev: add telemetry command for registers - ethdev: add report of register names and filter - net/hns3: support outer VLAN flow match - net/hns3: register VLAN flow match mode parameter - net/hns3: support general tunnel flow match - net/hns3: restrict tunnel flow rule to one header - net/hns3: remove ROH devices - net/hns3: dump queue head and tail pointer info - dmadev: fix potential null pointer access - net/hns3: verify reset type from firmware - ethdev: verify queue ID in Tx done cleanup Signed-off-by: Dengdui Huang <huangdengdui@huawei.com> (cherry picked from commit a1c828e1eb9cf716187d2a7656023e95bdce9b55)
194 lines
5.6 KiB
Diff
194 lines
5.6 KiB
Diff
From 3f85d1cd33b037b73ac6b5a9746cb8e01c52dfb7 Mon Sep 17 00:00:00 2001
|
|
From: Jie Hai <haijie1@huawei.com>
|
|
Date: Thu, 26 Sep 2024 20:42:43 +0800
|
|
Subject: ethdev: add telemetry command for registers
|
|
|
|
[ upstream commit d916d27e3dca9d2e19e411fff9208929a7c7cbdf ]
|
|
|
|
This patch adds a telemetry command for registers dump,
|
|
and supports obtaining the registers of a specified module.
|
|
|
|
In one way, the number of registers that can be exported
|
|
is limited by the number of elements carried by dict and
|
|
container. In another way, the length of the string
|
|
exported by telemetry is limited by MAX_OUTPUT_LEN.
|
|
Therefore, when the number of registers to be exported
|
|
exceeds, some information will be lost. Warn on the former
|
|
case.
|
|
|
|
An example usage is shown below:
|
|
--> /ethdev/regs,0,ring
|
|
{
|
|
"/ethdev/regs": {
|
|
"registers_length": 318,
|
|
"registers_width": 4,
|
|
"register_offset": "0x0",
|
|
"version": "0x1140011",
|
|
"group_0": {
|
|
"Q0_ring_rx_bd_num": "0x0",
|
|
"Q0_ring_rx_bd_len": "0x0",
|
|
...
|
|
},
|
|
"group_1": {
|
|
...
|
|
},
|
|
...
|
|
}
|
|
|
|
Signed-off-by: Jie Hai <haijie1@huawei.com>
|
|
Reviewed-by: Ferruh Yigit <ferruh.yigit@amd.com>
|
|
Acked-by: Chengwen Feng <fengchengwen@huawei.com>
|
|
---
|
|
lib/ethdev/rte_ethdev_telemetry.c | 130 ++++++++++++++++++++++++++++++
|
|
1 file changed, 130 insertions(+)
|
|
|
|
diff --git a/lib/ethdev/rte_ethdev_telemetry.c b/lib/ethdev/rte_ethdev_telemetry.c
|
|
index 128c8e0012..343f1817c7 100644
|
|
--- a/lib/ethdev/rte_ethdev_telemetry.c
|
|
+++ b/lib/ethdev/rte_ethdev_telemetry.c
|
|
@@ -1395,6 +1395,134 @@ eth_dev_handle_port_tm_node_caps(const char *cmd __rte_unused,
|
|
return ret;
|
|
}
|
|
|
|
+static void
|
|
+eth_dev_add_reg_data(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info,
|
|
+ uint32_t idx)
|
|
+{
|
|
+ if (reg_info->width == sizeof(uint32_t))
|
|
+ rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name,
|
|
+ *((uint32_t *)reg_info->data + idx), 0);
|
|
+ else
|
|
+ rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name,
|
|
+ *((uint64_t *)reg_info->data + idx), 0);
|
|
+}
|
|
+
|
|
+static int
|
|
+eth_dev_store_regs(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info)
|
|
+{
|
|
+ struct rte_tel_data *groups[RTE_TEL_MAX_DICT_ENTRIES];
|
|
+ char group_name[RTE_TEL_MAX_STRING_LEN] = {0};
|
|
+ struct rte_tel_data *group = NULL;
|
|
+ uint32_t grp_num = 0;
|
|
+ uint32_t i, max_cap;
|
|
+ int ret;
|
|
+
|
|
+ rte_tel_data_start_dict(d);
|
|
+ rte_tel_data_add_dict_uint(d, "register_length", reg_info->length);
|
|
+ rte_tel_data_add_dict_uint(d, "register_width", reg_info->width);
|
|
+ rte_tel_data_add_dict_uint_hex(d, "register_offset", reg_info->offset, 0);
|
|
+ rte_tel_data_add_dict_uint_hex(d, "version", reg_info->version, 0);
|
|
+
|
|
+ max_cap = (RTE_TEL_MAX_DICT_ENTRIES - 4) * RTE_TEL_MAX_DICT_ENTRIES;
|
|
+ if (reg_info->length > max_cap) {
|
|
+ RTE_ETHDEV_LOG(WARNING,
|
|
+ "Registers to be displayed are reduced from %u to %u due to limited capacity",
|
|
+ reg_info->length, max_cap);
|
|
+ reg_info->length = max_cap;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < reg_info->length; i++) {
|
|
+ if (i % RTE_TEL_MAX_DICT_ENTRIES != 0) {
|
|
+ eth_dev_add_reg_data(group, reg_info, i);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ group = rte_tel_data_alloc();
|
|
+ if (group == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ RTE_ETHDEV_LOG(WARNING, "No enough memory for group data");
|
|
+ goto out;
|
|
+ }
|
|
+ groups[grp_num++] = group;
|
|
+ rte_tel_data_start_dict(group);
|
|
+ eth_dev_add_reg_data(group, reg_info, i);
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < grp_num; i++) {
|
|
+ snprintf(group_name, RTE_TEL_MAX_STRING_LEN, "group_%u", i);
|
|
+ rte_tel_data_add_dict_container(d, group_name, groups[i], 0);
|
|
+ }
|
|
+ return 0;
|
|
+out:
|
|
+ for (i = 0; i < grp_num; i++)
|
|
+ rte_tel_data_free(groups[i]);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+eth_dev_get_port_regs(int port_id, struct rte_tel_data *d, char *filter)
|
|
+{
|
|
+ struct rte_dev_reg_info reg_info;
|
|
+ int ret;
|
|
+
|
|
+ memset(®_info, 0, sizeof(reg_info));
|
|
+ reg_info.filter = filter;
|
|
+
|
|
+ ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
|
|
+ if (ret != 0) {
|
|
+ RTE_ETHDEV_LOG(ERR, "Failed to get device reg info: %d", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ reg_info.data = calloc(reg_info.length, reg_info.width);
|
|
+ if (reg_info.data == NULL) {
|
|
+ RTE_ETHDEV_LOG(ERR, "Failed to allocate memory for reg_info.data");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ reg_info.names = calloc(reg_info.length, sizeof(struct rte_eth_reg_name));
|
|
+ if (reg_info.names == NULL) {
|
|
+ RTE_ETHDEV_LOG(ERR, "Failed to allocate memory for reg_info.names");
|
|
+ free(reg_info.data);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
|
|
+ if (ret != 0) {
|
|
+ RTE_ETHDEV_LOG(ERR, "Failed to get device reg info: %d", ret);
|
|
+ ret = -EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = eth_dev_store_regs(d, ®_info);
|
|
+out:
|
|
+ free(reg_info.data);
|
|
+ free(reg_info.names);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+eth_dev_handle_port_regs(const char *cmd __rte_unused,
|
|
+ const char *params,
|
|
+ struct rte_tel_data *d)
|
|
+{
|
|
+ char *filter, *end_param;
|
|
+ uint16_t port_id;
|
|
+ int ret;
|
|
+
|
|
+ ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
|
|
+ if (ret != 0)
|
|
+ return ret;
|
|
+
|
|
+ filter = strtok(end_param, ",");
|
|
+ if (filter != NULL && strlen(filter) == 0)
|
|
+ filter = NULL;
|
|
+
|
|
+ return eth_dev_get_port_regs(port_id, d, filter);
|
|
+}
|
|
+
|
|
static int eth_dev_telemetry_do(const char *cmd, const char *params, void *arg,
|
|
struct rte_tel_data *d)
|
|
{
|
|
@@ -1467,4 +1595,6 @@ RTE_INIT(ethdev_init_telemetry)
|
|
rte_telemetry_register_cmd_arg("/ethdev/tm_node_capability",
|
|
eth_dev_telemetry_do, eth_dev_handle_port_tm_node_caps,
|
|
"Returns TM Node Capabilities info for a port. Parameters: int port_id, int node_id (see tm_capability for the max)");
|
|
+ rte_telemetry_register_cmd("/ethdev/regs", eth_dev_handle_port_regs,
|
|
+ "Returns all or filtered registers info for a port. Parameters: int port_id, string module_name (Optional if show all)");
|
|
}
|
|
--
|
|
2.20.1.windows.1
|
|
|