八、PROCEDURES FOR FLOW CONTROL AND RETRANSMISSION(二)

8.6 ENHANCED RETRANSMISSION MODE

Enhanced Retransmission mode类似于一种HDLC均衡数据连接操作模式,任何一个L2CAP实体可能在任何时候发送frames而不需要经过其他L2CAP实体的允许。一次可以传输一个或者多个I-frame

8.6.1 Function Of PDU Types

Enhanced Retransmission mode使用I-frame传输上层数据,使用S-frame进行监督管理,S-frames分为四种:Receiver Ready (RR)、Reject (REJ)、Receiver Not Ready (RNR)、Selective Reject (SREJ). Enhanced Retransmission mode所有frame的格式中都用Enhanced Control Field.

8.6.1.1 Receiver Ready (RR)

RR frame的作用:

(1)表明已经准备好接收I-frame;

(2)表明编号(TxSeq)小于等于ReqSeq – 1的所有I-frame已经被识别;

(3)L2CAP实体发送P-bit=1(P=1)的RR frame,表示清除自己之前发送RNR frame而导致的忙碌异常;

8.6.1.2 Reject (REJ)

      REJ frame作用:

(1)L2CAP实体发送REJ frame用来请求重发编号从ReqSeq开始的I-frame;

(2)表明编号(TxSeq)小于等于ReqSeq - 1的I-frame已经被识别;

(3)其余在等待传输的I-frame会在重传的I-frame之后发送;

注意:

(1)在一定时间内,一个L2CAP实体到另一个L2CAP识别的REJ frame最多只能有一个,如果之前已经有一个REJ异常或者一个或多个SREJ异常没有被清除,则不能再次发送REJ frame;

(2)当收到一个I-frame的TxSeq=ReqSeq(REJ frame的)时,REJ异常条件清除;

(3)互相连接的两个L2CAP实体可能同时处于REJ异常;

8.6.1.3 Receiver Not Ready (RNR)

RNR frame作用:

(1)L2CAP实体发送RNR frame表明自己处于忙碌状态(即临时无法接收I-frames);

(2)表明编号(TxSeq)小于等于ReqSeq - 1的I-frame已经被识别,已发送的编号(TxSeq)大于等于ReqSeq的I-frame未被识别;

(3)未被识别的I-frame的验收状态会在后续传输过程中通知;

8.6.1.4 Selective Reject (SREJ)

SREJ frame作用:

(1)L2CAP实体发送SREJ frame用来请求重发一个I-frame;

(2)SREJ frame的ReqSeq表示请求重发的I-frame的TxSeq=ReqSeq(SREJ frame的),这个I-frame必须是最原始的而不是被其他SREJ请求重发的;

(3)如果SREJ frame的P-bit=1,则表明编号(TxSeq)小于等于ReqSeq -1的I-frame已经被识别,如果SREJ frame的P-bit=0,ReqSeq不能表明哪些I-frame被识别;

注意:

(1)每个SREJ异常条件都会在收到一个I-frame的TxSeq=ReqSeq(这个SREJ frame的)时被清除;

(2)之前已经有一个或者多个P=0的SREJ frames的异常还未被清除的情况下,可以继续发送P=0的SREJ frames;

(3)在其他SREJ frames的异常未被清除之前最多只能发送一个P=1的SREJ frame;

(4)如果之前的REJ frame导致的异常还未清除,则不能发送SREJ frame,同样,如果之前的一个或者多个SREJ frames导致的异常还未清除,也不能发送REJ frame;

(5)收到一个P=0的SREJ frame只需要回复一个I-frame,但是其余正在等待发送的frame会在重发P=1的SREJ frames要求的那个I-frame之后发送;

8.6.1.5 Functions of the Poll (P) and Final (F) bits.

(1)P-bit=1,表示请求对方尽快回复一个F-bit=1的frame;

(2)在一段时间内,一个方向最多只能有一个未被处理的P=1的frame,即在L2CAP实体发送另外一个P=1的frame之前,上一个P=1的frame必须要收到一个来自对方的回复的F=1的frame,如果在Monitor-timeout时间内没有收到F=1的有效的frame,则可能会重发这个P=1的frame;

(3)F bit=1,表示这个frame是某个soliciting poll (S-frame的P=1)的回复。

(4)F=1的frame不能重发,所以Monitor-timeout不用检测丢失的F=1的frame

(5)S-frame的F-bit和P-bit不能同时设置为1

(6)其他F=0的frame在F=1的frame之后发送

8.6.2 Rules For Timers

8.6.2.1 Timer Rules for ACL-U Logical Links

前提是L2CAP channel是Enhanced Retransmission mode

如果flush timeout不存在,Retransmission timeout至少2s,Monitor time-out至少12s;

如果flush timeout存在,Retransmission timeout应该是flush timeout的3倍,并且1s<=Retransmission timeout<=2s;

如果flush timeout存在,并且两端设置了相同的flush timeout,Monitor time-out应该是flush timeout的6倍,并且Retransmission timeout<=Monitor time-out<=12s;

如果L2CAP识别发现一个packet被flushed了而不是发送出去了,则这个L2CAP实体可能会立即执行适当的错误校正程序

当在ACL-U逻辑链路上配置一个L2CAP channel时,发送的Configuration Request包中的Retransmission timeout和Monitor timeout应该设置为0

(如果两端的flush timout不同,那么Monitor timeout怎么设置?)

注意:如果一个连接L2CAP channel设置了flush timeout,并且Enhanced Retransmission mode的packet都用Non-Flushable Packet Boundary Flag feature标记了,那么就Enhanced Retransmission mode而言,这个L2CAP连接是没有flush timeout的

8.6.3 General Rules for the State Machine

Enhanced Retransmission mode使用了一对状态机:一个Transmitter state machine和一个Receiver state machine

8.6.4 State Diagram

8.6.5 States Tables

8.6.5.1 State Machines

Enhanced Retransmission mode使用了一对状态机,Receiver state machine处理所有收到的frame,Transmitter State machine处理所有异步event(包括来自上层的request、timer超时)

Receiver state machine使用PassToTx调用Transmitter state machine,而这个调用在Transmitter state machine就是一个event,当Transmitter state machine被调用时,它必须要处理完(所有动作都执行完并且Transmitter state变成新的state)才能返回Receiver state machine,Receiver state machine和Transmitter state machine共享变量和timer

8.6.5.2 States

RECV:Receiver state machine的主状态

REJ_SENT:L2CAP实体已经发送一个REJ frame,正在等待接收对方重发的I-frame,即TxSeq=ReqSeq(REJ frame的)的I-frame

SREJ_SENT:L2CAP实体已经发送一个或者多个SREJ frame,正在等待接收对方重发所有的SREJ frame请求TxSeq=ReqSeq(SREJ frame的)的I-frame,如果在SREJ_SENT state时检测到有其他的丢失的I-frame,则可以发送SREJ frames或者一个REJ frame来请求对方重发

XMIT:Transmitter state machine的主状态

WAIT_F:当本地busy状态已经清除(或者Retransmission timer超时)且已经发送了一个P=1的S-frame,本地L2CAP实体正在等待接收一个F=1的frame,在WAIT_F状态下不能发送I-frame,防止I-frame的重传导致L2CAP channel断开。

8.6.5.3 Variables and Timers

用到的一些操作符、连接符和语法,如下图所示:

注意:

:=           用来给变量赋值的

mod       取模操作(A mod B,即A除以B取余)

序号

变量

含义

1

TxSeq

 

2

NextTxSeq

 

3

ExpectedAckSeq

 

4

ReqSeq

 

5

ExpectedTxSeq

 

6

BufferSeq

 

7

RemoteBusy

RemoteBusy=TRUE表示本地L2CAP实体从远端L2CAP实体收到了一个RNR frame,即远端L2CAP实体处于busy状态,此时远端L2CAP实体收到I-frame很可能会丢弃,当本地L2CAP实体收到RR、REJ或者SREJ frame时,RemoteBusy设置为FALSE,此时,本地L2CAP实体认为远端L2CAP实体可以接收I-frame。L2CAP channel刚建立时RemoteBusy=FALSE。

8

LocalBusy

LocalBusy=TRUE表示本地L2CAP实体处于busy状态,此时本地L2CAP实体收到I-frame会丢弃,这个变量为FALSE时,表示本地L2CAP实体可以接收I-frame。L2CAP channel刚建立时LocalBusy=FALSE

9

UnackedFrames

保存未识别I-frame的数量。L2CAP channel刚建立时UnackedFrames=0

10

UnackedList

