linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP
@ 2022-10-28 14:45 Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 1/5] net: microchip: sparx5: Differentiate IPv4 and IPv6 traffic in keyset config Steen Hegelund
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-28 14:45 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, Daniel Machon, Horatiu Vultur,
	Lars Povlsen

This provides extended tc flower filter key support for the Sparx5 VCAP
functionality.

It builds on top of the initial IS2 VCAP support found in this series:

https://lore.kernel.org/all/20221020130904.1215072-1-steen.hegelund@microchip.com/

Overview:
=========

The added flower filter key (dissector) support is this:

- ipv4_addr (sip and dip)
- ipv6_addr (sip and dip)
- control (IPv4 fragments)
- portnum (tcp and udp port numbers)
- basic (L3 and L4 protocol)
- vlan (outer vlan tag info)
- tcp (tcp flags)
- ip (tos field)

The IS2 VCAP supports classified VLAN information which amounts to the
outer VLAN info in case of multiple tags.

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

Before frames can match IS2 VCAP rules with e.g an IPv4 source address, the
IS2 VCAPs keyset configuration must include keyset that contains a IPv4
source address and this must be configured for the lookup/port/traffic-type
that you want to match on.

The Sparx5 IS2 VCAP has the following traffic types:

- Non-Ethernet frames
- IPv4 Unicast frames
- IPv4 Multicast frames
- IPv6 Unicast frames
- IPv6 Multicast frames
- ARP frames

So to cover IPv4 traffic the two IPv4 categories must be configured with a
keyset that contains IPv4 address information such as the
VCAP_KFS_IP4_TCP_UDP keyset.

The IPv4 and IPv6 traffic types are configured with useful default keysets,
in later series we will use the tc template functionality when we want to
change these defaults.

Delivery:
=========

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

Version History:
================
v2      Split one of the KUNIT tests into 3 tests to fix a kernel robot
        build warning.

v1      Initial version

Steen Hegelund (5):
  net: microchip: sparx5: Differentiate IPv4 and IPv6 traffic in keyset
    config
  net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  net: microchip: sparx5: Match keys in configured port keysets
  net: microchip: sparx5: Let VCAP API validate added key- and
    actionfields
  net: microchip: sparx5: Adding KUNIT tests of key/action values in
    VCAP API

 .../microchip/sparx5/sparx5_tc_flower.c       | 410 +++++++++++++++-
 .../microchip/sparx5/sparx5_vcap_impl.c       | 168 ++++++-
 .../net/ethernet/microchip/vcap/vcap_api.c    | 251 +++++++++-
 .../ethernet/microchip/vcap/vcap_api_client.h |  13 +
 .../ethernet/microchip/vcap/vcap_api_kunit.c  | 447 ++++++++++++++++++
 5 files changed, 1256 insertions(+), 33 deletions(-)

