Mesh 网络层核心概念网络层(Network Layer)负责 Mesh 消息的寻址、中继和加密。它是在承载层之上、传输层之下的核心协议层。地址类型Unicast Address(单播地址)范围说明0x0001 ~ 0x7FFF分配给配网后的节点,每个节点至少一个特点全网唯一,配网时由 Provisioner 分配用途点对点通信Group Address(组播地址)范围说明0xC000 ~ 0xFEFF固定或动态分配的组地址特点多个节点可订阅同一组地址用途分组控制(如:所有客厅灯)SIG 预定义组地址:地址名称用途0xC000all-proxies所有 Proxy 节点0xC001all-friends所有 Friend 节点0xC002all-relays所有 Relay 节点0xC003all-nodes所有节点是的,Relay = 中继。在 BLE Mesh 里,Relay是一种节点特性(Feature):节点收到不是发给自己的Mesh 消息后,会重新广播转发,让消息多跳到达更远节点。你文档里all-relays(0xC002)就是所有开启了 Relay 功能的节点组成的组地址。和「中继」的对应关系英文中文含义Relay中继 / 转发转发 Mesh 消息,实现多跳Relay Node中继节点具备 Relay 能力的节点all-relays所有中继节点组播发给全网所有 Relay 节点中继怎么工作Node A (TTL=5) ──PDU── Relay Node (TTL=4) ──PDU── Node B (TTL=3) │ TTL 减 1 后重发每中继一次,TTL 减 1TTL 到 0 或 1 时不再转发随机延迟 0~50ms,减少冲突和其他 SIG 组地址对比组地址节点类型作用all-proxiesProxy帮手机走 GATT 接入 Meshall-friendsFriend帮 Low Power 节点缓存消息all-relaysRelay负责多跳转发,扩大覆盖all-nodes全部广播给网络内所有节点实际场景照明网络里,常供电的灯通常会开 Relay,既当业务节点,也当中继,把控制命令传到远处开关或传感器。注意:Relay 和 WiFi 里的「中继器」概念类似,都是转发别人流量;Mesh 里是否中继由Relay State配置决定,可以开关。Virtual Address(虚拟地址)范围说明0x8000 ~ 0xBFFF基于 Label UUID 的地址特点128-bit UUID 哈希生成,碰撞概率极低用途跨网络共享资源其他地址名称说明0x0000Unassigned未分配地址(未配网设备)0xC004~0xCFFFRFU保留0xD000~0xFEFFDynamic Group动态组地址0xFF00~0xFFFFRFU保留网络 PDU 格式Network PDU: ┌────────┬────────┬─────────┬──────────┬───────────┬──────────┬─────┐ │ IVI:1b │ NID:7b │ CTL:1b │ TTL:7b │ SEQ:24b │ SRC:16b │ ... │ │ │ │ │ │ │ │ │ └────────┴────────┴─────────┴──────────┴───────────┴──────────┴─────┘ 完整结构: ┌──────────┬─────┬──────┬──────┬────────┬──────┬─────────┬──────┐ │ IVI+NID │ CTL │ TTL │ SEQ │ SRC │ DST │ Transport│ MIC │ │ 1 B │ 1b │ 7b │ 24b │ 16b │ 16b │ PDU │ 4/8B │ │ │ │ │ │ │ │ (加密) │ │ └──────────┴─────┴──────┴──────┴────────┴──────┴─────────┴──────┘字段详解字段大小说明IVI1 bitIV Index 最低位,用于识别 Network KeyNID7 bitsNetwork ID,派生自 Network Key,快速识别所属网络CTL1 bit0=Access 消息,1=Control 消息TTL7 bits生存时间,每中继一次减 1,到 0 不再转发SEQ24 bits序列号,防重放攻击SRC16 bits源地址(Unicast)DST16 bits目标地址(Unicast/Group/Virtual)Transport PDU变长加密的传输层数据MIC4/8 B消息完整性校验码(CTL=0 用 4B,CTL=1 用 8B)IV Index32-bit 计数器,用于加密和防重放所有节点共享同一 IV IndexIV Index 只能递增IV Update 过程:节点检测到 IV Index 需要更新发送 Secure Network Beacon,IV Update Flag = 1其他节点进入 IV Update 状态完成后 IV Update Flag = 0,新 IV Index 生效中继机制Relay 节点收到非自己的 Mesh 消息后重新广播每次中继 TTL 减 1TTL = 0 或 TTL = 1 时不中继中继延迟:随机 0~50ms(避免冲突)中继流程Node A (TTL=5) ──PDU── Relay Node (TTL=4) ──PDU── Node B (TTL=3) │ TTL 减 1 后重发Relay 特性配置配置说明Relay State开启/关闭中继功能Relay Retransmit Count中继重发次数 (0~7)Relay Retransmit Interval中继重发间隔 (0~31, 单位 10ms)中继节点是怎么"宣告"的(问题 1)关键:Relay 不靠 Beacon 周期性宣告身份。Mesh 协议里 Relay 的"身份"通过两个机制暴露:1. Composition Data(静态能力上报)节点配网后,Provisioner 通过Config Composition Data Get读取节点的 Composition Data,里面包含节点支持哪些 Feature:Composition Data Page 0 ├── CID / PID / VID ├── Features 字段(16-bit 位图) │ ├── bit0: Relay ← 是否支持中继能力 │ ├── bit1: Proxy │ ├── bit2: Friend │ └── bit3: Low Power └── Elements / Models这是能力声明:「我硬件上能做 Relay」,不等于"现在开着"。2. Relay State(运行时开关)是否真正启用中继,由Relay State决定,Provisioner 通过Config Server Model远程配置(详见下文「Relay 配置消息空口交互」章节)。全网没有任何节点需要预先知道「谁是 Relay」——这是 Mesh 泛洪的本质:每个收到包的节点自己判断要不要转发。转发时 TTL-1 是规范硬性要求(问题 1)NimBLEbt_mesh_net_relay()实现清晰:步骤 1:TTL 检查,TTL ≤ 1 不转发if(rx-ctx.recv_ttl=1U){return;}TTL=0:禁止转发(规范定义)TTL=1:到达最后一跳,转发出去会变 TTL=0,没意义,不转发步骤 2:检查 Relay 是否开启if(rx-net_if==BT_MESH_NET_IF_ADV!rx-friend_credbt_mesh_relay_get()!=BT_MESH_RELAY_ENABLEDbt_mesh_gatt_proxy_get()!=BT_MESH_GATT_PROXY_ENABLED){return;}从 ADV 收到的包:必须 Relay 开启从 GATT 收到的包:必须 GATT Proxy 开启步骤 3:TTL 减 1 写回包头(保留 CTL 位)/* Leave CTL bit intact */sbuf-om_data[1]=0x80;sbuf-om_data[1