Commit 9f927527 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'adding-sparx5-is0-vcap-support'

Steen Hegelund says:

====================
Adding Sparx5 IS0 VCAP support

This provides the Ingress Stage 0 (IS0) VCAP (Versatile Content-Aware
Processor) support for the Sparx5 platform.

The IS0 VCAP (also known in the datasheet as CLM) is a classifier VCAP that
mainly extracts frame information to metadata that follows the frame in the
Sparx5 processing flow all the way to the egress port.

The IS0 VCAP has 4 lookups and they are accessible with a TC chain id:

- chain 1000000: IS0 Lookup 0
- chain 1100000: IS0 Lookup 1
- chain 1200000: IS0 Lookup 2
- chain 1300000: IS0 Lookup 3
- chain 1400000: IS0 Lookup 4
- chain 1500000: IS0 Lookup 5

Each of these lookups have their own port keyset configuration that decides
which keys will be used for matching on which traffic type.

The IS0 VCAP has these traffic classifications:

- IPv4 frames
- IPv6 frames
- Unicast MPLS frames (ethertype = 0x8847)
- Multicast MPLS frames (ethertype = 0x8847)
- Other frame types than MPLS, IPv4 and IPv6

The IS0 VCAP has an action that allows setting the value of a PAG (Policy
Association Group) key field in the frame metadata, and this can be used
for matching in an IS2 VCAP rule.

This allow rules in the IS0 VCAP to be linked to rules in the IS2 VCAP.

The linking is exposed by using the TC "goto chain" action with an offset
from the IS2 chain ids.

As an example a "goto chain 8000001" will use a PAG value of 1 to chain to
a rule in IS2 Lookup 0.
====================

Link: https://lore.kernel.org/r/20230124104511.293938-1-steen.hegelund@microchip.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 3f17e16f 52df82cc
Loading
Loading
Loading
Loading
+62 −2
Original line number Diff line number Diff line
@@ -4,8 +4,8 @@
 * Copyright (c) 2021 Microchip Technology Inc.
 */

/* This file is autogenerated by cml-utils 2022-11-04 11:22:22 +0100.
 * Commit ID: 498242727be5db9b423cc0923bc966fc7b40607e
/* This file is autogenerated by cml-utils 2022-12-06 15:28:38 +0100.
 * Commit ID: 3db2ac730f134c160496f2b9f10915e347d871cb
 */

#ifndef _SPARX5_MAIN_REGS_H_
@@ -843,6 +843,66 @@ enum sparx5_target {
/*      ANA_CL:PORT:CAPTURE_BPDU_CFG */
#define ANA_CL_CAPTURE_BPDU_CFG(g) __REG(TARGET_ANA_CL, 0, 1, 131072, g, 70, 512, 196, 0, 1, 4)

/*      ANA_CL:PORT:ADV_CL_CFG_2 */
#define ANA_CL_ADV_CL_CFG_2(g, r) __REG(TARGET_ANA_CL, 0, 1, 131072, g, 70, 512, 200, r, 6, 4)

#define ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA      BIT(1)
#define ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA, x)
#define ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA, x)

#define ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA      BIT(0)
#define ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA, x)
#define ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA, x)

/*      ANA_CL:PORT:ADV_CL_CFG */
#define ANA_CL_ADV_CL_CFG(g, r)   __REG(TARGET_ANA_CL, 0, 1, 131072, g, 70, 512, 224, r, 6, 4)

#define ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL        GENMASK(30, 26)
#define ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL, x)
#define ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL, x)

#define ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL        GENMASK(25, 21)
#define ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL, x)
#define ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL, x)

#define ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL    GENMASK(20, 16)
#define ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL, x)
#define ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL, x)

#define ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL    GENMASK(15, 11)
#define ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL, x)
#define ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL, x)

#define ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL       GENMASK(10, 6)
#define ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL, x)
#define ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL, x)

#define ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL      GENMASK(5, 1)
#define ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL, x)
#define ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL, x)

#define ANA_CL_ADV_CL_CFG_LOOKUP_ENA             BIT(0)
#define ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(x)\
	FIELD_PREP(ANA_CL_ADV_CL_CFG_LOOKUP_ENA, x)
#define ANA_CL_ADV_CL_CFG_LOOKUP_ENA_GET(x)\
	FIELD_GET(ANA_CL_ADV_CL_CFG_LOOKUP_ENA, x)

/*      ANA_CL:COMMON:OWN_UPSID */
#define ANA_CL_OWN_UPSID(r)       __REG(TARGET_ANA_CL, 0, 1, 166912, 0, 1, 756, 0, r, 3, 4)

+189 −38
Original line number Diff line number Diff line
@@ -30,21 +30,12 @@ struct sparx5_tc_flower_parse_usage {
	struct flow_cls_offload *fco;
	struct flow_rule *frule;
	struct vcap_rule *vrule;
	struct vcap_admin *admin;
	u16 l3_proto;
	u8 l4_proto;
	unsigned int used_keys;
};

/* These protocols have dedicated keysets in IS2 and a TC dissector
 * ETH_P_ARP does not have a TC dissector
 */
static u16 sparx5_tc_known_etypes[] = {
	ETH_P_ALL,
	ETH_P_ARP,
	ETH_P_IP,
	ETH_P_IPV6,
};

enum sparx5_is2_arp_opcode {
	SPX5_IS2_ARP_REQUEST,
	SPX5_IS2_ARP_REPLY,
@@ -58,18 +49,6 @@ enum tc_arp_opcode {
	TC_ARP_OP_REPLY,
};

static bool sparx5_tc_is_known_etype(u16 etype)
{
	int idx;

	/* For now this only knows about IS2 traffic classification */
	for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_known_etypes); ++idx)
		if (sparx5_tc_known_etypes[idx] == etype)
			return true;

	return false;
}