-- 
2.38.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 1/5] net: microchip: sparx5: Differentiate IPv4 and IPv6 traffic in keyset config
  2022-10-28 14:45 [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP Steen Hegelund
@ 2022-10-28 14:45 ` Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP Steen Hegelund
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-28 14:45 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, Daniel Machon, Horatiu Vultur,
	Lars Povlsen

This changes the port keyset configuration for Sparx5 IS2 so that

- IPv4 generates a IP4_TCP_UDP keyset for IPv4 TCP/UDP frames and a
  IP4_OTHER keyset for other IPv4 frames (both UC and MC)
- IPv6 generates a IP_7TUPLE keyset (both UC and MC)

ARP and non-IP traffic continues to generate the MAC_ETYPE keyset

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
 .../microchip/sparx5/sparx5_vcap_impl.c       | 21 ++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
index 50153264179e..e4428d55af2b 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
@@ -21,6 +21,14 @@
 #define STREAMSIZE (64 * 4)  /* bytes in the VCAP cache area */
 
 #define SPARX5_IS2_LOOKUPS 4
+#define VCAP_IS2_KEYSEL(_ena, _noneth, _v4_mc, _v4_uc, _v6_mc, _v6_uc, _arp) \
+	(ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(_ena) | \
+	 ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(_noneth) | \
+	 ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(_v4_mc) | \
+	 ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(_v4_uc) | \
+	 ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(_v6_mc) | \
+	 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 */
 
@@ -368,13 +376,12 @@ static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5,
 	/* all traffic types generate the MAC_ETYPE keyset for now in all
 	 * lookups on all ports
 	 */
-	keysel = ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(true) |
-		ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(VCAP_IS2_PS_NONETH_MAC_ETYPE) |
-		ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(VCAP_IS2_PS_IPV4_MC_MAC_ETYPE) |
-		ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(VCAP_IS2_PS_IPV4_UC_MAC_ETYPE) |
-		ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(VCAP_IS2_PS_IPV6_MC_MAC_ETYPE) |
-		ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(VCAP_IS2_PS_IPV6_UC_MAC_ETYPE) |
-		ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(VCAP_IS2_PS_ARP_MAC_ETYPE);
+	keysel = VCAP_IS2_KEYSEL(true, VCAP_IS2_PS_NONETH_MAC_ETYPE,
+				 VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
+				 VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
+				 VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
+				 VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
+				 VCAP_IS2_PS_ARP_MAC_ETYPE);
 	for (lookup = 0; lookup < admin->lookups; ++lookup) {
 		for (portno = 0; portno < SPX5_PORTS; ++portno) {
 			spx5_wr(keysel, sparx5,
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-10-28 14:45 [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 1/5] net: microchip: sparx5: Differentiate IPv4 and IPv6 traffic in keyset config Steen Hegelund
@ 2022-10-28 14:45 ` Steen Hegelund
  2022-10-31 10:44   ` Casper Andersson
  2022-10-28 14:45 ` [PATCH net-next v2 3/5] net: microchip: sparx5: Match keys in configured port keysets Steen Hegelund
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Steen Hegelund @ 2022-10-28 14:45 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, Daniel Machon, Horatiu Vultur,
	Lars Povlsen

This adds the following TC flower filter keys to Sparx5 for IS2:

- ipv4_addr (sip and dip)
- ipv6_addr (sip and dip)
- control (IPv4 fragments)
- portnum (tcp and udp port numbers)
- basic (L3 and L4 protocol)
- vlan (outer vlan tag info)
- tcp (tcp flags)
- ip (tos field)

as well as an 128 bit keyfield interface on the VCAP API to set the IPv6
addresses.

IS2 supports the classified VLAN information which amounts to the outer
VLAN info in case of multiple tags.

Here are some examples of the tc flower filter operations that are now
supported for the IS2 VCAP:

- IPv4 Addresses
    tc filter add dev eth12 ingress chain 8000000 prio 12 handle 12 \
        protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
        action trap

- IPv6 Addresses
    tc filter add dev eth12 ingress chain 8000000 prio 13 handle 13 \
        protocol ipv6 flower skip_sw dst_ip 1::1:1 src_ip 2::2:2    \
        action trap

- IPv4 fragments
    tc filter add dev eth12 ingress chain 8000000 prio 14 handle 14 \
        protocol ip flower skip_sw dst_ip 3.0.3.3 src_ip 2.0.2.2    \
        ip_flags frag/nofirstfrag action trap

- TCP and UDP portnumbers
    tc filter add dev eth12 ingress chain 8000000 prio 21 handle 21 \
        protocol ip flower skip_sw dst_ip 8.8.8.8 src_ip 2.0.2.2    \
        ip_proto tcp dst_port 100 src_port 12000 action trap
    tc filter add dev eth12 ingress chain 8000000 prio 23 handle 23 \
        protocol ipv6 flower skip_sw dst_ip 5::5:5 src_ip 2::2:2    \
        ip_proto tcp dst_port 300 src_port 13000 action trap

- Layer 3 and Layer 4 protocol info
    tc filter add dev eth12 ingress chain 8000000 prio 28 handle 28 \
        protocol ipv4 flower skip_sw dst_ip 9.0.9.9 src_ip 2.0.2.2  \
        ip_proto icmp action trap

- VLAN tag info (outer tag)
    tc filter add dev eth12 ingress chain 8000000 prio 29 handle 29 \
        protocol 802.1q flower skip_sw vlan_id 600 vlan_prio 6      \
        vlan_ethtype ipv4 action trap
    tc filter add dev eth12 ingress chain 8000000 prio 31 handle 31 \
        protocol 802.1q flower skip_sw vlan_id 600 vlan_prio 5      \
        vlan_ethtype ipv6 action trap

- TCP flags
    tc filter add dev eth12 ingress chain 8000000 prio 15 handle 15 \
        protocol ip flower skip_sw dst_ip 4.0.4.4 src_ip 2.0.2.2    \
        ip_proto tcp tcp_flags 0x2a/0x3f action trap

- IP info (IPv4 TOS field)
    tc filter add dev eth12 ingress chain 8000000 prio 16 handle 16 \
        protocol ip flower skip_sw ip_tos 0x35 dst_ip 5.0.5.5       \
        src_ip 2.0.2.2 action trap

The "protocol all" selection is not supported yet.

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
 .../microchip/sparx5/sparx5_tc_flower.c       | 384 +++++++++++++++++-
 .../net/ethernet/microchip/vcap/vcap_api.c    |  11 +
 .../ethernet/microchip/vcap/vcap_api_client.h |   2 +
 3 files changed, 396 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 626558a5c850..13bc6bff4c1e 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
@@ -16,9 +16,32 @@ struct sparx5_tc_flower_parse_usage {
 	struct flow_cls_offload *fco;
 	struct flow_rule *frule;
 	struct vcap_rule *vrule;
+	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_IP,
+	ETH_P_IPV6,
+};
+
+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;
@@ -54,9 +77,368 @@ static int sparx5_tc_flower_handler_ethaddr_usage(struct sparx5_tc_flower_parse_
 	return err;
 }
 
+static int
+sparx5_tc_flower_handler_ipv4_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	int err = 0;
+
+	if (st->l3_proto == ETH_P_IP) {
+		struct flow_match_ipv4_addrs mt;
+
+		flow_rule_match_ipv4_addrs(st->frule, &mt);
+		if (mt.mask->src) {
+			err = vcap_rule_add_key_u32(st->vrule,
+						    VCAP_KF_L3_IP4_SIP,
+						    be32_to_cpu(mt.key->src),
+						    be32_to_cpu(mt.mask->src));
+			if (err)
+				goto out;
+		}
+		if (mt.mask->dst) {
+			err = vcap_rule_add_key_u32(st->vrule,
+						    VCAP_KF_L3_IP4_DIP,
+						    be32_to_cpu(mt.key->dst),
+						    be32_to_cpu(mt.mask->dst));
+			if (err)
+				goto out;
+		}
+	}
+
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS);
+
+	return err;
+
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_ipv6_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	int err = 0;
+
+	if (st->l3_proto == ETH_P_IPV6) {
+		struct flow_match_ipv6_addrs mt;
+		struct vcap_u128_key sip;
+		struct vcap_u128_key dip;
+
+		flow_rule_match_ipv6_addrs(st->frule, &mt);
+		/* Check if address masks are non-zero */
+		if (!ipv6_addr_any(&mt.mask->src)) {
+			vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16);
+			vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16);
+			err = vcap_rule_add_key_u128(st->vrule,
+						     VCAP_KF_L3_IP6_SIP, &sip);
+			if (err)
+				goto out;
+		}
+		if (!ipv6_addr_any(&mt.mask->dst)) {
+			vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16);
+			vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16);
+			err = vcap_rule_add_key_u128(st->vrule,
+						     VCAP_KF_L3_IP6_DIP, &dip);
+			if (err)
+				goto out;
+		}
+	}
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS);
+	return err;
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_control_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	struct flow_match_control mt;
+	u32 value, mask;
+	int err = 0;
+
+	flow_rule_match_control(st->frule, &mt);
+
+	if (mt.mask->flags) {
+		if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) {
+			if (mt.key->flags & FLOW_DIS_FIRST_FRAG) {
+				value = 1; /* initial fragment */
+				mask = 0x3;
+			} else {
+				if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+					value = 3; /* follow up fragment */
+					mask = 0x3;
+				} else {
+					value = 0; /* no fragment */
+					mask = 0x3;
+				}
+			}
+		} else {
+			if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+				value = 3; /* follow up fragment */
+				mask = 0x3;
+			} else {
+				value = 0; /* no fragment */
+				mask = 0x3;
+			}
+		}
+
+		err = vcap_rule_add_key_u32(st->vrule,
+					    VCAP_KF_L3_FRAGMENT_TYPE,
+					    value, mask);
+		if (err)
+			goto out;
+	}
+
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);
+
+	return err;
+
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_portnum_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	struct flow_match_ports mt;
+	u16 value, mask;
+	int err = 0;
+
+	flow_rule_match_ports(st->frule, &mt);
+
+	if (mt.mask->src) {
+		value = be16_to_cpu(mt.key->src);
+		mask = be16_to_cpu(mt.mask->src);
+		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value,
+					    mask);
+		if (err)
+			goto out;
+	}
+
+	if (mt.mask->dst) {
+		value = be16_to_cpu(mt.key->dst);
+		mask = be16_to_cpu(mt.mask->dst);
+		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value,
+					    mask);
+		if (err)
+			goto out;
+	}
+
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS);
+
+	return err;
+
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_basic_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	struct flow_match_basic mt;
+	int err = 0;
+
+	flow_rule_match_basic(st->frule, &mt);
+
+	if (mt.mask->n_proto) {
+		st->l3_proto = be16_to_cpu(mt.key->n_proto);
+		if (!sparx5_tc_is_known_etype(st->l3_proto)) {
+			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
+						    st->l3_proto, ~0);
+			if (err)
+				goto out;
+		} else if (st->l3_proto == ETH_P_IP) {
+			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
+						    VCAP_BIT_1);
+			if (err)
+				goto out;
+		} else if (st->l3_proto == ETH_P_IPV6) {
+			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
+						    VCAP_BIT_0);
+			if (err)
+				goto out;
+		}
+	}
+
+	if (mt.mask->ip_proto) {
+		st->l4_proto = mt.key->ip_proto;
+		if (st->l4_proto == IPPROTO_TCP) {
+			err = vcap_rule_add_key_bit(st->vrule,
+						    VCAP_KF_TCP_IS,
+						    VCAP_BIT_1);
+			if (err)
+				goto out;
+		} else if (st->l4_proto == IPPROTO_UDP) {
+			err = vcap_rule_add_key_bit(st->vrule,
+						    VCAP_KF_TCP_IS,
+						    VCAP_BIT_0);
+			if (err)
+				goto out;
+		} else {
+			err = vcap_rule_add_key_u32(st->vrule,
+						    VCAP_KF_L3_IP_PROTO,
+						    st->l4_proto, ~0);
+			if (err)
+				goto out;
+		}
+	}
+
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC);
+
+	return err;
+
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_vlan_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS;
+	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS;
+	struct flow_match_vlan mt;
+	int err;
+
+	flow_rule_match_vlan(st->frule, &mt);
+
+	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_VLAN);
+
+	return err;
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_tcp_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	struct flow_match_tcp mt;
+	u16 tcp_flags_mask;
+	u16 tcp_flags_key;
+	enum vcap_bit val;
+	int err = 0;
+
+	flow_rule_match_tcp(st->frule, &mt);
+	tcp_flags_key = be16_to_cpu(mt.key->flags);
+	tcp_flags_mask = be16_to_cpu(mt.mask->flags);
+
+	if (tcp_flags_mask & TCPHDR_FIN) {
+		val = VCAP_BIT_0;
+		if (tcp_flags_key & TCPHDR_FIN)
+			val = VCAP_BIT_1;
+		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val);
+		if (err)
+			goto out;
+	}
+
+	if (tcp_flags_mask & TCPHDR_SYN) {
+		val = VCAP_BIT_0;
+		if (tcp_flags_key & TCPHDR_SYN)
+			val = VCAP_BIT_1;
+		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val);
+		if (err)
+			goto out;
+	}
+
+	if (tcp_flags_mask & TCPHDR_RST) {
+		val = VCAP_BIT_0;
+		if (tcp_flags_key & TCPHDR_RST)
+			val = VCAP_BIT_1;
+		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val);
+		if (err)
+			goto out;
+	}
+
+	if (tcp_flags_mask & TCPHDR_PSH) {
+		val = VCAP_BIT_0;
+		if (tcp_flags_key & TCPHDR_PSH)
+			val = VCAP_BIT_1;
+		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val);
+		if (err)
+			goto out;
+	}
+
+	if (tcp_flags_mask & TCPHDR_ACK) {
+		val = VCAP_BIT_0;
+		if (tcp_flags_key & TCPHDR_ACK)
+			val = VCAP_BIT_1;
+		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val);
+		if (err)
+			goto out;
+	}
+
+	if (tcp_flags_mask & TCPHDR_URG) {
+		val = VCAP_BIT_0;
+		if (tcp_flags_key & TCPHDR_URG)
+			val = VCAP_BIT_1;
+		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val);
+		if (err)
+			goto out;
+	}
+
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP);
+
+	return err;
+
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error");
+	return err;
+}
+
+static int
+sparx5_tc_flower_handler_ip_usage(struct sparx5_tc_flower_parse_usage *st)
+{
+	struct flow_match_ip mt;
+	int err = 0;
+
+	flow_rule_match_ip(st->frule, &mt);
+
+	if (mt.mask->tos) {
+		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS,
+					    mt.key->tos,
+					    mt.mask->tos);
+		if (err)
+			goto out;
+	}
+
+	st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IP);
+
+	return err;
+
+out:
+	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error");
+	return err;
+}
+
 static int (*sparx5_tc_flower_usage_handlers[])(struct sparx5_tc_flower_parse_usage *st) = {
-	/* More dissector handlers will be added here later */
 	[FLOW_DISSECTOR_KEY_ETH_ADDRS] = sparx5_tc_flower_handler_ethaddr_usage,
+	[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = sparx5_tc_flower_handler_ipv4_usage,
+	[FLOW_DISSECTOR_KEY_IPV6_ADDRS] = sparx5_tc_flower_handler_ipv6_usage,
+	[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_VLAN] = sparx5_tc_flower_handler_vlan_usage,
+	[FLOW_DISSECTOR_KEY_TCP] = sparx5_tc_flower_handler_tcp_usage,
+	[FLOW_DISSECTOR_KEY_IP] = sparx5_tc_flower_handler_ip_usage,
 };
 
 static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco,
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index d255bc7deae7..ace2582d8552 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -1073,6 +1073,17 @@ int vcap_rule_add_key_u72(struct vcap_rule *rule, enum vcap_key_field key,
 }
 EXPORT_SYMBOL_GPL(vcap_rule_add_key_u72);
 
+/* Add a 128 bit key with value and mask to the rule */
+int vcap_rule_add_key_u128(struct vcap_rule *rule, enum vcap_key_field key,
+			   struct vcap_u128_key *fieldval)
+{
+	struct vcap_client_keyfield_data data;
+
+	memcpy(&data.u128, fieldval, sizeof(data.u128));
+	return vcap_rule_add_key(rule, key, VCAP_FIELD_U128, &data);
+}
+EXPORT_SYMBOL_GPL(vcap_rule_add_key_u128);
+
 static void vcap_copy_from_client_actionfield(struct vcap_rule *rule,
 					      struct vcap_client_actionfield *field,
 					      struct vcap_client_actionfield_data *data)
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h
index 5df6808679ff..577395402a9a 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h
@@ -176,6 +176,8 @@ int vcap_rule_add_key_u48(struct vcap_rule *rule, enum vcap_key_field key,
 			  struct vcap_u48_key *fieldval);
 int vcap_rule_add_key_u72(struct vcap_rule *rule, enum vcap_key_field key,
 			  struct vcap_u72_key *fieldval);
+int vcap_rule_add_key_u128(struct vcap_rule *rule, enum vcap_key_field key,
+			   struct vcap_u128_key *fieldval);
 int vcap_rule_add_action_bit(struct vcap_rule *rule,
 			     enum vcap_action_field action, enum vcap_bit val);
 int vcap_rule_add_action_u32(struct vcap_rule *rule,
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 3/5] net: microchip: sparx5: Match keys in configured port keysets
  2022-10-28 14:45 [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 1/5] net: microchip: sparx5: Differentiate IPv4 and IPv6 traffic in keyset config Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP Steen Hegelund
@ 2022-10-28 14:45 ` Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 4/5] net: microchip: sparx5: Let VCAP API validate added key- and actionfields Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 5/5] net: microchip: sparx5: Adding KUNIT tests of key/action values in VCAP API Steen Hegelund
  4 siblings, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-28 14:45 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, Daniel Machon, Horatiu Vultur,
	Lars Povlsen

This tries to match the keys in a rule with the keysets supported by the
VCAP instance, and generate a list of keysets.

This list is then validated against the list of keysets that is currently
selected for the lookups (per port) in the VCAP configuration.

The Sparx5 IS2 only has one actionset, so there is no actionset matching
performed for now.

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
 .../microchip/sparx5/sparx5_tc_flower.c       |  26 ++--
 .../microchip/sparx5/sparx5_vcap_impl.c       | 147 +++++++++++++++++-
 .../net/ethernet/microchip/vcap/vcap_api.c    | 137 ++++++++++++++--
 .../ethernet/microchip/vcap/vcap_api_client.h |  11 ++
 4 files changed, 298 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
index 13bc6bff4c1e..9b90e7d5517b 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
@@ -443,11 +443,13 @@ static int (*sparx5_tc_flower_usage_handlers[])(struct sparx5_tc_flower_parse_us
 
 static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco,
 				    struct vcap_admin *admin,
-				    struct vcap_rule *vrule)
+				    struct vcap_rule *vrule,
+				    u16 *l3_proto)
 {
 	struct sparx5_tc_flower_parse_usage state = {
 		.fco = fco,
 		.vrule = vrule,
+		.l3_proto = ETH_P_ALL,
 	};
 	int idx, err = 0;
 
@@ -461,6 +463,15 @@ static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco,
 		if (err)
 			return err;
 	}
+
+	if (state.frule->match.dissector->used_keys ^ state.used_keys) {
+		NL_SET_ERR_MSG_MOD(fco->common.extack,
+				   "Unsupported match item");
+		return -ENOENT;
+	}
+
+	if (l3_proto)
+		*l3_proto = state.l3_proto;
 	return err;
 }
 
@@ -473,6 +484,7 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
 	struct vcap_control *vctrl;
 	struct flow_rule *frule;
 	struct vcap_rule *vrule;
+	u16 l3_proto;
 	int err, idx;
 
 	frule = flow_cls_offload_flow_rule(fco);
@@ -491,7 +503,7 @@ 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);
+	sparx5_tc_use_dissectors(fco, admin, vrule, &l3_proto);
 	flow_action_for_each(idx, act, &frule->action) {
 		switch (act->id) {
 		case FLOW_ACTION_TRAP:
@@ -528,14 +540,8 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
 			goto out;
 		}
 	}
-	/* For now the keyset is hardcoded */
-	err = vcap_set_rule_set_keyset(vrule, VCAP_KFS_MAC_ETYPE);
-	if (err) {
-		NL_SET_ERR_MSG_MOD(fco->common.extack,
-				   "No matching port keyset for filter protocol and keys");
-		goto out;
-	}
-	err = vcap_val_rule(vrule, ETH_P_ALL);
+	/* provide the l3 protocol to guide the keyset selection */
+	err = vcap_val_rule(vrule, l3_proto);
 	if (err) {
 		vcap_set_tc_exterr(fco, vrule);
 		goto out;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
index e4428d55af2b..642c27299e22 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
@@ -160,7 +160,7 @@ static const char *sparx5_vcap_keyset_name(struct net_device *ndev,
 {
 	struct sparx5_port *port = netdev_priv(ndev);
 
-	return port->sparx5->vcap_ctrl->stats->keyfield_set_names[keyset];
+	return vcap_keyset_name(port->sparx5->vcap_ctrl, keyset);
 }
 
 /* Check if this is the first lookup of IS2 */
@@ -204,6 +204,127 @@ static void sparx5_vcap_add_wide_port_mask(struct vcap_rule *rule,
 	vcap_rule_add_key_u72(rule, VCAP_KF_IF_IGR_PORT_MASK, &port_mask);
 }
 
+/* Convert chain id to vcap lookup id */
+static int sparx5_vcap_cid_to_lookup(int cid)
+{
+	int lookup = 0;
+
+	/* For now only handle IS2 */
+	if (cid >= SPARX5_VCAP_CID_IS2_L1 && cid < SPARX5_VCAP_CID_IS2_L2)
+		lookup = 1;
+	else if (cid >= SPARX5_VCAP_CID_IS2_L2 && cid < SPARX5_VCAP_CID_IS2_L3)
+		lookup = 2;
+	else if (cid >= SPARX5_VCAP_CID_IS2_L3 && cid < SPARX5_VCAP_CID_IS2_MAX)
+		lookup = 3;
+
+	return lookup;
+}
+
+/* Return the list of keysets for the vcap port configuration */
+static int sparx5_vcap_is2_get_port_keysets(struct net_device *ndev,
+					    int lookup,
+					    struct vcap_keyset_list *keysetlist,
+					    u16 l3_proto)
+{
+	struct sparx5_port *port = netdev_priv(ndev);
+	struct sparx5 *sparx5 = port->sparx5;
+	int portno = port->portno;
+	u32 value;
+
+	/* Check if the port keyset selection is enabled */
+	value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
+	if (!ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_GET(value))
+		return -ENOENT;
+
+	/* Collect all keysets for the port in a list */
+	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
+		switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) {
+		case VCAP_IS2_PS_ARP_MAC_ETYPE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
+			break;
+		case VCAP_IS2_PS_ARP_ARP:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
+			break;
+		}
+	}
+
+	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
+		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) {
+		case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
+			break;
+		case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
+			break;
+		case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
+			break;
+		}
+
+		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) {
+		case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
+			break;
+		case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
+			break;
+		case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
+			break;
+		}
+	}
+
+	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
+		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) {
+		case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
+			break;
+		case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
+			break;
+		case VCAP_IS2_PS_IPV6_UC_IP6_STD:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
+			break;
+		case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
+			break;
+		}
+
+		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) {
+		case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
+			break;
+		case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
+			break;
+		case VCAP_IS2_PS_IPV6_MC_IP6_STD:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
+			break;
+		case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER:
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
+			break;
+		case VCAP_IS2_PS_IPV6_MC_IP6_VID:
+			/* Not used */
+			break;
+		}
+	}
+
+	if (l3_proto != ETH_P_ARP && l3_proto != ETH_P_IP &&
+	    l3_proto != ETH_P_IPV6) {
+		switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) {
+		case VCAP_IS2_PS_NONETH_MAC_ETYPE:
+			/* IS2 non-classified frames generate MAC_ETYPE */
+			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
+			break;
+		}
+	}
+	return 0;
+}
+
 /* API callback used for validating a field keyset (check the port keysets) */
 static enum vcap_keyfield_set
 sparx5_vcap_validate_keyset(struct net_device *ndev,
@@ -212,10 +333,30 @@ sparx5_vcap_validate_keyset(struct net_device *ndev,
 			    struct vcap_keyset_list *kslist,
 			    u16 l3_proto)
 {
+	struct vcap_keyset_list keysetlist = {};
+	enum vcap_keyfield_set keysets[10] = {};
+	int idx, jdx, lookup;
+
 	if (!kslist || kslist->cnt == 0)
 		return VCAP_KFS_NO_VALUE;
-	/* for now just return whatever the API suggests */
-	return kslist->keysets[0];
+
+	/* Get a list of currently configured keysets in the lookups */
+	lookup = sparx5_vcap_cid_to_lookup(rule->vcap_chain_id);
+	keysetlist.max = ARRAY_SIZE(keysets);
+	keysetlist.keysets = keysets;
+	sparx5_vcap_is2_get_port_keysets(ndev, lookup, &keysetlist, l3_proto);
+
+	/* Check if there is a match and return the match */
+	for (idx = 0; idx < kslist->cnt; ++idx)
+		for (jdx = 0; jdx < keysetlist.cnt; ++jdx)
+			if (kslist->keysets[idx] == keysets[jdx])
+				return kslist->keysets[idx];
+
+	pr_err("%s:%d: %s not supported in port key selection\n",
+	       __func__, __LINE__,
+	       sparx5_vcap_keyset_name(ndev, kslist->keysets[0]));
+
+	return -ENOENT;
 }
 
 /* API callback used for adding default fields to a rule */
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index ace2582d8552..9e67ea814768 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -704,15 +704,115 @@ static int vcap_add_type_keyfield(struct vcap_rule *rule)
 	return 0;
 }
 
+/* Add a keyset to a keyset list */
+bool vcap_keyset_list_add(struct vcap_keyset_list *keysetlist,
+			  enum vcap_keyfield_set keyset)
+{
+	int idx;
+
+	if (keysetlist->cnt < keysetlist->max) {
+		/* Avoid duplicates */
+		for (idx = 0; idx < keysetlist->cnt; ++idx)
+			if (keysetlist->keysets[idx] == keyset)
+				return keysetlist->cnt < keysetlist->max;
+		keysetlist->keysets[keysetlist->cnt++] = keyset;
+	}
+	return keysetlist->cnt < keysetlist->max;
+}
+EXPORT_SYMBOL_GPL(vcap_keyset_list_add);
+
+/* map keyset id to a string with the keyset name */
+const char *vcap_keyset_name(struct vcap_control *vctrl,
+			     enum vcap_keyfield_set keyset)
+{
+	return vctrl->stats->keyfield_set_names[keyset];
+}
+EXPORT_SYMBOL_GPL(vcap_keyset_name);
+
+/* map key field id to a string with the key name */
+const char *vcap_keyfield_name(struct vcap_control *vctrl,
+			       enum vcap_key_field key)
+{
+	return vctrl->stats->keyfield_names[key];
+}
+EXPORT_SYMBOL_GPL(vcap_keyfield_name);
+
+/* Return the keyfield that matches a key in a keyset */
+static const struct vcap_field *
+vcap_find_keyset_keyfield(struct vcap_control *vctrl,
+			  enum vcap_type vtype,
+			  enum vcap_keyfield_set keyset,
+			  enum vcap_key_field key)
+{
+	const struct vcap_field *fields;
+	int idx, count;
+
+	fields = vcap_keyfields(vctrl, vtype, keyset);
+	if (!fields)
+		return NULL;
+
+	/* Iterate the keyfields of the keyset */
+	count = vcap_keyfield_count(vctrl, vtype, keyset);
+	for (idx = 0; idx < count; ++idx) {
+		if (fields[idx].width == 0)
+			continue;
+
+		if (key == idx)
+			return &fields[idx];
+	}
+
+	return NULL;
+}
+
+/* Match a list of keys against the keysets available in a vcap type */
+static bool vcap_rule_find_keysets(struct vcap_rule_internal *ri,
+				   struct vcap_keyset_list *matches)
+{
+	const struct vcap_client_keyfield *ckf;
+	int keyset, found, keycount, map_size;
+	const struct vcap_field **map;
+	enum vcap_type vtype;
+
+	vtype = ri->admin->vtype;
+	map = ri->vctrl->vcaps[vtype].keyfield_set_map;
+	map_size = ri->vctrl->vcaps[vtype].keyfield_set_size;
+
+	/* Get a count of the keyfields we want to match */
+	keycount = 0;
+	list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list)
+		++keycount;
+
+	matches->cnt = 0;
+	/* Iterate the keysets of the VCAP */
+	for (keyset = 0; keyset < map_size; ++keyset) {
+		if (!map[keyset])
+			continue;
+
+		/* Iterate the keys in the rule */
+		found = 0;
+		list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list)
+			if (vcap_find_keyset_keyfield(ri->vctrl, vtype,
+						      keyset, ckf->ctrl.key))
+				++found;
+
+		/* Save the keyset if all keyfields were found */
+		if (found == keycount)
+			if (!vcap_keyset_list_add(matches, keyset))
+				/* bail out when the quota is filled */
+				break;
+	}
+
+	return matches->cnt > 0;
+}
+
 /* Validate a rule with respect to available port keys */
 int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto)
 {
 	struct vcap_rule_internal *ri = to_intrule(rule);
+	struct vcap_keyset_list matches = {};
 	enum vcap_keyfield_set keysets[10];
-	struct vcap_keyset_list kslist;
 	int ret;
 
-	/* This validation will be much expanded later */
 	ret = vcap_api_check(ri->vctrl);
 	if (ret)
 		return ret;
@@ -724,24 +824,41 @@ int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto)
 		ri->data.exterr = VCAP_ERR_NO_NETDEV;
 		return -EINVAL;
 	}
+
+	matches.keysets = keysets;
+	matches.max = ARRAY_SIZE(keysets);
 	if (ri->data.keyset == VCAP_KFS_NO_VALUE) {
-		ri->data.exterr = VCAP_ERR_NO_KEYSET_MATCH;
-		return -EINVAL;
+		/* Iterate over rule keyfields and select keysets that fits */
+		if (!vcap_rule_find_keysets(ri, &matches)) {
+			ri->data.exterr = VCAP_ERR_NO_KEYSET_MATCH;
+			return -EINVAL;
+		}
+	} else {
+		/* prepare for keyset validation */
+		keysets[0] = ri->data.keyset;
+		matches.cnt = 1;
 	}
-	/* prepare for keyset validation */
-	keysets[0] = ri->data.keyset;
-	kslist.keysets = keysets;
-	kslist.cnt = 1;
+
 	/* Pick a keyset that is supported in the port lookups */
-	ret = ri->vctrl->ops->validate_keyset(ri->ndev, ri->admin, rule, &kslist,
-					      l3_proto);
+	ret = ri->vctrl->ops->validate_keyset(ri->ndev, ri->admin, rule,
+					      &matches, l3_proto);
 	if (ret < 0) {
 		pr_err("%s:%d: keyset validation failed: %d\n",
 		       __func__, __LINE__, ret);
 		ri->data.exterr = VCAP_ERR_NO_PORT_KEYSET_MATCH;
 		return ret;
 	}
+	/* use the keyset that is supported in the port lookups */
+	ret = vcap_set_rule_set_keyset(rule, ret);
+	if (ret < 0) {
+		pr_err("%s:%d: keyset was not updated: %d\n",
+		       __func__, __LINE__, ret);
+		return ret;
+	}
 	if (ri->data.actionset == VCAP_AFS_NO_VALUE) {
+		/* Later also actionsets will be matched against actions in
+		 * the rule, and the type will be set accordingly
+		 */
 		ri->data.exterr = VCAP_ERR_NO_ACTIONSET_MATCH;
 		return -EINVAL;
 	}
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h
index 577395402a9a..959e125baa3f 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h
@@ -201,4 +201,15 @@ void vcap_set_tc_exterr(struct flow_cls_offload *fco, struct vcap_rule *vrule);
 /* Cleanup a VCAP instance */
 int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin);
 
+/* Add a keyset to a keyset list */
+bool vcap_keyset_list_add(struct vcap_keyset_list *keysetlist,
+			  enum vcap_keyfield_set keyset);
+
+/* map keyset id to a string with the keyset name */
+const char *vcap_keyset_name(struct vcap_control *vctrl,
+			     enum vcap_keyfield_set keyset);
+/* map key field id to a string with the key name */
+const char *vcap_keyfield_name(struct vcap_control *vctrl,
+			       enum vcap_key_field key);
+
 #endif /* __VCAP_API_CLIENT__ */
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 4/5] net: microchip: sparx5: Let VCAP API validate added key- and actionfields
  2022-10-28 14:45 [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP Steen Hegelund
                   ` (2 preceding siblings ...)
  2022-10-28 14:45 ` [PATCH net-next v2 3/5] net: microchip: sparx5: Match keys in configured port keysets Steen Hegelund
@ 2022-10-28 14:45 ` Steen Hegelund
  2022-10-28 14:45 ` [PATCH net-next v2 5/5] net: microchip: sparx5: Adding KUNIT tests of key/action values in VCAP API Steen Hegelund
  4 siblings, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-28 14:45 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, Daniel Machon, Horatiu Vultur,
	Lars Povlsen

Add support for validating keyfields and actionfields when they are added
to a VCAP rule.
We need to ensure that the field is not already present and that the field
is in the key- or actionset, if the client has added a key- or actionset to
the rule at this point.

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
---
 .../net/ethernet/microchip/vcap/vcap_api.c    | 103 +++++++++++++++++-
 1 file changed, 101 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 9e67ea814768..69ee34bb392a 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -737,6 +737,13 @@ const char *vcap_keyfield_name(struct vcap_control *vctrl,
 }
 EXPORT_SYMBOL_GPL(vcap_keyfield_name);
 
+/* 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)
+{
+	return vctrl->stats->actionfield_names[action];
+}
+
 /* Return the keyfield that matches a key in a keyset */
 static const struct vcap_field *
 vcap_find_keyset_keyfield(struct vcap_control *vctrl,
@@ -1109,14 +1116,60 @@ static void vcap_copy_from_client_keyfield(struct vcap_rule *rule,
 	memcpy(&field->data, data, sizeof(field->data));
 }
 
+/* Check if the keyfield is already in the rule */
+static bool vcap_keyfield_unique(struct vcap_rule *rule,
+				 enum vcap_key_field key)
+{
+	struct vcap_rule_internal *ri = to_intrule(rule);
+	const struct vcap_client_keyfield *ckf;
+
+	list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list)
+		if (ckf->ctrl.key == key)
+			return false;
+	return true;
+}
+
+/* Check if the keyfield is in the keyset */
+static bool vcap_keyfield_match_keyset(struct vcap_rule *rule,
+				       enum vcap_key_field key)
+{
+	struct vcap_rule_internal *ri = to_intrule(rule);
+	enum vcap_keyfield_set keyset = rule->keyset;
+	enum vcap_type vt = ri->admin->vtype;
+	const struct vcap_field *fields;
+
+	/* the field is accepted if the rule has no keyset yet */
+	if (keyset == VCAP_KFS_NO_VALUE)
+		return true;
+	fields = vcap_keyfields(ri->vctrl, vt, keyset);
+	if (!fields)
+		return false;
+	/* if there is a width there is a way */
+	return fields[key].width > 0;
+}
+
 static int vcap_rule_add_key(struct vcap_rule *rule,
 			     enum vcap_key_field key,
 			     enum vcap_field_type ftype,
 			     struct vcap_client_keyfield_data *data)
 {
+	struct vcap_rule_internal *ri = to_intrule(rule);
 	struct vcap_client_keyfield *field;
 
-	/* More validation will be added here later */
+	if (!vcap_keyfield_unique(rule, key)) {
+		pr_warn("%s:%d: keyfield %s is already in the rule\n",
+			__func__, __LINE__,
+			vcap_keyfield_name(ri->vctrl, key));
+		return -EINVAL;
+	}
+
+	if (!vcap_keyfield_match_keyset(rule, key)) {
+		pr_err("%s:%d: keyfield %s does not belong in the rule keyset\n",
+		       __func__, __LINE__,
+		       vcap_keyfield_name(ri->vctrl, key));
+		return -EINVAL;
+	}
+
 	field = kzalloc(sizeof(*field), GFP_KERNEL);
 	if (!field)
 		return -ENOMEM;
@@ -1209,14 +1262,60 @@ static void vcap_copy_from_client_actionfield(struct vcap_rule *rule,
 	memcpy(&field->data, data, sizeof(field->data));
 }
 
+/* Check if the actionfield is already in the rule */
+static bool vcap_actionfield_unique(struct vcap_rule *rule,
+				    enum vcap_action_field act)
+{
+	struct vcap_rule_internal *ri = to_intrule(rule);
+	const struct vcap_client_actionfield *caf;
+
+	list_for_each_entry(caf, &ri->data.actionfields, ctrl.list)
+		if (caf->ctrl.action == act)
+			return false;
+	return true;
+}
+
+/* Check if the actionfield is in the actionset */
+static bool vcap_actionfield_match_actionset(struct vcap_rule *rule,
+					     enum vcap_action_field action)
+{
+	enum vcap_actionfield_set actionset = rule->actionset;
+	struct vcap_rule_internal *ri = to_intrule(rule);
+	enum vcap_type vt = ri->admin->vtype;
+	const struct vcap_field *fields;
+
+	/* the field is accepted if the rule has no actionset yet */
+	if (actionset == VCAP_AFS_NO_VALUE)
+		return true;
+	fields = vcap_actionfields(ri->vctrl, vt, actionset);
+	if (!fields)
+		return false;
+	/* if there is a width there is a way */
+	return fields[action].width > 0;
+}
+
 static int vcap_rule_add_action(struct vcap_rule *rule,
 				enum vcap_action_field action,
 				enum vcap_field_type ftype,
 				struct vcap_client_actionfield_data *data)
 {
+	struct vcap_rule_internal *ri = to_intrule(rule);
 	struct vcap_client_actionfield *field;
 
-	/* More validation will be added here later */
+	if (!vcap_actionfield_unique(rule, action)) {
+		pr_warn("%s:%d: actionfield %s is already in the rule\n",
+			__func__, __LINE__,
+			vcap_actionfield_name(ri->vctrl, action));
+		return -EINVAL;
+	}
+
+	if (!vcap_actionfield_match_actionset(rule, action)) {
+		pr_err("%s:%d: actionfield %s does not belong in the rule actionset\n",
+		       __func__, __LINE__,
+		       vcap_actionfield_name(ri->vctrl, action));
+		return -EINVAL;
+	}
+
 	field = kzalloc(sizeof(*field), GFP_KERNEL);
 	if (!field)
 		return -ENOMEM;
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v2 5/5] net: microchip: sparx5: Adding KUNIT tests of key/action values in VCAP API
  2022-10-28 14:45 [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP Steen Hegelund
                   ` (3 preceding siblings ...)
  2022-10-28 14:45 ` [PATCH net-next v2 4/5] net: microchip: sparx5: Let VCAP API validate added key- and actionfields Steen Hegelund
@ 2022-10-28 14:45 ` Steen Hegelund
  4 siblings, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-28 14:45 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, Daniel Machon, Horatiu Vultur,
	Lars Povlsen, kernel test robot

This tests that the available keyfield and actionfield add methods are
doing the exepected work: adding the value (and mask) to the
keyfield/actionfield list item in the rule.

The test also covers the functionality that matches a rule to a keyset.

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 .../ethernet/microchip/vcap/vcap_api_kunit.c  | 447 ++++++++++++++++++
 1 file changed, 447 insertions(+)

diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
index b01a6e5039b0..a8b116493719 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
@@ -22,6 +22,7 @@ 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 = {};
 
 /* Callback used by the VCAP API */
 static enum vcap_keyfield_set test_val_keyset(struct net_device *ndev,
@@ -904,6 +905,450 @@ static void vcap_api_encode_rule_actionset_test(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[11]);
 }
 
+static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
+{
+	struct vcap_admin admin = {
+		.vtype = VCAP_TYPE_IS2,
+	};
+	struct vcap_rule_internal ri = {
+		.admin = &admin,
+		.data = {
+			.keyset = VCAP_KFS_NO_VALUE,
+		},
+		.vctrl = &test_vctrl,
+	};
+	struct vcap_rule *rule = (struct vcap_rule *)&ri;
+	struct vcap_client_keyfield *kf;
+	int ret;
+	struct vcap_u128_key dip = {
+		.value = {0x17, 0x26, 0x35, 0x44, 0x63, 0x62, 0x71},
+		.mask = {0xf1, 0xf2, 0xf3, 0xf4, 0x4f, 0x3f, 0x2f, 0x1f},
+	};
+	int idx;
+
+	INIT_LIST_HEAD(&rule->keyfields);
+	ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->keyfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield,
+			      ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_KF_LOOKUP_FIRST_IS, kf->ctrl.key);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.value);
+	KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.mask);
+
+	INIT_LIST_HEAD(&rule->keyfields);
+	ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_1);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->keyfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield,
+			      ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_KF_LOOKUP_FIRST_IS, kf->ctrl.key);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.value);
+	KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.mask);
+
+	INIT_LIST_HEAD(&rule->keyfields);
+	ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
+				    VCAP_BIT_ANY);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->keyfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield,
+			      ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_KF_LOOKUP_FIRST_IS, kf->ctrl.key);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.value);
+	KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.mask);
+
+	INIT_LIST_HEAD(&rule->keyfields);
+	ret = vcap_rule_add_key_u32(rule, VCAP_KF_TYPE, 0x98765432, 0xff00ffab);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->keyfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield,
+			      ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_KF_TYPE, kf->ctrl.key);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, kf->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x98765432, kf->data.u32.value);
+	KUNIT_EXPECT_EQ(test, 0xff00ffab, kf->data.u32.mask);
+
+	INIT_LIST_HEAD(&rule->keyfields);
+	ret = vcap_rule_add_key_u128(rule, VCAP_KF_L3_IP6_SIP, &dip);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->keyfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield,
+			      ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_KF_L3_IP6_SIP, kf->ctrl.key);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_U128, kf->ctrl.type);
+	for (idx = 0; idx < ARRAY_SIZE(dip.value); ++idx)
+		KUNIT_EXPECT_EQ(test, dip.value[idx], kf->data.u128.value[idx]);
+	for (idx = 0; idx < ARRAY_SIZE(dip.mask); ++idx)
+		KUNIT_EXPECT_EQ(test, dip.mask[idx], kf->data.u128.mask[idx]);
+}
+
+static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
+{
+	struct vcap_admin admin = {
+		.vtype = VCAP_TYPE_IS2,
+	};
+	struct vcap_rule_internal ri = {
+		.admin = &admin,
+		.data = {
+			.actionset = VCAP_AFS_NO_VALUE,
+		},
+	};
+	struct vcap_rule *rule = (struct vcap_rule *)&ri;
+	struct vcap_client_actionfield *af;
+	int ret;
+
+	INIT_LIST_HEAD(&rule->actionfields);
+	ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_0);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->actionfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	af = list_first_entry(&rule->actionfields,
+			      struct vcap_client_actionfield, ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x0, af->data.u1.value);
+
+	INIT_LIST_HEAD(&rule->actionfields);
+	ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_1);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->actionfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	af = list_first_entry(&rule->actionfields,
+			      struct vcap_client_actionfield, ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x1, af->data.u1.value);
+
+	INIT_LIST_HEAD(&rule->actionfields);
+	ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_ANY);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->actionfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	af = list_first_entry(&rule->actionfields,
+			      struct vcap_client_actionfield, ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x0, af->data.u1.value);
+
+	INIT_LIST_HEAD(&rule->actionfields);
+	ret = vcap_rule_add_action_u32(rule, VCAP_AF_TYPE, 0x98765432);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->actionfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	af = list_first_entry(&rule->actionfields,
+			      struct vcap_client_actionfield, ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_AF_TYPE, af->ctrl.action);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, af->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0x98765432, af->data.u32.value);
+
+	INIT_LIST_HEAD(&rule->actionfields);
+	ret = vcap_rule_add_action_u32(rule, VCAP_AF_MASK_MODE, 0xaabbccdd);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = list_empty(&rule->actionfields);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	af = list_first_entry(&rule->actionfields,
+			      struct vcap_client_actionfield, ctrl.list);
+	KUNIT_EXPECT_EQ(test, VCAP_AF_MASK_MODE, af->ctrl.action);
+	KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, af->ctrl.type);
+	KUNIT_EXPECT_EQ(test, 0xaabbccdd, af->data.u32.value);
+}
+
+static void vcap_api_rule_find_keyset_basic_test(struct kunit *test)
+{
+	struct vcap_keyset_list matches = {};
+	struct vcap_admin admin = {
+		.vtype = VCAP_TYPE_IS2,
+	};
+	struct vcap_rule_internal ri = {
+		.admin = &admin,
+		.vctrl = &test_vctrl,
+	};
+	struct vcap_client_keyfield ckf[] = {
+		{
+			.ctrl.key = VCAP_KF_TYPE,
+		}, {
+			.ctrl.key = VCAP_KF_LOOKUP_FIRST_IS,
+		}, {
+			.ctrl.key = VCAP_KF_IF_IGR_PORT_MASK_L3,
+		}, {
+			.ctrl.key = VCAP_KF_IF_IGR_PORT_MASK_RNG,
+		}, {
+			.ctrl.key = VCAP_KF_IF_IGR_PORT_MASK,
+		}, {
+			.ctrl.key = VCAP_KF_L2_DMAC,
+		}, {
+			.ctrl.key = VCAP_KF_ETYPE_LEN_IS,
+		}, {
+			.ctrl.key = VCAP_KF_ETYPE,
+		},
+	};
+	int idx;
+	bool ret;
+	enum vcap_keyfield_set keysets[10] = {};
+
+	matches.keysets = keysets;
+	matches.max = ARRAY_SIZE(keysets);
+
+	INIT_LIST_HEAD(&ri.data.keyfields);
+	for (idx = 0; idx < ARRAY_SIZE(ckf); idx++)
+		list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields);
+
+	ret = vcap_rule_find_keysets(&ri, &matches);
+
+	KUNIT_EXPECT_EQ(test, true, ret);
+	KUNIT_EXPECT_EQ(test, 1, matches.cnt);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, matches.keysets[0]);
+}
+
+static void vcap_api_rule_find_keyset_failed_test(struct kunit *test)
+{
+	struct vcap_keyset_list matches = {};
+	struct vcap_admin admin = {
+		.vtype = VCAP_TYPE_IS2,
+	};
+	struct vcap_rule_internal ri = {
+		.admin = &admin,
+		.vctrl = &test_vctrl,
+	};
+	struct vcap_client_keyfield ckf[] = {
+		{
+			.ctrl.key = VCAP_KF_TYPE,
+		}, {
+			.ctrl.key = VCAP_KF_LOOKUP_FIRST_IS,
+		}, {
+			.ctrl.key = VCAP_KF_ARP_OPCODE,
+		}, {
+			.ctrl.key = VCAP_KF_L3_IP4_SIP,
+		}, {
+			.ctrl.key = VCAP_KF_L3_IP4_DIP,
+		}, {
+			.ctrl.key = VCAP_KF_8021Q_PCP_CLS,
+		}, {
+			.ctrl.key = VCAP_KF_ETYPE_LEN_IS, /* Not with ARP */
+		}, {
+			.ctrl.key = VCAP_KF_ETYPE, /* Not with ARP */
+		},
+	};
+	int idx;
+	bool ret;
+	enum vcap_keyfield_set keysets[10] = {};
+
+	matches.keysets = keysets;
+	matches.max = ARRAY_SIZE(keysets);
+
+	INIT_LIST_HEAD(&ri.data.keyfields);
+	for (idx = 0; idx < ARRAY_SIZE(ckf); idx++)
+		list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields);
+
+	ret = vcap_rule_find_keysets(&ri, &matches);
+
+	KUNIT_EXPECT_EQ(test, false, ret);
+	KUNIT_EXPECT_EQ(test, 0, matches.cnt);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_NO_VALUE, matches.keysets[0]);
+}
+
+static void vcap_api_rule_find_keyset_many_test(struct kunit *test)
+{
+	struct vcap_keyset_list matches = {};
+	struct vcap_admin admin = {
+		.vtype = VCAP_TYPE_IS2,
+	};
+	struct vcap_rule_internal ri = {
+		.admin = &admin,
+		.vctrl = &test_vctrl,
+	};
+	struct vcap_client_keyfield ckf[] = {
+		{
+			.ctrl.key = VCAP_KF_TYPE,
+		}, {
+			.ctrl.key = VCAP_KF_LOOKUP_FIRST_IS,
+		}, {
+			.ctrl.key = VCAP_KF_8021Q_DEI_CLS,
+		}, {
+			.ctrl.key = VCAP_KF_8021Q_PCP_CLS,
+		}, {
+			.ctrl.key = VCAP_KF_8021Q_VID_CLS,
+		}, {
+			.ctrl.key = VCAP_KF_ISDX_CLS,
+		}, {
+			.ctrl.key = VCAP_KF_L2_MC_IS,
+		}, {
+			.ctrl.key = VCAP_KF_L2_BC_IS,
+		},
+	};
+	int idx;
+	bool ret;
+	enum vcap_keyfield_set keysets[10] = {};
+
+	matches.keysets = keysets;
+	matches.max = ARRAY_SIZE(keysets);
+
+	INIT_LIST_HEAD(&ri.data.keyfields);
+	for (idx = 0; idx < ARRAY_SIZE(ckf); idx++)
+		list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields);
+
+	ret = vcap_rule_find_keysets(&ri, &matches);
+
+	KUNIT_EXPECT_EQ(test, true, ret);
+	KUNIT_EXPECT_EQ(test, 6, matches.cnt);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_ARP, matches.keysets[0]);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_IP4_OTHER, matches.keysets[1]);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_IP4_TCP_UDP, matches.keysets[2]);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_IP6_STD, matches.keysets[3]);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_IP_7TUPLE, matches.keysets[4]);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, matches.keysets[5]);
+}
+
+static void vcap_api_encode_rule_test(struct kunit *test)
+{
+	/* Data used by VCAP Library callback */
+	static u32 keydata[32] = {};
+	static u32 mskdata[32] = {};
+	static u32 actdata[32] = {};
+
+	struct vcap_admin is2_admin = {
+		.vtype = VCAP_TYPE_IS2,
+		.first_cid = 10000,
+		.last_cid = 19999,
+		.lookups = 4,
+		.last_valid_addr = 3071,
+		.first_valid_addr = 0,
+		.last_used_addr = 800,
+		.cache = {
+			.keystream = keydata,
+			.maskstream = mskdata,
+			.actionstream = actdata,
+		},
+	};
+	struct vcap_rule *rule = 0;
+	struct vcap_rule_internal *ri = 0;
+	int vcap_chain_id = 10005;
+	enum vcap_user user = VCAP_USER_VCAP_UTIL;
+	u16 priority = 10;
+	int id = 100;
+	int ret;
+	struct vcap_u48_key smac = {
+		.value = { 0x88, 0x75, 0x32, 0x34, 0x9e, 0xb1 },
+		.mask = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+	};
+	struct vcap_u48_key dmac = {
+		.value = { 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 },
+		.mask = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+	};
+	u32 port_mask_rng_value = 0x05;
+	u32 port_mask_rng_mask = 0x0f;
+	u32 igr_port_mask_value = 0xffabcd01;
+	u32 igr_port_mask_mask = ~0;
+	/* counter is not written yet, so it is not in expwriteaddr */
+	u32 expwriteaddr[] = {792, 793, 794, 795, 796, 797, 0};
+	int idx;
+
+	vcap_test_api_init(&is2_admin);
+
+	/* Allocate the rule */
+	rule = vcap_alloc_rule(&test_vctrl, &test_netdev, vcap_chain_id, user,
+			       priority, id);
+	KUNIT_EXPECT_PTR_NE(test, NULL, rule);
+	ri = (struct vcap_rule_internal *)rule;
+
+	/* Add rule keys */
+	ret = vcap_rule_add_key_u48(rule, VCAP_KF_L2_DMAC, &dmac);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_key_u48(rule, VCAP_KF_L2_SMAC, &smac);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_key_bit(rule, VCAP_KF_ETYPE_LEN_IS, VCAP_BIT_1);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	/* Cannot add the same field twice */
+	ret = vcap_rule_add_key_bit(rule, VCAP_KF_ETYPE_LEN_IS, VCAP_BIT_1);
+	KUNIT_EXPECT_EQ(test, -EINVAL, ret);
+	ret = vcap_rule_add_key_bit(rule, VCAP_KF_IF_IGR_PORT_MASK_L3,
+				    VCAP_BIT_ANY);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_RNG,
+				    port_mask_rng_value, port_mask_rng_mask);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
+				    igr_port_mask_value, igr_port_mask_mask);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* Add rule actions */
+	ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_1);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_action_u32(rule, VCAP_AF_CNT_ID, id);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_action_u32(rule, VCAP_AF_MATCH_ID, 1);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	ret = vcap_rule_add_action_u32(rule, VCAP_AF_MATCH_ID_MASK, 1);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* For now the actionset is hardcoded */
+	ret = vcap_set_rule_set_actionset(rule, VCAP_AFS_BASE_TYPE);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+
+	/* Validation with validate keyset callback */
+	ret = vcap_val_rule(rule, ETH_P_ALL);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, rule->keyset);
+	KUNIT_EXPECT_EQ(test, VCAP_AFS_BASE_TYPE, rule->actionset);
+	KUNIT_EXPECT_EQ(test, 6, ri->size);
+	KUNIT_EXPECT_EQ(test, 2, ri->keyset_sw_regs);
+	KUNIT_EXPECT_EQ(test, 4, ri->actionset_sw_regs);
+
+	/* Add rule with write callback */
+	ret = vcap_add_rule(rule);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	KUNIT_EXPECT_EQ(test, 792, is2_admin.last_used_addr);
+	for (idx = 0; idx < ARRAY_SIZE(expwriteaddr); ++idx)
+		KUNIT_EXPECT_EQ(test, expwriteaddr[idx], test_updateaddr[idx]);
+
+	/* Check that the rule has been added */
+	ret = list_empty(&is2_admin.rules);
+	KUNIT_EXPECT_EQ(test, false, ret);
+	KUNIT_EXPECT_EQ(test, 0, ret);
+	vcap_free_rule(rule);
+
+	/* Check that the rule has been freed: tricky to access since this
+	 * memory should not be accessible anymore
+	 */
+	KUNIT_EXPECT_PTR_NE(test, NULL, rule);
+	ret = list_empty(&rule->keyfields);
+	KUNIT_EXPECT_EQ(test, true, ret);
+	ret = list_empty(&rule->actionfields);
+	KUNIT_EXPECT_EQ(test, true, ret);
+}
+
+static struct kunit_case vcap_api_full_rule_test_cases[] = {
+	KUNIT_CASE(vcap_api_rule_find_keyset_basic_test),
+	KUNIT_CASE(vcap_api_rule_find_keyset_failed_test),
+	KUNIT_CASE(vcap_api_rule_find_keyset_many_test),
+	KUNIT_CASE(vcap_api_encode_rule_test),
+	{}
+};
+
+static struct kunit_suite vcap_api_full_rule_test_suite = {
+	.name = "VCAP_API_Full_Rule_Testsuite",
+	.test_cases = vcap_api_full_rule_test_cases,
+};
+
+static struct kunit_case vcap_api_rule_value_test_cases[] = {
+	KUNIT_CASE(vcap_api_rule_add_keyvalue_test),
+	KUNIT_CASE(vcap_api_rule_add_actionvalue_test),
+	{}
+};
+
+static struct kunit_suite vcap_api_rule_value_test_suite = {
+	.name = "VCAP_API_Rule_Value_Testsuite",
+	.test_cases = vcap_api_rule_value_test_cases,
+};
+
 static struct kunit_case vcap_api_encoding_test_cases[] = {
 	KUNIT_CASE(vcap_api_set_bit_1_test),
 	KUNIT_CASE(vcap_api_set_bit_0_test),
@@ -930,4 +1375,6 @@ static struct kunit_suite vcap_api_encoding_test_suite = {
 	.test_cases = vcap_api_encoding_test_cases,
 };
 
+kunit_test_suite(vcap_api_full_rule_test_suite);
+kunit_test_suite(vcap_api_rule_value_test_suite);
 kunit_test_suite(vcap_api_encoding_test_suite);
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-10-28 14:45 ` [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP Steen Hegelund
@ 2022-10-31 10:44   ` Casper Andersson
  2022-10-31 12:14     ` Steen Hegelund
  0 siblings, 1 reply; 17+ messages in thread
From: Casper Andersson @ 2022-10-31 10:44 UTC (permalink / raw)
  To: Steen Hegelund
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Steen,

On 2022-10-28 16:45, Steen Hegelund wrote:
> - IPv4 Addresses
>     tc filter add dev eth12 ingress chain 8000000 prio 12 handle 12 \
>         protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
>         action trap

I'm not able to get this working on PCB135. I tested the VLAN tags and
did not work either (did not test the rest). The example from the
previous patch series doesn't work either after applying this series.

tc qdisc add dev eth3 clsact
tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
	protocol all flower skip_sw \
	dst_mac 0a:0b:0c:0d:0e:0f \
	src_mac 2:0:0:0:0:1 \
	action trap

This example was provided in your last patch series and worked earlier.

My setup is PC-eth0 -> PCB135-eth3 and I use the following EasyFrames
command to send packets:

ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f

IPv4:
tc qdisc add dev eth3 clsact
tc filter add dev eth3 ingress chain 8000000 prio 12 handle 12 \
    protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
    action trap

ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f ipv4 dip 1.0.1.1 sip 2.0.2.2

Same setup as above and I can't get this to work either.

I'm using tcpdump to watch the interface to see if the packets are being
trapped or not. Changing the packets' dmac to broadcast lets me see the
packets so I don't have any issue with the setup.

BR,
Casper


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-10-31 10:44   ` Casper Andersson
@ 2022-10-31 12:14     ` Steen Hegelund
  2022-10-31 14:52       ` Casper Andersson
  2022-11-01  1:41       ` Jakub Kicinski
  0 siblings, 2 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-31 12:14 UTC (permalink / raw)
  To: Casper Andersson
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Casper,

First of all thanks for the testing effort (as usual).  This is most welcome.

On Mon, 2022-10-31 at 11:44 +0100, Casper Andersson wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Hi Steen,
> 
> On 2022-10-28 16:45, Steen Hegelund wrote:
> > - IPv4 Addresses
> >     tc filter add dev eth12 ingress chain 8000000 prio 12 handle 12 \
> >         protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
> >         action trap
> 
> I'm not able to get this working on PCB135. I tested the VLAN tags and
> did not work either (did not test the rest). The example from the
> previous patch series doesn't work either after applying this series.


Yes I did not really explain this part (and I will update the series with an explanation).

1) The rule example in the previous series will no longer work as expected as the changes to the
port keyset configuration now requires a non-ip frame to generate the MAC_ETYPE keyset.

So to test the MAC_ETYPE case your rule must be non-ip and not use "protocol all" which is not
supported yet.  

Here is an example using the "protocol 0xbeef":

tc qdisc add dev eth3 clsact
tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
        protocol 0xbeef flower skip_sw \
        dst_mac 0a:0b:0c:0d:0e:0f \
        src_mac 2:0:0:0:0:1 \
        action trap

And send a frame like this (using EasyFrame):

ef tx eth_fiber1 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::1 et 0xbeef data repeat 50 0x61

I am not sure what went wrong when you tested the ipv4 rule, but if I create the rule that you
quoted above the rule is activated when I send frames like this:

ef tx eth_fiber1 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::2 ipv4 dip 1.0.1.1 sip 2.0.2.2  data
repeat 50 0x61 

Note that the smac is changed to avoid hitting the first rule.

2) As for the VLAN based rules, the VLAN information used by IS2 is the classified VID and PCP, so
you need to create a bridge and add the VID to the bridge and the ports to see this in action.

IS0 uses the VLAN tags in the frames directly: this is one of the differences between IS0 and IS2.

This is how I set up a bridge on my PCB134 when I do the testing:

ip link add name br5 type bridge
ip link set dev br5 up
ip link set eth12 master br5
ip link set eth13 master br5
ip link set eth14 master br5
ip link set eth15 master br5
sysctl -w net.ipv6.conf.eth12.disable_ipv6=1
sysctl -w net.ipv6.conf.eth13.disable_ipv6=1
sysctl -w net.ipv6.conf.eth14.disable_ipv6=1
sysctl -w net.ipv6.conf.eth15.disable_ipv6=1
sysctl -w net.ipv6.conf.br5.disable_ipv6=1
ip link set dev br5 type bridge vlan_filtering 1
bridge vlan add dev eth12 vid 600
bridge vlan add dev eth13 vid 600
bridge vlan add dev eth14 vid 600
bridge vlan add dev eth15 vid 600
bridge vlan add dev br5 vid 600 self

This should now allow you to use the classified VLAN information in IS2 on these four ports.

> 
> This example was provided in your last patch series and worked earlier.
> 
> My setup is PC-eth0 -> PCB135-eth3 and I use the following EasyFrames
> command to send packets:
> 
> ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f
> 
> IPv4:
> tc qdisc add dev eth3 clsact
> tc filter add dev eth3 ingress chain 8000000 prio 12 handle 12 \
>     protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
>     action trap
> 
> ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f ipv4 dip 1.0.1.1 sip 2.0.2.2
> 
> Same setup as above and I can't get this to work either.

Maybe you are hitting the first rule here, so changing the smac to avoid that, should help.

> 
> I'm using tcpdump to watch the interface to see if the packets are being
> trapped or not. Changing the packets' dmac to broadcast lets me see the
> packets so I don't have any issue with the setup.
> 
> BR,
> Casper
> 

Best Regards
Steen

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-10-31 12:14     ` Steen Hegelund
@ 2022-10-31 14:52       ` Casper Andersson
  2022-10-31 15:51         ` Steen Hegelund
  2022-11-01  1:41       ` Jakub Kicinski
  1 sibling, 1 reply; 17+ messages in thread
From: Casper Andersson @ 2022-10-31 14:52 UTC (permalink / raw)
  To: Steen Hegelund
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Steen,

On 2022-10-31 13:14, Steen Hegelund wrote:
> Hi Casper,
> 
> First of all thanks for the testing effort (as usual).  This is most welcome.
> 
> On Mon, 2022-10-31 at 11:44 +0100, Casper Andersson wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > Hi Steen,
> > 
> > On 2022-10-28 16:45, Steen Hegelund wrote:
> > > - IPv4 Addresses
> > >     tc filter add dev eth12 ingress chain 8000000 prio 12 handle 12 \
> > >         protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
> > >         action trap
> > 
> > I'm not able to get this working on PCB135. I tested the VLAN tags and
> > did not work either (did not test the rest). The example from the
> > previous patch series doesn't work either after applying this series.
> 
> 
> Yes I did not really explain this part (and I will update the series with an explanation).
> 
> 1) The rule example in the previous series will no longer work as expected as the changes to the
> port keyset configuration now requires a non-ip frame to generate the MAC_ETYPE keyset.
> 
> So to test the MAC_ETYPE case your rule must be non-ip and not use "protocol all" which is not
> supported yet.  
> 
> Here is an example using the "protocol 0xbeef":
> 
> tc qdisc add dev eth3 clsact
> tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
>         protocol 0xbeef flower skip_sw \
>         dst_mac 0a:0b:0c:0d:0e:0f \
>         src_mac 2:0:0:0:0:1 \
>         action trap
> 
> And send a frame like this (using EasyFrame):
> 
> ef tx eth_fiber1 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::1 et 0xbeef data repeat 50 0x61

Thanks, this works. I saw now that you even mentioned that "protocol
all" doesn't work at the very end of this commit message.

> I am not sure what went wrong when you tested the ipv4 rule, but if I create the rule that you
> quoted above the rule is activated when I send frames like this:
> 
> ef tx eth_fiber1 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::2 ipv4 dip 1.0.1.1 sip 2.0.2.2  data
> repeat 50 0x61 

Looks like adding the "data" at the end of it makes a difference when
creating the packets. Without it the ip.proto field becomes 17 (UDP).
With "data" it becomes 0 (IPv6 Hop-by-Hop Option). Ef will defaults to
17 if no data is specified, otherwise it ends up 0. And the reason
UDP doesn't get trapped I assume is because this rule falls under the
IPV4_OTHER keyset (as opposed to IPV4_TCP_UDP).

Doing just this was enough:
ef tx eth0 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::2 ipv4 dip 1.0.1.1 sip 2.0.2.2 data

This also solved it for VLANs. I have successfully tested ipv4, ipv6,
protocol info (ICMP), and vlan tag info from the examples you provided.

Tested on Microchip PCB135 switch.

Tested-by: Casper Andersson <casper.casan@gmail.com>

BR,
Casper

> 
> Note that the smac is changed to avoid hitting the first rule.
> 
> 2) As for the VLAN based rules, the VLAN information used by IS2 is the classified VID and PCP, so
> you need to create a bridge and add the VID to the bridge and the ports to see this in action.
> 
> IS0 uses the VLAN tags in the frames directly: this is one of the differences between IS0 and IS2.
> 
> This is how I set up a bridge on my PCB134 when I do the testing:
> 
> ip link add name br5 type bridge
> ip link set dev br5 up
> ip link set eth12 master br5
> ip link set eth13 master br5
> ip link set eth14 master br5
> ip link set eth15 master br5
> sysctl -w net.ipv6.conf.eth12.disable_ipv6=1
> sysctl -w net.ipv6.conf.eth13.disable_ipv6=1
> sysctl -w net.ipv6.conf.eth14.disable_ipv6=1
> sysctl -w net.ipv6.conf.eth15.disable_ipv6=1
> sysctl -w net.ipv6.conf.br5.disable_ipv6=1
> ip link set dev br5 type bridge vlan_filtering 1
> bridge vlan add dev eth12 vid 600
> bridge vlan add dev eth13 vid 600
> bridge vlan add dev eth14 vid 600
> bridge vlan add dev eth15 vid 600
> bridge vlan add dev br5 vid 600 self
> 
> This should now allow you to use the classified VLAN information in IS2 on these four ports.
> 
> > 
> > This example was provided in your last patch series and worked earlier.
> > 
> > My setup is PC-eth0 -> PCB135-eth3 and I use the following EasyFrames
> > command to send packets:
> > 
> > ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f
> > 
> > IPv4:
> > tc qdisc add dev eth3 clsact
> > tc filter add dev eth3 ingress chain 8000000 prio 12 handle 12 \
> >     protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
> >     action trap
> > 
> > ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f ipv4 dip 1.0.1.1 sip 2.0.2.2
> > 
> > Same setup as above and I can't get this to work either.
> 
> Maybe you are hitting the first rule here, so changing the smac to avoid that, should help.
> 
> > 
> > I'm using tcpdump to watch the interface to see if the packets are being
> > trapped or not. Changing the packets' dmac to broadcast lets me see the
> > packets so I don't have any issue with the setup.
> > 
> > BR,
> > Casper
> > 
> 
> Best Regards
> Steen

BR,
Casper

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-10-31 14:52       ` Casper Andersson
@ 2022-10-31 15:51         ` Steen Hegelund
  0 siblings, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-10-31 15:51 UTC (permalink / raw)
  To: Casper Andersson
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Casper,

On Mon, 2022-10-31 at 15:52 +0100, Casper Andersson wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Hi Steen,
> 
> On 2022-10-31 13:14, Steen Hegelund wrote:
> > Hi Casper,
> > 
> > First of all thanks for the testing effort (as usual).  This is most welcome.
> > 
> > On Mon, 2022-10-31 at 11:44 +0100, Casper Andersson wrote:
> > > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > > 
> > > Hi Steen,
> > > 
> > > On 2022-10-28 16:45, Steen Hegelund wrote:
> > > > - IPv4 Addresses
> > > >     tc filter add dev eth12 ingress chain 8000000 prio 12 handle 12 \
> > > >         protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
> > > >         action trap
> > > 
> > > I'm not able to get this working on PCB135. I tested the VLAN tags and
> > > did not work either (did not test the rest). The example from the
> > > previous patch series doesn't work either after applying this series.
> > 
> > 
> > Yes I did not really explain this part (and I will update the series with an explanation).
> > 
> > 1) The rule example in the previous series will no longer work as expected as the changes to the
> > port keyset configuration now requires a non-ip frame to generate the MAC_ETYPE keyset.
> > 
> > So to test the MAC_ETYPE case your rule must be non-ip and not use "protocol all" which is not
> > supported yet.
> > 
> > Here is an example using the "protocol 0xbeef":
> > 
> > tc qdisc add dev eth3 clsact
> > tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
> >         protocol 0xbeef flower skip_sw \
> >         dst_mac 0a:0b:0c:0d:0e:0f \
> >         src_mac 2:0:0:0:0:1 \
> >         action trap
> > 
> > And send a frame like this (using EasyFrame):
> > 
> > ef tx eth_fiber1 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::1 et 0xbeef data repeat 50 0x61
> 
> Thanks, this works. I saw now that you even mentioned that "protocol
> all" doesn't work at the very end of this commit message.
> 
> > I am not sure what went wrong when you tested the ipv4 rule, but if I create the rule that you
> > quoted above the rule is activated when I send frames like this:
> > 
> > ef tx eth_fiber1 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::2 ipv4 dip 1.0.1.1 sip 2.0.2.2  data
> > repeat 50 0x61
> 
> Looks like adding the "data" at the end of it makes a difference when
> creating the packets. Without it the ip.proto field becomes 17 (UDP).
> With "data" it becomes 0 (IPv6 Hop-by-Hop Option). Ef will defaults to
> 17 if no data is specified, otherwise it ends up 0. And the reason
> UDP doesn't get trapped I assume is because this rule falls under the
> IPV4_OTHER keyset (as opposed to IPV4_TCP_UDP).

Yes the EasyFrame tool just uses defaults if you do not specify any data for the frame, so I usually
try to remember to do that to tweak the test a bit.

> 
> Doing just this was enough:
> ef tx eth0 rep 10 eth dmac 0a:0b:0c:0d:0e:0f smac 2::2 ipv4 dip 1.0.1.1 sip 2.0.2.2 data
> 
> This also solved it for VLANs. I have successfully tested ipv4, ipv6,
> protocol info (ICMP), and vlan tag info from the examples you provided.
> 
> Tested on Microchip PCB135 switch.
> 
> Tested-by: Casper Andersson <casper.casan@gmail.com>
> 
> BR,
> Casper
> 
> > 
> > Note that the smac is changed to avoid hitting the first rule.
> > 
> > 2) As for the VLAN based rules, the VLAN information used by IS2 is the classified VID and PCP,
> > so
> > you need to create a bridge and add the VID to the bridge and the ports to see this in action.
> > 
> > IS0 uses the VLAN tags in the frames directly: this is one of the differences between IS0 and
> > IS2.
> > 
> > This is how I set up a bridge on my PCB134 when I do the testing:
> > 
> > ip link add name br5 type bridge
> > ip link set dev br5 up
> > ip link set eth12 master br5
> > ip link set eth13 master br5
> > ip link set eth14 master br5
> > ip link set eth15 master br5
> > sysctl -w net.ipv6.conf.eth12.disable_ipv6=1
> > sysctl -w net.ipv6.conf.eth13.disable_ipv6=1
> > sysctl -w net.ipv6.conf.eth14.disable_ipv6=1
> > sysctl -w net.ipv6.conf.eth15.disable_ipv6=1
> > sysctl -w net.ipv6.conf.br5.disable_ipv6=1
> > ip link set dev br5 type bridge vlan_filtering 1
> > bridge vlan add dev eth12 vid 600
> > bridge vlan add dev eth13 vid 600
> > bridge vlan add dev eth14 vid 600
> > bridge vlan add dev eth15 vid 600
> > bridge vlan add dev br5 vid 600 self
> > 
> > This should now allow you to use the classified VLAN information in IS2 on these four ports.
> > 
> > > 
> > > This example was provided in your last patch series and worked earlier.
> > > 
> > > My setup is PC-eth0 -> PCB135-eth3 and I use the following EasyFrames
> > > command to send packets:
> > > 
> > > ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f
> > > 
> > > IPv4:
> > > tc qdisc add dev eth3 clsact
> > > tc filter add dev eth3 ingress chain 8000000 prio 12 handle 12 \
> > >     protocol ip flower skip_sw dst_ip 1.0.1.1 src_ip 2.0.2.2    \
> > >     action trap
> > > 
> > > ef tx eth0 rep 50 eth smac 02:00:00:00:00:01 dmac 0a:0b:0c:0d:0e:0f ipv4 dip 1.0.1.1 sip
> > > 2.0.2.2
> > > 
> > > Same setup as above and I can't get this to work either.
> > 
> > Maybe you are hitting the first rule here, so changing the smac to avoid that, should help.
> > 
> > > 
> > > I'm using tcpdump to watch the interface to see if the packets are being
> > > trapped or not. Changing the packets' dmac to broadcast lets me see the
> > > packets so I don't have any issue with the setup.
> > > 
> > > BR,
> > > Casper
> > > 
> > 
> > Best Regards
> > Steen
> 
> BR,
> Casper

Thanks again for the testing.  I will send an updated series with a bit more explanation in the
commit header.

BR
Steen

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-10-31 12:14     ` Steen Hegelund
  2022-10-31 14:52       ` Casper Andersson
@ 2022-11-01  1:41       ` Jakub Kicinski
  2022-11-01  7:31         ` Steen Hegelund
  1 sibling, 1 reply; 17+ messages in thread
From: Jakub Kicinski @ 2022-11-01  1:41 UTC (permalink / raw)
  To: Steen Hegelund
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

On Mon, 31 Oct 2022 13:14:33 +0100 Steen Hegelund wrote:
> > I'm not able to get this working on PCB135. I tested the VLAN tags and
> > did not work either (did not test the rest). The example from the
> > previous patch series doesn't work either after applying this series.  

Previous series in this context means previous revision or something
that was already merged?

> tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \

How are you using chains?

I thought you need to offload FLOW_ACTION_GOTO to get to a chain,
and I get no hits on this driver.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-11-01  1:41       ` Jakub Kicinski
@ 2022-11-01  7:31         ` Steen Hegelund
  2022-11-01 15:49           ` Jakub Kicinski
  0 siblings, 1 reply; 17+ messages in thread
From: Steen Hegelund @ 2022-11-01  7:31 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Jacub,


On Mon, 2022-10-31 at 18:41 -0700, Jakub Kicinski wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On Mon, 31 Oct 2022 13:14:33 +0100 Steen Hegelund wrote:
> > > I'm not able to get this working on PCB135. I tested the VLAN tags and
> > > did not work either (did not test the rest). The example from the
> > > previous patch series doesn't work either after applying this series.
> 
> Previous series in this context means previous revision or something
> that was already merged?

Casper refers to this series (the first of the VCAP related series) that was merged on Oct 24th:

https://lore.kernel.org/all/20221020130904.1215072-1-steen.hegelund@microchip.com/

> 
> > tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
> 
> How are you using chains?

The chain ids are referring to the VCAP instances and their lookups.  There are some more details
about this in the series I referred to above.

The short version is that this allows you to select where in the frame processing flow your rule
will be inserted (using ingress or egress and the chain id).

> 
> I thought you need to offload FLOW_ACTION_GOTO to get to a chain,
> and I get no hits on this driver.

I have not yet added the goto action, but one use of that is to chain a filter from one VCAP
instance/lookup to another.

The goto action will be added in a soon-to-come series.  I just wanted to avoid a series getting too
large, but on the other hand each of them should provide functionality that you can use in practice.

BR
Steen



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-11-01  7:31         ` Steen Hegelund
@ 2022-11-01 15:49           ` Jakub Kicinski
  2022-11-01 19:32             ` Steen Hegelund
  2022-11-02 13:11             ` Steen Hegelund
  0 siblings, 2 replies; 17+ messages in thread
From: Jakub Kicinski @ 2022-11-01 15:49 UTC (permalink / raw)
  To: Steen Hegelund
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

On Tue, 1 Nov 2022 08:31:16 +0100 Steen Hegelund wrote:
> > Previous series in this context means previous revision or something
> > that was already merged?  
> 
> Casper refers to this series (the first of the VCAP related series) that was merged on Oct 24th:
> 
> https://lore.kernel.org/all/20221020130904.1215072-1-steen.hegelund@microchip.com/

Alright, looks like this is only in net-next so no risk of breaking
existing users.
 
That said you should reject filters you can't support with an extack
message set. Also see below.

> > > tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \  
> > 
> > How are you using chains?  
> 
> The chain ids are referring to the VCAP instances and their lookups.  There are some more details
> about this in the series I referred to above.
> 
> The short version is that this allows you to select where in the frame processing flow your rule
> will be inserted (using ingress or egress and the chain id).
> 
> > I thought you need to offload FLOW_ACTION_GOTO to get to a chain,
> > and I get no hits on this driver.  
> 
> I have not yet added the goto action, but one use of that is to chain a filter from one VCAP
> instance/lookup to another.
> 
> The goto action will be added in a soon-to-come series.  I just wanted to avoid a series getting too
> large, but on the other hand each of them should provide functionality that you can use in practice.

The behavior of the offload must be the same as the SW implementation.
It sounds like in your case it very much isn't, as adding rules to 
a magic chain in SW, without the goto will result in the rules being
unused.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-11-01 15:49           ` Jakub Kicinski
@ 2022-11-01 19:32             ` Steen Hegelund
  2022-11-02 13:11             ` Steen Hegelund
  1 sibling, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-11-01 19:32 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Jacub,

Thanks for the comments.

On Tue, 2022-11-01 at 08:49 -0700, Jakub Kicinski wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On Tue, 1 Nov 2022 08:31:16 +0100 Steen Hegelund wrote:
> > > Previous series in this context means previous revision or something
> > > that was already merged?
> > 
> > Casper refers to this series (the first of the VCAP related series) that was merged on Oct 24th:
> > 
> > https://lore.kernel.org/all/20221020130904.1215072-1-steen.hegelund@microchip.com/
> 
> Alright, looks like this is only in net-next so no risk of breaking
> existing users.

Yes, this is a new feature.

> 
> That said you should reject filters you can't support with an extack
> message set. Also see below.

That should also be the case.  

I just checked that using an unsupported key, action or chain will result in an extack error
message.

> 
> > > > tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
> > > 
> > > How are you using chains?
> > 
> > The chain ids are referring to the VCAP instances and their lookups.  There are some more
> > details
> > about this in the series I referred to above.
> > 
> > The short version is that this allows you to select where in the frame processing flow your rule
> > will be inserted (using ingress or egress and the chain id).
> > 
> > > I thought you need to offload FLOW_ACTION_GOTO to get to a chain,
> > > and I get no hits on this driver.
> > 
> > I have not yet added the goto action, but one use of that is to chain a filter from one VCAP
> > instance/lookup to another.
> > 
> > The goto action will be added in a soon-to-come series.  I just wanted to avoid a series getting
> > too
> > large, but on the other hand each of them should provide functionality that you can use in
> > practice.
> 
> The behavior of the offload must be the same as the SW implementation.
> It sounds like in your case it very much isn't, as adding rules to
> a magic chain in SW, without the goto will result in the rules being
> unused.

I will add the goto support to my implementation so that it will be consistent with the SW
implementation, adding a check to ensure that there is a goto action when HW offloading.

BR
Steen







^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-11-01 15:49           ` Jakub Kicinski
  2022-11-01 19:32             ` Steen Hegelund
@ 2022-11-02 13:11             ` Steen Hegelund
  2022-11-03  1:28               ` Jakub Kicinski
  1 sibling, 1 reply; 17+ messages in thread
From: Steen Hegelund @ 2022-11-02 13:11 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen

Hi Jacub,

On Tue, 2022-11-01 at 08:49 -0700, Jakub Kicinski wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On Tue, 1 Nov 2022 08:31:16 +0100 Steen Hegelund wrote:
> > > Previous series in this context means previous revision or something
> > > that was already merged?
> > 
> > Casper refers to this series (the first of the VCAP related series) that was
> > merged on Oct 24th:
> > 
> > https://lore.kernel.org/all/20221020130904.1215072-1-steen.hegelund@microchip.com/
> 
> Alright, looks like this is only in net-next so no risk of breaking
> existing users.
> 
> That said you should reject filters you can't support with an extack
> message set. Also see below.
> 
> > > > tc filter add dev eth3 ingress chain 8000000 prio 10 handle 10 \
> > > 
> > > How are you using chains?
> > 
> > The chain ids are referring to the VCAP instances and their lookups.  There
> > are some more details
> > about this in the series I referred to above.
> > 
> > The short version is that this allows you to select where in the frame
> > processing flow your rule
> > will be inserted (using ingress or egress and the chain id).
> > 
> > > I thought you need to offload FLOW_ACTION_GOTO to get to a chain,
> > > and I get no hits on this driver.
> > 
> > I have not yet added the goto action, but one use of that is to chain a
> > filter from one VCAP
> > instance/lookup to another.
> > 
> > The goto action will be added in a soon-to-come series.  I just wanted to
> > avoid a series getting too
> > large, but on the other hand each of them should provide functionality that
> > you can use in practice.
> 
> The behavior of the offload must be the same as the SW implementation.
> It sounds like in your case it very much isn't, as adding rules to
> a magic chain in SW, without the goto will result in the rules being
> unused.

I have sent a version 4 of the series, but I realized after sending it, that I
was probably not understanding the implications of what you were saying
entirely.

As far as I understand it now, I need to have a matchall rule that does a goto
from chain 0 (as this is where all traffic processing starts) to my first IS2
VCAP chain and this rule activates the IS2 VCAP lookup.

Each of the rules in this VCAP chain need to point to the next chain etc.

If the matchall rule is deleted the IS2 VCAP lookups should be disabled as there
is no longer any way to reach the VCAP chains.

Does that sound OK?

BR
Steen


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-11-02 13:11             ` Steen Hegelund
@ 2022-11-03  1:28               ` Jakub Kicinski
  2022-11-03 16:21                 ` Steen Hegelund
  0 siblings, 1 reply; 17+ messages in thread
From: Jakub Kicinski @ 2022-11-03  1:28 UTC (permalink / raw)
  To: Steen Hegelund
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen, Jiri Pirko

On Wed, 2 Nov 2022 14:11:37 +0100 Steen Hegelund wrote:
> I have sent a version 4 of the series, but I realized after sending it, that I
> was probably not understanding the implications of what you were saying
> entirely.
> 
> As far as I understand it now, I need to have a matchall rule that does a goto
> from chain 0 (as this is where all traffic processing starts) to my first IS2
> VCAP chain and this rule activates the IS2 VCAP lookup.
> 
> Each of the rules in this VCAP chain need to point to the next chain etc.
> 
> If the matchall rule is deleted the IS2 VCAP lookups should be disabled as there
> is no longer any way to reach the VCAP chains.
> 
> Does that sound OK?

It does as far as I understand.

I haven't grasped what the purpose of using multiple chains is in 
case of your design. IIRC correctly other drivers use it for instance
to partition TCAMs with each chain having a different set of fields it
can match on. But I don't see templates used in sparx5.

In general in TC offloads you can reject any configuration you can't
(or choose not to) support, and make up your own constraints (e.g. only
specific priority or chain values are supported).

But for a "target" ruleset, i.e. ruleset comprised fully of rules you
do offload - the behavior of executing that ruleset in software and in
the device must be the same.

Dunno if that helps :)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP
  2022-11-03  1:28               ` Jakub Kicinski
@ 2022-11-03 16:21                 ` Steen Hegelund
  0 siblings, 0 replies; 17+ messages in thread
