Message ID | 20210618183017.3340769-5-olteanv@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | Improvement for DSA cross-chip setups | expand |
On 6/18/2021 11:30 AM, Vladimir Oltean wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > If we have a cross-chip topology like this: > > sw0p0 sw0p1 sw0p2 sw0p3 sw0p4 > [ cpu ] [ user ] [ user ] [ dsa ] [ user ] > | > +---------+ > | > sw1p0 sw1p1 sw1p2 sw1p3 sw1p4 > [ user ] [ user ] [ user ] [ dsa ] [ dsa ] > > and we issue the following commands: > > 1. ip link set sw0p1 mtu 1700 > 2. ip link set sw1p1 mtu 1600 > > we notice the following happening: > > Command 1. emits a non-targeted MTU notifier for the CPU port (sw0p0) > with the largest_mtu calculated across switch 0, of 1700. This matches > sw0p0, sw0p3 and sw1p4 (all CPU ports and DSA links). > Then, it emits a targeted MTU notifier for the user port (sw0p1), again > with MTU 1700 (this doesn't matter). > > Command 2. emits a non-targeted MTU notifier for the CPU port (sw0p0) > with the largest_mtu calculated across switch 1, of 1600. This matches > the same group of ports as above, and decreases the MTU for the CPU port > and the DSA links from 1700 to 1600. > > As a result, the sw0p1 user port can no longer communicate with its CPU > port at MTU 1700. > > To address this, we should calculate the largest_mtu across all switches > that may share a CPU port, and only emit MTU notifiers with that value. > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> -- Florian
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 798944aa847a..ac2ca5f75af3 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1528,6 +1528,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) struct dsa_port *dp = dsa_slave_to_port(dev); struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->dp->ds; + struct dsa_port *dp_iter; struct dsa_port *cpu_dp; int port = p->dp->index; int largest_mtu = 0; @@ -1535,31 +1536,31 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) int old_master_mtu; int mtu_limit; int cpu_mtu; - int err, i; + int err; if (!ds->ops->port_change_mtu) return -EOPNOTSUPP; - for (i = 0; i < ds->num_ports; i++) { + list_for_each_entry(dp_iter, &ds->dst->ports, list) { int slave_mtu; - if (!dsa_is_user_port(ds, i)) + if (!dsa_port_is_user(dp_iter)) continue; /* During probe, this function will be called for each slave * device, while not all of them have been allocated. That's * ok, it doesn't change what the maximum is, so ignore it. */ - if (!dsa_to_port(ds, i)->slave) + if (!dp_iter->slave) continue; /* Pretend that we already applied the setting, which we * actually haven't (still haven't done all integrity checks) */ - if (i == port) + if (dp_iter == dp) slave_mtu = new_mtu; else - slave_mtu = dsa_to_port(ds, i)->slave->mtu; + slave_mtu = dp_iter->slave->mtu; if (largest_mtu < slave_mtu) largest_mtu = slave_mtu;