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 树形拓扑与点对点链路 Root Complex CPU / 内存子系统 Link PCIe Switch 虚拟PCI-PCI桥 Endpoint NVMe SSD Endpoint 网卡 NIC PCIe-to-PCI 桥 兼容旧设备 PCI 设备 说明:每条连线均为独立点对点 Link;Switch 只转发,不产生新事务。

二、分层架构:事务层、数据链路层、物理层

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)的收发。

抓包视角:协议分析仪若接在物理层,能看到有序集、SKP、TS1/TS2;若在链路层解析,能看到DLLP和带LCRC的TLP;若在事务层解析,则看到去掉LCRC后的TLP及其Header、Data Payload。

三、三层职责与常见术语对照

三层职责可以用“封装—可靠—传输”来概括:事务层定义“做什么”,数据链路层保证“可靠地做”,物理层负责“把比特送过去”。下表列出抓包中最常遇到的术语及其所属层次。

术语 所属层次 作用与抓包含义
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 错误路由到其他下游端口
实用技巧:定位“事务丢失”时,先确认物理层链路是否L0,再看数据链路层是否有NAK重传,最后才怀疑事务层路由或配置空间映射。自下而上排查,能避免在错误层次浪费时间。

五、常见误区与复盘

  • 误区一:把Switch当成总线。Switch是点对点交换,每个端口独立链路,抓包必须明确抓的是哪条Link。
  • 误区二:认为TLP全局唯一。Sequence Number和LCRC是逐链路维护的,同一事务在不同链路上编号可能不同。
  • 误区三:忽略DLLP。很多链路级故障(如重传、电源状态切换)只体现在DLLP中,不看DLLP会漏掉关键证据。
  • 误区四:只看事务层。链路训练失败、物理层误码等问题,在事务层根本看不到TLP,必须回到物理层。

复盘时建议按“拓扑定位链路 → 分层确认抓包点 → 逐层核对职责”的顺序进行。先明确抓的是哪条Link,再确认该Link上三层各自是否正常,最后才把现象归因到具体层次。这样既能快速缩小范围,也能让抓包结论经得起推敲。