在 BLE 中,L2CAP 主要运行在基本模式 下,数据帧被称为 B-frame(Basic information frame)。此外,LE Credit Based Flow Control 模式(用于 CoC 面向连接信道)也使用 K-frame。
1. L2CAP 数据包的基本结构
1.1 数据包在 BLE 空口中的位置
要理解 L2CAP 数据包,首先需要明确它在整个 BLE 空口数据包中的位置。BLE 链路层的数据包结构如下:

PDU结构

| 字段 | 长度 | 说明 |
|---|---|---|
| Preamble | 1 字节 | 前导码 |
| Access Address | 4 字节 | 接入地址 |
| LL Header | 2 字节 | 链路层头部(含 LLID、长度等) |
| L2CAP PDU | 可变 | L2CAP 协议数据单元 |
| MIC | 4 字节 | 消息完整性校验(加密时存在) |
| CRC | 3 字节 | 循环冗余校验 |
L2CAP PDU 就承载在链路层 PDU 的 Payload 字段中,它是链路层之上的第一层协议封装
1.2 基本 L2CAP 头部格式
所有 L2CAP 数据包都以一个4 字节的基本头部开始,该头部由两个 16 位字段组成:
| 偏移量 | 字段 | 大小 | 说明 |
|---|---|---|---|
| 0 | Length(PDU Length) | 2 字节 | 信息载荷的长度(不含头部本身),小端序 |
| 2 | Channel ID(CID) | 2 字节 | 信道标识符,标识目标信道端点 |
Length 字段指示了 L2CAP 头部之后的信息载荷大小。对于 B-frame,PDU Length 等于 payload 的长度;对于信令帧(C-frame),Length 还包含信令命令部分的长度。
CID 字段是 L2CAP 实现多路复用的核心。不同的 CID 对应不同的上层协议或信道。以下是 BLE 中常见的 CID 分配:
| CID 值 | 用途 | 说明 |
|---|---|---|
| 0x0001 | 信令通道 | L2CAP 信令命令 |
| 0x0004 | ATT 协议 | 属性协议 |
| 0x0005 | L2CAP 信令(LE) | BLE 信令通道 |
| 0x0006 | SMP 协议 | 安全管理协议 |
| 0x0040 | 动态分配 | 面向连接信道(CoC) |
2. 基本模式下的 B-frame 格式
在 BLE 中最常用的基本模式下,L2CAP 数据包被称为 B-frame,其结构非常简洁:

B-frame 的特点是:一个 B-frame 包含一个完整的 SDU(服务数据单元) ,其 payload 直接承载上层协议的数据。在 BLE 中,由于 ATT 层的 MTU 协商机制已经能够处理较大的数据单元(默认 23 字节,可协商至 517 字节),因此大多数 ATT 数据都可以在单个 B-frame 中完成传输,无需 L2CAP 层的分段重组。
3. 信令通道(C-frame)格式
信令通道使用 CID 0x0001(经典蓝牙)或 0x0005(BLE),所有信令命令都通过这个信道发送。信令命令的 PDU 被称为 C-frame
3.1 信令命令头部
每个信令命令的头部由以下字段组成:

| 字段 | 大小 | 说明 |
|---|---|---|
| Code | 1 字节 | 命令类型代码 |
| Identifier | 1 字节 | 请求/响应匹配标识符 |
| Length | 2 字节 | 命令数据部分的长度 |
Code 字段决定了命令的类型。当一个数据包携带了未知的 Code 时,接收方会返回 Command Reject 响应。
3.2 常见信令命令代码