保存所有未识别的I-frame,方便重发,I-frame在UnackedList中存放是使用它们自己的TxSeq作为标记的。例如:UnackedList[5]存储的是TxSeq=5的I-frame

11

PendingFrames

保存挂起的I-frame的数量,由于远端L2CAP实体的TxWindow满了或者处于busy状态或者本地状态错误时,I-frame无法立即发送,它们就会存在一个队列里,等到条件允许时再发送。L2CAP channel刚建立时PendingFrames=0

12

SrejList

保存本地L2CAP实体使用SREJ frame请求重发的I-frame的TxSeq的链表,SrejList链表为空用SrejList=0表示,SrejList链表不为空,用SrejList>0表示

13

RetryCount

保存一个S-frame重发的次数。如果重发次数达到MaxTransmit还未成功则关闭L2CAP channel

14

RetryIframes[]

保存每个I-frame的重发次数,当一个I-frame重发时,RetryIframes中对应的计数器会增加,当要重发I-frame时,如果RetryIframes中对应的计数器值等于MaxTransmit则关闭L2CAP channel

15

RNRsent

这个变量为TRUE表示本地L2CAP实体已经发送了一个RNR frame,这个变量用来判断本地L2CAP实体是否需要向远端L2CAP实体发送一个RR frame来清除busy异常(RNRsent =TRUE则当busy异常清除时需要发送RR frame),当L2CAP channel刚建立时RNRsent=FALSE

16

RejActioned

作用:防止F=1的frame导致已重传的I-frame(作为REJ的回复)被再次重传。

收到一个REJ frame并已经执行了相应的action,同时当前还有一个已发送的P=1的frame但是还没有收到F=1的回复,此时设置RejActioned=TRUE。当L2CAP channel刚建立时RejActioned=false

17

SrejActioned

这个变量和SrejSaveReqSeq一起使用,作用:防止F=1的frame导致一个已重传的I-frame(作为SREJ的回复)被再次重传。

收到一个SREJ frame并已经执行了相应的action,同时当前还有一个已发送的P=1的frame但是还没有收到F=1的回复,此时设置SrejActioned=TRUE。当L2CAP channel刚建立时SrejActioned =false

18

SrejSaveReqSeq

用来保存SREJ frame的ReqSeq(导致SrejActioned设置为True的SREJ frame)

19

SendRej

本地L2CAP实体处于SREJ_SENT状态且正在处理收到的I-frame,当本地L2CAP实体决定发送REJ frame时,设置SendRej=TRUE。SendRej=TRUE则停止发送新的SREJ frame。当L2CAP channel刚建立时SendRej=FALSE

20

BufferSeqSrej

使用这个变量记录L2CAP实体退出SREJ_SENT state时,BufferSeq将要设置的值

21

FramesSent

记录由于Send-Data和Retransmit-I-frames动作而发送的I-frame的数量

22

MaxTxWin

即maximum window size加1,当使用Extended Window Size option时,这个值应该是16384 (0x4000),当不使用Extended Window Size option时,这个值应该是64

23

RetransTimer

即Retransmission Timer,用来检测丢失的I-frames,当L2CAP channel刚建立时RetransTimer应该是off

24

MonitorTimer

即Monitor Timer,用来检测丢失的S-frames,当L2CAP channel刚建立时MonitorTimer应该是off

8.6.5.4 Events

序号

Event

含义

1

Data-Request

上层请求发送一个SDU,SDU可能会根据远端设备的MPS或者HCI(或者QoS)允许使用的最大值来确定分解成几个I-frame

2

Local-Busy-Detected

由于某些原因本地L2CAP实体无法接收I-frame,此时就会产生一个local busy异常。这种情况时,一种实现是先不发送RNR frame,看在对方Retransmission timer超时前busy异常会不会清除,如果清除了,则发送一个RR frame或者I-frame作为识别帧,如果没有清除,远端会发送一个RR或者RNR poll,此时回复一个RNR frame,另一种实现是检测到local busy异常立即发送一个RNR frame

3

Local-Busy-Clear

当本地L2CAP实体缓冲区释放,可以接受I-frame时,local busy异常清除

4

Recv ReqSeqAndFbit

这个event是Receiver state machine产生的。表示收到一个包含ReqSeq和F-bit值的frame

5

Recv Fbit

