[RFC PATCH net-next 16/20] net: dsa: sja1105: enforce FDB isolation
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Date: 2021-08-18 12:04:46
Subsystem:
networking drivers, networking [dsa], networking [general], the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Vladimir Oltean, Linus Torvalds
For sja1105, to enforce FDB isolation simply means to turn on Independent VLAN Learning unconditionally, and to remap VLAN-unaware FDB and MDB entries towards the private VLAN allocated by tag_8021q for each bridge. Standalone ports each have their own standalone tag_8021q VLAN. No learning happens in that VLAN due to: - learning being disabled on standalone user ports - learning being disabled on the CPU port (we use assisted_learning_on_cpu_port which only installs bridge FDBs) VLAN-aware ports learn FDB entries with the bridge VLANs. VLAN-unaware bridge ports learn with the tag_8021q VLAN for bridging. Since sja1105 is the first driver to use the dsa_bridge_num_find() helper, we need to export it. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- drivers/net/dsa/sja1105/sja1105_main.c | 38 +++++++------------------- include/net/dsa.h | 1 + net/dsa/dsa2.c | 3 +- 3 files changed, 13 insertions(+), 29 deletions(-)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 667e698b5ae8..bc0d89b96353 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c@@ -361,10 +361,8 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) .start_dynspc = 0, /* 2^8 + 2^5 + 2^3 + 2^2 + 2^1 + 1 in Koopman notation */ .poly = 0x97, - /* This selects between Independent VLAN Learning (IVL) and - * Shared VLAN Learning (SVL) - */ - .shared_learn = true, + /* Always use Independent VLAN Learning (IVL) */ + .shared_learn = false, /* Don't discard management traffic based on ENFPORT - * we don't perform SMAC port enforcement anyway, so * what we are setting here doesn't matter.
@@ -1736,6 +1734,9 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port, { struct sja1105_private *priv = ds->priv; + if (!vid) + vid = dsa_tag_8021q_bridge_vid(dsa_bridge_num_find(br)); + return priv->info->fdb_add_cmd(ds, port, addr, vid); }
@@ -1745,6 +1746,9 @@ static int sja1105_fdb_del(struct dsa_switch *ds, int port, { struct sja1105_private *priv = ds->priv; + if (!vid) + vid = dsa_tag_8021q_bridge_vid(dsa_bridge_num_find(br)); + return priv->info->fdb_del_cmd(ds, port, addr, vid); }
@@ -1787,8 +1791,9 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port, u64_to_ether_addr(l2_lookup.macaddr, macaddr); /* We need to hide the dsa_8021q VLANs from the user. */ - if (!priv->vlan_aware) + if (vid_is_dsa_8021q(l2_lookup.vlanid)) l2_lookup.vlanid = 0; + rc = cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data); if (rc) return rc;
@@ -2269,7 +2274,6 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, struct netlink_ext_ack *extack) { - struct sja1105_l2_lookup_params_entry *l2_lookup_params; struct sja1105_general_params_entry *general_params; struct sja1105_private *priv = ds->priv; struct sja1105_table *table;
@@ -2321,28 +2325,6 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, general_params->incl_srcpt1 = enabled; general_params->incl_srcpt0 = enabled; - /* VLAN filtering => independent VLAN learning. - * No VLAN filtering (or best effort) => shared VLAN learning. - * - * In shared VLAN learning mode, untagged traffic still gets - * pvid-tagged, and the FDB table gets populated with entries - * containing the "real" (pvid or from VLAN tag) VLAN ID. - * However the switch performs a masked L2 lookup in the FDB, - * effectively only looking up a frame's DMAC (and not VID) for the - * forwarding decision. - * - * This is extremely convenient for us, because in modes with - * vlan_filtering=0, dsa_8021q actually installs unique pvid's into - * each front panel port. This is good for identification but breaks - * learning badly - the VID of the learnt FDB entry is unique, aka - * no frames coming from any other port are going to have it. So - * for forwarding purposes, this is as though learning was broken - * (all frames get flooded). - */ - table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS]; - l2_lookup_params = table->entries; - l2_lookup_params->shared_learn = !priv->vlan_aware; - for (port = 0; port < ds->num_ports; port++) { if (dsa_is_unused_port(ds, port)) continue;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 103b738bd773..5bf8d3a85106 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h@@ -1046,6 +1046,7 @@ static inline int dsa_ndo_eth_ioctl(struct net_device *dev, struct ifreq *ifr, void dsa_unregister_switch(struct dsa_switch *ds); int dsa_register_switch(struct dsa_switch *ds); struct dsa_switch *dsa_switch_find(int tree_index, int sw_index); +int dsa_bridge_num_find(const struct net_device *bridge_dev); #ifdef CONFIG_PM_SLEEP int dsa_switch_suspend(struct dsa_switch *ds); int dsa_switch_resume(struct dsa_switch *ds);
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 1b2b25d7bd02..0d07a44eeecf 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c@@ -129,7 +129,7 @@ void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag) } } -static int dsa_bridge_num_find(const struct net_device *bridge_dev) +int dsa_bridge_num_find(const struct net_device *bridge_dev) { struct dsa_switch_tree *dst; struct dsa_port *dp;
@@ -147,6 +147,7 @@ static int dsa_bridge_num_find(const struct net_device *bridge_dev) return -1; } +EXPORT_SYMBOL_GPL(dsa_bridge_num_find); int dsa_bridge_num_get(const struct net_device *bridge_dev, int max) {
--
2.25.1