net: microchip: sparx5: Add VCAP rule debugFS support for the VCAP API
authorSteen Hegelund <steen.hegelund@microchip.com>
Thu, 17 Nov 2022 21:31:11 +0000 (22:31 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 21 Nov 2022 11:33:02 +0000 (11:33 +0000)
This add support to show all rules in a VCAP instance. The information
shown is:

 - rule id
 - address range
 - size
 - chain id
 - keyset name, subword size, register span
 - actionset name, subword size, register span
 - counter value
 - sticky bit (one bit width counter)

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/vcap/vcap_api.c
drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
drivers/net/ethernet/microchip/vcap/vcap_api_private.h

index 153e28e124bc50a1ddee94c0e61702a0f0c2df6c..3da714e9639c8dff6d97c1a3703b058b583dcaf9 100644 (file)
@@ -502,7 +502,7 @@ int vcap_api_check(struct vcap_control *ctrl)
        return 0;
 }
 
-static void vcap_erase_cache(struct vcap_rule_internal *ri)
+void vcap_erase_cache(struct vcap_rule_internal *ri)
 {
        ri->vctrl->ops->cache_erase(ri->admin);
 }
@@ -578,7 +578,7 @@ int vcap_lookup_rule_by_cookie(struct vcap_control *vctrl, u64 cookie)
 EXPORT_SYMBOL_GPL(vcap_lookup_rule_by_cookie);
 
 /* Make a shallow copy of the rule without the fields */
-static struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri)
+struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri)
 {
        struct vcap_rule_internal *duprule;
 
@@ -782,9 +782,16 @@ const char *vcap_keyfield_name(struct vcap_control *vctrl,
 }
 EXPORT_SYMBOL_GPL(vcap_keyfield_name);
 
+/* map actionset id to a string with the actionset name */
+const char *vcap_actionset_name(struct vcap_control *vctrl,
+                               enum vcap_actionfield_set actionset)
+{
+       return vctrl->stats->actionfield_set_names[actionset];
+}
+
 /* map action field id to a string with the action name */
-static const char *vcap_actionfield_name(struct vcap_control *vctrl,
-                                        enum vcap_action_field action)
+const char *vcap_actionfield_name(struct vcap_control *vctrl,
+                                 enum vcap_action_field action)
 {
        return vctrl->stats->actionfield_names[action];
 }
index 4a1ca26be901e87b7fcd742af8cc3238ddd3310d..b4bc32a08f2cfceaebc6923910a42be8ca7faedd 100644 (file)
@@ -234,6 +234,106 @@ static int vcap_addr_keyset(struct vcap_control *vctrl,
                                          admin->cache.maskstream, false, 0);
 }
 
