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

2024-03-15 00:30

本文主要是介绍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。

 

 

 

 

这篇关于PCI Express学习篇---链路层(一)ACK/NAK协议介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810223

相关文章

Python中win32包的安装及常见用途介绍

《Python中win32包的安装及常见用途介绍》在Windows环境下,PythonWin32模块通常随Python安装包一起安装,:本文主要介绍Python中win32包的安装及常见用途的相关... 目录前言主要组件安装方法常见用途1. 操作Windows注册表2. 操作Windows服务3. 窗口操作

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

如何在Spring Boot项目中集成MQTT协议

《如何在SpringBoot项目中集成MQTT协议》本文介绍在SpringBoot中集成MQTT的步骤,包括安装Broker、添加EclipsePaho依赖、配置连接参数、实现消息发布订阅、测试接口... 目录1. 准备工作2. 引入依赖3. 配置MQTT连接4. 创建MQTT配置类5. 实现消息发布与订阅

使用Python进行GRPC和Dubbo协议的高级测试

《使用Python进行GRPC和Dubbo协议的高级测试》GRPC(GoogleRemoteProcedureCall)是一种高性能、开源的远程过程调用(RPC)框架,Dubbo是一种高性能的分布式服... 目录01 GRPC测试安装gRPC编写.proto文件实现服务02 Dubbo测试1. 安装Dubb

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)

《MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)》掌握多表联查(INNERJOIN,LEFTJOIN,RIGHTJOIN,FULLJOIN)和子查询(标量、列、行、表子查询、相关/非相关、... 目录第一部分:多表联查 (JOIN Operations)1. 连接的类型 (JOIN Types)

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.