diff mbox series

[net,2/2] net: dsa: tag_8021q: Create a stable binary format

Message ID 20190528225005.10628-3-olteanv@gmail.com
State Changes Requested
Delegated to: David Miller
Headers show
Series Fixes for DSA tagging using 802.1Q | expand

Commit Message

Vladimir Oltean May 28, 2019, 10:50 p.m. UTC
Tools like tcpdump need to be able to decode the significance of fake
VLAN headers that DSA uses to separate switch ports.

But currently these have no global significance - they are simply an
ordered list of DSA_MAX_SWITCHES x DSA_MAX_PORTS numbers ending at 4095.

The reason why this is submitted as a fix is that the existing mapping
of VIDs should not enter into a stable kernel, so we can pretend that
only the new format exists. This way tcpdump won't need to try to make
something out of the VLAN tags on 5.2 kernels.

Fixes: f9bbe4477c30 ("net: dsa: Optional VLAN-based port separation for switches without tagging")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
---
 net/dsa/tag_8021q.c | 54 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 10 deletions(-)

Comments

Florian Fainelli May 29, 2019, 1:08 a.m. UTC | #1
On 5/28/2019 3:50 PM, Vladimir Oltean wrote:
> Tools like tcpdump need to be able to decode the significance of fake
> VLAN headers that DSA uses to separate switch ports.
> 
> But currently these have no global significance - they are simply an
> ordered list of DSA_MAX_SWITCHES x DSA_MAX_PORTS numbers ending at 4095.
> 
> The reason why this is submitted as a fix is that the existing mapping
> of VIDs should not enter into a stable kernel, so we can pretend that
> only the new format exists. This way tcpdump won't need to try to make
> something out of the VLAN tags on 5.2 kernels.
> 
> Fixes: f9bbe4477c30 ("net: dsa: Optional VLAN-based port separation for switches without tagging")
> Signed-off-by: Vladimir Oltean <olteanv@gmail.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

This looks a lot nicer actually, and kudos for documenting the format.
Vladimir Oltean May 29, 2019, 10:09 a.m. UTC | #2
On Wed, 29 May 2019 at 04:08, Florian Fainelli <f.fainelli@gmail.com> wrote:
>
>
>
> On 5/28/2019 3:50 PM, Vladimir Oltean wrote:
> > Tools like tcpdump need to be able to decode the significance of fake
> > VLAN headers that DSA uses to separate switch ports.
> >
> > But currently these have no global significance - they are simply an
> > ordered list of DSA_MAX_SWITCHES x DSA_MAX_PORTS numbers ending at 4095.
> >
> > The reason why this is submitted as a fix is that the existing mapping
> > of VIDs should not enter into a stable kernel, so we can pretend that
> > only the new format exists. This way tcpdump won't need to try to make
> > something out of the VLAN tags on 5.2 kernels.
> >
> > Fixes: f9bbe4477c30 ("net: dsa: Optional VLAN-based port separation for switches without tagging")
> > Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
>
> This looks a lot nicer actually, and kudos for documenting the format.
> --
> Florian

Please don't merge this. The MBZ bit doesn't actually prevent the VID
from taking the reserved value of 0. I don't know what I was thinking.
I'll send out a v2 soon.

Thanks,
-Vladimir
diff mbox series

Patch

diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 4adec6bbfe59..4c2c70ce5d54 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -11,20 +11,54 @@ 
 
 #include "dsa_priv.h"
 
-/* Allocating two VLAN tags per port - one for the RX VID and
- * the other for the TX VID - see below
+/* Binary structure of the fake 12-bit VID field (when the TPID is
+ * ETH_P_DSA_8021Q):
+ *
+ * +-----+------+-----------------+------+-----------------------------+-----+
+ * | DIR | RSVD |    SWITCH_ID    | RSVD |             PORT            | MBZ |
+ * +-----+------+-----------------+------+-----------------------------+-----+
+ * 12    11     10                7      6                             1     0
+ *
+ * DIR - VID[11]:
+ *	Direction flag. 0 for RX VLAN, 1 for TX VLAN
+ *
+ * RSVD - VID[10]:
+ *	To be used for further expansion of SWITCH_ID or for other purposes.
+ *
+ * SWITCH_ID - VID[9:7]:
+ *	Index of switch within DSA tree. Must be between 0 and
+ *	DSA_MAX_SWITCHES - 1.
+ *
+ * RSVD - VID[6]:
+ *	To be used for further expansion of PORT or for other purposes.
+ *
+ * PORT - VID[5:1]:
+ *	Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
+ *
+ * MBZ - VID[0]:
+ *	Must be zero. This makes the special VIDs of 0, 1 and 4095 to be left
+ *	unused by this coding scheme.
  */
-#define DSA_8021Q_VID_RANGE	(DSA_MAX_SWITCHES * DSA_MAX_PORTS)
-#define DSA_8021Q_VID_BASE	(VLAN_N_VID - 2 * DSA_8021Q_VID_RANGE - 1)
-#define DSA_8021Q_RX_VID_BASE	(DSA_8021Q_VID_BASE)
-#define DSA_8021Q_TX_VID_BASE	(DSA_8021Q_VID_BASE + DSA_8021Q_VID_RANGE)
+
+#define DSA_8021Q_DIR_TX		BIT(11)
+
+#define DSA_8021Q_SWITCH_ID_SHIFT	7
+#define DSA_8021Q_SWITCH_ID_MASK	GENMASK(9, 7)
+#define DSA_8021Q_SWITCH_ID(x)		(((x) << DSA_8021Q_SWITCH_ID_SHIFT) & \
+						 DSA_8021Q_SWITCH_ID_MASK)
+
+#define DSA_8021Q_PORT_MASK		GENMASK(5, 1)
+#define DSA_8021Q_PORT_SHIFT		1
+#define DSA_8021Q_PORT(x)		(((x) << DSA_8021Q_PORT_SHIFT) & \
+						 DSA_8021Q_PORT_MASK)
 
 /* Returns the VID to be inserted into the frame from xmit for switch steering
  * instructions on egress. Encodes switch ID and port ID.
  */
 u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port)
 {
-	return DSA_8021Q_TX_VID_BASE + (DSA_MAX_PORTS * ds->index) + port;
+	return DSA_8021Q_DIR_TX | DSA_8021Q_SWITCH_ID(ds->index) |
+	       DSA_8021Q_PORT(port);
 }
 EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
 
@@ -33,21 +67,21 @@  EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
  */
 u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port)
 {
-	return DSA_8021Q_RX_VID_BASE + (DSA_MAX_PORTS * ds->index) + port;
+	return DSA_8021Q_SWITCH_ID(ds->index) | DSA_8021Q_PORT(port);
 }
 EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid);
 
 /* Returns the decoded switch ID from the RX VID. */
 int dsa_8021q_rx_switch_id(u16 vid)
 {
-	return ((vid - DSA_8021Q_RX_VID_BASE) / DSA_MAX_PORTS);
+	return (vid & DSA_8021Q_SWITCH_ID_MASK) >> DSA_8021Q_SWITCH_ID_SHIFT;
 }
 EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id);
 
 /* Returns the decoded port ID from the RX VID. */
 int dsa_8021q_rx_source_port(u16 vid)
 {
-	return ((vid - DSA_8021Q_RX_VID_BASE) % DSA_MAX_PORTS);
+	return (vid & DSA_8021Q_PORT_MASK) >> DSA_8021Q_PORT_SHIFT;
 }
 EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);