Thursday 23 January 2014

Getting a Prolific PL-2501 based USB-to-USB link cable working with Debian and a Raspberry Pi

A while ago I had an idea to use a Raspberry Pi as a recovery interface to my bigger home server.  My home server acts as my fileserver, network router, dns server and provides the web interface for my home automation and is always on.  I wanted a way of being able to access it over the network even if it's own network interface is down for some reason (usually because I've been experimenting with something and made a mistake).

I looked into the options and decided the simplest way of making this work would be to get a USB-to-USB link cable.  These aren't simple USB cables, there is some electronics in the middle that makes it work.  They are fairly common though and there are quite a few different manufacturers, most of which seem to be based on a few chipsets.

The one I got was made by "Sandberg" and came from ebay for about £5.  Unfortunately, I was unlucky and it turned out to be based on a chipset that's not currently supported by the plusb kernel module for Prolific USB network interfaces.

The module description says:

"Prolific PL-2301/2302/25A1 USB Host to Host Link Driver"

The cable I got has a PL-2501 chipset.  It was being recognised by the USB system OK but the module simply doesn't know about this chipset:
Bus 001 Device 004: ID 067b:2501 Prolific Technology, Inc. PL2501 USB-USB Bridge (USB 2.0)
There is a patch you can find on the Internet to make this work.  It involves installing the kernel source, patching the module, compiling the module and then copying it over the original module in the kernel driver folder.

In hindsight I'd have been much better off either:
  • using the Raspberry Pi UART and a spare internal serial port in my home server along with a 3.3v-5v level converter to create a serial link
  • installing a 2nd network card into my home server, linking this to the Raspberry Pi's NIC and then using a USB-to-Ethernet dongle in the Raspberry Pi so it has 2 interfaces.
Since I already had my USB link cable I was determined to make it work.

Here is what I did to get it to work.  You will need to compile the module twice, once on the Linux server and once on the Raspberry Pi since they are different architectures.  A module compiled on x86 wont work on the ARM based Pi.

---

Standard Debian system howto

This was what I did to get the cable working on my Linux server, it's x86 architecture but this will work OK for anything using a standard Debian system (i.e. no custom kernel).

