mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-12 06:57:57 +04:00
realtek: dsa: track the primary port of a LAG
The first member of a LAG becomes its primary port when lag_primary[] holds -1, but the array comes zero-filled from devm_kzalloc() and is never set to -1. Every member is therefore marked non-primary, and the FDB and MDB code of the RTL83xx skips non-primary ports. The leave path is wrong as well: it elects a new primary whenever any member leaves, uses fls64(), which is one-based, as a port number, and keeps the old primary when the last member leaves, so the next LAG with that id starts without one. Set every slot to -1 at probe, record the primary only after the hardware join succeeded, and on leave elect a new primary only when the primary itself leaves: the lowest remaining member, or -1 when the LAG is empty. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Quinn O'Shea <qoshea@gmail.com> Link: https://github.com/openwrt/openwrt/pull/25792 Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
This commit is contained in:
1 parent
c39546671e
commit
8509328d1a
3 files changed
+14
-13
No files matched your search
@@ -439,6 +439,7 @@ static int rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->r = r;
|
||||
memset(priv->lag_primary, -1, sizeof(priv->lag_primary));
|
||||
|
||||
priv->l2_uc_map = devm_kcalloc(dev, r->fib_entries, sizeof(*priv->l2_uc_map),
|
||||
GFP_KERNEL);
|
||||
|
||||
@@ -1422,19 +1422,19 @@ static int rtldsa_port_lag_join(struct dsa_switch *ds,
|
||||
|
||||
pr_info("port_lag_join: group %d, port %d\n", group, port);
|
||||
|
||||
err = otto_lag_add(priv->ds, group, port, info);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->lag_primary[group] == -1)
|
||||
priv->lag_primary[group] = port;
|
||||
else
|
||||
priv->lag_non_primary |= BIT_ULL(port);
|
||||
|
||||
priv->lagmembers |= BIT_ULL(port);
|
||||
|
||||
pr_debug("lag_members = %llX\n", priv->lagmembers);
|
||||
err = otto_lag_add(priv->ds, group, port, info);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
@@ -1466,12 +1466,12 @@ static int rtldsa_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* To re-elect primary interface, just remove the first interface in
|
||||
* this-group's interfaces from non-primary
|
||||
*/
|
||||
if (priv->lags_port_members[group]) {
|
||||
priv->lag_primary[group] = fls64(priv->lags_port_members[group]);
|
||||
priv->lag_non_primary &= ~BIT_ULL(priv->lag_primary[group]);
|
||||
if (priv->lag_primary[group] == port) {
|
||||
u64 members = priv->lags_port_members[group];
|
||||
|
||||
priv->lag_primary[group] = members ? __ffs64(members) : -1;
|
||||
if (members)
|
||||
priv->lag_non_primary &= ~BIT_ULL(priv->lag_primary[group]);
|
||||
}
|
||||
|
||||
/* No need to update fdb entries since they make use of trunk_id for entry.
|
||||
|
||||
@@ -507,7 +507,7 @@ struct rtl838x_switch_priv {
|
||||
/** @lag_primary: port of a LAG is primary (repesenting) and is added to
|
||||
* the port matrix
|
||||
*/
|
||||
u32 lag_primary[MAX_LAGS];
|
||||
int lag_primary[MAX_LAGS];
|
||||
|
||||
/**
|
||||
* @lag_non_primary: Port (bit) is part of any LAG but not the
|
||||
|
||||
Reference in new issue
Block a user