[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200926173108.1230014-7-vladimir.oltean@nxp.com>
Date: Sat, 26 Sep 2020 20:30:58 +0300
From: Vladimir Oltean <vladimir.oltean@....com>
To: netdev@...r.kernel.org, davem@...emloft.net
Cc: andrew@...n.ch, f.fainelli@...il.com, vivien.didelot@...il.com,
kuba@...nel.org
Subject: [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector
For all DSA formats that don't use tail tags, it looks like behind the
obscure number crunching they're all doing the same thing: locating the
real EtherType behind the DSA tag. Nonetheless, this is not immediately
obvious, so create a generic helper for those DSA taggers that put the
header before the EtherType.
Another assumption for the generic function is that the DSA tags are of
equal length on RX and on TX. Prior to the previous patch, this was not
true for ocelot and for gswip. The problem was resolved for ocelot, but
for gswip it still remains, so that can't use this helper yet.
Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
net/dsa/dsa.c | 25 +++++++++++++++++++++++++
net/dsa/dsa_priv.h | 2 ++
2 files changed, 27 insertions(+)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 5c18c0214aac..aa925eac7888 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -305,6 +305,31 @@ bool dsa_schedule_work(struct work_struct *work)
return queue_work(dsa_owq, work);
}
+/* All DSA tags that push the EtherType to the right (basically all except tail
+ * tags, which don't break dissection) can be treated the same from the
+ * perspective of the flow dissector.
+ *
+ * We need to return:
+ * - offset: the (B - A) difference between:
+ * A. the position of the real EtherType and
+ * B. the current skb->data (aka ETH_HLEN bytes into the frame, aka 2 bytes
+ * after the normal EtherType was supposed to be)
+ * The offset in bytes is exactly equal to the tagger overhead (and half of
+ * that, in __be16 shorts).
+ *
+ * - proto: the value of the real EtherType.
+ */
+void dsa_tag_generic_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+ int *offset)
+{
+ const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops;
+ int tag_len = ops->overhead;
+
+ *offset = tag_len;
+ *proto = ((__be16 *)skb->data)[(tag_len / 2) - 1];
+}
+EXPORT_SYMBOL(dsa_tag_generic_flow_dissect);
+
static ATOMIC_NOTIFIER_HEAD(dsa_notif_chain);
int register_dsa_notifier(struct notifier_block *nb)
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 0348dbab4131..61120145679d 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -99,6 +99,8 @@ void dsa_tag_driver_put(const struct dsa_device_ops *ops);
bool dsa_schedule_work(struct work_struct *work);
const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops);
+void dsa_tag_generic_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+ int *offset);
int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
--
2.25.1
Powered by blists - more mailing lists