资源描述
1 将RLC SDU组成RLC PDU
1.1 功能介绍
发送UM RLC实体/AM RLC实体的发送侧将RLC SDU组成UMD PDU时,它们将:
- 根据低层通知的特定发送时机以及由低层指示的RLC PDU(s)的总大小,将RLC SDU分段和/或串接成合适的RLC PDU(UMD PDU / AMD PDU)
- 在RLC PDU中包含相应的RLC PDU头。
Figure 1.1-1: RLC PDU Structure
1.2数据结构和宏
MIN_PDU_DATA_SIZE宏值, 表示PDU数据域元素的最小长度(>=1)。
PDU_Header_Ext表示PDU头扩展部分的结构类型, 包含E和LI位域。
PDU表示一个RLC PDU结构的类型,包含的数据成员有:
ü PDU头固定部分:UM和AM模式的PDU头不同,不同模式,包含各自的所有的位域;
ü PDU头扩展部分:指向PDU_HeaderExt的指针;
数据域:每个元素为一个字节的数组。
SDU_context: 表示SDU上下文的结构类型,并包含的数据成员有:
BYTE *tbuff:指向存放RLC SDU的缓存器;
SDU_leftsize:RLC SDU的长度,初始表示当前顺序从buffer里取出的RLC SDU的长度,每次组建后更新为剩下的RLC SDU的长度;
Segment:表示RLC SDU分段的标识,初始为0, 每次顺序取到一个RLC SDU, 如果标识为1,表示是一个RLC SDU分段;否则,表示是一个RLC SDU;
PDU_context: 表示PDU上下文的结构类型,并包含的数据成员有:
PDU_SN:下一个将要发送的UMD PDU的 SN。
PDU_leftsize(PDU剩余大小):表示组建当前RLC PDU时,该PDU还可以包含的字节数。初始值为此发送时机低层指示的RLC PDU的总大小;
ElemNo: 该变量计数RLC PDU数据域元素的个数, 初始为0;每次组建一个RLC PDU结束,ElemNo更新为0。
PDU_finish:表示组建一个RLC PDU结束的标识。 值为0,表示正在组建一个RLC PDU; 值为1, 表示组建一个RLC PDU结束,也表示下一次将要组建一个新的RLC PDU。 初始为1,每次组建后,如果正在组建的RLC PDU未结束,更新为0;
1.3算法流程
1.4详细设计
函数原型
void Rlc_Pdu_Process(SDU_context &)
描述
RLC SDU分段或串接成RLC PDU
输入
SDU上下文:
* tbuff 指向存放RLC SDU的缓存器
SDU_leftsize RLC SDU的(剩余)长度
segment 表示RLC SDU分段的标识
输出
SDU上下文(记录发送buffer的第一个RLC SDU的信息)
1. 在MAC通知的发送时机,初始化PDU上下文;
2. 从发送Buffer里顺序取出一个RLC SDU,更新SDU上下文,如果PDU上下文里的PDU_finish=1,该SDU将用于组建一个新的RLC PDU,转到3;否则,转到4;
3. 创建一个新的RLC PDU
Ø 首先创建一个初始的RLC PDU;
Ø 根据SDU上下文里的SDU分段标识segment确定PDU头固定部分的
FI域的第一位:即如果segment为0,该RLC SDU是一个完整的SDU,
FI第一位为0;否则,它是一个SDU分段,FI的第一位为1;
Ø 并更新PDU_leftsize= PDU_leftsize-2(PDU头的固定部分大小)。
4. 比较PDU_leftsize与SDU_leftsize, 如果:
1) PDU_leftsize < SDU_leftsize:SDU需要分段
将RLC SDU分段,把长度等于PDU_leftsize的SDU前面分段拷贝到RLC PDU的数据域后面(正好映射到RLC PDU的最后一个数据域元素);
更新SDU上下文:SDU_leftsize = SDU_leftsize - PDU_leftsize; segment = 1;
更新PDU上下文:PDU_leftsize = 0; ElemNo ++; PDU_finish=1(PDU数据域组建完成);
确定RLC PDU头的固定部分:
FI域的后一位 = 1;
如果RLC PDU 只有一个数据域元素(即ElemNo=1),没有扩展部分, PDU头固定部分的E域 = 0; 否则,有扩展部分,PDU头固定部分的E域=1;
确定SN域等于发送状态变量(VT(US)或VT(S))。
对AM PDU,确定D/C域 = 1, RF域 = 0, P域(跟轮询机制有关)。
确定RLC PDU头扩展部分:(该SDU前面分段在扩展部分没有E和LI;)
如果ElemNo > 1,扩展部分的最后一个E域为0,即扩展部分第(ElemNo-1)个E域=0。(第1到ElemNo个E域已经确定,这里只需确定最后一个E域)
如果ElemNo为奇数,在最后一个LI后加四个填充比特,组建一个RLC PDU结束。
实例:以下面的AMD PDU为例,假设这次分段结束后,当前的ElemNo = k+1,
那么,该SDU前面分段是RLC PDU的最后一个数据域元素,
没有E和LI域;固定部分如上所述,其中FI=01或11, E=1;
扩展部分从第1个到第k-1个E = 1;LI1~k 为各自数据域元素长度;第K个E = 0。
2) PDU_leftsize = = SDU_leftsize:直接映射
直接把该RLC SDU映射到RLC PDU的最后一个数据域元素(拷贝)。
更新SDU上下文:SDU_leftsize = 0;segment = 0;
更新PDU上下文:PDU_leftsize = 0;PDU_finish=1;ElemNo++。
确定RLC PDU头的固定部分:
FI域的后一位 = 0;
如果RLC PDU 只有一个数据域元素(即ElemNo=1),没有扩展部分, PDU头固定部分的E域 = 0; 否则,有扩展部分,PDU头固定部分的E域=1;
确定SN域等于发送状态变量(VT(US)或VT(S))。
对AM PDU,确定D/C域 = 1, RF域 = 0, P域这里不设置。
确定PDU头扩展部分:(该RLC SDU在扩展部分没有E和LI;)
如果ElemNo > 1, 扩展部分的最后一个E域为0,即扩展部分第(ElemNo-1)个E域=0。(第1到ElemNo个E域已经确定,这里只需确定最后一个E域)
如果ElemNo为奇数,
在最后一个LI后加四个填充比特,组建一个RLC PDU结束。
实例:以下面的UMD PDU为例,假设这次组建结束后,当前的ElemNo =1,
那么, 该SDU是RLC PDU的唯一的一个数据域元素,没有扩展部分;
固定部分如上所述,其中FI=00或10, E = 0;
3) PDU_leftsize > SDU_leftsize: SDU串接
把该RLC SDU串接到RLC PDU的当前最后的数据域元素的后面。
更新PDU上下文: PDU_leftsize = PDU_leftsize-SDU_leftsize;
Ø 如果 PDU_leftsize + (k%2)*0.5 -1.5 >= MIN_PDU_DATA_SIZE,(1.5是PDU头扩展部分一个E和LI域的字节数, 当k= ElemNo是奇数是,0.5是当前补充比特的字节数,MIN_PDU_DATA_SIZE是初始定义的宏) 且Buffer不为空,那么还可以继续串接RLC SDU来组建该RLC PDU,
- 更新PDU上下文: ElemNo++;PDU_finish = 0;
PDU_leftsize = PDU_leftsize-(1.5* ElemNo+(ElemNo%2)*0.5)
v ElemNo奇数PDU_leftsize = PDU_leftsize-(1.5* ElemNo +0.5);
v ElemNo偶数PDU_leftsize = PDU_leftsize-1.5* ElemNo;
- 确定RLC PDU头的固定部分:
确定PDU头固定部分的E为1;
确定SN域等于发送状态变量(VT(US)或VT(S));
对AM PDU,确定D/C域 = 1; RF域 = 0; P域与轮询机制有关。
- 确定PDU头扩展部分:
PDU头的扩展部分包括第ElemNo个PDU_Header_Ext对象, 即一个E和LI k域(k=ElemNo);
确定LIk = SDU_leftsize(或者用偏移量来表示);
确定扩展部分的上一个(第k-1个)的E域为1;
- 更新SDU上下文:SDU_leftsize = 0;segment = 0;
- 循环回到 2, 即继续顺序取出发送Buffer里第一个RLC SDU, 开始继续串接该RLC SDU或一部分来组成RLC PDU;
实例:以下面的AMD PDU为例,假设这次串接结束后,当前的ElemNo = k+1,
那么,扩展部分新增的E和LIk+1是当前串接的SDU的E和LI域;
固定部分如上所述,其中E=1;
扩展部分第k个E=1; 第(K+1)个E = 0;LIk+1 = SDU_leftsize ;
Ø 否则,如果发送Buffer为空,或者0< PDU_leftsize + (k%2)*0.5-1.5 < MIN_PDU_DATA_SIZE
RLC PDU后面不能串接一个RLC SDU,该SDU是RLC PDU的最后一个数据域元素,不需要继续串接,
- 更新PDU上下文: PDU_finish = 0;PDU_leftsize = 0;
- 更新SDU上下文:SDU_leftsize = 0;segment = 0;ElemNo++
- 确定RLC PDU头的固定部分:
确定FI域的后一位为 0 ;
如果RLC PDU 只有一个数据域元素(即ElemNo=1),没有扩展部
分, PDU头固定部分的E域 = 0; 否则,有扩展部分,PDU头固定部分的E域=1;
确定SN域等于发送状态变量(VT(US)或VT(S))。
对AM PDU,确定D/C域 = 1, RF域 = 0, P域这里不设置。
- 确定PDU头扩展部分:
(该RLC SDU在扩展部分没有E和LI域;)
如果ElemNo > 1,扩展部分的最后一个E域为0,即扩展部分第ElemNo-1个E域 = 0 ;(第1到ElemNo-2个E域已经确定,这里只需确定最后一个E域,所有的LI域已确定)
- 如果ElemNo为奇数,在最后一个LI后加四个填充比特,组建一个RLC PDU结束。
以下面的AMD PDU为例,假设这次串接结束后,当前的ElemNo = k,
那么,扩展部分没有当前串接的SDU的E和LI域;
固定部分如上所述,其中FI=00或10;E=0;
扩展部分第k个E=1;
5. 将组建结束的RLC PDU递交给低层, 同时更新发送状态变量加1,结束。
1.5 AMD PDU
v 什么时候用到AMD PDU分段?
当重传AMD PDU的大小大于本次发送通知中对MAC SDU长度的要求时,可以对AMD PDU进行再分段,形成AMD PDU分段。
v 结构
再分段只是对数据域的分段,AMD PDU分段中头的部分除了RF域、新增的LSF域和SO域外都与再分段前的AMD PDU相同。
2 将RLC PDU重组为RLC SDU
2.1 接收UM RLC实体SDU重组
2.1.1 模块介绍
2.1.1.1功能需求
在接收UM RLC实体接收UMD PDU后,它:
- 将完成重排序的UMD PDU(不考虑已检测到丢失的RLC PDU)重组RLC SDU,并将完成重组的RLC SDU按序递交给高层(先重排序,再重组)
- 由于某个RLC SDU的一个UMD PDU在低层丢失,导致收到的UMD PDU不能重组为RLC SDU,则丢弃这些UMD PDU
2.1.1.2 算法描述
针对当前接收Buffer里已重排序的UMD PDUs按序循环进行重组:(重组是按照SN从小大到的顺序)
Ø 从最小的SN的UMD PDU开始, 循环遍历下一个SN(假设SN=x)的UMD PDU。 每次循环,顺序遍历UMD PDU的数据域元素,并把该数据域元素和上一次重组保留的RLC SDU分段(如果有的话)一起进行重组(按照SN从小大到的顺序):
² 如果重组后的RLC SDU之前没有递交过,将完成重组的RLC SDU按序递交给高层;
² 将由于某个UMD PDU在低层丢失而不能重组为RLC SDU的PDU丢弃(丢失的PDU为SDU的前面部分分段或中间部分分段);
² 将没有完成重组的RLC SDU分段保留(SDU的后面部分分段没有收到)。
2.1.2 数据结构设计
PDULeft: 结构类型,表示每次重组之后,没有完成重组的RLC SDU的相关信息 ,用于下一次按序重组,包含下面的成员:
SN_Left: 整型变量,记录当前没有完成重组的RLC SDU包含的PDU的最大的SN,初始值为-1; 若某次重组之后,当前被重组的UMD PDU的数据域有剩余,SN_Left更新为该PDU的SN;
SDU_Left: 数组,保留重组之后剩余的RLC PDU数据部分(即没有完成重组的RLC SDU分段),也就是0个、1个或多个SDU分段。初始为空数组。
注:PDULeft对象设计为静态对象。
2.1.3 算法流程
2.1.4 详细设计
函数原型
void Rlc_ Reassemble_UM_Process(PDU_Left &,SN_MIX, SN_MAX)
描述
将RLC PDU重组成RLC SDU
输入
PDU_Left:
SN_Left
SDU_Left
SN_MIX: 要重组的最小的SN
SN_MAX:要重组的最大的SN
输出
PDU_Left
当前接收Buffer里已重排序的UMD PDU(s)最小的SN = SN_MIX;
循环对SN=x的UMD PDU进行重组,循环直到接收Buffer里已重排序的最后一个SN(SN= SN_MAX)的UMD PDU重组后结束;
PDULeft对象保留上一次重组后没有完成重组RLC SDU的信息。
看下面的例子: 假设开始重组SN=x的UMD PDU,此时:
第1步:判断接受Buffer里SN = x的UMD PDU是否存在,
Ø 如果不存在,该UMD PDU 在低层丢失,那么:
丢弃PDULeft对象保留的没有完成重组的RLC SDU,即清空SDU_Left;
更新PDULeft对象的SN成员 = -1;
x = x+1;(下一个SN)
循环回到第1步;
Ø 如果存在, 继续第2步;
第2步:检查SN=x的UMD PDU头固定部分FI和E域,如果:
- 如果E = = 0,那么该UMD PDU只有一个数据域元素,又
Ø 如果FI的第一位为1,那么该UMD PDU的第一个数据域元素是一个SDU的后面分段(前面分段和后面分段根据2个SDU分段在原来的SDU中的相对位置而言), 判断PDULeft对象的成员SN,
² 如果SN != x-1,包含该SDU的前面分段的UMD PDU已经丢失,那么:
直接丢弃该UMD PDU;
更新PDULeft对象: 如果SN != -1, 丢弃的SDUs成员保留的数据;然后SN = -1;
x = x+1;
循环回到第1步;
² 否则SN = = x-1, PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
去掉PDU头, 将这2个SDU分段按序重组(SN升序)为RLC SDU; 这时,
l 如果FI的后一位为0, 那么:
更新PDULeft对象:SN = -1; SDUs 清空;
将完成重组的RLC SDU按序递交给高层;
l 否则FI的后一位为1,那么更新PDULeft对象:
SN = x; SDUs = 当前重组后没有完成重组的RLC SDU;
x = x+1;
循环回到第1步;
Ø 否则,FI的第一位为0,那么:
去掉PDU头,把PDU的数据域直接重组为RLC SDU;这时,
² 如果FI的后一位为0,那么:
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDU_Left 清空;
² 否则FI的后一位为1,那么:
更新PDULeft对象: SN = x;
SDUs = 当前重组后没有完成重组的RLC SDU;
x = x+1;
循环回到第1步;
- 否则E=1,该UMD PDU有多个数据域元素, 那么:
(一) 遍历PDU头扩展部分第一个数据域元素的E和LI域,该数据域元素
长度 = LI;
Ø 如果FI的第一位为1,该UMD PDU的第一个数据域元素是一个SDU的后面分段,那么:判断PDULeft对象的成员SN:
² 如果SN != x-1,包含该SDU的部分前面分段的UMD PDU已经丢失,那么:
直接丢弃该UMD PDU的第一个数据域元素;
更新PDULeft对象: 如果SN != -1, 丢弃SDUs成员保留的数据;然后SN = -1;
² 否则SN = =x-1, PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
将这2个SDU分段按序重组为RLC SDU;
将完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
此时,上面的例子的变化:
Ø 否则FI的第一位为0,那么:
把第一个数据域元素直接重组为RLC SDU;
将完成重组的RLC SDU按序递交给高层;
(二) 检查当前遍历的E域, 循环执行下面的操作:
Ø 如果E= =0,该UMD PDU只剩下的最后一个数据域元素,那么:
去掉PDU头,把PDU的最后一个数据域元素直接重组为RLC SDU;
² 如果FI的后一位为0,那么:
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
² 否则FI的后一位为1,那么:
更新PDULeft对象: SN = x;
SDUs = 当前重组后没有完成重组的RLC SDU;
x = x+1;
循环回到第1步;
最后,关于上面的例子:
RLC SDU 1、RLC SDU 2、RLC SDU 3 提交给高层;
Ø 否则E= =1,该UMD PDU还剩下多个数据域元素,那么:
按序遍历PDU头的扩展部分下一个数据域元素的E和LI域, 下一个数据域元素长度 = LI;
直接把下一个数据域元素重组为一个完整的RLC SDU;
更新PDULeft对象:SN = -1; SDUs 清空;
将该完成重组的RLC SDU按序递交给高层;
循环回到(二)。
第3步,循环结束,返回。
2.2 AM RLC实体接收侧SDU重组
2.2.1 模块介绍
2.2.1.1功能需求
AM RLC实体的接收侧收到RLC数据PDU后, 它:
- 将完成重排序的RLC数据PDU(完整的PDU)重组成RLC SDU,并将完成重组的RLC SDU按序递交给高层
2.2.1.2 算法描述
将落在接收窗外的SN所对应的AMD PDU的任何字节分段和SN = VR(R)的AMD PDU的连续字节分段进行重组:
从最小SN的AMD PDU或AMD PDU分段开始, 循环遍历下一个SN的AMD PDU或AMD PDU分段。每次循环,有下面2种情况:
Ø 对AMD PDU:根据E域和LI域,顺序遍历AMD PDU的数据域元素,把该PDU的数据域进行重组,重组时去掉RLC头:
² 如果重组后的RLC SDU之前没有递交过,将完成重组的RLC SDU按序递交给高层;
² 将没有完成重组的RLC SDU保留, 等到下一次继续重组。
Ø 对AMD PDU分段:首先根据LSF域和SO域将AMD PDU分段重组为AMD PDU,然后再根据同上把AMD PDU重组为RLC SDU。
Ø 按当前遍历的 相同SN的AMD PDU分段在原AMD PDU中的顺序, 把该AMD PDU的可以被重组的连续的字节分段进行重组,重组时去掉RLC头。
2.2.2 数据结构设计
PDULeft: 结构类型,表示每次重组之后,没有完成重组的RLC SDU的相关信息 ,用于下一次按序重组,包含下面的成员:
SN_Left: 整型变量,记录当前没有完成重组的RLC SDU包含的PDU的最大的SN,初始值为-1; 若某次重组之后,当前被重组的UMD PDU的数据域有剩余,SN_Left更新为该PDU的SN;
SDU_Left: 数组,保留重组之后剩余的RLC PDU数据部分(即没有完成重组的RLC SDU分段),也就是0个、1个或多个SDU分段。初始为空数组。
注:PDULeft对象设计为静态对象。
AMD_SegContext: 表示AMD PDU分段上下文, 包含下面的变量:
SN: AMD PDU分段的SN, 初始为-1;
SO: 没有被全部重组的AMD PDU分段在原AMD PDU中的偏移量;初始为0, 每次重组之后更新;
CSO(字节分段偏移): 没有被重组的第一个字节分段在原AMD PDU中的偏移,初始为0;
LISN: 没有被重组的连续字节分段的所有的LI中,顺序最小的LI的序号; 初始为1; LISN= 0表示这些连续字节分段是AMD PDU最后一个数据域元素; LISN = k(正整数), 表示这些连续字节分段对应的顺序最小的LI的序号。
注:AMD_SegContext对象设计为静态对象。
2.2.3 算法流程
2.2.4 详细设计
落在接收窗外的最小的SN = x, 循环开始对SN=x的 RLC PDU进行重组,循环结束条件: SN= =VR(R);
PDULeft对象初始化,以后保留上一次重组后没有完成重组RLC SDU的信息;
AMD_SegContext 对象初始化,以后记录上一次重组后AMD PDU分段的上下文信息。
第1步: 对SN = x的RLC PDU(s),执行:
1. 如果RLC PDU头RF域=1,表示该RLC PDUs是一些AMD PDU分段,那么:
l (1)执行循环,循环结束条件为LSF = 1,LSF初始为0, 每次循环,循环体里执行:
n (按SO升序)得到对应的AMD PDU分段;
n (按序)把当前AMD PDU分段的数据域串接,组成AMD PDU的数据域;
n LSF = 当前AMD PDU分段头的LSF域;
n 循环回到(1);
l 加上该AMD PDU的头,RF域修改为0, 接着转到第2步对该AMD PDU进行重组。
附注:下面红色的部分是上面“1“的另一种方法:(按照AMD PDU分段重组)
1. 如果RLC PDU头RF域=1,表示这些RLC PDUs是一些AMD PDU分段, 那么:检查AMD PDU分段头E域:
Ø 如果E==0, 即SN=VR(R)的原AMD PDU只有一个数据域元素,那么:
l 执行循环,循环结束条件为LSF = 1,LSF初始为0, 每次循环,循环体里执行:
(按SO升序)得到对应的AMD PDU分段;
(按序)把当前AMD PDU分段的数据域串接,重组为RLC SDU;
LSF = 当前AMD PDU分段头的LSF域;
l 接着,检查分段头FI域:
² 如果FI的第一位为1,那么重组后的RLC SDU是一个SDU的后面分段, 显然PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
将这2个SDU分段按序重组为一个RLC SDU; 这时,
l 如果FI的后一位为0, 那么:
更新PDULeft对象:SN = -1; SDUs 清空;
将完成重组的RLC SDU按序递交给高层;
l 否则FI的后一位为1,那么:更新PDULeft对象:
SN = x; SDUs = 当前重组后没有完成重组的RLC SDU;
² 否则,FI的第一位为0,且
l 如果FI的后一位为0,那么:
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
l 否则FI的后一位为1,那么:更新PDULeft对象:
SN = x; SDUs = 当前重组后没有完成重组的RLC SDU;
l 更新AMD_SegContext对象:(初始值)
² CSO = 0;
² SN = -1;
² LISN = 1;
² SO= 0;
l x = x+1;
l 循环回到第1步;
Ø 否则E域==1,即该SN的AMD PDU有多个数据域元素,那么:
n 检查AMD_SegContext对象的SN是否指示接收窗外最小的SN:
² 如果SN = = x, 即在上次重组过程中,该RLC PDUs的一部分连续的字节分段已经被重组为RLC SDU,那么:
l 如果LISN = 0,即剩下的RLC PDUs对应于原AMD PDU的最后的数据域元素,那么:
设置循环变量E=0;(转到(1))
² 否则, SN=x的RLC PDUs不是最小SN的AMD PDU分段。
n (1)执行循环:循环结束条件为 E = = 0,(循环变量E初始为1),在循环体里,执行:
l 根据AMD_SegContext对象的LISN,找到AMD PDU分段头扩展部分的第LISN个E和LI域;
l 更新循环变量E = 第LISN个E域;
l 计算得到长度为LI的连续字节分段,返回当前的AMD PDU分段的SO;(计算时, 用到SO和AMD PDU分段长)
l 检查CSO, 判断这些连续的字节分段是否从第一个字节分段开始的,即:
² 如果CSO = =0 且分段头FI的第一位为1, 即这些第一个连续字节分段是一个SDU的后面分段, 显然PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
将这2个SDU分段按序重组为RLC SDU;
将该完成重组的RLC SDU按序递交给高层;
² 否则,CSO != 0 或FI的第一位为0,那么:
把这些连续字节分段重组为RLC SDU;
将该完成重组的RLC SDU按序递交给高层;
l 更新PDULeft对象:SN = -1; SDUs 清空;
l 更新AMD_SegContext对象:
u CSO = CSO +LI;
u 如果E=1, LISN ++;否则LISN = 0;
u 如果LI = = length – CSO,
SO=当前AMD PDU分段的SO+分段长度;
否则(LI < length – CSO)
SO=当前AMD PDU分段的SO;
l 循环回到(1);
n 循环结束后,即循环变量E = 0,那么剩下的RLC PDUs正好对应于原AMD PDU的最后的数据域元素, 那么:
l 执行循环,循环结束条件为LSF = 1,LSF初始为0, 每次循环,循环体里执行:
(按SO升序)得到对应的AMD PDU分段;
(按序)把当前AMD PDU分段的数据域串接,从而重组为RLC SDU;
LSF = 当前AMD PDU分段头的LSF域;
l 继续检查分段头FI域
² 如果FI的后一位为0,那么:
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
² 否则FI的后一位为1,那么:更新PDULeft对象:
SN = x; SDUs = 当前重组后没有完成重组的RLC SDU;
l 更新AMD_SegContext对象:(初始值)
² CSO = 0;
² SN = -1;
² LISN = 1;
² SO= 0;
l x = x+1;
l 循环回到第1步;
2. 如果RLC PDU头RF域=0,检查SN=x(x<VR(R))的AMD PDU头FI和E域, 即:
Ø 如果E = = 0,该AMD PDU只有一个数据域元素,又
² 如果FI的第一位为1,那么该AMD PDU的第一个数据域元素是一个SDU的后面分段, 显然PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
去掉PDU头, 将这2个SDU分段按序重组(SN升序)为RLC SDU; 这时,
l 如果FI的后一位为0, 那么:
更新PDULeft对象:SN = -1; SDUs 清空;
将完成重组的RLC SDU按序递交给高层;
l 否则FI的后一位为1,那么更新PDULeft对象:
SN = x; SDUs = 当前重组后没有完成重组的RLC SDU;
² 否则,FI的第一位为0,那么:
去掉PDU头,把PDU的数据域直接重组为RLC SDU;这时,
l 如果FI的后一位为0,那么:
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
l 否则FI的后一位为1,那么:
更新PDULeft对象: SN = x;
SDUs = 当前重组后没有完成重组的RLC SDU;
x = x+1;
循环回到第1步;
Ø 否则E=1,该UMD PDU有多个数据域元素, 那么:
(一) 遍历PDU头扩展部分第一个数据域元素的E和LI域,该数据域元素
长度 = LI; 然后判断:
² 如果FI的第一位为1,该UMD PDU的第一个数据域元素是一个SDU的后面分段, 显然PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
将这2个SDU分段按序重组为RLC SDU;
将完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
² 否则FI的第一位为0,那么:
把第一个数据域元素直接重组为RLC SDU;
将完成重组的RLC SDU按序递交给高层;
(二) 检查当前遍历的E域, 循环执行下面的操作:
Ø 如果E==0,该AMD PDU只剩下的最后一个数据域元素,那么:
把PDU的最后一个数据域元素直接重组为RLC SDU;
² 如果FI的后一位为0,那么:
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
² 否则FI的后一位为1,那么:
更新PDULeft对象: SN = x;
SDUs = 当前重组后没有完成重组的RLC SDU;
x = x+1;
循环回到第1步;
Ø 否则E==1,该UMD PDU还剩下多个数据域元素,那么:
按序遍历PDU头的扩展部分下一个数据域元素的E和LI域, 下一个数据域元素长度 = LI;
直接把下一个数据域元素重组为一个完整的RLC SDU;
将该完成重组的RLC SDU按序递交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
循环回到(二)。
第2步: 尝试对SN = VR(R)的未完整接收的AMD PDU的连续字节分段进行重
组:
有下面的例子:对SN = VR(R)的未完整接收的AMD PDU的连续字节分段进行重组, 第3个分段还没有接收到。
- 如果没有接收到SN=VR(R)的AMD PDU任何字节分段, RLC SDU重组结束,返回。
- 否则, 尝试对 从AMD PDU第一个字节分段开始的连续的字节分段进行重组,第一个不连续的字节分段之后的所有字节分段不进行重组,那么:
检查所有的AMD PDU分段头的SO:
Ø 如果最小的SO > 0,不对该AMD PDU的任何字节分段进行重组,
RLC SDU重组结束,返回。
Ø 如果最小的SO = = 0,那么:检查AMD PDU分段头E域:
² 如果E==0, 即SN=VR(R)的 AMD PDU只有一个数据域元素, 显然这些字节分段不能被重组,那么:
RLC SDU重组结束,返回。
² 否则E==1,即SN=VR(R)的 AMD PDU有多个数据域元素,那么:
l 计算未被重组的连续AMD PDU分段的总长度(设为length);
l (1)执行结束条件为E=0的循环(表示遍历到AMD PDU的最后的未完整接收的数据域元素),在循环体里,执行:
n 得到AMD PDU分段头扩展部分的第LISN个E和LI域;
n 更新循环条件的E=当前E域;
n 比较LI 和 length – CSO,即:
Ø 如果LI =< length - CSO, 从CSO开始长度为LI的连续字节分段可以被重组, 那么:
计算得到长度为LI的连续字节分段,以及当前的AMD PDU分段的SO
² 如果CSO = =0 且分段头FI的第一位为1, 即这些第一个连续字节分段是一个SDU的后面分段, 显然PDULeft对象的SDUs成员保留了该SDU的前面分段,那么:
将这2个SDU分段按序重组为RLC SDU;
将该完成重组的RLC SDU按序递交给高层;
² 否则,CSO != 0 或FI的第一位为0,那么:
把这些连续字节分段重组为RLC SDU;
将该完成重组的RLC SDU按序递交给高层;
n 更新PDULeft对象:SN = -1; SDUs 清空;
n 更新length:length = length – LI;
n 更新AMD_SegContext对象:
u CSO = CSO +LI;
u SN = VR(R);
u 如果E=1, LISN ++;否则LISN = 0;
u 如果LI = = length – CSO,
SO=当前AMD PDU分段的SO+分段长度;
否则(LI < length – CSO)
SO=当前AMD PDU分段的SO;
n 循环回到(1);
Ø 如果LI > length - CSO, 没有满足长度为LI的连续字节分段, 那么:
退出循环, RLC SDU重组结束。
l 循环结束, 返回。
最后,关于上面的例子:
RLC SDU 1、 RLC SDU 2 提交给高层;
更新PDULeft对象:SN = -1; SDUs 清空;
更新AMD_SegContext对象:
u CSO = LI1 + LI2 ;
u SN = VR(R);
u LISN = 3;
u SO = 数据1长
3 实例
一、 分段和串接
最主要的就是要确定RLC PDU头的位域
RLC PDU 数据域只有一个RLC SDU或RLC SDU分段
SN=1:数据域刚好是一个RLC SDU前面部分分段
PDU头只有固定部分
FI = 01,E=0,SN= VT(US)或VT(S)
对AM PDU,确定D/C域 = 1, RF域 = 0
SN=3:数据域刚好是一个RLC S
展开阅读全文