蓝牙mesh网络层及网络PDU解析

网络层定义了网络PDU格式,允许承载层传输下层传输层的PDU。它对输入接口接收的传入消息进行解密和身份验证,并将其转发到上层和/或输出接口,对传出消息进行加密和身份验证并将其转发到输出网络接口。

网络地址(Address)

网络层定义了4种地址类型,地址长度为16位。
如下图:
单播地址范围从0x0001到0x7FFF,可以有32767个单播地址。
虚拟地址范围从0x8000到0xBFFF,可以有16384个虚拟地址。
组播地址范围从0xC000到0xFFFF,可以有16384个组播地址。组播地址包括256个固定组播地址和16128个可动态分配的组播地址。

蓝牙mesh对节点没有并发性限制或限制。

当与低功耗蓝牙传输一起使用时,该规范不存在拓扑限制或限制。

意味着什么?能分配多少单播个地址,就能有有多少个设备。虚拟地址、组播地址和单播地址是可以共存的,所以设备的个数,只能以单播地址计算。比如,一个设备即可以同时属于组1、组2,设备还有单播地址,一下就用掉了3个地址,但是只有一个设备。所以一个网络中可以有32767个有效地址。

地址的范围.jpg

未分配地址的意义在于,可以通过将模型的发布地址设置为未分配地址来禁用模型的消息发布。那这里有个问题,网络层在发现是未分配地址的消息会怎么做,未分配地址的消息是在网络层拦截还是在承载层拦截?meshNetworkManager。

单播地址即可在消息的源地址字段中使用,也可在消息的目标地址字段中使用。发送到单播地址的消息最多只能由一个元素处理。在配网阶段,配网器会在网络节点的生命周期内为节点的每个元素分配单播地址。该地址可以由配网器取消分配,以允许被重用。

虚拟地址表示一组目标地址。每个虚拟地址在逻辑上代表一个标签UUID,它是一个128位的值,无须集中管理。一个或多个元素可以配置发布或订阅同一个标签UUID。标签UUID不会被传输,应该用作上层消息层中消息完整性校验值的附加数据字段。虚拟地址涉及Hash值的计算。(这里无须对虚拟地址做过多研究,后面自然就清楚了)

组播地址从0xFF00到0xFFFF的组播地址保留给固定的用途,从0xC000到0xFEFF的组播地址可以用作其他用途。组播地址只能在消息的目标地址中使用。发送给组播地址的消息会被订阅这个组播地址的所有模型实体接收到。

  • 发送到所有代理节点地址的消息应由启用代理功能的所有节点的主元素处理。
  • 发送到所有朋友节点地址的消息应由启用朋友功能的所有节点的主元素处理。
  • 发送到所有中继节点地址的消息应由启用中继功能的所有节点的主元素处理。
  • 发送到所有节点地址的消息应由所有节点的主元素处理。


    Future与地址的关系.jpg

这句话对不对,那么任何一个BLE设备都可以加入mesh网络?该如何解读?

网络层PDU

Network PDU Format.jpg
网络层PDU.jpg
  • IVI字段是IV Index的最低有效位
  • NID字段是一个7位的网络标识符,该标识符用来方便地查找用于验证和加密此网络层PDU的加密密钥和隐私密钥。NID值是与加密密钥和隐私密钥一起从网络密钥派生出来的。对于主网络消息和朋友及其低功耗节点之间的私有网络消息,他的派生方式有所不同。
  • CTL字段是一个1位的值,用于确定消息是控制消息的一部分还是访问消息的一部分。
  • TTL字段,不用解释,大家都懂。
  • SEQ字段是一个24位的整数,与IV Index结合使用,对于该节点发起的每个新网络层PDU,该整数应该是唯一的值。我们目前的程序中,是让这个值自增加一。
  • SRC字段是一个16位的值,它标识发起这个网络层PDU的元素地址,此地址应为单播地址。SRC字段由发包节点来设置,中继节点在转发时不得修改该字段。
  • DST字段是一个16位的值,它标识网络层PDU所指向的一个或多个元素地址。此地址应为单播地址、组播地址或虚拟地址。DST字段由发包节点设置,中继节点在转发时不能修改。
  • TransportPDU字段是数据的字节序列。当CTL位为0时,TransportPDU字段的最大值为128位,当CTL位为1时,TransportPDU最大值为96位。TransportPDU字段由发包节点的底层传输层设置,网络层不能更改。
  • NetMIC字段是一个32位或64位的字段,取决于CTL位的值,它用于验证DST和TransportPDU是否被更改。当CTL位为0时,NetMIC字段为32位。当CTL位为1时,NetMIC字段为64位。NetMIC由网络层中每个传输节点或中继该网络层PDU的节点设置。


    访问消息与控制消息.jpg

网络层接口

网络层支持通过多个承载器发送和接收消息。一个承载器可能存在多个实例。承载器的每个实例都可以通过网络接口连接到网络层。例如,一个节点可能有三个承载器:一个广播承载器和两个GATT承载器的接口。

一个网络中,如果有两个配网器会怎么样?一键配网和多配网器是两个概念。

接口输入过滤器决定传入的网络消息是交付给网络层进一步处理,还是将其删除。
接口输出过滤器决定是将消息传给承载层还是删除。接口输出过滤器删除所有TTL值为1的消息。
本地网络接口允许在同一个节点内的元素之间发送消息。每个节点都应该实现一个本地网络接口。通过本地网络接口接收消息后,应该将所有消息发送给节点的所有元素处理。
广播承载器的网络接口,允许使用广播承载器发送消息。APP端不做研究。

网络层行为

中继功能

