Message ID | 20200907182910.1285496-5-olteanv@gmail.com |
---|---|
State | New |
Headers | show |
Series | Some VLAN handling cleanup in DSA | expand |
On Mon, Sep 07, 2020 at 09:07:34PM -0700, Florian Fainelli wrote: > You should be able to make b53 and bcm_sf2 also use > configure_vlan_while_not_filtering to true (or rather not specify it), give > me until tomorrow to run various tests if you don't mind. Ok, but I would prefer not doing that in this patch. Note that, given a choice, I try to avoid introducing functional changes in drivers where I don't have the hardware to test, or somebody to confirm that it works, at the very least. For that reason, mv88e6xxx doesn't even have this flag set, even though Russell had sent a patch for it with the old name: https://lore.kernel.org/netdev/E1ij6pq-00084C-47@rmk-PC.armlinux.org.uk/ Somebody with a Marvell switch should probably pick that up and resend. Thanks, -Vladimir
On Tue, Sep 08, 2020 at 05:02:06PM -0700, Florian Fainelli wrote: > Found the problem, we do not allow the CPU port to be configured as > untagged, and when we toggle vlan_filtering we actually incorrectly "move" > the PVID from 1 to 0, pvid 1 must be coming from the default_pvid of the bridge, I assume. Where is pvid 0 (aka dev->ports[port].pvid) coming from? Is it simply the cached value from B53_VLAN_PORT_DEF_TAG, from a previous b53_vlan_filtering() call? Strange. > which is incorrect, but since the CPU is also untagged in VID 0 this > is why it "works" or rather two mistakes canceling it each other. How does the CPU end up untagged in VLAN 0? > I still need to confirm this, but the bridge in VLAN filtering mode seems to > support receiving frames with the default_pvid as tagged, and it will untag > it for the bridge master device transparently. So it seems. > The reason for not allowing the CPU port to be untagged > (ca8931948344c485569b04821d1f6bcebccd376b) was because the CPU port could be > added as untagged in several VLANs, e.g.: when port0-3 are PVID 1 untagged, > and port 4 is PVID 2 untagged. Back then there was no support for Broadcom > tags, so the only way to differentiate traffic properly was to also add a > pair of tagged VIDs to the DSA master. > I am still trying to remember whether there were other concerns that > prompted me to make that change and would appreciate some thoughts on that. I think it makes some sense to always configure the VLANs on the CPU port as tagged either way. I did the same in Felix and it's ok. But that was due to a hardware limitation. On sja1105 I'm keeping the same flags as on the user port, and that is ok too. > Tangentially, maybe we should finally add support for programming the CPU > port's VLAN membership independently from the other ports. How? > The following appears to work nicely now and allows us to get rid of the > b53_vlan_filtering() logic, which would no longer work now because it > assumed that toggling vlan_filtering implied that there would be no VLAN > configuration when filtering was off. > > diff --git a/drivers/net/dsa/b53/b53_common.c > b/drivers/net/dsa/b53/b53_common.c > index 26fcff85d881..fac033730f4a 100644 > --- a/drivers/net/dsa/b53/b53_common.c > +++ b/drivers/net/dsa/b53/b53_common.c > @@ -1322,23 +1322,6 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up); > int b53_vlan_filtering(struct dsa_switch *ds, int port, bool > vlan_filtering) > { > struct b53_device *dev = ds->priv; > - u16 pvid, new_pvid; > - > - b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid); > - if (!vlan_filtering) { > - /* Filtering is currently enabled, use the default PVID > since > - * the bridge does not expect tagging anymore > - */ > - dev->ports[port].pvid = pvid; > - new_pvid = b53_default_pvid(dev); > - } else { > - /* Filtering is currently disabled, restore the previous > PVID */ > - new_pvid = dev->ports[port].pvid; > - } > - > - if (pvid != new_pvid) > - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), > - new_pvid); Yes, much simpler. > > b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); > > @@ -1389,7 +1372,7 @@ void b53_vlan_add(struct dsa_switch *ds, int port, > untagged = true; > > vl->members |= BIT(port); > - if (untagged && !dsa_is_cpu_port(ds, port)) > + if (untagged) > vl->untag |= BIT(port); > else > vl->untag &= ~BIT(port); > @@ -1427,7 +1410,7 @@ int b53_vlan_del(struct dsa_switch *ds, int port, > if (pvid == vid) > pvid = b53_default_pvid(dev); > > - if (untagged && !dsa_is_cpu_port(ds, port)) > + if (untagged) Ok, so you're removing this workaround now. A welcome simplification. > vl->untag &= ~(BIT(port)); > > b53_set_vlan_entry(dev, vid, vl); > @@ -2563,6 +2546,8 @@ struct b53_device *b53_switch_alloc(struct device > *base, > dev->priv = priv; > dev->ops = ops; > ds->ops = &b53_switch_ops; > + ds->configure_vlan_while_not_filtering = true; > + dev->vlan_enabled = ds->configure_vlan_while_not_filtering; > mutex_init(&dev->reg_mutex); > mutex_init(&dev->stats_mutex); > > > -- > Florian Looks good! I'm going to hold off with my configure_vlan_while_not_filtering patch. You can send this one before me. Thanks, -Vladimir
On Wed, Sep 09, 2020 at 10:22:42AM -0700, Florian Fainelli wrote: > How do you make sure that the CPU port sees the frame untagged which would > be necessary for a VLAN-unaware bridge? Do you have a special remapping > rule? No, I don't have any remapping rules that would be relevant here. Why would the frames need to be necessarily untagged for a VLAN-unaware bridge, why is it a problem if they aren't? bool br_allowed_ingress(const struct net_bridge *br, struct net_bridge_vlan_group *vg, struct sk_buff *skb, u16 *vid, u8 *state) { /* If VLAN filtering is disabled on the bridge, all packets are * permitted. */ if (!br_opt_get(br, BROPT_VLAN_ENABLED)) { BR_INPUT_SKB_CB(skb)->vlan_filtered = false; return true; } return __allowed_ingress(br, vg, skb, vid, state); } If I have a VLAN on a bridged switch port where the bridge is not filtering, I have an 8021q upper of the bridge with that VLAN ID. > Initially the concern I had was with the use case described above which was > a 802.1Q separation, but in hindsight MAC address learning would result in > the frames going to the appropriate ports/VLANs anyway. If by "separation" you mean "limiting the forwarding domain", the switch keeps the same VLAN associated with the frame internally, regardless of whether it's egress-tagged or not. > > > > > Tangentially, maybe we should finally add support for programming the CPU > > > port's VLAN membership independently from the other ports. > > > > How? > > Something like this: > > https://lore.kernel.org/lkml/20180625091713.GA13442@apalos/T/ I need to take some time to understand what's going on there.
Hi Vladimir, On Tue Sep 08 2020, Vladimir Oltean wrote: > On Tue, Sep 08, 2020 at 12:14:12PM +0200, Kurt Kanzenbach wrote: >> On Mon Sep 07 2020, Vladimir Oltean wrote: >> > New drivers always seem to omit setting this flag, for some reason. >> >> Yes, because it's not well documented, or is it? Before writing the >> hellcreek DSA driver, I've read dsa.rst documentation to find out what >> callback function should to what. Did I miss something? > > Honestly, Documentation/networking/dsa/dsa.rst is out of date by quite a > bit. And this trend of having boolean flags in struct dsa_switch started > after the documentation stopped being updated. Maybe it would be good to document new flags when they're introduced :). > > But I didn't say it's your fault for not setting the flag, it is easy to > miss, and that's what this patch is trying to improve. > >> > So let's reverse the logic: the DSA core sets it by default to true >> > before the .setup() callback, and legacy drivers can turn it off. This >> > way, new drivers get the new behavior by default, unless they >> > explicitly set the flag to false, which is more obvious during review. >> >> Yeah, that behavior makes more sense to me. Thank you. > > Ok, thanks. Is this merged? I don't see it. Do I have to set `configure_vlan_while_not_filtering' explicitly to true for the next hellcreek version? Thanks, Kurt
On Fri, Oct 02, 2020 at 10:06:28AM +0200, Kurt Kanzenbach wrote: > Hi Vladimir, > > On Tue Sep 08 2020, Vladimir Oltean wrote: > > On Tue, Sep 08, 2020 at 12:14:12PM +0200, Kurt Kanzenbach wrote: > >> On Mon Sep 07 2020, Vladimir Oltean wrote: > >> > New drivers always seem to omit setting this flag, for some reason. > >> > >> Yes, because it's not well documented, or is it? Before writing the > >> hellcreek DSA driver, I've read dsa.rst documentation to find out what > >> callback function should to what. Did I miss something? > > > > Honestly, Documentation/networking/dsa/dsa.rst is out of date by quite a > > bit. And this trend of having boolean flags in struct dsa_switch started > > after the documentation stopped being updated. > > Maybe it would be good to document new flags when they're introduced :). Yup, will definitely do that when I resend. > > > > But I didn't say it's your fault for not setting the flag, it is easy to > > miss, and that's what this patch is trying to improve. > > > >> > So let's reverse the logic: the DSA core sets it by default to true > >> > before the .setup() callback, and legacy drivers can turn it off. This > >> > way, new drivers get the new behavior by default, unless they > >> > explicitly set the flag to false, which is more obvious during review. > >> > >> Yeah, that behavior makes more sense to me. Thank you. > > > > Ok, thanks. > > Is this merged? I don't see it. Do I have to set > `configure_vlan_while_not_filtering' explicitly to true for the next > hellcreek version? Yes, please set it to true. The refactoring change didn't get merged in time, I don't want it to interfere with your series. Thanks, -Vladimir
Hi Kurt, On Fri, Oct 02, 2020 at 11:15:27AM +0300, Vladimir Oltean wrote: > > Is this merged? I don't see it. Do I have to set > > `configure_vlan_while_not_filtering' explicitly to true for the next > > hellcreek version? > > Yes, please set it to true. The refactoring change didn't get merged in > time, I don't want it to interfere with your series. Do you plan on resending hellcreek for 5.10? Thanks, -Vladimir
Hi Vladimir, On Sat Oct 03 2020, Vladimir Oltean wrote: > Hi Kurt, > > On Fri, Oct 02, 2020 at 11:15:27AM +0300, Vladimir Oltean wrote: >> > Is this merged? I don't see it. Do I have to set >> > `configure_vlan_while_not_filtering' explicitly to true for the next >> > hellcreek version? >> >> Yes, please set it to true. The refactoring change didn't get merged in >> time, I don't want it to interfere with your series. > > Do you plan on resending hellcreek for 5.10? I've implemented the configure_vlan_while_not_filtering behaviour yesterday with caching and lists like the sja driver does. It needs some testing and then I'll post it. Maybe next week. Thanks, Kurt
On Sat, Oct 03, 2020 at 11:45:27AM +0200, Kurt Kanzenbach wrote:
> Maybe next week.
The merge window opens next week. This means you can still resend as
RFC, but it can only be accepted in net-next after ~2 weeks.
Thanks,
-Vladimir
On Sun, Oct 04, 2020 at 01:56:17PM +0300, Vladimir Oltean wrote: > On Sat, Oct 03, 2020 at 11:45:27AM +0200, Kurt Kanzenbach wrote: > > Maybe next week. > > The merge window opens next week. This means you can still resend as > RFC, but it can only be accepted in net-next after ~2 weeks. False alarm, looks like we have an rc8. I guess that means you can resend some time this week. Thanks, -Vladimir
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 26fcff85d881..d127cdda16e8 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1011,6 +1011,7 @@ static int b53_setup(struct dsa_switch *ds) * devices. (not hardware supported) */ ds->vlan_filtering_is_global = true; + ds->configure_vlan_while_not_filtering = false; return ret; } diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 3263e8a0ae67..f9587a73fe54 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -1242,6 +1242,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) /* Advertise the 8 egress queues */ ds->num_tx_queues = SF2_NUM_EGRESS_QUEUES; + ds->configure_vlan_while_not_filtering = false; dev_set_drvdata(&pdev->dev, priv); diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c index b588614d1e5e..65b5c1a50282 100644 --- a/drivers/net/dsa/dsa_loop.c +++ b/drivers/net/dsa/dsa_loop.c @@ -343,7 +343,6 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev) ds->dev = &mdiodev->dev; ds->ops = &dsa_loop_driver; ds->priv = ps; - ds->configure_vlan_while_not_filtering = true; ps->bus = mdiodev->bus; dev_set_drvdata(&mdiodev->dev, ds); diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 521ebc072903..8622d836cbd3 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -837,6 +837,9 @@ static int gswip_setup(struct dsa_switch *ds) } gswip_port_enable(ds, cpu_port, NULL); + + ds->configure_vlan_while_not_filtering = false; + return 0; } diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index 8f1d15ea15d9..03d65dc5a304 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -1087,6 +1087,8 @@ static int ksz8795_setup(struct dsa_switch *ds) ksz_init_mib_timer(dev); + ds->configure_vlan_while_not_filtering = false; + return 0; } diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 3cb22d149813..fea265ca6f82 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -1357,6 +1357,8 @@ static int ksz9477_setup(struct dsa_switch *ds) ksz_init_mib_timer(dev); + ds->configure_vlan_while_not_filtering = false; + return 0; } diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 1aaf47a0da2b..4698e740f8fc 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -1220,7 +1220,6 @@ mt7530_setup(struct dsa_switch *ds) * as two netdev instances. */ dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent; - ds->configure_vlan_while_not_filtering = true; if (priv->id == ID_MT7530) { regulator_set_voltage(priv->core_pwr, 1000000, 1000000); diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 15b97a4f8d93..6948c6980092 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3090,6 +3090,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) chip->ds = ds; ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); + ds->configure_vlan_while_not_filtering = false; mv88e6xxx_reg_lock(chip); diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index a1e1d3824110..2032c046a056 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -612,7 +612,6 @@ static int felix_setup(struct dsa_switch *ds) ANA_FLOODING, tc); ds->mtu_enforcement_ingress = true; - ds->configure_vlan_while_not_filtering = true; return 0; } diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index e24a99031b80..20ac64219df2 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -328,6 +328,8 @@ static int ar9331_sw_setup(struct dsa_switch *ds) if (ret) goto error; + ds->configure_vlan_while_not_filtering = false; + return 0; error: dev_err_ratelimited(priv->dev, "%s: %i\n", __func__, ret); diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index f1e484477e35..e05b9cc39231 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1442,7 +1442,6 @@ qca8k_sw_probe(struct mdio_device *mdiodev) priv->ds->dev = &mdiodev->dev; priv->ds->num_ports = QCA8K_NUM_PORTS; - priv->ds->configure_vlan_while_not_filtering = true; priv->ds->priv = priv; priv->ops = qca8k_switch_ops; priv->ds->ops = &priv->ops; diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c index f763f93f600f..c518ab49b968 100644 --- a/drivers/net/dsa/rtl8366rb.c +++ b/drivers/net/dsa/rtl8366rb.c @@ -958,6 +958,8 @@ static int rtl8366rb_setup(struct dsa_switch *ds) return -ENODEV; } + ds->configure_vlan_while_not_filtering = false; + return 0; } diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 045077252799..e2cee36f578f 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3047,8 +3047,6 @@ static int sja1105_setup(struct dsa_switch *ds) ds->mtu_enforcement_ingress = true; - ds->configure_vlan_while_not_filtering = true; - rc = sja1105_setup_devlink_params(ds); if (rc < 0) return rc; diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index c0ffc7a2b65f..4a5e2832009b 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -414,6 +414,8 @@ static int dsa_switch_setup(struct dsa_switch *ds) if (err) goto unregister_devlink; + ds->configure_vlan_while_not_filtering = true; + err = ds->ops->setup(ds); if (err < 0) goto unregister_notifier; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index e429c71df854..e0c86e97bb78 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -314,11 +314,14 @@ static int dsa_slave_vlan_add(struct net_device *dev, if (obj->orig_dev != dev) return -EOPNOTSUPP; - if (dsa_port_skip_vlan_configuration(dp)) - return 0; - vlan = *SWITCHDEV_OBJ_PORT_VLAN(obj); + if (dsa_port_skip_vlan_configuration(dp)) { + netdev_warn(dev, "skipping configuration of VLAN %d-%d\n", + vlan.vid_begin, vlan.vid_end); + return 0; + } + err = dsa_port_vlan_add(dp, &vlan, trans); if (err) return err; @@ -377,17 +380,23 @@ static int dsa_slave_vlan_del(struct net_device *dev, const struct switchdev_obj *obj) { struct dsa_port *dp = dsa_slave_to_port(dev); + struct switchdev_obj_port_vlan *vlan; if (obj->orig_dev != dev) return -EOPNOTSUPP; - if (dsa_port_skip_vlan_configuration(dp)) + vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); + + if (dsa_port_skip_vlan_configuration(dp)) { + netdev_warn(dev, "skipping deletion of VLAN %d-%d\n", + vlan->vid_begin, vlan->vid_end); return 0; + } /* Do not deprogram the CPU port as it may be shared with other user * ports which can be members of this VLAN as well. */ - return dsa_port_vlan_del(dp, SWITCHDEV_OBJ_PORT_VLAN(obj)); + return dsa_port_vlan_del(dp, vlan); } static int dsa_slave_port_obj_del(struct net_device *dev, @@ -1248,8 +1257,11 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto, * need to emulate the switchdev prepare + commit phase. */ if (dp->bridge_dev) { - if (dsa_port_skip_vlan_configuration(dp)) + if (dsa_port_skip_vlan_configuration(dp)) { + netdev_warn(dev, "skipping configuration of VLAN %d\n", + vid); return 0; + } /* br_vlan_get_info() returns -EINVAL or -ENOENT if the * device, respectively the VID is not found, returning @@ -1302,8 +1314,11 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, * need to emulate the switchdev prepare + commit phase. */ if (dp->bridge_dev) { - if (dsa_port_skip_vlan_configuration(dp)) + if (dsa_port_skip_vlan_configuration(dp)) { + netdev_warn(dev, "skipping deletion of VLAN %d\n", + vid); return 0; + } /* br_vlan_get_info() returns -EINVAL or -ENOENT if the * device, respectively the VID is not found, returning