+static int vcap_read_rule(struct vcap_rule_internal *ri)
+{
+       struct vcap_admin *admin = ri->admin;
+       int sw_idx, ent_idx = 0, act_idx = 0;
+       u32 addr = ri->addr;
+
+       if (!ri->size || !ri->keyset_sw_regs || !ri->actionset_sw_regs) {
+               pr_err("%s:%d: rule is empty\n", __func__, __LINE__);
+               return -EINVAL;
+       }
+       vcap_erase_cache(ri);
+       /* Use the values in the streams to read the VCAP cache */
+       for (sw_idx = 0; sw_idx < ri->size; sw_idx++, addr++) {
+               ri->vctrl->ops->update(ri->ndev, admin, VCAP_CMD_READ,
+                                      VCAP_SEL_ALL, addr);
+               ri->vctrl->ops->cache_read(ri->ndev, admin,
+                                          VCAP_SEL_ENTRY, ent_idx,
+                                          ri->keyset_sw_regs);
+               ri->vctrl->ops->cache_read(ri->ndev, admin,
+                                          VCAP_SEL_ACTION, act_idx,
+                                          ri->actionset_sw_regs);
+               if (sw_idx == 0)
+                       ri->vctrl->ops->cache_read(ri->ndev, admin,
+                                                  VCAP_SEL_COUNTER,
+                                                  ri->counter_id, 0);
+               ent_idx += ri->keyset_sw_regs;
+               act_idx += ri->actionset_sw_regs;
+       }
+       return 0;
+}
+
+static void vcap_show_admin_rule(struct vcap_control *vctrl,
+                                struct vcap_admin *admin,
+                                struct vcap_output_print *out,
+                                struct vcap_rule_internal *ri)
+{
+       ri->counter.value = admin->cache.counter;
+       ri->counter.sticky = admin->cache.sticky;
+       out->prf(out->dst,
+                "rule: %u, addr: [%d,%d], X%d, ctr[%d]: %d, hit: %d\n",
+                ri->data.id, ri->addr, ri->addr + ri->size - 1, ri->size,
+                ri->counter_id, ri->counter.value, ri->counter.sticky);
+       out->prf(out->dst, "  chain_id: %d\n", ri->data.vcap_chain_id);
+       out->prf(out->dst, "  user: %d\n", ri->data.user);
+       out->prf(out->dst, "  priority: %d\n", ri->data.priority);
+       out->prf(out->dst, "  keyset: %s\n",
+                vcap_keyset_name(vctrl, ri->data.keyset));
+       out->prf(out->dst, "  actionset: %s\n",
+                vcap_actionset_name(vctrl, ri->data.actionset));
+}
+
+static void vcap_show_admin_info(struct vcap_control *vctrl,
+                                struct vcap_admin *admin,
+                                struct vcap_output_print *out)
+{
+       const struct vcap_info *vcap = &vctrl->vcaps[admin->vtype];
+
+       out->prf(out->dst, "name: %s\n", vcap->name);
+       out->prf(out->dst, "rows: %d\n", vcap->rows);
+       out->prf(out->dst, "sw_count: %d\n", vcap->sw_count);
+       out->prf(out->dst, "sw_width: %d\n", vcap->sw_width);
+       out->prf(out->dst, "sticky_width: %d\n", vcap->sticky_width);
+       out->prf(out->dst, "act_width: %d\n", vcap->act_width);
+       out->prf(out->dst, "default_cnt: %d\n", vcap->default_cnt);
+       out->prf(out->dst, "require_cnt_dis: %d\n", vcap->require_cnt_dis);
+       out->prf(out->dst, "version: %d\n", vcap->version);
+       out->prf(out->dst, "vtype: %d\n", admin->vtype);
+       out->prf(out->dst, "vinst: %d\n", admin->vinst);
+       out->prf(out->dst, "first_cid: %d\n", admin->first_cid);
+       out->prf(out->dst, "last_cid: %d\n", admin->last_cid);
+       out->prf(out->dst, "lookups: %d\n", admin->lookups);
+       out->prf(out->dst, "first_valid_addr: %d\n", admin->first_valid_addr);
+       out->prf(out->dst, "last_valid_addr: %d\n", admin->last_valid_addr);
+       out->prf(out->dst, "last_used_addr: %d\n", admin->last_used_addr);
+}
+
+static int vcap_show_admin(struct vcap_control *vctrl,
+                          struct vcap_admin *admin,
+                          struct vcap_output_print *out)
+{
+       struct vcap_rule_internal *elem, *ri;
+       int ret = 0;
+
+       vcap_show_admin_info(vctrl, admin, out);
+       list_for_each_entry(elem, &admin->rules, list) {
+               ri = vcap_dup_rule(elem);
+               if (IS_ERR(ri))
+                       goto free_rule;
+               /* Read data from VCAP */
+               ret = vcap_read_rule(ri);
+               if (ret)
+                       goto free_rule;
+               out->prf(out->dst, "\n");
+               vcap_show_admin_rule(vctrl, admin, out, ri);
+free_rule:
+               vcap_free_rule((struct vcap_rule *)ri);
+       }
+       return ret;
+}
+
 static int vcap_show_admin_raw(struct vcap_control *vctrl,
                               struct vcap_admin *admin,
                               struct vcap_output_print *out)
@@ -313,6 +413,19 @@ void vcap_port_debugfs(struct device *dev, struct dentry *parent,
 }
 EXPORT_SYMBOL_GPL(vcap_port_debugfs);
 
+/* Show the full VCAP instance data (rules with all fields) */
+static int vcap_debugfs_show(struct seq_file *m, void *unused)
+{
+       struct vcap_admin_debugfs_info *info = m->private;
+       struct vcap_output_print out = {
+               .prf = (void *)seq_printf,
+               .dst = m,
+       };
+
+       return vcap_show_admin(info->vctrl, info->admin, &out);
+}
+DEFINE_SHOW_ATTRIBUTE(vcap_debugfs);
+
 /* Show the raw VCAP instance data (rules with address info) */
 static int vcap_raw_debugfs_show(struct seq_file *m, void *unused)
 {
@@ -347,6 +460,9 @@ struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
                info->admin = admin;
                debugfs_create_file(name, 0444, dir, info,
                                    &vcap_raw_debugfs_fops);
+               sprintf(name, "%s_%d", vctrl->vcaps[admin->vtype].name,
+                       admin->vinst);
+               debugfs_create_file(name, 0444, dir, info, &vcap_debugfs_fops);
        }
        return dir;
 }
index 1ea25c5d0ca7753a73e54e4bcfc6382ff555fea4..57309de463d7c1bc339e9836ef8bb9bb76d6019a 100644 (file)
@@ -43,6 +43,10 @@ struct vcap_stream_iter {
 
 /* Check that the control has a valid set of callbacks */
 int vcap_api_check(struct vcap_control *ctrl);
+/* Make a shallow copy of the rule without the fields */
+struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri);
+/* Erase the VCAP cache area used or encoding and decoding */
+void vcap_erase_cache(struct vcap_rule_internal *ri);
 
 /* Iterator functionality */
 
@@ -70,4 +74,14 @@ vcap_keyfield_typegroup(struct vcap_control *vctrl,
 const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl,
                                        enum vcap_type vt,
                                        enum vcap_keyfield_set keyset);
+
+/* Actionset and actionfield functionality */
+
+/* Map actionset id to a string with the actionset name */
+const char *vcap_actionset_name(struct vcap_control *vctrl,
+                               enum vcap_actionfield_set actionset);
+/* Map key field id to a string with the key name */
+const char *vcap_actionfield_name(struct vcap_control *vctrl,
+                                 enum vcap_action_field action);
+
 #endif /* __VCAP_API_PRIVATE__ */