这个event是Receiver state machine产生的。表示收到一个包含F-bit值的frame

6

RetransTimer-Expires

Retransmission Timer超时

7

MonitorTimer-Expires

Monitor Timer 超时

8

Recv I-frame

收到一个F-bit为任意值的I-frame

9

Recv RR, REJ, RNR, SREJ (P=x) or (F=x)

表示收到具体特定P或者F值的S-frame,P和F都为1的S-frame应该忽略,如果P和F没有指定,则任何值都可以

10

Recv RRorRNR

收到一个RR或者RNR的S-frame,P和F为任意值

11

Recv REJorSREJ

收到一个REJ或者SREJ,P和F为任意值

12

Recv frame

这个event表示收到任何frame

8.6.5.5 Conditions

序号

Conditions

含义

1

RemoteBusy = TRUE or FALSE

TRUE表示远端L2CAP实体处于busy异常,FLASE表示远端L2CAP实体未处于busy异常

2

LocalBusy = TRUE or FALSE

TRUE表示本地L2CAP实体处于busy异常,FLASE表示本地L2CAP实体未处于busy异常

3

RemWindow-Not-Full

本地L2CAP实体发送的未识别的I-frame的数量还未达到远端L2CAP实体的TxWindow size

4

RemWindow-Full

本地L2CAP实体发送的未识别的I-frame的数量达到远端L2CAP实体的TxWindow size,此时不能再发送I-frame,需要等待识别帧确定一个或者多个I-frame被识别,才能再次发送

5

RNRsent = TRUE or FALSE

TRUE表示当local busy异常存在时已经发送了一个RNR,设置为FALSE表示local busy异常已经清除

6

F = 0 or 1

检测收到的frame的F-bit的值

7

RetryIframes[i] < or ≥ MaxTransmit

判断RetryIframes适当的计数器是否超过MaxTransmit

8

RetryCount < or ≥ MaxTransmit

判断RetryCount是否超过MaxTransmit

9

With-Expected-TxSeq

收到的I-frame的TxSeq=ExpectedTxSeq

10

With-Valid-ReqSeq

收到的frame的ReqSeq是有效的,即ExpectedAckSeq ≤ ReqSeq < NextTxSeq

11

With-Valid-ReqSeq-Retrans

收到的frame的ReqSeq是有效的,即ExpectedAckSeq ≤ ReqSeq < NextTxSeq

12

With-Valid-F-bit

如果收到的frame的F-bit=0,则是有效的,如果收到的frame的F-bit=1并且发送的P=1的frame还没有收到答复,则是有效的(例如:本地L2CAP实体发送了一个P=1的frame,但是没有收到F=1的frame)。如果Transmitter state machine当前是WAIT_F state,此时表示P=1的frame已经发送但没有收到答复

13

With-unexpected-TxSeq

收到的I-frame的TxSeq>ExpectedTxSeq,但是TxSeq还在接收端TxWindow范围内

14

With-duplicate-TxSeq

表示收到的I-frame的TxSeq<ExpectedTxSeq,即这个I-frame之前已经收到了

15

With-Invalid-TxSeq

表示收到的I-frame的TxSeq已经超出接收端I-frame的TxWindow

16

With-Invalid-ReqSeq

表示收到的frame的ReqSeq是无效的,ReqSeq即不在ExpectedAckSeq ≤ ReqSeq < NextTxSeq范围内

17

With-Invalid-ReqSeq-Retrans

表示收到的frame的ReqSeq是无效的,ReqSeq即不在ExpectedAckSeq ≤ ReqSeq < NextTxSeq范围内

18

Not-With-Expected-TxSeq

表示收到的I-frame的TxSeq还在接收端TxWindow范围内,但是不等于ExpectedTxSeq,可能是unexpected也可能是重复的,二选一

19

With-Expected-TxSeq-Srej

表示收到的I-frame的TxSeq等于SrejList链表头元素的值

20

SendRej = TRUE or FALSE

TRUE表示所有使用SREJ请求的I-frame收到后,将会发送REJ

21

SrejList = or > 1

判断SrejList中的元素个数是否大于等于1

22

With-Unexpected-TxSeq-Srej

表示收到的I-frame的TxSeq等于SrejList链表中的某一个,但是却不是SrejList链表头的那个,这表明一个或者多个SREJ请求重发的I-frame丢失了,可能是SREJ丢失了,也可能是SREJ请求的I-frame丢失了,不管是哪种情况,对应的SREJ都要重新发送去请求丢失的I-frame重发