在实际抓包中,信令通道最常见的命令包括连接参数更新(0x12/0x13)和 LE 信用管理(0x14-0x16)。例如,在一次典型的抓包中可以看到,外设的 BLE 控制器会周期性地发送 L2CAP 信令消息来更新连接参数。
3.3 信令命令的封装层次
一个完整的信令命令在 L2CAP 中的封装层次如下:
L2CAP Header (4B)
├── Length = 信令命令总长度
└── CID = 0x0005
信令命令
├── Code (1B)
├── Identifier (1B)
├── Length (2B)
└── Data (可变)
4. 无连接数据通道与 G-frame 格式
在 L2CAP 的所有 PDU 类型中,G-frame(Group frame,组帧) 是最特殊的一种------它专门用于无连接 L2CAP 通道(Connectionless L2CAP Channel) ,无需事先建立连接即可发送数据。这是经典蓝牙(BR/EDR)中 L2CAP 提供的一项能力,BLE 中并不使用 G-frame。不过,L2CAP 作为通用协议,了解 G-frame 有助于完整理解 L2CAP 的 PDU 家族。
4.1 为什么需要无连接通道?
传统的面向连接信道需要经过"连接请求 → 连接响应 → 配置请求 → 配置响应"的完整握手流程才能传输数据。对于某些应用场景------例如向微微网(piconet)中所有从设备广播数据------建立多条连接显然不现实。L2CAP 无连接通道解决了这个问题:
-
广播模式:通过 Active Peripheral Broadcast 向微微网内所有活动从设备广播数据
-
单播模式:也可以向单个远程设备发送无连接单播数据
G-frame 就是这条通道上承载数据的 PDU 类型。
4.2 G-frame 格式详解
G-frame 的结构在 B-frame 的基础上增加了一个 PSM(Protocol/Service Multiplexer,协议/服务复用器)字段,用于在无连接通道上实现第二层服务复用。
G-frame 完整格式:

各字段说明:
| 字段 | 大小 | 说明 |
|---|---|---|
| Length | 2 字节 | 信息载荷长度 + PSM 字段长度(小端序) |
| CID | 2 字节 | 固定值 0x0002(无连接接收通道) |
| PSM | ≥2 字节 | 协议/服务复用器,标识目标上层协议或服务 |
| Information Payload | 0 ~ 65535 字节 | 承载的完整 SDU 数据 |
关于 Length 字段的重要区别: G-frame 的 Length 字段与 B-frame 不同。B-frame 的 Length 仅表示 Information Payload 的长度,而 G-frame 的 Length 需要加上 PSM 字段的长度。Bluetooth Core Specification 明确规定:"For G-frames, the PDU Length equals the payload size plus the number of octets in the PSM"。
4.3 PSM 字段详解
PSM 是 G-frame 区别于其他所有 L2CAP PDU 类型的核心字段,它提供了无连接通道上的服务多路复用能力。
| 属性 | 说明 |
|---|---|
| 最小长度 | 2 字节 |
| 字节序 | 小端序(LSB 在前) |
| 功能 | 标识目标协议或服务,类似 TCP/UDP 中的端口号 |
| 分配方式 | 分为固定段(标准协议分配)和动态分配段 |
PSM 的工作机制是:发送方在 G-frame 中指定目标服务的 PSM,接收方根据 PSM 值将数据分发到对应的上层协议或应用。如果没有 PSM,接收方无法区分这是发给哪个服务的数据。
4.4 G-frame 与其他 PDU 类型的对比
为了更清晰地理解 G-frame 的定位,下面对 L2CAP 各 PDU 类型做一个系统性对比:
| PDU 类型 | 所在通道 | CID | 关键字段 | 适用场景 |
|---|---|---|---|---|
| B-frame | 面向连接(基本模式) | 动态分配 | 无额外字段 | 常规数据传输 |
| C-frame | 信令通道 | 0x0001/0x0005 | Code + Identifier | 信令交互 |
| G-frame | 无连接通道 | 0x0002 | PSM | 广播/无连接单播 |
| I-frame | 面向连接(重传/流控模式) | 动态分配 | Control + SDU Length | 可靠数据传输 |
| S-frame | 面向连接(重传/流控模式) | 动态分配 | Control | 确认/请求重传 |
| K-frame | LE CoC(信用模式) | 动态分配 | SDU Length(首帧) | LE 面向连接信道 |
关键区别:
-
G-frame 与 B-frame 的区别:B-frame 用于已建立的面向连接通道,G-frame 用于无需连接的广播/无连接场景;G-frame 多一个 PSM 字段,CID 也不同。
-
G-frame 与 I-frame/S-frame 的区别:I-frame 和 S-frame 属于重传/流控模式下的面向连接通道,而 G-frame 是无连接通道的专属 PDU,不具备重传和流控能力。
-
G-frame 与 K-frame 的区别:K-frame 用于 BLE 的 LE Credit Based Flow Control 模式,面向连接且有信用流控;G-frame 无连接、无流控。
4.4 注意事项
-
广播单播均可:G-frame 既可通过 Active Peripheral Broadcast 向微微网内所有从设备广播,也可用于向单个远程设备发送无连接单播数据。
-
无连接单播的自动刷新:通过无连接通道发送的单播数据受自动刷新机制约束,如果控制器支持 Packet Boundary Flag 特性,需要正确设置包边界标志。
-
BLE 不使用 G-frame:G-frame 是经典蓝牙(BR/EDR)的 L2CAP 特性,BLE 中对应的 PDU 类型为 B-frame(基本模式)和 K-frame(信用模式)。
-
协议栈实现差异:不同蓝牙协议栈对 G-frame 的支持程度不同。例如,Zephyr 协议栈对 LE 的支持仅涉及 B-frame 和 K-frame,G-frame 属于 BR/EDR 的 PDU 类型。
5. 增强重传模式与流控模式
基本模式虽然简单,但缺乏可靠性和流控机制。对于需要可靠传输的场景,L2CAP 定义了增强重传模式(Enhanced Retransmission Mode, ERTM)和流控模式(Flow Control Mode)。这两种模式引入了 I-frame(信息帧)和 S-frame(监督帧)的概念。

5.1 I-frame 控制字段

I-frame 在基本头部之后增加了一个控制字段:
| 字段 | 位数 | 说明 |
|---|---|---|
| SAR | 2 位 | 分段标志:00=未分段,01=SDU起始,10=SDU结束,11=SDU延续 |
| ReqSeq | 6 位 | 接收序列号,用于确认 I-frame |
| TxSeq | 6 位 | 发送序列号,用于排序和重传 |
| P | 1 位 | 轮询位,请求对端响应 |
| F | 1 位 | 最终位,响应轮询 |
SAR 字段是实现 L2CAP 层分段重组的关键。当一个 SDU 被分成多个 I-frame 时,第一个 I-frame 的 SAR 设为 0b01,中间的为 0b11,最后一个为 0b10。携带 SAR=01 的 I-frame 会额外包含一个 2 字节的 SDU Length 字段,告知接收方整个 SDU 的长度。
5.2 S-frame 类型


S-frame 用于监督和确认,其类型由 S 位决定:
| S 值 | 类型 | 说明 |
|---|---|---|
| 0b00 | RR (Receiver Ready) | 接收就绪 |
| 0b01 | REJ (Reject) | 拒绝,请求重传 |
| 0b10 | RNR (Receiver Not Ready) | 接收方忙 |
| 0b11 | SREJ (Selective Reject) | 选择性拒绝 |
5.3 SAR 分段重组流程
当一个较大的 SDU 需要在 L2CAP 层分段传输时,流程如下:
发送方 接收方
│ │
│── I-frame (SAR=01, SDU_Len=N) ──────> │ 收到起始帧
│── I-frame (SAR=11) ──────────────────> │ 收到中间帧
│── I-frame (SAR=11) ──────────────────> │ 收到中间帧
│── I-frame (SAR=10) ──────────────────> │ 收到结束帧,重组完成
│<──── S-frame (RR) ──────────────────── │ 确认
6. LE Credit Based Flow Control 模式(K-frame)
BLE 面向连接信道(CoC)使用 LE Credit Based Flow Control 模式,其数据帧称为 K-frame 。与基本模式的 B-frame 不同,K-frame 的第一个帧包含一个额外的 2 字节 SDU Length 字段。

6.1 K-frame 格式
| 字段 | 大小 | 说明 |
|---|---|---|
| Length | 2 字节 | PDU 总长度 |
| CID | 2 字节 | 信道标识符 |
| SDU Length | 2 字节 | 仅在第一个 K-frame 中存在 |
| Payload | 可变 | SDU 数据 |
6.2 信用管理机制
LE Credit Based Flow Control 使用信用(Credit)机制进行流控。发送方需要消耗信用才能发送数据,接收方通过 LE Flow Control Credit 命令(Code=0x16)补充信用。初始信用值在连接建立时通过 LE Credit Based Connection Request/Response 协商。
7. 抓包实例分析
以下是一个通过 Wireshark 抓取的 BLE L2CAP 数据包的示例:
Frame 1: 32 bytes on wire (256 bits), 32 bytes captured
Bluetooth Low Energy Link Layer
LL Header: LLID=0x02 (Start of L2CAP message), Length=24
Bluetooth L2CAP Protocol
Length: 20
CID: 0x0004 (Attribute Protocol)
Payload: 0x0a 0x01 0x00 0x04 ...
解读:
-
LL Header 的 LLID=0x02 表示这是一个 L2CAP 消息的开始
-
L2CAP Length=20 表示 payload 长度为 20 字节
-
CID=0x0004 表示承载的是 ATT 协议数据
-
Payload 以 ATT PDU 的 Opcode 开始
在 Wireshark 中,可以通过 btl2cap 显示过滤器仅查看 L2CAP 流量。如果看到"L2CAP Fragment"字样,说明 Wireshark 未开启 SDU 重组功能,可以在 Bluetooth L2CAP 首选项中开启。开启后,Wireshark 会自动将碎片化的 L2CAP 分段重新拼接为完整的信令 PDU。
8. MTU 与数据长度的关系
理解 L2CAP 中的几个 MTU 概念至关重要:
| 概念 | 默认值 | 最大协商值 | 说明 |
|---|---|---|---|
| ATT_MTU | 23 字节 | 517 字节 | ATT 层最大传输单元 |
| L2CAP MTU | 672 字节 | 65535 字节 | L2CAP 层最大传输单元 |
| LL Data Length | 27 字节 | 251 字节 | 链路层单次传输最大负载 |
在 BLE 4.0/4.1 中,L2CAP 层的 MTU 与 ATT_MTU 一致,均为 23 字节。BLE 4.2 引入了数据长度扩展和 LE Credit Based Flow Control,使得 L2CAP 层的 MTU 可以协商到更大的值。L2CAP 的最小 MTU 为 48 字节,最大可达 65535 字节。
9. 总结
L2CAP 虽然在实际开发中经常被"透明化"处理,但掌握其数据包格式对于深入理解 BLE 协议栈至关重要。本文从帧结构出发,系统梳理了以下要点:
-
基本头部:4 字节(Length + CID),是所有 L2CAP 数据包的共同结构
-
B-frame:基本模式下的信息帧,包含完整 SDU
-
C-frame:信令帧,通过 CID 0x0001/0x0005 传输,支持多种信令命令
-
G-frame:无连接通道帧,通过 CID 0x0002 传输,包含 PSM 字段,用于经典蓝牙的广播/无连接单播
-
I-frame/S-frame:增强重传模式下的信息帧和监督帧,支持分段重组和流控
-
K-frame:LE Credit Based Flow Control 模式下的数据帧,包含额外的 SDU Length 字段
-
抓包分析 :Wireshark 中通过
btl2cap过滤器查看 L2CAP 流量,开启 SDU 重组后可以查看完整的信令 PDU