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

参考

  1. USB Implementers Forum, Inc. - “移动宽带接口模型的通用串行总线通信类子类规范”,修订版 1.0(勘误表 1),2013 年 5 月 1 日

  2. USB Implementers Forum, Inc. - “网络控制模型设备的通用串行总线通信类子类规范”,修订版 1.0(勘误表 1),2010 年 11 月 24 日

  3. libmbim - “一个基于 glib 的库,用于与使用移动接口宽带模型 (MBIM) 协议的 WWAN 调制解调器和设备进行通信”

  4. ModemManager - “一个由 DBus 激活的守护程序,用于控制移动宽带 (2G/3G/4G) 设备和连接”

  5. “MBIM(移动宽带接口模型)注册表”

  6. “/sys/kernel/debug/usb/devices 输出格式”

  7. “/sys/bus/usb/devices/.../descriptors”