23

With-duplicate-TxSeq-Srej

表示收到的I-frame的TxSeq等于某个已经存储的I-frame的TxSeq,即这个I-frame重复了

8.6.5.6 Actions

序号

Action

含义

1

Send-Data

这个action是收到Data-Request event时被执行的。I-frame发送的未被识别的数量不能超过接收端L2CAP实体的TxWindow size(即UnackedFrames要小于等于接收端L2CAP实体的TxWindow size)。超过接收端L2CAP TxWindow size的I-frame需要排队等待后续发送

I-frame应该按照下面的步骤执行:

(a)发送I-frame(I-frame的TxSeq=NextTxSeq;ReqSeq=BufferSeq)

(b)将这个I-frame存放到UnackedList中下标为NextTxSeq的位置

(c)由于未被识别的I-frame多了一个,所以UnackedFrames加1

(d)记录由Send-Data和Retransmit-I-frames action发送的I-frame的数量

(e)将这个I-frame的重发次数存入RetryIframes,以NextTxSeq为下标,由于第一次发送所以重发次数是1

(f)NextTxSeq加1

(g)开始Retransmission timer

2

Pend-Data

当收到Data-Request event,但是由于某些原因(接收端TxWindow size满了或者远端设备busy或者本地L2CAP实体不在一个可以发送I-frame的state,例如WAIT_F)I-frame不能发送的时候,执行这个action

3

Process-ReqSeq

处理收到的frame的ReqSeq。包括设置ExpectedAckSeq=ReqSeq(表示TxSeq= ReqSeq – 1及之前的I-frame已经被识别)、将已经被识别的I-frame从UnackedList中移除、将这次被识别的I-frame对应的retry connter设置为0、UnackedFrames减去这次被识别的I-frame的数量、挂起的I-frame现在可以使用Send-Ack action发送,如果UnackedFrames=0则执行Stop-RetransTimer action

4

Send RR, RNR (P=x) or (F=x)

发送指定P-bit或者F-bit的RR或者RNR frame。如果P-bit or F-bit没有指定,则默认值0。例如Send RR(P=1)意思是发送一个P-bit=1,、F-bit=0的RR frame,ReqSeq= BufferSeq。如果发送了RNR,则RNRsent设置为TRUE

5

Send REJ (P =x) or (F=x)

发送指定P-bit或者F-bit的REJ frame,REJ frame的ReqSeq= ExpectedTxSeq,如果P-bit or F-bit没有指定则默认值0。如果本地L2CAP实体处于异常状态,当前不能识别收到的I-frame时,可以发送SREJ(P=0)或者RNR,也可能等到异常清除,能够识别I-frame时再发送REJ

6

Send RRorRNR (P=x) or (F=1)

根据LocalBusy发送一个指定P-bit或者F-bit的RR或者RNR frame。如果P-bit or F-bit没有指定则默认值0,如果LocalBusy=TRUE则发送RNR;如果LocalBusy=FALSE则发送RR

7

Send IorRRorRNR(F=1)

发送一个F-bit=1的I-frames或者RR或者RNR

具体的步骤如下:

(a)设置FramesSent为0

(b)判断LocalBusy = TRUE,如果符合条件则发送RNR(F=1)

(c)如果RemoteBusy = TRUE并且UnackedFrames > 0(有未识别的I-frame)则执行Start-RetransTimer action

(d)设置RemoteBusy=FALSE

(e)执行Send-Pending-I-frames action,发送挂起的I-frame,注意:在SendIorRRorRNR(F=1)过程中可能会调用多个action,发送多个frame,只有第一个frame需要设置F=1,其余的frame设置F=0

(f)执行完Send-Pending-I-frames action后,如果LocalBusy = FALSE并且FramesSent = 0(即Send-Pending-I-frames action没有挂起的I-frame)则发送RR(F=1)

8

Send SREJ

发送一个或者多个P=0的SREJ frames

