So far, OpenBSC already implemented mobility management, i.e. keeping track of which location area a mobile phone is locate in. However, this only works during idle mode, i.e. while there is no actual phone call in progress.
Throughout the last week, I've been working on getting real handover support into OpenBSC. This is now actually working very well! You can move from one cell into another cell while your phone call continues just like it is supposed to do.
The signalling part is actually not all that hard to implement. However, it has some dependencies on things like measurement reports, which in turn require us to send proper neighbor lists, which in turn requires proper generation of system information messages, etc.
The actual order of events in a successful handover case is as follows:
- OpenBSC send the neighbor cell information in the BCCH and SACCH
- OpenBSC regularly receives measurement reports from the phone, where it tells us how well neighbor cells are being received. OpenBSC then averages those measurements and decides if or not to make a hand-over. If it decides so, it
- allocates a channel on the new BTS
- waits until the BTS acknowledges this
- sends a HANDOVER COMMAND to the phone through the old BTS
- waits for HANDOVER ACCESS bursts and a HANDOVER COMPLETE on the new BTS
- closes the old channel on the old BTS
- takes care of re-routing the voice channels
As indicated, the signalling part was relatively easy, and once the measurement processing and neighbor lists were in place, this worked really quick. What turned out to be a much bigger PITA was the handling of the actual voice streams.
Let's assume you have a call from A to B, where B is changing cells and now becomes B*. In this case, after switching cells, the speech frames from A need to be re-routed to B* instead of B. That's simple and works very easy. In the other direction, switching off B is easy. However, a completely new channel B* suddenly sends speech frames to A. In case of classic TRAU frames on E1 that is simple as they don't have any context.
In the case of ip.access nanoBTS, the speech frames are transported using RTP. Changing the source of your stream will change its CSRC (synchronization source identifier), timestamps and sequence numbers. The receiver in BTS A is not happy at all about this. So with handover, it is no longer possible to send RTP streams directly between BTS's, but OpenBSC's RTP proxy needs to process the RTP packets and hide the details of the changed source.
This is further complicated by the fact that during handover you are losing speech frames, somewhere between 10 and 40 in the cases that I've seen. This means that when sending the new RTP frames from B*, the sequence number and timestamp needs to account for those lost frames, i.e. incremented by the respective loss count. Otherwise the RTP receiver in BTS A will think it is only receiving old frames and will discard all of them.
Luckily, all of this seems to have been sorted out now and I'm confident we will have actual full handover at the GSM network at 26th annual Chaos Communication Congress in a few days from now. We'll be running 3 BTS's with a total number of 5 TRX's inside the conference building.