The Importance of Separation of Signalling and Application Planes


Services and applications running in GSM, IMS and EPC networks require signalling protocol stacks. Embedding the stacks in the same process where the application runs is a solution that follows a non-distributed architecture.

A non-distributed architecture where the signalling and application planes are not separated has disadvantages, including limited scalability and performance capabilities, and higher costs in case of scaling by multiplying protocol layer licenses.

Distributed Architecture with Separation of Signalling and Application Planes Implemented by JN SPU

Applicata JN Singalling Processing Unit implements a distributed architecture wehre the signalling and application planes are separated. Signalling plane with JN SPU can be shared between the applications running at application plane

The signalling module(s) and the application(s) run in different processes or machines communicating with each other over IP

All applications and application instances at the application plane share the same Signalling Processing Unit(s) running at the signalling plane. The applications can be easily scaled without affecting the signalling layer.

Applicata JN Signalling Processing Unit

Applicata JN SPU offers a cost effective and feature reach signalling solution with integrated protocol stacks, configuration and monitoring, rate control, message dispatching, very high performance, easy integration, network virtualisation, service high availability and scalability

Download JN SPU Overview datasheet


Operating System

Linux RedHat, CentOS,

Support for Multiple Protocols

Full ASM.1 Encoding/Decoding for SS7 MAP Versions 1, 2, 3 and 4

Full ASM.1 Encoding/Decoding for SS7 CAP Phases 1, 2, 3 and 4

SIP† and Diameter

SSH for OA&M and Provisioning

High Performance, High Availability

One instance of JN SPU can handle the signalling traffic rate up to 48 Mb/sec running on a 8 core server and up to 16 Mb/sec on a virtual machine with two cores.

Several instances of JN SPU can be started in active-active mode. Because of SPU high performace capabilities two instances running in paralell provide high availability and enough performance for typical services and applications.

Easy Installation

JN SPU comes as rpm and debian packages for quick and easy installation.


Fully Software Based, Network Function Virtualisation

JN SPU does not require specialised hardware. It can be run on normal server, virtual machines or cloud environment. The solution allows SPU functions virtualisation.

Easy Scalability

Scalling the system at the application layer for new functionalities or increased capacity is easy and flawles by adding new servers or virtual machines with new applications or application instances.

Easy Integration with Applications Written in Different Languages

Applications implemented in Java, C/C++, Erlang, Python or other languages, including scripts, can use JN SPU as signalling processor.

JN SPU comes with Signalling Layer Interface libraries for different programming languages. These libraries implement the establishement of tcp connections with SPU nodes, sending/receiving and encoding/decoding the data over the connections in a language specific way.

The Signalling Layer Interface libraries hide the details of handling the interface with the SPU, convert the protocol messages to/from language specific structures, and make the integration of applications very easy.

Investment Protection

SPU licenses at signalling layer can be shared between different applications/services.

Operation, Administration and Monitoring Interface

JN SPU contains a lightful and powerful custom SSH shell implementation that provides functionality for secure configuration and monitoring.

The configuration and monitoring commands can be invoked using a standard SSH client console. JN SPU provides user access control over SSH based on password or public/private keys.

The configuration and monitoring functionality is based on a management model of the SPU system that represents the configurable and monitorable parameters in a tree view. The custom shell implements commands to view and/or edit the branches or leaves in the tree.

The execution of the commands sent over the OA&M Interface at JN SPU side is rather efficient. Unlike the standard SSH daemon in Linux the OA&M command execution in JN SPU does not require starting a new bash shell process in the operating system on each SSH connection. Instead, JN SPU SSH shell is implemented in Erlang and new SSH connections require starting of a Erlang process, an operation that is extremely light. This efficiency is especially important for handling the monitoring requests sent periodically and, possibly, frequently by monitoring consoles that typically use a pull based monitoring mechanism.

JN SPU is monitored over the OA&M interface using corresponding commands. Normally, the monitored data retrieved by the invocation of show command refer to the dynamic data in the configuration data tree and are sent periodically by some external automated process or monitoring console. Alternatively, for incidental queries, the monitored data can be retrieved manually.

JN SPU is delivered with plugin for Nagios console. When invoked by Nagios process, the plugin establishes a ssh session based on a public/private key pair, executes the corresponding command in JN SPU CLI shell, parses the result and returns the corresponding exit code and service status description lines.

Download JN SPU OA&M Interface datasheet

JN SPU Usage Examples

The usage of JN SPU from Erlang and Python 3 via corresponding language specific SPU Signalling Interface libraries is illustrated below.

Diameter 'Update-Location-Request' and 'Update-Location-Answer' belonging to Diameter S6ad application are included in the examples.

Erlang Example


main([]) ->
    {ok, S1} = gen_tcp:connect({127,0,0,1}, 9001, [{packet,2}
                                                   ,{active, true}]),
    ok = gen_tcp:send(S1, registration(<<"realm1">>)),
    io:format("S1 RCV: ~p~n", [receive_message(S1)]),

    {ok, S2} = gen_tcp:connect({127,0,0,1}, 9001, [{packet,2}
                                                  ,{active, true}]),
    ok = gen_tcp:send(S2, registration(<<"realm2">>)),
    io:format("S2 RCV: ~p~n", [receive_message(S2)]),

    ok = gen_tcp:send(S1, ulr(xxx)),
    {diameter, {request, s6ad, TID1, ULR}} = receive_message(S2),
    io:format("ULR(~p) ~p~n", [binary_to_term(TID1), ULR]),

    ok = gen_tcp:send(S2, ula(TID1)),
    {diameter, {answer, s6ad, OTID1, ULA}} = receive_message(S1),
    io:format("ULA(~p): ~p~n", [OTID1, ULA]),

receive_message(S) ->
        {tcp, S, Message} -> binary_to_term(Message)

registration(Realm) ->
    Registration = [{protocols, [{diameter, [{application, s6ad}
                                            ,{origin, Realm}
    term_to_binary({spu, {user, {register, Registration}}}).

Python 3 Example

import asyncio
import struct
import datetime
import time

from spuapi.transp import conn
from spuapi.prot import term
async def ulrula_task(loop):
    srv_ip = ""
    srv_port1 = "9001"
    srv_port2 = "9001"
    connect_timeout = 4

    conn1 = conn.SPUConnection(srv_ip, srv_port1, loop, connect_timeout)
    await conn1.connect()
    print(" SPU connecttion 1 established")

    conn2 = conn.SPUConnection(srv_ip, srv_port2, loop, connect_timeout)
    await conn2.connect()
    print(" SPU connecttion 2 established")

    apps = ['s6ad']
    await spu_register(b'User1', apps, [b'realm1'], conn1)
    print(" User1 registered")
    await spu_register(b'User2', apps, [b'realm2'], conn2)
    print(" User2 registered")

        await asyncio.sleep(0.5)

        sess_id, tid, ulr_buff = dia_ulr_request(b'1111',
                                                 b'spu.realm1', b'realm1',
        await conn1.send(ulr_buff)
        print(" ULR sent")

        rulr_buff = await conn2.recv(5)

        sess_id, tid_ula, ula_buff = dia_ula_answer(rulr_buff,
                                                    b'spu.realm2', b'realm2')

        await conn2.send(ula_buff)
        print(" ULA sent")

        ula_buff = await conn1.recv(5)
        print(" ULA received")
        ex = term.decode(ula_buff)
        (adiameter, (aanswer, as6ad, tid_rsp, data)) = ex
        assert tid_rsp == tid
    except asyncio.TimeoutError:
        print(" Receive Timeout exception")
        await spu_unregister(conn1)
        print(" User1 unregistered")
        await spu_unregister(conn2)
        print(" User2 unregistered")

def run():
    loop = asyncio.get_event_loop()
        print("\nStart ULR-ULA task")
        task_coro = asyncio.ensure_future(ulrula_task(loop), loop=loop)
        print("Finish ULR-ULA task successfully")
        print("ULR-ULA task error")

if __name__ == "__main__":