2. Switch拓扑架构:标准层级树与双主机拓扑设计

大家好,我是老张。今天咱们聊聊PCIe Switch的拓扑架构。说实话,这块内容在项目里踩过的坑最多。你想想看,一个系统里挂几十个设备,拓扑选错了,信号完整性直接崩盘。

PCIe拓扑,说白了就是设备怎么连的问题。标准规范里只定义了两种基本结构:层级树和双主机。但实际项目中,我见过各种魔改版本。嗯,咱们先从最基础的讲起。

2.1 标准层级树拓扑

层级树,也叫树形拓扑。这是PCIe最正统的连法。一个Root Complex(RC)挂在最上面,下面接Switch,Switch再往下挂Endpoint。就像一棵倒着长的树。

核心原则:层级树中,任意两个设备之间只有一条通路。没有环路,没有冗余。这是PCIe协议强制要求的。

我刚开始做设计时,总觉得这限制太死。后来在某个服务器项目里,客户非要搞冗余链路,结果枚举阶段就报错。嗯,从那以后我再也不敢挑战协议了。

2.1.1 层级深度限制

PCIe规范对层级深度有明确限制:最多256个层级。但实际项目中,我建议别超过6层。为什么?

  • 每多一层,信号就要多过一次Switch内部的MUX
  • 延迟累加,对等时性要求高的设备不友好
  • 电源完整性更难控制——我在一个AI加速卡项目里吃过这个亏

举个例子,一个典型的层级树长这样:

Root Complex (RC)
  └── Switch (上游端口)
        ├── Endpoint (GPU)
        ├── Switch (下游)
        │     ├── Endpoint (NVMe SSD)
        │     └── Endpoint (网卡)
        └── Endpoint (FPGA)

你看,这里用了两级Switch。GPU直接挂在一级Switch下,因为它的带宽需求最大。NVMe和网卡挂在二级Switch下,共享上游带宽。这种设计,我在实际项目中验证过多次,效果不错。

2.1.2 带宽分配策略

层级树里有个关键问题:带宽怎么分?

我个人习惯的做法是:

  1. 先算总带宽:上游端口的总带宽 = 所有下游设备带宽之和 × 1.2(留20%余量)
  2. 再分优先级:对延迟敏感的设备(比如GPU)直接挂一级Switch
  3. 最后看拓扑:尽量让高带宽设备靠近RC

小技巧:我曾经在一个项目里,把所有SSD都挂在同一个Switch下。结果发现,当多个SSD同时读写时,上游端口成了瓶颈。后来改成每个Switch只挂2-3个SSD,问题就解决了。

2.2 双主机拓扑设计

双主机拓扑,说白了就是两个RC共享一套PCIe设备。这在服务器里很常见,比如两个CPU共享一个NVMe盘。

但这里有个坑:PCIe协议本身不支持多主机共享。怎么办?靠Switch的Non-Transparent Bridging(NTB)功能。

2.2.1 NTB的工作原理

NTB,非透明桥。它把两个PCIe域隔离开,通过地址映射实现数据交换。

我记得第一次接触NTB时,被它的地址映射搞晕了。后来画了个图才明白:

主机A (RC-A)         主机B (RC-B)
    │                     │
    │   ┌─────────────┐   │
    └───┤  Switch      ├───┘
        │  (NTB模式)   │
        ├─────────────┤
        │  共享设备     │
        └─────────────┘

你看,两个主机各自有独立的地址空间。Switch在中间做地址翻译。主机A访问0x8000_0000,Switch把它映射到主机B的0x4000_0000。这样两边就能通信了。

注意:NTB不是万能的。它只支持简单的内存读写,不支持DMA。如果你需要高性能数据传输,得用专门的NTB驱动。我在一个存储项目里,因为没处理好驱动,导致数据一致性出问题,排查了整整三天。

2.2.2 双主机的典型应用场景

实际项目中,双主机拓扑主要用在:

  • 高可用系统:两个主机互为备份,共享存储
  • 计算集群:多个CPU共享GPU或FPGA加速器
  • 存储服务器:双控架构,共享NVMe盘

嗯,这里要注意:双主机拓扑对信号完整性要求更高。因为两个主机可能不在同一块板子上,走线更长,阻抗更难控制。

2.3 拓扑设计中的SI实战要点

拓扑选好了,接下来就是信号完整性的事了。我总结了几条实战经验:

2.3.1 走线长度匹配

PCIe是差分信号,对走线长度匹配要求很严。Gen3以上,差分对内偏差要控制在5mil以内。我曾经在一个项目里,因为没注意这个,导致链路训练失败。

具体做法:

  • 同一对差分线,长度差不超过5mil
  • 不同设备间的走线,尽量等长
  • Switch到Endpoint的走线,控制在10英寸以内

2.3.2 阻抗控制

PCIe要求差分阻抗85Ω ± 15%。但实际板材有误差,我建议设计时按85Ω ± 10%来控。

这里有个坑:不同层之间的阻抗不一样。我习惯把高速信号走在表层,因为表层阻抗更容易控制。如果必须走内层,记得加屏蔽地线。

2.3.3 去耦电容布局

Switch芯片的电源去耦,直接影响信号质量。我的经验是:

  • 每个电源引脚放一个0.1uF电容
  • 电容尽量靠近引脚,走线越短越好
  • 大电容(10uF以上)放在板边

避坑指南:我曾经在一个项目里,把去耦电容放得太远,结果电源纹波超标,导致链路误码率飙升。后来把电容挪到引脚旁边,问题就解决了。记住:电容离引脚越近越好,别超过100mil。

2.4 拓扑设计的决策流程

说了这么多,实际设计时怎么选?我一般按这个流程来:

  1. 先看需求:需要几个主机?几个设备?
  2. 再算带宽:总带宽够不够?瓶颈在哪?
  3. 然后选拓扑:单主机用层级树,双主机用NTB
  4. 最后做SI仿真:走线长度、阻抗、串扰,都得跑一遍

嗯,这个流程我用了好几年,基本没出过大问题。当然,每个项目都有特殊情况,到时候灵活调整就行。

2.5 本章小结

今天聊了层级树和双主机两种拓扑。层级树简单可靠,适合大多数场景。双主机靠NTB实现,适合高可用和共享设备场景。不管选哪种,信号完整性都得提前规划。

我个人觉得,拓扑设计最忌讳想当然。你以为这么连没问题,实际跑起来全是坑。所以,多仿真、多测试、多留余量,准没错。

好了,今天就到这。下次咱们聊聊Switch芯片选型,那又是另一门学问了。


公众号:蓝海资料掘金营,微信deep3321