PCI Express学习篇---链路层(一)ACK/NAK协议介绍

声明:此文章为原创,转载请注明 转自https://blog.csdn.net/weixin_48180416/article/details/117390013

数据链路层是为了保障TLP包的可靠传输,尽管Spec中规定了误码率小于10^-12,但是仍然会发生错误带来一些问题,单个bit的错误会使整个数据包被损坏。速率的提升会使这个问题更加显著。

为了实现链路层的保护,引入错误检测的编码---LCRC,计算范围是Sequence Number+TLP header+payload+ECRC。

接收端需要检查LCRC是否正确,Sequence Number是否正确,Receiver端通过ACK包告知接收到了正确的TLP包,通过NAK告知接收到了错误的TLP包。

以下介绍实现ACK/NAK协议的组件


发送端:

  • NEXT_TRANSMIT_SEQ: 记录下一个要发送的Sequence Number的值,最大值是4095之后会回0;
  • LCRC Generator: 产生32bit CRC, 计算范围包含TLP和Seq;
  • Replay Buffer: 按照发送的顺序存储TLP,包含Seq(2B)+Header(up to 16B)+Optional Payload(up to 4KB)+Optional ECRC(4B)+LCRC(4B),当收到ACK时会清除replay buffer内Seq小于或等于ACK包Seq的TLP,设计中允许一个ACK代表多个成功的TLP;当收到NAK时会清除replay buffer内Seq小于或等于NAK包Seq的TLP(因为NAK记录的是最后一个正确TLP的Seq),然后重传replay buffer中的所有TLP;
  • REPLAY_TIMER: 实质上是一个看门狗计数器,当timeout时还是没有收到ACK/NAK包就会replay并且restart;
  • REPLAY_NUM: 2bit Counter, 记录重传的次数,当从11 roll over到00(说明replay了4次),数据链路层就会自动force物理层重新训练状态机(LTSSM会进入Recovery状态);
  • ACKD_SEQ: 12bit寄存器,存储着最近收到的ACK/NAK的Seq,如果收到的ACK/NAK是"later Sequence Number"(可能存在4095->0 roll over的情况)可以认为是forward progress, 这个时候就可以清除replay buffer里面的TLP(replay buffer Seq <= ACK/NAK Seq),复位REPLAY_TIMER和REPLAY_NUM;
  • DLLP CRC Check: 检查DLLP的16bit CRC, 如果检测到错误,DLLP会丢弃并且会报告Correctable Error,DLLP包没有重传和校正的机制,只能期待下一个成功的ACK/NAK DLLP。

注:NEXT_TRANSMIT_SEQ - ACKD_SEQ不允许大于总Counter的一半,例如NEXT_TRANSMIT_SEQ - ACKD_SEQ = 2048时,链路层就不会从事务层接收TLP,直到有新的回应。如果发生了超过一半的情况,数据链路层会报告protocol error。

接收端:

收到的TLP会先检查LCRC错误,然后检查Sequence Number。如果没有错误的话TLP会传递到事务层,如果有错误,TLP会丢弃并且scheduled NAK除非已经有NAK outstanding。

  • LCRC Error Check:检查LCRC错误,如果计算的LCRC和TLP的LCRC不匹配,说明TLP中有bit错误,就会丢弃TLP并且发NAK;
  • NEXT_RCV_SEQ(NRS): 12bit计数器,跟踪下一个期待接收的Seq Num, TLP有CRC错误或无效包("nullified")或Seq Num Check有错误,就不会传到事务层,并且不会增加这个计数器;
  • Sequence Number Check:检查完LCRC OK后,检查接收的TLP Seq Num与NRS是否一致,存在以下三种情况:
  1. TLP Seq Num equal NRS:Good TLP,是正确的情况,当AckNak_LATENCY_TIMERS expire时,发送ACK包,包含最后一包good TLP的Seq Num(即NRS-1);
  2. TLP Seq Num earlier than NRS: Duplicate TLP,是以前发送过的重复包,NRS - TLP Seq Num不超过2048,不认为是错误,silently dropped并且发送一个带有Seq Num为(NRS-1)的ACK包;
  3. TLP Seq Num later than NRS: Invalid TLP,发生丢包的情况,会发送Nak,如果没有Nak outstanding。

由于4095后Seq Num会roll over,所以实际的范围是这样定义的:(以NRS=30/31/32为例)

  • NAK_SCHEDULED Flag: 当接收端schedule NAK的时候会置此标志位为1,当成功发送了一个带有Seq Num为(NRS-1)的NAK包后清零。目的是有outstanding NAK就不需要再发送NAK包;
  • AckNak_LATENCY_TIMER:接收到一个正确TLP后开始计数,当timer expire会发送一个带有Seq Num为(NRS-1)的ACK包,当发送了ACK或NAK包后复位;
  • Ack/Nak Generator: ACK/NAK中的Seq Num都是NRS-1,格式如下:

