staging: dpaa2-switch: add fast-ageing on bridge leave
authorIoana Ciornei <ioana.ciornei@nxp.com>
Wed, 10 Mar 2021 12:14:50 +0000 (14:14 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 10 Mar 2021 21:30:36 +0000 (13:30 -0800)
Upon leaving a bridge, any MAC addresses learnt on the switch port prior
to this point have to be removed so that we preserve the bridging domain
configuration.

Restructure the dpaa2_switch_port_fdb_dump() function in order to have a
common dpaa2_switch_fdb_iterate() function between the FDB dump callback
and the fast age procedure. To accomplish this, add a new callback -
dpaa2_switch_fdb_cb_t - which will be called on each MAC addr and,
depending on the situation, will either dump the FDB entry into a
netlink message or will delete the address from the FDB table, in case
of the fast-age.

Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/staging/fsl-dpaa2/ethsw/ethsw.c
drivers/staging/fsl-dpaa2/ethsw/ethsw.h

index 8058bc3..5fa7e41 100644 (file)
@@ -729,21 +729,14 @@ static int dpaa2_switch_port_fdb_valid_entry(struct fdb_dump_entry *entry,
        return valid;
 }
 
-static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
-                                     struct net_device *net_dev,
-                                     struct net_device *filter_dev, int *idx)
+static int dpaa2_switch_fdb_iterate(struct ethsw_port_priv *port_priv,
+                                   dpaa2_switch_fdb_cb_t cb, void *data)
 {
-       struct ethsw_port_priv *port_priv = netdev_priv(net_dev);
+       struct net_device *net_dev = port_priv->netdev;
        struct ethsw_core *ethsw = port_priv->ethsw_data;
        struct device *dev = net_dev->dev.parent;
        struct fdb_dump_entry *fdb_entries;
        struct fdb_dump_entry fdb_entry;
-       struct ethsw_dump_ctx dump = {
-               .dev = net_dev,
-               .skb = skb,
-               .cb = cb,
-               .idx = *idx,
-       };
        dma_addr_t fdb_dump_iova;
        u16 num_fdb_entries;
        u32 fdb_dump_size;
@@ -778,17 +771,12 @@ static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callba
        for (i = 0; i < num_fdb_entries; i++) {
                fdb_entry = fdb_entries[i];
 
-               if (!dpaa2_switch_port_fdb_valid_entry(&fdb_entry, port_priv))
-                       continue;
-
-               err = dpaa2_switch_fdb_dump_nl(&fdb_entry, &dump);
+               err = cb(port_priv, &fdb_entry, data);
                if (err)
                        goto end;
        }
 
 end:
-       *idx = dump.idx;
-
        kfree(dma_mem);
 
        return 0;
@@ -800,6 +788,59 @@ err_map:
        return err;
 }
 
+static int dpaa2_switch_fdb_entry_dump(struct ethsw_port_priv *port_priv,
+                                      struct fdb_dump_entry *fdb_entry,
+                                      void *data)
+{
+       if (!dpaa2_switch_port_fdb_valid_entry(fdb_entry, port_priv))
+               return 0;
+
+       return dpaa2_switch_fdb_dump_nl(fdb_entry, data);
+}
+
+static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
+                                     struct net_device *net_dev,
+                                     struct net_device *filter_dev, int *idx)
+{
+       struct ethsw_port_priv *port_priv = netdev_priv(net_dev);
+       struct ethsw_dump_ctx dump = {
+               .dev = net_dev,
+               .skb = skb,
+               .cb = cb,
+               .idx = *idx,
+       };
+       int err;
+
+       err = dpaa2_switch_fdb_iterate(port_priv, dpaa2_switch_fdb_entry_dump, &dump);
+       *idx = dump.idx;
+
+       return err;
+}
+
+static int dpaa2_switch_fdb_entry_fast_age(struct ethsw_port_priv *port_priv,
+                                          struct fdb_dump_entry *fdb_entry,
+                                          void *data __always_unused)
+{
+       if (!dpaa2_switch_port_fdb_valid_entry(fdb_entry, port_priv))
+               return 0;
+
+       if (!(fdb_entry->type & DPSW_FDB_ENTRY_TYPE_DYNAMIC))
+               return 0;
+
+       if (fdb_entry->type & DPSW_FDB_ENTRY_TYPE_UNICAST)
+               dpaa2_switch_port_fdb_del_uc(port_priv, fdb_entry->mac_addr);
+       else
+               dpaa2_switch_port_fdb_del_mc(port_priv, fdb_entry->mac_addr);
+
+       return 0;
+}
+
+static void dpaa2_switch_port_fast_age(struct ethsw_port_priv *port_priv)
+{
+       dpaa2_switch_fdb_iterate(port_priv,
+                                dpaa2_switch_fdb_entry_fast_age, NULL);
+}
+
 static int dpaa2_switch_port_vlan_add(struct net_device *netdev, __be16 proto,
                                      u16 vid)
 {
@@ -1511,6 +1552,9 @@ static int dpaa2_switch_port_bridge_leave(struct net_device *netdev)
        struct ethsw_core *ethsw = port_priv->ethsw_data;
        int err;
 
+       /* First of all, fast age any learn FDB addresses on this switch port */
+       dpaa2_switch_port_fast_age(port_priv);
+
        /* Clear all RX VLANs installed through vlan_vid_add() either as VLAN
         * upper devices or otherwise from the FDB table that we are about to
         * leave
index ac9335c..9335630 100644 (file)
@@ -172,4 +172,7 @@ int dpaa2_switch_port_vlans_add(struct net_device *netdev,
 int dpaa2_switch_port_vlans_del(struct net_device *netdev,
                                const struct switchdev_obj_port_vlan *vlan);
 
+typedef int dpaa2_switch_fdb_cb_t(struct ethsw_port_priv *port_priv,
+                                 struct fdb_dump_entry *fdb_entry,
+                                 void *data);
 #endif /* __ETHSW_H */