4.5 举几个例子来说一下PCIE链路层如何保证可靠传输的


这是剖析PCIE协议的第17篇文章

内容简介

2024-01-29

全文共1883字,阅读大约需要6分钟前面的三篇文章介绍了Ack/Nak的处理方法,本节就列举几个示例来感受下这种处理方法。并且对Ack/Nak机制做些补充说明,本文示例均来在《PCI Express Technology》。


    如下是发送端和接收端数据链路层的完整处理流程,结合上两篇文章可以再感受下。

    其中下图的AckNak_LATENCY_TIMER、REPLAY_TIMER等词的代表的功能模块可看上两篇文章。




01

正常的处理逻辑



1、设备A发送TLP的序列号为3、4、5、6、7


2、设备B成功接收了TLP3,启动AckNak_LATENCY_TIMER,


3、在AckNak_LATENCY_TIMER计满之前设备B成功收到TLP4、5


4、设备BAckNak_LATENCY_TIMER计满,发送Ack包给设备A,包的序列号为5


5、设备A收到Ack包后重置REPLAY_TIMER和REPLAY_NUM计数,由于收到的是Ack包,表明设备B是成功接收的,故将缓冲区里面的TLP3、4、5清除


6、设备B接收TLP6、7,AckNak_LATENCY_TIMER计满发送Ack包,序列号为7,设备A清除缓冲区里的TLP6、7数据包




02

正常逻辑,体现了序列号归零



1、设备A缓冲区有TLP4094、4095、0、1、2共5个TLP包,其中4094是发送的第一条TLP包,2是最后一条


2、设备B成功接收了序列号为4094、4095、0、1的TLP,在接收4094时启动了AckNak_LATENCY_TIMER,在计数计满之前已经接收了4095、0和1,TLP2在路上


3、由于AckNak_LATENCY_TIMER计满,设备B发送一个带有序号1的Ack给到设备A,已确认之前的数据以收到


4、设备A成功接收Ack,将缓冲区序号为4094、4095、0、1的TLP清除,并重置REPLAY_TIMER和REPLAY_NUM计数


5、设备B随后收到了TLP2,校验、检查通过也会给到事务层,待计时到了反馈Ack。



03

发送端收到了Nak的处理过程



1、设备A传输序列号为4094、4095、0、1和2的TLP包


2、设备接收到了序列号为4094的TLP包没有错误,将NEXT_RCV_SEQ置为了4095,并启动AckNak_LATENCY_TIMER的计数


3、设备B收到下一个序列号为4095的TLP包时检测到CRC错误,将NAK_SCHEDULED标志位置位,并发送一个Nak包,其携带的序列号为4094。这个Nak包不会等AckNak_LATENCY_TIMER的计满启动,而且Nak包会暂停并重置AckNak_LATENCY_TIMER。


4、设备B继续检测收到的TLP包,寻找有没有4095,此时设备A还不知道设备B没有收到序列号为4095的TLP,已经发送了TLP为0、1、和2的TLP包,设备B会接收这些数据包,但设备B会忽略掉,无论这些包有没有问题。但也不会额外发送Nak包,会等到收到期望的包才会把NAK_SCHEDULED标志清除,进入正常流程。


5、设备A收到Nak发现序列号为4094,就知道序列号为0、1、和2的TLP包白发了,会重新发这些包,并重置REPLAY_TIMER和REPLAY_NUM


6、由于设备A收到的是Nak,而不是Ack,所以REPLAY_NUM会加一,表示已经重新发了一包数据了。


7、设备B收到重发的4095数据包,会清除NAK_SCHEDULED标志,增加NEXT_RCV_SEQ计数,启动AckNak_LATENCY_TIMER计时。



04

接收端发现丢包了



1、设备A发送序列号为4094、4095、0、1和2的TLP包


2、设备B成功接收序列号为4094的TLP包,AckNak_LATENCY_TIMER启动计时,NEXT_RCV_SEQ加一


3、设备B成功接收TLP00后,AckNak_LATENCY_TIMER计到预定时间,发送Ack包,携带的序列号为0


4、设备A收到Ack,看到序列号为0,清除序列号为4094、4095和0的TLP


5、TLP1由于某些原因丢失,TLP2给到了设备B,但这时候设备B期待序列号为1的TLP,所以序列号不匹配,设备B丢弃该TLP,并将NAK_SCHEDULED标志位置位,发送Nak包,携带的序列号为0


7、设备A收到Nak后,重放序列号为1、2的TLP


8、设备B收到TLP1后将NAK_SCHEDULED标志位复位,并将TLP上推给



05

对Nak的处理的几点说明


1、首先要说的是,发送端收到Nak表示接收端收的有问题了,


2、发送端收到Nak,并不表示之前发送的都有问题,发送端会根据序列号判断一下


3、例如,发送端发送了序列号为2、3、4、5、6这5包数据,收到的NAK携带序列号为4,那么接收端会从缓冲区将序列号为2、3、4的清除,然后重新发送序列号为5和6的TLP


4、发送端的REPLAY_TIMER和REPLAY_NUM计数均会被重置,并将AckD_SEQ寄存器加载为Nak中的序列号。


5、在重发缓冲区TLP包时,发送端会阻塞事务层发送新的TLP包,直到重发完成


6、重发过程收到Ack或Nak是必须被处理的,可以在重发开始或结束时处理对应的Ack或Nak数据包,来清除一些接收方已经收到的数据包,减少重复的TLP条数。


7、需注意,TLP一旦启动是不可打断的。



06

如果重发解决不了问题怎么办


如果重播不能解决问题,则是一种新的情况,接收端已经将NAK_SCHEDULED置位,在正确的接收TLP之前是不会发送任何Ack或Nak的,这是防止卡死就需要REPLAY_TIMER所具备的机制,当重播完TLP包后会启动计时,如果一直没有收到TLP包就会因计满溢出而启动再次重播TLP包,并将REPLAY_NUM加一,如果REPLAY_NUM累加到3后依旧没有收到响应,REPLAY_NUM溢出会触发物理层的链路重新训练。但缓冲区里的内容会被保留,不会初始化链路,训练完成后发送端在启动相同的过程。如果一直都有问题会怎么办,协议没有给出要求,有些情况就卡死了



07

关于Replay Timer补充


    REPLAY_TIMER是为了确保TLP包及时的得到确认,当计数溢出时,表明发送端认为到点了,ACK或Nak不来说明出问题了,发送端能做的就是再发一遍。


1、如果计时器尚未开始运行,TLP包的最后一个数据发完后计数器启动


2、当计时器满足以下条件,计时器将被重置并重新启动

1)收到Ack,清楚以送到的TLP包后Buffer里还有TLP包

2)发送重播事件,第一个TLP包发送完成后启动


3、当满足以下条件会被重置

1)每条TLP包发送,Buffer时空的

2)收到Nak,重播第一个TLP之后

3)计数器溢出

4)数据链路层处于非活动状态

5)链路正在重新训练


    这个计数器的计数值不能拍脑门决定,是由最大长度载荷与链路位宽共同决定,该值应为Ack/Nak延时的三倍。


欢迎关注公众号点击【资料下载】领取相关资料








快来扫描下方二维码关注公众号,领取站内所有相关资料,所有哦~

有建议、有需求、有疑问、联系我

<