Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: delete dsa_legacy_fdb_add and dsa_legacy_fdb_del

We want to add reference counting for FDB entries in cross-chip
topologies, and in order for that to have any chance of working and not
be unbalanced (leading to entries which are never deleted), we need to
ensure that higher layers are sane, because if they aren't, it's garbage
in, garbage out.

For example, if we add a bridge FDB entry twice, the bridge properly
errors out:

$ bridge fdb add dev swp0 00:01:02:03:04:07 master static
$ bridge fdb add dev swp0 00:01:02:03:04:07 master static
RTNETLINK answers: File exists

However, the same thing cannot be said about the bridge bypass
operations:

$ bridge fdb add dev swp0 00:01:02:03:04:07
$ bridge fdb add dev swp0 00:01:02:03:04:07
$ bridge fdb add dev swp0 00:01:02:03:04:07
$ bridge fdb add dev swp0 00:01:02:03:04:07
$ echo $?
0

But one 'bridge fdb del' is enough to remove the entry, no matter how
many times it was added.

The bridge bypass operations are impossible to maintain in these
circumstances and lack of support for reference counting the cross-chip
notifiers is holding us back from making further progress, so just drop
support for them. The only way left for users to install static bridge
FDB entries is the proper one, using the "master static" flags.

With this change, rtnl_fdb_add() falls back to calling
ndo_dflt_fdb_add() which uses the duplicate-exclusive variant of
dev_uc_add(): dev_uc_add_excl(). Because DSA does not (yet) declare
IFF_UNICAST_FLT, this results in us going to promiscuous mode:

$ bridge fdb add dev swp0 00:01:02:03:04:05
[ 28.206743] device swp0 entered promiscuous mode
$ bridge fdb add dev swp0 00:01:02:03:04:05
RTNETLINK answers: File exists

So even if it does not completely fail, there is at least some indication
that it is behaving differently from before, and closer to user space
expectations, I would argue (the lack of a "local|static" specifier
defaults to "local", or "host-only", so dev_uc_add() is a reasonable
default implementation). If the generic implementation of .ndo_fdb_add
provided by Vlad Yasevich is a proof of anything, it only proves that
the implementation provided by DSA was always wrong, by not looking at
"ndm->ndm_state & NUD_NOARP" (the "static" flag which means that the FDB
entry points outwards) and "ndm->ndm_state & NUD_PERMANENT" (the "local"
flag which means that the FDB entry points towards the host). It all
used to mean the same thing to DSA.

Update the documentation so that the users are not confused about what's
going on.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vladimir Oltean and committed by
David S. Miller
b117e1e8 f851a721