丢失的I-frame指的的是收到一个I-frame TxSeq = A,但是A > ExpectedTxSeq,则大于等于ExpectedTxSeq并且小于A的所有的I-frame都是丢失的I-frame,每个丢失的I-frame都应该发送一个SREJ frame(设置ReqSeq为这个丢失的I-frame的TxSeq),发送一个SREJ frame则将对应丢失的I-frame的TxSeq插到SrejList的尾部。例如:ExpectedTxSeq=3,此时收到一个TxSeq=5的I-frame,则丢失了2个I-frame(TxSeq=3和TxSeq=4的I-frame),先发送一个ReqSeq=3的SREJ,然后发送一个ReqSeq=4的SREJ,TxSeq=3先插入SrejList,然后插入TxSeq=4。当所有的SREJ frames都发送后,ExpectedTxSeq应该设置为A+1 mod MaxTxWin

9

Send SREJ(SrejList)

发送一个或者多个P=0的SREJ frames

收到一个I-frame,它的TxSeq可以在SrejList中找到,但是不是SrejList中的第一个值,这意味着通过SREJ请求重发的I-frame依然有丢失的,假设SrejList从头部到尾部存放了1、2、3、4、5五个值,收到的I-frame的TxSeq=4,则SREJ请求重发的TxSeq=1、TxSeq=2、TxSeq=3的三个I-frame都丢失了,就需要再次使用SREJ请求重发这个3个I-frame(SREJ对应的ReqSeq分别等于1、2、3)。然后分别将1、2、3从SrejList移除并插到尾部,即SrejList为4、5、1、2、3,最后将收到的I-frame的TxSeq从SrejList移除,即移除4,此时SrejList为5、1、2、3

10

Send SREJ(SrejList-tail)(F=1)

发送一个SREJ,这个SREJ的F=1,ReqSeq为SrejList保存的中最后一个TxSeq

10

Start-RetransTimer

如果Monitor timer没有运行则以初始值运行Retransmission Timer,如果Retransmission timer正在运行,则以初始值重新开始运行Retransmission Timer,如果Monitor timer正在运行,则Retransmission timer不能启动

11

Start-MonitorTimer

以初始值运行Monitor timer,如果Monitor timer正在运行,则以初始值重新开始运行Monitor Timer

12

PassToTx

传递收到的frame的ReqSeq和F-bit值给Transmitter state machine,在Transmitter state machine会收到一个Recv ReqSeqAndFbit event

13

PassToTxFbit

传递收到的frame的F-bit值给Transmitter state machine,在Transmitter state machine会收到一个Recv Recv Fbit event

14

Data-Indication

表示将一个收到的I-frame发送到SDU reassembly function。这个动作应该是立即完成的,Send_Ack应该是下一个要执行的action。在某些情况下,SDU reassembly function可能无法接收这个I-frame,此时会将I-frame存放到L2CAP实体内,同时消耗一部分TxWindow,当I-frame被SDU reassembly function获取后,Send_Ack才应该执行,Send_Ack在执行前,BufferSeq应该执行下面操作

15

Increment-ExpectedTxSeq

表示增加ExpectedTxSeq的值,按照下面的规则

16

Stop-RetransTimer

表示停止Retransmission timer

17

Stop-MonitorTimer

表示停止Monitor timer

18

Send-Ack (F=x)

发送一个识别帧(F-bit可能指定为具体值,如果没有指定具体值,则默认F=0)。需要注意的是这个action可能和其他正在发送frame的action在一个action块中。如果指定了P值,则F-bit的值应该等于这个已收到的I-frame(正在使用识别帧告知收到的I-frame)的P-bit。如果指定F-bit=1且需要发送超过一个frame时,则只有第一个frame需要设置F-bit=1。一个识别帧可能是RR、RNR、或者pending I-frame(s)(即还未发送的I-frames)。如果存在允许发送的pending I-frames,那么应该尽量多的使用pending I-frame(s)作为识别帧。没必要每收到一个I-frame都发送一个RR或者RNR作为识别帧。 一般来说发送一个RR或者RNR的实现可以在收到一定数量的I-frame或者经过了一定的时间段后。为了保持数据流正常应该在TxWindow满之前发送识别帧,需要注意的是远端L2CAP实体的unacknowledged I-frame list可能小于本地L2CAP实体的TxWindow,这种情况远端L2CAP实体不可能填满本地L2CAP实体的TxWindow,因此需要尽快告知收到I-frames。发送一个识别帧的具体算法如下:

(a)判断本地是否处于忙碌状态,如果处于则执行Send_RNR(F=x),否则继续执行

