Skip to content

Commit 0471dd4

Browse files
vladimirolteandavem330
authored andcommitted
net: dsa: tag_8021q: Create a stable binary format
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: f9bbe44 ("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> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d34d2ba commit 0471dd4

File tree

1 file changed

+50
-10
lines changed

1 file changed

+50
-10
lines changed

net/dsa/tag_8021q.c

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,59 @@
1111

1212
#include "dsa_priv.h"
1313

14-
/* Allocating two VLAN tags per port - one for the RX VID and
15-
* the other for the TX VID - see below
14+
/* Binary structure of the fake 12-bit VID field (when the TPID is
15+
* ETH_P_DSA_8021Q):
16+
*
17+
* | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
18+
* +-----------+-----+-----------------+-----------+-----------------------+
19+
* | DIR | RSV | SWITCH_ID | RSV | PORT |
20+
* +-----------+-----+-----------------+-----------+-----------------------+
21+
*
22+
* DIR - VID[11:10]:
23+
* Direction flags.
24+
* * 1 (0b01) for RX VLAN,
25+
* * 2 (0b10) for TX VLAN.
26+
* These values make the special VIDs of 0, 1 and 4095 to be left
27+
* unused by this coding scheme.
28+
*
29+
* RSV - VID[9]:
30+
* To be used for further expansion of SWITCH_ID or for other purposes.
31+
*
32+
* SWITCH_ID - VID[8:6]:
33+
* Index of switch within DSA tree. Must be between 0 and
34+
* DSA_MAX_SWITCHES - 1.
35+
*
36+
* RSV - VID[5:4]:
37+
* To be used for further expansion of PORT or for other purposes.
38+
*
39+
* PORT - VID[3:0]:
40+
* Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
1641
*/
17-
#define DSA_8021Q_VID_RANGE (DSA_MAX_SWITCHES * DSA_MAX_PORTS)
18-
#define DSA_8021Q_VID_BASE (VLAN_N_VID - 2 * DSA_8021Q_VID_RANGE - 1)
19-
#define DSA_8021Q_RX_VID_BASE (DSA_8021Q_VID_BASE)
20-
#define DSA_8021Q_TX_VID_BASE (DSA_8021Q_VID_BASE + DSA_8021Q_VID_RANGE)
42+
43+
#define DSA_8021Q_DIR_SHIFT 10
44+
#define DSA_8021Q_DIR_MASK GENMASK(11, 10)
45+
#define DSA_8021Q_DIR(x) (((x) << DSA_8021Q_DIR_SHIFT) & \
46+
DSA_8021Q_DIR_MASK)
47+
#define DSA_8021Q_DIR_RX DSA_8021Q_DIR(1)
48+
#define DSA_8021Q_DIR_TX DSA_8021Q_DIR(2)
49+
50+
#define DSA_8021Q_SWITCH_ID_SHIFT 6
51+
#define DSA_8021Q_SWITCH_ID_MASK GENMASK(8, 6)
52+
#define DSA_8021Q_SWITCH_ID(x) (((x) << DSA_8021Q_SWITCH_ID_SHIFT) & \
53+
DSA_8021Q_SWITCH_ID_MASK)
54+
55+
#define DSA_8021Q_PORT_SHIFT 0
56+
#define DSA_8021Q_PORT_MASK GENMASK(3, 0)
57+
#define DSA_8021Q_PORT(x) (((x) << DSA_8021Q_PORT_SHIFT) & \
58+
DSA_8021Q_PORT_MASK)
2159

2260
/* Returns the VID to be inserted into the frame from xmit for switch steering
2361
* instructions on egress. Encodes switch ID and port ID.
2462
*/
2563
u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port)
2664
{
27-
return DSA_8021Q_TX_VID_BASE + (DSA_MAX_PORTS * ds->index) + port;
65+
return DSA_8021Q_DIR_TX | DSA_8021Q_SWITCH_ID(ds->index) |
66+
DSA_8021Q_PORT(port);
2867
}
2968
EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
3069

@@ -33,21 +72,22 @@ EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
3372
*/
3473
u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port)
3574
{
36-
return DSA_8021Q_RX_VID_BASE + (DSA_MAX_PORTS * ds->index) + port;
75+
return DSA_8021Q_DIR_RX | DSA_8021Q_SWITCH_ID(ds->index) |
76+
DSA_8021Q_PORT(port);
3777
}
3878
EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid);
3979

4080
/* Returns the decoded switch ID from the RX VID. */
4181
int dsa_8021q_rx_switch_id(u16 vid)
4282
{
43-
return ((vid - DSA_8021Q_RX_VID_BASE) / DSA_MAX_PORTS);
83+
return (vid & DSA_8021Q_SWITCH_ID_MASK) >> DSA_8021Q_SWITCH_ID_SHIFT;
4484
}
4585
EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id);
4686

4787
/* Returns the decoded port ID from the RX VID. */
4888
int dsa_8021q_rx_source_port(u16 vid)
4989
{
50-
return ((vid - DSA_8021Q_RX_VID_BASE) % DSA_MAX_PORTS);
90+
return (vid & DSA_8021Q_PORT_MASK) >> DSA_8021Q_PORT_SHIFT;
5191
}
5292
EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);
5393

0 commit comments

Comments
 (0)