Skip to content

Commit 045c45d

Browse files
vladimirolteandavem330
authored andcommitted
net: dsa: centralize fast ageing when address learning is turned off
Currently DSA leaves it down to device drivers to fast age the FDB on a port when address learning is disabled on it. There are 2 reasons for doing that in the first place: - when address learning is disabled by user space, through IFLA_BRPORT_LEARNING or the brport_attr_learning sysfs, what user space typically wants to achieve is to operate in a mode with no dynamic FDB entry on that port. But if the port is already up, some addresses might have been already learned on it, and it seems silly to wait for 5 minutes for them to expire until something useful can be done. - when a port leaves a bridge and becomes standalone, DSA turns off address learning on it. This also has the nice side effect of flushing the dynamically learned bridge FDB entries on it, which is a good idea because standalone ports should not have bridge FDB entries on them. We let drivers manage fast ageing under this condition because if DSA were to do it, it would need to track each port's learning state, and act upon the transition, which it currently doesn't. But there are 2 reasons why doing it is better after all: - drivers might get it wrong and not do it (see b53_port_set_learning) - we would like to flush the dynamic entries from the software bridge too, and letting drivers do that would be another pain point So track the port learning state and trigger a fast age process automatically within DSA. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 64ec13e commit 045c45d

File tree

4 files changed

+33
-12
lines changed

4 files changed

+33
-12
lines changed

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5797,7 +5797,6 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
57975797
struct netlink_ext_ack *extack)
57985798
{
57995799
struct mv88e6xxx_chip *chip = ds->priv;
5800-
bool do_fast_age = false;
58015800
int err = -EOPNOTSUPP;
58025801

58035802
mv88e6xxx_reg_lock(chip);
@@ -5809,9 +5808,6 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
58095808
err = mv88e6xxx_port_set_assoc_vector(chip, port, pav);
58105809
if (err)
58115810
goto out;
5812-
5813-
if (!learning)
5814-
do_fast_age = true;
58155811
}
58165812

58175813
if (flags.mask & BR_FLOOD) {
@@ -5843,9 +5839,6 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
58435839
out:
58445840
mv88e6xxx_reg_unlock(chip);
58455841

5846-
if (do_fast_age)
5847-
mv88e6xxx_port_fast_age(ds, port);
5848-
58495842
return err;
58505843
}
58515844

include/net/dsa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ struct dsa_port {
254254
struct device_node *dn;
255255
unsigned int ageing_time;
256256
bool vlan_filtering;
257+
bool learning;
257258
u8 stp_state;
258259
struct net_device *bridge_dev;
259260
int bridge_num;

net/dsa/dsa_priv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ int dsa_port_host_mdb_del(const struct dsa_port *dp,
241241
int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
242242
struct switchdev_brport_flags flags,
243243
struct netlink_ext_ack *extack);
244-
int dsa_port_bridge_flags(const struct dsa_port *dp,
244+
int dsa_port_bridge_flags(struct dsa_port *dp,
245245
struct switchdev_brport_flags flags,
246246
struct netlink_ext_ack *extack);
247247
int dsa_port_vlan_add(struct dsa_port *dp,

net/dsa/port.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v)
3030
return dsa_tree_notify(dp->ds->dst, e, v);
3131
}
3232

33+
static void dsa_port_fast_age(const struct dsa_port *dp)
34+
{
35+
struct dsa_switch *ds = dp->ds;
36+
37+
if (!ds->ops->port_fast_age)
38+
return;
39+
40+
ds->ops->port_fast_age(ds, dp->index);
41+
}
42+
3343
int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age)
3444
{
3545
struct dsa_switch *ds = dp->ds;
@@ -40,7 +50,7 @@ int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age)
4050

4151
ds->ops->port_stp_state_set(ds, port, state);
4252

43-
if (do_fast_age && ds->ops->port_fast_age) {
53+
if (do_fast_age) {
4454
/* Fast age FDB entries or flush appropriate forwarding database
4555
* for the given port, if we are moving it from Learning or
4656
* Forwarding state, to Disabled or Blocking or Listening state.
@@ -54,7 +64,7 @@ int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age)
5464
(state == BR_STATE_DISABLED ||
5565
state == BR_STATE_BLOCKING ||
5666
state == BR_STATE_LISTENING))
57-
ds->ops->port_fast_age(ds, port);
67+
dsa_port_fast_age(dp);
5868
}
5969

6070
dp->stp_state = state;
@@ -633,16 +643,33 @@ int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
633643
return ds->ops->port_pre_bridge_flags(ds, dp->index, flags, extack);
634644
}
635645

636-
int dsa_port_bridge_flags(const struct dsa_port *dp,
646+
int dsa_port_bridge_flags(struct dsa_port *dp,
637647
struct switchdev_brport_flags flags,
638648
struct netlink_ext_ack *extack)
639649
{
640650
struct dsa_switch *ds = dp->ds;
651+
int err;
641652

642653
if (!ds->ops->port_bridge_flags)
643654
return -EOPNOTSUPP;
644655

645-
return ds->ops->port_bridge_flags(ds, dp->index, flags, extack);
656+
err = ds->ops->port_bridge_flags(ds, dp->index, flags, extack);
657+
if (err)
658+
return err;
659+
660+
if (flags.mask & BR_LEARNING) {
661+
bool learning = flags.val & BR_LEARNING;
662+
663+
if (learning == dp->learning)
664+
return 0;
665+
666+
if (dp->learning && !learning)
667+
dsa_port_fast_age(dp);
668+
669+
dp->learning = learning;
670+
}
671+
672+
return 0;
646673
}
647674

648675
int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,

0 commit comments

Comments
 (0)