diff mbox series

[net-next,2/2] net: stmmac: add tc flower filter for EtherType matching

Message ID 20211209151631.138326-3-boon.leong.ong@intel.com (mailing list archive)
State New, archived
Headers show
Series net: stmmac: add EthType Rx Frame steering | expand

Commit Message

Ong Boon Leong Dec. 9, 2021, 3:16 p.m. UTC
This patch adds basic support for EtherType RX frame steering for
LLDP and PTP using the hardware offload capabilities.

Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |   3 +
 .../net/ethernet/stmicro/stmmac/stmmac_tc.c   | 121 ++++++++++++++++++
 2 files changed, 124 insertions(+)

Comments

Kurt Kanzenbach Dec. 10, 2021, 9:35 a.m. UTC | #1
Hi BL,

On Thu Dec 09 2021, Ong Boon Leong wrote:
> This patch adds basic support for EtherType RX frame steering for
> LLDP and PTP using the hardware offload capabilities.

Maybe add an example here for users?

|tc filter add dev eno1 parent ffff: protocol 0x88f7 flower hw_tc 4
|tc filter add dev eno1 parent ffff: protocol 0x88cc flower hw_tc 4

>
> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>

Something is not quite correct. The use of the etype variable generates
new warnings. For instance:

|drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:768:25: warning: restricted __be16 degrades to integer
|drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:768:25: warning: restricted __be16 degrades to integer
|drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:817:22: warning: restricted __be16 degrades to integer
|drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:817:22: warning: restricted __be16 degrades to integer

However, the steering works as expected. Thanks!

Thanks,
Kurt
Kurt Kanzenbach Dec. 10, 2021, 10:10 a.m. UTC | #2
On Thu Dec 09 2021, Ong Boon Leong wrote:
> This patch adds basic support for EtherType RX frame steering for
> LLDP and PTP using the hardware offload capabilities.
>
> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com>

[snip]