中继功能用于中继节点或转发节点通过广播承载器接收的网络PDU。此功能是可选的,如果支持此功能,则可以单独启用和禁用此功能。如果支持代理特性,则必须同时支持GATT承载器和广播承载器。

代理功能

代理功能指节点在GATT承载网络和广播承载网络之间中继或转发网络层PDU来实现GATT承载网络和广播承载网络间的消息互通。此功能是可选的,如果支持此功能,可以单独启用和禁用此功能。如果支持代理特性,则同时支持GATT和广播承载。

接收消息处理

节点收到来自承载层的消息后,检查NID字段值是否匹配一个或多个已知的NID。如果NID字段的值与已知的NID不匹配,则该消息将被忽略。如果NID字段的值与已知的NID匹配,节点将根据每个已知的匹配的网络密钥验证消息。如果消息没有对任何已知的网络密钥进行验证,则该消息将被忽略。如果消息确实根据网络密钥认证,SRC和DST字段被认为是有效的,并且消息不在网络消息缓存中,那么该消息将由较低的传输层处理。

当一条消息被重传时,定义如下,重传时使用的IV索引应与接收时的IV索引相同。

如果节点的网络层收到了广播承载器分发过来的消息,通过了验证,要上报给底层传输层处理时,如果节点启用了中继功能,TTL字段的值为2或更大,且元素的目标地址不是这个节点的任何一个单播地址,那么TTL字段值应该减1,网络层PDU应标记为中继PDU,并转发给连接到广播承载层的所有网络接口。建议在接收网络PDU和中继网络PDU之间设置一个较小的随机延迟,以避免同时接收同一个网络PDU的多个中继消息而发生冲突。

如果节点的网络层收到了来自GATT承载器(如果是广播承载器)的消息,并通过了验证,要上报给底层传输层处理时,如果节点支持代理功能且代理功能是开启的,同时TTL字段的值为2或更大,且目标地址不是本节点的任何一个元素的单播地址,那么设置该消息TTL值减一,并转发这个消息到所有网络层接口(转发到与GATT承载器连接的所有网络层接口)。

网络层PDU处理步骤.jpg

发送消息处理

参照网络层PDU格式生成数据包,然后调用承载层进行传输即可。

网络消息缓存

为了减少不必要的安全检查和过度的中继,一个节点应该包括所有最近看到的网络pdu的网络消息缓存。如果收到的网络PDU已经在网络消息缓存中,则不处理网络PDU(即立即丢弃)。如果接收到一个网络PDU,而该网络PDU不在网络消息缓存中,则可以对网络PDU进行处理(例如,根据网络安全性进行检查),如果它是一个有效的网络PDU,则应该存储在网络消息缓存中。

节点不需要缓存整个网络PDU,可以只缓存一部分用于跟踪,例如NetMIC、SRC/SEQ或其他的值。只要能在设备能力的限制范围内实现不多次处理同一网络PDU,筛选条件是可以自定义的。

当网络消息缓存已满,需要缓存一个新的网络PDU时,一个新的网络PDU将取代网络消息缓存中已经存在的最久的网络PDU。
网络消息缓存应该能够存储至少两个网络pdu,尽管强烈建议拥有一个适合预期网络密度的网络消息缓存大小。传入消息处理过程的细节还是留给开发者自己实现。

两个网络层PDU验证数据

收到<- 0x003EBB5242C5F1E3FDFB18251C5942BFE8EC25CC767D1E1AE1FDD9C73CC0
networkKey: F9B024F55B95EFA75F6B2B8D8D3A3F5C
NetworkPdu.pdu = 0x3EBB5242C5F1E3FDFB18251C5942BFE8EC25CC767D1E1AE1FDD9C73CC0
ivi==== 0
nid==== 0x3E(10进制62)
解混淆时的keys.privacyKey:A212C7601572F72C15EBA9179775D9D0
解混淆时的ivIndex:0
解混淆的结果:050000030003
===ctl:0,
===ttl:5,
===sequence:3,
===source:3,
===netMicSize:4
===micOffset:25,
===destAndTransportPdu:FDFB18251C5942BFE8EC25CC767D1E1AE1FD,
===mic:D9C73CC0
====nonce:00050000030003000000000000,
keys.encryptionKey:DA33D708B9D25EDE5FDE26BBC1EC848A
decryptedData:0001800008034458CCC398FD700CF04E7C05,
destination:1,
transportPdu:800008034458CCC398FD700CF04E7C05

收到<- 0x003EDC3EEFD43C51766AE52CE58BD0969F312C144A14753C9B28EAA5BB8B
networkKey: F9B024F55B95EFA75F6B2B8D8D3A3F5C
NetworkPdu.pdu = 3EDC3EEFD43C51766AE52CE58BD0969F312C144A14753C9B28EAA5BB8B
ivi==== 0
nid==== 0x3E(10进制62)
解混淆时的keys.privacyKey:A212C7601572F72C15EBA9179775D9D0
解混淆时的ivIndex:0
解混淆的结果:050000040003
===ctl:0,
===ttl:5,
===sequence:4,
===source:3,
===netMicSize:4
===micOffset:25,
===destAndTransportPdu:766AE52CE58BD0969F312C144A14753C9B28,
===mic:EAA5BB8B
====nonce:00050000040003000000000000,
keys.encryptionKey:DA33D708B9D25EDE5FDE26BBC1EC848A
decryptedData:0001800008231CDC2FCB23CD2EB4C47D8BE8,
destination:1,
transportPdu:800008231CDC2FCB23CD2EB4C47D8BE8

你可能感兴趣的:(蓝牙mesh网络层及网络PDU解析)