Commit 685b4801 authored by Ioana Ciornei's avatar Ioana Ciornei Committed by David S. Miller
Browse files

staging: dpaa2-switch: add fast-ageing on bridge leave



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: default avatarIoana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d671407f
Loading
Loading
Loading
Loading
+60 −16
Original line number Diff line number Diff line
@@ -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 @@ static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callba
	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
+3 −0
Original line number Diff line number Diff line
@@ -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 */