cdc_mbim - CDC MBIM 移动宽带调制解调器驱动¶
cdc_mbim 驱动支持符合“移动宽带接口模型的通用串行总线通信类子类规范”[1] 的 USB 设备,它是“网络控制模型设备的通用串行总线通信类子类规范”[2] 的进一步发展,针对移动宽带设备(又名“3G/LTE 调制解调器”)进行了优化。
命令行参数¶
cdc_mbim 驱动程序没有自己的参数。但是,对于 NCM 1.0 向后兼容 MBIM 函数(如 [1] 第 3.2 节中定义的“NCM/MBIM 函数”),其探测行为会受到 cdc_ncm 驱动程序参数的影响
prefer_mbim¶
- 类型:
布尔值
- 有效范围:
N/Y (0-1)
- 默认值:
Y (首选 MBIM)
此参数设置 NCM/MBIM 函数的系统策略。此类函数将由 cdc_ncm 驱动程序或 cdc_mbim 驱动程序处理,具体取决于 prefer_mbim 设置。设置 prefer_mbim=N 会使 cdc_mbim 驱动程序忽略这些函数,而让 cdc_ncm 驱动程序来处理它们。
该参数是可写的,可以随时更改。需要手动取消绑定/绑定才能使更改对绑定到“错误”驱动程序的 NCM/MBIM 函数生效
基本用法¶
MBIM 函数在未管理时处于非活动状态。 cdc_mbim 驱动程序仅提供一个到 MBIM 控制通道的用户空间接口,并且不参与该函数的管理。这意味着始终需要用户空间 MBIM 管理应用程序才能启用 MBIM 功能。
此类用户空间应用程序包括但不限于
mbimcli(包含在 libmbim [3] 库中),以及
ModemManager [4]
建立 MBIM IP 会话至少需要管理应用程序执行以下操作
打开控制通道
配置网络连接设置
连接到网络
配置 IP 接口
管理应用程序开发¶
下面介绍了驱动程序 <-> 用户空间接口。 MBIM 控制通道协议在 [1] 中描述。
MBIM 控制通道用户空间 ABI¶
/dev/cdc-wdmX 字符设备¶
驱动程序使用 cdc-wdm 驱动程序作为子驱动程序创建到 MBIM 功能控制通道的双向管道。控制通道管道的用户空间端是 /dev/cdc-wdmX 字符设备。
cdc_mbim 驱动程序不会处理或管理控制通道上的消息。该通道已完全委派给用户空间管理应用程序。因此,此应用程序有责任确保其符合 [1] 中的所有控制通道要求。
cdc-wdmX 设备是作为 MBIM 控制接口 USB 设备的子设备创建的。可以使用 sysfs 查找与特定 MBIM 功能关联的字符设备。例如
bjorn@nemi:~$ ls /sys/bus/usb/drivers/cdc_mbim/2-4:2.12/usbmisc
cdc-wdm0
bjorn@nemi:~$ grep . /sys/bus/usb/drivers/cdc_mbim/2-4:2.12/usbmisc/cdc-wdm0/dev
180:0
USB 配置描述符¶
CDC MBIM 功能描述符的 wMaxControlMessage 字段限制了最大控制消息大小。管理应用程序负责协商符合 [1] 第 9.3.1 节要求的控制消息大小,同时要考虑此描述符字段。
用户空间应用程序可以使用 [6] 或 [7] 中描述的两个 USB 配置描述符内核接口中的任何一个来访问 MBIM 功能的 CDC MBIM 功能描述符。
另请参阅下面的 ioctl 文档。
分片¶
用户空间应用程序负责所有控制消息分片和解片,如 [1] 的第 9.5 节中所述。
/dev/cdc-wdmX write()¶
来自管理应用程序的 MBIM 控制消息不得超过协商的控制消息大小。
/dev/cdc-wdmX read()¶
管理应用程序必须接受最大为协商的控制消息大小的控制消息。
/dev/cdc-wdmX ioctl()¶
IOCTL_WDM_MAX_COMMAND:获取最大命令大小。此 ioctl 返回 MBIM 设备的 CDC MBIM 功能描述符的 wMaxControlMessage 字段。这旨在提供便利,从而无需从用户空间解析 USB 描述符。
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/usb/cdc-wdm.h>
int main()
{
__u16 max;
int fd = open("/dev/cdc-wdm0", O_RDWR);
if (!ioctl(fd, IOCTL_WDM_MAX_COMMAND, &max))
printf("wMaxControlMessage is %d\n", max);
}
自定义设备服务¶
MBIM 规范允许供应商自由定义其他服务。 cdc_mbim 驱动程序完全支持这一点。
对新 MBIM 服务的支持(包括供应商指定的服务)完全在用户空间中实现,就像 MBIM 控制协议的其余部分一样
新服务应在 MBIM 注册表 [5] 中注册。
MBIM 数据通道用户空间 ABI¶
wwanY 网络设备¶
cdc_mbim 驱动程序将 MBIM 数据通道表示为“wwan”类型的单个网络设备。此网络设备最初映射到 MBIM IP 会话 0。
多路复用 IP 会话 (IPS)¶
MBIM 允许通过单个 USB 数据通道多路复用最多 256 个 IP 会话。 cdc_mbim 驱动程序将此类 IP 会话建模为主 wwanY 设备的 802.1q VLAN 子设备,对于大于 0 的所有 Z 值,将 MBIM IP 会话 Z 映射到 VLAN ID Z。
设备最大 Z 在 [1] 的第 10.5.1 节中描述的 MBIM_DEVICE_CAPS_INFO 结构中给出。
用户空间管理应用程序负责在建立 SessionId 大于 0 的 MBIM IP 会话之前添加新的 VLAN 链接。可以使用普通的 VLAN 内核接口(ioctl 或 netlink)添加这些链接。
例如,为 SessionId 为 3 的 MBIM IP 会话添加链接
ip link add link wwan0 name wwan0.3 type vlan id 3
驱动程序将自动将“wwan0.3”网络设备映射到 MBIM IP 会话 3。
设备服务流 (DSS)¶
MBIM 还允许通过同一共享 USB 数据通道多路复用最多 256 个非 IP 数据流。 cdc_mbim 驱动程序将这些会话建模为主 wwanY 设备的另一组 802.1q VLAN 子设备,对于所有 A 值,将 MBIM DSS 会话 A 映射到 VLAN ID (256 + A)。
设备最大 A 在 [1] 的第 10.5.29 节中描述的 MBIM_DEVICE_SERVICES_INFO 结构中给出。
DSS VLAN 子设备用作共享 MBIM 数据通道和 MBIM DSS 感知用户空间应用程序之间的实际接口。它不打算按原样呈现给最终用户。假设启动 DSS 会话的用户空间应用程序也会处理 DSS 数据的必要成帧,从而以适合流类型的方式将流呈现给最终用户。
网络设备 ABI 要求每个传输的 DSS 数据帧都有一个虚拟以太网标头。此标头的内容是任意的,但以下情况除外
使用 IP 协议(0x0800 或 0x86dd)的 TX 帧将被丢弃
RX 帧的协议字段将设置为 ETH_P_802_3(但不会正确格式化 802.3 帧)
RX 帧的目的地址将设置为主设备的硬件地址
支持 DSS 的用户空间管理应用程序负责在 TX 上添加虚拟以太网标头,并在 RX 上将其剥离。
这是一个使用常用工具的简单示例,将 DssSessionId 5 导出为 pty 字符设备,该设备由 /dev/nmea 符号链接指向
ip link add link wwan0 name wwan0.dss5 type vlan id 261
ip link set dev wwan0.dss5 up
socat INTERFACE:wwan0.dss5,type=2 PTY:,echo=0,link=/dev/nmea
这只是一个示例,最适合测试 DSS 服务。支持特定 MBIM DSS 服务的用户空间应用程序应使用该服务所需的工具和编程接口。
请注意,为 DSS 会话添加 VLAN 链接是完全可选的。管理应用程序可以改为将数据包套接字直接绑定到主网络设备,使用收到的 VLAN 标记将帧映射到正确的 DSS 会话,并在 TX 上添加带有相应标记的 18 字节 VLAN 以太网标头。在这种情况下,建议使用套接字过滤器,仅匹配 DSS VLAN 子集。这避免了将不相关的 IP 会话数据不必要地复制到用户空间。例如
static struct sock_filter dssfilter[] = {
/* use special negative offsets to get VLAN tag */
BPF_STMT(BPF_LD|BPF_B|BPF_ABS, SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 1, 0, 6), /* true */
/* verify DSS VLAN range */
BPF_STMT(BPF_LD|BPF_H|BPF_ABS, SKF_AD_OFF + SKF_AD_VLAN_TAG),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 0, 4), /* 256 is first DSS VLAN */
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 512, 3, 0), /* 511 is last DSS VLAN */
/* verify ethertype */
BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 2 * ETH_ALEN),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ETH_P_802_3, 0, 1),
BPF_STMT(BPF_RET|BPF_K, (u_int)-1), /* accept */
BPF_STMT(BPF_RET|BPF_K, 0), /* ignore */
};
标记的 IP 会话 0 VLAN¶
如上所述,驱动程序将 MBIM IP 会话 0 视为特殊会话。它最初映射到 wwanY 网络设备上的未标记帧。
此映射意味着对多路复用 IPS 和 DSS 会话的一些限制,这些限制可能并不总是实际的
任何 IPS 或 DSS 会话都不能使用大于 IP 会话 0 上 MTU 的帧大小
除非代表 IP 会话 0 的网络设备也处于启动状态,否则任何 IPS 或 DSS 会话都不能处于启动状态
通过选择性地使驱动程序将 IP 会话 0 映射到 VLAN 子设备(类似于所有其他 IP 会话),可以避免这些问题。通过为 magic VLAN ID 4094 添加 VLAN 链接来触发此行为。然后,驱动程序将立即开始将 MBIM IP 会话 0 映射到此 VLAN,并会丢弃主 wwanY 设备上的未标记帧。
提示:最终用户将此 VLAN 子设备命名为 MBIM SessionID 而不是 VLAN ID 可能不太令人困惑。例如
ip link add link wwan0 name wwan0.0 type vlan id 4094
VLAN 映射¶
总结上述 cdc_mbim 驱动程序映射,我们可以在 wwanY 网络设备上的 VLAN 标记和共享 USB 数据通道上的 MBIM 会话之间建立这种关系
VLAN ID MBIM type MBIM SessionID Notes
---------------------------------------------------------
untagged IPS 0 a)
1 - 255 IPS 1 - 255 <VLANID>
256 - 511 DSS 0 - 255 <VLANID - 256>
512 - 4093 b)
4094 IPS 0 c)
a) if no VLAN ID 4094 link exists, else dropped
b) unsupported VLAN range, unconditionally dropped
c) if a VLAN ID 4094 link exists, else dropped
参考¶
USB Implementers Forum, Inc. - “移动宽带接口模型的通用串行总线通信类子类规范”,修订版 1.0(勘误表 1),2013 年 5 月 1 日
USB Implementers Forum, Inc. - “网络控制模型设备的通用串行总线通信类子类规范”,修订版 1.0(勘误表 1),2010 年 11 月 24 日
libmbim - “一个基于 glib 的库,用于与使用移动接口宽带模型 (MBIM) 协议的 WWAN 调制解调器和设备进行通信”
ModemManager - “一个由 DBus 激活的守护程序,用于控制移动宽带 (2G/3G/4G) 设备和连接”
“MBIM(移动宽带接口模型)注册表”
“/sys/kernel/debug/usb/devices 输出格式”
“/sys/bus/usb/devices/.../descriptors”