瀏覽代碼

realtek: dsa: rtl93xx: Support multi spanning tree states

The MSTP support (usually implemented by mstpd) requires from the kernel
that a VLAN can associated with an MSTI. At the moment, all these VLANs
just get the msti 0 harcoded on creation. But the
vlan_tables_read()+vlan_tables_write() helper already allow the
modification of the MSTI and only require a minimal hook to expose this
functionality.

It is also necessary to adjust the (M)STP states per MSTI and not only per
port (or for the CIST). The rtl83xx_port_stp_state_set() function was in
theory already capable to modify other MSTIs than CIST - if the msti would
not have been hardcoded to 0.

The userspace can trigger these modifications using netlink:

* (Re)associating VLANs with an MSTI:

      bridge vlan global set dev <BR> vid <X> msti <Y>

* Setting the port state in a given MSTI:

      bridge mst set dev <PORT> msti <Y> state <Z>

Signed-off-by: Issam Hamdi <[email protected]>
Co-developed-by: Sven Eckelmann <[email protected]>
Signed-off-by: Sven Eckelmann <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20421
Signed-off-by: Hauke Mehrtens <[email protected]>
Issam Hamdi 6 月之前
父節點
當前提交
6c15c5d5eb
共有 1 個文件被更改,包括 33 次插入0 次删除
  1. 33 0
      target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c

+ 33 - 0
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c

@@ -1677,6 +1677,18 @@ static void rtl930x_fast_age(struct dsa_switch *ds, int port)
 	mutex_unlock(&priv->reg_mutex);
 }
 
+static int rtldsa_port_mst_state_set(struct dsa_switch *ds, int port,
+				     const struct switchdev_mst_state *st)
+{
+	struct rtl838x_switch_priv *priv = ds->priv;
+
+	mutex_lock(&priv->reg_mutex);
+	rtldsa_port_xstp_state_set(priv, port, st->state, st->msti);
+	mutex_unlock(&priv->reg_mutex);
+
+	return 0;
+}
+
 static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port,
 				  bool vlan_filtering,
 				  struct netlink_ext_ack *extack)
@@ -1877,6 +1889,23 @@ static int rtldsa_port_vlan_fast_age(struct dsa_switch *ds, int port, u16 vid)
 	return ret;
 }
 
+static int rtldsa_vlan_msti_set(struct dsa_switch *ds, struct dsa_bridge bridge,
+				const struct switchdev_vlan_msti *msti)
+{
+	struct rtl838x_switch_priv *priv = ds->priv;
+	struct rtl838x_vlan_info info;
+	int mst_slot = msti->msti;
+
+	if (mst_slot >= priv->n_mst)
+		return -EINVAL;
+
+	priv->r->vlan_tables_read(msti->vid, &info);
+	info.fid = mst_slot;
+	priv->r->vlan_set_tagged(msti->vid, &info);
+
+	return 0;
+}
+
 static void rtl83xx_setup_l2_uc_entry(struct rtl838x_l2_entry *e, int port, int vid, u64 mac)
 {
 	memset(e, 0, sizeof(*e));
@@ -2666,10 +2695,12 @@ const struct dsa_switch_ops rtl83xx_switch_ops = {
 	.port_bridge_leave	= rtldsa_port_bridge_leave,
 	.port_stp_state_set	= rtl83xx_port_stp_state_set,
 	.port_fast_age		= rtl83xx_fast_age,
+	.port_mst_state_set	= rtldsa_port_mst_state_set,
 
 	.port_vlan_filtering	= rtl83xx_vlan_filtering,
 	.port_vlan_add		= rtl83xx_vlan_add,
 	.port_vlan_del		= rtl83xx_vlan_del,
+	.vlan_msti_set		= rtldsa_vlan_msti_set,
 
 	.port_fdb_add		= rtl83xx_port_fdb_add,
 	.port_fdb_del		= rtl83xx_port_fdb_del,
@@ -2723,11 +2754,13 @@ const struct dsa_switch_ops rtl93xx_switch_ops = {
 	.port_bridge_leave	= rtldsa_port_bridge_leave,
 	.port_stp_state_set	= rtl83xx_port_stp_state_set,
 	.port_fast_age		= rtl930x_fast_age,
+	.port_mst_state_set	= rtldsa_port_mst_state_set,
 
 	.port_vlan_filtering	= rtl83xx_vlan_filtering,
 	.port_vlan_add		= rtl83xx_vlan_add,
 	.port_vlan_del		= rtl83xx_vlan_del,
 	.port_vlan_fast_age	= rtldsa_port_vlan_fast_age,
+	.vlan_msti_set		= rtldsa_vlan_msti_set,
 
 	.port_fdb_add		= rtl83xx_port_fdb_add,
 	.port_fdb_del		= rtl83xx_port_fdb_del,