WWAN MBIM multiplexing in ModemManager for multiple PDNs

WWAN MBIM concurrent data connections can now be used in ModemManager.

ModemManager support for concurrent multiple PDNs when using the cdc_mbim driver has been there for a while, but that feature applies just to USB modems.

Modems using the WWAN subsystem for MBIM (e.g. Qualcomm ones driven by mhi_wwan_mbim) had this feature available at the kernel level, but it was not yet supported by libmbim and ModemManager.

WWAN MBIM

With libmbim MR “Add wwan pci link management” and ModemManager MR “bearer-mbim: enable multiplex support for wwan devices“, ModemManager is now capable of setting-up multiple concurrent data connections with WWAN MBIM modems.

Setting-up multiple WWAN MBIM connections

At the moment of writing this feature is available just in main, so a build from sources is required.

For showing the feature I’m using Telit FN990, which is supported in Linux kernel mainline since v5.19-rc1.

$ mmcli -m 1
  -----------------------------------
  General   |                   path: /org/freedesktop/ModemManager1/Modem/1
            |              device id: 5363d56741fc2e042a95eeee8f74e2b3ee62373e
  -----------------------------------
  Hardware  |           manufacturer: telit
            |                  model: FN990A28
            |         carrier config: default
            |           h/w revision: FN990A28
            |              supported: gsm-umts, lte, 5gnr
            |                current: gsm-umts, lte, 5gnr
            |           equipment id: *********
  -----------------------------------
  System    |                 device:
/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0
            |                drivers: mhi-pci-generic
            |                 plugin: telit
            |           primary port: wwan0mbim0
            |                  ports: wwan0 (net), wwan0at0 (at), wwan0at1 (at),
            |                         wwan0mbim0 (mbim), wwan0nmea0 (ignored), wwan0qcdm0 (ignored)

Since NetworkManager does not yet support multiplexed data connections, the whole operation is done through mmcli and manual netdevice configuration. The first step is to create a bearer with the multiplex property flagged as required:

$ sudo mmcli -m <modem index> --create-bearer="apn=<apn 1>,ip-type=<ip
type>,multiplex=required"
Successfully created new bearer in modem:
        /org/freedesktop/ModemManager1/Bearer/<bearer index 1>

The related line in ModemManager debug log is:

ModemManager[8120]: <debug> [1666615818.556410] [modem1] creating MBIM bearer in MBIM modem

Then, a second bearer can be added with the same line, so we are ready to have two concurrent data connections.

Once the bearers are ready, it is possible to connect them:

$ sudo mmcli -m <modem index> -b <bearer index 1> --connect
successfully connected the bearer

The interesting part of ModemManager debug log is the following, showing ModemManager creating the mbimmux1.1 netdevice:

ModemManager[8120]: <debug> [1666616022.246592] [modem1/bearer2] user
request to connect
ModemManager[8120]: <debug> [1666616022.248342] [modem1/bearer2] connecting...
ModemManager[8120]: <info>  [1666616022.248382] [modem1] state changed
(registered -> connecting)
ModemManager[8120]: <debug> [1666616022.248516] [modem1/bearer2]
launching multiplexed connection with data port (net/wwan0)
ModemManager[8120]: <debug> [1666616022.248538] [modem1/bearer2]
activating packet service...
ModemManager[8120]: <debug> [1666616022.248565] [/dev/wwan0mbim0] sent
message...
...
ModemManager[8120]: <debug> [1666616022.321065] [modem1/bearer2]
packet service update:
ModemManager[8120]: <debug> [1666616022.321111] [modem1/bearer2]
     state: 'attached'
ModemManager[8120]: <debug> [1666616022.321142] [modem1/bearer2]
data class: 'lte'
ModemManager[8120]: <debug> [1666616022.321173] [modem1/bearer2]
data subclass: 'none'
ModemManager[8120]: <debug> [1666616022.321206] [modem1/bearer2]
    uplink: '1250000000' bps
ModemManager[8120]: <debug> [1666616022.321233] [modem1/bearer2]
  downlink: '3951000000' bps
ModemManager[8120]: <debug> [1666616022.321258] [modem1/bearer2]
frequency range: 'unknown'
ModemManager[8120]: <debug> [1666616022.321287] [modem1/bearer2]
setting up new multiplexed link...
ModemManager[8120]: <debug> [1666616022.329025] Using dynamic session ID 1
ModemManager[8120]: <debug> [1666616022.329060] Using ifname
'mbimmux1.1' and link id 1
ModemManager[8120]: <info>  [1666616022.329378] [modem1/bearer2] net
link mbimmux1.1 created (session id 1)
ModemManager[8120]: <debug> [1666616022.329403] [modem1] waiting for
port 'net/mbimmux1.1'...
ModemManager[8120]: <debug> [1666616022.339826] [mbimmux1.1] port
contents loaded:
ModemManager[8120]: <debug> [1666616022.339855] [mbimmux1.1]   bus: pci
ModemManager[8120]: <debug> [1666616022.339866] [mbimmux1.1]   device:
/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0
ModemManager[8120]: <debug> [1666616022.339875] [mbimmux1.1]   driver:
mhi-pci-generic
ModemManager[8120]: <debug> [1666616022.339884] [mbimmux1.1]   vendor: 17cb
ModemManager[8120]: <debug> [1666616022.339892] [mbimmux1.1]   product: 0308
ModemManager[8120]: <debug> [1666616022.339901] [mbimmux1.1]
subsystem vendor: 1c5d
ModemManager[8120]: <debug> [1666616022.339909] [base-manager] adding
port mbimmux1.1 at sysfs path:
/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/mhi0/wwan/wwan0/net/mbimmux1.1
ModemManager[8120]: <debug> [1666616022.339992] [filter]
(net/mbimmux1.1) port allowed: device is allowlisted by plugin
(vid/subsystem vid)
ModemManager[8120]: <debug> [1666616022.340012] [base-manager]
additional port mbimmux1.1 in device
/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0
ModemManager[8120]: <debug> [1666616022.340027] [device
/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0] grabbing wwan
multiplexed device mbimmux1.1
ModemManager[8120]: <debug> [1666616022.340052] [modem1] link port
'net/mbimmux1.1' grabbed
ModemManager[8120]: <debug> [1666616022.340071] [modem1/bearer2]
bringing main interface wwan0 up...

Checking the bearer properties we can get the desired addresses:

$ mmcli -m <modem id> -b <bearer id>
  ------------------------------------
  General            |           path: /org/freedesktop/ModemManager1/Bearer/5
                     |           type: default
  ------------------------------------
  Status             |      connected: yes
                     |      suspended: no
                     |    multiplexed: yes
                     |      interface: mbimmux2.1
                     |     ip timeout: 20
  ------------------------------------
  Properties         |            apn: web.omnitel.it
                     |        roaming: allowed
                     |        ip type: ipv4
  ------------------------------------
  IPv4 configuration |         method: static
                     |        address: 176.247.66.211
                     |         prefix: 29
                     |        gateway: 176.247.66.212
                     |            dns: 10.133.106.46, 10.132.100.212
                     |            mtu: 1500
  ------------------------------------
  Statistics         |     start date: 2022-10-24T12:58:41Z
                     |   uplink-speed: 1250000000
                     | downlink-speed: 3951000000
                     |       attempts: 1

The information can be used for configuring the netdevice:

$ sudo ip addr add 176.247.66.211/29 dev mbimmux2.1
$ sudo ip link set mbimmux2.1 up

And we can finally verify that traffic is properly passing:

$ ping 8.8.8.8 -I mbimmux2.1
PING 8.8.8.8 (8.8.8.8) from 176.247.66.211 mbimmux2.1: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=111 time=80.1 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=111 time=41.7 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=111 time=44.8 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=111 time=44.7 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=111 time=46.8 ms
^C
--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 41.716/51.628/80.132/14.344 ms

$ ip -s l

5: wwan0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel
state UNKNOWN mode DEFAULT group default qlen 1000
    link/[519]
    RX: bytes  packets  errors  dropped overrun mcast
    0          0        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    456        6        0       0       0       0
6: mbimmux2.1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel
state UNKNOWN mode DEFAULT group default qlen 1000
    link/[519]
    RX: bytes  packets  errors  dropped overrun mcast
    420        5        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    788        8        0       0       0       0

It’s now possible to connect the second bearer and configure the related netdevice in the same way, paying attention to choose the second wwan multiplexed netdevice (e.g. mbimmux2.2). After connection and addresses configuration there will be two different multiplexed devices:

$ ip addr show
...
6: mbimmux2.1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel
state UNKNOWN group default qlen 1000
    link/[519]
    inet 176.247.66.211/29 scope global mbimmux2.1
       valid_lft forever preferred_lft forever
    inet6 fe80::200:ff:fe00:0/64 scope link
       valid_lft forever preferred_lft forever
7: mbimmux2.2: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel
state UNKNOWN group default qlen 1000
    link/[519]
    inet 100.105.159.91/32 scope global mbimmux2.2
       valid_lft forever preferred_lft forever
    inet6 fe80::200:ff:fe00:0/64 scope link
       valid_lft forever preferred_lft forever

To disconnect a bearer and dispose the multiplexed netdevice the following command can be used:

$ sudo mmcli -m <modem index> -b <bearer index> --disconnect