> +	if (match.mask->n_proto) {
> +		__be16 etype = ntohs(match.key->n_proto);

n_proto is be16. The ntohs() call will produce an u16.

Delta patch below.

Thanks,
Kurt

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 35ff7c835018..d64e42308eb6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -182,7 +182,7 @@ enum stmmac_rfs_type {
 
 struct stmmac_rfs_entry {
        unsigned long cookie;
-       __be16 etype;
+       u16 etype;
        int in_use;
        int type;
        int idx;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index cb7400943bb0..afa918185cf7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -759,7 +759,7 @@ static int tc_add_ethtype_flow(struct stmmac_priv *priv,
        flow_rule_match_basic(rule, &match);
 
        if (match.mask->n_proto) {
-               __be16 etype = ntohs(match.key->n_proto);
+               u16 etype = ntohs(match.key->n_proto);
 
                if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) {
                        netdev_err(priv->dev, "Only full mask is supported for EthType filter");
Sebastian Andrzej Siewior Dec. 10, 2021, 11:57 a.m. UTC | #3
On 2021-12-10 11:10:04 [+0100], Kurt Kanzenbach wrote:
> > +	if (match.mask->n_proto) {
> > +		__be16 etype = ntohs(match.key->n_proto);
> 
> n_proto is be16. The ntohs() call will produce an u16.

While at it, could we be please remove that __force in
ETHER_TYPE_FULL_MASK and use cpu_to_be16() macro?

> Thanks,
> Kurt

Sebastian
Ong Boon Leong Dec. 11, 2021, 2:02 p.m. UTC | #4
>[snip]
>
>> +	if (match.mask->n_proto) {
>> +		__be16 etype = ntohs(match.key->n_proto);
>
>n_proto is be16. The ntohs() call will produce an u16.
>
>Delta patch below.
>
>Thanks,
>Kurt
>
>diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
>b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
>index 35ff7c835018..d64e42308eb6 100644
>--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
>+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
>@@ -182,7 +182,7 @@ enum stmmac_rfs_type {
>
> struct stmmac_rfs_entry {
>        unsigned long cookie;
>-       __be16 etype;
>+       u16 etype;
>        int in_use;
>        int type;
>        int idx;
>diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
>b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
>index cb7400943bb0..afa918185cf7 100644
>--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
>+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
>@@ -759,7 +759,7 @@ static int tc_add_ethtype_flow(struct stmmac_priv
>*priv,
>        flow_rule_match_basic(rule, &match);
>
>        if (match.mask->n_proto) {
>-               __be16 etype = ntohs(match.key->n_proto);
>+               u16 etype = ntohs(match.key->n_proto);
>
>                if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) {
>                        netdev_err(priv->dev, "Only full mask is supported for EthType
>filter");

Thanks for the suggestion. I will incorporate in v2 patch after we conclude
if the tc flower hw_tc interface used for specifying RxQ queue is agreeable
by community.
Ong Boon Leong Dec. 11, 2021, 2:03 p.m. UTC | #5
>On 2021-12-10 11:10:04 [+0100], Kurt Kanzenbach wrote:
>> > +	if (match.mask->n_proto) {
>> > +		__be16 etype = ntohs(match.key->n_proto);
>>
>> n_proto is be16. The ntohs() call will produce an u16.
>
>While at it, could we be please remove that __force in
>ETHER_TYPE_FULL_MASK and use cpu_to_be16() macro?
>
>> Thanks,
>> Kurt
>
>Sebastian

Thanks. Will do.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 18a262ef17f..ce12b2fbd80 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -174,11 +174,14 @@  struct stmmac_flow_entry {
 /* Rx Frame Steering */
 enum stmmac_rfs_type {
 	STMMAC_RFS_T_VLAN,
+	STMMAC_RFS_T_LLDP,
+	STMMAC_RFS_T_1588,
 	STMMAC_RFS_T_MAX,
 };
 
 struct stmmac_rfs_entry {
 	unsigned long cookie;
+	__be16 etype;
 	int in_use;
 	int type;
 	int tc;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index d0a2b289f46..de7ce4697a5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -237,6 +237,8 @@  static int tc_rfs_init(struct stmmac_priv *priv)
 	int i;
 
 	priv->rfs_entries_max[STMMAC_RFS_T_VLAN] = 8;
+	priv->rfs_entries_max[STMMAC_RFS_T_LLDP] = 1;
+	priv->rfs_entries_max[STMMAC_RFS_T_1588] = 1;
 
 	for (i = 0; i < STMMAC_RFS_T_MAX; i++)
 		priv->rfs_entries_total += priv->rfs_entries_max[i];
@@ -451,6 +453,8 @@  static int tc_parse_flow_actions(struct stmmac_priv *priv,
 	return 0;
 }
 
+#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
+
 static int tc_add_basic_flow(struct stmmac_priv *priv,
 			     struct flow_cls_offload *cls,
 			     struct stmmac_flow_entry *entry)
@@ -464,6 +468,7 @@  static int tc_add_basic_flow(struct stmmac_priv *priv,
 		return -EINVAL;
 
 	flow_rule_match_basic(rule, &match);
+
 	entry->ip_proto = match.key->ip_proto;
 	return 0;
 }
@@ -724,6 +729,114 @@  static int tc_del_vlan_flow(struct stmmac_priv *priv,
 	return 0;
 }
 
+static int tc_add_ethtype_flow(struct stmmac_priv *priv,
+			       struct flow_cls_offload *cls)
+{
+	struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false);
+	struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
+	struct flow_dissector *dissector = rule->match.dissector;
+	int tc = tc_classid_to_hwtc(priv->dev, cls->classid);
+	struct flow_match_basic match;
+
+	if (!entry) {
+		entry = tc_find_rfs(priv, cls, true);
+		if (!entry)
+			return -ENOENT;
+	}
+
+	/* Nothing to do here */
+	if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_BASIC))
+		return -EINVAL;
+
+	if (tc < 0) {
+		netdev_err(priv->dev, "Invalid traffic class\n");
+		return -EINVAL;
+	}
+
+	flow_rule_match_basic(rule, &match);
+
+	if (match.mask->n_proto) {
+		__be16 etype = ntohs(match.key->n_proto);
+
+		if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) {
+			netdev_err(priv->dev, "Only full mask is supported for EthType filter");
+			return -EINVAL;
+		}
+		switch (etype) {
+		case ETH_P_LLDP:
+			if (priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP] >=
+			    priv->rfs_entries_max[STMMAC_RFS_T_LLDP])
+				return -ENOENT;
+
+			entry->type = STMMAC_RFS_T_LLDP;
+			priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP]++;
+
+			stmmac_rx_queue_routing(priv, priv->hw,
+						PACKET_DCBCPQ, tc);
+			break;
+		case ETH_P_1588:
+			if (priv->rfs_entries_cnt[STMMAC_RFS_T_1588] >=
+			    priv->rfs_entries_max[STMMAC_RFS_T_1588])
+				return -ENOENT;
+
+			entry->type = STMMAC_RFS_T_1588;
+			priv->rfs_entries_cnt[STMMAC_RFS_T_1588]++;
+
+			stmmac_rx_queue_routing(priv, priv->hw,
+						PACKET_PTPQ, tc);
+			break;
+		default:
+			netdev_err(priv->dev, "EthType(0x%x) is not supported", etype);
+			return -EINVAL;
+		}
+
+		entry->in_use = true;
+		entry->cookie = cls->cookie;
+		entry->tc = tc;
+		entry->etype = etype;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int tc_del_ethtype_flow(struct stmmac_priv *priv,
+			       struct flow_cls_offload *cls)
+{
+	struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false);
+
+	if (!entry || !entry->in_use ||
+	    entry->type < STMMAC_RFS_T_LLDP ||
+	    entry->type > STMMAC_RFS_T_1588)
+		return -ENOENT;
+
+	switch (entry->etype) {
+	case ETH_P_LLDP:
+		stmmac_rx_queue_routing(priv, priv->hw,
+					PACKET_DCBCPQ, 0);
+		priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP]--;
+		break;
+	case ETH_P_1588:
+		stmmac_rx_queue_routing(priv, priv->hw,
+					PACKET_PTPQ, 0);
+		priv->rfs_entries_cnt[STMMAC_RFS_T_1588]--;
+		break;
+	default:
+		netdev_err(priv->dev, "EthType(0x%x) is not supported",
+			   entry->etype);
+		return -EINVAL;
+	}
+
+	entry->in_use = false;
+	entry->cookie = 0;
+	entry->tc = 0;
+	entry->etype = 0;
+	entry->type = 0;
+
+	return 0;
+}
+
 static int tc_add_flow_cls(struct stmmac_priv *priv,
 			   struct flow_cls_offload *cls)
 {
@@ -733,6 +846,10 @@  static int tc_add_flow_cls(struct stmmac_priv *priv,
 	if (!ret)
 		return ret;
 
+	ret = tc_add_ethtype_flow(priv, cls);
+	if (!ret)
+		return ret;
+
 	return tc_add_vlan_flow(priv, cls);
 }
 
@@ -745,6 +862,10 @@  static int tc_del_flow_cls(struct stmmac_priv *priv,
 	if (!ret)
 		return ret;
 
+	ret = tc_del_ethtype_flow(priv, cls);
+	if (!ret)
+		return ret;
+
 	return tc_del_vlan_flow(priv, cls);
 }