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”