rtl93xx: dsa: Handle lag_change properly

LACP frequently changes active/backup links. driver must also handle
dp->lag_tx_enabled.

This should only affect egress LAG table, ingress should not be touched.
To test, connect a known working 802.3ad compatible switch (Mikrotik).
Configure bond with 802.3ad on openwrt as well as mikrotik.
Observer active/backup links on openwrt with
```
for iface in <list of bond participants>; do
ip -d link show $iface
done
```
This should show ACTIVE/BACKUP status which must be synchronized with
the partner's ACTIVE/BACKUP status if LACP is working correctly.

Backup interface must not be chosen by the distribution algorithm to
transmit egress packet

At the moment, we have two parties involved in the selection of active LAG TX
ports:
- the bonding/DSA code which informs about activated/deactivated ports using
  .port_lag_change
- the HW which is deactivating ports based on the link state see
  RTL93XX_TRK_CTRL_LINK_DOWN_AVOID

In our case, the software is supposed to manage everything

Co-developed-by: Sven Eckelmann <se@simonwunderlich.de>
Signed-off-by: Sven Eckelmann <se@simonwunderlich.de>
Signed-off-by: Harshal Gohel <hg@simonwunderlich.de>
Link: https://github.com/openwrt/openwrt/pull/21740
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Harshal Gohel 2026-01-27 11:35:16 +00:00 committed by Hauke Mehrtens
parent 05096060ca
commit 89322b4d69
2 changed files with 28 additions and 3 deletions

View file

@ -3,6 +3,7 @@
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
#include <net/arp.h>
#include <net/lag.h>
#include <net/nexthop.h>
#include <net/neighbour.h>
#include <net/netevent.h>
@ -565,6 +566,11 @@ static int rtldsa_93xx_lag_set_group2ports(struct rtl838x_switch_priv *priv, int
table_pos = 0;
for_each_set_bit(i, ports, ARRAY_SIZE(priv->ports)) {
struct net_device *lag_slave = priv->ports[i].dp->user;
if (lag_slave && !net_lag_port_dev_txable(lag_slave))
continue;
group_ports[table_pos] = i;
table_pos++;
}
@ -1803,7 +1809,6 @@ void rtldsa_93xx_lag_switch_init(struct rtl838x_switch_priv *priv)
trk_ctrlmask |= RTL93XX_TRK_CTRL_NON_TMN_TUNNEL_HASH_SEL;
trk_ctrlmask |= RTL93XX_TRK_CTRL_TRK_STAND_ALONE_MODE;
trk_ctrlmask |= RTL93XX_TRK_CTRL_LOCAL_FIRST;
trk_ctrlmask |= RTL93XX_TRK_CTRL_LINK_DOWN_AVOID;
sw_w32(trk_ctrlmask, priv->r->trk_ctrl);

View file

@ -2377,8 +2377,28 @@ static bool rtldsa_83xx_lag_can_offload(struct dsa_switch *ds,
static int rtldsa_port_lag_change(struct dsa_switch *ds, int port)
{
pr_debug("%s: %d\n", __func__, port);
/* Nothing to be done... */
struct dsa_port *dp = dsa_to_port(ds, port);
struct rtl838x_switch_priv *priv = ds->priv;
int lag_group;
int ret;
if (!dp)
return -EINVAL;
lag_group = rtldsa_find_lag_group_from_port(priv, port);
if (lag_group < 0)
return lag_group;
if (priv->r->lag_set_port_members) {
/* Set same port members again, the function should check against
* lag_tx_enabled and set egress ports accordingly.
*/
ret = priv->r->lag_set_port_members(priv, lag_group,
priv->lags_port_members[lag_group],
NULL);
if (ret)
return ret;
}
return 0;
}