👉个人主页:highman110
👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容
参考书籍:《深入浅出SSD:固态存储核心技术、原理与实战》
目录
前言
ACK/NAK协议基本原理
ACK/NAK DLLP报文组成
ACK/NAK的具体操作
前言
上篇文章我们提到了数据链路层DLLP有ACK/NAK类、电源管理类、流控类几种,今天讲一下ACK/NAK类DLLP。数据链路层就是依靠ACK/NAK DLLP和重传机制来确保TLP的正确传输。
ACK/NAK协议基本原理
数据链路层通过ACK/NAK协议来保证每个TLP的正确传输,其基本原理为:TLP发送端的数据链路层为每个TLP加上序列号和LCRC,在该TLP被接收端正确收到之前,它会一直保持在一个叫Replay Buffer的接口里面。TLP接收端的数据链路层接收到该TLP后,做CRC校验和序列号检查,如果没有问题,TLP接收端(可能,为了保证传输效率,通常不会每收到一个TLP就回一个ACK,而是会设置一个阈值,超过了阈值才会回ACK)会生成和发送ACK DLLP,TLP发送方接收到ACK后,知道TLP被正确接收,因此它会把相关的TLP从Replay Buffer中清除;如果TLP接收方检测到TLP有错误,则会生成和发送NAK DLLP,TLP发送方接收到NAK后,知道有TLP传输出错,会重新发送Replay Buffer相关的TLP给对方。TLP传输出错往往是瞬态的,重传基本能保证TLP传输正确。TLP接收方只有收到正确的TLP才会去掉序列号和LCRC,并把TLP交给它的事务层。
ACK/NAK DLLP报文组成
此类型的DLLP包含如下几个字段:
1、ACK/NAK类型,用来区分两种DLLP;
2、ACK/NAK序列号,用来告诉发送端哪个序列号被成功接收或接收错误;
3、CRC,生成本DLLP的校验码,用于接收端的DLLP校验。
ACK/NAK的具体操作
前面提到,发送端在收到ACK之前,会把之前已发送的DLLP内容保存在Replay Buffer中,就是为了防止万一某个包接收出错还可以重传。
假设当前发送端Replay Buffer中有序列号分别为10、11、12、13的4个TLP,即这些TLP发送出去了,但还没有得到响应。假设接收端上一个成功接收到的TLP序列号为11,期望下个接收到的TLP序列号为12。这时,接收端接收到一个TLP,首先,它会对该TLP做LCRC校验:
(1)校验失败
TLP接收端会发送一个NAK,其中AckNak_SEQ_NUM设为11。TLP发送端接收到该NAK后,知道11和它之前的TLP(这里是TLP 10)被成功接收,因此TLP 10和TLP 11会从Replay Buffer清掉(不需要重发)。同时,它知道12和后面的TLP(这里是TLP 13)没有被成功接收,因此它们会重发。
(2)校验成功
CRC没有问题,接下来就检查TLP的序列号了。这里有三种情况:
a、TLP接收端发现收到的TLP序列号为12,与预期相符。
TLP接收端可能需要发一个ACK,也可能不需要发ACK。为什么这么说?为减少数据链路层DLLP的传输,可能设置正确接收到若干个TLP后,才会返回一个ACK,并非每成功接收一个TLP,就返回一个ACK。假设这个时候需要返回ACK,则设AckNak_SEQ_NUM为12。TLP发送端接收到该ACK,知道TLP 12和它之前所有的TLP都被成功接收,因此TLP 10、TLP 11和TLP 12会从Replay Buffer清掉。
b、TLP接收端发现收到的TLP序列号为13,与预期不符(预期为TLP 12)。
TLP接收端希望接收到的TLP为12,这个时候收到的却是13,说明TLP 12在半路丢了,发生丢包。这个时候,接收端会发一个NAK,其中AckNak_SEQ_NUM设为11(即上一个成功被接收的TLP序列号)。TLP发送端接收到该DLLP后,知道TLP 11和它之前所有的TLP都被成功接收,因此TLP 10和TLP 11会从Replay Buffer清掉,并重发TLP 12和它后面的TLP(这里是TLP 13)。
c、TLP接收端发现收到的TLP序列号为10,与预期不符(预期为TLP 12)。
TLP上次正确接收到的是TLP 11,这次又收到一个序列号比它小的TLP,为什么会这样?原因是在TLP发送端,一个TLP在一定时间内没有收到ACK,它会自动重发所有Hold在Replay Buffer中的TLP。由于发送端的这个超时重发机制,导致一个TLP会被接收端接收到两次或者更多次(如果接收端一直不能及时响应)。TLP接收端如果收到重复的TLP包,它会默默扔掉这些重复的TLP,并发送ACK,其中的AckNak_SEQ_NUM设为11。TLP发送端接收到该DLLP后,知道TLP 11和它之前所有的TLP都被成功接收,因此TLP 10和TLP 11会从Replay Buffer清掉。
如下是数据链路层内部框图,从中我们可以看到ACK/NAK是怎样实现的: