Implementing the GPRS protocol stack for OpenBSC
During the last week or so, I've been spending way too much time implementing the network-side GPRS protocol stack as part of an effort to not only provide GSM voice + SMS but also GPRS+EDGE data services with OpenBSC
GPRS is fundamentally very different from the classic circuit-switched domain of voice calls and CSD (circuit switched data). Not only conceptually and on the protocol level, but also in the actual system architecture. They way it was added on top of the existing GSM spec is by making no modification to the BSC and MSC, and only the minimal necessary modifications to the BTS. They then added a new Gb interface to the BTS, and the SGSN and GGSN core network components, who in turn talk to HLR/VLR/AUC.
So in the most primitive GPRS network, you can have the GSM and GPRS domains completely independent, only using the same databases for subscriber records and authentication keys. This goes to the extreme end that your phone would actually independently register with the GSM network (ISMI ATTACH / LOCATION UPDATING) and to the GPRS network (GPRS ATTACH / ROUTING AREA UPDATE). While both of the requests get sent to the same BTS, the BTS will send the GSM part to the BSC (and successively MSC), and the GPRS part to the SGSN.
Also, the actual software architecture looks completely different. In the GSM circuit-switched domain you always have a dedicated channel when you talk to a phone. The number of dedicated channels is limited by the transceiver capacity and the channel configuration. In OpenBSC I chose to simply attach a lot of state to the data structure representing such a dedicated channel. In the packet-switched domain this obviously no longer works. Many phones can and will use the same on-air timeslot and there is no fixed limit on how many phones can share a radio resource.
What's further important to note: The protocol stack is very deep. If you look at the GPRS related output on an ip.access nanoBTS while your mobile phone makes a HTTP request, the stack is something like HTTP-TCP-IP-PPP-SNDCP-LLC-BSSGP-NS-UDP-IP-Ethernet, while the first HTTP-TCP-IP-PPP is obvious, I would not have expected that many layers on the underlying network. Especailly if you look at the almost zero functionality that NS (GSM TS 08.16) seems to add to this stack. Also, the headers within the protocol can actually be quite big. If we only count the number of bytes between the two IP layers in this stack: 8 bytes UDP, 4 bytes NS, 20 bytes BSSGP, 6 bytes LLC and 4 byte SNDCP. That's a total of 42 extra bytes. And that for every small packet like TCP SYN, SYN/ACK or the like! No wonder that mobile data plans have been prohibitively expensive all those years ;)
So with regard to the actual GPRS implementation in OpenBSC, the following things had (or still have) to be done
- Add support for generating System Information 3 + 4 rest octets and System Information 13
- Add support for the ip.access extensions to the A-bis OML (TS 12.21) layer
- Implement the NS protocol (GSM TS 08.16)
- Implement the BSSGP protocol (GSM TS 08.18)
- Implement the LLC protocol (GSM TS 04.64)
- Implement the GPRS mobility management (GSM TS 04.08)
- Implement the GPRS session management (GSM TS 04.08)
- Implement GGSN functionality (PPP tunnel endpoints
This is a very time-consuming bit-fucking experience, encoded relative to the padding pattern of 0x2b. Without this, the phones would not realize that the cell actually supports GPRS. DONE.
This is needed to configure the GPRS parameters such as channel configuration, coding schemes or the IP and NS/BSSGP parameters for the link to the SGSN (OpenBSC). Without it, the BTS would not even start to speak NS/BSSGP, i.e. not connect to OpenBSC for GPRS services. DONE.
Turns out this was really simple, as NS doesn't really do much anyway. DONE.
This protocol is - among other things - responsible for the flow control. Both globally for the BTS as well as individually for each MS. I've implemented the basic functionality to be able to send/receive signalling and user data, but no flow control yet.
This is actually the protocol that is terminated between the MS and the SGSN, so we have moved beyond the BTS level here. Actual data from/to the mobile phone. I've implemented a minimal subset of it, including the CRC24 checksumming. I'm not taking care of packet loss, retransmissions or fragmentation yet. Just simple S, UI or U frames.
This is pretty much work in progress, but GPRS ATTACH and ROUTING AREA UPDATE is already handled. More work needed here, especially with regard to persistent storage of P-TMSI allocations as well as the last-seen position of every MS in a database.
This is the messages for activating and de-activating PDP contexts. Work has not started yet.
After all, we need to terminate the PPP sessions that the phones establish somewhere. Work has not started yet
Once all that full stack has reached a level where it works to a minimal extent, issues like BSSGP flow-control as well as LLC re-transmission, fragmentation and [selective] acknowledgement have to be dealt with.
Finally, if somebody is bored enough, he could also work on things like combined GSM/GPRS attach, or SMS over GPRS.
As you can see, it's quite a large task. But we need to start somewhere, and a lot of this will still be needed when moving into the 3G and 3.5G domain. Even if not at the lower level protocols, but from the software architecture point.
If you're into communications protocol development and don't mind our ascetic 'plain old C language' approach and are interested to contribute, feel free to introduce yourself on the OpenBSC mailing list.