分布式交换机架构(DSA)
分布式交换机架构(DSA)并不是什么新事物。多年来,它一直是 Linux 中成熟的子系统。本文档略去了背景、术语及任何相关知识描述,用户可以在 Linux DSA documentation 中找到所有这些内容。
DSA 交换机 TX/RX 处理过程
DSA 交换机 TX/RX 处理过程如下。
主机接口
主机接口网络设备使用常规、未经修改的以太网驱动程序,作为 DSA 通道端口(conduit port)工作,并通过处理器管理交换机。
交换机接口
交换机接口在 Zephyr 中也作为标准以太网接口呈现。连接到通道端口的接口充当 CPU 端口,其他供用户使用的接口则充当用户端口。
交换机标记协议
通常,交换机标记协议因厂商而异。它们都包含以下内容:
标识以太网帧来自哪个端口/应发送到哪个端口
提供该帧被转发到管理接口的原因
并在数据包上打标记,为其添加交换机帧报头。但也存在无标记的情况,这取决于厂商。
网络协议栈处理过程
为了让 DSA 子系统通过通道端口处理以太网交换机特定的标记协议。
对于 RX 路径,将 dsa_recv() 放在 subsys/net/ip/net_core.c 中 net_recv_data() 的开头,以便首先进行去标记和接口重定向处理。
对于 TX 路径,交换机接口注册为标准以太网设备,并将 dsa_xmit() 作为 ethernet_api->send。dsa_xmit() 负责处理标记以及到通道端口的重定向工作。
DSA 设备驱动程序支持
由于 DSA 核心驱动程序与 MDIO、PHY 和 Devicetree 等子系统/驱动程序交互,以支持通用的 DSA 搭建和工作流程,因此设备驱动程序支持要容易得多。
对于 Devicetree,交换机描述应遵循 dts/bindings/dsa/dsa.yaml。
对于设备驱动程序,需要准备的是 dsa_api、私有数据(如果有)和 dsa_port_config。可以利用宏函数。下面是 i.MX NETC 的示例。
#define DSA_NETC_PORT_INST_INIT(port, n) \
COND_CODE_1(DT_NUM_PINCTRL_STATES(port), \
(PINCTRL_DT_DEFINE(port);), (EMPTY)) \
struct dsa_netc_port_config dsa_netc_##n##_##port##_config = { \
.pincfg = COND_CODE_1(DT_NUM_PINCTRL_STATES(port), \
(PINCTRL_DT_DEV_CONFIG_GET(port)), NULL), \
.phy_mode = NETC_PHY_MODE(port), \
}; \
struct dsa_port_config dsa_##n##_##port##_config = { \
.mcfg = NET_ETH_MAC_DT_CONFIG_INIT(port), \
.port_idx = DT_REG_ADDR(port), \
.phy_dev = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(port, phy_handle)), \
.phy_mode = DT_PROP_OR(port, phy_connection_type, ""), \
.ethernet_connection = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(port, ethernet)), \
.prv_config = &dsa_netc_##n##_##port##_config, \
}; \
DSA_PORT_INST_INIT(port, n, &dsa_##n##_##port##_config)
#define DSA_NETC_DEVICE(n) \
AT_NONCACHEABLE_SECTION_ALIGN(static netc_cmd_bd_t dsa_netc_##n##_cmd_bd[8], \
NETC_BD_ALIGN); \
static struct dsa_netc_data dsa_netc_data_##n = { \
.cmd_bd = dsa_netc_##n##_cmd_bd, \
}; \
DSA_SWITCH_INST_INIT(n, &dsa_netc_api, &dsa_netc_data_##n, DSA_NETC_PORT_INST_INIT);
使用 DSA 搭建时的常见陷阱
以下内容摘自 Linux DSA 文档,同样适用于 Zephyr。尽管通道端口和 CPU 端口在 Zephyr 中作为以太网设备呈现,但它们无法使用。
备注
一旦通道网络设备被配置为使用 DSA(dev->dsa_ptr 变为非 NULL),并且其后面的交换机要求使用标记协议,该网络接口就只能专门用作通道接口。直接通过此接口发送数据包(例如:使用此接口打开 socket)不会经过交换机标记协议的发送函数,因此另一端期望收到标记的以太网交换机通常会丢弃该帧。
待完成的工作
与 Linux 相比,Zephyr DSA 中需要支持的功能太多。但基本上应支持桥接层。这样 DSA 就可以为用户提供两种使用交换机端口的方式。
独立模式:所有用户端口都作为常规以太网设备工作,不进行交换。
桥接模式:将用户端口加入虚拟桥接设备,从而启用交换模式。可以为该桥接分配 IP 地址。