netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA
@ 2020-09-26 17:30 Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 01/16] net: mscc: ocelot: move NPI port configuration to DSA Vladimir Oltean
                   ` (15 more replies)
  0 siblings, 16 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

This is the v2 of a series initially submitted in May:
https://www.spinics.net/lists/netdev/msg651866.html

The end goal is to get rid of the unintuitive code for the flow
dissector that currently exists in the taggers. It can all be replaced
by a single, common function.

Some background work needs to be done for that. Especially the ocelot
driver poses some problems, since it has a different tag length between
RX and TX, and I didn't want to make DSA aware of that, since I could
instead make the tag lengths equal.

Vladimir Oltean (16):
  net: mscc: ocelot: move NPI port configuration to DSA
  net: dsa: allow drivers to request promiscuous mode on master
  net: dsa: sja1105: request promiscuous mode for master
  net: dsa: tag_ocelot: use a short prefix on both ingress and egress
  net: dsa: make the .flow_dissect tagger callback return void
  net: dsa: add a generic procedure for the flow dissector
  net: dsa: tag_ar8331: use generic flow dissector procedure
  net: dsa: tag_brcm: use generic flow dissector procedure
  net: dsa: tag_dsa: use the generic flow dissector procedure
  net: dsa: tag_edsa: use the generic flow dissector procedure
  net: dsa: tag_lan9303: use the generic flow dissector procedure
  net: dsa: tag_mtk: use the generic flow dissector procedure
  net: dsa: tag_ocelot: use the generic flow dissector procedure
  net: dsa: tag_qca: use the generic flow dissector procedure
  net: dsa: tag_sja1105: use the generic flow dissector procedure
  net: dsa: tag_rtl4_a: use the generic flow dissector procedure

 drivers/net/dsa/ocelot/felix.c             | 32 ++++++++++++++---
 drivers/net/dsa/ocelot/felix_vsc9959.c     | 13 +++++--
 drivers/net/dsa/ocelot/seville_vsc9953.c   | 13 +++++--
 drivers/net/dsa/sja1105/sja1105_main.c     |  3 ++
 drivers/net/ethernet/mscc/ocelot.c         | 40 ++++------------------
 drivers/net/ethernet/mscc/ocelot_vsc7514.c |  7 ++--
 include/net/dsa.h                          | 11 ++++--
 include/soc/mscc/ocelot.h                  |  4 +--
 net/core/flow_dissector.c                  |  4 +--
 net/dsa/dsa.c                              | 25 ++++++++++++++
 net/dsa/dsa_priv.h                         |  2 ++
 net/dsa/master.c                           | 21 +++++++++++-
 net/dsa/tag_ar9331.c                       |  1 +
 net/dsa/tag_brcm.c                         | 37 ++++++++------------
 net/dsa/tag_dsa.c                          | 10 +-----
 net/dsa/tag_edsa.c                         | 10 +-----
 net/dsa/tag_lan9303.c                      |  1 +
 net/dsa/tag_mtk.c                          | 11 +-----
 net/dsa/tag_ocelot.c                       | 20 +++++++----
 net/dsa/tag_qca.c                          | 11 +-----
 net/dsa/tag_rtl4_a.c                       | 12 +------
 net/dsa/tag_sja1105.c                      | 11 ++++++
 22 files changed, 164 insertions(+), 135 deletions(-)

-- 
2.25.1


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

* [PATCH v2 net-next 01/16] net: mscc: ocelot: move NPI port configuration to DSA
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master Vladimir Oltean
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Remove the ocelot_configure_cpu() function, which was in fact bringing
up 2 ports: the CPU port module, which both switchdev and DSA have, and
the NPI port, which only DSA has.

The (non-Ethernet) CPU port module is at a fixed index in the analyzer,
whereas the NPI port is selected through the "ethernet" property in the
device tree.

Therefore, the function to set up an NPI port is DSA-specific, so we
move it there, simplifying the ocelot switch library a little bit.

Cc: Horatiu Vultur <horatiu.vultur@microchip.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: UNGLinuxDriver <UNGLinuxDriver@microchip.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c             | 29 +++++++++++++---
 drivers/net/ethernet/mscc/ocelot.c         | 40 ++++------------------
 drivers/net/ethernet/mscc/ocelot_vsc7514.c |  7 ++--
 include/soc/mscc/ocelot.h                  |  3 --
 4 files changed, 35 insertions(+), 44 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index a56fc50f5be4..b8e192374a32 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -439,6 +439,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 	ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
 	ocelot->vcap		= felix->info->vcap;
 	ocelot->ops		= felix->info->ops;
+	ocelot->inj_prefix	= OCELOT_TAG_PREFIX_NONE;
+	ocelot->xtr_prefix	= OCELOT_TAG_PREFIX_LONG;
 
 	port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
 				 GFP_KERNEL);
@@ -538,6 +540,28 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 	return 0;
 }
 
+/* The CPU port module is connected to the Node Processor Interface (NPI). This
+ * is the mode through which frames can be injected from and extracted to an
+ * external CPU, over Ethernet.
+ */
+static void felix_npi_port_init(struct ocelot *ocelot, int port)
+{
+	ocelot->npi = port;
+
+	ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
+		     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port),
+		     QSYS_EXT_CPU_CFG);
+
+	/* NPI port Injection/Extraction configuration */
+	ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR,
+			    ocelot->xtr_prefix);
+	ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR,
+			    ocelot->inj_prefix);
+
+	/* Disable transmission of pause frames */
+	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0);
+}
+
 /* Hardware initialization done here so that we can allocate structures with
  * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
  * us to allocate structures twice (leak memory) and map PCI memory twice
@@ -570,11 +594,8 @@ static int felix_setup(struct dsa_switch *ds)
 	for (port = 0; port < ds->num_ports; port++) {
 		ocelot_init_port(ocelot, port);
 
-		/* Bring up the CPU port module and configure the NPI port */
 		if (dsa_is_cpu_port(ds, port))
-			ocelot_configure_cpu(ocelot, port,
-					     OCELOT_TAG_PREFIX_NONE,
-					     OCELOT_TAG_PREFIX_LONG);
+			felix_npi_port_init(ocelot, port);
 
 		/* Set the default QoS Classification based on PCP and DEI
 		 * bits of vlan tag.
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 0445c5ee5551..b9375d96cdbc 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1346,22 +1346,14 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
 }
 EXPORT_SYMBOL(ocelot_init_port);
 
-/* Configure and enable the CPU port module, which is a set of queues.
- * If @npi contains a valid port index, the CPU port module is connected
- * to the Node Processor Interface (NPI). This is the mode through which
- * frames can be injected from and extracted to an external CPU,
- * over Ethernet.
+/* Configure and enable the CPU port module, which is a set of queues
+ * accessible through register MMIO, frame DMA or Ethernet (in case
+ * NPI mode is used).
  */
-void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
-			  enum ocelot_tag_prefix injection,
-			  enum ocelot_tag_prefix extraction)
+static void ocelot_cpu_port_init(struct ocelot *ocelot)
 {
 	int cpu = ocelot->num_phys_ports;
 
-	ocelot->npi = npi;
-	ocelot->inj_prefix = injection;
-	ocelot->xtr_prefix = extraction;
-
 	/* The unicast destination PGID for the CPU port module is unused */
 	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
 	/* Instead set up a multicast destination PGID for traffic copied to
@@ -1373,31 +1365,13 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 			 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
 			 ANA_PORT_PORT_CFG, cpu);
 
-	if (npi >= 0 && npi < ocelot->num_phys_ports) {
-		ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
-			     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi),
-			     QSYS_EXT_CPU_CFG);
-
-		/* Enable NPI port */
-		ocelot_fields_write(ocelot, npi,
-				    QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
-		/* NPI port Injection/Extraction configuration */
-		ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_XTR_HDR,
-				    extraction);
-		ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_INJ_HDR,
-				    injection);
-
-		/* Disable transmission of pause frames */
-		ocelot_fields_write(ocelot, npi, SYS_PAUSE_CFG_PAUSE_ENA, 0);
-	}
-
 	/* Enable CPU port module */
 	ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
 	/* CPU port Injection/Extraction configuration */
 	ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
-			    extraction);
+			    ocelot->xtr_prefix);
 	ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
-			    injection);
+			    ocelot->inj_prefix);
 
 	/* Configure the CPU port to be VLAN aware */
 	ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
@@ -1405,7 +1379,6 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 				 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
 			 ANA_PORT_VLAN_CFG, cpu);
 }
-EXPORT_SYMBOL(ocelot_configure_cpu);
 
 int ocelot_init(struct ocelot *ocelot)
 {
@@ -1445,6 +1418,7 @@ int ocelot_init(struct ocelot *ocelot)
 	ocelot_mact_init(ocelot);
 	ocelot_vlan_init(ocelot);
 	ocelot_vcap_init(ocelot);
+	ocelot_cpu_port_init(ocelot);
 
 	for (port = 0; port < ocelot->num_phys_ports; port++) {
 		/* Clear all counters (5 groups) */
diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
index dfb1535f26f2..d7aef2fb9848 100644
--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
@@ -930,10 +930,6 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,
 	if (!ocelot->ports)
 		return -ENOMEM;
 
-	/* No NPI port */
-	ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
-			     OCELOT_TAG_PREFIX_NONE);
-
 	for_each_available_child_of_node(ports, portnp) {
 		struct ocelot_port_private *priv;
 		struct ocelot_port *ocelot_port;
@@ -1120,6 +1116,9 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
 	ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
 	ocelot->vcap = vsc7514_vcap_props;
+	ocelot->inj_prefix = OCELOT_TAG_PREFIX_NONE;
+	ocelot->xtr_prefix = OCELOT_TAG_PREFIX_NONE;
+	ocelot->npi = -1;
 
 	err = ocelot_init(ocelot);
 	if (err)
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 3105bbb6cdcf..349e839c4c18 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -672,9 +672,6 @@ void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
 int ocelot_regfields_init(struct ocelot *ocelot,
 			  const struct reg_field *const regfields);
 struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res);
-void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
-			  enum ocelot_tag_prefix injection,
-			  enum ocelot_tag_prefix extraction);
 int ocelot_init(struct ocelot *ocelot);
 void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);
-- 
2.25.1


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

* [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 01/16] net: mscc: ocelot: move NPI port configuration to DSA Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 17:47   ` Andrew Lunn
  2020-09-26 17:30 ` [PATCH v2 net-next 03/16] net: dsa: sja1105: request promiscuous mode for master Vladimir Oltean
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Currently DSA assumes that taggers don't mess with the destination MAC
address of the frames on RX. That is not always the case. Some DSA
headers are placed before the Ethernet header (ocelot), and others
simply mangle random bytes from the destination MAC address (sja1105
with its incl_srcpt option).

The DSA master goes to promiscuous mode automatically when the slave
devices go too (such as when enslaved to a bridge), but in standalone
mode this is a problem that needs to be dealt with.

So give drivers the possibility to signal that their tagging protocol
will get randomly dropped otherwise, and let DSA deal with fixing that.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/net/dsa.h |  7 +++++++
 net/dsa/master.c  | 21 ++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index d16057c5987a..70571b179d05 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -317,6 +317,13 @@ struct dsa_switch {
 	 */
 	bool			mtu_enforcement_ingress;
 
+	/* Some tagging protocols either mangle or shift the destination MAC
+	 * address, in which case the DSA master would drop packets on ingress
+	 * if what it understands out of the destination MAC address is not in
+	 * its RX filter.
+	 */
+	bool			promisc_on_master;
+
 	size_t num_ports;
 };
 
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 61615ebc70e9..c12cbcdd54b1 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -259,6 +259,19 @@ static void dsa_netdev_ops_set(struct net_device *dev,
 	dev->dsa_ptr->netdev_ops = ops;
 }
 
+static void dsa_master_set_promiscuity(struct net_device *dev, int inc)
+{
+	struct dsa_port *cpu_dp = dev->dsa_ptr;
+	struct dsa_switch *ds = cpu_dp->ds;
+
+	if (!ds->promisc_on_master)
+		return;
+
+	rtnl_lock();
+	dev_set_promiscuity(dev, inc);
+	rtnl_unlock();
+}
+
 static ssize_t tagging_show(struct device *d, struct device_attribute *attr,
 			    char *buf)
 {
@@ -314,9 +327,12 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 	dev->dsa_ptr = cpu_dp;
 	lockdep_set_class(&dev->addr_list_lock,
 			  &dsa_master_addr_list_lock_key);
+
+	dsa_master_set_promiscuity(dev, 1);
+
 	ret = dsa_master_ethtool_setup(dev);
 	if (ret)
-		return ret;
+		goto out_err_reset_promisc;
 
 	dsa_netdev_ops_set(dev, &dsa_netdev_ops);
 
@@ -329,6 +345,8 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 out_err_ndo_teardown:
 	dsa_netdev_ops_set(dev, NULL);
 	dsa_master_ethtool_teardown(dev);
+out_err_reset_promisc:
+	dsa_master_set_promiscuity(dev, -1);
 	return ret;
 }
 
@@ -338,6 +356,7 @@ void dsa_master_teardown(struct net_device *dev)
 	dsa_netdev_ops_set(dev, NULL);
 	dsa_master_ethtool_teardown(dev);
 	dsa_master_reset_mtu(dev);
+	dsa_master_set_promiscuity(dev, -1);
 
 	dev->dsa_ptr = NULL;
 
-- 
2.25.1


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

* [PATCH v2 net-next 03/16] net: dsa: sja1105: request promiscuous mode for master
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 01/16] net: mscc: ocelot: move NPI port configuration to DSA Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 04/16] net: dsa: tag_ocelot: use a short prefix on both ingress and egress Vladimir Oltean
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Currently PTP is broken when ports are in standalone mode (the tagger
keeps printing this message):

sja1105 spi0.1: Expected meta frame, is 01-80-c2-00-00-0e in the DSA master multicast filter?

Sure, one might say "simply add 01-80-c2-00-00-0e to the master's RX
filter" but things become more complicated because:

- Actually all frames in the 01-80-c2-xx-xx-xx and 01-1b-19-xx-xx-xx
  range are trapped to the CPU automatically
- The switch mangles bytes 3 and 4 of the MAC address via the incl_srcpt
  ("include source port [in the DMAC]") option, which is how source port
  and switch id identification is done for link-local traffic on RX. But
  this means that an address installed to the RX filter would, at the
  end of the day, not correspond to the final address seen by the DSA
  master.

Assume RX filtering lists on DSA masters are typically too small to
include all necessary addresses for PTP to work properly on sja1105, and
just request promiscuous mode unconditionally.

Just an example:
Assuming the following addresses are trapped to the CPU:
01-80-c2-00-00-00 to 01-80-c2-00-00-ff
01-1b-19-00-00-00 to 01-1b-19-00-00-ff

These are 512 addresses.
Now let's say this is a board with 3 switches, and 4 ports per switch.
The 512 addresses become 6144 addresses that must be managed by the DSA
master's RX filtering lists.

This may be refined in the future, but for now, it is simply not worth
it to add the additional addresses to the master's RX filter, so simply
request it to become promiscuous as soon as the driver probes.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/sja1105/sja1105_main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 547487c535df..626902b54ce0 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -2914,6 +2914,9 @@ static int sja1105_setup(struct dsa_switch *ds)
 		dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc);
 		return rc;
 	}
+
+	ds->promisc_on_master = true;
+
 	/* On SJA1105, VLAN filtering per se is always enabled in hardware.
 	 * The only thing we can do to disable it is lie about what the 802.1Q
 	 * EtherType is.
-- 
2.25.1


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

* [PATCH v2 net-next 04/16] net: dsa: tag_ocelot: use a short prefix on both ingress and egress
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (2 preceding siblings ...)
  2020-09-26 17:30 ` [PATCH v2 net-next 03/16] net: dsa: sja1105: request promiscuous mode for master Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 17:30 ` [PATCH v2 net-next 05/16] net: dsa: make the .flow_dissect tagger callback return void Vladimir Oltean
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

There are 2 goals that we follow:

- Reduce the header size
- Make the header size equal between RX and TX

The issue that required long prefix on RX was the fact that the ocelot
DSA tag, being put before Ethernet as it is, would overlap with the area
that a DSA master uses for RX filtering (destination MAC address
mainly).

Now that we can ask DSA to put the master in promiscuous mode, in theory
we could remove the prefix altogether and call it a day, but it looks
like we can't. Using no prefix on ingress, some packets (such as ICMP)
would be received, while others (such as PTP) would not be received.
This is because the DSA master we use (enetc) triggers parse errors
("MAC rx frame errors") presumably because it sees Ethernet frames with
a bad length. And indeed, when using no prefix, the EtherType (bytes
12-13 of the frame, bits 96-111) falls over the REW_VAL field from the
extraction header, aka the PTP timestamp.

When turning the short (32-bit) prefix on, the EtherType overlaps with
bits 64-79 of the extraction header, which are a reserved area
transmitted as zero by the switch. The packets are not dropped by the
DSA master with a short prefix. Actually, the frames look like this in
tcpdump (below is a PTP frame, with an extra dsa_8021q tag - dadb 0482 -
added by a downstream sja1105).

89:0c:a9:f2:01:00 > 88:80:00:0a:00:1d, 802.3, length 0: LLC, \
	dsap Unknown (0x10) Individual, ssap ProWay NM (0x0e) Response, \
	ctrl 0x0004: Information, send seq 2, rcv seq 0, \
	Flags [Response], length 78

0x0000:  8880 000a 001d 890c a9f2 0100 0000 100f  ................
0x0010:  0400 0000 0180 c200 000e 001f 7b63 0248  ............{c.H
0x0020:  dadb 0482 88f7 1202 0036 0000 0000 0000  .........6......
0x0030:  0000 0000 0000 0000 0000 001f 7bff fe63  ............{..c
0x0040:  0248 0001 1f81 0500 0000 0000 0000 0000  .H..............
0x0050:  0000 0000 0000 0000 0000 0000            ............

So the short prefix is our new default: we've shortened our RX frames by
12 octets, increased TX by 4, and headers are now equal between RX and
TX. Note that we still need promiscuous mode for the DSA master to not
drop it.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c           |  7 ++++---
 drivers/net/dsa/ocelot/felix_vsc9959.c   | 13 ++++++++++---
 drivers/net/dsa/ocelot/seville_vsc9953.c | 13 ++++++++++---
 include/soc/mscc/ocelot.h                |  1 +
 net/dsa/tag_ocelot.c                     | 19 ++++++++++++-------
 5 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index b8e192374a32..897e013d89eb 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -439,8 +439,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 	ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
 	ocelot->vcap		= felix->info->vcap;
 	ocelot->ops		= felix->info->ops;
-	ocelot->inj_prefix	= OCELOT_TAG_PREFIX_NONE;
-	ocelot->xtr_prefix	= OCELOT_TAG_PREFIX_LONG;
+	ocelot->inj_prefix	= OCELOT_TAG_PREFIX_SHORT;
+	ocelot->xtr_prefix	= OCELOT_TAG_PREFIX_SHORT;
 
 	port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
 				 GFP_KERNEL);
@@ -511,7 +511,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 			return PTR_ERR(target);
 		}
 
-		template = devm_kzalloc(ocelot->dev, OCELOT_TAG_LEN,
+		template = devm_kzalloc(ocelot->dev, OCELOT_TOTAL_TAG_LEN,
 					GFP_KERNEL);
 		if (!template) {
 			dev_err(ocelot->dev,
@@ -618,6 +618,7 @@ static int felix_setup(struct dsa_switch *ds)
 				 ANA_FLOODING_FLD_UNICAST(PGID_UC),
 				 ANA_FLOODING, tc);
 
+	ds->promisc_on_master = true;
 	ds->mtu_enforcement_ingress = true;
 	ds->configure_vlan_while_not_filtering = true;
 
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 3ab6d6847c5b..2e9270c00096 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1155,6 +1155,8 @@ static void vsc9959_xmit_template_populate(struct ocelot *ocelot, int port)
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
 	u8 *template = ocelot_port->xmit_template;
 	u64 bypass, dest, src;
+	__be32 *prefix;
+	u8 *injection;
 
 	/* Set the source port as the CPU port module and not the
 	 * NPI port
@@ -1163,9 +1165,14 @@ static void vsc9959_xmit_template_populate(struct ocelot *ocelot, int port)
 	dest = BIT(port);
 	bypass = true;
 
-	packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
-	packing(template, &dest,    68,  56, OCELOT_TAG_LEN, PACK, 0);
-	packing(template, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
+	injection = template + OCELOT_SHORT_PREFIX_LEN;
+	prefix = (__be32 *)template;
+
+	packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
+	packing(injection, &dest,    68,  56, OCELOT_TAG_LEN, PACK, 0);
+	packing(injection, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
+
+	*prefix = cpu_to_be32(0x8880000a);
 }
 
 static const struct felix_info felix_info_vsc9959 = {
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index b0ff90c0ae16..e28dd600f464 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -1003,6 +1003,8 @@ static void vsc9953_xmit_template_populate(struct ocelot *ocelot, int port)
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
 	u8 *template = ocelot_port->xmit_template;
 	u64 bypass, dest, src;
+	__be32 *prefix;
+	u8 *injection;
 
 	/* Set the source port as the CPU port module and not the
 	 * NPI port
@@ -1011,9 +1013,14 @@ static void vsc9953_xmit_template_populate(struct ocelot *ocelot, int port)
 	dest = BIT(port);
 	bypass = true;
 
-	packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
-	packing(template, &dest,    67,  57, OCELOT_TAG_LEN, PACK, 0);
-	packing(template, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
+	injection = template + OCELOT_SHORT_PREFIX_LEN;
+	prefix = (__be32 *)template;
+
+	packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
+	packing(injection, &dest,    67,  57, OCELOT_TAG_LEN, PACK, 0);
+	packing(injection, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
+
+	*prefix = cpu_to_be32(0x88800005);
 }
 
 static const struct felix_info seville_info_vsc9953 = {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 349e839c4c18..3093385f6147 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -101,6 +101,7 @@
 #define OCELOT_TAG_LEN			16
 #define OCELOT_SHORT_PREFIX_LEN		4
 #define OCELOT_LONG_PREFIX_LEN		16
+#define OCELOT_TOTAL_TAG_LEN	(OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN)
 
 #define OCELOT_SPEED_2500		0
 #define OCELOT_SPEED_1000		1
diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c
index d1a7e224adff..fb6d006eb986 100644
--- a/net/dsa/tag_ocelot.c
+++ b/net/dsa/tag_ocelot.c
@@ -141,10 +141,12 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
 	struct dsa_switch *ds = dp->ds;
 	struct ocelot *ocelot = ds->priv;
 	struct ocelot_port *ocelot_port;
+	u8 *prefix, *injection;
 	u64 qos_class, rew_op;
-	u8 *injection;
+	int err;
 
-	if (unlikely(skb_cow_head(skb, OCELOT_TAG_LEN) < 0)) {
+	err = skb_cow_head(skb, OCELOT_TOTAL_TAG_LEN);
+	if (unlikely(err < 0)) {
 		netdev_err(netdev, "Cannot make room for tag.\n");
 		return NULL;
 	}
@@ -153,7 +155,10 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
 
 	injection = skb_push(skb, OCELOT_TAG_LEN);
 
-	memcpy(injection, ocelot_port->xmit_template, OCELOT_TAG_LEN);
+	prefix = skb_push(skb, OCELOT_SHORT_PREFIX_LEN);
+
+	memcpy(prefix, ocelot_port->xmit_template, OCELOT_TOTAL_TAG_LEN);
+
 	/* Fix up the fields which are not statically determined
 	 * in the template
 	 */
@@ -187,11 +192,11 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
 	 * so it points to the beginning of the frame.
 	 */
 	skb_push(skb, ETH_HLEN);
-	/* We don't care about the long prefix, it is just for easy entrance
+	/* We don't care about the short prefix, it is just for easy entrance
 	 * into the DSA master's RX filter. Discard it now by moving it into
 	 * the headroom.
 	 */
-	skb_pull(skb, OCELOT_LONG_PREFIX_LEN);
+	skb_pull(skb, OCELOT_SHORT_PREFIX_LEN);
 	/* And skb->data now points to the extraction frame header.
 	 * Keep a pointer to it.
 	 */
@@ -205,7 +210,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
 	skb_pull(skb, ETH_HLEN);
 
 	/* Remove from inet csum the extraction header */
-	skb_postpull_rcsum(skb, start, OCELOT_LONG_PREFIX_LEN + OCELOT_TAG_LEN);
+	skb_postpull_rcsum(skb, start, OCELOT_TOTAL_TAG_LEN);
 
 	packing(extraction, &src_port,  46, 43, OCELOT_TAG_LEN, UNPACK, 0);
 	packing(extraction, &qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
@@ -231,7 +236,7 @@ static const struct dsa_device_ops ocelot_netdev_ops = {
 	.proto			= DSA_TAG_PROTO_OCELOT,
 	.xmit			= ocelot_xmit,
 	.rcv			= ocelot_rcv,
-	.overhead		= OCELOT_TAG_LEN + OCELOT_LONG_PREFIX_LEN,
+	.overhead		= OCELOT_TOTAL_TAG_LEN,
 };
 
 MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH v2 net-next 05/16] net: dsa: make the .flow_dissect tagger callback return void
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (3 preceding siblings ...)
  2020-09-26 17:30 ` [PATCH v2 net-next 04/16] net: dsa: tag_ocelot: use a short prefix on both ingress and egress Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 17:49   ` Andrew Lunn
  2020-09-26 17:30 ` [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector Vladimir Oltean
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

There is no tagger that returns anything other than zero, so just change
the return type appropriately.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/net/dsa.h         | 4 ++--
 net/core/flow_dissector.c | 4 ++--
 net/dsa/tag_brcm.c        | 5 ++---
 net/dsa/tag_dsa.c         | 5 ++---
 net/dsa/tag_edsa.c        | 5 ++---
 net/dsa/tag_mtk.c         | 6 ++----
 net/dsa/tag_qca.c         | 6 ++----
 net/dsa/tag_rtl4_a.c      | 6 ++----
 8 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 70571b179d05..80f5a388337c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -74,8 +74,8 @@ struct dsa_device_ops {
 	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
 	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
 			       struct packet_type *pt);
-	int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
-			    int *offset);
+	void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
+			     int *offset);
 	/* Used to determine which traffic should match the DSA filter in
 	 * eth_type_trans, and which, if any, should bypass it and be processed
 	 * as regular on the master net device.
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 29806eb765cf..13cc4c0a8863 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -932,8 +932,8 @@ bool __skb_flow_dissect(const struct net *net,
 			int offset = 0;
 
 			ops = skb->dev->dsa_ptr->tag_ops;
-			if (ops->flow_dissect &&
-			    !ops->flow_dissect(skb, &proto, &offset)) {
+			if (ops->flow_dissect) {
+				ops->flow_dissect(skb, &proto, &offset);
 				hlen -= offset;
 				nhoff += offset;
 			}
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index 1dab212a294f..610bc7469667 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -150,8 +150,8 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
 	return skb;
 }
 
-static int brcm_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				 int *offset)
+static void brcm_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				  int *offset)
 {
 	/* We have been called on the DSA master network device after
 	 * eth_type_trans() which pulled the Ethernet header already.
@@ -168,7 +168,6 @@ static int brcm_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
 	 */
 	*offset = BRCM_TAG_LEN;
 	*proto = ((__be16 *)skb->data)[1];
