欢迎关注同名微信公众号“modem协议笔记”。
这篇是RLC AM mode的相关内容,RLC的ARQ是一种重传机制,其实NR三个不同的协议层MAC(HARQ)、 RLC(ARQ)和PDCP都有重传功能。为什么三层协议都需要具备重传功能?早期也有思考过这个问题,这里引用5G NR The Next Generation Wireless Access Technology中的一段话来解释这个问题。
MAC层HARQ机制的目标是实现快速重传,因此,在UE收到TB后需要对DL的接收情况进行HARQ ACK/NACK的反馈,而对于UL传输,则没有类似HARQ-ACK的显式反馈机制,主要原因是UL场景中,网络侧既是接收侧也是data的调度端,网络侧通过DCI 中NDI就可以指示UE是否需要进行重传。虽然HARQ可以达到一个非常低的错误概率,但是HARQ是以牺牲传输资源作为代价。有些情况这种做法就不太试用,一个明显的例子就是超可靠低时延的数据传输的场景,在这种情况下,要么需要降低反馈错误率,要么必须接受反馈信令增加的成本,或者在不依赖反馈信号的情况下进行额外的重传,但是这样就会降低频谱效率。低错误率不仅是URLLC类型服务的关注点,而且从数据速率的角度来看也很重要。TCP 的高数据速率可能需要将数据包几乎无错误地传送到 TCP 层。如ACM/IEEE Trans TCP reno performance: a simple model and its empirical validation133–145所述,对于可持续的数据速率超过 100Mbit/s的情况,需要小于 10^-5 的丢包概率。
与HARQ 确认相比,RLC Status report的传输频率相对较低,获得 10^-5或更低可靠性的成本比较小。将HARQ和RLC ARQ两种重传机制组合在一起就可以取得RTT足够小且反馈开销适度的效果,所以两个机制相互补充,HARQ负责快速重传,RLC ARQ现实数据包的可靠传送。
为什么PDCP仍然具备重传的功能?主要原因是PDCP重传主要用于inter-gNB切换场景。切换时,未送达的下行数据包将通过PDCP由从旧 gNB 转发到新 gNB。这种情况下,在新gNB中会建立新的 RLC entity以及HARQ entity,这样原有的RLC状态就会丢失。PDCP重传功能可以确保在切换过程中没有数据包丢失。在UL,因为HARQ buffer在切换时会被刷新,UE的PDCP entity将处理之前所有为传输给gNB的UL数据包。
下面开始看下本篇NR RLC AM mode的具体内容,除此之外有将几个其他的琐碎知识点放在最后。
AM data transfer 发送端
AM RLC entity的发送端要优先处理RLC control PDU。AM RLC entity传输端也要优先传输包含先前传输过的RLC SDU或RLC SDU segment的AMD PDU(比如重传场景),后面再处理新的要传输的 RLC SDU 或 RLC SDU segment的 AMD PDU。
AM RLC entity的发送端要根据TX_Next_Ack维护发送窗,发送窗对应的SN范围为[TX_Next_Ack,TX_Next_Ack+AM_Window_Size),只有TX_Next_Ack 更新,发送窗才会更新,如果TX_Next_Ack长时间不更新(例如收不到网络侧的postive ack),在发送窗范围内的SN发送完后,UE就不能继续发送新的data,即window stalling。
AM mode TX_Next本身是发送状态的变量,保存的是下一个新生成的 AMD PDU 的 SN 值。初始设置为 0,并且每当AM RLC entity构造一个SN= TX_Next 的 AMD PDU 其包含一个RLC SDU 或一个 last segment RLC SDU 时,该变量就会更新。从PDCP收到RLC SDU后,AM RLC entity应该将其与当前TX_Next的SN相关联,将新生成AMD PDU的SN设置为TX_Next对应的值;之后TX_Next +1,指向下一个要产生的SN。
TX_Next的这种自增方式主要和AM RLC SN的规定有关,对于AM RLC, sn是以RLC SDU为单位递增的,即每个RLC SDU有唯一的SN,一个RLC SDU要进行分段,分段后的每个segment的SN和原始的RLC SDU SN相同。
如上图,SRB UL RLC发送的log 打印,UE发送了6个RLC PDU,分别是SN=3,4,5,6 的RLC SDU,因为UL grant不足,SN=4 的RLC SDU 被分成三个segment,通过SI可以看出具体segment信息,分别是first segment,中间部分的segment及last segment,后面的SO字段指示各个RLC SDU segment的第一个字节在原始RLC SDU中所对应的位置,3个segment的SN都是4,正如上述TX_Next 自增的规定。
当向MAC层提交包含segment RLC SDU的 AMD PDU 时,AM RLC entity发送端应将AMD PDU的SN设置为相应RLC SDU的SN。
AM RLC entity发送端可以通过从对端AM RLC entity接收STATUS PDU的方式来确定相关 RLC SDU 的positive ack(代表对端AM RLC entity有成功接收):
当接收到SN = x 的 RLC SDU positive ACK时,AM RLC entity发送端应向PDCP发送 RLC SDU 成功传递的指示;将 TX_Next_Ack 按顺序递增,将其设置为当前最小的还没有收到ack 的RLC SDU SN, 这个SN需要在[TX_Next_Ack,TX_Next]区间范围内。
比如 TX_Next_Ack=1 TX_Next=7,其中只有SN 2和4 收到positive ack,接下来通过对端的STATUS PDU 收到了SN 1和5的positive ack,UE发送了SN=7的RLC AMD PDU,那要更新发送窗,新发送窗的最低边界TX_Next_Ack=3,而TX_Next=8。
AM data transfer 接收端
AM RLC entity接收端会根据RX_Next维护一个接收窗,接收窗的范围对应[RX_Next,RX_Next+AM_Window_Size)。当从MAC 收到AMD PDU时,AM RLC entity接收端会根据场景将收到的AMD PDU discard或者将其放置在接收buffer中;对于处于接收buffer中的AMD PDU,会对状态变量进行更新,将AMD PDU重组后传递给PDCP,并根据需要start/stop t-Reassembly。t-Reassembly超时,AM RLC entity的接收端要更新对应的状态变量并将根据需要start t-Reassembly。
这种由下边界RX_Next推动更新的窗口机制,就是所谓的push窗口;而UM mode接收端的由上边界RX_Next_Highest驱动的更新reassembly window的机制,就是所谓的pull窗口。采用不同的机制,主要也是由各自的特性确定的,例如UM更多考虑实时性,AM更多考虑可靠性等。
AM接收端从MAC收到AMD PDU时要进行判断,以便丢弃没用的数据,将有用的数据放入buffer后,再进行数据的重组及向PDCP的转发。主要涉及过程就是接收到AMD PDU的SN与接收窗状态变量的比较。
从MAC收到AMD PDU时
当从MAC收到AMD PDU时,AMD PDU 包含 SN = x 的 RLC SDU 的segment number y ~ z,AM RLC entity接收端应按照下面的情况处理:
(1)如果 x 落在接收窗口之外或者如果之前收到过SN=x的RLC SDU 的segment number y ~ z,就丢弃收到的 AMD PDU。
(2)其他情况就将收到的AMD PDU放入接收buffer;如果某些segement之前接收到过,要丢弃重复的segment。
接收buffer中有AMD PDU时
对于放置在接收buffer中SN = x 的AMD PDU,
(1)如果 x >= RX_Next_Highest,将 RX_Next_Highest 更新为 x+ 1。
(2)如果收到SN = x RLC SDU 的所有字节,将SN = x 的 AMD PDU重组成RLC SDU,remove RLC header,并将重组的RLC SDU 传送到PDCP;
如果此时x = RX_Highest_Status,将 RX_Highest_Status 更新为第一个大于当前RX_Highest_Status的尚未收全RLC SDU 的SN;如果此时x = RX_Next,就将 RX_Next 更新为第一个大于当前RX_Next且尚未接收到所有字节的RLC SDU的SN。
例如最初RX_Next=1 RX_Next_Highest=7,黄色代表收全的SN,绿色代表未收全的SN,下面收到了SN=7 AMD PDU 的segment,但是SN=1的 PDU还没有收全,下一步 RX_Next_Highest=8。
假如最初RX_Next=1,RX_Next_Highest=7,RX_Highest_Status=1 ,此时SN 2和4已经收全;下面收到了SN=7 AMD PDU 的segment,并且SN=1 的AMD PDU也收全了,此时RX_Next=3,RX_Next_Highest=8,RX_Highest_Status=3,由于RX_Next=3,此时AM接收窗也向前移动了2个SN。
t-Reassembly
假如t-Reassembly 正在运行,如果 RX_Next_Status_Trigger = RX_Next或者RX_Next_Status_Trigger = RX_Next + 1(此时RX_Next对应SN的SDU所有收到segment的最后一个byte之前没有缺失的segment)或者
RX_Next_Status_Trigger 落在接收窗之外并且 RX_Next_Status_Trigger不等于 RX_Next + AM_Window_Size,就要停止并reset t-Reassembly。
RX_Next_Status_Trigger对应t-Reassembly 状态变量,该状态变量保存的是触发 t-Reassembly的 RLC SDU SN 的下一个 SN。
上图对应的就是t-Reassembly run期间要stop并reset t-Reassembly的三个场景举例。
假如t-Reassembly没有运行(包括 t-Reassembly 由于上述操作而停止的情况),如果RX_Next_Highest > RX_Next +1或者RX_Next_Highest = RX_Next + 1(此时RX_Next对应SN的SDU所有收到segment最后一个byte之前至少有1 byte segment缺失),就要开启t-Reassembly并将RX_Next_Status_Trigger设置为RX_Next_Highest。
如上图场景t-Reassembly没有运行,RX_Next_Highest > RX_Next +1,这时候将RX_Next_Status_Trigger更新到RX_Next_Highest=7的位置。
t-Reassembly 超时
假如t-Reassembly超时,将RX_Highest_Status更新为第一个大于等于RX_Next_Status_Trigger且还没有收全的 RLC SDU SN;
如果RX_Next_Highest>RX_Highest_Status +1或RX_Next_Highest=RX_Highest_Status+1 (此时RX_Highest_Status对应SN的SDU所有收到segment最后1 byte之前至少有1 byte segment缺失),就start t-Reassembly并将 RX_Next_Status_Trigger设置为 RX_Next_Highest。
如上图假如RX_Next_Highest >RX_Highest_Status +1,要开启t-Reassembly,然后再将RX_Next_Status_Trigger更新到RX_Next_Highest=7的位置。
假如RX_Next_Highest =RX_Highest_Status +1,其中RX_Highest_Status对应SN 6 的SDU所有收到的segment最后1 byte之前至少有1 byte segment缺失,要开启t-Reassembly,然后再将RX_Next_Status_Trigger更新到RX_Next_Highest=7的位置。
ARQ procedures
ARQ(Automatic Repeat request) procedures是AM RLC entity特有过程 ,UM 和TM都没有ARQ。
重传丢失的PDU也是RLC AM mode 主要功能之一。大多数错误可以由HARQ处理,而ARQ是第二级重传机制,作为HARQ的补充。AM RLC接收端可以检查接收到PDU的数量,如果发现有PDU丢失,就可以通过STATUS report的方式请求对端发送端重传相应data。
下面就看看ARQ是怎么进行重传的。
AM RLC entity发送端可以通过接收对端AM RLC entity的STATUS PDU,然后来确定对端RLC接收端是否存在某些RLC SDU或segment接收失败的情况 。
当收到NACK,如果NACK 对应 RLC SDU 的 SN 落在 TX_Next_Ack <= SN < = 交给MAC层发送的最大AMD PDU SN value的范围内,就要将对端报NACK的SN 对应的RLC SDU 或segement进行重传。这段话的描述就是ARQ的大概过程。
对于要进行重传的RLC SDU或segment,如果 RLC SDU或segment是第一次重传,将与该RLC SDU关联的 RETX_COUNT初始化为0;如果对应的RLC SDU或segment送出去了,但是在STATUS PDU中又收到了NACK,RLC 就会再次进行重传,此时将RETX_COUNT++。
每个 RLC SDU 都会维护一个 RETX_COUNT计数器;如果RETX_COUNT = maxRetxThreshold就要指示上层已达到最大重传,这时候就引起rlc max numRetx进而导致RLF。
当在进行RLC SDU或segment的重传时,根据MAC 层提供的UL grant大小,UE可以对 RLC SDU 或 RLC SDU segment进行分段(比如UL grant不足以发送时),生成一个MAC足够发送的New AMD PDU,交给MAC 层。
形成新的 AMD PDU 时,AM RLC entity发送端仅会将原始RLC SDU 或 RLC SDU segment映射到新 AMD PDU 的Data field并根据具体情况设置new AMD PDU的header。
Polling
AM RLC entity发送端可以通过poll的方式要求对端RLC entity发送STATUS report,以便知晓对端RLC SN 的ack nack情况,进行重发或者更新发送窗,具体的是在发送的AMD PDU中设置 p bit 为1,具体场景如下述。
在MAC层通知传输机会后,对于提交传输的每个AMD PDU,如果包含未传输过的RLC SDU或者segment,这时AM RLC entity发送端要将PDU_WITHOUT_POLL +1;将 BYTE_WITHOUT_POLL 加上 AMD PDU data field中对应的新传 byte;
如果 PDU_WITHOUT_POLL >= pollPDU或BYTE_WITHOUT_POLL >= pollByte,就要在AMD PDU 中包含一个poll bit。
在MAC层通知传输机会后,对于提交传输的每个 AMD PDU,
如果传新传和重传buffer都为空(不包括等待ack的已经发送的 RLC SDU 或segment);或者在传输完AMD PDU后,没有新的RLC SDU可以传输的情况下(例如发送窗满了,不能继续发送新的RLC SDU,需要TX_Next_Ack更新后,才能发送新的RLC SDU,这时候就需要对端的STATUS report),这时候就要在 AMD PDU 中包含一个poll。
在AMD PDU中包含poll的方法,就是将 AMD PDU 的 P field置为“1”;然后还要将 PDU_WITHOUT_POLL和BYTE_WITHOUT_POLL 设置为 0,以便后续poll的生成。
在向MAC层提交包含poll的AMD PDU后,AM RLC entity发送端要将 POLL_SN设置为提交给MAC层的 AMD PDU 中最高的SN value;如果t-PollRetransmit没有运行,就启动t-PollRetransmit,否则 就重启t-PollRetransmit。
在收到来自对端RLC AM entity的 STATUS report后,如果STATUS report包含 POLL_SN 对应RLC SDU 的ack或nack,就停止并重置 t-PollRetransmit(如果 t-PollRetransmit 正在运行)。
在 t-PollRetransmit 超时后,如果新传和重传buffer都为空(不包括等待ack的已经发送的 RLC SDU 或segment);或者在传输完AMD PDU后,没有新的RLC SDU可以传输的情况下(例如发送窗满了,卡住了),就将highest SN提交给MAC 重发,或者重传任意没有收到ack的RLC SDU。这种情况下也要在 AMD PDU 中包含一个poll,要对端发送STATUS report。毕竟UE发送端之前已经通过poll要了对端的STATUS report,但是对应t-PollRetransmit超时,UE就会接着要;这里可以看出在t-PollRetransmit运行期间,不能多次触发poll,t-PollRetransmit超时后,才能新的poll过程。
这里先看一个RLC AM DL接收的例子,log是一个VONR场景,一般voice场景更注重实时性会采用RLC UM mode,但是也有例外,之前LTE时代也有voice用RLC AM mode的情况,在网络状况良好的情况,也没什么问题,网络状况差就另说了,下面这个例子正好对应5G场景下voice用RLC AM mode的情况,简单看下 。
一开始建立起PDU session 2,其qfi 4相关配置用于IMS signalling的传输(5qi=5),对应DRB5 LCID 5,AM mode。
上图是RRCReconfiguration中相关的RLC配置参数的打印。
之后进行VONR通话,配置了qfi 7 用于voice的传输,对应DRB6 LCID 6,RLC AM mode。
上图是RRCReconfiguration中相关的voice DRB RLC配置参数的打印。
之后可以看到RLC AM mode发送端的4个参数的变化,RX_Next始终等于RX_Next_Highest,即当前所有的RLC PDU都收全了,并传递给了PDCP,对应的是接收状况最佳情况,类似下图的场景。
上面是一个RLC AM mode DL接收正常的例子,至于其他情况,还需要根据RLC AM mode发送端的4个参数的变化,具体情况具体分析,这里就不一一举例了。
再看一个UL的问题,UE在发送RRCSetup Complete时,UL RLC一直收不到sn ack,导致重发到达最大次数,引起RLF,下面看下log中RLC相关过程。
在RRC setup中配置下来SRB1,后面的RRCSetup Complete要通过SRB1 发送,由于RRC setup中没有配置RLC级别的参数,这时候就要应用38.331中SRB1的默认配置,如上橙色框中对应的参数。
紧接着通过上图就可看到SRB1 RLC的相关参数配置,例如sn length=12bit, max retx threshold =8等等,后面RLC entity就发送了SN=0的AMD PDU,TX_Next_Ack=0,说明在等网络侧通过STATUS report回复sn=0的ack,TX_Next=1代表下一个新产生的AMD PDU的SN。通过上面的RLC header SN=0 SI=00可以看出发送的SN=0对应的AMD PDU 是个完整RLC SDU;通过 P =1 说明 有进行 poll STATUS report;通过NEW_TX/RE_TX/RE_TX/RE_TX,可以看到UE一直在重传 SN=0 的PDU,log中一共打印了8次RE_TX,正好对应max retx threshold =8,后面就以RLCUL MAX RETX 触发了RLF。
通过RLC UL Stats的打印,也可以看出进行了8次PDU 的Retx,后面看到期间一个status pdu都没有收到,也就是没有收到STATUS report。
最后再关注下为什么在第一次new tx sn=0 时,RLC header就带上了P(Polling bit)=1,即Status report is requested。印象最深刻的触发Polling的判断条件和pollPDU与pollBYTE 有关系,具体是PDU_WITHOUT_POLL >= pollPDU或BYTE_WITHOUT_POLL >= pollByte,就要在AMD PDU 中包含一个poll bit。但是38.331中SRB1 的默认配置pollPDU=pollBYTE=infinity,显然不可能通过上面这个条件触发,那还有什么情况可以触发?翻看38.322,最后找到了那个最容易忽略的要触发polling的条件:
“如果传输和重传buffer都为空(不包括等待ack的已经发送的 RLC SDU 或segment);或者在传输完AMD PDU后,没有新的RLC SDU可以传输的情况下(例如window stalling),这时候就要在 AMD PDU 中包含一个poll。” 那log中的P=1显然是前面传输缓冲区和重传缓冲区都为空的条件触发的,UE在发送完SN=0的PDU后,就没有东西要发了,毕竟这个场景UE只需要发送RRCSetup Complete,剩下就是AM RLC 发送端等peer AM RLC 接收端通过STATUS PDU指示的ack。
紧接着看下AM RLC entity接收端什么情况下要进行STATUS report以及如何构造STATUS PDU。
Status reporting
STATUS PDU 由一个 STATUS PDU payload和一个RLC control PDU header组成。RLC control PDU header由D/C 和CPT字段组成。STATUS PDU payload的起始位置是从RLC control PDU header后面的第一个bit开始的,它由一个ACK_SN和一个E1,及零个或多个NACK_SN和一个E1,一个E2和一个E3组成,有时候可能还有一对SOstart 以及每个 NACK_SN 的 SOend 或 NACK 范围字段,根据NACK_SN的场景不同,上述所需的field也不同,需要具体情况具体分析。
AM RLC entity会向peer AM RLC entity发送STATUS PDU,以便给对端RLC 发送端提供其RLC SDU(或segment)的ack和nack。
触发STATUS reporting的情况如下:
(1)当从MAC层收到对端的 SN = x 的AMD PDU且 P field=1时,AM RLC entity接收端首先按照上面从MAC 层收到AMD PDU的规定判断这个AMD PDU 是否需要discard,之后要触发STATUS report,以防止对端继续发送重复的AMD PDU;
如果 x < RX_Highest_Status 或 x >= RX_Next + AM_Window_Size,就要触发STATUS report;
其他情况,就延迟触发STATUS report直到 x < RX_Highest_Status 或 x>= RX_Next + AM_Window_Size。
值得注意的是RLC STATUS report是在HARQ reordering后才能传输,即先进行HARQ级别的底层数据重传,待HARQ操作结束后,再开始RLC级别的状态反馈,两种反馈机制搭配,干活不累。
(2)当检测到有AMD PDU接收失败的情况时,如果这时候t-Reassembly也超时,AM RLC entity接收端也应触发 STATUS report。t-Reassembly超时会引起RX_Highest_Status 的更新和 STATUS 报告的触发,这两者有先后处理顺序,STATUS report应在RX_Highest_Status更新后再触发。
当触发STATUS report时,如果t-StatusProhibit没有运行 ,当在MAC层指示有传输机会时,AM RLC接收端就构造一个STATUS PDU并将其提交给下层发送;否则,在t-StatusProhibit 超时后的第一个传输机会,根据当前的情况构建单个STATUS PDU(即使在t-StatusProhibit 运行期间触发了多次STATUS report)并将其提交给下层。
当一个STATUS PDU提交给MAC层时,AM RLC接收端应该立刻启动t-StatusProhibit。
在构造一个STATUS PDU时,AM RLC entity应该:
对于SN处于RX_Next <= SN < RX_Highest_Status中的尚未收全的RLC SDU,相同SN的RLC SDU中的segment,按照byte升序,;不同SN的RLC SDU按照SN升序, 从SN=RX_Next开始生成的STATUS PDU, 直到足够当前UL grant发送为止:
(1)对于没有收到任何byte segment的RLC SDU,将其SN设定为NACK_SN 包含在STATUS PDU中;
(2)如果某个RLC SDU 有部分连续 byte的segment没有收到,将其SN设置为NACK_SN,并将未收到的部分通过SOstart和SOend表示出来;
(3)对于尚未收到的连续完整 RLC SDU,将其SN 设定为NACK_SN, 并通过NACK range表示未收到的RLC SDU,如果需要的话,可以在STATUS PDU中包含一对SOstart 和 SOend。
将ACK_SN设置为没有在STATUS PDU指示为丢失的SN,这个SN对应的是下一个没有收到的RLC SDU的SN。
以12 bit SN STATUS PDU 为例,看下应该如何填写具体field,假如RLC 接收端接收窗如上,那ACK_SN=8;其中SN=1的RLC SDU 全没收到,STATUS report中的内容对应蓝色字体部分;SN=2 中间部分没收到,STATUS report中的内容对应绿色字体部分,SOstart=X和SOend=Y 表示的是SN=2缺失的中间部范围 ;SN=5,6,7,5收到前半部分,6 全没收到,7收到后半部分,STATUS report中的内容对应紫色字体部分,SOstart=W和SOend=Z代表的是SN 5~7 连续缺失的范围。通过上面的STATUS report的内容,peer发送端就可以知道当前UE 接收端SN =3 和4 已经收到,以及未收到的SN 1,2,5,6,7具体哪部分没有收到,之后peer发送端就可以安排对应SN的重传。
SDU discard procedures
当PDCP指示要丢弃特定的RLC SDU,如果相关RLC SDU或其segment都没有提交给MAC时,AM RLC发送端应该discard对应RLC SDU。在丢弃 RLC SDU时RLC 发送端不应引入RLC SN gap,即假如要发送的SN=3的SDU 要丢弃,将后面要发送的SDU替补成SN=3继续按SN编号升序发送,防止出现SN gap,以避免可能引起对端RLC接收窗卡住的问题。
Data volume calculation
UE在进行MAC BSR时,会进行data volume估计,以便网络收到BSR后分配足够的UL grant,RLC data volume包含以下部分:
(1)尚未包含在 RLC data PDU 中的 RLC SDU 和 RLC SDU segment;
(2)等待初始传输的 RLC data PDU;
(3)等待重传的 RLC data PDU (RLC AM)。
此外,如果STATUS PDU已经被触发并且t-StatusProhibit没有运行或者已经超时,UE应该评估下一个传输机会将要传输的STATUS PDU的大小,并将其视为RLC data volume的一部分。
如果收到的RLC PDU 包含一个reserved 或invalid value,这时UE要discard 这个RLC PDU。例如收到的RLC STATUS PDU CPT field的值为001,此时UE要discard该RLC STATUS PDU。