static int sparx5_tc_flower_handler_ethaddr_usage(struct sparx5_tc_flower_parse_usage *st)
{
	enum vcap_key_field smac_key = VCAP_KF_L2_SMAC;
@@ -272,7 +251,7 @@ sparx5_tc_flower_handler_basic_usage(struct sparx5_tc_flower_parse_usage *st)

	if (mt.mask->n_proto) {
		st->l3_proto = be16_to_cpu(mt.key->n_proto);
		if (!sparx5_tc_is_known_etype(st->l3_proto)) {
		if (!sparx5_vcap_is_known_etype(st->admin, st->l3_proto)) {
			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
						    st->l3_proto, ~0);
			if (err)
@@ -304,6 +283,13 @@ sparx5_tc_flower_handler_basic_usage(struct sparx5_tc_flower_parse_usage *st)
						    VCAP_BIT_0);
			if (err)
				goto out;
			if (st->admin->vtype == VCAP_TYPE_IS0) {
				err = vcap_rule_add_key_bit(st->vrule,
							    VCAP_KF_TCP_UDP_IS,
							    VCAP_BIT_1);
				if (err)
					goto out;
			}
		} else {
			err = vcap_rule_add_key_u32(st->vrule,
						    VCAP_KF_L3_IP_PROTO,
@@ -322,6 +308,51 @@ sparx5_tc_flower_handler_basic_usage(struct sparx5_tc_flower_parse_usage *st)
	return err;
}

static int
sparx5_tc_flower_handler_cvlan_usage(struct sparx5_tc_flower_parse_usage *st)
{
	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID0;
	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP0;
	struct flow_match_vlan mt;
	u16 tpid;
	int err;

	if (st->admin->vtype != VCAP_TYPE_IS0)
		return -EINVAL;

	flow_rule_match_cvlan(st->frule, &mt);

	tpid = be16_to_cpu(mt.key->vlan_tpid);

	if (tpid == ETH_P_8021Q) {
		vid_key = VCAP_KF_8021Q_VID1;
		pcp_key = VCAP_KF_8021Q_PCP1;
	}

	if (mt.mask->vlan_id) {
		err = vcap_rule_add_key_u32(st->vrule, vid_key,
					    mt.key->vlan_id,
					    mt.mask->vlan_id);
		if (err)
			goto out;
	}

	if (mt.mask->vlan_priority) {
		err = vcap_rule_add_key_u32(st->vrule, pcp_key,
					    mt.key->vlan_priority,
					    mt.mask->vlan_priority);
		if (err)
			goto out;
	}

	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN);

	return 0;
out:
	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error");
	return err;
}

static int
sparx5_tc_flower_handler_vlan_usage(struct sparx5_tc_flower_parse_usage *st)
{
@@ -332,6 +363,11 @@ sparx5_tc_flower_handler_vlan_usage(struct sparx5_tc_flower_parse_usage *st)

	flow_rule_match_vlan(st->frule, &mt);

	if (st->admin->vtype == VCAP_TYPE_IS0) {
		vid_key = VCAP_KF_8021Q_VID0;
		pcp_key = VCAP_KF_8021Q_PCP0;
	}

	if (mt.mask->vlan_id) {
		err = vcap_rule_add_key_u32(st->vrule, vid_key,
					    mt.key->vlan_id,
@@ -527,6 +563,7 @@ static int (*sparx5_tc_flower_usage_handlers[])(struct sparx5_tc_flower_parse_us
	[FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage,
	[FLOW_DISSECTOR_KEY_PORTS] = sparx5_tc_flower_handler_portnum_usage,
	[FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage,
	[FLOW_DISSECTOR_KEY_CVLAN] = sparx5_tc_flower_handler_cvlan_usage,
	[FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage,
	[FLOW_DISSECTOR_KEY_TCP] = sparx5_tc_flower_handler_tcp_usage,
	[FLOW_DISSECTOR_KEY_ARP] = sparx5_tc_flower_handler_arp_usage,
@@ -542,6 +579,7 @@ static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco,
		.fco = fco,
		.vrule = vrule,
		.l3_proto = ETH_P_ALL,
		.admin = admin,
	};
	int idx, err = 0;

@@ -623,18 +661,21 @@ static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
	return 0;
}

/* Add a rule counter action - only IS2 is considered for now */
/* Add a rule counter action */
static int sparx5_tc_add_rule_counter(struct vcap_admin *admin,
				      struct vcap_rule *vrule)
{
	int err;

	err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID, vrule->id);
	if (admin->vtype == VCAP_TYPE_IS2) {
		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID,
					       vrule->id);
		if (err)
			return err;

		vcap_rule_set_counter_id(vrule, vrule->id);
	return err;
	}

	return 0;
}

/* Collect all port keysets and apply the first of them, possibly wildcarded */
@@ -815,6 +856,107 @@ static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl,
	return err;
}

/* Add the actionset that is the default for the VCAP type */
static int sparx5_tc_set_actionset(struct vcap_admin *admin,
				   struct vcap_rule *vrule)
{
	enum vcap_actionfield_set aset;
	int err = 0;

	switch (admin->vtype) {
	case VCAP_TYPE_IS0:
		aset = VCAP_AFS_CLASSIFICATION;
		break;
	case VCAP_TYPE_IS2:
		aset = VCAP_AFS_BASE_TYPE;
		break;
	default:
		return -EINVAL;
	}
	/* Do not overwrite any current actionset */
	if (vrule->actionset == VCAP_AFS_NO_VALUE)
		err = vcap_set_rule_set_actionset(vrule, aset);
	return err;
}

/* Add the VCAP key to match on for a rule target value */
static int sparx5_tc_add_rule_link_target(struct vcap_admin *admin,
					  struct vcap_rule *vrule,
					  int target_cid)
{
	int link_val = target_cid % VCAP_CID_LOOKUP_SIZE;
	int err;

	if (!link_val)
		return 0;

	switch (admin->vtype) {
	case VCAP_TYPE_IS0:
		/* Add NXT_IDX key for chaining rules between IS0 instances */
		err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL,
					    1, /* enable */
					    ~0);
		if (err)
			return err;
		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX,
					     link_val, /* target */
					     ~0);
	case VCAP_TYPE_IS2:
		/* Add PAG key for chaining rules from IS0 */
		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
					     link_val, /* target */
					     ~0);
	default:
		break;
	}
	return 0;
}

