Skip to content

Commit

Permalink
Merge branch 'sarx5-VCAP-debugfs'
Browse files Browse the repository at this point in the history
netdev.vger.kernel.org archive mirror
Steen Hegelund says:

====================
net: Add support for VCAP debugFS in Sparx5

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/

Functionality:
==============

The VCAP API exposes a /sys/kernel/debug/sparx5/vcaps folder containing
the following entries:

- raw_<vcap>_<instance>
    This is a raw dump of the VCAP instance with a line for each available
    VCAP rule.  This information is limited to the VCAP rule address, the
    rule size and the rule keyset name as this requires very little
    information from the VCAP cache.

    This can be used to detect if a valid rule is stored at the correct
    address.

- <vcap>_<instance>
    This dumps the VCAP instance configuration: address ranges, chain id
    ranges, word size of keys and actions etc, and for each VCAP rule the
    details of keys (values and masks) and actions are shown.

    This is useful when discovering if the expected rule is present and in
    which order it will be matched.

- <interface>
    This shows the keyset configuration per lookup and traffic type and the
    set of sticky bits (common for all interfaces). This is cleared when
    shown, so it is possible to sample over a period of time.

    It also shows if this port/lookup is enabled for matching in the VCAP.

    This can be used to find out which keyset the traffic being sent to a
    port, will be matched against, and if such traffic has been seen by one
    of the ports.

Delivery:
=========

This is current plan for delivering the full VCAP feature set of Sparx5:

- TC protocol all support for IS2 VCAP
- Sparx5 IS0 VCAP support
- TC policer and drop action support (depends on the Sparx5 QoS support
  upstreamed separately)
- Sparx5 ES0 VCAP support
- TC flower template support
- TC matchall filter support for mirroring and policing ports
- TC flower filter mirror action support
- Sparx5 ES2 VCAP support

Version History:
================
v2      Removed a 'support' folder (used for integration testing) that had
        been added in patch 6/8 by a mistake.
        Wrapped long lines.

v1      Initial version
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 21, 2022
2 parents 418e072 + 552b7d1 commit 4dca131
Show file tree
Hide file tree
Showing 17 changed files with 1,838 additions and 128 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/microchip/sparx5/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions drivers/net/ethernet/microchip/sparx5/sparx5_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,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");
Expand Down Expand Up @@ -906,6 +908,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;
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/microchip/sparx5/sparx5_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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 */
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
200 changes: 200 additions & 0 deletions drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// 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"

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)
{
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;
}
33 changes: 33 additions & 0 deletions drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.h
Original file line number Diff line number Diff line change
@@ -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__ */
Loading

0 comments on commit 4dca131

Please sign in to comment.