aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-05-30 17:47:14 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-30 17:47:14 -0400
commitc3bc6debb4c7555e7fb1b104ffda416e89570b50 (patch)
tree052e42634fbcade7d76df01b3dcfe5eda0151f42
parent21808437214637952b61beaba6034d97880fbeb3 (diff)
parent0471dd429cea6507a4000169ff6a33f41ba371b3 (diff)
Merge branch 'Fixes-for-DSA-tagging-using-802-1Q'
Vladimir Oltean says: ==================== Fixes for DSA tagging using 802.1Q During the prototyping for the "Decoupling PHYLINK from struct net_device" patchset, the CPU port of the sja1105 driver was moved to a different spot. This uncovered an issue in the tag_8021q DSA code, which used to work by mistake - the CPU port was the last hardware port numerically, and this was masking an ordering issue which is very likely to be seen in other drivers that make use of 802.1Q tags. A question was also raised whether the VID numbers bear any meaning, and the conclusion was that they don't, at least not in an absolute sense. The second patch defines bit fields inside the DSA 802.1Q VID so that tcpdump can decode it unambiguously (although the meaning is now clear even by visual inspection). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/dsa/tag_8021q.c79
1 files changed, 65 insertions, 14 deletions
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 8ae48c7e1e76..65a35e976d7b 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -11,20 +11,59 @@
11 11
12#include "dsa_priv.h" 12#include "dsa_priv.h"
13 13
14/* Allocating two VLAN tags per port - one for the RX VID and 14/* Binary structure of the fake 12-bit VID field (when the TPID is
15 * the other for the TX VID - see below 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.
16 */ 41 */
17#define DSA_8021Q_VID_RANGE (DSA_MAX_SWITCHES * DSA_MAX_PORTS) 42
18#define DSA_8021Q_VID_BASE (VLAN_N_VID - 2 * DSA_8021Q_VID_RANGE - 1) 43#define DSA_8021Q_DIR_SHIFT 10
19#define DSA_8021Q_RX_VID_BASE (DSA_8021Q_VID_BASE) 44#define DSA_8021Q_DIR_MASK GENMASK(11, 10)
20#define DSA_8021Q_TX_VID_BASE (DSA_8021Q_VID_BASE + DSA_8021Q_VID_RANGE) 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)
21 59
22/* Returns the VID to be inserted into the frame from xmit for switch steering 60/* Returns the VID to be inserted into the frame from xmit for switch steering
23 * instructions on egress. Encodes switch ID and port ID. 61 * instructions on egress. Encodes switch ID and port ID.
24 */ 62 */
25u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port) 63u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port)
26{ 64{
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);
28} 67}
29EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid); 68EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
30 69
@@ -33,21 +72,22 @@ EXPORT_SYMBOL_GPL(dsa_8021q_tx_vid);
33 */ 72 */
34u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) 73u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port)
35{ 74{
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);
37} 77}
38EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid); 78EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid);
39 79
40/* Returns the decoded switch ID from the RX VID. */ 80/* Returns the decoded switch ID from the RX VID. */
41int dsa_8021q_rx_switch_id(u16 vid) 81int dsa_8021q_rx_switch_id(u16 vid)
42{ 82{
43 return ((vid - DSA_8021Q_RX_VID_BASE) / DSA_MAX_PORTS); 83 return (vid & DSA_8021Q_SWITCH_ID_MASK) >> DSA_8021Q_SWITCH_ID_SHIFT;
44} 84}
45EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id); 85EXPORT_SYMBOL_GPL(dsa_8021q_rx_switch_id);
46 86
47/* Returns the decoded port ID from the RX VID. */ 87/* Returns the decoded port ID from the RX VID. */
48int dsa_8021q_rx_source_port(u16 vid) 88int dsa_8021q_rx_source_port(u16 vid)
49{ 89{
50 return ((vid - DSA_8021Q_RX_VID_BASE) % DSA_MAX_PORTS); 90 return (vid & DSA_8021Q_PORT_MASK) >> DSA_8021Q_PORT_SHIFT;
51} 91}
52EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); 92EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);
53 93
@@ -128,10 +168,7 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
128 u16 flags; 168 u16 flags;
129 169
130 if (i == upstream) 170 if (i == upstream)
131 /* CPU port needs to see this port's RX VID 171 continue;
132 * as tagged egress.
133 */
134 flags = 0;
135 else if (i == port) 172 else if (i == port)
136 /* The RX VID is pvid on this port */ 173 /* The RX VID is pvid on this port */
137 flags = BRIDGE_VLAN_INFO_UNTAGGED | 174 flags = BRIDGE_VLAN_INFO_UNTAGGED |
@@ -150,6 +187,20 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
150 return err; 187 return err;
151 } 188 }
152 } 189 }
190
191 /* CPU port needs to see this port's RX VID
192 * as tagged egress.
193 */
194 if (enabled)
195 err = dsa_port_vid_add(upstream_dp, rx_vid, 0);
196 else
197 err = dsa_port_vid_del(upstream_dp, rx_vid);
198 if (err) {
199 dev_err(ds->dev, "Failed to apply RX VID %d to port %d: %d\n",
200 rx_vid, port, err);
201 return err;
202 }
203
153 /* Finally apply the TX VID on this port and on the CPU port */ 204 /* Finally apply the TX VID on this port and on the CPU port */
154 if (enabled) 205 if (enabled)
155 err = dsa_port_vid_add(dp, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED); 206 err = dsa_port_vid_add(dp, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED);