1. L2CAP 协议概述
逻辑链路控制与适配协议(Logical Link Control and Adaptation Protocol,L2CAP)是蓝牙协议栈中承上启下的核心层。它位于主机控制器接口(HCI)之上,向上为服务发现协议(SDP)、射频通信(RFCOMM)、属性协议(ATT)等高层协议提供统一的数据传输服务。理解 L2CAP 的定位与功能,是掌握蓝牙通信机制的基础。
1.1 L2CAP 在蓝牙协议栈中的位置
蓝牙协议栈采用分层架构,L2CAP 处于协议栈的中间位置,负责屏蔽底层基带与链路控制器的差异,为上层应用提供逻辑信道抽象。下图展示了 L2CAP 在经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)协议栈中的位置。
关键要点:L2CAP 层在 BR/EDR 和 BLE 协议栈中均位于 HCI 之上,是上层协议与底层传输之间的桥梁。在 Linux 内核中,L2CAP 层由 net/bluetooth/l2cap_core.c 和 net/bluetooth/l2cap_sock.c 等文件实现。
1.2 L2CAP 核心功能
L2CAP 层主要提供以下三项核心功能:协议复用、分段与重组、服务质量控制。这些功能共同保证了蓝牙通信的灵活性与可靠性。
1.2.1 协议复用(Protocol Multiplexing)
L2CAP 使用 通道标识符(Channel Identifier,CID) 来区分不同的上层协议实例。每个 L2CAP 通道由一对 CID(本地 CID 和远端 CID)唯一标识。上层协议(如 RFCOMM、ATT、SDP)通过注册不同的 CID 来共享同一条 ACL 逻辑链路。
| CID 范围 | 用途 | 说明 |
|---|---|---|
| 0x0001 | L2CAP 信令通道 | 用于连接建立、配置、释放等控制信令 |
| 0x0002 | 无连接数据通道(BR/EDR) | 用于广播或无连接的数据传输 |
| 0x0003 – 0x003F | 保留 | 蓝牙规范保留,暂未分配 |
| 0x0040 – 0xFFFF | 动态分配 | 用于上层协议实例(如 RFCOMM、ATT) |
性能提示:在 Linux 内核中,CID 的分配由 l2cap_chan_create() 函数管理。高并发场景下,CID 分配锁(l2cap_chan_lock)可能成为瓶颈,建议监控 /proc/net/bluetooth/l2cap 中的通道数量。
1.2.2 分段与重组(Segmentation and Reassembly)
上层协议的数据单元(Service Data Unit,SDU)可能超过底层链路层的最大传输单元(MTU)。L2CAP 负责将大的 SDU 分割成多个协议数据单元(PDU),并在接收端重组为完整的 SDU。
- 分段(Segmentation):发送端将 SDU 拆分为多个 PDU,每个 PDU 包含 L2CAP 头部(4 字节:长度 + 通道 ID)和有效载荷。
- 重组(Reassembly):接收端根据 PDU 头部信息(如序列号、分段标志)将多个 PDU 按序重组为原始 SDU。
- MTU 协商:在连接建立阶段,通信双方通过信令通道交换 MTU 大小,确保分段策略匹配。
1.2.3 服务质量控制(Quality of Service)
L2CAP 支持服务质量(QoS)参数协商,允许上层协议指定数据传输的延迟、吞吐量和可靠性要求。QoS 参数在连接建立阶段通过信令通道交换。
| QoS 参数 | 描述 | 典型值 |
|---|---|---|
| 服务类型(Service Type) | 指示是否启用 QoS 保证 | 0(尽力而为)/ 1(保证) |
| 令牌速率(Token Rate) | 平均数据传输速率(字节/秒) | 取决于应用需求 |
| 令牌桶大小(Token Bucket Size) | 允许的突发数据量(字节) | 通常为 MTU 的 2-4 倍 |
| 峰值带宽(Peak Bandwidth) | 最大瞬时传输速率(字节/秒) | 受链路层限制 |
| 延迟(Latency) | 最大允许传输延迟(微秒) | BR/EDR:通常 < 10ms |
| 延迟变化(Delay Variation) | 允许的抖动范围(微秒) | 实时音频:< 1ms |
调优注意:在 Linux 内核中,QoS 参数通过 struct l2cap_qos 结构体表示。如果上层应用未显式设置 QoS,L2CAP 默认使用尽力而为模式。对于音频/视频等高实时性应用,建议在连接建立时明确协商 QoS 参数。
1.3 L2CAP 与 HCI 和 SMP 的关系
L2CAP 层在协议栈中与 HCI 和 SMP(安全管理器协议)紧密协作,共同完成数据传输与安全控制。
1.3.1 L2CAP 与 HCI 的关系
HCI(Host Controller Interface)是主机与蓝牙控制器之间的标准接口。L2CAP 层通过 HCI 命令与控制器交互,完成以下操作:
- 数据发送:L2CAP 将 PDU 封装为 HCI 数据包(ACL Data Packet),通过 HCI 传输层发送给控制器。
- 数据接收:控制器通过 HCI 事件将接收到的 ACL 数据包传递给 L2CAP 层进行重组。
- 流控:HCI 层提供基于数据包数量的流控机制,L2CAP 需要根据 HCI 缓冲区状态调整发送速率。
1.3.2 L2CAP 与 SMP 的关系
SMP(Security Manager Protocol)负责蓝牙设备间的配对、认证和加密密钥分发。L2CAP 为 SMP 提供专用的固定通道(CID = 0x0006 用于 BLE,CID = 0x0007 用于 BR/EDR)。
- 固定通道:SMP 使用 L2CAP 的固定通道传输安全协议数据单元(PDU),无需动态建立连接。
- 加密控制:L2CAP 层在接收到 SMP 的加密请求后,通过 HCI 命令启动链路层加密。
- 安全属性:L2CAP 通道可以关联安全属性(如加密、认证),确保只有满足安全要求的通道才能传输敏感数据。
实现细节:在 Linux 内核中,SMP 通道的初始化在 l2cap_smp_init() 函数中完成。SMP 通道的 CID 固定为 0x0006(BLE)和 0x0007(BR/EDR),这些通道在 L2CAP 层启动时自动注册。
1.4 L2CAP 通道类型与数据模式
L2CAP 支持多种通道类型和数据传输模式,以适应不同的应用场景。
| 通道类型 | 描述 | 适用场景 |
|---|---|---|
| 面向连接通道(Connection-Oriented Channel) | 需要显式建立连接,支持双向数据流 | RFCOMM、ATT 等大多数上层协议 |
| 无连接数据通道(Connectionless Data Channel) | 无需建立连接,支持广播或多播 | 广播数据、服务发现 |
| 固定通道(Fixed Channel) | 预定义的 CID,无需动态分配 | SMP、信令通道 |
L2CAP 还定义了多种数据模式来控制数据传输的可靠性与顺序:
- 基本模式(Basic Mode):无重传、无顺序保证,适用于对可靠性要求不高的场景。
- 流量控制模式(Flow Control Mode):基于信用(Credit)的流控机制,接收端通过信用值控制发送端的数据量。
- 重传模式(Retransmission Mode):支持自动重传请求(ARQ),确保数据可靠传输。
- 增强重传模式(Enhanced Retransmission Mode):在重传模式基础上增加监控超时(Monitor Timeout)机制。
- 流模式(Streaming Mode):无重传,但保证顺序,适用于实时音视频。
- LE 信用模式(LE Credit Mode):BLE 特有的基于信用的流控模式,用于 LE 面向连接通道。
性能调优建议:对于 BLE 应用,推荐使用 LE 信用模式(L2CAP_MODE_LE_CREDIT),它提供了高效的流控机制,避免数据溢出。在 Linux 内核中,可通过 setsockopt() 设置 L2CAP_OPTIONS 来配置模式。