下传输层协议,即Lower Transport Layer,它是相对于上传输层协议而言定义的。下传输层协议在Bluetooth MESH协议栈中的位置如下图所示,它位于网络层之上,上传输层之下。它的功能是对上层的PDU进行分段以及重组。
下传输层的PDU有四种格式,由网络层PDU的CTL字段以及下传输层PDU的SEG字段确定本PDU的格式。其中,网络层PDU的CTL用于区分access报文和control报文。
CTL |
SEG |
PDU格式 |
0 |
0 |
不分段的Access消息 |
0 |
1 |
分段的Access消息 |
1 |
0 |
不分段的control消息 |
1 |
1 |
分段的control消息 |
SEG(1 bits): 1表示该PDU为分段格式;
AKF(1 bit):应用层密钥标志位;
AID(6 bits):应用层密钥ID;这两个字段跟密钥相关,将会在上传输层章节进行详细介绍;
SZMIC(1 bit):TransMIC的长度指示,如果此位为0,则在上传输层(UpperTransport Layer)的TransMIC有32 bits;如果此位为1,则TransMIC是一个64 bits的值;
SeqZero(13 bits): SeqAuth向量的最低13位,该值由上传输层指定;
SegO(5bits): 分段偏移值;
SegN(5bits): 最后的分段序号;
比如一共有5个分段,如果是第一个分段,则SegO=1, SegN=5;
Segmentm;某一个分段的数据,它的长度范围为8至96bits (120 – 1 – 13 – 5 – 5 =96)。
Control包的最大长度限制为88bits。大于88bits的PDU将会进行分段处理。
SEG(1 bit): 1表示该PDU为分段格式;
Opcode(7 bits):值为0表示该PDU为分段Ack,其它值会在上传层章节中介绍;
RFU(1 bit):预留位,暂时没使用;
SeqZero, SegO, SegN的定义与accessPDU中所使用的一样,不同指示在于Segment m的最大长度为64bits (88 – 1 – 13 – 5 – 5 = 64)。分段传输不可避免的会碰到某个分段由于各种原因导致传输失败的情况,在这种情况下,lower transport layer应该有一套机制来保证upper transport layer的PDU被正确传输。这套机制中的一种重要参数就是分段传输定时器。
在一个分段PDU发送之后,启动分段传输定时器,这个定时器的最小值为200+50*TTL ms。其中,TTL值为网络层数据包中所设定的值。
如果发送端收到了一个有效ack包,发送端将会重置分段传输定时器,同时对接收端没有收到的PDU进行重传。如果ack包指示所有的分段都被正确接收,则可以确认上传层PDU被完整送达。
如果在定时器超时的情况都没有收到一个有效的ack包,lower transport layer将会重传所有的PDU。
在接收端,当收到一个比当前期望收到的Upper transport layer PDU序号大时(在lowertransport layer,不同分段的数据包有同样的upper transport layer PDU序号),启动未完成定时器,该定时器最小值为10s。这个定时器限定了在接收到序号大的PDU时,留给当前PDU序号完成所有分段的时间。
如果接收到上述PDU的一个分段包为单播时,启动ack定时器。定时器值设置为150+50*TTL ms。这个定时器用于定义接收端给发送端反馈ack消息的时间。
如果收到一个期望upper transport layer PDU序号的分段包,并且未完成定时器已经启动,则重新启动未完成定时器。
如果一个upper transport layer PDU全部接收到,则向发送端反馈每个分段的接收情况。同时,停止未完成定时器以及ack定时器,并且将重组后的数据包发送给upper transport layer。
如果ack定时器超时,lower transport layer将会发送一个分段ack消息。
如果未完成定时器超时,接收端会认为接收失败,所有已接收的数据包将会被忽略,同时停止ack定时器。