/* Add the VCAP action that adds a target value to a rule */
static int sparx5_tc_add_rule_link(struct vcap_control *vctrl,
				   struct vcap_admin *admin,
				   struct vcap_rule *vrule,
				   int from_cid, int to_cid)
{
	struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid);
	int diff, err = 0;

	diff = vcap_chain_offset(vctrl, from_cid, to_cid);
	if (!(to_admin && diff > 0)) {
		pr_err("%s:%d: unsupported chain direction: %d\n",
		       __func__, __LINE__, to_cid);
		return -EINVAL;
	}
	if (admin->vtype == VCAP_TYPE_IS0 &&
	    to_admin->vtype == VCAP_TYPE_IS0) {
		/* Between IS0 instances the G_IDX value is used */
		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX, diff);
		if (err)
			goto out;
		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX_CTRL,
					       1); /* Replace */
		if (err)
			goto out;
	} else if (admin->vtype == VCAP_TYPE_IS0 &&
		   to_admin->vtype == VCAP_TYPE_IS2) {
		/* Between IS0 and IS2 the PAG value is used */
		err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff);
		if (err)
			goto out;
		err = vcap_rule_add_action_u32(vrule,
					       VCAP_AF_PAG_OVERRIDE_MASK,
					       0xff);
		if (err)
			goto out;
	} else {
		pr_err("%s:%d: unsupported chain destination: %d\n",
		       __func__, __LINE__, to_cid);
		err = -EOPNOTSUPP;
	}
