All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Yang <mmyangfl@gmail.com>
To: netdev@vger.kernel.org
Cc: David Yang <mmyangfl@gmail.com>, Andrew Lunn <andrew@lunn.ch>,
	Vladimir Oltean <olteanv@gmail.com>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH net-next] net: dsa: motorcomm: Extend ACL with UDF
Date: Sat, 17 Oct 2026 10:31:32 +0800	[thread overview]
Message-ID: <20261017023136.2961543-1-mmyangfl@gmail.com> (raw)

The native ACL key set cannot express IP TTL or ICMP type/code. Use the
User Defined Filter windows to match them in the tc flower offload.

Signed-off-by: David Yang <mmyangfl@gmail.com>
---
 drivers/net/dsa/motorcomm/chip.h |   2 +-
 drivers/net/dsa/motorcomm/tc.c   | 140 +++++++++++++++++++++++++++++--
 drivers/net/dsa/motorcomm/tc.h   |  12 ++-
 3 files changed, 144 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index 7047ad98f431..fc315f1d8f87 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -440,7 +440,7 @@ enum yt921x_fdb_entry_status {
 #define YT921X_TAG_LEN	8
 
 #define YT921X_ACL_BLK_NUM	48
-#define YT921X_UDF_NUM		8
+#define YT921X_UDF_NUM		16
 
 #define YT921X_LED_GROUP_NUM	3
 #define YT921X_LED_PORT_NUM	10
diff --git a/drivers/net/dsa/motorcomm/tc.c b/drivers/net/dsa/motorcomm/tc.c
index 3e0f80500f41..9dbd61e48fee 100644
--- a/drivers/net/dsa/motorcomm/tc.c
+++ b/drivers/net/dsa/motorcomm/tc.c
@@ -543,6 +543,24 @@ yt921x_acl_rule_set_ports(struct yt921x_acl_rule *aclrule, u16 ord,
 	}
 }
 
+struct yt921x_udf_entry {
+	unsigned char type;
+	unsigned char offset;
+	u8 key;
+	u8 mask;
+};
+
+struct yt921x_udf_map {
+	unsigned char type;
+	unsigned char offset;
+};
+
+/* UDF windows are preselected - that's enough for now. */
+static struct yt921x_udf_map yt921x_udf_maps[] = {
+	{YT921X_UDF_TYPE_L3, 7},
+	{YT921X_UDF_TYPE_L4, 0},
+};
+
 struct yt921x_acl_rule_ext {
 	struct yt921x_acl_rule r;
 
@@ -556,9 +574,13 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 	const struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
 	struct yt921x_acl_entry *entries = ruleext->r.entries;
 	struct netlink_ext_ack *extack = cls->common.extack;
+	struct yt921x_udf_entry udfs[YT921X_UDF_NUM];
 	const struct flow_dissector *dissector;
 	struct yt921x_acl_entry *entry;
+	unsigned int udfs_cnt = 0;
 	unsigned int size = 0;
+	__be16 n_proto = 0;
+	u8 ip_proto = 0;
 	bool use_dport;
 	bool use_sport;
 
@@ -575,7 +597,8 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 	      BIT_ULL(FLOW_DISSECTOR_KEY_PORTS_RANGE) |
 	      BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
 	      BIT_ULL(FLOW_DISSECTOR_KEY_IP) |
-	      BIT_ULL(FLOW_DISSECTOR_KEY_TCP))) {
+	      BIT_ULL(FLOW_DISSECTOR_KEY_TCP) |
+	      BIT_ULL(FLOW_DISSECTOR_KEY_ICMP))) {
 		NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used");
 		return -EOPNOTSUPP;
 	}