发送接收端具体实现细节


发送端:

  • Sequence Number:从事务层发往链路层,首先需要加入Sequence Number,Seq Num可能会roll over;
  • 32bit LCRC: 加入LCRC,范围是Seq Num+TLP;
  • Response to ACK DLLP: 把收到的ACK的Seq load到ACKD_SEQ中,复位REPLAY_TIMER和REPLAY_NUM,清除Replay buffer中的<=SEQ NUM的TLP;
  • Response to NAK DLLP:把收到的NAK的Seq load到ACKD_SEQ中,复位REPLAY_TIMER和REPLAY_NUM,清除Replay buffer中的<=SEQ NUM的TLP,重放buffer中剩余的包;

接收端:

  • Physical Layer: TLP接收在物理层检测到receiver error(framing,disparity, invalid symbols)如果告知链路层,链路层发NAK包并重放TLP包,如果不告知链路层,链路层也会因为Seq Num丢包而发NAK包并重放TLP包;
  • LCRC Check:检查LCRC错误,如果计算的LCRC和TLP的LCRC不匹配,说明TLP中有bit错误,就会丢弃TLP并且发NAK;
  • Next Received TLP's Sequence Number: 如果LCRC正确,会比较接收到的TLP的Seq Num和NRS;
  • Receiver Schedules a ACK:  AckNak_LATENCY_TIMER expire后发送一个ACK,含有NRS-1的Seq Num;
  • Receiver Schedules a NAK: 虽然发送端需要立刻发送NAK(因为后面的接收的其他TLP也会丢弃),但是其他的已经再处理的TLP, DLLP, Order Set优先级更高,NAK会等到它们都完成再发,同时,如果其他接收的TLP丢弃,由于NAK_SCHEDULED flag=1,就不会再有额外ACK/NAK schedule。

Replay Number Rolls Over


当REPLAY_TIMER由于没有接收到ACK或NAK而expire,replay过程可以被重复3次,如果重复大于3次,REPLAY_NUM就会从3 roll over至0.

  • 如果发生这种情况一定是链路存在一些问题,链路层就会触发物理层重新训练链路(LTSSM进入Recovery状态机);
  • 如果使能AER会报Replay Number Rollover error错误;
  • Replay Buffer的内容会保持,数据链路层不会初始化(只是重新训练链路,不会复位链路);
  • 当链路训练完成后,transmitter会再重放,以期望问题能够解决;
  • Spec没有规定如何处理repeat rollover event, PCIe Technology3.0建议记录重新训练的次数,超过规定的次数后,通过Uncorrectable Fatal Error或者中断通知软件。

Transmitter DLLP Handling


Ack/Nak Error Checking模块检查ACK/NAK DLLP的16bit CRC是否存在错误,

  • 如果存在错误,DLLP会丢弃,DLLP包没有重传和校正的机制;
  • AER会报告Correctable Error;
  • 会使ACK之间的间隔变大,REPLAY_TIMER可能会expire,导致TLP replay。

Error Situations Handled by Ack/Nak


  • LCRC错误
  • TLP Losts(物理层检测到错误后丢包)
  • Ack/Nak包损坏
  • 没有接收到Ack/Nak包
  • Receiver fails to send Ack/Nak

上述情况的详细处理过程见(二)ACK/NAK实例博文。

Switch Cut-Through Mode


当TLP经过Switch的Ingress Port的时候,当没有收到TLP的整包的时候是没有办法判断LCRC是否正确的,通常情况下用到Store-Forward模式缓存整包,没问题再送到Egress Port,但是这样的情况大包会有很大的Latency,会影响性能。

为了提高性能可以采用Cut-Through模式,这种模式下Ingress Port可能会将TLP传给Egress Port后才会发现LCRC错误。

Cut-Though Mode提供一个解决方案:“nullified” TLP

  • 这种TLP的LCRC是invert(按位取反)+EDB;
  • 这种TLP本质上处理的时候“好像不存在一样”;
  • 在Egress Port,不存入replay buffer,NEXT_TRANSMIT_SEQ回滚-1;
  • 接收端的NRS不增加,AckNak_LATENCY_TIMER不启动, NAK_SCHEDULED不设置;
  • 接收端只是简单的丢弃此包,不需要返回ACK/NAK。

 

 

 

 

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值