欢迎关注同名微信公众号“modem协议笔记”。
实际查看RLC部分log难免要翻协议,查阅最多的就是相关参数的含义,反而RLC具体过程就没有像当初阅读时那样特别关注了。其实清楚RLC参数含义,看38.322就没那么困难。而RLC具体过程往往要用到相关参数,所以这里先看下相关参数含义及结构。这篇主要是RLC PDU,RLC Formats及其参数的含义, 收发过程中用到的变量,常量和定时器的总结,因而本篇笔记都是概念性描述,难免枯燥。
RLC PDU可以分为RLC data PDU和RLC control PDU。TM、UM 和 AM RLC entity使用RLC data PDU 来传输上层PDU(即 RLC SDU)。AM RLC entity使用RLC control PDU来执行ARQ过程。
Protocol data units
TMD PDU对应的是TM RLC entity传送的PDCP PDU。
UMD PDU 对应的是UM RLC entity传输PDCP PDU。
AMD PDU 对应的是AM RLC entity传输PDCP PDU。
AM RLC接收端用STATUS PDU通知对端AM RLC成功接收到的RLC data PDU以及AM RLC的接收端检测到丢失的RLC data PDU。
Formats and parameters
RLC PDU是一个bit string。下面会用表格表示bit string,其中第一及最高有效位对应的是表格第一行最左边的bit,最后一个及最低有效位对应的是最后一行最右边的bit;通常,bit string是从左到右读取,然后按行的顺序读取。
RLC SDU是按8 bit 的倍数进行的对齐。RLC SDU从第一位开始就包含在RLC PDU 中,如下图示。
TMD PDU的结构很简单,只有Data field 不包含RLC headers。
UMD PDU由data field和UMD PDU header组成。UMD PDU header也是按照8 bit 进行的对齐。
如果UMD PDU包含的是一个完整的RLC SDU时,UMD PDU header只会包含SI和R field,没有SN,换言之,带SN的UMD PDU 对应的是RLC SDU的segement。
UM RLC entity会根据RRC 层参数配置成 6 bit SN 或 12 bit SN。对于 NR 侧链路通信的组播和广播,仅支持配置 6 bit SN 长度。只有当相应的 RLC SDU 被分段时,UMD PDU header才包含 SN 字段。携带 RLC SDU的第一段UMD PDU 在其header中不会携带 SO field。SO field的长度为 16 bits。
AMD PDU 由data字段和 AMD PDU header组成。AMD PDU header是按照8 bit 进行的对齐。
AM RLC entity根据RRC 层参数配置成 12 bit SN 或 18 bit SN。AMD PDU header的长度分别是两个和三个bytes。
AMD PDU header会包含 D/C、P、SI 和 SN。仅当data字段对应的不是 RLC SDU segment的第一段时,AMD PDU header才包含 SO 字段,在这种情况下,SO 对应16 bits。
Parameters
下面是每个字段的定义,参数中的bit 第一个及最高有效位对应是最左边的bit,最后一个及最不重要的位对应的是最右边的bit。除非另有说明,这里的整数是以无符号整数的标准二进制编码进行的。
Data field对应元素是按照它们到达RLC entity发射端的顺序映射的。
对于 TMD PDU、UMD PDU 和 AMD PDU,Data field大小的粒度是一个byte;最大data field大小对应的是PDCP PDU的最大size。
对于TMD PDU,只有RLC SDU可以映射到TMD PDU 的Data field,即TMD PDU不存在segment。
对于UMD PDU和AMD PDU,RLC SDU或segment都可以映射到Data field。
Sequence Number (SN) field对应12 bits或18 bits,用于指示相关RLC SDU 的SN值,对于AM RLC, sn是以RLC SDU为单位递增的,即每个RLC SDU 有唯一的SN,一个RLC SDU 要进行分段,分段后的每个segment 的SN 和原始的RLC SDU SN 相同;对于UM RLC,segment RLC SDU才会有sn,sn也是逐一递增的,换而言之,完整的RLC SDU 是没有SN的,所以后面UM RLC entity接收端在处理数据时,要考虑UM PDU没有SN的情况。sn的长度由RRC层参数sn-FieldLength配置。另外LTE RLC SN的规定和NR有很大不同,这里就不细说了,以免搞混,对比下38.322和36.322,顺带看下就清楚了。
SI field对应 2bits, 不同的value代表RLC SDU的不同情况,'00'代表是一个完整的RLC SDU;'01'代表是RLC SDU 的first segment;‘10’代表RLC SDU的last segment;'11'代表当前的AMD PDU对应的是RLC SDU的中间部分的segment。
SO field对应16 bits,SO field指示的是RLC SDU segment在原始RLC SDU中的位置。具体地,SO字段指示Data field中RLC SDU segment的第一个字节在原始RLC SDU中所对应的位置。原始 RLC SDU的第一个字节用SO 字段值“0000000000000000”表示,即从零开始编号。
Data/Control(D/C) field 对应1 bit,用于区分Control PDU(0)和Data PDU(1)。
Polling bit:P 字段对应1 bit,代表AM RLC entity发送端是否请求来自其对等 AM RLC entity的STATUS Report,value 0代表不需要Status report,value 1代表需要Status report。
R field对应 1bit,发送端要将R 设置为0,接收端也会忽略这个field。
CPT field 对应3 bits,用于确定RLC control PDU的类型,只有值'000'有实际意义,对应STATUS PDU。
ACK_SN长度对应12 bits或 18 bits。从STATUS report的发送端来看,ACK_SN 字段指示下一个未收到的 RLC SDU 的 SN,且该 SDU没有在 STATUS PDU 中报告为nack。当 AM RLC entity发送端收到一个 STATUS PDU时,其代表的内容是截至SN = ACK_SN 的RLC SDU为止目前所有收到的RLC SDU,当然要排除报NACK_SN的PDU,其包含具有NACK_SN、SOstart和SOend的部分RLC SDU,具有NACK_SN和NACK_range的RLC SDU以及具有NACK_SN、NACK range、SOstart和SOstart的部分RLC。SDU。很繁琐的一段,后面到STATUS report的生成时,再具体看。
E1 对应1 bit,代表是否后面还会有一些列NACK_SN E1,E2,E3 bit位出现,E1 =0代表不会有,E1=1代表有。
NACK_SN对应 12 bits或18 bits,代表接收端当前认为是 lost的RLC SDU 的SN。
E2对应1 bit,用于指示后面是否还会有一系列的SOstart和SOend,E2=0指没有 E2=1指有。
E3对应1 bit,用于指示NACK_SN后是否还有NACK range,value 0 代表没有,value 1代表有。
NACK range field 对应8 bits,通常RLC SDU 连续整段的丢失时,才会用到,代表的是从NACK_SN(包含NACK_SN)开始连续lost RLC SDUs 的数目。
SOstart 字段与 SOend 字段组合在一块使用,SOstart 字段对应16 bits,指示在 AM RLC entity接收端已检测到丢失的 RLC SDU 部分,与NACK_SN=SN相关。 原始 RLC SDU 的第一个字节由 SOstart 字段值“0000000000000000”引用,即编号从零开始。具体地,SOstart字段以字节为单位指示原始RLC SDU内丢失部分的第一字节的位置。
当 E3 =0 时,SOend 字段连同SOstart 字段一起用于表示 RLC SDU SN = NACK_SN 在 AM 接收端检测为丢失的部分。
具体地,SOend字段指示原始RLC SDU中以字节为单位的RLC SDU部分的最后一个字节的位置。原始 RLC SDU 的第一个字节由 SOend 字段值“0000000000000000”引用,即编号从零开始。特殊的 SOend 值“1111111111111111” 代表当前丢失的RLC SDU SN 的结尾对应的就是该RLC SDU 最后一个字节。
当E3为1时,SOend字段指示在AM RLC接收端检测到丢失的SN=NACK_SN + NACK range - 1的RLC SDU部分。具体地,SOend字段指示原始RLC SDU中以字节为单位的RLC SDU部分的最后一个字节的位置。原始RLC SDU 的第一个字节由 SOend 字段值“0000000000000000”引用,即编号从零开始。特殊的 SOend 值“1111111111111111”用于指示 RLC SDU 的缺失部分包括到 RLC SDU最后一个字节的所有字节。
State variables
这里开始看下AM和UM RLC entity中使用的state variables,这些参数对于查看UE RLC 层数据的收发很重要,读懂这些state variables就很容易看出RLC tx/rx的具体状况。值得注意的是所有state variables和所有counters都是非负整数。
对于 12 bit SN,与 AM 数据传输相关的所有state variables的取值范围为 0~4095,对于18 bit SN,取值范围为 0~262143。RLC协议中包含的与 AM 数据传输相关的状态变量的所有算术运算均受 AM modules的影响(即12 bit SN 对应的最终值=[算术运算的值] modulo 4096 ;18 bit SN对应的最终值=[算术运算的值] modulo 262144),不能超过各自的取值范围。
与UM 数据传输相关的所有状态变量对于 6 bit SN 可以采用 0~63 之间的值,对于 12 bit SN 可以采用 0~4095 之间的值。RLC协议中包含的与 UM 数据传输相关的状态变量的所有算术运算均受 UM modules的影响(即6 bit SN 对应的最终值=[算术运算的值] modulo 64 ;12 bit SN对应的最终值=[算术运算的值] modulo 4096)。
当执行状态变量或 SN值的算术比较时,应使用modulus base运算。
TX_Next_Ack 和 RX_Next 应分别假定为 AM RLC entity的发送端和接收端的modulus base。从所有涉及的值中减去该modulus base,然后执行绝对值比较(例如处于发送window中的SN:RX_Next <= SN < RX_Next + AM_Window_Size 的计算方式为 [RX_Next – RX_Next] mod 2^[sn-FieldLength] <= [SN – RX_Next] mod 2^[sn-FieldLength] < [RX_Next + AM_Window_Size – RX_Next] mod 2^[sn-FieldLength]),其中对于 12 bit SN 和 18 bit SN,sn-FieldLength分别为 12 或 18。
RX_Next_Highest – UM_Window_Size 应假定为接收 UM RLC entity的modulus base。从所有涉及的值中减去该模数基数,然后执行绝对比较(例如 处于接收窗中的SN :RX_Next_Highest– UM_Window_Size) <= SN < RX_Next_Highest 的计算方式为 [(RX_Next_Highest– UM_Window_Size) – (RX_Next_Highest– UM_Window_Size)] mod 2[sn -FieldLength] <= [SN – (RX_Next_Highest– UM_Window_Size)] mod 2[sn-FieldLength] < [RX_Next_Highest– (RX_Next_Highest– UM_Window_Size)] mod 2[sn-FieldLength]),其中 6 bit SN 和 12 bit SN的sn-FieldLength分别为 6 或 12。
AM_Window_Size 代表的是AM RLC entity的发送端和接收端 window的size,12 bit SN :AM_Window_Size=2048;18 bit SN:AM_Window_Size=131072。
UM_Window_Size代表的是 UM RLC entity接收端 window的size,用于UM reassemble window的确定,6 bit SN :UM_Window_Size=32;12 bit SN :UM_Window_Size=2048。
AM RLC
AM RLC entity 发送端有3个状态变量:
(1) TX_Next_Ack 是代表ack状态的变量,此状态变量保存的是下一个按顺序要接收positive ack的RLC SDU 的SN值,该变量对应的是传输窗的下边缘。初始设置为 0,会在AM RLC entity收到 对RLC SDU 的SN = TX_Next_Ack的positive ack时进行更新。
(2)TX_Next代表的是发送状态的变量,此状态变量保存的是下一个新生成的 AMD PDU 的 SN 值。初始设置为 0,并且每当AM RLC entity构造一个SN= TX_Next 的 AMD PDU 并包含一个 RLC SDU 或一个 last segment RLC SDU 时,该变量就会更新。
(3)POLL_SN 代表Poll 发送状态的变量,在设置 POLL_SN 时,该状态变量保存的提交给MAC层的AMD PDU中最高 SN的值。初始设置为 0。
上面关于TX_Next的解释,可能会有点疑惑,但是再结合下面这段描述应该就会比较清楚了。
当向MAC层提交包含segment RLC SDU 的 AMD PDU 时,AM RLC entity发送端应将AMD PDU的SN设置为相应RLC SDU的SN。这里可以看出,AMD PDU 的SN对应的是RLC SDU 的SN ,如果RLC SDU存在segment的话,其所有的segment的SN都是相同的。这里也是和LTE AM RLC处理有所不同的地方。
从PDCP收到的RLC SDU后,AM RLC entity应该将其与TX_Next的SN相关联,然后将新生成AMD PDU的SN设置为TX_Next;之后TX_Next +1,指向下一个要产生的SN。
比如上图RLC UL 发送出去了SN 1~6,其中只有SN 2和4 收到了对端RLC 的positive ack,这时候TX_Next_Ack=1 TX_Next=7,接下来通过对端RLC的STATUS PDU 收到了SN 1和5 的positive ack,UE发送了SN=7的RLC AMD PDU,那要更新发送窗,新发送窗的最低边界TX_Next_Ack=3,而TX_Next=8;如果当前RLC向MAC层提交了包含poll的AMD PDU后,AM RLC entity发送端要将 POLL_SN 设置为提交给MAC层的 AMD PDU 中最高 的SN value,即POLL_SN=7。
AM RLC entity 发送端也有3个counter:
(1)PDU_WITHOUT_POLL:初始设置为 0。它计算的是最近的一个poll bit传输以后 UE发送AMD PDUs的数量。
(2)BYTE_WITHOUT_POLL:初始设置为 0。它计算自最近的一个poll bit发送以后 UE发送的data bytes数。上述两个counter 用于RLC 发送端确定何时在AMD PDU中包含poll bit。
(3)RETX_COUNT:计算的是RLC SDU 或 RLC SDU segment的重传次数。每个 RLC SDU 都会维护一个 RETX_COUNT计数器;这个counter不断增加达到配置的maxRetxThreshold,就导致rlc max numRetx进而引起RLF。
(1)maxRetxThreshold:每个AM RLC entity的发送端使用该参数来限制RLC SDU 的重传次数,包括segments。
(2) pollPDU:每个AM RLC entity的发送端使用该参数来触发对每个 pollPDU PDU的poll。
(3) pollByte:每个 AM RLC entity的发送端使用此参数来触发每个pollByte bytes的poll。
当AM RLC entity 发送端 PDU_WITHOUT_POLL >= pollPDU或BYTE_WITHOUT_POLL >= pollByte,就要在AMD PDU 中包含一个poll bit,peer AM RLC接收端收到后,就要出发STATUS report, 具体情况后面再说。下面是RRC层Counter和参数的配置结构。
sn-FieldLength的配置值得关注下, DRB 的sn-FieldLength的值只能通过reconfiguration with sync来改变。网络侧只能为 SRB 配置 SN-FieldLengthAM=size12,DRB 没有上述限制。
如上图实网配置,SRB1和SRB2 的sn-FieldLength都为 size12,而DRB size12和size18 都行。
AM RLC entity接收端有4个状态变量:
(1)RX_Next代表接收状态变量,该状态变量保存最近一个按顺序完全接收到RLC SDU SN 的下一个SN值,该变量对应的就是接收收窗的下边缘。初始设置为 0,并且每当AM RLC entity接收到 RLC SDU的SN = RX_Next 时就会更新。
(2)RX_Next_Status_Trigger:t-Reassembly 状态变量,该状态变量保存的是触发 t-Reassembly的 RLC SDU SN 的下一个 SN 值。
(3)RX_Highest_Status代表Max STATUS 传输状态变量,当需要构建 STATUS PDU 时,该状态变量保存的是STATUS PDU中ACK_SN指示的那个SN。初始设置为 0。结合后面构造STATUS PDU ,设置ACK_SN的规定,如上黄色字体,就将ACK_SN 设置为没有在STATUS PDU指示为丢失的SN,这个SN 对应的是下一个没有收到的RLC SDU的SN。
(4)RX_Next_Highest代表的是highest接收状态变量,该状态变量保存的是当前接收到的RLC SDU highest SN 的 下一个SN 值,初始设置为 0。
假如当前AM RLC 接收端 值收到了SN 1~6 RLC SDU,其中只有2和4收全了,那RX_Next=1,RX_Next_Highest=7,如果这时候收到了peer 发送端的 AMD PDU 带poll bit =1,这时候就要生成STATUS report,根据规定ACK_SN对应的是没有在STATUS PDU中指示为丢失的SN,这个SN 对应的是下一个没有收到的RLC SDU 的SN,具体到这里RX_Highest_Status=7。
UM RLC
UM RLC entity发送端只有一个状态变量:TX_Next代表UM 发送状态变量,此状态变量保存的是下一个新生成的UMD PDU segment的SN值。初始设置为0,并且在UM RLC entity向MAC 提交包括RLC SDU的 last segment的UMD PDU之后才会更新。这里又与AM RLC 的定义有所不同,只有UMD PDU 对应的是RLC SDU segment时才有sn,如果UM PDU对应的是完整的RLC SDU,UMD PDU 是没有sn的。这样的设定 从分析问题的角度看,是十分友好的,网络状况良好的情况下,UL grant十分充足,segment就可能比较少,进而SN的处理会少很多,UE处理起来也会稍微便捷些;网络状况不好的时候,UL grant通常不会给足,这时候segment会比较多,对应的UM PDU大多都会带SN ,在检查UE UL发送和DL接收时,通过SN分析UE收发也更能看出问题。
UM RLC entity 接收端有3个状态变量:
(1)RX_Next_Reassemble 代表UM 接收状态变量
此状态变量保存的是仍认为在进行reassembly的最早的 SN 值。初始设置为 0。对于 NR sidelink 通信的组播和广播,它初始设置为第一个接收到的包含 SN 的 UMD PDU 的 SN值。
(2)RX_Timer_Trigger 代表UM t-Reassembly 状态变量,保存的是触发t-Reassembly SN的下一个SN的值。
(3)RX_Next_Highest代表UM receive 状态变量,保存的是当前UE收到的UMD PDUs中highest SN的下一个SN值,作为reassembly window的最高边缘,初始设置为0。对于 NR sidelink 通信的组播和广播,它初始设置为第一个接收到的包含 SN 的 UMD PDU 的 SN值。
假如RX_Next_Reassembly 仍处于reassembly window [RX_Next_Highest – UM_Window_Size,RX_Next_Highest)的范围,上述场景RX_Next_Reassembly=1,RX_Next_Highest=7。
(1) t-PollRetransmit:由 AM RLC entity的发送端用来重传poll使用。
(2) t-Reassembly:由 AM RLC entity和 UM RLC entity的接收端使用,用来检测下层 RLC PDU 的丢失。如果 t-Reassembly 正在运行,则不应额外启动 t-Reassembly,即每个 RLC entity只有一个 t-Reassembly可以在特定时间运行。
(3) t-StatusProhibit:由 AM RLC entity的接收端使用,在运行期间禁止传输 STATUS PDU。
几个Timer 的工作原理,后面再具体看。
到这里本篇就结束。后面会针对RLC具体流程以及实际问题分析过程进行简单总结,但是免不了要再回看上面的这些个参数定义。