-	return 0;
 }
 #endif
 
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index 7ddec9794477..ef15aee58dfc 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -142,12 +142,11 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static int dsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				int *offset)
+static void dsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				 int *offset)
 {
 	*offset = 4;
 	*proto = ((__be16 *)skb->data)[1];
-	return 0;
 }
 
 static const struct dsa_device_ops dsa_netdev_ops = {
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index d6200ff98200..275e7d931b1a 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -192,12 +192,11 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static int edsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				 int *offset)
+static void edsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				  int *offset)
 {
 	*offset = 8;
 	*proto = ((__be16 *)skb->data)[3];
-	return 0;
 }
 
 static const struct dsa_device_ops edsa_netdev_ops = {
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index f602fc758d68..2aba17b43e69 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -105,13 +105,11 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static int mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				int *offset)
+static void mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				 int *offset)
 {
 	*offset = 4;
 	*proto = ((__be16 *)skb->data)[1];
-
-	return 0;
 }
 
 static const struct dsa_device_ops mtk_netdev_ops = {
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index 7066f5e697d7..a75c6b20c215 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -89,13 +89,11 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static int qca_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-                                int *offset)
+static void qca_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				 int *offset)
 {
 	*offset = QCA_HDR_LEN;
 	*proto = ((__be16 *)skb->data)[0];
-
-	return 0;
 }
 
 static const struct dsa_device_ops qca_netdev_ops = {
diff --git a/net/dsa/tag_rtl4_a.c b/net/dsa/tag_rtl4_a.c
index 7b63010fa87b..868980ba1fcd 100644
--- a/net/dsa/tag_rtl4_a.c
+++ b/net/dsa/tag_rtl4_a.c
@@ -106,14 +106,12 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
 	return skb;
 }
 
-static int rtl4a_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				  int *offset)
+static void rtl4a_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				   int *offset)
 {
 	*offset = RTL4_A_HDR_LEN;
 	/* Skip past the tag and fetch the encapsulated Ethertype */
 	*proto = ((__be16 *)skb->data)[1];
-
-	return 0;
 }
 
 static const struct dsa_device_ops rtl4a_netdev_ops = {
-- 
2.25.1


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

* [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (4 preceding siblings ...)
  2020-09-26 17:30 ` [PATCH v2 net-next 05/16] net: dsa: make the .flow_dissect tagger callback return void Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 18:05   ` Andrew Lunn
  2020-09-26 18:13   ` Andrew Lunn
  2020-09-26 17:30 ` [PATCH v2 net-next 07/16] net: dsa: tag_ar8331: use generic flow dissector procedure Vladimir Oltean
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

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@nxp.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


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

* [PATCH v2 net-next 07/16] net: dsa: tag_ar8331: use generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (5 preceding siblings ...)
  2020-09-26 17:30 ` [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector Vladimir Oltean
@ 2020-09-26 17:30 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 08/16] net: dsa: tag_brcm: " Vladimir Oltean
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:30 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

The switch inside these Atheros chips seems to place the DSA tag before
the Ethernet destination MAC address, so it can use the generic flow
dissector procedure which accounts for a header displacement equal with
the tag length.

Cc: Oleksij Rempel <linux@rempel-privat.de>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_ar9331.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/dsa/tag_ar9331.c b/net/dsa/tag_ar9331.c
index 55b00694cdba..5a7e13e36aa7 100644
--- a/net/dsa/tag_ar9331.c
+++ b/net/dsa/tag_ar9331.c
@@ -89,6 +89,7 @@ static const struct dsa_device_ops ar9331_netdev_ops = {
 	.xmit	= ar9331_tag_xmit,
 	.rcv	= ar9331_tag_rcv,
 	.overhead = AR9331_HDR_LEN,
+	.flow_dissect = dsa_tag_generic_flow_dissect,
 };
 
 MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH v2 net-next 08/16] net: dsa: tag_brcm: use generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (6 preceding siblings ...)
  2020-09-26 17:30 ` [PATCH v2 net-next 07/16] net: dsa: tag_ar8331: use generic flow dissector procedure Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 09/16] net: dsa: tag_dsa: use the " Vladimir Oltean
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

There are 2 Broadcom tags in use, one places the DSA tag before the
Ethernet destination MAC address, and the other before the EtherType.
Nonetheless, both displace the rest of the headers, so this tagger can
use the generic flow dissector procedure which accounts for that.

The ASCII art drawing is a good reference though, so keep it but move it
somewhere else.

Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_brcm.c | 36 ++++++++++++++----------------------
 1 file changed, 14 insertions(+), 22 deletions(-)

diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index 610bc7469667..880736e39d3a 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -107,6 +107,18 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
 	return skb;
 }
 
