00fa91bc | 12-Apr-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: fix tagging protocol changes with multiple CPU ports
When the device tree has 2 CPU ports defined, a single one is active (has any dp->cpu_dp pointers point to it). Yet the second o
net: dsa: felix: fix tagging protocol changes with multiple CPU ports
When the device tree has 2 CPU ports defined, a single one is active (has any dp->cpu_dp pointers point to it). Yet the second one is still a CPU port, and DSA still calls ->change_tag_protocol on it.
On the NXP LS1028A, the CPU ports are ports 4 and 5. Port 4 is the active CPU port and port 5 is inactive.
After the following commands:
# Initial setting cat /sys/class/net/eno2/dsa/tagging ocelot echo ocelot-8021q > /sys/class/net/eno2/dsa/tagging echo ocelot > /sys/class/net/eno2/dsa/tagging
traffic is now broken, because the driver has moved the NPI port from port 4 to port 5, unbeknown to DSA.
The problem can be avoided by detecting that the second CPU port is unused, and not doing anything for it. Further rework will be needed when proper support for multiple CPU ports is added.
Treat this as a bug and prepare current kernels to work in single-CPU mode with multiple-CPU DT blobs.
Fixes: adb3dccf090b ("net: dsa: felix: convert to the new .change_tag_protocol DSA API") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20220412172209.2531865-1-vladimir.oltean@nxp.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
show more ...
|
7e580490 | 08-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: avoid early deletion of host FDB entries
The Felix driver declares FDB isolation but puts all standalone ports in VID 0. This is mostly problem-free as discussed with Alvin here: ht
net: dsa: felix: avoid early deletion of host FDB entries
The Felix driver declares FDB isolation but puts all standalone ports in VID 0. This is mostly problem-free as discussed with Alvin here: https://patchwork.kernel.org/project/netdevbpf/cover/20220302191417.1288145-1-vladimir.oltean@nxp.com/#24763870
however there is one catch. DSA still thinks that FDB entries are installed on the CPU port as many times as there are user ports, and this is problematic when multiple user ports share the same MAC address.
Consider the default case where all user ports inherit their MAC address from the DSA master, and then the user runs:
ip link set swp0 address 00:01:02:03:04:05
The above will make dsa_slave_set_mac_address() call dsa_port_standalone_host_fdb_add() for 00:01:02:03:04:05 in port 0's standalone database, and dsa_port_standalone_host_fdb_del() for the old address of swp0, again in swp0's standalone database.
Both the ->port_fdb_add() and ->port_fdb_del() will be propagated down to the felix driver, which will end up deleting the old MAC address from the CPU port. But this is still in use by other user ports, so we end up breaking unicast termination for them.
There isn't a problem in the fact that DSA keeps track of host standalone addresses in the individual database of each user port: some drivers like sja1105 need this. There also isn't a problem in the fact that some drivers choose the same VID/FID for all standalone ports. It is just that the deletion of these host addresses must be delayed until they are known to not be in use any longer, and only the driver has this knowledge. Since DSA keeps these addresses in &cpu_dp->fdbs and &cpu_db->mdbs, it is just a matter of walking over those lists and see whether the same MAC address is present on the CPU port in the port db of another user port.
I have considered reusing the generic dsa_port_walk_fdbs() and dsa_port_walk_mdbs() schemes for this, but locking makes it difficult. In the ->port_fdb_add() method and co, &dp->addr_lists_lock is held, but dsa_port_walk_fdbs() also acquires that lock. Also, even assuming that we introduce an unlocked variant of the address iterator, we'd still need some relatively complex data structures, and a void *ctx in the dsa_fdb_walk_cb_t which we don't currently pass, such that drivers are able to figure out, after iterating, whether the same MAC address is or isn't present in the port db of another port.
All the above, plus the fact that I expect other drivers to follow the same model as felix where all standalone ports use the same FID, made me conclude that a generic method provided by DSA is necessary: dsa_fdb_present_in_other_db() and the mdb equivalent. Felix calls this from the ->port_fdb_del() handler for the CPU port, when the database was classified to either a port db, or a LAG db.
For symmetry, we also call this from ->port_fdb_add(), because if the address was installed once, then installing it a second time serves no purpose: it's already in hardware in VID 0 and it affects all standalone ports.
This change moves dsa_db_equal() from switch.c to dsa.c, since it now has one more caller.
Fixes: 54c319846086 ("net: mscc: ocelot: enforce FDB isolation when VLAN-unaware") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
f2e2662c | 08-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: actually disable flooding towards NPI port
The two blamed commits were written/tested individually but not together.
When put together, commit 90897569beb1 ("net: dsa: felix: start
net: dsa: felix: actually disable flooding towards NPI port
The two blamed commits were written/tested individually but not together.
When put together, commit 90897569beb1 ("net: dsa: felix: start off with flooding disabled on the CPU port"), which deletes a reinitialization of PGID_UC/PGID_MC/PGID_BC, is no longer sufficient to ensure that these port masks don't contain the CPU port module.
This is because commit b903a6bd2e19 ("net: dsa: felix: migrate flood settings from NPI to tag_8021q CPU port") overwrites the hardware default settings towards the CPU port module with the settings that used to be present on the NPI port treated as a regular port. There, flooding is enabled, so flooding would get enabled on the CPU port module too.
Adding conditional logic somewhere within felix_setup_tag_npi() to configure either the default no-flood policy or the flood policy inherited from the tag_8021q CPU port from a previous call to dsa_port_manage_cpu_flood() is getting complicated. So just let the migration logic do its thing during initial setup (which will temporarily turn on flooding), then turn flooding off for the NPI port after felix_set_tag_protocol() finishes. Here we are in felix_setup(), so the DSA slave interfaces are not yet created, and this doesn't affect traffic in any way.
Fixes: 90897569beb1 ("net: dsa: felix: start off with flooding disabled on the CPU port") Fixes: b903a6bd2e19 ("net: dsa: felix: migrate flood settings from NPI to tag_8021q CPU port") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
162fbf6a | 03-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: remove redundant assignment in felix_8021q_cpu_port_deinit
Due to an apparently incorrect conflict resolution on my part in commit 54c319846086 ("net: mscc: ocelot: enforce FDB isol
net: dsa: felix: remove redundant assignment in felix_8021q_cpu_port_deinit
Due to an apparently incorrect conflict resolution on my part in commit 54c319846086 ("net: mscc: ocelot: enforce FDB isolation when VLAN-unaware"), "ocelot->ports[port]->is_dsa_8021q_cpu = false" was supposed to be replaced by "ocelot_port_unset_dsa_8021q_cpu(ocelot, port)" which does the same thing, and more. But now we have both, so the direct assignment is redundant. Remove it.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
5d3bb7dd | 03-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: print error message in felix_check_xtr_pkt()
Packet extraction failures over register-based MMIO are silent, and difficult to pinpoint. Add an error message to remedy this.
Signed-
net: dsa: felix: print error message in felix_check_xtr_pkt()
Packet extraction failures over register-based MMIO are silent, and difficult to pinpoint. Add an error message to remedy this.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
dbd03285 | 03-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: initialize "err" to 0 in felix_check_xtr_pkt()
Automated tools complain that felix_check_xtr_pkt() has logic to drain the CPU queue on the reception of a PTP packet over Ethernet, y
net: dsa: felix: initialize "err" to 0 in felix_check_xtr_pkt()
Automated tools complain that felix_check_xtr_pkt() has logic to drain the CPU queue on the reception of a PTP packet over Ethernet, yet it returns an uninitialized error code in the case where the CPU queue was empty.
This is not likely to happen (/possible if hardware works correctly), but it isn't a fatal condition either. The PTP packet will be dequeued from the CPU queue when the next PTP packet arrives. So initialize "err" to 0 for the case where nothing was dequeued during this iteration.
Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
d219b4b6 | 03-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: drop the ptp_type argument from felix_check_xtr_pkt()
The DSA ->port_rxtstamp() function is never called for PTP_CLASS_NONE:
dsa_skb_defer_rx_timestamp:
if (type == PTP_CLASS_NON
net: dsa: felix: drop the ptp_type argument from felix_check_xtr_pkt()
The DSA ->port_rxtstamp() function is never called for PTP_CLASS_NONE:
dsa_skb_defer_rx_timestamp:
if (type == PTP_CLASS_NONE) return false;
if (likely(ds->ops->port_rxtstamp)) return ds->ops->port_rxtstamp(ds, p->dp->index, skb, type);
So practically, the argument is unused, so remove it.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
0cc36980 | 02-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: stop clearing CPU flooding in felix_setup_tag_8021q
felix_migrate_flood_to_tag_8021q_port() takes care of clearing the flooding bits on the old CPU port (which was the CPU port modu
net: dsa: felix: stop clearing CPU flooding in felix_setup_tag_8021q
felix_migrate_flood_to_tag_8021q_port() takes care of clearing the flooding bits on the old CPU port (which was the CPU port module), so manually clearing this bit from PGID_UC, PGID_MC, PGID_BC is redundant.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
90897569 | 02-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: start off with flooding disabled on the CPU port
The driver probes with all ports as standalone, and it supports unicast filtering. So DSA will call port_fdb_add() for all necessary
net: dsa: felix: start off with flooding disabled on the CPU port
The driver probes with all ports as standalone, and it supports unicast filtering. So DSA will call port_fdb_add() for all necessary addresses on the current CPU port. We also handle migrations when the CPU port hardware resource changes (on tagging protocol change), so there should not be any unknown address that we have to receive while not promiscuous.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
b903a6bd | 02-Mar-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: felix: migrate flood settings from NPI to tag_8021q CPU port
When the tagging protocol changes from "ocelot" to "ocelot-8021q" or in reverse, the DSA promiscuity setting that was applied f
net: dsa: felix: migrate flood settings from NPI to tag_8021q CPU port
When the tagging protocol changes from "ocelot" to "ocelot-8021q" or in reverse, the DSA promiscuity setting that was applied for the old CPU port must be transferred to the new one.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
54c31984 | 25-Feb-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: mscc: ocelot: enforce FDB isolation when VLAN-unaware
Currently ocelot uses a pvid of 0 for standalone ports and ports under a VLAN-unaware bridge, and the pvid of the bridge for ports under a
net: mscc: ocelot: enforce FDB isolation when VLAN-unaware
Currently ocelot uses a pvid of 0 for standalone ports and ports under a VLAN-unaware bridge, and the pvid of the bridge for ports under a VLAN-aware bridge. Standalone ports do not perform learning, but packets received on them are still subject to FDB lookups. So if the MAC DA that a standalone port receives has been also learned on a VLAN-unaware bridge port, ocelot will attempt to forward to that port, even though it can't, so it will drop packets.
So there is a desire to avoid that, and isolate the FDBs of different bridges from one another, and from standalone ports.
The ocelot switch library has two distinct entry points: the felix DSA driver and the ocelot switchdev driver.
We need to code up a minimal bridge_num allocation in the ocelot switchdev driver too, this is copied from DSA with the exception that ocelot does not care about DSA trees, cross-chip bridging etc. So it only looks at its own ports that are already in the same bridge.
The ocelot switchdev driver uses the bridge_num it has allocated itself, while the felix driver uses the bridge_num allocated by DSA. They are both stored inside ocelot_port->bridge_num by the common function ocelot_port_bridge_join() which receives the bridge_num passed by value.
Once we have a bridge_num, we can only use it to enforce isolation between VLAN-unaware bridges. As far as I can see, ocelot does not have anything like a FID that further makes VLAN 100 from a port be different to VLAN 100 from another port with regard to FDB lookup. So we simply deny multiple VLAN-aware bridges.
For VLAN-unaware bridges, we crop the 4000-4095 VLAN region and we allocate a VLAN for each bridge_num. This will be used as the pvid of each port that is under that VLAN-unaware bridge, for as long as that bridge is VLAN-unaware.
VID 0 remains only for standalone ports. It is okay if all standalone ports use the same VID 0, since they perform no address learning, the FDB will contain no entry in VLAN 0, so the packets will always be flooded to the only possible destination, the CPU port.
The CPU port module doesn't need to be member of the VLANs to receive packets, but if we use the DSA tag_8021q protocol, those packets are part of the data plane as far as ocelot is concerned, so there it needs to. Just ensure that the DSA tag_8021q CPU port is a member of all reserved VLANs when it is created, and is removed when it is deleted.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
06b9cce4 | 25-Feb-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: pass extack to .port_bridge_join driver methods
As FDB isolation cannot be enforced between VLAN-aware bridges in lack of hardware assistance like extra FID bits, it seems plausible that m
net: dsa: pass extack to .port_bridge_join driver methods
As FDB isolation cannot be enforced between VLAN-aware bridges in lack of hardware assistance like extra FID bits, it seems plausible that many DSA switches cannot do it. Therefore, they need to reject configurations with multiple VLAN-aware bridges from the two code paths that can transition towards that state:
- joining a VLAN-aware bridge - toggling VLAN awareness on an existing bridge
The .port_vlan_filtering method already propagates the netlink extack to the driver, let's propagate it from .port_bridge_join too, to make sure that the driver can use the same function for both.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|
c2693363 | 25-Feb-2022 |
Vladimir Oltean <vladimir.oltean@nxp.com> |
net: dsa: request drivers to perform FDB isolation
For DSA, to encourage drivers to perform FDB isolation simply means to track which bridge does each FDB and MDB entry belong to. It then becomes th
net: dsa: request drivers to perform FDB isolation
For DSA, to encourage drivers to perform FDB isolation simply means to track which bridge does each FDB and MDB entry belong to. It then becomes the driver responsibility to use something that makes the FDB entry from one bridge not match the FDB lookup of ports from other bridges.
The top-level functions where the bridge is determined are: - dsa_port_fdb_{add,del} - dsa_port_host_fdb_{add,del} - dsa_port_mdb_{add,del} - dsa_port_host_mdb_{add,del}
aka the pre-crosschip-notifier functions.
Changing the API to pass a reference to a bridge is not superfluous, and looking at the passed bridge argument is not the same as having the driver look at dsa_to_port(ds, port)->bridge from the ->port_fdb_add() method.
DSA installs FDB and MDB entries on shared (CPU and DSA) ports as well, and those do not have any dp->bridge information to retrieve, because they are not in any bridge - they are merely the pipes that serve the user ports that are in one or multiple bridges.
The struct dsa_bridge associated with each FDB/MDB entry is encapsulated in a larger "struct dsa_db" database. Although only databases associated to bridges are notified for now, this API will be the starting point for implementing IFF_UNICAST_FLT in DSA. There, the idea is to install FDB entries on the CPU port which belong to the corresponding user port's port database. These are supposed to match only when the port is standalone.
It is better to introduce the API in its expected final form than to introduce it for bridges first, then to have to change drivers which may have made one or more assumptions.
Drivers can use the provided bridge.num, but they can also use a different numbering scheme that is more convenient.
DSA must perform refcounting on the CPU and DSA ports by also taking into account the bridge number. So if two bridges request the same local address, DSA must notify the driver twice, once for each bridge.
In fact, if the driver supports FDB isolation, DSA must perform refcounting per bridge, but if the driver doesn't, DSA must refcount host addresses across all bridges, otherwise it would be telling the driver to delete an FDB entry for a bridge and the driver would delete it for all bridges. So introduce a bool fdb_isolation in drivers which would make all bridge databases passed to the cross-chip notifier have the same number (0). This makes dsa_mac_addr_find() -> dsa_db_equal() say that all bridge databases are the same database - which is essentially the legacy behavior.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
show more ...
|