来源: http://www.ssdfans.com/?p=3720
一个TLP,是怎样经历千山万水,最后顺利抵达目的地呢?
今天就以上图的简单拓扑结构为例,讨论一个TLP是怎样从发起者到达接收者,即TLP路由问题。
PCIe共有三种路由方式:基于地址(Address)路由,基于设备ID(Bus number + Device number + Function Number)路由,还有就是隐式(Implicit)路由。
不同类型的TLP,其寻址方式也不同,下表总结了每种TLP对应的路由方式:
TLP类型 |
路由方式 |
Memory Read/Write TLP |
地址路由 |
Configuration Read/Write TLP |
ID路由 |
Completion TLP |
ID路由 |
Message TLP |
地址路由或者ID路由或者隐式路由 |
下面分别讲讲这几种路由方式。
-
地址路由
前面提到,Switch负责路由和TLP的转发,而路由信息是存储在Switch的Configuration空间的,因此,很有必要先理解Switch的Configuration。
BAR0和BAR1没有什么好说,跟前一节讲的Endpoint的BAR意义一样,存放Switch内部空间在Host内存空间映射基址。
Switch有一个上游端口(靠近RC)和若干个下游端口,每个端口其实是一个Bridge,都是有一个Configuration的,每个Configuration描述了其下面连接设备空间映射的范围,分别由Memory Base和Memory Limit来表示。对上游端口,其Configuration描述的地址范围是它下游所有设备的映射空间范围,而对每个下游端口的Configuration,描述了连接它端口设备的映射空间范围。大家看看下面这张图,理解一下我刚才说的。(Range由Memory Base和Memory Limit限定)
前面我们看到,Memory Read 或者Memory Write TLP的Header里面都有一个地址信息,该地址是PCIe设备内部空间在内存中的映射地址。
-
当一个Endpoint收到一个Memory Read或者Memory Write TLP,它会把TLP Header中的地址跟它Configuration当中的所有BAR寄存器比较,如果TLP Header中的地址落在这些BAR的地址空间,那么它就认为该TLP是发给它的,于是接收该TLP,否则就忽略。
-
当一个Switch上游端口收到一个Memory Read或者Memory Write TLP,它首先把TLP Header中的地址跟它自己Configuration当中的所有BAR寄存器比较,如果TLP Header当中的地址落在这些BAR的地址空间,那么它就认为该TLP是发给它的,于是接收该TLP(这个过程与Endpoint的处理方式一样);如果不是,然后看这个地址是否落在其下游设备的地址范围内(是否在memory base 和memory limit之间),如果是,说明该TLP是发给它下游设备的,因此它要完成路由转发;如果地址不落在下游设备的地方范围内,说明该TLP不是发给它下面设备的,因此不接受该TLP。
刚才的描述是针对TLP从Upstream流到Downstream的路由。如果是TLP从下游往上走呢?
它首先把TLP Header中的地址跟它自己Configuration当中的所有BAR寄存器比较,如果TLP Header当中的地址落在这些BAR的地址空间,那么它就认为该TLP是发给它的,于是接收该TLP(跟前面描述一样);如果不是,然后看这个地址是否落在其下游设备的地址范围内(是否在memory base 和memory limit之间),如果是,这个时候不是接受,而是拒绝;相反,如果地址不落在下游设备的地方范围内,Switch则把该TLP传上去。
-
ID路由
在一个PCIe拓扑结构中,由ID = Bus number+Device number+Function Number(BDF)能唯一找到某个设备的某个功能。这种按设备ID号来寻址的方式叫做ID路由。Configuration TLP和Completion TLP(以C打头的TLP)按ID路由,Message在某些情况下也是ID路由。
使用ID路由的TLP,其TLP Header中含有BDF信息:
当一个Endpoint收到一个这样的TLP,它用自己的ID和收到TLP Header中的BDF比较,如果是给自己的,就收下TLP,否则就拒绝。
如果是一个Switch收到这样的一个TLP,怎么处理?我们再回头去看看Switch的Configuration Header。
看三个寄存器:Subordinate Bus Number,Secondary Bus Number和Primary Bus Number,看下图就知道这几个寄存器是什么意思:
对一个Switch来说,每个Port靠近RC(上游)的那根Bus叫做Primary Bus,其Number写在其Configuration Header中的Primary Bus Number寄存器;每个Port下面的那根Bus叫做Secondary Bus,其Number写在其Configuration Header中的Secondary Bus Number寄存器;对上游端口,Subordinate Bus是其下游所有端口连接的Bus 编号最大的那个Bus,Subordinate Bus Number写在每个Port的Configuration Header中的Subordinate Bus Number寄存器。
当一个Switch收到一个基于ID寻址的TLP,首先检查TLP中的BDF是否与自己的ID匹配,如匹配,说明该TLP是给自己的,收下;否则,则检查该TLP中的Bus Number是否落在Secondary Bus Number和Subordinate Bus Number之间,如果是,说明该TLP是发给其下游设备的,然后转发到对应的下游端口;如果其他情况,则拒绝这些TLP。
-
隐式路由
只有Message TLP才支持隐式路由。在PCIe总线中,有些Message是与RC通信的,RC是该TLP的发送者或者接收者,因此没有必要明明白白的指定地址或者ID,而是采用”你懂的”的方式进行路由,这种路由方式为隐式路由。Message TLP还支持地址路由和ID路由,但以隐式路由为主。
Message TLP的Header总是4DW,如下图所示:
Type字段,低三位,用rrr表示的,指明该Message的路由方式,具体如下:
当一个Endpoint收到一个Message TLP,检查TLP Header,如果是RC的广播Message(011b)或者该Message终结于它(100b),它就接受该Message。
当一个Switch收到一个Message TLP,检查TLP Header,如果是RC的广播Message(011b),则往它每个下游端口复制该Message然后转发;如果该Message终结于它(100b),则接受该TLP;如果下游端口收到发给RC的message,往上游端口转发便是。
上面说的是Message使用隐式路由的情况。如果是地址路由或者ID路由,Message TLP的路由跟别的TLP一样,不赘述。