+/* Frames with this tag have one of these two layouts:
+ * -----------------------------------
+ * | MAC DA | MAC SA | 4b tag | Type | DSA_TAG_PROTO_BRCM
+ * -----------------------------------
+ * -----------------------------------
+ * | 4b tag | MAC DA | MAC SA | Type | DSA_TAG_PROTO_BRCM_PREPEND
+ * -----------------------------------
+ * In both cases, at receive time, skb->data points 2 bytes before the actual
+ * Ethernet type field and we have an offset of 4bytes between where skb->data
+ * and where the payload starts. So the same low-level receive function can be
+ * used.
+ */
 static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
 				       struct net_device *dev,
 				       struct packet_type *pt,
@@ -149,26 +161,6 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
 
 	return skb;
 }
-
-static void brcm_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				  int *offset)
-{
-	/* We have been called on the DSA master network device after
-	 * eth_type_trans() which pulled the Ethernet header already.
-	 * Frames have one of these two layouts:
-	 * -----------------------------------
-	 * | MAC DA | MAC SA | 4b tag | Type | DSA_TAG_PROTO_BRCM
-	 * -----------------------------------
-	 * -----------------------------------
-	 * | 4b tag | MAC DA | MAC SA | Type | DSA_TAG_PROTO_BRCM_PREPEND
-	 * -----------------------------------
-	 * skb->data points 2 bytes before the actual Ethernet type field and
-	 * we have an offset of 4bytes between where skb->data and where the
-	 * payload starts.
-	 */
-	*offset = BRCM_TAG_LEN;
-	*proto = ((__be16 *)skb->data)[1];
-}
 #endif
 
 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
