== Distributed GSM / Multicast MS Lookup Distributed GSM (D-GSM) allows independent mobile core network stacks to provide voice, SMS and Roaming services to each other, without the need for centralised entities or administration authority, and in a way that is resilient against unstable network links between sites. D-GSM aims at communal networks, where several independent sites, let's call them villages, each have a full mobile core network infrastructure. It elegantly provides ad-hoc service for subscribers moving across villages, and allows villages to dynamically join or leave the cooperative network without the need for configuration changes at other sites. A challenge for linking separate sites is to find the current location of a subscriber. Typically, in mobile networks, a centralized entity keeps track of where to Page for subscribers. Running several fully independent sites with unreliable links between them makes it hard to provide such centralisation. D-GSM finds subscribers by mslookup, a service provided by OsmoHLR, typically using multicast DNS queries. This allows routing Location Updating requests, calls, and SMS to the right site without administrative delay nor the need for a reliable link to a central database. D-GSM is highly resilient against single sites or links becoming temporarily unavailable. Service between still reachable sites simply continues; Service to a disconnected site resumes as soon as it becomes reachable again. This brings an entirely new paradigm to mobile core network infrastructure: as sites become reachable on the IP network and join the common IP multicast group, services between them become available immediately. Basically, the only premise is that IP routing and multicast works across sites, and that each site uses unique IPA names in the GSUP config. This chapter describes how D-GSM and mslookup work, and how to configure sites to use D-GSM, using Osmocom core network infrastructure. === Finding Subscribers: mslookup Clients There are two fundamentally distinct subscriber lookups provided by the mslookup service. ==== Find the Current Location of an MSISDN [[fig_dgsm_connect]] .mslookup for connecting subscribers: Alice is visiting village C; a phone call gets routed directly to her current location independently from her resident village infrastructure [graphviz] ---- digraph G { rankdir=LR subgraph cluster_village_b { label="Village B" ms_bob [label="Bob\n(from village B)",shape=box] pbx_b [label="SIP B"] } subgraph cluster_village_c { label="Village C" ms_alice [label="Alice\n(from village A)",shape=box] msc_c [label="MSC C"] hlr_c [label="HLR C"] sip_c [label="SIP C"] } ms_alice -> msc_c [style=dashed,arrowhead=none] msc_c -> hlr_c [label="attached",style=dashed,arrowhead=none] ms_bob -> pbx_b [label="call Alice"] pbx_b -> hlr_c [label="mslookup by MSISDN",style=dotted,dir=both] pbx_b -> sip_c -> msc_c -> ms_alice [label="call"] } ---- For example, if a subscriber is currently visiting another village, establish a phone call / send SMS towards that village. - To deliver a phone call, a SIP agent integrates an mslookup client to request the SIP service of an MSISDN's current location (example: <>). It receives an IP address and port to send the SIP Invite to. - To deliver an SMS, an ESME integrates an mslookup client to request the SMPP service of an MSISDN's current location (example: <>). The current location of a subscriber may change at any time, and, when moving across locations, a subscriber may suddenly lose reception to the previous location without explicitly detaching. Hence an mslookup request for the current location of an MSISDN may get numerous responses. To find the currently valid location, mslookup includes the age of the subscriber record, i.e. how long ago the subscriber was last reached. The one response with the youngest age reflects the current location. In order to evaluate several responses, mslookup always waits for a fixed amount of time (1 second), and then evaluates the available responses. Services are not limited to SIP and SMPP, arbitrarily named services can be added to the mslookup configuration. .Message sequence for locating an MSISDN to deliver a voice call ["mscgen"] ---- msc { hscale="2"; moms[label="MS,BSS\nvillage A"],momsc[label="MSC,MGW\nvillage A"],mosipcon[label="osmo-sip-connector\nvillage A"],mopbx[label="PBX\nvillage A"],mthlr[label="OsmoHLR\nvillage B"],mtsipcon[label="osmo-sip-connector\nvillage B"],mtmsc[label="MGW,MSC\nvillage B"],mtms[label="RAN,MS\nvillage B"]; moms =>> momsc [label="CC Setup"]; momsc =>> mosipcon [label="MNCC_SETUP_IND"]; mosipcon =>> mopbx [label="SIP INVITE"]; mopbx rbox mopbx [label="dialplan: launch mslookup by MSISDN"]; --- [label="multicast-DNS query to all connected sites"]; ...; mopbx <<= mthlr [label="mDNS response\n(age)"]; mopbx rbox mopbx [label="wait ~ 1s for more mDNS responses"]; ...; mopbx =>> mtsipcon [label="SIP INVITE (MT)"]; mtmsc <<= mtsipcon [label="MNCC_SETUP_REQ"]; mtms <<= mtmsc [label="Paging (CC)"]; moms rbox mtms [label="voice call commences"]; } ---- ==== Find the Home HLR for an IMSI [[fig_dgsm_roaming]] .mslookup for Roaming: Alice visits village B; she can attach to the local mobile network, which proxies HLR administration to her home village. [graphviz] ---- digraph G { rankdir=LR subgraph cluster_village_b { label="Village B" ms_alice [label="Alice\n(from village A)",shape=box] msc_b [label="MSC B"] hlr_b [label="HLR B"] } subgraph cluster_village_a { label="Village A" hlr_alice [label="Alice's home HLR"] } ms_alice -> msc_b -> hlr_b [label="Location\nUpdating"] hlr_b -> hlr_alice [label="mslookup by IMSI",style=dotted,dir=both] hlr_b -> hlr_alice [label="GSUP proxy forwarding"] } ---- For example, when attaching to a local network, a local resident gets serviced directly by the local village's HLR, while a visitor from another village gets serviced by the remote village's HLR (Roaming). A home HLR typically stays the same for a given IMSI. If the home site is reachable, there should be exactly one response to an mslookup request asking for it. The age of such a home-HLR response is always sent as zero. If a response's age is zero, mslookup does not wait for further responses and immediately uses the result. If there were more than one HLR accepting service for an IMSI, the one with the shortest response latency is used. === mslookup Configuration OsmoHLR the main mslookup agent. It provides the responses for both current location services as well as for locating the fixed home-HLR. But naturally, depending on the mslookup request's purpose, different OsmoHLR instances will respond for a given subscriber. - When querying the home HLR, it is always the (typically single) home HLR instance that sends the mslookup response. As soon as it finds the queried IMSI in the local HLR database, an OsmoHLR will respond to home-HLR requests. In <>, Alice's home HLR responds to the Roaming request ("where is the home HLR?"). - When querying the location of an MSISDN, it is always the HLR proxy nearest to the servicing MSC that sends the mslookup response. Even though the home HLR keeps the Location Updating record also for Roaming cases, it will only respond to an mslookup service request if the subscriber has attached at a directly connected MSC. If attached at a remote MSC, that MSC's remote HLR will be the GSUP proxy for the home HLR, and the remote HLR is responsible for responding to service requests. In <>, HLR B is the nearest proxy and will answer all service requests ("where is this MSISDN?"). Alice's home HLR will not answer service requests, because it detects that the servicing MSC is connected via another HLR proxy. [[dgsm_example_config]] ==== Example Here is an osmo-hlr.cfg mslookup configuration example for one site, which is explained in subsequent chapters. hlr gsup bind ip 10.9.8.7 ipa-name hlr-23 mslookup mdns bind server service sip.voice at 10.9.8.7 5060 service smpp.sms at 10.9.8.7 2775 OsmoHLR has both an mslookup server and a client. - The server responds to incoming service and home-HLR requests, when the local HLR is responsible. - The client is used as GSUP proxy to a remote home HLR (found by mslookup upon a locally unknown IMSI). - The client may also be used for forwarding SMS-over-GSUP. The mslookup service can be implemented by various methods. At the time of writing, the only method implemented is mDNS. ==== mDNS The stock mslookup method is mDNS, multicast DNS. It consists of standard DNS encoding according to <> and <>, but sent and received on IP multicast. In the response, standard A and AAAA records return the service's IP address, while additional TXT records provide the service's port number and the MS attach age. TIP: To watch D-GSM mDNS conversations in wireshark, select "udp.port == 4266" (the default mslookup mDNS port number), right click on the packet to "Decode as...", and select "DNS". In OsmoHLR, the mDNS server and client are typically both enabled at the same time: mslookup mdns bind Server and client can also be enabled/disabled individually: mslookup server mdns bind client mdns bind These examples use the default mslookup multicast IP address and port. It is possible to configure custom IP address and port, but beware that the IP address must be from a multicast range, see <>: mslookup mdns bind 239.192.23.42 4266 Domain names generated from mslookup queries (e.g. "sip.voice.123.msisdn") should not collide with IANA permitted domains. Therefore we add the "mdns.osmocom.org" suffix. It can be overridden as follows: mslookup mdns domain-suffix mdns.osmocom.org ==== Server: Site Services The mslookup server requires a list of service addresses provided at the local site, in order to respond to service requests matching locally attached subscribers. mslookup server service sip.voice at 10.9.8.7 5060 service smpp.sms at 10.9.8.7 2775 In this example: - "10.9.8.7 5060" are the IP address and port on which the local site's osmo-sip-connector is bound to receive SIP Invite requests. - "10.9.8.7 2775" are the local site's OsmoMSC SMPP bind address and port. Obviously, these IP addresses must be routable back to this site from all other sites. Using link-local or "ANY" addresses, like 127.0.0.1 or 0.0.0.0, will not work here. Instead, each service config requires a public IP address that all remote requestors are able to reach (not necessarily on the host that osmo-hlr is running on). If a site has more than one MSC, services can also be configured for each MSC individually, keyed by the IPA unit name that each MSC sends on the GSUP link: mslookup server msc ipa-name msc-262-42-0 service sip.voice at 10.11.12.13 5060 service smpp.sms at 10.11.12.13 2775 msc ipa-name msc-901-70-0 service sip.voice at 10.9.8.7 5060 service smpp.sms at 10.9.8.7 2775 Here, "msc-262-42-0" is the IPA name of a local OsmoMSC instance. To configure an OsmoMSC's IPA name on the GSUP link, see osmo-msc.cfg, setting `hlr` / `ipa-name`. For mslookup service responses, only Location Updatings in the Circuit Switched domain are relevant. OsmoHLR does manage IMSIs attaching in the Packet Switched domain (via an SGSN) similarly to Circuit Switched (via an MSC), but mslookup completely ignores the Packet Switched attach status. ==== Server: Own GSUP Address When responding to home-HLR requests, OsmoHLR implicitly by default responds with its locally configured GSUP bind address (setting `hlr` / `gsup` / `bind ip`). If required, an explicit local GSUP address and port can be configured, for example: hlr gsup bind ip 0.0.0.0 ipa-name hlr-23 mslookup server # osmo-hlr's own GSUP address to send in mslookup responses: service gsup.hlr at 10.9.8.7 4222 The gsup.hlr service can only be configured globally (because requests come from arbitrary mDNS clients, before a Location Updating has associated the IMSI with the requesting MSC). ==== Client IPA Naming For reliable GSUP proxy routing to a remote HLR (Roaming), it is important that each GSUP client, i.e. each HLR, MSC and SGSN instance, has a unique IPA name. Example for configuring an OsmoHLR instance's IPA name: hlr gsup ipa-name hlr-23 Here, "hlr-23" is the unique identification of this OsmoHLR instance across all potentially connected D-GSM sites. Furthermore, each MSC and SGSN must have a uniquely distinct IPA name across all sites (here "msc-262-42-0" and "msc-901-70-0" are used as example IPA names for local MSCs). When this OsmoHLR connects to a remote HLR, be it for GSUP proxying or SMS-over-GSUP, it communicates its own IPA name (on GSUP link-up) as well as the IPA name of the requesting client MSC/SGSN (as Source Name in each message) to the remote OsmoHLR GSUP server. These names are used to route GSUP responses back to the respective requesting peer. If two MSCs were accidentally configured with identical names, a problem will occur as soon as both MSCs attempt to attach to the same OsmoHLR (either directly or via GSUP proxying). The MSC that shows up first will work normally, but any duplicate that shows up later will be rejected, since a route for its name already exists. === Queries In URL notation, typical mslookup queries look like: gsup.hlr.123456789.imsi sip.voice.123.msisdn smpp.sms.123.msisdn A query consists of - a service name ("gsup.hlr"), - an id ("123456789"), - the id type ("imsi"). The calling client also defines a timeout to wait for responses. The mslookup ID types are fixed, while service names can be chosen arbitrarily. .mslookup ID types, no other ID types are understood by mslookup [options="header",width="100%",cols="20%,80%"] |=== |ID Type|Description |imsi|An IMSI as existing in an OsmoHLR subscriber database |msisdn|A phone number as configured in an OsmoHLR subscriber database |=== .mslookup service name conventions, arbitrary service names can be added as required [options="header",width="100%",cols="20%,20%,60%"] |=== |Service Name|Protocol|Description |gsup.hlr | GSUP | Home HLR's GSUP server, to handle Location Updating related procedures |sip.voice | SIP | OsmoSIPConnector, to receive a SIP Invite (MT side of a call) |smpp.sms | SMPP | Destination OsmoMSC (or other SMPP server) to deliver an SMS to the recipient |gsup.sms | GSUP | GSUP peer to deliver an SMS to the recipient using SMS-over-GSUP |=== Arbitrarily named services can be added to the mslookup configuration and queried by mslookup clients; as soon as a service name is present in osmo-hlr.cfg, it can be queried from any mslookup client. Service names should consist of a protocol name (like "sip", "gsup", "english") and an intended action/entity (like "voice", "hlr", "greeting"). === Service Client Implementation In principle, arbitrary services could query target addresses via mslookup, leaving it up to any and all kinds of clients to find their respective destination addresses. But of course, mslookup was designed with specific services in mind, namely: - SIP call agents and - SMS delivery (an ESME or SMSC) The following chapters describe examples of setting up a working distributed core network providing SIP voice calls and SMS forwarding across sites. ==== mslookup Library The OsmoHLR provides an mslookup client C library, libosmo-mslookup. Service lookups can be integrated directly in client programs using this library. However, its mDNS implementation requires the libosmocore select() loop, which can be challenging to integrate in practice. An alternative solution is the osmo-mslookup-client tool. [[dgsm_osmo_mslookup_client]] ==== osmo-mslookup-client The mslookup C library is available, but often, a simpler approach for client implementations is desirable: - When querying for a service address, the client is typically interested in the single final best result (youngest age / first responding home HLR). - Voice call and SMS clients typically would block until an mslookup result is known. For example, the FreeSwitch dialplan integration expects a result synchronously, i.e. without waiting for mslookup responses via a select() loop. - Integrating the libosmocore select() loop required for mDNS can break the already existing socket handling in the client program. The osmo-mslookup-client cmdline tool provides a trivial way to synchronously acquire the single result for an mslookup request. The service client can invoke an osmo-mslookup-client process per request and read the result from stdout. Each invocation obviously spawns a separate process and opens a multicast socket for mDNS. For better scalability, osmo-mslookup-client can also be run as a daemon, providing results via a unix domain socket. Using synchronous write() and recv() allows blocking until a result is received without interfering with the client program's select() setup. By itself, osmo-mslookup-client is also helpful as a diagnostic tool: ---- $ osmo-mslookup-client sip.voice.1001.msisdn sip.voice.1001.msisdn ok 10.9.8.7 5060 $ osmo-mslookup-client gsup.hlr.901700000014701.imsi gsup.hlr.901700000014701.imsi ok 10.9.8.7 4222 $ osmo-mslookup-client gsup.hlr.111111.imsi gsup.hlr.111111.imsi not-found $ osmo-mslookup-client gsup.hlr.1001.msisdn sip.voice.1001.msisdn smpp.sms.1001.msisdn foo.1001.msisdn gsup.hlr.1001.msisdn ok 10.9.8.7 4222 foo.1001.msisdn not-found smpp.sms.1001.msisdn ok 10.9.8.7 2775 sip.voice.1001.msisdn ok 10.9.8.7 5060 $ osmo-mslookup-client --csv-headers gsup.hlr.901700000014701.imsi QUERY RESULT V4_IP V4_PORT V6_IP V6_PORT gsup.hlr.901700000014701.imsi ok 10.9.8.7 4222 $ osmo-mslookup-client -f json gsup.hlr.901700000014701.imsi {"query": "gsup.hlr.901700000014701.imsi", "result": "ok", "v4": ["10.9.8.7", "4222"]} ---- For full help including example client invocations in Python, see the output of: osmo-mslookup-client -h ==== SIP Service Client [[dgsm_conf_dialplan]] ===== FreeSwitch dialplan.py The FreeSWITCH PBX software <> offers a Python integration to determine a SIP call recipient by a custom dialplan implementation. An example dialplan implementation for FreeSWITCH that uses D-GSM mslookup is provided in the osmo-hlr source tree under `contrib`, called `freeswitch_dialplan_dgsm.py`. To integrate it with your FREESWITCH setup, add a new `extension` block to your `dialplan/public.xml`: ---- ---- Make sure that the dir containing `freeswitch_dialplan_dgsm.py` is in your `PYTHONPATH` environment variable, and start the server: ---- $ export PYTHONPATH="$PYTHONPATH:/home/user/code/osmo-hlr/contrib/dgsm" $ freeswitch -nf -nonat -nonatmap -nocal -nort -c ---- ==== SMS Service Client [[dgsm_conf_esme_smpp]] ===== SMS via SMPP Port An example ESME using D-GSM mslookup, `esme_dgsm.py`, is provided in the osmo-hlr source tree under `contrib`. It attaches to OsmoMSC's SMPP port to send SMS to recipients determined by mslookup. OsmoMSC should be configured as "smpp-first", so that all SMS routing is determined by mslookup. If configured without smpp-first, OsmoMSC may try to deliver an SMS locally, even though the recipient has recently moved to a different site. An example OsmoMSC configuration to work with esme_dgsm.py: ---- smpp local-tcp-ip 127.0.0.1 2775 system-id test-msc policy closed smpp-first # outgoing to esme_dgsm.py esme OSMPP no alert-notifications password foo default-route # incoming from esme_dgsm.py esme ISMPP no alert-notifications password foo ---- Launch esme_dgsm.py alongside OsmoMSC: ---- ./esme_dgsm.py --src-host 127.0.0.1 ---- esme_dgsm.py will be notified via SMPP for each SMS to be delivered, and will forward them either to a remote recipient, or back to the same OsmoMSC, depending on the mslookup result. If the MSISDN is not reachable (or esme_dgsm.py can't handle the message for other reasons), it returns the RSYSERR code back to OsmoMSC. Note that the esme_dgsm.py is a proof of concept and should not be used in production. It has several limitations, such as not supporting multipart SMS messages. ===== SMS-Over-GSUP The GSUP protocol defines SMS delivery messages. When OsmoMSC is configured to deliver SMS via GSUP, MO SMS are directly forwarded to the HLR, which will determine where to forward the SMS-over-GSUP messages using its mslookup client. FIXME implement this