mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-03-14 23:09:45 +01:00
realtek: dsa: Reelect primary port for a LAG
rtl93xx hardware supports trunk fdb entries. That requires driver to translate port-fdb entry to trunk fdb entry if the port is part of a LAG. There is no standard way of indicating fdb entries for bond interfaces. One can use debugfs interface l2_table to dump all the entries stored in the hardware. Trunk FDB entries are now displayed properly with trunk ID and participating ports 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:
parent
286445257d
commit
3743ed0e02
5 changed files with 85 additions and 4 deletions
|
|
@ -268,6 +268,13 @@ static void l2_table_print_entry(struct seq_file *m, struct rtl838x_switch_priv
|
|||
e->vid, e->rvid);
|
||||
|
||||
seq_printf(m, " port %d age %d", e->port, e->age);
|
||||
if (e->is_trunk) {
|
||||
seq_printf(m, " trunk %d trunk_members: 0x%08llx non-primary: 0x%08llx primary-port: %d",
|
||||
e->trunk,
|
||||
priv->lags_port_members[e->trunk],
|
||||
priv->lag_non_primary,
|
||||
priv->lag_primary[e->trunk]);
|
||||
}
|
||||
if (e->is_static)
|
||||
seq_puts(m, " static");
|
||||
if (e->block_da)
|
||||
|
|
|
|||
|
|
@ -1865,6 +1865,39 @@ static int rtldsa_find_l2_cam_entry(struct rtl838x_switch_priv *priv, u64 seed,
|
|||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtldsa_find_lag_group_from_port() - Find lag group of current port
|
||||
* @priv: private data of rtldsa switch
|
||||
* @port: port id of potential LAG member
|
||||
* Return: -ENOENT when port does not belong to any lag group, lag id otherwise
|
||||
*/
|
||||
static int rtldsa_find_lag_group_from_port(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
if (!(priv->lagmembers & BIT_ULL(port)))
|
||||
return -ENOENT;
|
||||
|
||||
/* port is a lag member */
|
||||
for (int lag_group = 0; lag_group < MAX_LAGS; lag_group++) {
|
||||
if (priv->lags_port_members[lag_group] & BIT_ULL(port))
|
||||
return lag_group;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtldsa_93xx_prepare_lag_fdb() - Prepare fdb entry for LAG
|
||||
* @e: L2 entry data
|
||||
* @lag_group: lag id of the trunk group
|
||||
*/
|
||||
inline void rtldsa_93xx_prepare_lag_fdb(struct rtl838x_l2_entry *e, int lag_group)
|
||||
{
|
||||
if (e && lag_group >= 0) {
|
||||
e->is_trunk = true;
|
||||
e->trunk = lag_group;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtldsa_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
const struct dsa_db db)
|
||||
|
|
@ -1874,10 +1907,16 @@ static int rtldsa_port_fdb_add(struct dsa_switch *ds, int port,
|
|||
struct rtl838x_l2_entry e;
|
||||
int err = 0, idx;
|
||||
u64 seed = priv->r->l2_hash_seed(mac, vid);
|
||||
int lag_group = rtldsa_find_lag_group_from_port(priv, port);
|
||||
|
||||
if (priv->lag_non_primary & BIT_ULL(port)) {
|
||||
pr_debug("%s: %d is lag slave. ignore\n", __func__, port);
|
||||
return 0;
|
||||
if (lag_group >= 0 && priv->r->prepare_lag_fdb) {
|
||||
priv->r->prepare_lag_fdb(&e, lag_group);
|
||||
} else {
|
||||
if (priv->lag_non_primary & BIT_ULL(port)) {
|
||||
pr_debug("%s: %d is lag slave but prepare_lag_fdb is not supported. ignore\n",
|
||||
__func__, port);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
|
@ -1917,8 +1956,13 @@ static int rtldsa_port_fdb_del(struct dsa_switch *ds, int port,
|
|||
struct rtl838x_l2_entry e;
|
||||
int err = 0, idx;
|
||||
u64 seed = priv->r->l2_hash_seed(mac, vid);
|
||||
int lag_group = rtldsa_find_lag_group_from_port(priv, port);
|
||||
|
||||
if (lag_group >= 0 && priv->r->prepare_lag_fdb)
|
||||
priv->r->prepare_lag_fdb(&e, lag_group);
|
||||
|
||||
pr_debug("In %s, mac %llx, vid: %d\n", __func__, mac, vid);
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
idx = rtldsa_find_l2_hash_entry(priv, seed, true, &e);
|
||||
|
|
@ -1960,6 +2004,10 @@ static int rtldsa_port_fdb_dump(struct dsa_switch *ds, int port,
|
|||
if (!e.valid)
|
||||
continue;
|
||||
|
||||
// Ignore trunk fdb entries
|
||||
if (e.is_trunk)
|
||||
continue;
|
||||
|
||||
if (e.port == port || e.port == RTL930X_PORT_IGNORE)
|
||||
cb(e.mac, e.vid, e.is_static, data);
|
||||
|
||||
|
|
@ -1973,6 +2021,10 @@ static int rtldsa_port_fdb_dump(struct dsa_switch *ds, int port,
|
|||
if (!e.valid)
|
||||
continue;
|
||||
|
||||
// Ignore trunk fdb entries
|
||||
if (e.is_trunk)
|
||||
continue;
|
||||
|
||||
if (e.port == port)
|
||||
cb(e.mac, e.vid, e.is_static, data);
|
||||
}
|
||||
|
|
@ -2396,7 +2448,6 @@ static int rtldsa_port_lag_leave(struct dsa_switch *ds, int port,
|
|||
}
|
||||
pr_info("port_lag_del: group %d, port %d\n", group, port);
|
||||
priv->lagmembers &= ~BIT_ULL(port);
|
||||
priv->lag_primary[group] = -1;
|
||||
priv->lag_non_primary &= ~BIT_ULL(port);
|
||||
pr_debug("lag_members = %llX\n", priv->lagmembers);
|
||||
err = rtl83xx_lag_del(priv->ds, group, port);
|
||||
|
|
@ -2405,6 +2456,19 @@ 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]);
|
||||
}
|
||||
|
||||
/* No need to update fdb entries since they make use of trunk_id for entry.
|
||||
* The primary interface is only calculated at time of
|
||||
* port_fdb_dump
|
||||
*/
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1366,6 +1366,8 @@ struct rtldsa_config {
|
|||
void (*led_init)(struct rtl838x_switch_priv *priv);
|
||||
void (*qos_init)(struct rtl838x_switch_priv *priv);
|
||||
int (*trk_mbr_ctr)(int group);
|
||||
void (*lag_switch_init)(struct rtl838x_switch_priv *priv);
|
||||
void (*prepare_lag_fdb)(struct rtl838x_l2_entry *e, int lag_group);
|
||||
int (*lag_set_port_members)(struct rtl838x_switch_priv *priv, int group, u64 members,
|
||||
struct netdev_lag_upper_info *info);
|
||||
int (*lag_setup_algomask)(struct rtl838x_switch_priv *priv, int group,
|
||||
|
|
@ -1449,6 +1451,8 @@ void rtl930x_dbgfs_init(struct rtl838x_switch_priv *priv);
|
|||
int rtldsa_93xx_lag_set_distribution_algorithm(struct rtl838x_switch_priv *priv,
|
||||
int group, int algoidx, u32 algomsk);
|
||||
|
||||
void rtldsa_93xx_prepare_lag_fdb(struct rtl838x_l2_entry *e, int lag_group);
|
||||
|
||||
void rtldsa_counters_lock_register(struct rtl838x_switch_priv *priv, int port)
|
||||
__acquires(&priv->ports[port].counters.lock);
|
||||
void rtldsa_counters_unlock_register(struct rtl838x_switch_priv *priv, int port)
|
||||
|
|
|
|||
|
|
@ -2801,5 +2801,8 @@ const struct rtldsa_config rtldsa_930x_cfg = {
|
|||
.set_receive_management_action = rtldsa_930x_set_receive_management_action,
|
||||
.qos_init = rtldsa_930x_qos_init,
|
||||
.trk_hash_ctrl = RTL930X_TRK_HASH_CTRL,
|
||||
.prepare_lag_fdb = rtldsa_93xx_prepare_lag_fdb,
|
||||
.lag_switch_init = rtldsa_93xx_lag_switch_init,
|
||||
.lag_set_port_members = rtldsa_93xx_lag_set_port_members,
|
||||
.lag_set_distribution_algorithm = rtldsa_93xx_lag_set_distribution_algorithm,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1925,5 +1925,8 @@ const struct rtldsa_config rtldsa_931x_cfg = {
|
|||
.set_receive_management_action = rtldsa_931x_set_receive_management_action,
|
||||
.qos_init = rtldsa_931x_qos_init,
|
||||
.trk_hash_ctrl = RTL931X_TRK_HASH_CTRL,
|
||||
.prepare_lag_fdb = rtldsa_93xx_prepare_lag_fdb,
|
||||
.lag_switch_init = rtldsa_93xx_lag_switch_init,
|
||||
.lag_set_port_members = rtldsa_93xx_lag_set_port_members,
|
||||
.lag_set_distribution_algorithm = rtldsa_93xx_lag_set_distribution_algorithm,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue