This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] [参考译文] 【常见问题解答】TDA4VH-Q1:如何使用本机 Linux 驱动程序通过 CPSW 透明地传递 VLAN 0 数据包

Guru**** 2933120 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1654954/faq-tda4vh-q1-how-to-pass-vlan-0-packets-transparently-through-cpsw-using-the-native-linux-driver

器件型号: TDA4VH-Q1

默认情况下、CPSW 不按原样传递 VID 0(有优先级标记)帧。 Linux 驱动程序在入口 和出口处剥离或替换 VID 0、因此对于需要在 线路上设置优先级位的 VID 0 的用例而言、不可能。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    以下是 CPSW 阻止 VID 0 直通的原因。

    入口 — PVID 替代: CPSW 控制寄存器具有每个端口的 PASS_PRI_Tagged 位(位 3-11,每个端口一个)。 如果 未设置这些参数、一个优先级标记的帧、VID 0 到达任何端口、其 VID 0 将替换为该端口的 已配置 PVID。 另外、ALE 具有 VID 0 模式 (ALE_NO_PORT_VLAN)、控制 VID 0 入口数据包是作为 VID 0 处理、还是重新映射到端口的 VLAN。 两者都默认为 PVID 替代。

    出口 — 标签剥离:在驱动程序初始化时,使用强制未标记数据包出站 = 0x7f (所有端口)创建默认 ALE VLAN 0 条目。 这会在每个出口端口上剥离 VID 0 标记、因此有优先级标记的帧永远不会出现在线路上。

    泛洪 — VID 0 无 ALE 进入/学习: ALE MAC 学习是按 VLAN 进行的。 Linux 内核保留 VID 0 并拒绝任何 在网桥或网络接口上配置它的尝试(网桥 VLAN 添加 vid 0 会返回错误)。 因此、不会 为 VID 0 创建 ALE 条目、ALE 在 VID 0 下没有单播条目、所有 VID 0 单播通信将 通过 VID 0 成员掩码中的每个端口泛洪。

    修复:
    CPSW Linux 驱动程序 (am65-cpsw-nuss.c) 中需要以下 chages 才能按原样传递 VLAN 0 数据包。

    ——
    更改 1 — 设置 CPSW 控制寄存器中的 PASS_PRI_Tagged 位

    添加每端口 pass_pri_tagged 定义并与现有的 VLAN_Aware 和 P0_R0_ENABLE 位一起设置它们。 该命令指示 CPSW 硬件转发有优先级标记的帧、而不使用端口 PVID 替换 VID 0。

    --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
    +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
    @@ -87,6 +87,15 @@
     
     #define AM65_CPSW_CTL_VLAN_AWARE		BIT(1)
     #define AM65_CPSW_CTL_P0_ENABLE			BIT(2)
    +#define AM65_CPSW_CTL_P0_PASS_PRI_TAGGED	BIT(3)
    +#define AM65_CPSW_CTL_P1_PASS_PRI_TAGGED	BIT(4)
    +#define AM65_CPSW_CTL_P2_PASS_PRI_TAGGED	BIT(5)
    +#define AM65_CPSW_CTL_P3_PASS_PRI_TAGGED	BIT(6)
    +#define AM65_CPSW_CTL_P4_PASS_PRI_TAGGED	BIT(7)
    +#define AM65_CPSW_CTL_P5_PASS_PRI_TAGGED	BIT(8)
    +#define AM65_CPSW_CTL_P6_PASS_PRI_TAGGED	BIT(9)
    +#define AM65_CPSW_CTL_P7_PASS_PRI_TAGGED	BIT(10)
    +#define AM65_CPSW_CTL_P8_PASS_PRI_TAGGED	BIT(11)
     #define AM65_CPSW_CTL_P0_TX_CRC_REMOVE		BIT(13)
     #define AM65_CPSW_CTL_P0_RX_PAD			BIT(14)
     
    @@ -739,7 +748,16 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
     
     	/* Control register */
     	writel(AM65_CPSW_CTL_P0_ENABLE | AM65_CPSW_CTL_P0_TX_CRC_REMOVE |
    -	       AM65_CPSW_CTL_P0_RX_PAD,
    +	       AM65_CPSW_CTL_VLAN_AWARE | AM65_CPSW_CTL_P0_RX_PAD |
    +	       AM65_CPSW_CTL_P0_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P1_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P2_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P3_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P4_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P5_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P6_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P7_PASS_PRI_TAGGED |
    +	       AM65_CPSW_CTL_P8_PASS_PRI_TAGGED,
     	       common->cpsw_base + AM65_CPSW_REG_CTL);

    ——
    更改 2-在 ALE 主机端口上启用 VLAN 0 模式


    设置 CPSW ALE 控制寄存器中的 ALE_NO_PORT_VLAN、以便 ALE 将 VID 0 入口数据包视为 VID 0、而不会重新映射到端口的 VLAN。

    --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
    +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
    @@ -2987,6 +2987,10 @@ static void am65_cpsw_init_host_port_switch(struct am65_cpsw_common *common)
     
     	cpsw_ale_control_set(common->ale, HOST_PORT_NUM, ALE_P0_UNI_FLOOD, 1);
     	dev_dbg(common->dev, "Set P0_UNI_FLOOD\n");
    +
    +	cpsw_ale_control_set(common->ale, HOST_PORT_NUM, ALE_NO_PORT_VLAN, 1);
    +	dev_dbg(common->dev, "Set VLAN 0 Mode\n");
    +
     	cpsw_ale_control_set(common->ale, HOST_PORT_NUM, ALE_PORT_NOLEARN, 0);

    ——
    更改 3 — 清除 ALE VID 0 条目上的强制未标记出口掩码

    默认的 ALE VID 0 条目是使用 untag = ALE_ALL_PORTS (0x7f) 创建的、它在每个出口 端口上条目 VID 0 标签。 相反、传递 untag = 0、这样 VID 0 数据包离开时其 VLAN 标记完好无损。

    @@ -782,7 +800,7 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
     		    ~common->disabled_ports_mask;
     
     	cpsw_ale_add_vlan(common->ale, 0, port_mask,
    -			  port_mask, port_mask,
    +			  0, port_mask,
     			  port_mask & ~ALE_PORT_HOST);
     

    ——
    更改 4-为每个外部端口的 VID 0 添加静态主机端口 ALE 条目

    在 VID 0 下为每个外部端口添加主机 MAC 的单播和多播 ALE 条目。 如果没有这些、ALE 将不会 对 VID 0 通信进行单播匹配、并将其泛洪到所有成员端口上。

    --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
    +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
    @@ -3059,12 +3059,20 @@ static void am65_cpsw_init_port_switch_ale(struct am65_cpsw_port *port)
     			   HOST_PORT_NUM, ALE_SECURE | ALE_BLOCKED | ALE_VLAN,
     			   slave->port_vlan);
     
    +	cpsw_ale_add_ucast(cpsw->ale, port->ndev->dev_addr,
    +			   HOST_PORT_NUM, ALE_SECURE | ALE_BLOCKED | ALE_VLAN,
    +			   0);
    +
     	port_mask = BIT(port->port_id) | ALE_PORT_HOST;
     
     	cpsw_ale_add_mcast(cpsw->ale, port->ndev->broadcast,
     			   port_mask, ALE_VLAN, slave->port_vlan,
     			   ALE_MCAST_FWD_2);
     
    +	cpsw_ale_add_mcast(cpsw->ale, port->ndev->broadcast,
    +			   port_mask, ALE_VLAN, 0,
    +			   ALE_MCAST_FWD_2);
    +
     	writel(slave->port_vlan, port->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
     
     	cpsw_ale_control_set(cpsw->ale, port->port_id,