2. PCIe Switch架构:内部结构、端口类型与路由机制
好,咱们今天聊聊PCIe Switch的内部架构。说实话,很多做DMA设计的工程师,对Switch的理解就停留在“一个能把多个设备连在一起的盒子”。但如果你真要做多主机拓扑,不了解Switch内部怎么工作的,迟早要踩坑。
我个人习惯把Switch看作一个“智能的报文分发中心”。它不像网桥那样简单转发,而是根据报文类型、目标地址,做出一系列决策。咱们从三个核心维度来拆解:内部结构、端口类型、路由机制。
2.1 Switch内部结构:到底长什么样?
先看一张我手绘的结构图,帮你建立直观印象。
Switch内部的核心,是那个内部互联总线(也叫Fabric)。它负责把各个端口连起来。每个端口背后,其实都是一个PCIe到PCIe桥(P2P Bridge)。嗯,这里要注意:Switch本质上就是一组P2P桥的集合体。
核心要点:Switch内部有一个路由表,它决定了报文从哪个端口进,从哪个端口出。仲裁器则负责处理多个端口同时请求时的优先级问题。
2.2 端口类型:UP、DOWN、NF
端口类型这事儿,我刚开始接触时也迷糊过。其实很简单,咱们按角色分:
2.2.1 UP端口(上行端口)
UP端口朝向Root Complex(RC)。说白了,就是离CPU更近的那个方向。在标准树形拓扑里,UP端口是Switch的“上级”。
- 通常只有一个UP端口(但也有多UP的Switch,后面会讲)
- UP端口处理发往RC的报文
- 我记得有一次项目,客户非要把两个UP端口接到同一个RC上,结果配置了半天才发现,这需要特殊的非透明桥支持
2.2.2 DOWN端口(下行端口)
DOWN端口朝向Endpoint(EP)或者下一级Switch。它是“下级”接口。
- 一个Switch可以有多个DOWN端口
- DOWN端口负责管理挂在其下的设备
- 我建议在设计多主机拓扑时,把关键设备挂在独立的DOWN端口上,避免带宽争抢
2.2.3 NF端口(非透明桥)
这个比较特殊。NF端口,说白了就是隔离域的边界。它不像普通端口那样直接转发报文,而是做地址转换。
实战技巧:NF端口常用于多主机隔离场景。比如两个主机共享一个存储设备,但彼此不想让对方看到自己的内存空间。NF端口会把一侧的地址空间映射到另一侧,实现“物理连通,逻辑隔离”。
我曾经在一个项目中,用NF端口实现了两个CPU域共享一个NVMe SSD。每个CPU看到的地址范围不同,但实际访问的是同一块物理存储。嗯,这个设计当时让客户觉得很神奇。
2.3 路由机制:报文怎么找到路?
PCIe Switch有三种路由方式。我按使用频率排序讲:
2.3.1 基于ID的路由(最常用)
每个PCIe设备都有一个唯一的Bus:Device:Function(BDF)编号。Switch根据这个ID来转发报文。
- 配置读写(Configuration Read/Write)必须用ID路由
- Switch内部维护一个ID路由表,记录每个BDF对应的端口
- 我习惯把ID路由想象成“门牌号寻址”——你知道具体住址,直接找过去
// ID路由表示例(简化)
// Bus Number -> 对应端口
Bus 0x00 -> UP Port
Bus 0x01 -> DOWN Port 0
Bus 0x02 -> DOWN Port 1
Bus 0x03 -> NF Port
2.3.2 基于地址的路由
内存读写(Memory Read/Write)和IO读写走的是地址路由。Switch根据报文中的目标地址,查地址路由表决定转发端口。
- 地址路由表本质上是基地址寄存器(BAR)的汇总
- 每个端口都有对应的地址窗口
- 你想想看,如果两个设备的地址窗口重叠了,那就会出大问题
避坑指南:我曾经遇到过一个案例,两个EP的BAR配置了重叠的地址范围,结果Switch不知道该把报文发给谁。系统直接挂死。所以,地址窗口必须互斥,这是铁律。
2.3.3 隐式路由
这个用得最少,但很重要。隐式路由用于消息报文(Message)。报文里不包含明确的地址或ID,而是通过消息类型来隐含目的地。
- 典型例子:INTx中断消息、PME电源管理事件
- Switch根据消息类型,决定是广播还是定向转发
- 说实话,隐式路由在调试时最让人头疼,因为你看不到明确的目标地址
2.4 三种路由的对比
| 路由类型 | 适用报文 | 路由依据 | 典型场景 |
|---|---|---|---|
| ID路由 | 配置读写 | BDF编号 | 设备枚举、配置空间访问 |
| 地址路由 | 内存/IO读写 | 目标地址 | DMA传输、数据搬运 |
| 隐式路由 | 消息报文 | 消息类型 | 中断、电源管理 |
2.5 多主机拓扑中的特殊考量
在多主机场景下,Switch的架构会变得更复杂。我简单提几个关键点:
- 多UP端口:有些Switch支持多个UP端口,每个接一个主机。这时候需要非透明桥来隔离不同主机的地址域
- 地址映射:NF端口会做地址转换,把一侧的物理地址映射到另一侧的虚拟地址空间
- 死锁预防:多主机同时发起DMA时,可能形成循环依赖。Switch内部需要实现信用流控和超时机制
个人经验:我做过一个4主机共享1个GPU的项目。每个主机都认为GPU是自己的,但实际上GPU的BAR被分成了4个区域,每个区域映射给一个主机。Switch的NF端口在这里起了关键作用——它做了4组地址转换。调试那会儿,我盯着逻辑分析仪看了整整三天,才把地址映射的bug找出来。
好了,关于Switch架构的核心内容就这些。记住:端口类型决定了角色,路由机制决定了路径,内部结构决定了性能。搞懂这三样,多主机拓扑的设计你就有了底气。
一句话总结:Switch不是简单的集线器,它是一个带路由表的智能交换中心。UP/DOWN/NF三种端口各司其职,ID/地址/隐式三种路由各管一摊。设计时,先想清楚你的拓扑需要哪种端口组合,再考虑路由怎么配。
公众号:蓝海资料掘金营,微信deep3321