1. 29 Jul, 2021 35 commits
  2. 28 Jul, 2021 5 commits
    • Hu Haowen's avatar
      Documentation: networking: add ioam6-sysctl into index · 883d71a5
      Hu Haowen authored
      Append ioam6-sysctl to toctree in order to get rid of building warnings.
      Signed-off-by: default avatarHu Haowen <src.res@email.cn>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      883d71a5
    • Vladimir Oltean's avatar
      net: dsa: sja1105: be stateless when installing FDB entries · b11f0a4c
      Vladimir Oltean authored
      Currently there are issues when adding a bridge FDB entry as VLAN-aware
      and deleting it as VLAN-unaware, or vice versa.
      
      However this is an unneeded complication, since the bridge always
      installs its default FDB entries in VLAN 0 to match on VLAN-unaware
      ports, and in the default_pvid (VLAN 1) to match on VLAN-aware ports.
      So instead of trying to outsmart the bridge, just install all entries it
      gives us, and they will start matching packets when the vlan_filtering
      mode changes.
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      b11f0a4c
    • David S. Miller's avatar
      Merge branch 'switchdev-notifiers' · b0fdb999
      David S. Miller authored
      Vladimir Oltean says:
      
      ====================
      Plug the last 2 holes in the switchdev notifiers for local FDB entries
      
      The work for trapping local FDB entries to the CPU in switchdev/DSA
      started with the "RX filtering in DSA" series:
      https://patchwork.kernel.org/project/netdevbpf/cover/20210629140658.2510288-1-olteanv@gmail.com/
      and was continued with further improvements such as "Fan out FDB entries
      pointing towards the bridge to all switchdev member ports":
      https://patchwork.kernel.org/project/netdevbpf/cover/20210719135140.278938-1-vladimir.oltean@nxp.com/
      https://patchwork.kernel.org/project/netdevbpf/cover/20210720173557.999534-1-vladimir.oltean@nxp.com/
      
      There are only 2 more issues left to be addressed (famous last words),
      and these are:
      - dynamically learned FDB entries towards interfaces foreign to DSA need
        to be replayed too
      - adding/deleting a VLAN on a port causes the local FDB entries in that
        VLAN to be prematurely deleted
      
      This patch series addresses both, and patch 2 depends on 1 to work properly.
      ====================
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      b0fdb999
    • Vladimir Oltean's avatar
      net: bridge: switchdev: treat local FDBs the same as entries towards the bridge · 52e4bec1
      Vladimir Oltean authored
      Currently the following script:
      
      1. ip link add br0 type bridge vlan_filtering 1 && ip link set br0 up
      2. ip link set swp2 up && ip link set swp2 master br0
      3. ip link set swp3 up && ip link set swp3 master br0
      4. ip link set swp4 up && ip link set swp4 master br0
      5. bridge vlan del dev swp2 vid 1
      6. bridge vlan del dev swp3 vid 1
      7. ip link set swp4 nomaster
      8. ip link set swp3 nomaster
      
      produces the following output:
      
      [  641.010738] sja1105 spi0.1: port 2 failed to delete 00:1f:7b:63:02:48 vid 1 from fdb: -2
      
      [ swp2, swp3 and br0 all have the same MAC address, the one listed above ]
      
      In short, this happens because the number of FDB entry additions
      notified to switchdev is unbalanced with the number of deletions.
      
      At step 1, the bridge has a random MAC address. At step 2, the
      br_fdb_replay of swp2 receives this initial MAC address. Then the bridge
      inherits the MAC address of swp2 via br_fdb_change_mac_address(), and it
      notifies switchdev (only swp2 at this point) of the deletion of the
      random MAC address and the addition of 00:1f:7b:63:02:48 as a local FDB
      entry with fdb->dst == swp2, in VLANs 0 and the default_pvid (1).
      
      During step 7:
      
      del_nbp
      -> br_fdb_delete_by_port(br, p, vid=0, do_all=1);
         -> fdb_delete_local(br, p, f);
      
      br_fdb_delete_by_port() deletes all entries towards the ports,
      regardless of vid, because do_all is 1.
      
      fdb_delete_local() has logic to migrate local FDB entries deleted from
      one port to another port which shares the same MAC address and is in the
      same VLAN, or to the bridge device itself. This migration happens
      without notifying switchdev of the deletion on the old port and the
      addition on the new one, just fdb->dst is changed and the added_by_user
      flag is cleared.
      
      In the example above, the del_nbp(swp4) causes the
      "addr 00:1f:7b:63:02:48 vid 1" local FDB entry with fdb->dst == swp4
      that existed up until then to be migrated directly towards the bridge
      (fdb->dst == NULL). This is because it cannot be migrated to any of the
      other ports (swp2 and swp3 are not in VLAN 1).
      
      After the migration to br0 takes place, swp4 requests a deletion replay
      of all FDB entries. Since the "addr 00:1f:7b:63:02:48 vid 1" entry now
      point towards the bridge, a deletion of it is replayed. There was just
      a prior addition of this address, so the switchdev driver deletes this
      entry.
      
      Then, the del_nbp(swp3) at step 8 triggers another br_fdb_replay, and
      switchdev is notified again to delete "addr 00:1f:7b:63:02:48 vid 1".
      But it can't because it no longer has it, so it returns -ENOENT.
      
      There are other possibilities to trigger this issue, but this is by far
      the simplest to explain.
      
      To fix this, we must avoid the situation where the addition of an FDB
      entry is notified to switchdev as a local entry on a port, and the
      deletion is notified on the bridge itself.
      
      Considering that the 2 types of FDB entries are completely equivalent
      and we cannot have the same MAC address as a local entry on 2 bridge
      ports, or on a bridge port and pointing towards the bridge at the same
      time, it makes sense to hide away from switchdev completely the fact
      that a local FDB entry is associated with a given bridge port at all.
      Just say that it points towards the bridge, it should make no difference
      whatsoever to the switchdev driver and should even lead to a simpler
      overall implementation, will less cases to handle.
      
      This also avoids any modification at all to the core bridge driver, just
      what is reported to switchdev changes. With the local/permanent entries
      on bridge ports being already reported to user space, it is hard to
      believe that the bridge behavior can change in any backwards-incompatible
      way such as making all local FDB entries point towards the bridge.
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      52e4bec1
    • Vladimir Oltean's avatar
      net: bridge: switchdev: replay the entire FDB for each port · b4454bc6
      Vladimir Oltean authored
      Currently when a switchdev port joins a bridge, we replay all FDB
      entries pointing towards that port or towards the bridge.
      
      However, this is insufficient in certain situations:
      
      (a) DSA, through its assisted_learning_on_cpu_port logic, snoops
          dynamically learned FDB entries on foreign interfaces.
          These are FDB entries that are pointing neither towards the newly
          joined switchdev port, nor towards the bridge. So these addresses
          would be missed when joining a bridge where a foreign interface has
          already learned some addresses, and they would also linger on if the
          DSA port leaves the bridge before the foreign interface forgets them.
          None of this happens if we replay the entire FDB when the port joins.
      
      (b) There is a desire to treat local FDB entries on a port (i.e. the
          port's termination MAC address) identically to FDB entries pointing
          towards the bridge itself. More details on the reason behind this in
          the next patch. The point is that this cannot be done given the
          current structure of br_fdb_replay() in this situation:
            ip link set swp0 master br0  # br0 inherits its MAC address from swp0
            ip link set swp1 master br0
          What is desirable is that when swp1 joins the bridge, br_fdb_replay()
          also notifies swp1 of br0's MAC address, but this won't in fact
          happen because the MAC address of br0 does not have fdb->dst == NULL
          (it doesn't point towards the bridge), but it has fdb->dst == swp0.
          So our current logic makes it impossible for that address to be
          replayed. But if we dump the entire FDB instead of just the entries
          with fdb->dst == swp1 and fdb->dst == NULL, then the inherited MAC
          address of br0 will be replayed too, which is what we need.
      
      A natural question arises: say there is an FDB entry to be replayed,
      like a MAC address dynamically learned on a foreign interface that
      belongs to a bridge where no switchdev port has joined yet. If 10
      switchdev ports belonging to the same driver join this bridge, one by
      one, won't every port get notified 10 times of the foreign FDB entry,
      amounting to a total of 100 notifications for this FDB entry in the
      switchdev driver?
      
      Well, yes, but this is where the "void *ctx" argument for br_fdb_replay
      is useful: every port of the switchdev driver is notified whenever any
      other port requests an FDB replay, but because the replay was initiated
      by a different port, its context is different from the initiating port's
      context, so it ignores those replays.
      
      So the foreign FDB entry will be installed only 10 times, once per port.
      This is done so that the following 4 code paths are always well balanced:
      (a) addition of foreign FDB entry is replayed when port joins bridge
      (b) deletion of foreign FDB entry is replayed when port leaves bridge
      (c) addition of foreign FDB entry is notified to all ports currently in bridge
      (c) deletion of foreign FDB entry is notified to all ports currently in bridge
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      b4454bc6