2. PCIe基础概念
要真正读懂一次PCIe抓包,先要建立三张“地图”:设备之间怎么连(拓扑)、协议怎么分层(分层架构)、每一层各自负责什么(职责)。抓包工具看到的TLP、DLLP、有序集,本质上都是这三张地图在不同层次上的投影。本节围绕这三条主线展开,并给出常见术语的对照,为后续的抓包解析和故障定位打基础。
一、PCIe拓扑结构:树形、点对点、以Switch为中心
PCIe在物理上是点对点链路,每条Link只连接两个端点;在逻辑上则组织成一棵树形拓扑。树的根是RC(Root Complex,根复合体),它把CPU、内存子系统与PCIe域连接起来。RC下方可以直连Endpoint(如NVMe SSD、网卡),也可以通过Switch扩展出更多端口。
Switch内部并不是一根总线,而是由多个虚拟PCI-PCI桥构成的交换结构,每个下游端口都是一个独立的PCIe链路。因此,从配置空间看,整棵树仍然是标准的PCI总线/设备/功能层次;从链路层看,每个端口之间是独立的点对点连接。这正是抓包时“同一事务在不同链路上看到的TLP不同”的根本原因。
拓扑中还有几个关键角色:Root Complex负责发起和接收配置、内存、IO事务;Endpoint是事务的最终完成者;Switch只做转发,不产生新的事务;PCIe-to-PCI桥用于兼容旧设备。理解“谁发起、谁转发、谁完成”,是判断抓包中TLP方向的前提。
二、分层架构:事务层、数据链路层、物理层
PCIe协议自上而下分为三层:事务层(Transaction Layer)、数据链路层(Data Link Layer)、物理层(Physical Layer)。发送方向,数据从上层逐层封装;接收方向,数据从下层逐层解封装。抓包点不同,看到的报文形态也不同。
事务层负责生成和解析TLP(Transaction Layer Packet),处理Memory、IO、Configuration、Message四类事务,并管理流量控制Credit。数据链路层负责TLP的可靠传输,给TLP加上Sequence Number和LCRC,生成DLLP(Data Link Layer Packet)用于ACK/NAK和电源管理。物理层负责链路训练、字节条带、加扰、编码(8b/10b或128b/130b)以及有序集(Ordered Set)的收发。
三、三层职责与常见术语对照
三层职责可以用“封装—可靠—传输”来概括:事务层定义“做什么”,数据链路层保证“可靠地做”,物理层负责“把比特送过去”。下表列出抓包中最常遇到的术语及其所属层次。
| 术语 | 所属层次 | 作用与抓包含义 |
|---|---|---|
| TLP | 事务层 | 事务层包,含Header、Data、ECRC,是抓包分析的核心对象 |
| DLLP | 数据链路层 | 链路层包,用于ACK/NAK、电源管理,不携带事务数据 |
| LCRC | 数据链路层 | 链路CRC,校验TLP在链路上是否出错 |
| Sequence Number | 数据链路层 | TLP序号,用于ACK/NAK重传判断 |
| Ordered Set | 物理层 | 有序集,如TS1/TS2、SKP,用于链路训练与时钟补偿 |
| Credit | 事务层 | 流控信用,决定能否发送某类TLP |
| LTSSM | 物理层 | 链路训练状态机,决定链路能否进入L0 |
四、案例:一次NVMe读请求的抓包分层观察
假设主机通过RC向NVMe SSD发起一次内存读请求,抓包点分别放在Switch上游和SSD下游。上游看到的是RC发出的Memory Read TLP,下游看到的是Switch转发后的同一事务,但Sequence Number和LCRC可能不同,因为它们是逐链路维护的。若在物理层抓包,还会看到链路训练阶段的大量TS1/TS2有序集。
# 典型抓包过滤思路(伪代码)
filter = "TLP.Type == MemRd && TLP.Addr == 0xFE000000"
# 若看不到该TLP,先检查:
# 1) 链路是否处于 L0 状态(LTSSM)
# 2) Credit 是否耗尽导致发送阻塞
# 3) 是否被 Switch 错误路由到其他下游端口
五、常见误区与复盘
- 误区一:把Switch当成总线。Switch是点对点交换,每个端口独立链路,抓包必须明确抓的是哪条Link。
- 误区二:认为TLP全局唯一。Sequence Number和LCRC是逐链路维护的,同一事务在不同链路上编号可能不同。
- 误区三:忽略DLLP。很多链路级故障(如重传、电源状态切换)只体现在DLLP中,不看DLLP会漏掉关键证据。
- 误区四:只看事务层。链路训练失败、物理层误码等问题,在事务层根本看不到TLP,必须回到物理层。
复盘时建议按“拓扑定位链路 → 分层确认抓包点 → 逐层核对职责”的顺序进行。先明确抓的是哪条Link,再确认该Link上三层各自是否正常,最后才把现象归因到具体层次。这样既能快速缩小范围,也能让抓包结论经得起推敲。