(b)判断远端是否(处于忙绿状态、且存在Pending I-frames、且本地发送的未被识别的I-frame的数量还没有超过远端L2CAP实体的TxWindow),则执行Send-Pending-I-frames (F=x),否则继续执行

(c)执行Send_RR (F=x)

19

InitSrej

初始化用于处理SREJ的变量,具体如下:

(a)清空SrejList

(b)设置SendRej为FALSE

(c)设置BufferSeqSrej=BufferSeq

20

SaveIframeSrej

保存收到的I-frame。

丢失的I-frame(s)将作为SREJ frame(s)的响应被重发,为了按照正确的顺序保存,需要为丢失的Iframe(s)留出空间,当发送SREJ frame收到重发的I-frame时,将其存入对应的空间内。

21

StoreOrIgnore

如果本地L2CAP实体还有空间则存储收到的I-frame,如果没有空间则丢失。当存储收到的I-frame时,ExpectedTxSeq按照如下方式运算:

22

Retransmit-I-frames

重发所有未识别的I-frame,从TxSeq=收到的S-frame(REJ或者RR)的ReqSeq开始。如果收到的S-frame的P-bit=1,则重发的第一个I-frame的F-bit设置为1,如果收到的S-frame的P-bit=0,则重发的第一个I-frame的F-bit设置为0,其余的未识别的I-frame的F-bit设置为0。RetryIframes[]中对应的重发的I-frame的重发计数器加1,如果RetryIframes[]中某个重发计数器的值等于MaxTransmit,则关闭L2CAP channel,每重发一个I-frame,FramesSent加1,如果RetransTimer没有运行,则执行Start-RetransTimer action

23

Retransmit-Requested-I-frame

重发TxSeq=收到的S-frame(SREJ)的ReqSeq的I-frame,如果收到的S-frame的P-bit=1,则重发的I-frame的F-bit设置为1,如果收到的S-frame的P-bit=0,则重发的I-frame的F-bit设置为0,RetryIframes[]中对应的重发的I-frame的重发计数器加1,如果RetransTimer没有运行,则执行Start-RetransTimer action

24

Send-Pending-I-frames (F=x)

在不超过接收端TxWindow的情况下,使用Send-Data action发送所有挂起的I-frame,如果F-bit已经指定为某个值,则发送的第一个I-frame的F-bit应该设置成这个值,其余的I-frame的F-bit应该设置为0;如果F-bit没有指定为某个值,则所有的I-frame的F-bit都应该设置为0。挂起的I-frame指的是上层已经发送给了L2CAP实体,但是L2CAP实体还未发送的I-frame,如果一个或者多个I-frame被发送,RetransTimer正在运行,则执行Start-RetransTimer action

25

Close Channel

关闭L2CAP channel

26

Ignore

表示忽略event

27

PopSrejList

从SrejList的头部移除TxSeq

28

Data-IndicationSrej

这个action的意思是当前保存的I-frame队列中有丢失的I-frame,当收到一个作为SREJ响应的I-frame时,正好补充了其中一个丢失的I-frame,然后会将保存的I-frame传到SDU reassembly function。例如:当前已经保存了TxSeq为2、3、5、6、9的I-frame,收到一个TxSeq=4的I-frame,此时正好补充了丢失的I-frame,保存的I-frame的TxSeq变成了2、3、4、5、6、9,此时就可以把TxSeq为2、3、4、5、6的I-frame一块传给SDU reassembly function。当将这些I-frame传给SDU reassembly function后,L2CAP 实体对应的接收缓冲区立即释放,同时BufferSeqSrej按照下面的算法处理:

8.6.5.7 XMIT State Table

疑问1:收到Local-Busy-Detected event时有两种实现:

(1)LocalBusy := TRUE:这种实现是先不发送RNR frame,看在对方Retransmission timer超时前busy异常会不会清除,如果清除了,则发送一个RR frame或者I-frame作为识别帧,如果没有清除,远端会发送一个RR或者RNR poll,此时回复一个RNR frame

(2)LocalBusy := TRUE;Send RNR这种实现是检测到local busy异常立即发送一个RNR frame,,这里的RNR的P和F使用的是默认值0

疑问2:收到RetransTimer-Expires event时,执行Send RRorRNR(P=1),至于发送RR还是RNR根据LocalBusy = TRUE还是FALSE判断

8.6.5.8 WAIT_F State Table