@@ -204,7 +196,7 @@ static const struct dsa_device_ops brcm_netdev_ops = {
 	.xmit	= brcm_tag_xmit,
 	.rcv	= brcm_tag_rcv,
 	.overhead = BRCM_TAG_LEN,
-	.flow_dissect = brcm_tag_flow_dissect,
+	.flow_dissect = dsa_tag_generic_flow_dissect,
 };
 
 DSA_TAG_DRIVER(brcm_netdev_ops);
@@ -239,7 +231,7 @@ static const struct dsa_device_ops brcm_prepend_netdev_ops = {
 	.xmit	= brcm_tag_xmit_prepend,
 	.rcv	= brcm_tag_rcv_prepend,
 	.overhead = BRCM_TAG_LEN,
-	.flow_dissect = brcm_tag_flow_dissect,
+	.flow_dissect = dsa_tag_generic_flow_dissect,
 };
 
 DSA_TAG_DRIVER(brcm_prepend_netdev_ops);
-- 
2.25.1


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

* [PATCH v2 net-next 09/16] net: dsa: tag_dsa: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (7 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 08/16] net: dsa: tag_brcm: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 10/16] net: dsa: tag_edsa: " Vladimir Oltean
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Refactor the .flow_dissect procedure to call the common helper instead
of open-coding the header displacement.

Cc: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_dsa.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index ef15aee58dfc..413086dcddb4 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -142,19 +142,12 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static void dsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				 int *offset)
-{
-	*offset = 4;
-	*proto = ((__be16 *)skb->data)[1];
-}
-
 static const struct dsa_device_ops dsa_netdev_ops = {
 	.name	= "dsa",
 	.proto	= DSA_TAG_PROTO_DSA,
 	.xmit	= dsa_xmit,
 	.rcv	= dsa_rcv,
-	.flow_dissect   = dsa_tag_flow_dissect,
+	.flow_dissect   = dsa_tag_generic_flow_dissect,
 	.overhead = DSA_HLEN,
 };
 
