pfSense and Mobile Broadband

This article describes how to expand the default pfSense mobile broadband support by creating a custom build with additional device support. The process is a unification of FreeBSD and Mobile Broadband and building a custom pfSense image.

pfSense is built on top of FreeBSD, so the kernel is identical. Device support can be added or removed simply by recompiling the kernel after modifying its configuration file. The default image builds do not have the necessary tools to allow this, so if you want to add support for a new device you need to rebuild pfSense from sources as described here.

Start from a clean install of FreeBSD 8.3 and follow the build process until you reach step 5.3 “Invoke the Build ISO option”. Before you start this step, create the following patch called “broadband.diff” replacing all instances of ????? with your corresponding device information:

--- ./sys/dev/usb/serial/u3g.c   2012-03-06 14:37:00.000000000 +0100
+++ ./sys/dev/usb/serial/u3g.c.new   2012-06-03 18:19:07.000000000 +0200
@@ -460,2 +460,3 @@
    U3G_DEV(SIERRA, E6892, 0),
+   U3G_DEV(?????, ?????, 0),
    U3G_DEV(SIERRA, E6893, 0),
--- sys/dev/usb/usbdevs   2012-06-03 18:26:29.000000000 +0200
+++ sys/dev/usb/usbdevs.new   2012-06-03 18:26:22.000000000 +0200
@@ -2992,2 +2992,3 @@
 product SIERRA E6892      0x6892   E6892
+product ????? ?????      ?????   ?????
 product SIERRA E6893      0x6893   E6893

Place it under “/home/pfsense/tools/patches/RELENG_8_3″.
Edit “/home/pfsense/tools/builder_scripts/patches.RELENG_8_3″ and add “~~broadband.diff” below “~~huawei_k4505.diff”.

Proceed with step 5.3 (run “./build_iso.sh”) to build the images. The build process will fail the first time, perform a cleanup and re-run “./build_iso.sh”
That will re-fetch the kernel sources, re-apply the patches (including “broadband.diff”) and build the images.

It should work for all Sierra and Novatel devices, and for the majority of HUAWEI and ZTE devices.

FreeBSD and Mobile Broadband

Since there is not much information on how to get mobile broadband up and running on FreeBSD, I decided to share the knowledge. This article will focus on miniPCIe 3G and 4G wireless modules but should provide enough information for USB 3G and 4G wireless sticks (aircards) since the concept is the same. I will start with a quick overview, some requirements, then I will go into FreeBSD support and setting up the connection.

Overview
Requirements
FreeBSD Support
Wireless Module Info
PPP Configuration
Troubleshooting

Overview

What is 2G, 3G, or 4G?

These are generations of technical standards that define how data is transmitted over cellular networks. 2G (2nd Generation) was the first set of standards that introduced data transfers over cellular networks. These standards “transformed” from generation to generation, allowing for higher speeds and efficiency without being backwards compatible.

What is LTE?

LTE (or 4G LTE) is a 4G standard which allows for theoretical speeds of up to 100 Mbps download and 50 Mbps upload. Keep in mind that 4G does not automatically imply LTE, since LTE is a standard of 4G. In some countries some Wireless Providers (cellular carriers) already deployed LTE networks in certain areas, so please check with your local cellular service providers for coverage and availability.

Requirements

Let’s start with the Hardware requirements.

First we’re going to need a miniPCIe 3G or 4G wireless module, preferably made by HUAWEI, Novatel, Option or Sierra. These are also known as Broadband Embedded Modules or WWAN cards. Some versions of these modules rebranded by DELL, HP or Toshiba should also work. These modules require antennas to be attached via U.FL connectors to function properly. Make sure that the antennas are designed to work under the same frequency range as the module, or the specific frequency you are trying to connect at the very minimum.

Some laptops have an integrated SIM slot and mobile broadband support, but generally speaking any motherboard that has a miniPCIe slot and a SIM slot should work if the miniPCIe slot has USB interface support. On most motherboards the miniPCIe slot supports both interface types (PCIe and USB), but it’s best to check with the manufacturer first. Most miniPCIe 3G or 4G wireless modules need USB interface support to function, so this is important.

You will also need an active SIM card with a data plan from one of your local wireless providers. The best way to check if this part is covered is by being able to browse the Internet on your Smartphone using the same SIM card.

Another important factor is the compatibility of standards and frequencies between your wireless provider and your miniPCIe 3G or 4G wireless module.
A way to check this is to compare the supported standards and frequencies of your miniPCIe wireless module with the ones of your smartphone where you successfully used the SIM card to connect to the Internet. This information should be widely available on the Internet, sites such as http://www.gsmarena.com provide a large database of smartphones with their standards and frequencies support.