From: Steen Hegelund @ 2022-11-03 16:21 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Casper Andersson, David S . Miller, Eric Dumazet, Paolo Abeni,
	UNGLinuxDriver, Randy Dunlap, Russell King, Wan Jiabing,
	Nathan Huckleberry, linux-kernel, netdev, linux-arm-kernel,
	Daniel Machon, Horatiu Vultur, Lars Povlsen, Jiri Pirko

Hi Jacub,

On Wed, 2022-11-02 at 18:28 -0700, Jakub Kicinski wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On Wed, 2 Nov 2022 14:11:37 +0100 Steen Hegelund wrote:
> > I have sent a version 4 of the series, but I realized after sending it, that
> > I
> > was probably not understanding the implications of what you were saying
> > entirely.
> > 
> > As far as I understand it now, I need to have a matchall rule that does a
> > goto
> > from chain 0 (as this is where all traffic processing starts) to my first
> > IS2
> > VCAP chain and this rule activates the IS2 VCAP lookup.
> > 
> > Each of the rules in this VCAP chain need to point to the next chain etc.
> > 
> > If the matchall rule is deleted the IS2 VCAP lookups should be disabled as
> > there
> > is no longer any way to reach the VCAP chains.
> > 
> > Does that sound OK?
> 
> It does as far as I understand.
> 
> I haven't grasped what the purpose of using multiple chains is in
> case of your design. IIRC correctly other drivers use it for instance
> to partition TCAMs with each chain having a different set of fields it
> can match on. But I don't see templates used in sparx5.

