当使用Enhanced Retransmission mode、Streaming mode、Flow Control mode或者Retransmission mode时,将会用到这部分的程序,其中包括I-frame的编号、SDU的分割和重组、错误帧的检测和通知,Retransmission mode和Enhanced Retransmission mode还会用到错误帧的重发
8.1 INFORMATION RETRIEVAL
一个L2CAP channel要配置为Enhanced Retransmission mode、Streaming mode、Flow Control mode或者Retransmission mode之前,首先需要使用INFORMATION REQUEST command确定“Extended features supported”(information type为0x0002)中支持相关的mode。在INFORMATION RESPONSE(information type为0x0002)中会回复,如下图所示:
8.2 FUNCTION OF PDU TYPES FOR FLOW CONTROL AND RETRANSMISSION
Enhanced Retransmission mode、Streaming Mode、Flow Control Mode和Retransmission mode会用到两种类型的frame:I-frame和S-frame,其中I-frame代替B-frame用来发送information,S-frame用来监控管理。
8.2.1 Information frame (I-frame)
I-frame是一种有连续编号的frame,其中包含information字段。I-frame还包括一部分S-frame的RR frame的功能,具体参考RR frame
8.2.2 Supervisory Frame (S-frame)
S-frame是用来控制I-frame传输的
Streaming mode时,不使用S-frame
Retransmission mode和Flow Control mode时,S-frame有两种格式:Receiver Ready (RR)和Reject (REJ)
Enhanced Retransmission mode时,S-frame有4种格式:Receiver Ready (RR)、Reject (REJ)、Receiver Not Ready (RNR)、Selective Reject (SREJ),这部分在8.6.1会解释。
8.2.2.1 Receiver Ready (RR)
作用:
(1)告知已经收到的I-frames的编号已经到达ReqSeq - 1
(2)通过更新Retransmission Disable Bit,开启或者禁用I-frames的重发
注意:RR frame没有information field.
8.2.2.2 Reject (REJ)
作用:请求重发从TxSeq(与REJ中ReqSeq字段值相同)开始的所有I-frame,例如发送端已经发送了TxSeq=9的I-frame,但是收到REJ中ReqSeq=7,则发送端需要重发7、8、9三个I-frame,REJ发送以后会触发一个REJ Exception条件,这个条件不清除不能发送第二个REJ frame,当收到的I-frame的TxSeq等于REJ frame的ReqSeq的时候,这个条件会被清除,REJ Exception只是单方向的。
8.3 VARIABLES AND SEQUENCE NUMBERS
(一)发送端使用的变量和序号如下:
(1)TxSeq:表示每次发送一个新的I-frame时使用的序号,每个I-frame都包含TxSeq,当第一次发送I-frame时,TxSeq= NextTxSeq,如果I-frame被重发则TxSeq不变。
(2)NextTxSeq:表示下一个将要发送的I-frame使用的序号,连接被建立时,这个值应该是0,每发送完一个I-frame,NextTxSeq的值加1,NextTxSeq<=(ExpectedAckSeq+ TxWindow),其中TxWindow表示发送但未被识别的I-frame的数量。Retransmission mode和Flow Control mode时,TxWindow取值范围(1-32),Enhanced Retransmission mode时,TxWindow取值范围(1-63)
(3)ExpectedAckSeq:表示下一个预期被接收端识别的I-frame的序号,最后一个被识别的I-frame的TxSeq等于ExpectedAckSeq–1,连接被建立时,这个值应该是0,当接收端识别TxSeq= ExpectedAckSeq的I-frame时,接收端回复的识别帧的ReqSeq=ExpectedAckSeq+1,当这个识别帧被发送端收到时,发送端的ExpectedAckSeq会设置为识别帧的ReqSeq(例如:发送端发送了TxSeq=5的I-frame,接收端已经识别了TxSeq=4及以前的I-frame,此时ExpectedAckSeq=5,当接收端识别TxSeq=5的I-frame时,接收端需要回复一个I-frame或者S-frame,因为已经识别了TxSeq=5及以前的I-frame,所以此时ReqSeq=6即ExpectedAckSeq+1,当发送端收到这个识别帧时,发送端知道接收端已经识别了TxSeq=5及以前的I-frame,所以ExpectedAckSeq=6,即ExpectedAckSeq等于识别帧的ReqSeq),ExpectedAckSeq≤ReqSeq≤NextTxSeq(注意:为了方便理解不要考虑这些变量的取值范围)
如下图所示:
上图中
TxWindow:值为5
F1:已经别接收端识别的I-frame
F2、F3、F4、F5、F6:已经发送但是未被接收端识别的I-frame,所以F2是下一个期望被接收端识别的I-frame,即ExpectedAckSeq
F7、F8、F9:等待发送的3个I-frame,所以F7应该是下一个将要发送的I-frame
NextTXSeq,当F2被识别时,就可以发送F7了,F7的TxSeq=NextTXSeq,F7发送后,NextTXSeq会加1
(二)接收端使用的变量和序号:
ReqSeq:表示请求发送端发送序列号值为ReqSeq的I-frame(即请求发送端发送一个I-frame,这个I-frame的TxSeq就这个ReqSeq的值),同时也表示接收端已经识别了ReqSeq-1及之前的frame,I-frame和S-frame中都包含ReqSeq字段。接收端发送识别帧(I-frame或者S-frame)时,ReqSeq= ExpectedTxSeq(或者BufferSeq),当ReqSeq=BufferSeq时,如果BufferSeq!= ExpectedTxSeq,则接收端需要设置Retransmission Disable Bit=1来避免不必要的重发。
ExpectedTxSeq:表示下一个预期会收到的I-frame的TxSeq
BufferSeq:当接收端缓冲区有限,接收端收到的I-frame存在于缓冲区中一段时间后,上层应用不能及时的从缓冲区获取I-frame,此时用BufferSeq表示即将被上层应用获取的I-frame,当缓冲区没有额外的I-frame并且上层应用能快速获取并识别I-frame时BufferSeq = ExpectedTxSeq,当缓冲区中有多余的未被上层获取的I-frame时,为了防止缓冲区溢出,接收端可能不会设置ReqSeq = ExpectedTxSeq而设置ReqSeq=BufferSeq,此时BufferSeq增加就表示有缓冲区被释放。当ExpectedTxSeq – BufferSeq = TxWindow时,就应该停止数据传输了。接收端收到的I-frame的TxSeq应该满足:ExpectedTxSeq ≤ TxSeq < (BufferSeq + TxWindow),无论之前收到的I-frame的TxSeq比ExpectedTxSeq大多少,只要当前收到的I-frame的TxSeq= ExpectedTxSeq,则ExpectedTxSeq加1
如下图所示:
TxWindow:值为5
F1:表示成功接收并被上层应用获取的I-frame
F2:表示已经成功接收,下一个将被上层应用获取的I-frame,即BufferSeq
F3:表示已经成功接收,没有被上层应用获取的I-frame
F4:表示希望接收到下一个I-frame,即ExpectedTxSeq
F5、F6:表示接收到的异常的I-frame,F4还没有接收到,但是已经接收到了F5和F6,所以需要触发SREJ或者REJ异常,同时丢弃F5和F6,F5和F6会被重发
F7、F8、F9:表示异常帧。由于TxWindow已经满了,在Retransmission mode或者Flow Control mode时,接收端需要设置Retransmission Disable Bit为1,并给发送端发送RR帧,告诉发送端停止无意义的重发,发送和接收端都会发送S-Frame来确定对方已经知道了Retransmission Disable Bit的当前值
注意:所有变量的取值范围是0-63,分为状态变量(NextTXSeq, ExpectedTxSeq, ExpectedAckSeq, BufferSeq)和序号(TxSeq, ReqSeq)
8.4 RETRANSMISSION MODE
8.4.1 Transmitting frames(发送I-frame)
发送的一些条件:
(A)只有TxWindow未满时才可以发送新的I-frame。
(B)RetransmissionDisableBit(R)为1,不能发送I-frame
(C)即使当前TxWindow已满,I-frame依然可以被重发。I-frame重发时,I-frame的TxSeq应该与之前发送时一样。
(D)具体如何发送I-frame,由RetransmissionDisableBit(R)和RetransmissionTimer决定
发送I-frame主要分两种情况:
(1)RetransmissionDisableBit(R)为0(可以发送I-frame)时,根据RetransmissionTimer的使用情况,分为两种情况:
(A)RetransmissionTimer使用的情况下:
(a)已发送的一个或者多个I-frame未被识别,RetransmissionTimer超时,则需要重发一个未识别的I-frame,同时RetransmissionTimer重新开始
(b)已发送的一个或者多个I-frame未被识别,RetransmissionTimer未超时,如果有等待发送的I-frame,则可以发送一个新的I-frame,RetransmissionTimer不需要进行任何操作
(c)已发送的I-frame都已被识别,有等待发送的I-frame,则可以发送一个新的I-frame,同时启动RetransmissionTimer,如果此时MonitorTimer正在运行,则停止MonitorTimer
(d)已发送的I-frame都已被识别,没有等待发送的I-frame,RetransmissionTimer正在运行,则应该停止RetransmissionTimer,并启动MonitorTimer
下图解释了当使用RetransmissionTimer并且R=0时的动作
(B)RetransmissionTimer未使用的情况下:
(a)没有等待发送的I-frame,MonitorTimer正在运行,并且没有超时,此时不需要有任何动作
(b)没有等待发送的I-frame,MonitorTimer超时,然后需要发送一个S-frame,并且重新开始MonitorTimer
(c)有等待的I-frame需要发送时,停止MonitorTimer,并开始RetransmissionTimer,I-frame发送时,ReqSeq设置为ExpectedTxSeq,TxSeq设置为NextTxSeq,然后NextTxSeq加1
(2)RetransmissionDisableBit(R)为1(不可以发送I-frame,只能发送S-frame)时:
此时S-frame发送规则如下:
(a)如果MonitorTimer正在运行,且没有超时,此时不需要有任何动作
(b)如果MonitorTimer超时,此时需要发送一个S-frame,并重新开始MonitorTimer
8.4.2 Receiving I-frames(接收I-frame)
收到I-frame,正常情况下TxSeq=ExpectedTxSeq;
发送REJ后收到的第一个I-frame,TxSeq=ReqSeq(REJ的),同时清空REJ Exception,TxSeq!=ExpectedTxSeq时,会触发一个异常,具体参考8.4.7。
8.4.3 I-frames pulled by the SDU reassembly function(SDU重组程序从缓冲区获取I-frame)
SDU重组程序从缓冲区获取I-frame后,L2CAP层会从缓冲区移除相应数量的I-frame,BufferSeq可能根据缓冲区释放的大小增加一定的数量。当BufferSeq增加时,需要向对方设备发送识别帧。识别帧可以是RR frame也可以是一个I-frame,识别帧的ReqSeq=BufferSeq。当ExpectedTxSeq=BufferSeq时,表示缓冲区已经没有I-frame。发送识别帧后,如果MonitorTimer正在运行中,则重新开始MonitorTimer
注意:因为BufferSeq的主要作用是为了防止缓冲区溢出,所以可能根据还能保存多少新的I-frame来设置BufferSeq,而不根据已经释放了多少缓冲区
8.4.4 Sending and receiving acknowledgements(发送和接收识别帧)
同一时间MonitorTimer和RetransmissionTimer只能使用一个,不能同时使用
(1)Sending acknowledgements(发送识别帧),任何时候,发送I-frame和S-frame,需要设置ReqSeq=ExpectedTxSeq或者BufferSeq
(2)Receiving acknowledgements(接收识别帧),接收到S-frame或者I-frame,并且其中的ReqSeq=A,则表示TxSeq= A–1及之前的I-frame都被识别了,同时设置ExpectedAckSeq=A,另外:
如果RetransmissionDisableBit的值从0变成1 (停止重发),本地设备则进行如下操作:
(a)如果RetransmissionTimer正在运行,则停止RetransmissionTimer,开始MonitorTimer
(b)保存收到的RetransmissionDisableBit的值
如果RetransmissionDisableBit的值从1变成0 (开始重发),本地设备则进行如下操作:
(a)保存收到的RetransmissionDisableBit的值
(b)如果发送了I-frame并且未被识别,则停止MonitorTimer,开始RetransmissionTimer
(c)发送I-frames要根据8.4.1的的描述进行操作
如果收到识别帧的ReqSeq表示所有的I-frame都被识别了,RetransmissionDisableBit = 1(停止重发), 此时发送I-frame要根据8.4.1的的描述进行操作
如果收到识别帧的ReqSeq表示所有的I-frame都被识别了,RetransmissionDisableBit = 0(开始重发),本地设备则进行如下操作
(a)如果RetransmissionTimer正在运行,则停止
(b)如果发送了I-frames并且未被识别,则开始RetransmissionTimer
(c)发送I-frames要根据8.4.1的的描述进行操作
(d)如果RetransmissionTimer和MonitorTimer都没有运行,则开始MonitorTimer.
8.4.5 Receiving REJ frames(接收到REJ frame)
当收到REJ frame时, 假设REJ frame中的ReqSeq=A,那么就表示本地发送的TxSeq=A的I-frame未被识别,TxSeq=A-1及以前的I-frame已经被识别,此时本地应该设置ExpectedAckSeq=ReqSeq,NextTXSeq=ReqSeq
如果收到REJ frame的ReqSeq=ExpectedAckSeq,则REJ frame应该被忽略
8.4.6 Waiting acknowledgements(等待识别帧)
有一个计数器TransmitCounter,用来记录一个L2CAP PDU发送的次数,L2CAP PDU第一次发送时应该设置TransmitCounter=1,当RetransmissionTimer超时时,如果TransmitCounter<MaxTransmit,则TransmitCounter+1,然后重发这个未识别的I-frame;如果TransmitCounter=MaxTransmit,则channel设置为CLOSE状态并通知上层
8.4.7 Exception conditions(异常处理)
(1)TxSeq Sequence error(I-frame中TxSeq序号错误,即TxSeq!= ExpectedTxSeq)分为3种情况:
第一种:重复的I-frame,即收到的I-frame的TxSeq范围在BufferSeq ≤TxSeq<ExpectedTxSeq内,由于这个I-frame之前已经接收到了,所以这个I-frame的Information field应该丢弃
第二种:无序的I-frame,即收到的I-frame的TxSeq范围在ExpectedTxSeq<TxSeq<(BufferSeq + TxWindow)内,这个I-frame应该丢弃丢弃,并触发一个REJ异常,同时回复一个REJ frame(ReqSeq=ExpectedTxSeq)
第三种:无效的TxSeq,即TxSeq不在BufferSeq ≤TxSeq<ExpectedTxSeq范围内,也不在ExpectedTxSeq < TxSeq < (BufferSeq + TxWindow)范围内,这种I-frame直接丢弃
(2)ReqSeq Sequence error(ReqSeq序号错误)
当收到的S-frame或者I-frame的ReqSeq不在ExpectedAckSeq ≤ ReqSeq ≤ NextTxSeq范围内,此时应该关闭channel
(3)Timer recovery error(定时器恢复异常)
如果L2CAP实体发送I-frame没有收到识别帧,那么它将不会检测到序列异常,也就不会发送REJ帧,因此当L2CAP实体发送I-frame没有收到识别帧,在RetransmissionTimer超时时,应该按照8.4.6的描述进行操作
发送了I-frame并未被识别,RetransmissionTimer超时时会触发异常。
(4)Invalid frame(无效的I-frame或者S-frame)
当收到的I-frame或者S-frame符合下面的条件时直接丢弃:
(a)CID未知
(b)FCS校验错误
(c)length字段值大于maximum PDU payload size (MPS)
(d)I-frame少于8个字节(SAR=01b即Start of L2CAP SDU时少于10个字节)
(e)I-frame并且有SAR字段时,SAR的值没有定义(即不是00b Unsegmented L2CAP SDU、01b Start of L2CAP SDU、10b End of L2CAP SDU、11b Continuation of L2CAP SDU)
(f)S-frame长度不等于4.
8.5 FLOW CONTROL MODE
Flow Control mode跟Retransmission mode比较相似,主要有下面几个区别
(A)Flow Control mode不进行CRC校验
(B)Flow Control mode不会用到REJ frame
(C)Flow Control mode时,RetransmissionDisableBit一直都是0,并且应该忽略
假设TxWindow的size=接收端可用缓冲区,那么在Flow Control mode时,发送端发送的未识别的I-frame的总size<=接收端可用缓冲区,丢失的I-frame也占用TxWindow,如下图所示:
Frame 1:表示已接收并被重组程序获取I-frame
Frame 2:表示已接收的下一个即将被重组程序获取的I-frame
Frame 3、5:表示已接收且未被重组程序获取I-frame
Frame 4:丢失的I-frame
Frame 6:表示下一个希望收到的I-frame,即ExpectedTxSeq
Frame 7、8、9:无效的I-frame
8.5.1 Transmitting I-frames(发送I-frame)
发送条件:只有TxWindow未满时才可以发送新的I-frame。
当发送I-frame时,如果没有未识别的I-frame,则停止MonitorTimer,并开始RetransmissionTimer;如果有未识别的I-frame,则继续保持RetransmissionTimer。
发送的I-frame的ReqSeq=ExpectedTxSeq,TxSeq=NextTXSeq,然后NextTXSeq加1
8.5.2 Receiving I-frames(接收I-frame)
正常情况下,接收到的I-frame的TxSeq= ExpectedTxSeq,然后ExpectedTxSeq加1,一直到SDU重组程序将这个I-frame从缓冲区拿走后,才能发送识别帧。
当收到的I-frame的TxSeq无序时,所有小于TxSeq的I-frame会被认为丢失了。丢失的I-frame的编号从ExpectedTxSeq到TxSeq-1,然后ExpectedTxSeq=TxSeq +1,
8.5.3 I-frames pulled by the SDU reassembly function(SDU重组程序从缓冲区获取I-frame)
SDU重组程序从缓冲区获取I-frame后,L2CAP层会从缓冲区移除相应数量的I-frame,BufferSeq可能根据缓冲区释放的大小增加一定的数量。当BufferSeq增加时,需要向对方设备发送识别帧。识别帧可以是RR frame也可以是一个I-frame,识别帧的ReqSeq=BufferSeq。当ExpectedTxSeq=BufferSeq时,表示缓冲区已经没有I-frame。发送识别帧后,如果MonitorTimer正在运行中,则重新开始MonitorTimer
注意:因为BufferSeq的主要作用是为了防止缓冲区溢出,所以可能根据还能保存多少新的I-frame来设置BufferSeq,而不根据已经释放了多少缓冲区
8.5.4 Sending and receiving acknowledgements(发送和接收识别帧)
Flow Control mode下,同一时间MonitorTimer和RetransmissionTimer只能使用一个,不能同时使用
8.5.4.1 Sending acknowledgements(发送识别帧)
发送识别帧(I-frame或者S-frame),识别帧的ReqSeq=ExpectedTxSeq或者BufferSeq
8.5.4.2 Receiving acknowledgements(接收识别帧)
接收到S-frame或者I-frame,并且其中的ReqSeq=A,则表示TxSeq= A–1及之前的I-frame都被识别了,同时设置ExpectedAckSeq=A,如果识别帧显示有I-frame被识别,则:
(a)首先停止RetransmissionTimer
(b)然后,如果依然存在未识别的I-frame,则重新开始RetransmissionTimer,否则开始MonitorTimer
(c)继续发送I-frame根据8.5.1
8.5.5 Waiting acknowledgements(等待识别帧)
如果RetransmissionTimer超时,则表示RetransmissionTimer本次监控的I-frame丢失了,此时ExpectedAckSeq加1
RetransmissionTimer超时时,如果有等待发送的I-frame,则:
(a)重新开始RetransmissionTimer
(b)根据8.5.1的描述发送I-frames
RetransmissionTimer超时时,如果没有等待发送的I-frame,则:
(a)有未识别的I-frame,则重新开始RetransmissionTimer,否则开始MonitorTimer
8.5.6 Exception conditions(异常处理)
(1)TxSeq Sequence error(I-frame中TxSeq序号错误,即TxSeq!= ExpectedTxSeq)分为3种情况:
第一种:重复的I-frame,即收到的I-frame的TxSeq范围在BufferSeq ≤TxSeq<ExpectedTxSeq内,由于这个I-frame之前已经接收到了,所以这个I-frame的Information field应该丢弃
第二种:无序的I-frame,即收到的I-frame的TxSeq范围在ExpectedTxSeq<TxSeq<(BufferSeq + TxWindow)内,表示编号从ExpectedTxSeq到TxSeq-1的I-frame都丢失了,ExpectedTXSeq= TxSeq+1
第三种:无效的TxSeq,即TxSeq不在BufferSeq ≤TxSeq<ExpectedTxSeq范围内,也不在ExpectedTxSeq < TxSeq < (BufferSeq + TxWindow)范围内,这种I-frame直接丢弃
(2)ReqSeq Sequence error(ReqSeq序号错误)
当收到的S-frame或者I-frame的ReqSeq不在ExpectedAckSeq ≤ ReqSeq ≤ NextTxSeq范围内,此时应该关闭channel
因此当L2CAP实体发送I-frame没有收到识别帧,在RetransmissionTimer超时时,应该按照8.5.5的描述进行操作
(3)Invalid frame(无效的I-frame或者S-frame)
当收到的I-frame或者S-frame符合下面的条件时,直接丢弃:
(a)CID未知
(b)FCS校验错误
(c)length字段值大于maximum PDU payload size (MPS)
(d)I-frame少于8个字节(SAR=01b即Start of L2CAP SDU时少于10个字节)
(e)I-frame并且有SAR字段时,SAR的值没有定义(即不是00b Unsegmented L2CAP SDU、01b Start of L2CAP SDU、10b End of L2CAP SDU、11b Continuation of L2CAP SDU)
(f)S-frame长度不等于4.
注意:如果接收端L2CAP配置为将错误帧发送到上层,则无效帧里面的数据可能会被放到接收缓冲区,并被SDU重组程序获取。