[PATCH v2 2/3] net: stmmac: fix l3l4 filter rejecting unsupported offload requests
From: muhammad . nazim . amirul . nazle . asmade
Date: Thu Jun 04 2026 - 04:43:01 EST
From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@xxxxxxxxxx>
The basic flow parser in tc_add_basic_flow() does not validate match
keys before proceeding. Unsupported offload configurations such as
partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport
proto are silently accepted instead of returning -EOPNOTSUPP.
Add validation to return -EOPNOTSUPP early for:
- No network or transport proto present in the key
- Partial protocol mask (only full mask supported)
- Network proto is not IPv4
- Transport proto is not TCP or UDP
Also propagate -EOPNOTSUPP from the basic flow parser in tc_add_flow()
to fail early rather than continue with subsequent parsers.
Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower")
Signed-off-by: Rohan G Thomas <rohan.g.thomas@xxxxxxxxxx>
Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@xxxxxxxxxx>
---
.../net/ethernet/stmicro/stmmac/stmmac_tc.c | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index d78652718599..869f84756ca5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv,
}
#define ETHER_TYPE_FULL_MASK cpu_to_be16(~0)
+#define IP_PROTO_FULL_MASK 0xFF
static int tc_add_basic_flow(struct stmmac_priv *priv,
struct flow_cls_offload *cls,
@@ -461,6 +462,25 @@ static int tc_add_basic_flow(struct stmmac_priv *priv,
flow_rule_match_basic(rule, &match);
+ /* Both network proto and transport proto not present in the key */
+ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto))
+ return -EOPNOTSUPP;
+
+ /* If the proto is present in the key and is not full mask */
+ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) ||
+ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK))
+ return -EOPNOTSUPP;
+
+ /* Network proto is present in the key and is not IPv4 */
+ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP))
+ return -EOPNOTSUPP;
+
+ /* Transport proto is present in the key and is not TCP or UDP */
+ if (match.mask->ip_proto &&
+ match.key->ip_proto != IPPROTO_TCP &&
+ match.key->ip_proto != IPPROTO_UDP)
+ return -EOPNOTSUPP;
+
entry->ip_proto = match.key->ip_proto;
return 0;
}
@@ -598,6 +618,12 @@ static int tc_add_flow(struct stmmac_priv *priv,
ret = tc_flow_parsers[i].fn(priv, cls, entry);
if (!ret)
entry->in_use = true;
+ else if (ret == -EOPNOTSUPP)
+ /* The basic flow parser will return EOPNOTSUPP, if a
+ * requested offload not fully supported by the hw. And
+ * in that case fail early.
+ */
+ break;
}
if (!entry->in_use)
--
2.43.7