-- 
2.25.1


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

* [PATCH v2 net-next 10/16] net: dsa: tag_edsa: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (8 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 09/16] net: dsa: tag_dsa: use the " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 11/16] net: dsa: tag_lan9303: " Vladimir Oltean
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Refactor the .flow_dissect procedure to call the common helper instead
of open-coding the header displacement.

Cc: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_edsa.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index 275e7d931b1a..ae883124f679 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -192,19 +192,12 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static void edsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				  int *offset)
-{
-	*offset = 8;
-	*proto = ((__be16 *)skb->data)[3];
-}
-
 static const struct dsa_device_ops edsa_netdev_ops = {
 	.name	= "edsa",
 	.proto	= DSA_TAG_PROTO_EDSA,
 	.xmit	= edsa_xmit,
 	.rcv	= edsa_rcv,
-	.flow_dissect   = edsa_tag_flow_dissect,
+	.flow_dissect   = dsa_tag_generic_flow_dissect,
 	.overhead = EDSA_HLEN,
 };
 
-- 
2.25.1


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

* [PATCH v2 net-next 11/16] net: dsa: tag_lan9303: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (9 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 10/16] net: dsa: tag_edsa: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 12/16] net: dsa: tag_mtk: " Vladimir Oltean
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

The LAN9303 switches use a DSA tag placed before the EtherType, so they
displace all headers that follow afterwards. Call the generic flow
dissector procedure so that this is accounted for.

Cc: Juergen Beisert <jbe@pengutronix.de>
Cc: Egil Hjelmeland <privat@egil-hjelmeland.no>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_lan9303.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index ccfb6f641bbf..94e3808500d9 100644
--- a/net/dsa/tag_lan9303.c
+++ b/net/dsa/tag_lan9303.c
@@ -135,6 +135,7 @@ static const struct dsa_device_ops lan9303_netdev_ops = {
 	.xmit = lan9303_xmit,
 	.rcv = lan9303_rcv,
 	.overhead = LAN9303_TAG_LEN,
+	.flow_dissect = dsa_tag_generic_flow_dissect,
 };
 
 MODULE_LICENSE("GPL");
-- 
2.25.1


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

* [PATCH v2 net-next 12/16] net: dsa: tag_mtk: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (10 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 11/16] net: dsa: tag_lan9303: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 13/16] net: dsa: tag_ocelot: " Vladimir Oltean
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Mediatek switches already account for shifting the frame headers to the
right, replace that with a call to the generic flow dissector procedure.

Cc: DENG Qingfang <dqfext@gmail.com>
Cc: Sean Wang <sean.wang@mediatek.com>
Cc: John Crispin <john@phrozen.org>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_mtk.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 2aba17b43e69..7aea20b1d58d 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -105,19 +105,12 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static void mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				 int *offset)
-{
-	*offset = 4;
-	*proto = ((__be16 *)skb->data)[1];
-}
-
 static const struct dsa_device_ops mtk_netdev_ops = {
 	.name		= "mtk",
 	.proto		= DSA_TAG_PROTO_MTK,
 	.xmit		= mtk_tag_xmit,
 	.rcv		= mtk_tag_rcv,
-	.flow_dissect	= mtk_tag_flow_dissect,
+	.flow_dissect	= dsa_tag_generic_flow_dissect,
 	.overhead	= MTK_HDR_LEN,
 };
 
-- 
2.25.1


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

* [PATCH v2 net-next 13/16] net: dsa: tag_ocelot: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (11 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 12/16] net: dsa: tag_mtk: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 14/16] net: dsa: tag_qca: " Vladimir Oltean
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Ocelot switches put their DSA tag before the Ethernet header, so they
shift the other headers and need to call the generic flow dissector
procedure. Do this now, once we've made the injection and the extraction
header use the same length prefixes.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_ocelot.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c
index fb6d006eb986..5ee81b535357 100644
--- a/net/dsa/tag_ocelot.c
+++ b/net/dsa/tag_ocelot.c
@@ -237,6 +237,7 @@ static const struct dsa_device_ops ocelot_netdev_ops = {
 	.xmit			= ocelot_xmit,
 	.rcv			= ocelot_rcv,
 	.overhead		= OCELOT_TOTAL_TAG_LEN,
+	.flow_dissect		= dsa_tag_generic_flow_dissect,
 };
 
 MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH v2 net-next 14/16] net: dsa: tag_qca: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (12 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 13/16] net: dsa: tag_ocelot: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 15/16] net: dsa: tag_sja1105: " Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 16/16] net: dsa: tag_rtl4_a: " Vladimir Oltean
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

Refactor the .flow_dissect procedure to call the common helper instead
of open-coding the header displacement.

Cc: John Crispin <john@phrozen.org>
Cc: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_qca.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index a75c6b20c215..bb929b8092cb 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -89,19 +89,12 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
 	return skb;
 }
 
-static void qca_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				 int *offset)
-{
-	*offset = QCA_HDR_LEN;
-	*proto = ((__be16 *)skb->data)[0];
-}
-
 static const struct dsa_device_ops qca_netdev_ops = {
 	.name	= "qca",
 	.proto	= DSA_TAG_PROTO_QCA,
 	.xmit	= qca_tag_xmit,
 	.rcv	= qca_tag_rcv,
-	.flow_dissect = qca_tag_flow_dissect,
+	.flow_dissect = dsa_tag_generic_flow_dissect,
 	.overhead = QCA_HDR_LEN,
 };
 
-- 
2.25.1


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

* [PATCH v2 net-next 15/16] net: dsa: tag_sja1105: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (13 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 14/16] net: dsa: tag_qca: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  2020-09-26 17:31 ` [PATCH v2 net-next 16/16] net: dsa: tag_rtl4_a: " Vladimir Oltean
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

The sja1105 is a bit of a special snowflake, in that not all frames are
transmitted/received in the same way. L2 link-local frames are received
with the source port/switch ID information put in the destination MAC
address. For the rest, a tag_8021q header is used. So only the latter
frames displace the rest of the headers and need to use the generic flow
dissector procedure.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_sja1105.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index 3710f9daa46d..57408bbd789b 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -346,6 +346,16 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
 					      is_meta);
 }
 
+static void sja1105_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				 int *offset)
+{
+	/* No tag added for management frames, all ok */
+	if (unlikely(sja1105_is_link_local(skb)))
+		return;
+
+	dsa_tag_generic_flow_dissect(skb, proto, offset);
+}
+
 static const struct dsa_device_ops sja1105_netdev_ops = {
 	.name = "sja1105",
 	.proto = DSA_TAG_PROTO_SJA1105,
@@ -353,6 +363,7 @@ static const struct dsa_device_ops sja1105_netdev_ops = {
 	.rcv = sja1105_rcv,
 	.filter = sja1105_filter,
 	.overhead = VLAN_HLEN,
+	.flow_dissect = sja1105_flow_dissect,
 };
 
 MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH v2 net-next 16/16] net: dsa: tag_rtl4_a: use the generic flow dissector procedure
  2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
                   ` (14 preceding siblings ...)
  2020-09-26 17:31 ` [PATCH v2 net-next 15/16] net: dsa: tag_sja1105: " Vladimir Oltean
@ 2020-09-26 17:31 ` Vladimir Oltean
  15 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:31 UTC (permalink / raw)
  To: netdev, davem; +Cc: andrew, f.fainelli, vivien.didelot, kuba