Last but not least, we’re going to need FreeBSD Operating System installed. I chose FreeBSD STABLE which is version 8.3 at the time of writing this article, but I’m sure other branches or versions will also work. Make sure you install the source code for the kernel because we will potentially need to make some modifications to it to add support for your miniPCIe module and recompile. For more information about FreeBSD including a place to download it from, please visit http://www.freebsd.org.

FreeBSD Support

And now, on with the fun part.

Insert your miniPCIe wireless module into an available port, and boot up FreeBSD. First check to see if your module is supported out of the box so you can skip all the way to the ppp.conf section. Look for any cuaU* devices under /dev by running the following command:

FreeBSD# ls /dev/cuaU*
ls: No match.
FreeBSD#

“No match” means that we cannot communicate with the modem yet because it is not recognized. We need to make some modifications to the kernel source code and recompile it in order to have the modem recognized. If your module has a USB control interface, it should be picked up by the generic USB driver like shown below:

FreeBSD# dmesg | grep ugen
ugen0.1: <Intel> at usbus0
ugen1.1: <Intel> at usbus1
ugen2.1: <Intel> at usbus2
ugen3.1: <Intel> at usbus3
ugen4.1: <Intel> at usbus4
ugen5.1: <Intel> at usbus5
ugen6.1: <Intel> at usbus6
ugen2.2: <Novatel Wireless, Inc.> at usbus2
ugen5.2: <DIALOGUE INC> at usbus5
ugen3.2: <HP> at usbus3
FreeBSD#

In this particular case, a Novatel Wireless module has been discovered on USB bus 2 at address 2. Your numbers will most likely be different, but keep in mind that the number after “ugen” and before the “.” is the USB bus number, and the number after the “.” is the address. We now need to get more information about this device so we can modify FreeBSD’s u3g driver to add support for it and be able to control it. Getting the information we’re after can be done with the following “usbconfig” command:

FreeBSD# usbconfig -u 2 -a 2 dump_device_desc
ugen2.2:  at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON

  bLength = 0x0012
  bDescriptorType = 0x0001
  bcdUSB = 0x0200
  bDeviceClass = 0x00ef
  bDeviceSubClass = 0x0002
  bDeviceProtocol = 0x0001
  bMaxPacketSize0 = 0x0040
  idVendor = 0x03f0
  idProduct = 0x3b1d
  bcdDevice = 0x0000
  iManufacturer = 0x0004  
  iProduct = 0x0003  
  iSerialNumber = 0x0005  
  bNumConfigurations = 0x0001

FreeBSD#

We’re only interested in the values for idVendor and idProduct. In our case idVendor equals 0x03f0 and idProduct equals 0x3b1d, but depending on what Make/Model wireless module you have, your values will most likely be different. Take note of these values, they are important.
Navigate to FreeBSD’s kernel source directory “/usr/src/sys/dev/usb/” and open the “usbdevs” file with vi or your favourite editor. Perform a search function for the value of idVendor, in our particular case for 0x03f0, and take note of the whole line:

vendor HP	0x03f0	Hewlett Packard

Looks like it is an HP branded Novatel Wireless module, found in some HP laptops.
Let’s make sure there is no support for it first by searching for the value of idProduct in the same “usbdevs” file. If there isn’t, locate the corresponding group (“HP products” in our case) and add it. In my case I know it’s an E362 but if you don’t know the model, choose something unique using numbers, letters or both. Here’s how I added it:

/usr/src/sys/dev/usb/usbdevs [snippet]:

/* HP products */
product HP E362                 0x3b1d  Novatel E362	
product HP 895C                 0x0004  DeskJet 895C
product HP 4100C                0x0101  Scanjet 4100C
product HP S20                  0x0102  Photosmart S20
product HP 880C                 0x0104  DeskJet 880C
product HP 4200C                0x0105  ScanJet 4200C
product HP CDWRITERPLUS         0x0107  CD-Writer Plus
product HP KBDHUB               0x010c  Multimedia Keyboard Hub
product HP G55XI                0x0111  OfficeJet G55xi
product HP HN210W               0x011c  HN210W 802.11b WLAN

Now navigate to “/usr/src/sys/dev/usb/serial” and open the “u3g.c” file with vi or your favourite editor. Search the file for vendor and add it with the other HP products
Add a line that references to the model we want to add support for:

/usr/src/sys/dev/usb/serial/u3g.c [snippet]:

        U3G_DEV(HP, E362, 0),
        U3G_DEV(HP, EV2200, 0),
        U3G_DEV(HP, HS2300, 0),
        U3G_DEV(HUAWEI, E1401, U3GINIT_HUAWEI),
        U3G_DEV(HUAWEI, E1402, U3GINIT_HUAWEI),
        U3G_DEV(HUAWEI, E1403, U3GINIT_HUAWEI),
        U3G_DEV(HUAWEI, E1404, U3GINIT_HUAWEI),
        U3G_DEV(HUAWEI, E1405, U3GINIT_HUAWEI),
        U3G_DEV(HUAWEI, E1406, U3GINIT_HUAWEI),

Next you need to recompile the kernel. For detailed information on how to accomplish this please visit http://www.freebsd.org/handbook/kernelconfig.html.
After booting your newly compiled kernel, the u3g driver should now detect your wireless module as shown below:

FreeBSD# dmesg | grep u3g
u3g0: <Novatel Wireless, Inc. Novatel Wireless 4G, class 239/2, rev 2.00/0.00, addr 2> on usbus2
u3g0: Found 4 ports.
FreeBSD#

If all goes well we should now have the cuaU* devices listed under /dev:

FreeBSD# ls /dev/cuaU*
/dev/cuaU0.0            /dev/cuaU0.1.init       /dev/cuaU0.2.lock
/dev/cuaU0.0.init       /dev/cuaU0.1.lock       /dev/cuaU0.3
/dev/cuaU0.0.lock       /dev/cuaU0.2            /dev/cuaU0.3.init
/dev/cuaU0.1            /dev/cuaU0.2.init       /dev/cuaU0.3.lock
FreeBSD#

At this point we can move on and configure the ppp (Point-to-point Protocol) application to control the modem, but before we do that it’s good to know more about these wireless modems.

Embedded Modules tested and working with FreeBSD 8.x:

Sierra AirPrime MC7700
DELL DW5800 (Novatel Expedite E362)
HP LT2510 (Novatel Expedite E362)

Wireless Module Info

In order to have a better idea on how to control these wireless modules, some basic knowledge on what they are and how they operate is required.
Essentially, these wireless modules are smart modems with Data, GPS and SMS capabilities. The core functionality is usually provided by a Qualcomm chipset which has 2 modes of operation: DirectIP and QMI (Gobi).

In DirectIP mode the wireless module can be controlled through AT commands (aka Hayes command set) just like any modem, by any application that can open a serial connection to the modem’s command control port. Here’s where the ppp application comes into play, and in this article we will focus on this mode.

QMI (Gobi) mode is Qualcomm specific, and it is a mode of operation where the modem is controlled through an API that sits on top of the wireless module driver. QMI mode is more flexible, and it is usually used on customized firmware by wireless providers to control the way the modem connects to the wireless network.
Changing from DirectIP to QMI mode is done through an AT command.

Please contact your manufacturer for API documentation and details on supported AT commands. They usually provide both a basic (standard) and advanced (extended) AT command set.

PPP Configuration

ppp.conf is the configuration file for the ppp (Point-to-point Protocol) application.
I will go over and explain the mobile broadband specific parameters. For general information how to configure user-ppp please visit http://www.freebsd.org/handbook/userppp.html.
Wireless provider information (APN, authentication credentials and dial number) is different from carrier to carrier and you can acquire it by either contacting them directly or by searching the web.

default:
 set log Phase Chat LCP IPCP CCP tun command
 set device /dev/cuaU0.0
 set timeout 180

provider:
 set speed 921600
 set timeout 0
 set authname wapuser1
 set authkey wap
 set dial "ABORT BUSY TIMEOUT 3 \
        \"\" \
        AT OK-AT-OK \
        AT+CFUN=1 OK-AT-OK \
        AT+CMEE=2 OK-AT-OK \
        AT+CSQ OK \
        AT+CGDCONT=1,\\\"IP\\\",\\\"lteinternet.apn\\\" OK \
        ATD*99# CONNECT"
 enable dns
 resolv writable
 set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.255 0.0.0.0
 add default HISADDR

Most of the commands start with AT. The first AT command lets the modem know that a sequence of commands will follow.
AT+CFUN=1 enables full functionality. Depending on the manufacturer, different values represent different functionality levels such as low power mode or transmit/receive only.
AT+CMEE=2 enables verbose error codes in human readable form.
AT+CSQ returns the signal strength, and 7 or greater is usually needed for a successful connection (valuable in troubleshooting).
AT+CGDCONT=1,\\\”IP\\\”,\\\”lteinternet.apn\\\” configures the modem’s profile number 1 with the protocol to use (IP) and the wireless provider’s APN (lteinternet.apn).
ATD*99# is the command to dial *99#

Troubleshooting

(to be continued)