1) Install the kernel headers and kernel source packages for your current kernel:
apt-get install linux-headers-`uname -r` linux-source
Note the use of backticks - ` these are not apostrophes, on a UK keyboard the key is next to the number one key.

Then extract the source:
cd /usr/src
tar xjf linux-source-3.2.tar.gz
Note - at the time of writing the source was for kernel 3.2, might have changed when you read this!

2) Copy your running kernel config into the source folder so any compiled modules are use the correct settings:
cd /usr/src/linux-source-3.2
cp /boot/config-`uname -r` .config
cp /usr/src/linux-headers-`uname -r`/Module.symvers ./
3) Patch the plusb module to work with our PL-2501.  I found a patch someone had made and downloaded it.  However it failed to patch against my source code.   The patch was very simple though so I manually patched my file and created a new patch file that can be downloaded here:
plusb.patch
Then apply the patch:
cd /usr/src/linux-source-3.2/drivers/net/usb/
patch < plusb.patch 
4) build your module:
cd /usr/src/linux-source-3.2
 make prepare
 make scripts
 make SUBDIRS=drivers/net/usb modules
 Note - this actually builds all the modules in the net/usb folder but there's not many and it doesn't take long.

5) Replace the old module with your new one:
rmmod -f plusb
mv drivers/net/usb/plusb.ko /lib/modules/`uname -r`/kernel/drivers/net/usb/
6) Load the module and make sure it's worked:
modprobe plusb
ifconfig -a
And you should see the usb0 interface listed that you can now use like any other network interface.

Raspberry Pi howto 

The process is very similar on the R-Pi.  To keep things as simple as possible I used the kernel maintained by the Raspbian people.  If you are using a non-standard kernel or the latest kernel from the Raspberry Pi foundation it'll be a lot more involved as they don't provide header packages.

You will need quite a lot of free space on your Pi's filesystem for this, I'd estimate at least 1GB.  It depends what you already have installed.

1) Install the latest Raspbian kernel and the source package:
apt-get install linux-image-rpi-rpfv
Note - I'm not sure if this is normal (I had been messing about with kernels a fair bit) but after installing this I had to copy the new kernel over the old one before rebooting would get it to load:
cp /boot/vmlinuz-3.10-3-rpi /boot/kernel.img
Or you could add a "kernel=vmlinuz-3.10-3-rpi" line to the config.txt file.

3) Get the kernel headers and source:
apt-get install linux-headers-rpi-rpfv linux-source-3.10
Note - make sure you have the deb-src repo in your sources.list.  http://www.raspbian.org/RaspbianRepository

4) Extract the source:
cd /usr/src
tar xJf linux-source-3.10.tar.xz
Everything else is the same as the instructions for standard Debian, step 2 onwards.  Just replace "linux-source-3.2" with "linux-source-3.10" anywhere.

After that, you'll have a usb0 interface on the Raspberry Pi too.  Once you've assigned IP addresses to this interface on both systems you can access one via the other simply using ssh.

You'll definitely want the device to come up at boot time.  So create a udev rule (create a file called something like /etc/udev/rules.d/99-plusb.rules) and put this in it:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="067b", ATTR{idProduct}=="2501", RUN+="/sbin/modprobe plusb"
Do this on both systems.

In case these are of any use, here are my finished working modules for both the Raspberry Pi and x86 (Intel Atom) server:

plusb-3.2.0.4-686-pae.tar

plusb-3.10-3-rpi.tar

Tuesday 14 January 2014

Misunderstood SIP - Registration Expiry

How Registration expiry and Re-Registering works seems to be one of the most mis-understood concepts in SIP.

Registration Expiry

A SIP UAC (such as your SIP telephone) sends a Registration request to a SIP UAS (such as your PBX or hosted platform).
This Registration request has an Expires header in it (which can be an individual header or a tag in the Contact header). The value used is nearly always a configurable setting in the UAC itself.

The UAS responds to the Registration request accordingly (usually there is a process of Authentication that goes on which I wont go into here). At the end, if the Registration is accepted, the UAS will send an OK message to the UAC which contains the actual Registration expiry time (again, either an individual Expires header or as a tag in the Contact header). 

The important thing to note is that it is the UAS which decides what the expiry will be, not the UAC which is where most people go wrong. The assumption is often that if you set an expiry of 600 seconds in the UAC settings then that's what gets used. Not necessarily the case, the UAS has the final say.

Often a SIP PBX will have settings to control minimum & maximum permissible values for the Registration Expiry. Then a UAC is allowed to use any value inside this range. Outside the range, the UAS decides what gets used. Sometimes there is a default expiry to use when a UAC selects something outside of the permissible range.

Re-Registering

Once a UAC is Registered, it has to decide when to re-Register. The Expiry is not a timer to start re-Registering, it's the time when the UAS will assume the UAC isn't there any more. Think of it as a Re-Registration deadline.

So, a UAC must have completed it's re-Registration before this Expiry time or calls will stop working. There is no definitive strategy for doing this in SIP, it seems to be up to the UAC manufacturers to decide what they think is best. 

Some halve the Expiry and then start to Re-Register from that point onwards, so with an Expiry of 180 seconds, you'll start to see more Register messages after 90 seconds. This gives more than enough time for the Re-Registration to complete before the previous Registration expires. 

Other UACs choose different times either based on some percentage of the Expiry, a set number of seconds before Expiry etc...etc... 

Due to this second misunderstanding, many people think that they can alleviate Registration problems by setting a very low Expiry. In reality this nearly always makes it much worse as the UAC now has less time to actually get Re-Registered. 

Generally, I wouldn't set Registration Expiry to less than 600 seconds. There can be some circumstances when it makes sense to use a lower setting (e.g. a mobile roaming handset moving from network to network regularly might need a shorter Expiry) but in general it should be avoided.

Trying to use a very short Re-Registration timer for overcome NAT mapping issues (where a NAT router is destroying NAT mappings too quickly), isn't the correct way of doing it. Any decent UAC will have a NAT keep-alive setting somewhere (or often this happens automatically). Then the UAC will send out a SIP Options message or sometimes just a blank packet on port 5060 to keep a NAT mapping open. Use this as very short Expiry will often cause others problems as described above.