+68 -23
+68
Documentation/networking/dsa/configuration.rst
··· 292 292 293 293 # bring up the bridge devices 294 294 ip link set br0 up 295 + 296 + Forwarding database (FDB) management 297 + ------------------------------------ 298 + 299 + The existing DSA switches do not have the necessary hardware support to keep 300 + the software FDB of the bridge in sync with the hardware tables, so the two 301 + tables are managed separately (``bridge fdb show`` queries both, and depending 302 + on whether the ``self`` or ``master`` flags are being used, a ``bridge fdb 303 + add`` or ``bridge fdb del`` command acts upon entries from one or both tables). 304 + 305 + Up until kernel v4.14, DSA only supported user space management of bridge FDB 306 + entries using the bridge bypass operations (which do not update the software 307 + FDB, just the hardware one) using the ``self`` flag (which is optional and can 308 + be omitted). 309 + 310 + .. code-block:: sh 311 + 312 + bridge fdb add dev swp0 00:01:02:03:04:05 self static 313 + # or shorthand 314 + bridge fdb add dev swp0 00:01:02:03:04:05 static 315 + 316 + Due to a bug, the bridge bypass FDB implementation provided by DSA did not 317 + distinguish between ``static`` and ``local`` FDB entries (``static`` are meant 318 + to be forwarded, while ``local`` are meant to be locally terminated, i.e. sent 319 + to the host port). Instead, all FDB entries with the ``self`` flag (implicit or 320 + explicit) are treated by DSA as ``static`` even if they are ``local``. 321 + 322 + .. code-block:: sh 323 + 324 + # This command: 325 + bridge fdb add dev swp0 00:01:02:03:04:05 static 326 + # behaves the same for DSA as this command: 327 + bridge fdb add dev swp0 00:01:02:03:04:05 local 328 + # or shorthand, because the 'local' flag is implicit if 'static' is not 329 + # specified, it also behaves the same as: 330 + bridge fdb add dev swp0 00:01:02:03:04:05 331 + 332 + The last command is an incorrect way of adding a static bridge FDB entry to a 333 + DSA switch using the bridge bypass operations, and works by mistake. Other 334 + drivers will treat an FDB entry added by the same command as ``local`` and as 335 + such, will not forward it, as opposed to DSA. 336 + 337 + Between kernel v4.14 and v5.14, DSA has supported in parallel two modes of 338 + adding a bridge FDB entry to the switch: the bridge bypass discussed above, as 339 + well as a new mode using the ``master`` flag which installs FDB entries in the 340 + software bridge too. 341 + 342 + .. code-block:: sh 343 + 344 + bridge fdb add dev swp0 00:01:02:03:04:05 master static 345 + 346 + Since kernel v5.14, DSA has gained stronger integration with the bridge's 347 + software FDB, and the support for its bridge bypass FDB implementation (using 348 + the ``self`` flag) has been removed. This results in the following changes: 349 + 350 + .. code-block:: sh 351 + 352 + # This is the only valid way of adding an FDB entry that is supported, 353 + # compatible with v4.14 kernels and later: 354 + bridge fdb add dev swp0 00:01:02:03:04:05 master static 355 + # This command is no longer buggy and the entry is properly treated as 356 + # 'local' instead of being forwarded: 357 + bridge fdb add dev swp0 00:01:02:03:04:05 358 + # This command no longer installs a static FDB entry to hardware: 359 + bridge fdb add dev swp0 00:01:02:03:04:05 static 360 + 361 + Script writers are therefore encouraged to use the ``master static`` set of 362 + flags when working with bridge FDB entries on DSA switch interfaces.
-23
net/dsa/slave.c
··· 1651 1651 .self_test = dsa_slave_net_selftest, 1652 1652 }; 1653 1653 1654 - /* legacy way, bypassing the bridge *****************************************/ 1655 - static int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 1656 - struct net_device *dev, 1657 - const unsigned char *addr, u16 vid, 1658 - u16 flags, 1659 - struct netlink_ext_ack *extack) 1660 - { 1661 - struct dsa_port *dp = dsa_slave_to_port(dev); 1662 - 1663 - return dsa_port_fdb_add(dp, addr, vid); 1664 - } 1665 - 1666 - static int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 1667 - struct net_device *dev, 1668 - const unsigned char *addr, u16 vid) 1669 - { 1670 - struct dsa_port *dp = dsa_slave_to_port(dev); 1671 - 1672 - return dsa_port_fdb_del(dp, addr, vid); 1673 - } 1674 - 1675 1654 static struct devlink_port *dsa_slave_get_devlink_port(struct net_device *dev) 1676 1655 { 1677 1656 struct dsa_port *dp = dsa_slave_to_port(dev); ··· 1692 1713 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 1693 1714 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 1694 1715 .ndo_set_mac_address = dsa_slave_set_mac_address, 1695 - .ndo_fdb_add = dsa_legacy_fdb_add, 1696 - .ndo_fdb_del = dsa_legacy_fdb_del, 1697 1716 .ndo_fdb_dump = dsa_slave_fdb_dump, 1698 1717 .ndo_do_ioctl = dsa_slave_ioctl, 1699 1718 .ndo_get_iflink = dsa_slave_get_iflink,