疑问1:收到MonitorTimer-Expires时,执行Send RRorRNR(P=1),至于发送RR还是RNR根据LocalBusy = TRUE还是FALSE判断

8.6.5.9 RECV State Table

疑问1:

(1)收到一个F=1的I-frame,这个I-frame的TxSeq、ReqSeq、F-bit都是正常的且本地也不处于忙碌状态即LocalBusy= FALSE

(2)此时应该增加ExpectedTxSeq、处理F-bit(PassToTx)、SDU reassembly function处于I-frame(Data-Indication),然后检测RejActioned的值,最后发送识别帧,即Send-Ack(F=0)

注意:RejActioned值的检测我是这么理解的:

RejActioned如果为TRUE,说明本地已经收到一个REJ并且做出了相应的动作(即已重发了I-frame),同时本地也发送了一个P=1的S-frame,还未收到回复,这里收到一个F=1的I-frame,即发送的P=1的S-frame收到回复了,此时因为之前已经从重发了I-frame,所以这里不需要再次重发I-frame,直接设置RejActioned = FALSE即可;

疑问2和疑问3:

2中收到的I-frame的TxSeq、ReqSeq、F-bit都是正常的,但是本地处于忙碌状态即LocalBusy= TRUE,说明I-frame本身没有问题,所以可以在处理完F=bit后(即PassToTx),选择保存这个I-frame或者直接忽略(StoreOrIgnore)

而3中中收到的I-frame的ReqSeq、F-bit是正常的,TxSeq是不正常的,同时本地还处于忙碌状态即LocalBusy= TRUE,说明I-frame本身就有问题,所以只需要处理下F=bit(即PassToTx)即可,I-frame直接丢弃

疑问4:

Recv RNR (P=1)和Recv RNR (P=0),收到RNR时说明远端处于busy状态了,所以都执行了RemoteBusy := TRUE

PassToTx

Stop-RetransTimer

其实这时候还需要有个Pend-Data的动作。所以此时本地不会发送I-frame,但是Recv RNR (P=1)时又必须回复一个F=1的frame,所以执行Send RRorRNR (F=1)

疑问5:收到REJ的时候,设置RemoteBusy := FALSE,原因应该是收到REJ,说明远端设备处理了一部分数据发现有问题了,所以自动解除busy状态

8.6.5.10 REJ_SENT State Table

8.6.5.11 SREJ_SENT State Table

8.7 STREAMING MODE

Streaming Mode使用的frame格式和Enhanced Retransmission mode一样,但是不需要回复识别帧,所以RR、REJ、RNR和SREJ在Streaming Mode都不需要使用,F-bit应该设置为0,MonitorTimer和RetransmissionTimer也不使用,但是需要在发送端设置一个有限的Flush Timeout

8.7.1 Transmitting I-frames

发送新的I-frame时,ReqSeq=0,TxSeq设置为NextTXSeq,然后NextTXSeq加1

8.7.2 Receiving I-frames

收到I-frame时,如果收到的I-Frame的TxSeq= ExpectedTxSeq,则表示这个I-frame是有效的,可以发送给reassembly function,然后ExpectedTxSeq加1。

收到的I-Frame的TxSeq是有效的,但是乱序了,参考8.7.3.1,所有小于这个I-frame的TxSeq的I-frame会被认为丢失了(即从ExpectedTxSeq到TxSeq – 1都丢失了),ExpectedTxSeq设置为TxSeq +1,然后这个I-frame会发送到reassembly function,至于收到的I-frame的ReqSeq应该忽略

注意:可能整个window size的I-frame都丢失了,这样就无法检测I-frame丢失,例如window size=63,此时有连续63个I-frame丢失了,这样我们就会认为没有丢失,无法检测到丢失的I-frame,所以建议使用Extended Window Size option;如果空间不足,当收到已存在的I-frame时,那么就删除现有的I-frame为新I-frame空出空间,删除的I-frame会被认为丢失了

8.7.3 Exception Conditions

8.7.3.1 TxSeq Sequence error

当收到一个有效的I-frame,但是TxSeq序号错误即ExpectedTxSeq< TxSeq,此时ExpectedTXSeq设置为这个I-frame的TxSeq加1,>=ExpectedTxSeq并且<=TxSeq-1的I-frame会被认为丢失了,并通知SDU reassembly function

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值