Skip to content

Commit b0274eb

Browse files
committed
Merge branch 'Dynamic-toggling-of-vlan_filtering-for-SJA1105-DSA'
Vladimir Oltean says: ==================== Dynamic toggling of vlan_filtering for SJA1105 DSA This patchset addresses a limitation in dsa_8021q where this sequence of commands was causing the switch to stop forwarding traffic: ip link add name br0 type bridge vlan_filtering 0 ip link set dev swp2 master br0 echo 1 > /sys/class/net/br0/bridge/vlan_filtering echo 0 > /sys/class/net/br0/bridge/vlan_filtering The issue has to do with the VLAN table manipulations that dsa_8021q does without notifying the bridge layer. The solution is to always restore the VLANs that the bridge knows about, when disabling tagging. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 5c63592 + 5f33183 commit b0274eb

File tree

2 files changed

+84
-20
lines changed

2 files changed

+84
-20
lines changed

net/bridge/br_vlan.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,8 @@ int br_vlan_get_info(const struct net_device *dev, u16 vid,
12811281

12821282
p_vinfo->vid = vid;
12831283
p_vinfo->flags = v->flags;
1284+
if (vid == br_get_pvid(vg))
1285+
p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID;
12841286
return 0;
12851287
}
12861288
EXPORT_SYMBOL_GPL(br_vlan_get_info);

net/dsa/tag_8021q.c

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,79 @@ int dsa_8021q_rx_source_port(u16 vid)
9191
}
9292
EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);
9393

94+
static int dsa_8021q_restore_pvid(struct dsa_switch *ds, int port)
95+
{
96+
struct bridge_vlan_info vinfo;
97+
struct net_device *slave;
98+
u16 pvid;
99+
int err;
100+
101+
if (!dsa_is_user_port(ds, port))
102+
return 0;
103+
104+
slave = ds->ports[port].slave;
105+
106+
err = br_vlan_get_pvid(slave, &pvid);
107+
if (err < 0)
108+
/* There is no pvid on the bridge for this port, which is
109+
* perfectly valid. Nothing to restore, bye-bye!
110+
*/
111+
return 0;
112+
113+
err = br_vlan_get_info(slave, pvid, &vinfo);
114+
if (err < 0) {
115+
dev_err(ds->dev, "Couldn't determine PVID attributes\n");
116+
return err;
117+
}
118+
119+
return dsa_port_vid_add(&ds->ports[port], pvid, vinfo.flags);
120+
}
121+
122+
/* If @enabled is true, installs @vid with @flags into the switch port's HW
123+
* filter.
124+
* If @enabled is false, deletes @vid (ignores @flags) from the port. Had the
125+
* user explicitly configured this @vid through the bridge core, then the @vid
126+
* is installed again, but this time with the flags from the bridge layer.
127+
*/
128+
static int dsa_8021q_vid_apply(struct dsa_switch *ds, int port, u16 vid,
129+
u16 flags, bool enabled)
130+
{
131+
struct dsa_port *dp = &ds->ports[port];
132+
struct bridge_vlan_info vinfo;
133+
int err;
134+
135+
if (enabled)
136+
return dsa_port_vid_add(dp, vid, flags);
137+
138+
err = dsa_port_vid_del(dp, vid);
139+
if (err < 0)
140+
return err;
141+
142+
/* Nothing to restore from the bridge for a non-user port.
143+
* The CPU port VLANs are restored implicitly with the user ports,
144+
* similar to how the bridge does in dsa_slave_vlan_add and
145+
* dsa_slave_vlan_del.
146+
*/
147+
if (!dsa_is_user_port(ds, port))
148+
return 0;
149+
150+
err = br_vlan_get_info(dp->slave, vid, &vinfo);
151+
/* Couldn't determine bridge attributes for this vid,
152+
* it means the bridge had not configured it.
153+
*/
154+
if (err < 0)
155+
return 0;
156+
157+
/* Restore the VID from the bridge */
158+
err = dsa_port_vid_add(dp, vid, vinfo.flags);
159+
if (err < 0)
160+
return err;
161+
162+
vinfo.flags &= ~BRIDGE_VLAN_INFO_PVID;
163+
164+
return dsa_port_vid_add(dp->cpu_dp, vid, vinfo.flags);
165+
}
166+
94167
/* RX VLAN tagging (left) and TX VLAN tagging (right) setup shown for a single
95168
* front-panel switch port (here swp0).
96169
*
@@ -146,8 +219,6 @@ EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);
146219
int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
147220
{
148221
int upstream = dsa_upstream_port(ds, port);
149-
struct dsa_port *dp = &ds->ports[port];
150-
struct dsa_port *upstream_dp = &ds->ports[upstream];
151222
u16 rx_vid = dsa_8021q_rx_vid(ds, port);
152223
u16 tx_vid = dsa_8021q_tx_vid(ds, port);
153224
int i, err;
@@ -164,7 +235,6 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
164235
* restrictions, so there are no concerns about leaking traffic.
165236
*/
166237
for (i = 0; i < ds->num_ports; i++) {
167-
struct dsa_port *other_dp = &ds->ports[i];
168238
u16 flags;
169239

170240
if (i == upstream)
@@ -177,10 +247,7 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
177247
/* The RX VID is a regular VLAN on all others */
178248
flags = BRIDGE_VLAN_INFO_UNTAGGED;
179249

180-
if (enabled)
181-
err = dsa_port_vid_add(other_dp, rx_vid, flags);
182-
else
183-
err = dsa_port_vid_del(other_dp, rx_vid);
250+
err = dsa_8021q_vid_apply(ds, i, rx_vid, flags, enabled);
184251
if (err) {
185252
dev_err(ds->dev, "Failed to apply RX VID %d to port %d: %d\n",
186253
rx_vid, port, err);
@@ -191,37 +258,32 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
191258
/* CPU port needs to see this port's RX VID
192259
* as tagged egress.
193260
*/
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);
261+
err = dsa_8021q_vid_apply(ds, upstream, rx_vid, 0, enabled);
198262
if (err) {
199263
dev_err(ds->dev, "Failed to apply RX VID %d to port %d: %d\n",
200264
rx_vid, port, err);
201265
return err;
202266
}
203267

204268
/* Finally apply the TX VID on this port and on the CPU port */
205-
if (enabled)
206-
err = dsa_port_vid_add(dp, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED);
207-
else
208-
err = dsa_port_vid_del(dp, tx_vid);
269+
err = dsa_8021q_vid_apply(ds, port, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED,
270+
enabled);
209271
if (err) {
210272
dev_err(ds->dev, "Failed to apply TX VID %d on port %d: %d\n",
211273
tx_vid, port, err);
212274
return err;
213275
}
214-
if (enabled)
215-
err = dsa_port_vid_add(upstream_dp, tx_vid, 0);
216-
else
217-
err = dsa_port_vid_del(upstream_dp, tx_vid);
276+
err = dsa_8021q_vid_apply(ds, upstream, tx_vid, 0, enabled);
218277
if (err) {
219278
dev_err(ds->dev, "Failed to apply TX VID %d on port %d: %d\n",
220279
tx_vid, upstream, err);
221280
return err;
222281
}
223282

224-
return 0;
283+
if (!enabled)
284+
err = dsa_8021q_restore_pvid(ds, port);
285+
286+
return err;
225287
}
226288
EXPORT_SYMBOL_GPL(dsa_port_setup_8021q_tagging);
227289

0 commit comments

Comments
 (0)