The purpose of this document is to get you familiar with the concepts and command line tools involved with connecting to the internet using modern 4G LTE modems on both Debian/Ubuntu and OpenWRT.
This writeup is based on my experiences with the Sierra Wireless AirPrime MC7455 modem and a Calyx (Sprint) SIM card, but it should apply to most modern 4G LTE modems.
These are the steps required:
- Physically connect antennas
- Physically connect modem to computer using USB adaptor
- Flash latest firmware to modem
- Configure modem using AT commands
- Configure modem using QMI protocol (for some modems)
- Use command-line tools to connect
- Assign IP address, gateway and DNS
These modems come with a variety of connectors. Some use USB Type A, some use Mini PCI Express, and some use M.2 but they all communicate using USB 2 (with some supporting USB 3). This is possible because both the PCI Express Mini Card edge connector and the M.2 (aka NGFF) edge connector provide not just PCIe pins, but also USB and SIM card pins. This means that the PCIe Mini and M.2 modems can be connected to USB via an adaptor. These adaptors are cheap (e.g. on ebay) and usually include a slot for the SIM card.
For the MC7455 you will need such a Mini PCIe to USB adaptor, and probably a nanoSIM or microSIM to normal SIM adaptor since most PCIe to USB adaptors only accept a full-sized SIM card.
You will also need two antennas, or a single MIMO antenna. The frequencies used by Sprint in my area are:
- 25: 1850 to 1995 MHz (FDD-LTE)
- 26: 814 to 894 MHz (FDD-LTE)
- 41: 2496 to 2690 MHz (TDD-LTE)
The MC7455 supports all frequencies and both FDD-LTE and TDD-LTE (which are just two different ways of splitting upstream and downstream bandwidth). You can check on cellmapper.net which channels are supported by the cell towers near you and look up the corresponding frequencies here. You can then either get a wideband antenna that covers all of the frequencies supported by your modem and the cell tower, or you can pick one or two frequencies and get an antenna for just those frequencies. Usually wideband antennas that support multiple frequencies don't have as much gain. You might want to try forcing your modem to use each of the frequencies in turn and check the bandwidth during peak times before you decide on the best antenna.
For the MC7455 you will probably need pigtails (antenna adaptors) from u.fl to either SMA or N-type connectors depending on your antenna. Other modems like the EM7565 use MHF4 connectors instead of u.fl. Remember that the longer the cable from your modem to the antenna, the more signal you will loose.
If you have a Sierra modem then you will probably want to upgrade the firmware to the latest version from Sierra.
I recommend using the bootable ISO from Daniel E Wood which includes everything you need.
USB modems use the USB Communications Device Class or USB CDC. They usually show up as multiple devices in /dev
. I see three tty devices: /dev/ttyUSB0
to /dev/ttyUSB2
and one /dev/cdc-wdm0
.
One of the /dev/ttyUSBx
devices should be a serial console for AT
commands, probably using 9600 baud. If it isn't, refer to the Switching to NBIM
section of this guide.
You can connect using minicom:
minicom -o -D /dev/ttyUSB2 -b 9600
For the MC7455 you can download an AT command guide from Sierra Wireless (though you have to create an account) but you hopefully won't need any commands that aren't in this guide. There is also a nice writeup on AT commands here.
Another one of these /dev/ttyUSBx
devices will probably be for NMEA, meaning that it's for talking to the built-in GPS. This has no bearing on the 4G LTE connectivity.
There are several communications protocols used by modems. Years ago all modems used PPP, but even if your modern modem supports PPP you probably don't want to use it since it doesn't support very high bandwidth. For modern modems you will probably want to use either MBIM or QMI.
MBIM, or Mobile Broadband Interface Model, is an official USB standard created by the USB Implementors Forum.
QMI or Qualcomm Mobile Station Modem Interface was developed by Qualcomm and is only supported by Qualcomm chips.
Many Qualcomm chips like the Sierra MC7455 support both MBIM and QMI.
Both MBIM and QMI are actually just using existing Ethernet over USB standards with an added signalling channel.
MBIM is just the NCM protocol + a signalling channel and QMI is just the ECM protocol + a signalling channel.
ECM is the Ethernet Control Model and NCM is the Network Control Model. ECM is an earlier standard and has some issues with latency while NCM resolves those issues and is designed for high speed operation. You can read more here.
You can learn more about MBIM in Linux via the kernel documentation.
When configuring your modem, some settings can be changed with AT commands and others using the QMI signalling channel. I had problems changing the mode from QMI to MBIM using AT commands but was successful using the QMI signalling channel.
Since MBIM is an official USB standard and uses the more modern NCM protocol, that's what I ended up using.
With the SIM card and modem installed in the USB adaptor, plug the modem into a USB port and wait. It taked a while for the modem to boot up. Maybe give it 30 seconds.
Now use the minicom command from earlier to verify that you can talk to the modem and the SIM card is connected:
at!entercnd="A710"
at+cpin?
It should respond with "READY".
Now let's enable IPv6 while we're at it:
at!custom="IPV6ENABLE",1
at+cgdcont=1,"ipv4v6","r.ispsn"
If you want, you can ensure that the modem uses only 4G LTE:
at!selrat=06
You can also attempt to set the USB composition mode. For the MC7455 use this:
at!usbcomp = 1,1,1009
Don't worry if the at!usbcomp command fails or you have a different modem, but if it succeeds you can skip using the swi_setusbcomp
script below.
When you're done, reboot the modem:
at!reset
Exit minicom.
Now we need to change the USB composition mode of the modem. "USB composition" refers to the set and types of the devices in /dev
associated with the modem.
For this we'll use this swi_setusbcomp script.
First list the supported USB compositions using:
swi_setusbcomp.pl --device=/dev/cdc-wdm0
You will see a list with entries that look something like this:
6 => 'DM NMEA AT QMI',
7 => 'DM NMEA AT RMNET1 RMNET2 RMNET3',
8 => 'DM NMEA AT MBIM',
9 => 'MBIM',
10 => 'NMEA MBIM',
Pick an entry that includes both AT and NBIM and note down the number, then run:
swi_setusbcomp.pl --device=/dev/cdc-wdm0 --usbcomp=<number>
Replacing <number>
with the number of that entry. I used number 1.
Now unplug the modem and plug it back in.
You should now be able to connect. For testing this on Debian/Ubuntu you can install libqmi-utils:
sudo apt install libmbim-utils
which installs the command mbim-network
. To connect you will need your APN for your 4G LTE provider. For the Sprint connection you get from Calyx this is r.ispsn
. Edit /etc/mbim-network.conf
(create it if it doesn't exist) and make sure a line says "APN=<your_apn>" so for Calyx Sprint it would be "APN=r.ispsn". Also ensure that the file has a line that says "PROXY=yes". If you don't use a proxy then you can't query the active connection while it is being used. If you have a username and password see man mbim-network
.
You might want to stop network-manager before you run this test:
sudo service network-manager stop
Check that you can use mbimcli
to talk to the device at all:
sudo mbimcli --device=/dev/cdc-wdm0 --query-device-caps
Start the network connection:
sudo mbim-network /dev/cdc-wdm0 start
If it works you should see a new network interface probably called wwan0
when you run ip link
.
Now to figure out which IP, gateway and DNS to use you can run:
sudo mbimcli -d /dev/cdc-wdm0 -p --query-ip-configuration
I got the IPv4 IP and subnet 184.250.142.38/30
so to set it I did:
sudo ip link set dev wwan0 up
sudo ip addr add 184.250.142.38/30 dev wwan0
and then to set the gateway (in my case 184.250.142.37):
sudo ip route add default via 184.250.142.37 dev wwan0
You should now be able to ping 8.8.8.8
.
If you want to configure a nameserver then you can edit /etc/resolv.conf
but remember to put it back the way it was before re-starting network-manager.
If MBIM doesn't work for you, you can try using swi_setusbcomp.pl
to switch to a USB composition that includes QMI.
Then you can repeat the above instructions for MBIM but with the package libqmi-utils
, the config file /etc/qmi-network.conf
and the commands qmi-network
and qmicli
. The command to get the IP and gateway is different though and I don't know what it is for qmicli
.
OpenWRT doesn't seem to have complete official support for MBIM/QMI modems. An updated (as of late 2018) patch-set that uses ModemManager is available here. The problem with this solution (and why it will probably not get merged) is that it requires DBus rather than ubus.
The other option is to use the GoldenOrb ROOter firmware which automates everything via a nice web UI, but then you're no longer running stock OpenWRT.
For now it just doesn't seem that MBIM and QMI is well-integrated into OpenWRT, but I could be wrong. It could be that it's simply not documented. The only mention seems to be here. For QMI, using the uqmi
utility manually is documented here but it doesn't seem to be integrated into uci
or ubus
.
OpenWRT does have a utility for mbim
called umbim
. You can install it using:
opkg update
opkg install umbim
If you want to use it on a non-openwrt system you can compile it like so:
sudo apt install libjson-c-dev lua5.1 lua-json liblua5.1-0-dev
# bit hacky
sudo cp /usr/include/lua.h /usr/include/lua.h.old
sudo cp /usr/include/lua5.1/lua.h /usr/include/
git clone https://git.openwrt.org/project/libubox.git
cd libubox
mkdir build
cd build/
cmake ..
make
sudo make install
cd ../..
sudo cp /usr/include/lua.h.old /usr/include/lua.h
# or delete /usr/include/lua.h if there is no lua.h.old
git clone https://git.openwrt.org/project/umbim.git
cd umbim/
mkdir build
cd build/
cmake ..
make
sudo make install
sudo ldconfig -v
Now you can run umbim
.
To install all the required packages for umbim
on OpenWRT:
opkg update
opkg install umbim kmod-usb-net-cdc-mbim kmod-usb-net-sierrawireless kmod-usb-serial-wwan kmod-usb-serial-sierrawireless kmod-usb-serial-qualcomm
With umbim
you can connect like so:
sudo umbim -d /dev/cdc-wdm0 -n -t 2 subscriber
sudo umbim -d /dev/cdc-wdm0 -n -t 2 attach # don't worry if you get a timeout error
sudo umbim -d /dev/cdc-wdm0 connect <apn> [pap|chap|mscapv2] [username] [password]
E.g. for Calyx Sprint the last command is just:
sudo umbim -d /dev/cdc-wdm0 connect r.ispsn
When you are connected you should get some output from umbim like:
sessionid: 0
activationstate: 0001 - activated
voicecallstate: 0000 - none
nwerror: 0000 - unknown
iptype: 0003 - ipv4v6
and an interface, probably named wwan0
will appear.
To get the IP config do:
sudo umbim -d /dev/cdc-wdm0 -n -t 2 config
Now set your IP and gateway based on the config, e.g:
sudo ip link set dev wwan0 up
sudo ip addr add 184.250.142.38/30 dev wwan0
sudo ip route add default via 184.250.142.37 dev wwan0
That's it! (well maybe you want to set DNS as well, but otherwise you should be online).
Manually running a bunch of commands to connect after each reboot is obviously not ideal.
I found a nice guide for how to get MBIM working properly in OpenWRT here but unfortunately the links to the files are broken. I did find a working link to the /lib/netifd/proto/mbim.sh
file here and that seems to be the core of it. It seems like the rest of the missing files implement some sort of automatic ping and re-connect when the 4G LTE connection stops working.
TODO There is a way to force the modem to only use specified channels using AT commands. This could be useful if some channels are more crowded than others or if you have an antenna which doesn't work well for some channels.
It seems that many people experience intermittent disconnections with the MC7455. I've seen this happen myself and the GoldenOrb ROOter firmware has a nice feature for detecting these disconnects and re-connecting automatically. You have to enable this feature using the web UI. Remember to specify the IP to ping, otherwise it won't work.
For OpenWRT you could write a simple scripts that pings some server and then reboots or re-initializes the modem when pings begin failing. Or maybe you could look at how it's done in GoldebOrb ROOter.
Some have reported that the newer and faster EM7565 modem doesn't suffer from these disconnection issues but I have not tested this.
For troubleshooting modem configuration, I recommend this guide.
Great write-up. I am curious if all this is done in a ubuntu or debian OS? or are you using 2 different hardware devices, 1 for setting up module and 1 for openwrt? I have a Raspberry Pi 4 that i am trying to setup with dual cellular service (to modules connected via usb) and load-balance them out the 1Gb ethernet port. to my home network. Any suggestions would be awesome ive been at it for days. GoldenOrb doesnt support rpi4