The Realtek 4 byte A tag is placed before the EtherType, so refactor the
.flow_dissect procedure to call the common helper created for this
specific case.

Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: DENG Qingfang <dqfext@gmail.com>
Cc: Mauri Sandberg <sandberg@mailfence.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_rtl4_a.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/net/dsa/tag_rtl4_a.c b/net/dsa/tag_rtl4_a.c
index 868980ba1fcd..d2237a6a06d6 100644
--- a/net/dsa/tag_rtl4_a.c
+++ b/net/dsa/tag_rtl4_a.c
@@ -106,20 +106,12 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
 	return skb;
 }
 
-static void rtl4a_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
-				   int *offset)
-{
-	*offset = RTL4_A_HDR_LEN;
-	/* Skip past the tag and fetch the encapsulated Ethertype */
-	*proto = ((__be16 *)skb->data)[1];
-}
-
 static const struct dsa_device_ops rtl4a_netdev_ops = {
 	.name	= "rtl4a",
 	.proto	= DSA_TAG_PROTO_RTL4_A,
 	.xmit	= rtl4a_tag_xmit,
 	.rcv	= rtl4a_tag_rcv,
-	.flow_dissect = rtl4a_tag_flow_dissect,
+	.flow_dissect = dsa_tag_generic_flow_dissect,
 	.overhead = RTL4_A_HDR_LEN,
 };
 module_dsa_tag_driver(rtl4a_netdev_ops);
-- 
2.25.1


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

* Re: [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master
  2020-09-26 17:30 ` [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master Vladimir Oltean
@ 2020-09-26 17:47   ` Andrew Lunn
  2020-09-26 17:55     ` Vladimir Oltean
  0 siblings, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2020-09-26 17:47 UTC (permalink / raw)
  To: Vladimir Oltean; +Cc: netdev, davem, f.fainelli, vivien.didelot, kuba

On Sat, Sep 26, 2020 at 08:30:54PM +0300, Vladimir Oltean wrote:
> Currently DSA assumes that taggers don't mess with the destination MAC
> address of the frames on RX. That is not always the case. Some DSA
> headers are placed before the Ethernet header (ocelot), and others
> simply mangle random bytes from the destination MAC address (sja1105
> with its incl_srcpt option).

...

> So give drivers the possibility to signal that their tagging protocol
> will get randomly dropped otherwise, and let DSA deal with fixing that.

> @@ -317,6 +317,13 @@ struct dsa_switch {
>  	 */
>  	bool			mtu_enforcement_ingress;
>  
> +	/* Some tagging protocols either mangle or shift the destination MAC
> +	 * address, in which case the DSA master would drop packets on ingress
> +	 * if what it understands out of the destination MAC address is not in
> +	 * its RX filter.
> +	 */
> +	bool			promisc_on_master;
> +
>  	size_t num_ports;
>  };

Hi Vladimir

I actually think this is a property of the tagger, not the DSA
driver. In fact, DSA drivers never handle actual frames, they are all
about the control plane, not the data plane. So i think this bool
should be in the tagger structure, dsa_device_ops.

       Andrew

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

* Re: [PATCH v2 net-next 05/16] net: dsa: make the .flow_dissect tagger callback return void
  2020-09-26 17:30 ` [PATCH v2 net-next 05/16] net: dsa: make the .flow_dissect tagger callback return void Vladimir Oltean
@ 2020-09-26 17:49   ` Andrew Lunn
  0 siblings, 0 replies; 24+ messages in thread
From: Andrew Lunn @ 2020-09-26 17:49 UTC (permalink / raw)
  To: Vladimir Oltean; +Cc: netdev, davem, f.fainelli, vivien.didelot, kuba

On Sat, Sep 26, 2020 at 08:30:57PM +0300, Vladimir Oltean wrote:
> There is no tagger that returns anything other than zero, so just change
> the return type appropriately.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

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

* Re: [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master
  2020-09-26 17:47   ` Andrew Lunn
@ 2020-09-26 17:55     ` Vladimir Oltean
  0 siblings, 0 replies; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 17:55 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev, davem, f.fainelli, vivien.didelot, kuba

On Sat, Sep 26, 2020 at 07:47:00PM +0200, Andrew Lunn wrote:
> Hi Vladimir
>
> I actually think this is a property of the tagger, not the DSA
> driver. In fact, DSA drivers never handle actual frames, they are all
> about the control plane, not the data plane. So i think this bool
> should be in the tagger structure, dsa_device_ops.

This is actually a good comment that will simplify my future work a
little bit. I need to add a Kconfig-selectable tagger for the Felix
driver (tag_ocelot.c vs a future tag_ocelot_8021q.c) and, predictably
enough, one tagger needs promisc on master while the other doesn't.

If you have no other comments on this series, I'm thinking about
resending it right away with this change, since I made a big blunder and
the people in Cc on the tagger patches were not actually copied to my
emails, since I have supresscc=all in my .gitconfig.

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

* Re: [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector
  2020-09-26 17:30 ` [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector Vladimir Oltean
@ 2020-09-26 18:05   ` Andrew Lunn
  2020-09-26 18:18     ` Vladimir Oltean
  2020-09-26 18:13   ` Andrew Lunn
  1 sibling, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2020-09-26 18:05 UTC (permalink / raw)
  To: Vladimir Oltean; +Cc: netdev, davem, f.fainelli, vivien.didelot, kuba

On Sat, Sep 26, 2020 at 08:30:58PM +0300, Vladimir Oltean wrote:
> 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.

This is interesting, and opens up the possibility of an optimisation on
the hot path.

net/core/flow_dissector.c:

bool __skb_flow_dissect(const struct net *net,
                        const struct sk_buff *skb,
                        struct flow_dissector *flow_dissector,
                        void *target_container,
                        void *data, __be16 proto, int nhoff, int hlen,
                        unsigned int flags)
{
...

#if IS_ENABLED(CONFIG_NET_DSA)
                if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) &&
                             proto == htons(ETH_P_XDSA))) {
                        const struct dsa_device_ops *ops;
                        int offset = 0;

                        ops = skb->dev->dsa_ptr->tag_ops;
                        if (ops->flow_dissect &&
                            !ops->flow_dissect(skb, &proto, &offset)) {
                                hlen -= offset;
                                nhoff += offset;
                        }
                }
#endif

Given spectra and meltdown etc, jumping through a pointer is expensive
and we try to avoid it on the hot path. Given most of the taggers are
going to use the generic version, maybe add a test here, is
ops->flow_dissect the generic version, and if so, call it directly,
rather than go through the pointer. Or only set ops->flow_dissect if
the generic version cannot be used.

    Andrew

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

* Re: [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector
  2020-09-26 17:30 ` [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector Vladimir Oltean
  2020-09-26 18:05   ` Andrew Lunn
@ 2020-09-26 18:13   ` Andrew Lunn
  1 sibling, 0 replies; 24+ messages in thread
From: Andrew Lunn @ 2020-09-26 18:13 UTC (permalink / raw)
  To: Vladimir Oltean; +Cc: netdev, davem, f.fainelli, vivien.didelot, kuba

> +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);

If you look where this is used:

#if IS_ENABLED(CONFIG_NET_DSA)
                if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) &&
                             proto == htons(ETH_P_XDSA))) {
                        const struct dsa_device_ops *ops;
                        int offset = 0;

                        ops = skb->dev->dsa_ptr->tag_ops;
                        if (ops->flow_dissect &&
                            !ops->flow_dissect(skb, &proto, &offset)) {
                                hlen -= offset;
                                nhoff += offset;
                        }
                }