@@ -741,7 +764,9 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 		if (match.mask->n_proto) {
 			enum yt921x_l3_type l3type = YT921X_L3_TYPE_OTHER;
 
-			if (match.mask->n_proto == htons(~0))
+			if (match.mask->n_proto == htons(~0)) {
+				n_proto = match.key->n_proto;
+
 				switch (match.key->n_proto) {
 				case htons(ETH_P_IP):
 					l3type = YT921X_L3_TYPE_IPV4;
@@ -762,6 +787,7 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 					l3type = YT921X_L3_TYPE_ERP;
 					break;
 				}
+			}
 
 			if (l3type != YT921X_L3_TYPE_OTHER) {
 				size = yt921x_acl_entries_set_l3_type(entries,
@@ -783,7 +809,9 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 		if (match.mask->ip_proto) {
 			enum yt921x_l4_type l4type = YT921X_L4_TYPE_OTHER;
 
-			if (match.mask->ip_proto == (u8)~0)
+			if (match.mask->ip_proto == (u8)~0) {
+				ip_proto = match.key->ip_proto;
+
 				switch (match.key->ip_proto) {
 				case IPPROTO_TCP:
 					l4type = YT921X_L4_TYPE_TCP;
@@ -801,6 +829,7 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 					l4type = YT921X_L4_TYPE_IGMP;
 					break;
 				}
+			}
 
 			if (l4type != YT921X_L4_TYPE_OTHER) {
 				size = yt921x_acl_entries_set_l4_type(entries,
@@ -852,10 +881,25 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 		struct flow_match_ip match;
 
 		flow_rule_match_ip(rule, &match);
+
 		if (match.mask->ttl) {
-			NL_SET_ERR_MSG_MOD(extack,
-					   "Matching on TTL not supported");
-			return -EOPNOTSUPP;
+			if (n_proto != htons(ETH_P_IP) &&
+			    n_proto != htons(ETH_P_IPV6)) {
+				NL_SET_ERR_MSG_MOD(extack,
+						   "Matching on TTL requires protocol ip or ipv6");
+				return -EOPNOTSUPP;
+			}
+
+			if (udfs_cnt >= YT921X_UDF_NUM)
+				goto err;
+
+			udfs[udfs_cnt] = (struct yt921x_udf_entry){
+				.type = YT921X_UDF_TYPE_L3,
+				.offset = n_proto == htons(ETH_P_IP) ? 8 : 7,
+				.key = match.key->ttl,
+				.mask = match.mask->ttl,
+			};
+			udfs_cnt++;
 		}
 
 		if (match.mask->tos) {
@@ -889,6 +933,82 @@ yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
 		}
 	}
 
+	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) {
+		struct flow_match_icmp match;
+
+		flow_rule_match_icmp(rule, &match);
+
+		if (match.mask->type || match.mask->code) {
+			if (ip_proto != IPPROTO_ICMP &&
+			    ip_proto != IPPROTO_ICMPV6) {
+				NL_SET_ERR_MSG_MOD(extack,
+						   "Matching on ICMP type/code requires ip_proto icmp or icmpv6");
+				return -EOPNOTSUPP;
+			}
+
+			if (match.mask->type) {
+				if (udfs_cnt >= YT921X_UDF_NUM)
+					goto err;
+
+				udfs[udfs_cnt] = (struct yt921x_udf_entry){
+					.type = YT921X_UDF_TYPE_L4,
+					.offset = 0,
+					.key = match.key->type,
+					.mask = match.mask->type,
+				};
+				udfs_cnt++;
+			}
+
+			if (match.mask->code) {
+				if (udfs_cnt >= YT921X_UDF_NUM)
+					goto err;
+
+				udfs[udfs_cnt] = (struct yt921x_udf_entry){
+					.type = YT921X_UDF_TYPE_L4,
+					.offset = 1,
+					.key = match.key->code,
+					.mask = match.mask->code,
+				};
+				udfs_cnt++;
+			}
+		}
+	}
+
+	/* Compile UDFs */
+	for (unsigned int i = 0; i < udfs_cnt; i++) {
+		unsigned int o;
+		u32 mask;
+		u32 key;
+
+		for (o = 0; o < ARRAY_SIZE(yt921x_udf_maps); o++)
+			if (udfs[i].type == yt921x_udf_maps[o].type &&
+			    (udfs[i].offset == yt921x_udf_maps[o].offset ||
+			     udfs[i].offset == yt921x_udf_maps[o].offset + 1))
+				break;
+
+		if (WARN_ON(o == ARRAY_SIZE(yt921x_udf_maps)))
+			return -EOPNOTSUPP;
+
+		entry = yt921x_acl_entries_find(entries, &size,
+						YT921X_ACL_TYPE_UDF0 + o / 2);
+		if (!entry)
+			goto err;
+
+		key = udfs[i].key;
+		mask = udfs[i].mask;
+		if (udfs[i].offset == yt921x_udf_maps[o].offset) {
+			key <<= 8;
+			mask <<= 8;
+		}
+		if (!(o % 2)) {
+			key <<= 16;
+			mask <<= 16;
+		}
+
+		entry->key[0] |= key;
+		entry->mask[0] |= mask;
+	}
+
 	if (!size) {
 		NL_SET_ERR_MSG_MOD(extack, "Empty rule generated, this should not happen");
 		return -EOPNOTSUPP;
@@ -1579,5 +1699,13 @@ int yt921x_chip_setup_acl(struct yt921x_priv *priv)
 	if (res)
 		return res;
 
+	for (unsigned int o = 0; o < ARRAY_SIZE(yt921x_udf_maps); o++) {
+		ctrl = YT921X_UDF_CTRL_UDF_OFFSET(yt921x_udf_maps[o].offset) |
+		       YT921X_UDF_CTRL_UDF_TYPE(yt921x_udf_maps[o].type);
+		res = yt921x_reg_write(priv, YT921X_UDFn_CTRL(o), ctrl);
+		if (res)
+			return res;
+	}
+
 	return 0;
 }
diff --git a/drivers/net/dsa/motorcomm/tc.h b/drivers/net/dsa/motorcomm/tc.h
index f11136a1c5e2..cc53f148d690 100644
--- a/drivers/net/dsa/motorcomm/tc.h
+++ b/drivers/net/dsa/motorcomm/tc.h
@@ -118,6 +118,9 @@ enum yt921x_acl_type {
 	YT921X_ACL_TYPE_IPV6_SA3,
 	YT921X_ACL_TYPE_MISC,
 	YT921X_ACL_TYPE_L4,
+	/* Each User Defined Filter entry contains 2 UDF windows (UDF_CTRL 2i
+	 * and 2i+1)
+	 */
 	YT921X_ACL_TYPE_UDF0,
 	YT921X_ACL_TYPE_UDF1,
 	YT921X_ACL_TYPE_UDF2,
@@ -255,12 +258,15 @@ enum yt921x_l4_type {
 #define YT921X_UDFn_CTRL(x)		(0x210094 + 4 * (x))
 #define  YT921X_UDF_CTRL_UDF_TYPE_M		GENMASK(8, 7)
 #define   YT921X_UDF_CTRL_UDF_TYPE(x)			FIELD_PREP(YT921X_UDF_CTRL_UDF_TYPE_M, (x))
-#define   YT921X_UDF_CTRL_UDF_TYPE_ETH			YT921X_UDF_CTRL_UDF_TYPE(0)
-#define   YT921X_UDF_CTRL_UDF_TYPE_L3			YT921X_UDF_CTRL_UDF_TYPE(1)
-#define   YT921X_UDF_CTRL_UDF_TYPE_L4			YT921X_UDF_CTRL_UDF_TYPE(2)
 #define  YT921X_UDF_CTRL_UDF_OFFSET_M		GENMASK(6, 0)
 #define   YT921X_UDF_CTRL_UDF_OFFSET(x)			FIELD_PREP(YT921X_UDF_CTRL_UDF_OFFSET_M, (x))
 
+enum yt921x_udf_type {
+	YT921X_UDF_TYPE_L2,
+	YT921X_UDF_TYPE_L3,
+	YT921X_UDF_TYPE_L4,
+};
+
 #define YT921X_PORTn_RATE(port)		(0x220000 + 4 * (port))
 #define  YT921X_PORT_RATE_GAP_VALUE		GENMASK(4, 0)	/* default 20 */
 #define YT921X_METER_SLOT		0x220104
-- 
2.53.0


             reply	other threads:[~2026-10-17  2:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-17  2:31 David Yang [this message]
2026-10-21 13:10 ` [PATCH net-next] net: dsa: motorcomm: Extend ACL with UDF patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261017023136.2961543-1-mmyangfl@gmail.com \
    --to=mmyangfl@gmail.com \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.