* [PATCH net-next v2 1/8] net: microchip: sparx5: Ensure L3 protocol has a default value
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 2/8] net: microchip: sparx5: Ensure VCAP last_used_addr is set back to default Steen Hegelund
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
This ensures that the l3_proto always have a valid value and that any
dissector parsing errors causes the flower rule to be discarded.
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
index a48baeacc1d2..04fc2f3b1979 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
@@ -648,7 +648,11 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
return PTR_ERR(vrule);
vrule->cookie = fco->cookie;
- sparx5_tc_use_dissectors(fco, admin, vrule, &l3_proto);
+
+ l3_proto = ETH_P_ALL;
+ err = sparx5_tc_use_dissectors(fco, admin, vrule, &l3_proto);
+ if (err)
+ goto out;
err = sparx5_tc_add_rule_counter(admin, vrule);
if (err)
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 2/8] net: microchip: sparx5: Ensure VCAP last_used_addr is set back to default
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 1/8] net: microchip: sparx5: Ensure L3 protocol has a default value Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 3/8] net: microchip: sparx5: Add VCAP debugFS support Steen Hegelund
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
This ensures that the last_used_addr in a VCAP instance is returned to the
default value when all rules have been deleted.
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
drivers/net/ethernet/microchip/vcap/vcap_api.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index d12c8ec40fe2..24f4ea1eacb3 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -1249,9 +1249,9 @@ int vcap_del_rule(struct vcap_control *vctrl, struct net_device *ndev, u32 id)
vctrl->ops->init(ndev, admin, admin->last_used_addr, ri->size + gap);
kfree(ri);
- /* Update the last used address */
+ /* Update the last used address, set to default when no rules */
if (list_empty(&admin->rules)) {
- admin->last_used_addr = admin->last_valid_addr;
+ admin->last_used_addr = admin->last_valid_addr + 1;
} else {
elem = list_last_entry(&admin->rules, struct vcap_rule_internal,
list);
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 3/8] net: microchip: sparx5: Add VCAP debugFS support
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 1/8] net: microchip: sparx5: Ensure L3 protocol has a default value Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 2/8] net: microchip: sparx5: Ensure VCAP last_used_addr is set back to default Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 4/8] net: microchip: sparx5: Add raw VCAP debugFS support for the VCAP API Steen Hegelund
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
Add a debugFS root folder for Sparx5 and add a vcap folder underneath with
the VCAP instances and the ports
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
.../net/ethernet/microchip/sparx5/Makefile | 1 +
.../ethernet/microchip/sparx5/sparx5_main.c | 3 +
.../ethernet/microchip/sparx5/sparx5_main.h | 3 +
.../microchip/sparx5/sparx5_vcap_debugfs.c | 23 +++++
.../microchip/sparx5/sparx5_vcap_debugfs.h | 33 +++++++
.../microchip/sparx5/sparx5_vcap_impl.c | 65 ++-----------
.../microchip/sparx5/sparx5_vcap_impl.h | 48 ++++++++++
drivers/net/ethernet/microchip/vcap/Makefile | 1 +
.../net/ethernet/microchip/vcap/vcap_api.h | 13 ++-
.../microchip/vcap/vcap_api_debugfs.c | 93 +++++++++++++++++++
.../microchip/vcap/vcap_api_debugfs.h | 41 ++++++++
.../ethernet/microchip/vcap/vcap_api_kunit.c | 6 +-
12 files changed, 266 insertions(+), 64 deletions(-)
create mode 100644 drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
create mode 100644 drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.h
create mode 100644 drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
create mode 100644 drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h
diff --git a/drivers/net/ethernet/microchip/sparx5/Makefile b/drivers/net/ethernet/microchip/sparx5/Makefile
index cff07b8841bd..d0ed7090aa54 100644
--- a/drivers/net/ethernet/microchip/sparx5/Makefile
+++ b/drivers/net/ethernet/microchip/sparx5/Makefile
@@ -12,6 +12,7 @@ sparx5-switch-y := sparx5_main.o sparx5_packet.o \
sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o sparx5_tc_matchall.o
sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o
+sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o
# Provide include files
ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/vcap
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
index 0b70c00c6eaa..569917abe1c4 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
@@ -760,6 +760,8 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
/* Default values, some from DT */
sparx5->coreclock = SPX5_CORE_CLOCK_DEFAULT;
+ sparx5->debugfs_root = debugfs_create_dir("sparx5", NULL);
+
ports = of_get_child_by_name(np, "ethernet-ports");
if (!ports) {
dev_err(sparx5->dev, "no ethernet-ports child node found\n");
@@ -903,6 +905,7 @@ static int mchp_sparx5_remove(struct platform_device *pdev)
{
struct sparx5 *sparx5 = platform_get_drvdata(pdev);
+ debugfs_remove_recursive(sparx5->debugfs_root);
if (sparx5->xtr_irq) {
disable_irq(sparx5->xtr_irq);
sparx5->xtr_irq = -ENXIO;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
index 5985f2087d7f..4a574cdcb584 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
@@ -17,6 +17,7 @@
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/hrtimer.h>
+#include <linux/debugfs.h>
#include "sparx5_main_regs.h"
@@ -292,6 +293,8 @@ struct sparx5 {
struct vcap_control *vcap_ctrl;
/* PGID allocation map */
u8 pgid_map[PGID_TABLE_SIZE];
+ /* Common root for debugfs */
+ struct dentry *debugfs_root;
};
/* sparx5_switchdev.c */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
new file mode 100644
index 000000000000..2cb061e891c5
--- /dev/null
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip Sparx5 Switch driver VCAP debugFS implementation
+ *
+ * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include "sparx5_vcap_debugfs.h"
+#include "sparx5_main_regs.h"
+#include "sparx5_main.h"
+#include "sparx5_vcap_impl.h"
+#include "sparx5_vcap_ag_api.h"
+
+/* Provide port information via a callback interface */
+int sparx5_port_info(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ /* this will be added later */
+ return 0;
+}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.h b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.h
new file mode 100644
index 000000000000..f9ede03441f2
--- /dev/null
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Microchip Sparx5 Switch driver VCAP implementation
+ *
+ * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#ifndef __SPARX5_VCAP_DEBUGFS_H__
+#define __SPARX5_VCAP_DEBUGFS_H__
+
+#include <linux/netdevice.h>
+
+#include <vcap_api.h>
+#include <vcap_api_client.h>
+
+#if defined(CONFIG_DEBUG_FS)
+
+/* Provide port information via a callback interface */
+int sparx5_port_info(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out);
+
+#else
+
+static inline int sparx5_port_info(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ return 0;
+}
+
+#endif
+
+#endif /* __SPARX5_VCAP_DEBUGFS_H__ */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
index e8f3d030eba2..e70ff1aa6d57 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
@@ -12,10 +12,12 @@
#include "vcap_api.h"
#include "vcap_api_client.h"
+#include "vcap_api_debugfs.h"
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
#include "sparx5_vcap_impl.h"
#include "sparx5_vcap_ag_api.h"
+#include "sparx5_vcap_debugfs.h"
#define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */
#define STREAMSIZE (64 * 4) /* bytes in the VCAP cache area */
@@ -30,54 +32,6 @@
ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \
ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp))
-/* IS2 port keyset selection control */
-
-/* IS2 non-ethernet traffic type keyset generation */
-enum vcap_is2_port_sel_noneth {
- VCAP_IS2_PS_NONETH_MAC_ETYPE,
- VCAP_IS2_PS_NONETH_CUSTOM_1,
- VCAP_IS2_PS_NONETH_CUSTOM_2,
- VCAP_IS2_PS_NONETH_NO_LOOKUP
-};
-
-/* IS2 IPv4 unicast traffic type keyset generation */
-enum vcap_is2_port_sel_ipv4_uc {
- VCAP_IS2_PS_IPV4_UC_MAC_ETYPE,
- VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
- VCAP_IS2_PS_IPV4_UC_IP_7TUPLE,
-};
-
-/* IS2 IPv4 multicast traffic type keyset generation */
-enum vcap_is2_port_sel_ipv4_mc {
- VCAP_IS2_PS_IPV4_MC_MAC_ETYPE,
- VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
- VCAP_IS2_PS_IPV4_MC_IP_7TUPLE,
- VCAP_IS2_PS_IPV4_MC_IP4_VID,
-};
-
-/* IS2 IPv6 unicast traffic type keyset generation */
-enum vcap_is2_port_sel_ipv6_uc {
- VCAP_IS2_PS_IPV6_UC_MAC_ETYPE,
- VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
- VCAP_IS2_PS_IPV6_UC_IP6_STD,
- VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER,
-};
-
-/* IS2 IPv6 multicast traffic type keyset generation */
-enum vcap_is2_port_sel_ipv6_mc {
- VCAP_IS2_PS_IPV6_MC_MAC_ETYPE,
- VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
- VCAP_IS2_PS_IPV6_MC_IP6_VID,
- VCAP_IS2_PS_IPV6_MC_IP6_STD,
- VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER,
-};
-
-/* IS2 ARP traffic type keyset generation */
-enum vcap_is2_port_sel_arp {
- VCAP_IS2_PS_ARP_MAC_ETYPE,
- VCAP_IS2_PS_ARP_ARP,
-};
-
static struct sparx5_vcap_inst {
enum vcap_type vtype; /* type of vcap */
int vinst; /* instance number within the same type */
@@ -548,15 +502,6 @@ static void sparx5_vcap_move(struct net_device *ndev, struct vcap_admin *admin,
sparx5_vcap_wait_super_update(sparx5);
}
-/* Provide port information via a callback interface */
-static int sparx5_port_info(struct net_device *ndev, enum vcap_type vtype,
- int (*pf)(void *out, int arg, const char *fmt, ...),
- void *out, int arg)
-{
- /* this will be added later */
- return 0;
-}
-
/* Enable all lookups in the VCAP instance */
static int sparx5_vcap_enable(struct net_device *ndev,
struct vcap_admin *admin,
@@ -702,6 +647,7 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
const struct sparx5_vcap_inst *cfg;
struct vcap_control *ctrl;
struct vcap_admin *admin;
+ struct dentry *dir;
int err = 0, idx;
/* Create a VCAP control instance that owns the platform specific VCAP
@@ -740,6 +686,11 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
sparx5_vcap_port_key_selection(sparx5, admin);
list_add_tail(&admin->list, &ctrl->list);
}
+ dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl);
+ for (idx = 0; idx < SPX5_PORTS; ++idx)
+ if (sparx5->ports[idx])
+ vcap_port_debugfs(sparx5->dev, dir, ctrl,
+ sparx5->ports[idx]->ndev);
return err;
}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h
index 8e44ebd76b41..8a6b7e3d2618 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h
@@ -17,4 +17,52 @@
#define SPARX5_VCAP_CID_IS2_MAX \
(VCAP_CID_INGRESS_STAGE2_L3 + VCAP_CID_LOOKUP_SIZE - 1) /* IS2 Max */
+/* IS2 port keyset selection control */
+
+/* IS2 non-ethernet traffic type keyset generation */
+enum vcap_is2_port_sel_noneth {
+ VCAP_IS2_PS_NONETH_MAC_ETYPE,
+ VCAP_IS2_PS_NONETH_CUSTOM_1,
+ VCAP_IS2_PS_NONETH_CUSTOM_2,
+ VCAP_IS2_PS_NONETH_NO_LOOKUP
+};
+
+/* IS2 IPv4 unicast traffic type keyset generation */
+enum vcap_is2_port_sel_ipv4_uc {
+ VCAP_IS2_PS_IPV4_UC_MAC_ETYPE,
+ VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
+ VCAP_IS2_PS_IPV4_UC_IP_7TUPLE,
+};
+
+/* IS2 IPv4 multicast traffic type keyset generation */
+enum vcap_is2_port_sel_ipv4_mc {
+ VCAP_IS2_PS_IPV4_MC_MAC_ETYPE,
+ VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
+ VCAP_IS2_PS_IPV4_MC_IP_7TUPLE,
+ VCAP_IS2_PS_IPV4_MC_IP4_VID,
+};
+
+/* IS2 IPv6 unicast traffic type keyset generation */
+enum vcap_is2_port_sel_ipv6_uc {
+ VCAP_IS2_PS_IPV6_UC_MAC_ETYPE,
+ VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
+ VCAP_IS2_PS_IPV6_UC_IP6_STD,
+ VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER,
+};
+
+/* IS2 IPv6 multicast traffic type keyset generation */
+enum vcap_is2_port_sel_ipv6_mc {
+ VCAP_IS2_PS_IPV6_MC_MAC_ETYPE,
+ VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
+ VCAP_IS2_PS_IPV6_MC_IP6_VID,
+ VCAP_IS2_PS_IPV6_MC_IP6_STD,
+ VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER,
+};
+
+/* IS2 ARP traffic type keyset generation */
+enum vcap_is2_port_sel_arp {
+ VCAP_IS2_PS_ARP_MAC_ETYPE,
+ VCAP_IS2_PS_ARP_ARP,
+};
+
#endif /* __SPARX5_VCAP_IMPL_H__ */
diff --git a/drivers/net/ethernet/microchip/vcap/Makefile b/drivers/net/ethernet/microchip/vcap/Makefile
index b377569f92d8..0adb8f5a8735 100644
--- a/drivers/net/ethernet/microchip/vcap/Makefile
+++ b/drivers/net/ethernet/microchip/vcap/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_VCAP) += vcap.o
obj-$(CONFIG_VCAP_KUNIT_TEST) += vcap_model_kunit.o
+vcap-$(CONFIG_DEBUG_FS) += vcap_api_debugfs.o
vcap-y += vcap_api.o
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.h b/drivers/net/ethernet/microchip/vcap/vcap_api.h
index bfb8ad535074..e71e7d3d79c2 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.h
@@ -203,6 +203,13 @@ struct vcap_keyset_list {
enum vcap_keyfield_set *keysets; /* the list of keysets */
};
+/* Client output printf-like function with destination */
+struct vcap_output_print {
+ __printf(2, 3)
+ void (*prf)(void *out, const char *fmt, ...);
+ void *dst;
+};
+
/* Client supplied VCAP callback operations */
struct vcap_operations {
/* validate port keyset operation */
@@ -252,10 +259,8 @@ struct vcap_operations {
/* informational */
int (*port_info)
(struct net_device *ndev,
- enum vcap_type vtype,
- int (*pf)(void *out, int arg, const char *fmt, ...),
- void *out,
- int arg);
+ struct vcap_admin *admin,
+ struct vcap_output_print *out);
/* enable/disable the lookups in a vcap instance */
int (*enable)
(struct net_device *ndev,
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
new file mode 100644
index 000000000000..0c7557b1ed81
--- /dev/null
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip VCAP API debug file system support
+ *
+ * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/netdevice.h>
+
+#include "vcap_api_debugfs.h"
+
+struct vcap_admin_debugfs_info {
+ struct vcap_control *vctrl;
+ struct vcap_admin *admin;
+};
+
+struct vcap_port_debugfs_info {
+ struct vcap_control *vctrl;
+ struct net_device *ndev;
+};
+
+/* Show the port configuration and status */
+static int vcap_port_debugfs_show(struct seq_file *m, void *unused)
+{
+ struct vcap_port_debugfs_info *info = m->private;
+ struct vcap_admin *admin;
+ struct vcap_output_print out = {
+ .prf = (void *)seq_printf,
+ .dst = m,
+ };
+
+ list_for_each_entry(admin, &info->vctrl->list, list) {
+ if (admin->vinst)
+ continue;
+ info->vctrl->ops->port_info(info->ndev, admin, &out);
+ }
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vcap_port_debugfs);
+
+void vcap_port_debugfs(struct device *dev, struct dentry *parent,
+ struct vcap_control *vctrl,
+ struct net_device *ndev)
+{
+ struct vcap_port_debugfs_info *info;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
+
+ info->vctrl = vctrl;
+ info->ndev = ndev;
+ debugfs_create_file(netdev_name(ndev), 0444, parent, info,
+ &vcap_port_debugfs_fops);
+}
+EXPORT_SYMBOL_GPL(vcap_port_debugfs);
+
+/* Show the raw VCAP instance data (rules with address info) */
+static int vcap_raw_debugfs_show(struct seq_file *m, void *unused)
+{
+ /* The output will be added later */
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vcap_raw_debugfs);
+
+struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
+ struct vcap_control *vctrl)
+{
+ struct vcap_admin_debugfs_info *info;
+ struct vcap_admin *admin;
+ struct dentry *dir;
+ char name[50];
+
+ dir = debugfs_create_dir("vcaps", parent);
+ if (PTR_ERR_OR_ZERO(dir))
+ return NULL;
+ list_for_each_entry(admin, &vctrl->list, list) {
+ sprintf(name, "raw_%s_%d", vctrl->vcaps[admin->vtype].name,
+ admin->vinst);
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return NULL;
+ info->vctrl = vctrl;
+ info->admin = admin;
+ debugfs_create_file(name, 0444, dir, info,
+ &vcap_raw_debugfs_fops);
+ }
+ return dir;
+}
+EXPORT_SYMBOL_GPL(vcap_debugfs);
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h
new file mode 100644
index 000000000000..9f2c59b5f6f5
--- /dev/null
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries.
+ * Microchip VCAP API
+ */
+
+#ifndef __VCAP_API_DEBUGFS__
+#define __VCAP_API_DEBUGFS__
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <linux/netdevice.h>
+
+#include "vcap_api.h"
+
+#if defined(CONFIG_DEBUG_FS)
+
+void vcap_port_debugfs(struct device *dev, struct dentry *parent,
+ struct vcap_control *vctrl,
+ struct net_device *ndev);
+
+/* Create a debugFS entry for a vcap instance */
+struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
+ struct vcap_control *vctrl);
+
+#else
+
+static inline void vcap_port_debugfs(struct device *dev, struct dentry *parent,
+ struct vcap_control *vctrl,
+ struct net_device *ndev)
+{
+}
+
+static inline struct dentry *vcap_debugfs(struct device *dev,
+ struct dentry *parent,
+ struct vcap_control *vctrl)
+{
+ return NULL;
+}
+
+#endif
+#endif /* __VCAP_API_DEBUGFS__ */
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
index 6858e44ce4a5..a3dc1b2d029c 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
@@ -204,9 +204,9 @@ static void test_cache_move(struct net_device *ndev, struct vcap_admin *admin,
}
/* Provide port information via a callback interface */
-static int vcap_test_port_info(struct net_device *ndev, enum vcap_type vtype,
- int (*pf)(void *out, int arg, const char *fmt, ...),
- void *out, int arg)
+static int vcap_test_port_info(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
{
return 0;
}
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 4/8] net: microchip: sparx5: Add raw VCAP debugFS support for the VCAP API
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (2 preceding siblings ...)
2022-11-17 21:31 ` [PATCH net-next v2 3/8] net: microchip: sparx5: Add VCAP debugFS support Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 5/8] net: microchip: sparx5: Add VCAP rule " Steen Hegelund
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
This adds support for decoding VCAP rules with a minimum number of
attributes: address, rule size and keyset.
This allows for a quick inspection of a VCAP instance to determine if the
rule are present and in the correct order.
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
.../microchip/sparx5/sparx5_vcap_debugfs.c | 179 +++++++++++-
.../net/ethernet/microchip/vcap/vcap_api.c | 65 ++---
.../microchip/vcap/vcap_api_debugfs.c | 274 +++++++++++++++++-
.../microchip/vcap/vcap_api_private.h | 73 +++++
4 files changed, 535 insertions(+), 56 deletions(-)
create mode 100644 drivers/net/ethernet/microchip/vcap/vcap_api_private.h
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
index 2cb061e891c5..b91e05ffe2f4 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
@@ -13,11 +13,188 @@
#include "sparx5_vcap_impl.h"
#include "sparx5_vcap_ag_api.h"
+static void sparx5_vcap_port_keys(struct sparx5 *sparx5,
+ struct vcap_admin *admin,
+ struct sparx5_port *port,
+ struct vcap_output_print *out)
+{
+ int lookup;
+ u32 value;
+
+ out->prf(out->dst, " port[%02d] (%s): ", port->portno,
+ netdev_name(port->ndev));
+ for (lookup = 0; lookup < admin->lookups; ++lookup) {
+ out->prf(out->dst, "\n Lookup %d: ", lookup);
+
+ /* Get lookup state */
+ value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_CFG(port->portno));
+ out->prf(out->dst, "\n state: ");
+ if (ANA_ACL_VCAP_S2_CFG_SEC_ENA_GET(value))
+ out->prf(out->dst, "on");
+ else
+ out->prf(out->dst, "off");
+
+ /* Get key selection state */
+ value = spx5_rd(sparx5,
+ ANA_ACL_VCAP_S2_KEY_SEL(port->portno, lookup));
+
+ out->prf(out->dst, "\n noneth: ");
+ switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) {
+ case VCAP_IS2_PS_NONETH_MAC_ETYPE:
+ out->prf(out->dst, "mac_etype");
+ break;
+ case VCAP_IS2_PS_NONETH_CUSTOM_1:
+ out->prf(out->dst, "custom1");
+ break;
+ case VCAP_IS2_PS_NONETH_CUSTOM_2:
+ out->prf(out->dst, "custom2");
+ break;
+ case VCAP_IS2_PS_NONETH_NO_LOOKUP:
+ out->prf(out->dst, "none");
+ break;
+ }
+ out->prf(out->dst, "\n ipv4_mc: ");
+ switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) {
+ case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE:
+ out->prf(out->dst, "mac_etype");
+ break;
+ case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER:
+ out->prf(out->dst, "ip4_tcp_udp ip4_other");
+ break;
+ case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE:
+ out->prf(out->dst, "ip_7tuple");
+ break;
+ case VCAP_IS2_PS_IPV4_MC_IP4_VID:
+ out->prf(out->dst, "ip4_vid");
+ break;
+ }
+ out->prf(out->dst, "\n ipv4_uc: ");
+ switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) {
+ case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE:
+ out->prf(out->dst, "mac_etype");
+ break;
+ case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER:
+ out->prf(out->dst, "ip4_tcp_udp ip4_other");
+ break;
+ case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE:
+ out->prf(out->dst, "ip_7tuple");
+ break;
+ }
+ out->prf(out->dst, "\n ipv6_mc: ");
+ switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) {
+ case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE:
+ out->prf(out->dst, "mac_etype");
+ break;
+ case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE:
+ out->prf(out->dst, "ip_7tuple");
+ break;
+ case VCAP_IS2_PS_IPV6_MC_IP6_VID:
+ out->prf(out->dst, "ip6_vid");
+ break;
+ case VCAP_IS2_PS_IPV6_MC_IP6_STD:
+ out->prf(out->dst, "ip6_std");
+ break;
+ case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER:
+ out->prf(out->dst, "ip4_tcp_udp ipv4_other");
+ break;
+ }
+ out->prf(out->dst, "\n ipv6_uc: ");
+ switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) {
+ case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE:
+ out->prf(out->dst, "mac_etype");
+ break;
+ case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE:
+ out->prf(out->dst, "ip_7tuple");
+ break;
+ case VCAP_IS2_PS_IPV6_UC_IP6_STD:
+ out->prf(out->dst, "ip6_std");
+ break;
+ case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER:
+ out->prf(out->dst, "ip4_tcp_udp ip4_other");
+ break;
+ }
+ out->prf(out->dst, "\n arp: ");
+ switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) {
+ case VCAP_IS2_PS_ARP_MAC_ETYPE:
+ out->prf(out->dst, "mac_etype");
+ break;
+ case VCAP_IS2_PS_ARP_ARP:
+ out->prf(out->dst, "arp");
+ break;
+ }
+ }
+ out->prf(out->dst, "\n");
+}
+
+static void sparx5_vcap_port_stickies(struct sparx5 *sparx5,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ int lookup;
+ u32 value;
+
+ out->prf(out->dst, " Sticky bits: ");
+ for (lookup = 0; lookup < admin->lookups; ++lookup) {
+ out->prf(out->dst, "\n Lookup %d: ", lookup);
+ /* Get lookup sticky bits */
+ value = spx5_rd(sparx5, ANA_ACL_SEC_LOOKUP_STICKY(lookup));
+
+ if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_CLM_STICKY_GET(value))
+ out->prf(out->dst, " sel_clm");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_IRLEG_STICKY_GET(value))
+ out->prf(out->dst, " sel_irleg");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_ERLEG_STICKY_GET(value))
+ out->prf(out->dst, " sel_erleg");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_PORT_STICKY_GET(value))
+ out->prf(out->dst, " sel_port");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_CUSTOM2_STICKY_GET(value))
+ out->prf(out->dst, " custom2");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_CUSTOM1_STICKY_GET(value))
+ out->prf(out->dst, " custom1");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_OAM_STICKY_GET(value))
+ out->prf(out->dst, " oam");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_VID_STICKY_GET(value))
+ out->prf(out->dst, " ip6_vid");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_STD_STICKY_GET(value))
+ out->prf(out->dst, " ip6_std");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_TCPUDP_STICKY_GET(value))
+ out->prf(out->dst, " ip6_tcpudp");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP_7TUPLE_STICKY_GET(value))
+ out->prf(out->dst, " ip_7tuple");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_VID_STICKY_GET(value))
+ out->prf(out->dst, " ip4_vid");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_TCPUDP_STICKY_GET(value))
+ out->prf(out->dst, " ip4_tcpudp");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_OTHER_STICKY_GET(value))
+ out->prf(out->dst, " ip4_other");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_ARP_STICKY_GET(value))
+ out->prf(out->dst, " arp");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_SNAP_STICKY_GET(value))
+ out->prf(out->dst, " mac_snap");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_LLC_STICKY_GET(value))
+ out->prf(out->dst, " mac_llc");
+ if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY_GET(value))
+ out->prf(out->dst, " mac_etype");
+ /* Clear stickies */
+ spx5_wr(value, sparx5, ANA_ACL_SEC_LOOKUP_STICKY(lookup));
+ }
+ out->prf(out->dst, "\n");
+}
+
/* Provide port information via a callback interface */
int sparx5_port_info(struct net_device *ndev,
struct vcap_admin *admin,
struct vcap_output_print *out)
{
- /* this will be added later */
+ struct sparx5_port *port = netdev_priv(ndev);
+ struct sparx5 *sparx5 = port->sparx5;
+ const struct vcap_info *vcap;
+ struct vcap_control *vctrl;
+
+ vctrl = sparx5->vcap_ctrl;
+ vcap = &vctrl->vcaps[admin->vtype];
+ out->prf(out->dst, "%s:\n", vcap->name);
+ sparx5_vcap_port_keys(sparx5, admin, port, out);
+ sparx5_vcap_port_stickies(sparx5, admin, out);
return 0;
}
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 24f4ea1eacb3..153e28e124bc 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -6,28 +6,7 @@
#include <linux/types.h>
-#include "vcap_api.h"
-#include "vcap_api_client.h"
-
-#define to_intrule(rule) container_of((rule), struct vcap_rule_internal, data)
-
-/* Private VCAP API rule data */
-struct vcap_rule_internal {
- struct vcap_rule data; /* provided by the client */
- struct list_head list; /* for insertion in the vcap admin list of rules */
- struct vcap_admin *admin; /* vcap hw instance */
- struct net_device *ndev; /* the interface that the rule applies to */
- struct vcap_control *vctrl; /* the client control */
- u32 sort_key; /* defines the position in the VCAP */
- int keyset_sw; /* subwords in a keyset */
- int actionset_sw; /* subwords in an actionset */
- int keyset_sw_regs; /* registers in a subword in an keyset */
- int actionset_sw_regs; /* registers in a subword in an actionset */
- int size; /* the size of the rule: max(entry, action) */
- u32 addr; /* address in the VCAP at insertion */
- u32 counter_id; /* counter id (if a dedicated counter is available) */
- struct vcap_counter counter; /* last read counter value */
-};
+#include "vcap_api_private.h"
/* Moving a rule in the VCAP address space */
struct vcap_rule_move {
@@ -36,16 +15,6 @@ struct vcap_rule_move {
int count; /* blocksize of addresses to move */
};
-/* Bit iterator for the VCAP cache streams */
-struct vcap_stream_iter {
- u32 offset; /* bit offset from the stream start */
- u32 sw_width; /* subword width in bits */
- u32 regs_per_sw; /* registers per subword */
- u32 reg_idx; /* current register index */
- u32 reg_bitpos; /* bit offset in current register */
- const struct vcap_typegroup *tg; /* current typegroup */
-};
-
/* Stores the filter cookie that enabled the port */
struct vcap_enabled_port {
struct list_head list; /* for insertion in enabled ports list */
@@ -53,8 +22,8 @@ struct vcap_enabled_port {
unsigned long cookie; /* filter that enabled the port */
};
-static void vcap_iter_set(struct vcap_stream_iter *itr, int sw_width,
- const struct vcap_typegroup *tg, u32 offset)
+void vcap_iter_set(struct vcap_stream_iter *itr, int sw_width,
+ const struct vcap_typegroup *tg, u32 offset)
{
memset(itr, 0, sizeof(*itr));
itr->offset = offset;
@@ -74,7 +43,7 @@ static void vcap_iter_skip_tg(struct vcap_stream_iter *itr)
}
}
-static void vcap_iter_update(struct vcap_stream_iter *itr)
+void vcap_iter_update(struct vcap_stream_iter *itr)
{
int sw_idx, sw_bitpos;
@@ -86,15 +55,15 @@ static void vcap_iter_update(struct vcap_stream_iter *itr)
itr->reg_bitpos = sw_bitpos % 32;
}
-static void vcap_iter_init(struct vcap_stream_iter *itr, int sw_width,
- const struct vcap_typegroup *tg, u32 offset)
+void vcap_iter_init(struct vcap_stream_iter *itr, int sw_width,
+ const struct vcap_typegroup *tg, u32 offset)
{
vcap_iter_set(itr, sw_width, tg, offset);
vcap_iter_skip_tg(itr);
vcap_iter_update(itr);
}
-static void vcap_iter_next(struct vcap_stream_iter *itr)
+void vcap_iter_next(struct vcap_stream_iter *itr)
{
itr->offset++;
vcap_iter_skip_tg(itr);
@@ -179,9 +148,9 @@ static void vcap_encode_typegroups(u32 *stream, int sw_width,
}
/* Return the list of keyfields for the keyset */
-static const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl,
- enum vcap_type vt,
- enum vcap_keyfield_set keyset)
+const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ enum vcap_keyfield_set keyset)
{
/* Check that the keyset exists in the vcap keyset list */
if (keyset >= vctrl->vcaps[vt].keyfield_set_size)
@@ -190,9 +159,9 @@ static const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl,
}
/* Return the keyset information for the keyset */
-static const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
- enum vcap_type vt,
- enum vcap_keyfield_set keyset)
+const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ enum vcap_keyfield_set keyset)
{
const struct vcap_set *kset;
@@ -206,7 +175,7 @@ static const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
}
/* Return the typegroup table for the matching keyset (using subword size) */
-static const struct vcap_typegroup *
+const struct vcap_typegroup *
vcap_keyfield_typegroup(struct vcap_control *vctrl,
enum vcap_type vt, enum vcap_keyfield_set keyset)
{
@@ -219,8 +188,8 @@ vcap_keyfield_typegroup(struct vcap_control *vctrl,
}
/* Return the number of keyfields in the keyset */
-static int vcap_keyfield_count(struct vcap_control *vctrl,
- enum vcap_type vt, enum vcap_keyfield_set keyset)
+int vcap_keyfield_count(struct vcap_control *vctrl,
+ enum vcap_type vt, enum vcap_keyfield_set keyset)
{
/* Check that the keyset exists in the vcap keyset list */
if (keyset >= vctrl->vcaps[vt].keyfield_set_size)
@@ -515,7 +484,7 @@ static int vcap_encode_rule(struct vcap_rule_internal *ri)
return 0;
}
-static int vcap_api_check(struct vcap_control *ctrl)
+int vcap_api_check(struct vcap_control *ctrl)
{
if (!ctrl) {
pr_err("%s:%d: vcap control is missing\n", __func__, __LINE__);
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
index 0c7557b1ed81..4a1ca26be901 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
@@ -5,11 +5,7 @@
*
*/
-#include <linux/types.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/netdevice.h>
-
+#include "vcap_api_private.h"
#include "vcap_api_debugfs.h"
struct vcap_admin_debugfs_info {
@@ -22,6 +18,265 @@ struct vcap_port_debugfs_info {
struct net_device *ndev;
};
+static bool vcap_bitarray_zero(int width, u8 *value)
+{
+ int bytes = DIV_ROUND_UP(width, BITS_PER_BYTE);
+ u8 total = 0, bmask = 0xff;
+ int rwidth = width;
+ int idx;
+
+ for (idx = 0; idx < bytes; ++idx, rwidth -= BITS_PER_BYTE) {
+ if (rwidth && rwidth < BITS_PER_BYTE)
+ bmask = (1 << rwidth) - 1;
+ total += value[idx] & bmask;
+ }
+ return total == 0;
+}
+
+static bool vcap_get_bit(u32 *stream, struct vcap_stream_iter *itr)
+{
+ u32 mask = BIT(itr->reg_bitpos);
+ u32 *p = &stream[itr->reg_idx];
+
+ return !!(*p & mask);
+}
+
+static void vcap_decode_field(u32 *stream, struct vcap_stream_iter *itr,
+ int width, u8 *value)
+{
+ int idx;
+
+ /* Loop over the field value bits and get the field bits and
+ * set them in the output value byte array
+ */
+ for (idx = 0; idx < width; idx++) {
+ u8 bidx = idx & 0x7;
+
+ /* Decode one field value bit */
+ if (vcap_get_bit(stream, itr))
+ *value |= 1 << bidx;
+ vcap_iter_next(itr);
+ if (bidx == 7)
+ value++;
+ }
+}
+
+/* Verify that the typegroup bits have the correct values */
+static int vcap_verify_typegroups(u32 *stream, int sw_width,
+ const struct vcap_typegroup *tgt, bool mask,
+ int sw_max)
+{
+ struct vcap_stream_iter iter;
+ int sw_cnt, idx;
+
+ vcap_iter_set(&iter, sw_width, tgt, 0);
+ sw_cnt = 0;
+ while (iter.tg->width) {
+ u32 value = 0;
+ u32 tg_value = iter.tg->value;
+
+ if (mask)
+ tg_value = (1 << iter.tg->width) - 1;
+ /* Set position to current typegroup bit */
+ iter.offset = iter.tg->offset;
+ vcap_iter_update(&iter);
+ for (idx = 0; idx < iter.tg->width; idx++) {
+ /* Decode one typegroup bit */
+ if (vcap_get_bit(stream, &iter))
+ value |= 1 << idx;
+ iter.offset++;
+ vcap_iter_update(&iter);
+ }
+ if (value != tg_value)
+ return -EINVAL;
+ iter.tg++; /* next typegroup */
+ sw_cnt++;
+ /* Stop checking more typegroups */
+ if (sw_max && sw_cnt >= sw_max)
+ break;
+ }
+ return 0;
+}
+
+/* Find the subword width of the key typegroup that matches the stream data */
+static int vcap_find_keystream_typegroup_sw(struct vcap_control *vctrl,
+ enum vcap_type vt, u32 *stream,
+ bool mask, int sw_max)
+{
+ const struct vcap_typegroup **tgt;
+ int sw_idx, res;
+
+ tgt = vctrl->vcaps[vt].keyfield_set_typegroups;
+ /* Try the longest subword match first */
+ for (sw_idx = vctrl->vcaps[vt].sw_count; sw_idx >= 0; sw_idx--) {
+ if (!tgt[sw_idx])
+ continue;
+
+ res = vcap_verify_typegroups(stream, vctrl->vcaps[vt].sw_width,
+ tgt[sw_idx], mask, sw_max);
+ if (res == 0)
+ return sw_idx;
+ }
+ return -EINVAL;
+}
+
+/* Verify that the type id in the stream matches the type id of the keyset */
+static bool vcap_verify_keystream_keyset(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ u32 *keystream,
+ u32 *mskstream,
+ enum vcap_keyfield_set keyset)
+{
+ const struct vcap_info *vcap = &vctrl->vcaps[vt];
+ const struct vcap_field *typefld;
+ const struct vcap_typegroup *tgt;
+ const struct vcap_field *fields;
+ struct vcap_stream_iter iter;
+ const struct vcap_set *info;
+ u32 value = 0;
+ u32 mask = 0;
+
+ if (vcap_keyfield_count(vctrl, vt, keyset) == 0)
+ return false;
+
+ info = vcap_keyfieldset(vctrl, vt, keyset);
+ /* Check that the keyset is valid */
+ if (!info)
+ return false;
+
+ /* a type_id of value -1 means that there is no type field */
+ if (info->type_id == (u8)-1)
+ return true;
+
+ /* Get a valid typegroup for the specific keyset */
+ tgt = vcap_keyfield_typegroup(vctrl, vt, keyset);
+ if (!tgt)
+ return false;
+
+ fields = vcap_keyfields(vctrl, vt, keyset);
+ if (!fields)
+ return false;
+
+ typefld = &fields[VCAP_KF_TYPE];
+ vcap_iter_init(&iter, vcap->sw_width, tgt, typefld->offset);
+ vcap_decode_field(mskstream, &iter, typefld->width, (u8 *)&mask);
+ /* no type info if there are no mask bits */
+ if (vcap_bitarray_zero(typefld->width, (u8 *)&mask))
+ return false;
+
+ /* Get the value of the type field in the stream and compare to the
+ * one define in the vcap keyset
+ */
+ vcap_iter_init(&iter, vcap->sw_width, tgt, typefld->offset);
+ vcap_decode_field(keystream, &iter, typefld->width, (u8 *)&value);
+
+ return (value == info->type_id);
+}
+
+/* Verify that the typegroup information, subword count, keyset and type id
+ * are in sync and correct, return the keyset
+ */
+static enum
+vcap_keyfield_set vcap_find_keystream_keyset(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ u32 *keystream,
+ u32 *mskstream,
+ bool mask, int sw_max)
+{
+ const struct vcap_set *keyfield_set;
+ int sw_count, idx;
+ bool res;
+
+ sw_count = vcap_find_keystream_typegroup_sw(vctrl, vt, keystream, mask,
+ sw_max);
+ if (sw_count < 0)
+ return sw_count;
+
+ keyfield_set = vctrl->vcaps[vt].keyfield_set;
+ for (idx = 0; idx < vctrl->vcaps[vt].keyfield_set_size; ++idx) {
+ if (keyfield_set[idx].sw_per_item != sw_count)
+ continue;
+
+ res = vcap_verify_keystream_keyset(vctrl, vt, keystream,
+ mskstream, idx);
+ if (res)
+ return idx;
+ }
+ return -EINVAL;
+}
+
+/* Read key data from a VCAP address and discover if there is a rule keyset
+ * here
+ */
+static int vcap_addr_keyset(struct vcap_control *vctrl,
+ struct net_device *ndev,
+ struct vcap_admin *admin,
+ int addr)
+{
+ enum vcap_type vt = admin->vtype;
+ int keyset_sw_regs, idx;
+ u32 key = 0, mask = 0;
+
+ /* Read the cache at the specified address */
+ keyset_sw_regs = DIV_ROUND_UP(vctrl->vcaps[vt].sw_width, 32);
+ vctrl->ops->update(ndev, admin, VCAP_CMD_READ, VCAP_SEL_ALL, addr);
+ vctrl->ops->cache_read(ndev, admin, VCAP_SEL_ENTRY, 0,
+ keyset_sw_regs);
+ /* Skip uninitialized key/mask entries */
+ for (idx = 0; idx < keyset_sw_regs; ++idx) {
+ key |= ~admin->cache.keystream[idx];
+ mask |= admin->cache.maskstream[idx];
+ }
+ if (key == 0 && mask == 0)
+ return -EINVAL;
+ /* Decode and locate the keyset */
+ return vcap_find_keystream_keyset(vctrl, vt, admin->cache.keystream,
+ admin->cache.maskstream, false, 0);
+}
+
+static int vcap_show_admin_raw(struct vcap_control *vctrl,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ enum vcap_type vt = admin->vtype;
+ struct vcap_rule_internal *ri;
+ const struct vcap_set *info;
+ int keyset;
+ int addr;
+ int ret;
+
+ if (list_empty(&admin->rules))
+ return 0;
+
+ ret = vcap_api_check(vctrl);
+ if (ret)
+ return ret;
+
+ ri = list_first_entry(&admin->rules, struct vcap_rule_internal, list);
+
+ /* Go from higher to lower addresses searching for a keyset */
+ for (addr = admin->last_valid_addr; addr >= admin->first_valid_addr;
+ --addr) {
+ keyset = vcap_addr_keyset(vctrl, ri->ndev, admin, addr);
+ if (keyset < 0)
+ continue;
+ info = vcap_keyfieldset(vctrl, vt, keyset);
+ if (!info)
+ continue;
+ if (addr % info->sw_per_item)
+ pr_info("addr: %d X%d error rule, keyset: %s\n",
+ addr,
+ info->sw_per_item,
+ vcap_keyset_name(vctrl, keyset));
+ else
+ out->prf(out->dst, " addr: %d, X%d rule, keyset: %s\n",
+ addr,
+ info->sw_per_item,
+ vcap_keyset_name(vctrl, keyset));
+ }
+ return 0;
+}
+
/* Show the port configuration and status */
static int vcap_port_debugfs_show(struct seq_file *m, void *unused)
{
@@ -61,8 +316,13 @@ EXPORT_SYMBOL_GPL(vcap_port_debugfs);
/* Show the raw VCAP instance data (rules with address info) */
static int vcap_raw_debugfs_show(struct seq_file *m, void *unused)
{
- /* The output will be added later */
- return 0;
+ struct vcap_admin_debugfs_info *info = m->private;
+ struct vcap_output_print out = {
+ .prf = (void *)seq_printf,
+ .dst = m,
+ };
+
+ return vcap_show_admin_raw(info->vctrl, info->admin, &out);
}
DEFINE_SHOW_ATTRIBUTE(vcap_raw_debugfs);
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
new file mode 100644
index 000000000000..1ea25c5d0ca7
--- /dev/null
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries.
+ * Microchip VCAP API
+ */
+
+#ifndef __VCAP_API_PRIVATE__
+#define __VCAP_API_PRIVATE__
+
+#include <linux/types.h>
+
+#include "vcap_api.h"
+#include "vcap_api_client.h"
+
+#define to_intrule(rule) container_of((rule), struct vcap_rule_internal, data)
+
+/* Private VCAP API rule data */
+struct vcap_rule_internal {
+ struct vcap_rule data; /* provided by the client */
+ struct list_head list; /* the vcap admin list of rules */
+ struct vcap_admin *admin; /* vcap hw instance */
+ struct net_device *ndev; /* the interface that the rule applies to */
+ struct vcap_control *vctrl; /* the client control */
+ u32 sort_key; /* defines the position in the VCAP */
+ int keyset_sw; /* subwords in a keyset */
+ int actionset_sw; /* subwords in an actionset */
+ int keyset_sw_regs; /* registers in a subword in an keyset */
+ int actionset_sw_regs; /* registers in a subword in an actionset */
+ int size; /* the size of the rule: max(entry, action) */
+ u32 addr; /* address in the VCAP at insertion */
+ u32 counter_id; /* counter id (if a dedicated counter is available) */
+ struct vcap_counter counter; /* last read counter value */
+};
+
+/* Bit iterator for the VCAP cache streams */
+struct vcap_stream_iter {
+ u32 offset; /* bit offset from the stream start */
+ u32 sw_width; /* subword width in bits */
+ u32 regs_per_sw; /* registers per subword */
+ u32 reg_idx; /* current register index */
+ u32 reg_bitpos; /* bit offset in current register */
+ const struct vcap_typegroup *tg; /* current typegroup */
+};
+
+/* Check that the control has a valid set of callbacks */
+int vcap_api_check(struct vcap_control *ctrl);
+
+/* Iterator functionality */
+
+void vcap_iter_init(struct vcap_stream_iter *itr, int sw_width,
+ const struct vcap_typegroup *tg, u32 offset);
+void vcap_iter_next(struct vcap_stream_iter *itr);
+void vcap_iter_set(struct vcap_stream_iter *itr, int sw_width,
+ const struct vcap_typegroup *tg, u32 offset);
+void vcap_iter_update(struct vcap_stream_iter *itr);
+
+/* Keyset and keyfield functionality */
+
+/* Return the keyset information for the keyset */
+const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ enum vcap_keyfield_set keyset);
+/* Return the number of keyfields in the keyset */
+int vcap_keyfield_count(struct vcap_control *vctrl,
+ enum vcap_type vt, enum vcap_keyfield_set keyset);
+/* Return the typegroup table for the matching keyset (using subword size) */
+const struct vcap_typegroup *
+vcap_keyfield_typegroup(struct vcap_control *vctrl,
+ enum vcap_type vt, enum vcap_keyfield_set keyset);
+/* Return the list of keyfields for the keyset */
+const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ enum vcap_keyfield_set keyset);
+#endif /* __VCAP_API_PRIVATE__ */
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 5/8] net: microchip: sparx5: Add VCAP rule debugFS support for the VCAP API
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (3 preceding siblings ...)
2022-11-17 21:31 ` [PATCH net-next v2 4/8] net: microchip: sparx5: Add raw VCAP debugFS support for the VCAP API Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 6/8] net: microchip: sparx5: Add VCAP debugFS key/action " Steen Hegelund
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
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>
---
.../net/ethernet/microchip/vcap/vcap_api.c | 15 ++-
.../microchip/vcap/vcap_api_debugfs.c | 116 ++++++++++++++++++
.../microchip/vcap/vcap_api_private.h | 14 +++
3 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 153e28e124bc..3da714e9639c 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -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];
}
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
index 4a1ca26be901..b4bc32a08f2c 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
@@ -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;
}
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
index 1ea25c5d0ca7..57309de463d7 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
@@ -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__ */
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 6/8] net: microchip: sparx5: Add VCAP debugFS key/action support for the VCAP API
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (4 preceding siblings ...)
2022-11-17 21:31 ` [PATCH net-next v2 5/8] net: microchip: sparx5: Add VCAP rule " Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 7/8] net: microchip: sparx5: Add VCAP locking to protect rules Steen Hegelund
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
This add support for displaying the keys and actions in a rule.
The keys and action display format will be determined by the size and the
type of the key or action. The longer keys will typically be displayed as a
hexadecimal byte array.
The actionset is not decoded in full as the Sparx5 IS2 only has one
supported action, so this will be added later with other VCAP types.
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
.../net/ethernet/microchip/vcap/vcap_api.c | 12 +-
.../microchip/vcap/vcap_api_debugfs.c | 315 +++++++++++++++++-
.../microchip/vcap/vcap_api_private.h | 16 +
3 files changed, 333 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 3da714e9639c..3415605350c9 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -316,7 +316,7 @@ static int vcap_encode_rule_keyset(struct vcap_rule_internal *ri)
}
/* Return the list of actionfields for the actionset */
-static const struct vcap_field *
+const struct vcap_field *
vcap_actionfields(struct vcap_control *vctrl,
enum vcap_type vt, enum vcap_actionfield_set actionset)
{
@@ -326,7 +326,7 @@ vcap_actionfields(struct vcap_control *vctrl,
return vctrl->vcaps[vt].actionfield_set_map[actionset];
}
-static const struct vcap_set *
+const struct vcap_set *
vcap_actionfieldset(struct vcap_control *vctrl,
enum vcap_type vt, enum vcap_actionfield_set actionset)
{
@@ -342,7 +342,7 @@ vcap_actionfieldset(struct vcap_control *vctrl,
}
/* Return the typegroup table for the matching actionset (using subword size) */
-static const struct vcap_typegroup *
+const struct vcap_typegroup *
vcap_actionfield_typegroup(struct vcap_control *vctrl,
enum vcap_type vt, enum vcap_actionfield_set actionset)
{
@@ -355,9 +355,9 @@ vcap_actionfield_typegroup(struct vcap_control *vctrl,
}
/* Return the number of actionfields in the actionset */
-static int vcap_actionfield_count(struct vcap_control *vctrl,
- enum vcap_type vt,
- enum vcap_actionfield_set actionset)
+int vcap_actionfield_count(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ enum vcap_actionfield_set actionset)
{
/* Check that the actionset exists in the vcap actionset list */
if (actionset >= vctrl->vcaps[vt].actionfield_set_size)
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
index b4bc32a08f2c..981c4ed6ad7d 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
@@ -120,6 +120,28 @@ static int vcap_find_keystream_typegroup_sw(struct vcap_control *vctrl,
return -EINVAL;
}
+/* Find the subword width of the action typegroup that matches the stream data
+ */
+static int vcap_find_actionstream_typegroup_sw(struct vcap_control *vctrl,
+ enum vcap_type vt, u32 *stream,
+ int sw_max)
+{
+ const struct vcap_typegroup **tgt;
+ int sw_idx, res;
+
+ tgt = vctrl->vcaps[vt].actionfield_set_typegroups;
+ /* Try the longest subword match first */
+ for (sw_idx = vctrl->vcaps[vt].sw_count; sw_idx >= 0; sw_idx--) {
+ if (!tgt[sw_idx])
+ continue;
+ res = vcap_verify_typegroups(stream, vctrl->vcaps[vt].act_width,
+ tgt[sw_idx], false, sw_max);
+ if (res == 0)
+ return sw_idx;
+ }
+ return -EINVAL;
+}
+
/* Verify that the type id in the stream matches the type id of the keyset */
static bool vcap_verify_keystream_keyset(struct vcap_control *vctrl,
enum vcap_type vt,
@@ -205,6 +227,75 @@ vcap_keyfield_set vcap_find_keystream_keyset(struct vcap_control *vctrl,
return -EINVAL;
}
+/* Read key data from a VCAP address and discover if there is a rule keyset
+ * here
+ */
+static bool
+vcap_verify_actionstream_actionset(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ u32 *actionstream,
+ enum vcap_actionfield_set actionset)
+{
+ const struct vcap_typegroup *tgt;
+ const struct vcap_field *fields;
+ const struct vcap_set *info;
+
+ if (vcap_actionfield_count(vctrl, vt, actionset) == 0)
+ return false;
+
+ info = vcap_actionfieldset(vctrl, vt, actionset);
+ /* Check that the actionset is valid */
+ if (!info)
+ return false;
+
+ /* a type_id of value -1 means that there is no type field */
+ if (info->type_id == (u8)-1)
+ return true;
+
+ /* Get a valid typegroup for the specific actionset */
+ tgt = vcap_actionfield_typegroup(vctrl, vt, actionset);
+ if (!tgt)
+ return false;
+
+ fields = vcap_actionfields(vctrl, vt, actionset);
+ if (!fields)
+ return false;
+
+ /* Later this will be expanded with a check of the type id */
+ return true;
+}
+
+/* Verify that the typegroup information, subword count, actionset and type id
+ * are in sync and correct, return the actionset
+ */
+static enum vcap_actionfield_set
+vcap_find_actionstream_actionset(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ u32 *stream,
+ int sw_max)
+{
+ const struct vcap_set *actionfield_set;
+ int sw_count, idx;
+ bool res;
+
+ sw_count = vcap_find_actionstream_typegroup_sw(vctrl, vt, stream,
+ sw_max);
+ if (sw_count < 0)
+ return sw_count;
+
+ actionfield_set = vctrl->vcaps[vt].actionfield_set;
+ for (idx = 0; idx < vctrl->vcaps[vt].actionfield_set_size; ++idx) {
+ if (actionfield_set[idx].sw_per_item != sw_count)
+ continue;
+
+ res = vcap_verify_actionstream_actionset(vctrl, vt,
+ stream, idx);
+ if (res)
+ return idx;
+ }
+ return -EINVAL;
+}
+
/* Read key data from a VCAP address and discover if there is a rule keyset
* here
*/
@@ -265,6 +356,224 @@ static int vcap_read_rule(struct vcap_rule_internal *ri)
return 0;
}
+/* Dump the keyfields value and mask values */
+static void vcap_debugfs_show_rule_keyfield(struct vcap_control *vctrl,
+ struct vcap_output_print *out,
+ enum vcap_key_field key,
+ const struct vcap_field *keyfield,
+ u8 *value, u8 *mask)
+{
+ bool hex = false;
+ int idx, bytes;
+
+ out->prf(out->dst, " %s: W%d: ", vcap_keyfield_name(vctrl, key),
+ keyfield[key].width);
+
+ switch (keyfield[key].type) {
+ case VCAP_FIELD_BIT:
+ out->prf(out->dst, "%d/%d", value[0], mask[0]);
+ break;
+ case VCAP_FIELD_U32:
+ if (key == VCAP_KF_L3_IP4_SIP || key == VCAP_KF_L3_IP4_DIP) {
+ out->prf(out->dst, "%pI4h/%pI4h", value, mask);
+ } else if (key == VCAP_KF_ETYPE ||
+ key == VCAP_KF_IF_IGR_PORT_MASK) {
+ hex = true;
+ } else {
+ u32 fmsk = (1 << keyfield[key].width) - 1;
+ u32 val = *(u32 *)value;
+ u32 msk = *(u32 *)mask;
+
+ out->prf(out->dst, "%u/%u", val & fmsk, msk & fmsk);
+ }
+ break;
+ case VCAP_FIELD_U48:
+ if (key == VCAP_KF_L2_SMAC || key == VCAP_KF_L2_DMAC)
+ out->prf(out->dst, "%pMR/%pMR", value, mask);
+ else
+ hex = true;
+ break;
+ case VCAP_FIELD_U56:
+ case VCAP_FIELD_U64:
+ case VCAP_FIELD_U72:
+ case VCAP_FIELD_U112:
+ hex = true;
+ break;
+ case VCAP_FIELD_U128:
+ if (key == VCAP_KF_L3_IP6_SIP || key == VCAP_KF_L3_IP6_DIP) {
+ u8 nvalue[16], nmask[16];
+
+ vcap_netbytes_copy(nvalue, value, sizeof(nvalue));
+ vcap_netbytes_copy(nmask, mask, sizeof(nmask));
+ out->prf(out->dst, "%pI6/%pI6", nvalue, nmask);
+ } else {
+ hex = true;
+ }
+ break;
+ }
+ if (hex) {
+ bytes = DIV_ROUND_UP(keyfield[key].width, BITS_PER_BYTE);
+ out->prf(out->dst, "0x");
+ for (idx = 0; idx < bytes; ++idx)
+ out->prf(out->dst, "%02x", value[bytes - idx - 1]);
+ out->prf(out->dst, "/0x");
+ for (idx = 0; idx < bytes; ++idx)
+ out->prf(out->dst, "%02x", mask[bytes - idx - 1]);
+ }
+ out->prf(out->dst, "\n");
+}
+
+static void
+vcap_debugfs_show_rule_actionfield(struct vcap_control *vctrl,
+ struct vcap_output_print *out,
+ enum vcap_action_field action,
+ const struct vcap_field *actionfield,
+ u8 *value)
+{
+ bool hex = false;
+ int idx, bytes;
+ u32 fmsk, val;
+
+ out->prf(out->dst, " %s: W%d: ",
+ vcap_actionfield_name(vctrl, action),
+ actionfield[action].width);
+
+ switch (actionfield[action].type) {
+ case VCAP_FIELD_BIT:
+ out->prf(out->dst, "%d", value[0]);
+ break;
+ case VCAP_FIELD_U32:
+ fmsk = (1 << actionfield[action].width) - 1;
+ val = *(u32 *)value;
+ out->prf(out->dst, "%u", val & fmsk);
+ break;
+ case VCAP_FIELD_U48:
+ case VCAP_FIELD_U56:
+ case VCAP_FIELD_U64:
+ case VCAP_FIELD_U72:
+ case VCAP_FIELD_U112:
+ case VCAP_FIELD_U128:
+ hex = true;
+ break;
+ }
+ if (hex) {
+ bytes = DIV_ROUND_UP(actionfield[action].width, BITS_PER_BYTE);
+ out->prf(out->dst, "0x");
+ for (idx = 0; idx < bytes; ++idx)
+ out->prf(out->dst, "%02x", value[bytes - idx - 1]);
+ }
+ out->prf(out->dst, "\n");
+}
+
+static int vcap_debugfs_show_rule_keyset(struct vcap_rule_internal *ri,
+ struct vcap_output_print *out)
+{
+ struct vcap_control *vctrl = ri->vctrl;
+ struct vcap_stream_iter kiter, miter;
+ struct vcap_admin *admin = ri->admin;
+ const struct vcap_field *keyfield;
+ enum vcap_type vt = admin->vtype;
+ const struct vcap_typegroup *tgt;
+ enum vcap_keyfield_set keyset;
+ int idx, res, keyfield_count;
+ u32 *maskstream;
+ u32 *keystream;
+ u8 value[16];
+ u8 mask[16];
+
+ keystream = admin->cache.keystream;
+ maskstream = admin->cache.maskstream;
+ res = vcap_find_keystream_keyset(vctrl, vt, keystream, maskstream,
+ false, 0);
+ if (res < 0) {
+ pr_err("%s:%d: could not find valid keyset: %d\n",
+ __func__, __LINE__, res);
+ return -EINVAL;
+ }
+ keyset = res;
+ out->prf(out->dst, " keyset: %s\n",
+ vcap_keyset_name(vctrl, ri->data.keyset));
+ out->prf(out->dst, " keyset_sw: %d\n", ri->keyset_sw);
+ out->prf(out->dst, " keyset_sw_regs: %d\n", ri->keyset_sw_regs);
+ keyfield_count = vcap_keyfield_count(vctrl, vt, keyset);
+ keyfield = vcap_keyfields(vctrl, vt, keyset);
+ tgt = vcap_keyfield_typegroup(vctrl, vt, keyset);
+ /* Start decoding the streams */
+ for (idx = 0; idx < keyfield_count; ++idx) {
+ if (keyfield[idx].width <= 0)
+ continue;
+ /* First get the mask */
+ memset(mask, 0, DIV_ROUND_UP(keyfield[idx].width, 8));
+ vcap_iter_init(&miter, vctrl->vcaps[vt].sw_width, tgt,
+ keyfield[idx].offset);
+ vcap_decode_field(maskstream, &miter, keyfield[idx].width,
+ mask);
+ /* Skip if no mask bits are set */
+ if (vcap_bitarray_zero(keyfield[idx].width, mask))
+ continue;
+ /* Get the key */
+ memset(value, 0, DIV_ROUND_UP(keyfield[idx].width, 8));
+ vcap_iter_init(&kiter, vctrl->vcaps[vt].sw_width, tgt,
+ keyfield[idx].offset);
+ vcap_decode_field(keystream, &kiter, keyfield[idx].width,
+ value);
+ vcap_debugfs_show_rule_keyfield(vctrl, out, idx, keyfield,
+ value, mask);
+ }
+ return 0;
+}
+
+static int vcap_debugfs_show_rule_actionset(struct vcap_rule_internal *ri,
+ struct vcap_output_print *out)
+{
+ struct vcap_control *vctrl = ri->vctrl;
+ struct vcap_admin *admin = ri->admin;
+ const struct vcap_field *actionfield;
+ enum vcap_actionfield_set actionset;
+ enum vcap_type vt = admin->vtype;
+ const struct vcap_typegroup *tgt;
+ struct vcap_stream_iter iter;
+ int idx, res, actfield_count;
+ u32 *actstream;
+ u8 value[16];
+ bool no_bits;
+
+ actstream = admin->cache.actionstream;
+ res = vcap_find_actionstream_actionset(vctrl, vt, actstream, 0);
+ if (res < 0) {
+ pr_err("%s:%d: could not find valid actionset: %d\n",
+ __func__, __LINE__, res);
+ return -EINVAL;
+ }
+ actionset = res;
+ out->prf(out->dst, " actionset: %s\n",
+ vcap_actionset_name(vctrl, ri->data.actionset));
+ out->prf(out->dst, " actionset_sw: %d\n", ri->actionset_sw);
+ out->prf(out->dst, " actionset_sw_regs: %d\n", ri->actionset_sw_regs);
+ actfield_count = vcap_actionfield_count(vctrl, vt, actionset);
+ actionfield = vcap_actionfields(vctrl, vt, actionset);
+ tgt = vcap_actionfield_typegroup(vctrl, vt, actionset);
+ /* Start decoding the stream */
+ for (idx = 0; idx < actfield_count; ++idx) {
+ if (actionfield[idx].width <= 0)
+ continue;
+ /* Get the action */
+ memset(value, 0, DIV_ROUND_UP(actionfield[idx].width, 8));
+ vcap_iter_init(&iter, vctrl->vcaps[vt].act_width, tgt,
+ actionfield[idx].offset);
+ vcap_decode_field(actstream, &iter, actionfield[idx].width,
+ value);
+ /* Skip if no bits are set */
+ no_bits = vcap_bitarray_zero(actionfield[idx].width, value);
+ if (no_bits)
+ continue;
+ /* Later the action id will also be checked */
+ vcap_debugfs_show_rule_actionfield(vctrl, out, idx, actionfield,
+ value);
+ }
+ return 0;
+}
+
static void vcap_show_admin_rule(struct vcap_control *vctrl,
struct vcap_admin *admin,
struct vcap_output_print *out,
@@ -279,10 +588,8 @@ static void vcap_show_admin_rule(struct vcap_control *vctrl,
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));
+ vcap_debugfs_show_rule_keyset(ri, out);
+ vcap_debugfs_show_rule_actionset(ri, out);
}
static void vcap_show_admin_info(struct vcap_control *vctrl,
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
index 57309de463d7..18a9a0cd9606 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h
@@ -77,6 +77,22 @@ const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl,
/* Actionset and actionfield functionality */
+/* Return the actionset information for the actionset */
+const struct vcap_set *
+vcap_actionfieldset(struct vcap_control *vctrl,
+ enum vcap_type vt, enum vcap_actionfield_set actionset);
+/* Return the number of actionfields in the actionset */
+int vcap_actionfield_count(struct vcap_control *vctrl,
+ enum vcap_type vt,
+ enum vcap_actionfield_set actionset);
+/* Return the typegroup table for the matching actionset (using subword size) */
+const struct vcap_typegroup *
+vcap_actionfield_typegroup(struct vcap_control *vctrl, enum vcap_type vt,
+ enum vcap_actionfield_set actionset);
+/* Return the list of actionfields for the actionset */
+const struct vcap_field *
+vcap_actionfields(struct vcap_control *vctrl,
+ enum vcap_type vt, enum vcap_actionfield_set actionset);
/* Map actionset id to a string with the actionset name */
const char *vcap_actionset_name(struct vcap_control *vctrl,
enum vcap_actionfield_set actionset);
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 7/8] net: microchip: sparx5: Add VCAP locking to protect rules
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (5 preceding siblings ...)
2022-11-17 21:31 ` [PATCH net-next v2 6/8] net: microchip: sparx5: Add VCAP debugFS key/action " Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-17 21:31 ` [PATCH net-next v2 8/8] net: microchip: sparx5: Add VCAP debugfs KUNIT test Steen Hegelund
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
This ensures that the VCAP cache and the lists maintained in the VCAP
instance is protected when accessed by different clients.
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
.../net/ethernet/microchip/sparx5/sparx5_vcap_impl.c | 2 ++
drivers/net/ethernet/microchip/vcap/vcap_api.c | 10 ++++++++++
drivers/net/ethernet/microchip/vcap/vcap_api.h | 1 +
drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c | 2 ++
4 files changed, 15 insertions(+)
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
index e70ff1aa6d57..0c4d4e6d51e6 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
@@ -579,6 +579,7 @@ static void sparx5_vcap_admin_free(struct vcap_admin *admin)
{
if (!admin)
return;
+ mutex_destroy(&admin->lock);
kfree(admin->cache.keystream);
kfree(admin->cache.maskstream);
kfree(admin->cache.actionstream);
@@ -598,6 +599,7 @@ sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl,
INIT_LIST_HEAD(&admin->list);
INIT_LIST_HEAD(&admin->rules);
INIT_LIST_HEAD(&admin->enabled);
+ mutex_init(&admin->lock);
admin->vtype = cfg->vtype;
admin->vinst = cfg->vinst;
admin->lookups = cfg->lookups;
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 3415605350c9..ac7a32ff755e 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -1054,6 +1054,7 @@ int vcap_add_rule(struct vcap_rule *rule)
if (ret)
return ret;
/* Insert the new rule in the list of vcap rules */
+ mutex_lock(&ri->admin->lock);
ret = vcap_insert_rule(ri, &move);
if (ret < 0) {
pr_err("%s:%d: could not insert rule in vcap list: %d\n",
@@ -1072,6 +1073,7 @@ int vcap_add_rule(struct vcap_rule *rule)
if (ret)
pr_err("%s:%d: rule write error: %d\n", __func__, __LINE__, ret);
out:
+ mutex_unlock(&ri->admin->lock);
return ret;
}
EXPORT_SYMBOL_GPL(vcap_add_rule);
@@ -1221,9 +1223,11 @@ int vcap_del_rule(struct vcap_control *vctrl, struct net_device *ndev, u32 id)
gap = vcap_fill_rule_gap(ri);
/* Delete the rule from the list of rules and the cache */
+ mutex_lock(&admin->lock);
list_del(&ri->list);
vctrl->ops->init(ndev, admin, admin->last_used_addr, ri->size + gap);
kfree(ri);
+ mutex_unlock(&admin->lock);
/* Update the last used address, set to default when no rules */
if (list_empty(&admin->rules)) {
@@ -1246,6 +1250,8 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin)
if (ret)
return ret;
+
+ mutex_lock(&admin->lock);
list_for_each_entry_safe(ri, next_ri, &admin->rules, list) {
vctrl->ops->init(ri->ndev, admin, ri->addr, ri->size);
list_del(&ri->list);
@@ -1258,6 +1264,7 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin)
list_del(&eport->list);
kfree(eport);
}
+ mutex_unlock(&admin->lock);
return 0;
}
@@ -1687,10 +1694,13 @@ int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
if (chain_id) {
if (vcap_is_enabled(admin, ndev, cookie))
return -EADDRINUSE;
+ mutex_lock(&admin->lock);
vcap_enable(admin, ndev, cookie);
} else {
+ mutex_lock(&admin->lock);
vcap_disable(admin, ndev, cookie);
}
+ mutex_unlock(&admin->lock);
return 0;
}
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.h b/drivers/net/ethernet/microchip/vcap/vcap_api.h
index e71e7d3d79c2..f4a5ba5ffa87 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.h
@@ -167,6 +167,7 @@ struct vcap_admin {
struct list_head list; /* for insertion in vcap_control */
struct list_head rules; /* list of rules */
struct list_head enabled; /* list of enabled ports */
+ struct mutex lock; /* control access to rules */
enum vcap_type vtype; /* type of vcap */
int vinst; /* instance number within the same type */
int first_cid; /* first chain id in this vcap */
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
index 981c4ed6ad7d..891034e349de 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
@@ -625,6 +625,7 @@ static int vcap_show_admin(struct vcap_control *vctrl,
int ret = 0;
vcap_show_admin_info(vctrl, admin, out);
+ mutex_lock(&admin->lock);
list_for_each_entry(elem, &admin->rules, list) {
ri = vcap_dup_rule(elem);
if (IS_ERR(ri))
@@ -638,6 +639,7 @@ static int vcap_show_admin(struct vcap_control *vctrl,
free_rule:
vcap_free_rule((struct vcap_rule *)ri);
}
+ mutex_unlock(&admin->lock);
return ret;
}
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next v2 8/8] net: microchip: sparx5: Add VCAP debugfs KUNIT test
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (6 preceding siblings ...)
2022-11-17 21:31 ` [PATCH net-next v2 7/8] net: microchip: sparx5: Add VCAP locking to protect rules Steen Hegelund
@ 2022-11-17 21:31 ` Steen Hegelund
2022-11-21 11:40 ` [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 patchwork-bot+netdevbpf
2022-11-21 19:01 ` Jakub Kicinski
9 siblings, 0 replies; 13+ messages in thread
From: Steen Hegelund @ 2022-11-17 21:31 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Steen Hegelund, UNGLinuxDriver, Randy Dunlap, Casper Andersson,
Russell King, Wan Jiabing, Nathan Huckleberry, linux-kernel,
netdev, linux-arm-kernel, Steen Hegelund, Daniel Machon,
Horatiu Vultur, Lars Povlsen
This tests the functionality of the debugFS support:
- finding valid keyset on an address
- raw VCAP output
- full rule VCAP output
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
drivers/net/ethernet/microchip/vcap/Kconfig | 1 +
.../microchip/vcap/vcap_api_debugfs.c | 4 +
.../microchip/vcap/vcap_api_debugfs_kunit.c | 545 ++++++++++++++++++
.../ethernet/microchip/vcap/vcap_api_kunit.c | 6 +-
4 files changed, 553 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c
diff --git a/drivers/net/ethernet/microchip/vcap/Kconfig b/drivers/net/ethernet/microchip/vcap/Kconfig
index 1af30a358a15..97f43fd4473f 100644
--- a/drivers/net/ethernet/microchip/vcap/Kconfig
+++ b/drivers/net/ethernet/microchip/vcap/Kconfig
@@ -40,6 +40,7 @@ config VCAP_KUNIT_TEST
bool "KUnit test for VCAP library" if !KUNIT_ALL_TESTS
depends on KUNIT
depends on KUNIT=y && VCAP=y && y
+ select DEBUG_FS
default KUNIT_ALL_TESTS
help
This builds unit tests for the VCAP library.
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
index 891034e349de..d9c7ca988b76 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
@@ -776,3 +776,7 @@ struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
return dir;
}
EXPORT_SYMBOL_GPL(vcap_debugfs);
+
+#ifdef CONFIG_VCAP_KUNIT_TEST
+#include "vcap_api_debugfs_kunit.c"
+#endif
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c
new file mode 100644
index 000000000000..ed455dad3a14
--- /dev/null
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries.
+ * Microchip VCAP API kunit test suite
+ */
+
+#include <kunit/test.h>
+#include "vcap_api.h"
+#include "vcap_api_client.h"
+#include "vcap_api_debugfs.h"
+#include "vcap_model_kunit.h"
+
+/* First we have the test infrastructure that emulates the platform
+ * implementation
+ */
+#define TEST_BUF_CNT 100
+#define TEST_BUF_SZ 350
+#define STREAMWSIZE 64
+
+static u32 test_updateaddr[STREAMWSIZE] = {};
+static int test_updateaddridx;
+static int test_cache_erase_count;
+static u32 test_init_start;
+static u32 test_init_count;
+static u32 test_hw_counter_id;
+static struct vcap_cache_data test_hw_cache;
+static struct net_device test_netdev = {};
+static int test_move_addr;
+static int test_move_offset;
+static int test_move_count;
+static char test_pr_buffer[TEST_BUF_CNT][TEST_BUF_SZ];
+static int test_pr_bufferidx;
+static int test_pr_idx;
+
+/* Callback used by the VCAP API */
+static enum vcap_keyfield_set test_val_keyset(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_rule *rule,
+ struct vcap_keyset_list *kslist,
+ u16 l3_proto)
+{
+ int idx;
+
+ if (kslist->cnt > 0) {
+ switch (admin->vtype) {
+ case VCAP_TYPE_IS0:
+ for (idx = 0; idx < kslist->cnt; idx++) {
+ if (kslist->keysets[idx] == VCAP_KFS_ETAG)
+ return kslist->keysets[idx];
+ if (kslist->keysets[idx] ==
+ VCAP_KFS_PURE_5TUPLE_IP4)
+ return kslist->keysets[idx];
+ if (kslist->keysets[idx] ==
+ VCAP_KFS_NORMAL_5TUPLE_IP4)
+ return kslist->keysets[idx];
+ if (kslist->keysets[idx] ==
+ VCAP_KFS_NORMAL_7TUPLE)
+ return kslist->keysets[idx];
+ }
+ break;
+ case VCAP_TYPE_IS2:
+ for (idx = 0; idx < kslist->cnt; idx++) {
+ if (kslist->keysets[idx] == VCAP_KFS_MAC_ETYPE)
+ return kslist->keysets[idx];
+ if (kslist->keysets[idx] == VCAP_KFS_ARP)
+ return kslist->keysets[idx];
+ if (kslist->keysets[idx] == VCAP_KFS_IP_7TUPLE)
+ return kslist->keysets[idx];
+ }
+ break;
+ default:
+ pr_info("%s:%d: no validation for VCAP %d\n",
+ __func__, __LINE__, admin->vtype);
+ break;
+ }
+ }
+ return -EINVAL;
+}
+
+/* Callback used by the VCAP API */
+static void test_add_def_fields(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_rule *rule)
+{
+ if (admin->vinst == 0 || admin->vinst == 2)
+ vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
+ VCAP_BIT_1);
+ else
+ vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
+ VCAP_BIT_0);
+}
+
+/* Callback used by the VCAP API */
+static void test_cache_erase(struct vcap_admin *admin)
+{
+ if (test_cache_erase_count) {
+ memset(admin->cache.keystream, 0, test_cache_erase_count);
+ memset(admin->cache.maskstream, 0, test_cache_erase_count);
+ memset(admin->cache.actionstream, 0, test_cache_erase_count);
+ test_cache_erase_count = 0;
+ }
+}
+
+/* Callback used by the VCAP API */
+static void test_cache_init(struct net_device *ndev, struct vcap_admin *admin,
+ u32 start, u32 count)
+{
+ test_init_start = start;
+ test_init_count = count;
+}
+
+/* Callback used by the VCAP API */
+static void test_cache_read(struct net_device *ndev, struct vcap_admin *admin,
+ enum vcap_selection sel, u32 start, u32 count)
+{
+ u32 *keystr, *mskstr, *actstr;
+ int idx;
+
+ pr_debug("%s:%d: %d %d\n", __func__, __LINE__, start, count);
+ switch (sel) {
+ case VCAP_SEL_ENTRY:
+ keystr = &admin->cache.keystream[start];
+ mskstr = &admin->cache.maskstream[start];
+ for (idx = 0; idx < count; ++idx) {
+ pr_debug("%s:%d: keydata[%02d]: 0x%08x\n", __func__,
+ __LINE__, start + idx, keystr[idx]);
+ }
+ for (idx = 0; idx < count; ++idx) {
+ /* Invert the mask before decoding starts */
+ mskstr[idx] = ~mskstr[idx];
+ pr_debug("%s:%d: mskdata[%02d]: 0x%08x\n", __func__,
+ __LINE__, start + idx, mskstr[idx]);
+ }
+ break;
+ case VCAP_SEL_ACTION:
+ actstr = &admin->cache.actionstream[start];
+ for (idx = 0; idx < count; ++idx) {
+ pr_debug("%s:%d: actdata[%02d]: 0x%08x\n", __func__,
+ __LINE__, start + idx, actstr[idx]);
+ }
+ break;
+ case VCAP_SEL_COUNTER:
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ test_hw_counter_id = start;
+ admin->cache.counter = test_hw_cache.counter;
+ admin->cache.sticky = test_hw_cache.sticky;
+ break;
+ case VCAP_SEL_ALL:
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ break;
+ }
+}
+
+/* Callback used by the VCAP API */
+static void test_cache_write(struct net_device *ndev, struct vcap_admin *admin,
+ enum vcap_selection sel, u32 start, u32 count)
+{
+ u32 *keystr, *mskstr, *actstr;
+ int idx;
+
+ switch (sel) {
+ case VCAP_SEL_ENTRY:
+ keystr = &admin->cache.keystream[start];
+ mskstr = &admin->cache.maskstream[start];
+ for (idx = 0; idx < count; ++idx) {
+ pr_debug("%s:%d: keydata[%02d]: 0x%08x\n", __func__,
+ __LINE__, start + idx, keystr[idx]);
+ }
+ for (idx = 0; idx < count; ++idx) {
+ /* Invert the mask before encoding starts */
+ mskstr[idx] = ~mskstr[idx];
+ pr_debug("%s:%d: mskdata[%02d]: 0x%08x\n", __func__,
+ __LINE__, start + idx, mskstr[idx]);
+ }
+ break;
+ case VCAP_SEL_ACTION:
+ actstr = &admin->cache.actionstream[start];
+ for (idx = 0; idx < count; ++idx) {
+ pr_debug("%s:%d: actdata[%02d]: 0x%08x\n", __func__,
+ __LINE__, start + idx, actstr[idx]);
+ }
+ break;
+ case VCAP_SEL_COUNTER:
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ test_hw_counter_id = start;
+ test_hw_cache.counter = admin->cache.counter;
+ test_hw_cache.sticky = admin->cache.sticky;
+ break;
+ case VCAP_SEL_ALL:
+ pr_err("%s:%d: cannot write all streams at once\n",
+ __func__, __LINE__);
+ break;
+ }
+}
+
+/* Callback used by the VCAP API */
+static void test_cache_update(struct net_device *ndev, struct vcap_admin *admin,
+ enum vcap_command cmd,
+ enum vcap_selection sel, u32 addr)
+{
+ if (test_updateaddridx < ARRAY_SIZE(test_updateaddr))
+ test_updateaddr[test_updateaddridx] = addr;
+ else
+ pr_err("%s:%d: overflow: %d\n", __func__, __LINE__,
+ test_updateaddridx);
+ test_updateaddridx++;
+}
+
+static void test_cache_move(struct net_device *ndev, struct vcap_admin *admin,
+ u32 addr, int offset, int count)
+{
+ test_move_addr = addr;
+ test_move_offset = offset;
+ test_move_count = count;
+}
+
+/* Provide port information via a callback interface */
+static int vcap_test_port_info(struct net_device *ndev,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ return 0;
+}
+
+static int vcap_test_enable(struct net_device *ndev,
+ struct vcap_admin *admin,
+ bool enable)
+{
+ return 0;
+}
+
+static struct vcap_operations test_callbacks = {
+ .validate_keyset = test_val_keyset,
+ .add_default_fields = test_add_def_fields,
+ .cache_erase = test_cache_erase,
+ .cache_write = test_cache_write,
+ .cache_read = test_cache_read,
+ .init = test_cache_init,
+ .update = test_cache_update,
+ .move = test_cache_move,
+ .port_info = vcap_test_port_info,
+ .enable = vcap_test_enable,
+};
+
+static struct vcap_control test_vctrl = {
+ .vcaps = kunit_test_vcaps,
+ .stats = &kunit_test_vcap_stats,
+ .ops = &test_callbacks,
+};
+
+static void vcap_test_api_init(struct vcap_admin *admin)
+{
+ /* Initialize the shared objects */
+ INIT_LIST_HEAD(&test_vctrl.list);
+ INIT_LIST_HEAD(&admin->list);
+ INIT_LIST_HEAD(&admin->rules);
+ list_add_tail(&admin->list, &test_vctrl.list);
+ memset(test_updateaddr, 0, sizeof(test_updateaddr));
+ test_updateaddridx = 0;
+ test_pr_bufferidx = 0;
+ test_pr_idx = 0;
+}
+
+/* callback used by the show_admin function */
+static __printf(2, 3)
+int test_prf(void *out, const char *fmt, ...)
+{
+ static char test_buffer[TEST_BUF_SZ];
+ va_list args;
+ int idx, cnt;
+
+ if (test_pr_bufferidx >= TEST_BUF_CNT) {
+ pr_err("%s:%d: overflow: %d\n", __func__, __LINE__,
+ test_pr_bufferidx);
+ return 0;
+ }
+
+ va_start(args, fmt);
+ cnt = vscnprintf(test_buffer, TEST_BUF_SZ, fmt, args);
+ va_end(args);
+
+ for (idx = 0; idx < cnt; ++idx) {
+ test_pr_buffer[test_pr_bufferidx][test_pr_idx] =
+ test_buffer[idx];
+ if (test_buffer[idx] == '\n') {
+ test_pr_buffer[test_pr_bufferidx][++test_pr_idx] = 0;
+ test_pr_idx = 0;
+ test_pr_bufferidx++;
+ } else {
+ ++test_pr_idx;
+ }
+ }
+
+ return cnt;
+}
+
+/* Define the test cases. */
+
+static void vcap_api_addr_keyset_test(struct kunit *test)
+{
+ u32 keydata[12] = {
+ 0x40450042, 0x000feaf3, 0x00000003, 0x00050600,
+ 0x10203040, 0x00075880, 0x633c6864, 0x00040003,
+ 0x00000020, 0x00000008, 0x00000240, 0x00000000,
+ };
+ u32 mskdata[12] = {
+ 0x0030ff80, 0xfff00000, 0xfffffffc, 0xfff000ff,
+ 0x00000000, 0xfff00000, 0x00000000, 0xfff3fffc,
+ 0xffffffc0, 0xffffffff, 0xfffffc03, 0xffffffff,
+ };
+ u32 actdata[12] = {};
+ struct vcap_admin admin = {
+ .vtype = VCAP_TYPE_IS2,
+ .cache = {
+ .keystream = keydata,
+ .maskstream = mskdata,
+ .actionstream = actdata,
+ },
+ };
+ int ret, idx, addr;
+
+ vcap_test_api_init(&admin);
+
+ /* Go from higher to lower addresses searching for a keyset */
+ for (idx = ARRAY_SIZE(keydata) - 1, addr = 799; idx > 0;
+ --idx, --addr) {
+ admin.cache.keystream = &keydata[idx];
+ admin.cache.maskstream = &mskdata[idx];
+ ret = vcap_addr_keyset(&test_vctrl, &test_netdev, &admin, addr);
+ KUNIT_EXPECT_EQ(test, -EINVAL, ret);
+ }
+
+ /* Finally we hit the start of the rule */
+ admin.cache.keystream = &keydata[idx];
+ admin.cache.maskstream = &mskdata[idx];
+ ret = vcap_addr_keyset(&test_vctrl, &test_netdev, &admin, addr);
+ KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, ret);
+}
+
+static void vcap_api_show_admin_raw_test(struct kunit *test)
+{
+ u32 keydata[4] = {
+ 0x40450042, 0x000feaf3, 0x00000003, 0x00050600,
+ };
+ u32 mskdata[4] = {
+ 0x0030ff80, 0xfff00000, 0xfffffffc, 0xfff000ff,
+ };
+ u32 actdata[12] = {};
+ struct vcap_admin admin = {
+ .vtype = VCAP_TYPE_IS2,
+ .cache = {
+ .keystream = keydata,
+ .maskstream = mskdata,
+ .actionstream = actdata,
+ },
+ .first_valid_addr = 786,
+ .last_valid_addr = 788,
+ };
+ struct vcap_rule_internal ri = {
+ .ndev = &test_netdev,
+ };
+ struct vcap_output_print out = {
+ .prf = (void *)test_prf,
+ };
+ const char *test_expected =
+ " addr: 786, X6 rule, keyset: VCAP_KFS_MAC_ETYPE\n";
+ int ret;
+
+ vcap_test_api_init(&admin);
+ list_add_tail(&ri.list, &admin.rules);
+
+ ret = vcap_show_admin_raw(&test_vctrl, &admin, &out);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+ KUNIT_EXPECT_STREQ(test, test_expected, test_pr_buffer[0]);
+}
+
+static const char * const test_admin_info_expect[] = {
+ "name: is2\n",
+ "rows: 256\n",
+ "sw_count: 12\n",
+ "sw_width: 52\n",
+ "sticky_width: 1\n",
+ "act_width: 110\n",
+ "default_cnt: 73\n",
+ "require_cnt_dis: 0\n",
+ "version: 1\n",
+ "vtype: 2\n",
+ "vinst: 0\n",
+ "first_cid: 10000\n",
+ "last_cid: 19999\n",
+ "lookups: 4\n",
+ "first_valid_addr: 0\n",
+ "last_valid_addr: 3071\n",
+ "last_used_addr: 794\n",
+};
+
+static void vcap_api_show_admin_test(struct kunit *test)
+{
+ struct vcap_admin admin = {
+ .vtype = VCAP_TYPE_IS2,
+ .first_cid = 10000,
+ .last_cid = 19999,
+ .lookups = 4,
+ .last_valid_addr = 3071,
+ .first_valid_addr = 0,
+ .last_used_addr = 794,
+ };
+ struct vcap_output_print out = {
+ .prf = (void *)test_prf,
+ };
+ int idx;
+
+ vcap_test_api_init(&admin);
+
+ vcap_show_admin_info(&test_vctrl, &admin, &out);
+ for (idx = 0; idx < test_pr_bufferidx; ++idx) {
+ /* pr_info("log[%02d]: %s", idx, test_pr_buffer[idx]); */
+ KUNIT_EXPECT_STREQ(test, test_admin_info_expect[idx],
+ test_pr_buffer[idx]);
+ }
+}
+
+static const char * const test_admin_expect[] = {
+ "name: is2\n",
+ "rows: 256\n",
+ "sw_count: 12\n",
+ "sw_width: 52\n",
+ "sticky_width: 1\n",
+ "act_width: 110\n",
+ "default_cnt: 73\n",
+ "require_cnt_dis: 0\n",
+ "version: 1\n",
+ "vtype: 2\n",
+ "vinst: 0\n",
+ "first_cid: 8000000\n",
+ "last_cid: 8199999\n",
+ "lookups: 4\n",
+ "first_valid_addr: 0\n",
+ "last_valid_addr: 3071\n",
+ "last_used_addr: 794\n",
+ "\n",
+ "rule: 100, addr: [794,799], X6, ctr[0]: 0, hit: 0\n",
+ " chain_id: 0\n",
+ " user: 0\n",
+ " priority: 0\n",
+ " keyset: VCAP_KFS_MAC_ETYPE\n",
+ " keyset_sw: 6\n",
+ " keyset_sw_regs: 2\n",
+ " ETYPE_LEN_IS: W1: 1/1\n",
+ " IF_IGR_PORT_MASK: W32: 0xffabcd01/0xffffffff\n",
+ " IF_IGR_PORT_MASK_RNG: W4: 5/15\n",
+ " L2_DMAC: W48: 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff\n",
+ " L2_PAYLOAD_ETYPE: W64: 0x9000002000000081/0xff000000000000ff\n",
+ " L2_SMAC: W48: b1:9e:34:32:75:88/ff:ff:ff:ff:ff:ff\n",
+ " LOOKUP_FIRST_IS: W1: 1/1\n",
+ " TYPE: W4: 0/15\n",
+ " actionset: VCAP_AFS_BASE_TYPE\n",
+ " actionset_sw: 3\n",
+ " actionset_sw_regs: 4\n",
+ " CNT_ID: W12: 100\n",
+ " MATCH_ID: W16: 1\n",
+ " MATCH_ID_MASK: W16: 1\n",
+ " POLICE_ENA: W1: 1\n",
+ " PORT_MASK: W68: 0x0514670115f3324589\n",
+};
+
+static void vcap_api_show_admin_rule_test(struct kunit *test)
+{
+ u32 keydata[] = {
+ 0x40450042, 0x000feaf3, 0x00000003, 0x00050600,
+ 0x10203040, 0x00075880, 0x633c6864, 0x00040003,
+ 0x00000020, 0x00000008, 0x00000240, 0x00000000,
+ };
+ u32 mskdata[] = {
+ 0x0030ff80, 0xfff00000, 0xfffffffc, 0xfff000ff,
+ 0x00000000, 0xfff00000, 0x00000000, 0xfff3fffc,
+ 0xffffffc0, 0xffffffff, 0xfffffc03, 0xffffffff,
+ };
+ u32 actdata[] = {
+ 0x00040002, 0xf3324589, 0x14670115, 0x00000005,
+ 0x00000000, 0x00100000, 0x06400010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ };
+ struct vcap_admin admin = {
+ .vtype = VCAP_TYPE_IS2,
+ .first_cid = 8000000,
+ .last_cid = 8199999,
+ .lookups = 4,
+ .last_valid_addr = 3071,
+ .first_valid_addr = 0,
+ .last_used_addr = 794,
+ .cache = {
+ .keystream = keydata,
+ .maskstream = mskdata,
+ .actionstream = actdata,
+ },
+ };
+ struct vcap_rule_internal ri = {
+ .admin = &admin,
+ .data = {
+ .id = 100,
+ .keyset = VCAP_KFS_MAC_ETYPE,
+ .actionset = VCAP_AFS_BASE_TYPE,
+ },
+ .size = 6,
+ .keyset_sw = 6,
+ .keyset_sw_regs = 2,
+ .actionset_sw = 3,
+ .actionset_sw_regs = 4,
+ .addr = 794,
+ .vctrl = &test_vctrl,
+ };
+ struct vcap_output_print out = {
+ .prf = (void *)test_prf,
+ };
+ int ret, idx;
+
+ vcap_test_api_init(&admin);
+ list_add_tail(&ri.list, &admin.rules);
+
+ ret = vcap_show_admin(&test_vctrl, &admin, &out);
+ KUNIT_EXPECT_EQ(test, 0, ret);
+ for (idx = 0; idx < test_pr_bufferidx; ++idx) {
+ /* pr_info("log[%02d]: %s", idx, test_pr_buffer[idx]); */
+ KUNIT_EXPECT_STREQ(test, test_admin_expect[idx],
+ test_pr_buffer[idx]);
+ }
+}
+
+static struct kunit_case vcap_api_debugfs_test_cases[] = {
+ KUNIT_CASE(vcap_api_addr_keyset_test),
+ KUNIT_CASE(vcap_api_show_admin_raw_test),
+ KUNIT_CASE(vcap_api_show_admin_test),
+ KUNIT_CASE(vcap_api_show_admin_rule_test),
+ {}
+};
+
+static struct kunit_suite vcap_api_debugfs_test_suite = {
+ .name = "VCAP_API_DebugFS_Testsuite",
+ .test_cases = vcap_api_debugfs_test_cases,
+};
+
+kunit_test_suite(vcap_api_debugfs_test_suite);
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
index a3dc1b2d029c..ec910e1c4c00 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
@@ -1691,7 +1691,7 @@ static void vcap_api_rule_remove_at_end_test(struct kunit *test)
KUNIT_EXPECT_EQ(test, 0, test_move_count);
KUNIT_EXPECT_EQ(test, 780, test_init_start);
KUNIT_EXPECT_EQ(test, 12, test_init_count);
- KUNIT_EXPECT_EQ(test, 3071, admin.last_used_addr);
+ KUNIT_EXPECT_EQ(test, 3072, admin.last_used_addr);
}
static void vcap_api_rule_remove_in_middle_test(struct kunit *test)
@@ -1766,7 +1766,7 @@ static void vcap_api_rule_remove_in_middle_test(struct kunit *test)
KUNIT_EXPECT_EQ(test, 0, test_move_count);
KUNIT_EXPECT_EQ(test, 798, test_init_start);
KUNIT_EXPECT_EQ(test, 2, test_init_count);
- KUNIT_EXPECT_EQ(test, 799, admin.last_used_addr);
+ KUNIT_EXPECT_EQ(test, 800, admin.last_used_addr);
}
static void vcap_api_rule_remove_in_front_test(struct kunit *test)
@@ -1805,7 +1805,7 @@ static void vcap_api_rule_remove_in_front_test(struct kunit *test)
KUNIT_EXPECT_EQ(test, 0, test_move_count);
KUNIT_EXPECT_EQ(test, 780, test_init_start);
KUNIT_EXPECT_EQ(test, 12, test_init_count);
- KUNIT_EXPECT_EQ(test, 799, admin.last_used_addr);
+ KUNIT_EXPECT_EQ(test, 800, admin.last_used_addr);
test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 400, 6, 792);
test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 789);
--
2.38.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (7 preceding siblings ...)
2022-11-17 21:31 ` [PATCH net-next v2 8/8] net: microchip: sparx5: Add VCAP debugfs KUNIT test Steen Hegelund
@ 2022-11-21 11:40 ` patchwork-bot+netdevbpf
2022-11-21 19:01 ` Jakub Kicinski
9 siblings, 0 replies; 13+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-11-21 11:40 UTC (permalink / raw)
To: Steen Hegelund
Cc: davem, edumazet, kuba, pabeni, UNGLinuxDriver, rdunlap,
casper.casan, rmk+kernel, wanjiabing, nhuck, linux-kernel,
netdev, linux-arm-kernel, Steen.Hegelund, daniel.machon,
horatiu.vultur, lars.povlsen
Hello:
This series was applied to netdev/net-next.git (master)
by David S. Miller <davem@davemloft.net>:
On Thu, 17 Nov 2022 22:31:06 +0100 you wrote:
> This provides support for getting VCAP instance, VCAP rule and VCAP port
> keyset configuration information via the debug file system.
>
> It builds on top of the initial IS2 VCAP support found in these series:
>
> https://lore.kernel.org/all/20221020130904.1215072-1-steen.hegelund@microchip.com/
> https://lore.kernel.org/all/20221109114116.3612477-1-steen.hegelund@microchip.com/
> https://lore.kernel.org/all/20221111130519.1459549-1-steen.hegelund@microchip.com/
>
> [...]
Here is the summary with links:
- [net-next,v2,1/8] net: microchip: sparx5: Ensure L3 protocol has a default value
https://git.kernel.org/netdev/net-next/c/bcddc196d481
- [net-next,v2,2/8] net: microchip: sparx5: Ensure VCAP last_used_addr is set back to default
https://git.kernel.org/netdev/net-next/c/277e9179efe5
- [net-next,v2,3/8] net: microchip: sparx5: Add VCAP debugFS support
https://git.kernel.org/netdev/net-next/c/e0305cc1d125
- [net-next,v2,4/8] net: microchip: sparx5: Add raw VCAP debugFS support for the VCAP API
https://git.kernel.org/netdev/net-next/c/d4134d41e3cb
- [net-next,v2,5/8] net: microchip: sparx5: Add VCAP rule debugFS support for the VCAP API
https://git.kernel.org/netdev/net-next/c/3a7921560d2f
- [net-next,v2,6/8] net: microchip: sparx5: Add VCAP debugFS key/action support for the VCAP API
https://git.kernel.org/netdev/net-next/c/72d84dd609be
- [net-next,v2,7/8] net: microchip: sparx5: Add VCAP locking to protect rules
https://git.kernel.org/netdev/net-next/c/71c9de995260
- [net-next,v2,8/8] net: microchip: sparx5: Add VCAP debugfs KUNIT test
https://git.kernel.org/netdev/net-next/c/552b7d131aa0
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5
2022-11-17 21:31 [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 Steen Hegelund
` (8 preceding siblings ...)
2022-11-21 11:40 ` [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5 patchwork-bot+netdevbpf
@ 2022-11-21 19:01 ` Jakub Kicinski
2022-11-22 9:17 ` Steen Hegelund
9 siblings, 1 reply; 13+ messages in thread
From: Jakub Kicinski @ 2022-11-21 19:01 UTC (permalink / raw)
To: Steen Hegelund
Cc: David S . Miller, Eric Dumazet, Paolo Abeni, UNGLinuxDriver,
Randy Dunlap, Casper Andersson, Russell King, Wan Jiabing,
Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
Daniel Machon, Horatiu Vultur, Lars Povlsen
On Thu, 17 Nov 2022 22:31:06 +0100 Steen Hegelund wrote:
> This provides support for getting VCAP instance, VCAP rule and VCAP port
> keyset configuration information via the debug file system.
Have you checked devlink dpipe? On a quick scan it may be the right API
to use here? Perhaps this was merged before people who know the code
had a chance to take a look :(
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5
2022-11-21 19:01 ` Jakub Kicinski
@ 2022-11-22 9:17 ` Steen Hegelund
2022-11-22 18:47 ` Jakub Kicinski
0 siblings, 1 reply; 13+ messages in thread
From: Steen Hegelund @ 2022-11-22 9:17 UTC (permalink / raw)
To: Jakub Kicinski
Cc: David S . Miller, Eric Dumazet, Paolo Abeni, UNGLinuxDriver,
Randy Dunlap, Casper Andersson, Russell King, Wan Jiabing,
Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
Daniel Machon, Horatiu Vultur, Lars Povlsen
Hi Jacub,
On Mon, 2022-11-21 at 11:01 -0800, Jakub Kicinski wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
>
> On Thu, 17 Nov 2022 22:31:06 +0100 Steen Hegelund wrote:
> > This provides support for getting VCAP instance, VCAP rule and VCAP port
> > keyset configuration information via the debug file system.
>
> Have you checked devlink dpipe? On a quick scan it may be the right API
> to use here? Perhaps this was merged before people who know the code
> had a chance to take a look :(
No I was not aware of the scope of devlink-dpipe, but it looks like the Sparx5
VCAP feature would fit in.
I need to take a closer look at the model and see if I can make ends meet, but
if so, then I could send support for devlink-dpipe at a later stage...
BR
Steen
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 0/8] Add support for VCAP debugFS in Sparx5
2022-11-22 9:17 ` Steen Hegelund
@ 2022-11-22 18:47 ` Jakub Kicinski
0 siblings, 0 replies; 13+ messages in thread
From: Jakub Kicinski @ 2022-11-22 18:47 UTC (permalink / raw)
To: Steen Hegelund
Cc: David S . Miller, Eric Dumazet, Paolo Abeni, UNGLinuxDriver,
Randy Dunlap, Casper Andersson, Russell King, Wan Jiabing,
Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
Daniel Machon, Horatiu Vultur, Lars Povlsen
On Tue, 22 Nov 2022 10:17:22 +0100 Steen Hegelund wrote:
> > Have you checked devlink dpipe? On a quick scan it may be the right API
> > to use here? Perhaps this was merged before people who know the code
> > had a chance to take a look :(
>
> No I was not aware of the scope of devlink-dpipe, but it looks like the Sparx5
> VCAP feature would fit in.
>
> I need to take a closer look at the model and see if I can make ends meet, but
> if so, then I could send support for devlink-dpipe at a later stage...
SG. I don't feel strongly, maybe someone else does..
^ permalink raw reply [flat|nested] 13+ messages in thread