Yes, so far I have only added the IS2 VCAP, but there are 3 more that I am
planning to to add, and they have very different capabilities in terms of keys
and actions, so I think it makes good sense to keep them in separate chains.

> 
> In general in TC offloads you can reject any configuration you can't
> (or choose not to) support, and make up your own constraints (e.g. only
> specific priority or chain values are supported).

Understood.

> 
> But for a "target" ruleset, i.e. ruleset comprised fully of rules you
> do offload - the behavior of executing that ruleset in software and in
> the device must be the same.
> 
> Dunno if that helps :)

It does, thanks!

I been fireing up a QEMU instance so I have been able to test my understanding,
and it looks like I now have the same experience when I test the same rule there
and in the hardware of Sparx5.

BR
Steen


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-11-03 16:22 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-28 14:45 [PATCH net-next v2 0/5] Extend TC key support for Sparx5 IS2 VCAP Steen Hegelund
2022-10-28 14:45 ` [PATCH net-next v2 1/5] net: microchip: sparx5: Differentiate IPv4 and IPv6 traffic in keyset config Steen Hegelund
2022-10-28 14:45 ` [PATCH net-next v2 2/5] net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP Steen Hegelund
2022-10-31 10:44   ` Casper Andersson
2022-10-31 12:14     ` Steen Hegelund
2022-10-31 14:52       ` Casper Andersson
2022-10-31 15:51         ` Steen Hegelund
2022-11-01  1:41       ` Jakub Kicinski
2022-11-01  7:31         ` Steen Hegelund
2022-11-01 15:49           ` Jakub Kicinski
2022-11-01 19:32             ` Steen Hegelund
2022-11-02 13:11             ` Steen Hegelund
2022-11-03  1:28               ` Jakub Kicinski
2022-11-03 16:21                 ` Steen Hegelund
2022-10-28 14:45 ` [PATCH net-next v2 3/5] net: microchip: sparx5: Match keys in configured port keysets Steen Hegelund
2022-10-28 14:45 ` [PATCH net-next v2 4/5] net: microchip: sparx5: Let VCAP API validate added key- and actionfields Steen Hegelund
2022-10-28 14:45 ` [PATCH net-next v2 5/5] net: microchip: sparx5: Adding KUNIT tests of key/action values in VCAP API Steen Hegelund

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).