out:
	return err;
}

static int sparx5_tc_flower_replace(struct net_device *ndev,
				    struct flow_cls_offload *fco,
				    struct vcap_admin *admin)
@@ -850,10 +992,21 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
	if (err)
		goto out;

	err = sparx5_tc_add_rule_link_target(admin, vrule,
					     fco->common.chain_index);
	if (err)
		goto out;

	frule = flow_cls_offload_flow_rule(fco);
	flow_action_for_each(idx, act, &frule->action) {
		switch (act->id) {
		case FLOW_ACTION_TRAP:
			if (admin->vtype != VCAP_TYPE_IS2) {
				NL_SET_ERR_MSG_MOD(fco->common.extack,
						   "Trap action not supported in this VCAP");
				err = -EOPNOTSUPP;
				goto out;
			}
			err = vcap_rule_add_action_bit(vrule,
						       VCAP_AF_CPU_COPY_ENA,
						       VCAP_BIT_1);
@@ -867,21 +1020,19 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
						       SPX5_PMM_REPLACE_ALL);
			if (err)
				goto out;
			/* For now the actionset is hardcoded */
			err = vcap_set_rule_set_actionset(vrule,
							  VCAP_AFS_BASE_TYPE);
			if (err)
				goto out;
			break;
		case FLOW_ACTION_ACCEPT:
			/* For now the actionset is hardcoded */
			err = vcap_set_rule_set_actionset(vrule,
							  VCAP_AFS_BASE_TYPE);
			err = sparx5_tc_set_actionset(admin, vrule);
			if (err)
				goto out;
			break;
		case FLOW_ACTION_GOTO:
			/* Links between VCAPs will be added later */
			err = sparx5_tc_set_actionset(admin, vrule);
			if (err)
				goto out;
			sparx5_tc_add_rule_link(vctrl, admin, vrule,
						fco->common.chain_index,
						act->chain_index);
			break;
		default:
			NL_SET_ERR_MSG_MOD(fco->common.extack,
+1048 −62

File changed.

Preview size limit exceeded, changes collapsed.

+122 −9
Original line number Diff line number Diff line
@@ -13,7 +13,110 @@
#include "sparx5_vcap_impl.h"
#include "sparx5_vcap_ag_api.h"

static void sparx5_vcap_port_keys(struct sparx5 *sparx5,
static const char *sparx5_vcap_is0_etype_str(u32 value)
{
	switch (value) {
	case VCAP_IS0_PS_ETYPE_DEFAULT:
		return "default";
	case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
		return "normal_7tuple";
	case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
		return "normal_5tuple_ip4";
	case VCAP_IS0_PS_ETYPE_MLL:
		return "mll";
	case VCAP_IS0_PS_ETYPE_LL_FULL:
		return "ll_full";
	case VCAP_IS0_PS_ETYPE_PURE_5TUPLE_IP4:
		return "pure_5tuple_ip4";
	case VCAP_IS0_PS_ETYPE_ETAG:
		return "etag";
	case VCAP_IS0_PS_ETYPE_NO_LOOKUP:
		return "no lookup";
	default:
		return "unknown";
	}
}

static const char *sparx5_vcap_is0_mpls_str(u32 value)
{
	switch (value) {
	case VCAP_IS0_PS_MPLS_FOLLOW_ETYPE:
		return "follow_etype";
	case VCAP_IS0_PS_MPLS_NORMAL_7TUPLE:
		return "normal_7tuple";
	case VCAP_IS0_PS_MPLS_NORMAL_5TUPLE_IP4:
		return "normal_5tuple_ip4";
	case VCAP_IS0_PS_MPLS_MLL:
		return "mll";
	case VCAP_IS0_PS_MPLS_LL_FULL:
		return "ll_full";
	case VCAP_IS0_PS_MPLS_PURE_5TUPLE_IP4:
		return "pure_5tuple_ip4";
	case VCAP_IS0_PS_MPLS_ETAG:
		return "etag";
	case VCAP_IS0_PS_MPLS_NO_LOOKUP:
		return "no lookup";
	default:
		return "unknown";
	}
}

static const char *sparx5_vcap_is0_mlbs_str(u32 value)
{
	switch (value) {
	case VCAP_IS0_PS_MLBS_FOLLOW_ETYPE:
		return "follow_etype";
	case VCAP_IS0_PS_MLBS_NO_LOOKUP:
		return "no lookup";
	default:
		return "unknown";
	}
}

static void sparx5_vcap_is0_port_keys(struct sparx5 *sparx5,
				      struct vcap_admin *admin,
				      struct sparx5_port *port,
				      struct vcap_output_print *out)
{
	int lookup;
	u32 value, val;

	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_CL_ADV_CL_CFG(port->portno, lookup));
		out->prf(out->dst, "\n      state: ");
		if (ANA_CL_ADV_CL_CFG_LOOKUP_ENA_GET(value))
			out->prf(out->dst, "on");
		else
			out->prf(out->dst, "off");
		val = ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value);
		out->prf(out->dst, "\n      etype: %s",
			 sparx5_vcap_is0_etype_str(val));
		val = ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value);
		out->prf(out->dst, "\n      ipv4: %s",
			 sparx5_vcap_is0_etype_str(val));
		val = ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value);
		out->prf(out->dst, "\n      ipv6: %s",
			 sparx5_vcap_is0_etype_str(val));
		val = ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_GET(value);
		out->prf(out->dst, "\n      mpls_uc: %s",
			 sparx5_vcap_is0_mpls_str(val));
		val = ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_GET(value);
		out->prf(out->dst, "\n      mpls_mc: %s",
			 sparx5_vcap_is0_mpls_str(val));
		val = ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_GET(value);
		out->prf(out->dst, "\n      mlbs: %s",
			 sparx5_vcap_is0_mlbs_str(val));
	}
	out->prf(out->dst, "\n");
}

static void sparx5_vcap_is2_port_keys(struct sparx5 *sparx5,
				      struct vcap_admin *admin,
				      struct sparx5_port *port,
				      struct vcap_output_print *out)
@@ -126,7 +229,7 @@ static void sparx5_vcap_port_keys(struct sparx5 *sparx5,
	out->prf(out->dst, "\n");
}

static void sparx5_vcap_port_stickies(struct sparx5 *sparx5,
static void sparx5_vcap_is2_port_stickies(struct sparx5 *sparx5,
					  struct vcap_admin *admin,
					  struct vcap_output_print *out)
{
@@ -194,7 +297,17 @@ int sparx5_port_info(struct net_device *ndev,
	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);
	switch (admin->vtype) {
	case VCAP_TYPE_IS0:
		sparx5_vcap_is0_port_keys(sparx5, admin, port, out);
		break;
	case VCAP_TYPE_IS2:
		sparx5_vcap_is2_port_keys(sparx5, admin, port, out);
		sparx5_vcap_is2_port_stickies(sparx5, admin, out);
		break;
	default:
		out->prf(out->dst, "  no info\n");
		break;
	}
	return 0;
}
+356 −45

File changed.

Preview size limit exceeded, changes collapsed.

Loading