net: hns3: debugfs support for dumping fd rules

Currently, the tc tool only supports adding and deleting rules from
the driver but does not support querying rules from the driver.

This patch adds a rule dump file in debugfs to check whether the driver's
configuration matches the configuration issued by tc flow.

Signed-off-by: Jijie Shao <shaojijie@huawei.com>
Link: https://patch.msgid.link/20260610060618.834987-6-shaojijie@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jijie Shao 2026-06-10 14:06:17 +08:00 committed by Jakub Kicinski
parent cc2c4dbb00
commit 6c586b3ab8
3 changed files with 162 additions and 0 deletions

View File

@ -331,6 +331,7 @@ enum hnae3_dbg_cmd {
HNAE3_DBG_CMD_TX_QUEUE_INFO,
HNAE3_DBG_CMD_FD_TCAM,
HNAE3_DBG_CMD_FD_COUNTER,
HNAE3_DBG_CMD_FD_RULE,
HNAE3_DBG_CMD_MAC_TNL_STATUS,
HNAE3_DBG_CMD_SERV_INFO,
HNAE3_DBG_CMD_UMV_INFO,

View File

@ -273,6 +273,12 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = {
.dentry = HNS3_DBG_DENTRY_FD,
.init = hns3_dbg_common_init_t2,
},
{
.name = "fd_rule",
.cmd = HNAE3_DBG_CMD_FD_RULE,
.dentry = HNS3_DBG_DENTRY_FD,
.init = hns3_dbg_common_init_t2,
},
{
.name = "service_task_info",
.cmd = HNAE3_DBG_CMD_SERV_INFO,

View File

@ -2121,6 +2121,157 @@ static int hclge_dbg_dump_fd_counter(struct seq_file *s, void *data)
return 0;
}
__printf(4, 5)
static void hclge_fd_dump_item(struct seq_file *s, const char *name,
const char *suffix, const char *fmt, ...)
{
va_list args;
seq_printf(s, "\t\t%s%s: ", name, suffix);
va_start(args, fmt);
seq_vprintf(s, fmt, args);
va_end(args);
seq_putc(s, '\n');
}
#define hclge_fd_dump_any(s, rule, type, name, fmt, key, mask) \
do { \
typeof(s) _s = (s); \
typeof(name) _name = (name); \
typeof(fmt) _fmt = (fmt); \
\
if (!((rule)->unused_tuple & BIT(type))) { \
hclge_fd_dump_item(_s, _name, "", _fmt, key); \
hclge_fd_dump_item(_s, _name, "_mask", _fmt, mask); \
} \
} while (0)
#define hclge_fd_dump_u32 hclge_fd_dump_any
#define hclge_fd_dump_ptr hclge_fd_dump_any
static void hclge_fd_dump_ip(struct seq_file *s,
struct hclge_fd_rule *rule,
u32 type, const char *name,
const u32 *ip, const u32 *mask)
{
__be32 be_mask[IPV6_ADDR_WORDS];
__be32 be_ip[IPV6_ADDR_WORDS];
if (rule->unused_tuple & BIT(type) ||
rule->unused_tuple & BIT(INNER_ETH_TYPE))
return;
ipv6_addr_cpu_to_be32(be_ip, ip);
ipv6_addr_cpu_to_be32(be_mask, mask);
if (rule->tuples.ether_proto == ETH_P_IPV6)
hclge_fd_dump_ptr(s, rule, type, name, "%pI6",
be_ip, be_mask);
else
hclge_fd_dump_ptr(s, rule, type, name, "%pI4",
&be_ip[IPV4_INDEX], &be_mask[IPV4_INDEX]);
}
static void hclge_dbg_dump_fd_tuples(struct seq_file *s,
struct hclge_fd_rule *rule)
{
seq_puts(s, "\trule tuples:\n");
hclge_fd_dump_ptr(s, rule, INNER_DST_MAC, "dst_mac", "%pM",
rule->tuples.dst_mac, rule->tuples_mask.dst_mac);
hclge_fd_dump_ptr(s, rule, INNER_SRC_MAC, "src_mac", "%pM",
rule->tuples.src_mac, rule->tuples_mask.src_mac);
hclge_fd_dump_u32(s, rule, INNER_VLAN_TAG_FST, "vlan_tag", "0x%04x",
rule->tuples.vlan_tag1, rule->tuples_mask.vlan_tag1);
hclge_fd_dump_u32(s, rule, INNER_ETH_TYPE, "ether_proto", "0x%04x",
rule->tuples.ether_proto,
rule->tuples_mask.ether_proto);
hclge_fd_dump_u32(s, rule, INNER_L2_RSV, "l2_user_def", "0x%04x",
rule->tuples.l2_user_def,
rule->tuples_mask.l2_user_def);
hclge_fd_dump_ip(s, rule, INNER_SRC_IP, "src_ip",
rule->tuples.src_ip, rule->tuples_mask.src_ip);
hclge_fd_dump_ip(s, rule, INNER_DST_IP, "dst_ip",
rule->tuples.dst_ip, rule->tuples_mask.dst_ip);
hclge_fd_dump_u32(s, rule, INNER_IP_TOS, "ip_tos", "0x%02x",
rule->tuples.ip_tos, rule->tuples_mask.ip_tos);
hclge_fd_dump_u32(s, rule, INNER_IP_PROTO, "ip_proto", "0x%02x",
rule->tuples.ip_proto, rule->tuples_mask.ip_proto);
hclge_fd_dump_u32(s, rule, INNER_L3_RSV, "l3_user_def", "0x%04x",
rule->tuples.l3_user_def,
rule->tuples_mask.l3_user_def);
hclge_fd_dump_u32(s, rule, INNER_SRC_PORT, "src_port", "0x%04x",
rule->tuples.src_port, rule->tuples_mask.src_port);
hclge_fd_dump_u32(s, rule, INNER_DST_PORT, "dst_port", "0x%04x",
rule->tuples.dst_port, rule->tuples_mask.dst_port);
hclge_fd_dump_u32(s, rule, INNER_L4_RSV, "l4_user_def", "0x%08x",
rule->tuples.l4_user_def,
rule->tuples_mask.l4_user_def);
hclge_fd_dump_u32(s, rule, OUTER_TUN_VNI, "outer_tun_vni", "0x%06x",
rule->tuples.outer_tun_vni,
rule->tuples_mask.outer_tun_vni);
}
static void hclge_dbg_dump_fd_action(struct seq_file *s,
struct hclge_fd_rule *rule)
{
static const char * const action_str[] = {
[HCLGE_FD_ACTION_SELECT_QUEUE] = "select_queue",
[HCLGE_FD_ACTION_DROP_PACKET] = "drop_packet",
[HCLGE_FD_ACTION_SELECT_TC] = "select_tc",
};
if (rule->action <= HCLGE_FD_ACTION_SELECT_TC)
seq_printf(s, "\taction: %s\n", action_str[rule->action]);
else
seq_printf(s, "\taction: %s\n", "unknown");
if (rule->action == HCLGE_FD_ACTION_SELECT_QUEUE)
seq_printf(s, "\tqueue_id: %u\n", rule->queue_id);
else if (rule->action == HCLGE_FD_ACTION_SELECT_TC)
seq_printf(s, "\ttc: %u\n", rule->cls_flower.tc);
}
static void hclge_dbg_dump_fd_type(struct hclge_dev *hdev, struct seq_file *s)
{
static const char * const type_str[] = {
[HCLGE_FD_RULE_NONE] = "none",
[HCLGE_FD_ARFS_ACTIVE] = "arfs",
[HCLGE_FD_EP_ACTIVE] = "ep",
[HCLGE_FD_TC_FLOWER_ACTIVE] = "tc_flow"
};
if (hdev->fd_active_type <= HCLGE_FD_TC_FLOWER_ACTIVE)
seq_printf(s, "fd type: %s\n", type_str[hdev->fd_active_type]);
else
seq_printf(s, "fd type: %s\n", "unknown");
}
static int hclge_dbg_dump_fd_rule(struct seq_file *s, void *data)
{
struct hclge_dev *hdev = hclge_seq_file_to_hdev(s);
struct hclge_fd_rule *rule;
if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
return -EOPNOTSUPP;
spin_lock_bh(&hdev->fd_rule_lock);
hclge_dbg_dump_fd_type(hdev, s);
hlist_for_each_entry(rule, &hdev->fd_rule_list, rule_node) {
if (rule->state != HCLGE_FD_ACTIVE)
continue;
seq_printf(s, "location: %u\n", rule->location);
seq_printf(s, "vport_id: %u\n", rule->vf_id);
hclge_dbg_dump_fd_action(s, rule);
hclge_dbg_dump_fd_tuples(s, rule);
}
spin_unlock_bh(&hdev->fd_rule_lock);
return 0;
}
static const struct hclge_dbg_status_dfx_info hclge_dbg_rst_info[] = {
{HCLGE_MISC_VECTOR_REG_BASE, "vector0 interrupt enable status"},
{HCLGE_MISC_RESET_STS_REG, "reset interrupt source"},
@ -2913,6 +3064,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = {
.cmd = HNAE3_DBG_CMD_FD_TCAM,
.dbg_read_func = hclge_dbg_dump_fd_tcam,
},
{
.cmd = HNAE3_DBG_CMD_FD_RULE,
.dbg_read_func = hclge_dbg_dump_fd_rule,
},
{
.cmd = HNAE3_DBG_CMD_MAC_TNL_STATUS,
.dbg_read_func = hclge_dbg_dump_mac_tnl_status,