#endif

We have already done ops = skb->dev->dsa_ptr->tag_ops once. But since
it is in a different compilation unit, the optimise has no idea about
this. So building on my last comment, it would be nice to make this an
inline function to help out the optimiser.

       Andrew

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

* Re: [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector
  2020-09-26 18:05   ` Andrew Lunn
@ 2020-09-26 18:18     ` Vladimir Oltean
  2020-09-26 18:28       ` Andrew Lunn
  0 siblings, 1 reply; 24+ messages in thread
From: Vladimir Oltean @ 2020-09-26 18:18 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Vladimir Oltean, netdev, davem, f.fainelli, vivien.didelot, kuba

On Sat, Sep 26, 2020 at 08:05:45PM +0200, Andrew Lunn wrote:
> Given spectra and meltdown etc, jumping through a pointer is expensive
> and we try to avoid it on the hot path. Given most of the taggers are
> going to use the generic version, maybe add a test here, is
> ops->flow_dissect the generic version, and if so, call it directly,
> rather than go through the pointer. Or only set ops->flow_dissect if
> the generic version cannot be used.

Agree about the motivation to eliminate an indirect call if possible.

The situation is as follows:
- Some taggers are before DMAC or before EtherType. These are the vast
  majority, and dsa_tag_generic_flow_dissect works well for them. We can
  keep the .flow_dissect callback as an override, but if this is absent,
  then the flow dissector can call dsa_tag_generic_flow_dissect
  directly.
- Some taggers use tail tags. These don't need any massaging at all. But
  we need to tell the flow dissector to not call
  dsa_tag_generic_flow_dissect if it doesn't find a function pointer.
  I'm thinking about adding another "bool tail_tag" in struct
  dsa_device_ops, for this purpose and not only*.
  *Usually tunnel interfaces need to set dev->needed_headroom for the
  memory allocator. But DSA doesn't request that, and needs to check
  manually in the xmit function if the headroom is large enough to push
  a tag. BUT! tail tags don't need dev->needed_headroom, they need
  dev->needed_tailroom, I think. So I was thinking about adding this
  bool anyway, to distinguish between these 2 cases.

What do you think?

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

* Re: [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector
  2020-09-26 18:18     ` Vladimir Oltean
@ 2020-09-26 18:28       ` Andrew Lunn
  0 siblings, 0 replies; 24+ messages in thread
From: Andrew Lunn @ 2020-09-26 18:28 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Vladimir Oltean, netdev, davem, f.fainelli, vivien.didelot, kuba

On Sat, Sep 26, 2020 at 09:18:15PM +0300, Vladimir Oltean wrote:
> On Sat, Sep 26, 2020 at 08:05:45PM +0200, Andrew Lunn wrote:
> > Given spectra and meltdown etc, jumping through a pointer is expensive
> > and we try to avoid it on the hot path. Given most of the taggers are
> > going to use the generic version, maybe add a test here, is
> > ops->flow_dissect the generic version, and if so, call it directly,
> > rather than go through the pointer. Or only set ops->flow_dissect if
> > the generic version cannot be used.
> 
> Agree about the motivation to eliminate an indirect call if possible.
> 
> The situation is as follows:
> - Some taggers are before DMAC or before EtherType. These are the vast
>   majority, and dsa_tag_generic_flow_dissect works well for them. We can
>   keep the .flow_dissect callback as an override, but if this is absent,
>   then the flow dissector can call dsa_tag_generic_flow_dissect
>   directly.
> - Some taggers use tail tags. These don't need any massaging at all. But
>   we need to tell the flow dissector to not call
>   dsa_tag_generic_flow_dissect if it doesn't find a function pointer.
>   I'm thinking about adding another "bool tail_tag" in struct
>   dsa_device_ops, for this purpose and not only*.
>   *Usually tunnel interfaces need to set dev->needed_headroom for the
>   memory allocator. But DSA doesn't request that, and needs to check
>   manually in the xmit function if the headroom is large enough to push
>   a tag. BUT! tail tags don't need dev->needed_headroom, they need
>   dev->needed_tailroom, I think. So I was thinking about adding this
>   bool anyway, to distinguish between these 2 cases.
> 
> What do you think?

Sounds good.

       Andrew

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

end of thread, other threads:[~2020-09-26 18:28 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-26 17:30 [PATCH v2 net-next 00/16] Generic adjustment for flow dissector in DSA Vladimir Oltean
2020-09-26 17:30 ` [PATCH v2 net-next 01/16] net: mscc: ocelot: move NPI port configuration to DSA Vladimir Oltean
2020-09-26 17:30 ` [PATCH v2 net-next 02/16] net: dsa: allow drivers to request promiscuous mode on master Vladimir Oltean
2020-09-26 17:47   ` Andrew Lunn
2020-09-26 17:55     ` Vladimir Oltean
2020-09-26 17:30 ` [PATCH v2 net-next 03/16] net: dsa: sja1105: request promiscuous mode for master Vladimir Oltean
2020-09-26 17:30 ` [PATCH v2 net-next 04/16] net: dsa: tag_ocelot: use a short prefix on both ingress and egress Vladimir Oltean
2020-09-26 17:30 ` [PATCH v2 net-next 05/16] net: dsa: make the .flow_dissect tagger callback return void Vladimir Oltean
2020-09-26 17:49   ` Andrew Lunn
2020-09-26 17:30 ` [PATCH v2 net-next 06/16] net: dsa: add a generic procedure for the flow dissector Vladimir Oltean
2020-09-26 18:05   ` Andrew Lunn
2020-09-26 18:18     ` Vladimir Oltean
2020-09-26 18:28       ` Andrew Lunn
2020-09-26 18:13   ` Andrew Lunn
2020-09-26 17:30 ` [PATCH v2 net-next 07/16] net: dsa: tag_ar8331: use generic flow dissector procedure Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 08/16] net: dsa: tag_brcm: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 09/16] net: dsa: tag_dsa: use the " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 10/16] net: dsa: tag_edsa: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 11/16] net: dsa: tag_lan9303: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 12/16] net: dsa: tag_mtk: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 13/16] net: dsa: tag_ocelot: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 14/16] net: dsa: tag_qca: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 15/16] net: dsa: tag_sja1105: " Vladimir Oltean
2020-09-26 17:31 ` [PATCH v2 net-next 16/16] net: dsa: tag_rtl4_a: " Vladimir Oltean

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).