1. Segmentation
- Lower Transport Layer 同一时刻只能传输一个 Upper Transport PDU到同一地址。能不分段传输则不分段(好像是废话)。
- Segmented messages需要lower transpot layer应答,Unsegmented messages则不需要。
- 如果使用单分段传输比不分段消息传输更符合应用则应该使用单分段传输,因为分段消息有应答机制。
- 一旦可以确认的最后一个上层传输PDU的所有段都已确认或消息已取消,下层传输层应仅为同一目的地的另一个上层传输PDU发送分段消息(即每次只能传输一个Upper Transport PDU到同一地址)。
注意:PDU大小如下图
类型PDU Size(byte)Unsegmented Access Message5-15Segmented Access Message1-12Unsegmented Control Message0-11Segmented Control Message1-8
例如:使用32位Trans-MIC, Upper Transport Access PDU 为 42 字节,那么:
octetssegment/SegO0 to 11012 to 23124 to 35236 to 413
Upper Transport Control PDU 为 42 字节,那么:
octetssegment/SegO0 to 708 to 15116 to 23224 to 31332 to 39440 to 415
一个Upper Transport PDU的每一个Lower Transport PDU(segment 0~n ) 的IV Index 都是一样的,它作为SeqAuth的一部分。
- Upper Transport Access PDU:SeqAuth用来加密或者解密Upper Transport Access PDU
- Upper Transport Control PDU:SeqAuth用来识别Upper Transport Access PDU
SeqAuth是一个56 bits的值,它的高位是IV Index(32 bits),低位是第一个分段(segment0)的SEQ(24 bits);分段消息和分段应答消息只包含SeqAuth的最低 13 bits,称为SqeZero。
https://github.com/sifive/riscv-zephyr/blob/master/subsys/bluetooth/host/mesh/transport.c
https://elixir.bootlin.com/zephyr/v1.14.0-rc3/source/subsys/bluetooth/host/mesh/transport.c
#define SEQ_AUTH(iv_index, seq) (((u64_t)iv_index) << 24 | (u64_t)seq)
seq_zero = tx->seq_auth & 0x1fff;
u16_t seq_zero = *seq_auth & 0x1fff;
tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
由于 SeqZero 的大小有限,一旦 SEQ 比 SeqAuth 高 8192,就无法发送分段消息。 如果在 SEQ 比 SeqAuth 高 8192 时还没有确认分段消息,则应取消上层传输 PDU 的传递。
2. Reassembly
- 在接收设备中执行重新组装。 当使用低功耗节点功能时,消息的确认由朋友节点执行,低功耗节点不会发送段确认消息。
- 收到分段消息后,应检查 SeqAuth 以确定是否正在接收或先前已接收到上层传输 PDU。
- 如果尚未收到分段消息,则接收设备应分配足够的内存,由最后一个段号 (SegN) 确定,以存储接收到的上层传输 PDU 的段并跟踪它的段。 已收到,然后它会认为正在接收此消息。
- 如果未使用低功耗节点功能,并且消息的目的地是单播地址,并且节点此时无法接收此上层传输 PDU,例如因为节点忙或资源不足而无法重新组装 该消息,则节点应通过将 BlockAck 值设置为 0x00000000 向源节点发出信号,告知其无法接收此上层传输 PDU。
- 如果分段消息正在接收过程中,则段号(SegO)应用于确定该分段消息中的上层传输 PDU 八位字节应放置在先前为该消息分配的存储器中的位置。 接收方应更新 BlockAck 值以记录分段的成功传递。
- 一旦接收到给定 SeqZero 的上层传输 PDU 的所有段,上层传输层将检查上层传输 PDU。