[RFC PATCH net-next 04/10] net: dsa: introduce and use robust form of dsa_port_notify()
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Date: 2022-08-18 15:50:51
Subsystem:
networking [dsa], networking [general], the rest · Maintainers:
Andrew Lunn, Vladimir Oltean, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Introduce dsa_port_notify_robust(), which uses dsa_tree_notify_robust(), and convert as many call paths to use it. Some notable exceptions are DSA_NOTIFIER_LAG_CHANGE, for which it isn't clear how to restore the state (or why this is allowed to return an error for that matter), and DSA_NOTIFIER_MTU (which we'll convert separately to the robust form). Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- net/dsa/port.c | 51 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 11 deletions(-)
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 6aa6402d3ed9..2fec3df65643 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c@@ -30,6 +30,24 @@ static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v) return dsa_tree_notify(dp->ds->dst, e, v); } +/** + * dsa_port_notify_robust - Notify fabric of changes to port, with rollback + * @dp: port on which change occurred + * @e: event, must be of type DSA_NOTIFIER_* + * @v: event-specific value. + * @e_rollback: event, must be of type DSA_NOTIFIER_* + * @v_rollback: event-specific value. + * + * Like dsa_port_notify(), except makes sure that switches are restored to the + * previous state in case the notifier call chain fails mid way. + */ +static int dsa_port_notify_robust(const struct dsa_port *dp, unsigned long e, + void *v, unsigned long e_rollback, + void *v_rollback) +{ + return dsa_tree_notify_robust(dp->ds->dst, e, v, e_rollback, v_rollback); +} + static void dsa_port_notify_bridge_fdb_flush(const struct dsa_port *dp, u16 vid) { struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
@@ -641,7 +659,8 @@ int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev, goto err_lag_create; info.lag = *dp->lag; - err = dsa_port_notify(dp, DSA_NOTIFIER_LAG_JOIN, &info); + err = dsa_port_notify_robust(dp, DSA_NOTIFIER_LAG_JOIN, &info, + DSA_NOTIFIER_LAG_LEAVE, &info); if (err) goto err_lag_join;
@@ -854,12 +873,14 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock) { unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock); unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); - struct dsa_notifier_ageing_time_info info; + struct dsa_notifier_ageing_time_info info, old_info; int err; info.ageing_time = ageing_time; + old_info.ageing_time = dp->ageing_time; - err = dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info); + err = dsa_port_notify_robust(dp, DSA_NOTIFIER_AGEING_TIME, &info, + DSA_NOTIFIER_AGEING_TIME, &old_info); if (err) return err;
@@ -971,7 +992,8 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, if (!dp->ds->fdb_isolation) info.db.bridge.num = 0; - return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_FDB_ADD, &info, + DSA_NOTIFIER_FDB_DEL, &info); } int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
@@ -1007,7 +1029,8 @@ static int dsa_port_host_fdb_add(struct dsa_port *dp, if (!dp->ds->fdb_isolation) info.db.bridge.num = 0; - return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_HOST_FDB_ADD, &info, + DSA_NOTIFIER_HOST_FDB_DEL, &info); } int dsa_port_standalone_host_fdb_add(struct dsa_port *dp,
@@ -1107,7 +1130,8 @@ int dsa_port_lag_fdb_add(struct dsa_port *dp, const unsigned char *addr, if (!dp->ds->fdb_isolation) info.db.bridge.num = 0; - return dsa_port_notify(dp, DSA_NOTIFIER_LAG_FDB_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_LAG_FDB_ADD, &info, + DSA_NOTIFIER_LAG_FDB_DEL, &info); } int dsa_port_lag_fdb_del(struct dsa_port *dp, const unsigned char *addr,
@@ -1155,7 +1179,8 @@ int dsa_port_mdb_add(const struct dsa_port *dp, if (!dp->ds->fdb_isolation) info.db.bridge.num = 0; - return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_MDB_ADD, &info, + DSA_NOTIFIER_MDB_DEL, &info); } int dsa_port_mdb_del(const struct dsa_port *dp,
@@ -1189,7 +1214,8 @@ static int dsa_port_host_mdb_add(const struct dsa_port *dp, if (!dp->ds->fdb_isolation) info.db.bridge.num = 0; - return dsa_port_notify(dp, DSA_NOTIFIER_HOST_MDB_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_HOST_MDB_ADD, &info, + DSA_NOTIFIER_HOST_MDB_DEL, &info); } int dsa_port_standalone_host_mdb_add(const struct dsa_port *dp,
@@ -1274,7 +1300,8 @@ int dsa_port_vlan_add(struct dsa_port *dp, .extack = extack, }; - return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_VLAN_ADD, &info, + DSA_NOTIFIER_VLAN_DEL, &info); } int dsa_port_vlan_del(struct dsa_port *dp,
@@ -1300,7 +1327,8 @@ int dsa_port_host_vlan_add(struct dsa_port *dp, struct dsa_port *cpu_dp = dp->cpu_dp; int err; - err = dsa_port_notify(dp, DSA_NOTIFIER_HOST_VLAN_ADD, &info); + err = dsa_port_notify_robust(dp, DSA_NOTIFIER_HOST_VLAN_ADD, &info, + DSA_NOTIFIER_HOST_VLAN_DEL, &info); if (err && err != -EOPNOTSUPP) return err;
@@ -1742,7 +1770,8 @@ int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast) return dsa_broadcast_robust(DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info, DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, &info); - return dsa_port_notify(dp, DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info); + return dsa_port_notify_robust(dp, DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info, + DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, &info); } void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast)
--
2.34.1