net: dsa: sja1105: enforce FDB isolation
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. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
06b9cce426
commit
219827ef92
@ -393,10 +393,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.
|
||||
@ -1808,6 +1806,19 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
|
||||
if (!vid) {
|
||||
switch (db.type) {
|
||||
case DSA_DB_PORT:
|
||||
vid = dsa_tag_8021q_standalone_vid(db.dp);
|
||||
break;
|
||||
case DSA_DB_BRIDGE:
|
||||
vid = dsa_tag_8021q_bridge_vid(db.bridge.num);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return priv->info->fdb_add_cmd(ds, port, addr, vid);
|
||||
}
|
||||
|
||||
@ -1817,13 +1828,25 @@ static int sja1105_fdb_del(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
|
||||
if (!vid) {
|
||||
switch (db.type) {
|
||||
case DSA_DB_PORT:
|
||||
vid = dsa_tag_8021q_standalone_vid(db.dp);
|
||||
break;
|
||||
case DSA_DB_BRIDGE:
|
||||
vid = dsa_tag_8021q_bridge_vid(db.bridge.num);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return priv->info->fdb_del_cmd(ds, port, addr, vid);
|
||||
}
|
||||
|
||||
static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
|
||||
dsa_fdb_dump_cb_t *cb, void *data)
|
||||
{
|
||||
struct dsa_port *dp = dsa_to_port(ds, port);
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct device *dev = ds->dev;
|
||||
int i;
|
||||
@ -1860,7 +1883,7 @@ 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 (!dsa_port_is_vlan_filtering(dp))
|
||||
if (vid_is_dsa_8021q(l2_lookup.vlanid))
|
||||
l2_lookup.vlanid = 0;
|
||||
rc = cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
|
||||
if (rc)
|
||||
@ -2354,7 +2377,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;
|
||||
@ -2392,28 +2414,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 = !enabled;
|
||||
|
||||
for (port = 0; port < ds->num_ports; port++) {
|
||||
if (dsa_is_unused_port(ds, port))
|
||||
continue;
|
||||
@ -3099,6 +3099,7 @@ static int sja1105_setup(struct dsa_switch *ds)
|
||||
*/
|
||||
ds->vlan_filtering_is_global = true;
|
||||
ds->untag_bridge_pvid = true;
|
||||
ds->fdb_isolation = true;
|
||||
/* tag_8021q has 3 bits for the VBID, and the value 0 is reserved */
|
||||
ds->max_num_bridges = 7;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user