10. Local Number Porting

10.1. Local LNP Database
10.1.1. LNP Carriers
10.1.2. LNP Numbers
10.1.3. Enabling local LNP support
10.1.4. LNP Routing Procedure
10.1.4.1. Calls to non-authoritative Carriers
10.1.5. Transit Calls using LNP
10.1.6. CSV Format
10.2. External LNP via LNP API
10.2.1. Enabling LNP lookup via API
10.2.2. Redundancy feature
10.2.3. Configuration of Sipwise LNP daemon

The sip:carrier comes with two ways of accomplishing local number porting (LNP). One is populating the integrated LNP database with porting data, and the other is accessing external LNP databases via the Sipwise LNP daemon using the LNP API (PRO/CARRIER only).

10.1. Local LNP Database

The local LNP database provides the possibility to define LNP Carriers (the owners of certain ported numbers or number blocks) and their corresponding LNP Numbers belonging to those carriers. It can be configured on the admin panel in SettingsNumber Porting or via the API. The LNP configuration can be populated individually or via CSV import/export both on the panel and the API.

10.1.1. LNP Carriers

LNP Carriers are defined by an arbitrary Name for proper identification (e.g. British Telecom) and contain a Prefix which can be used as routing prefix in LNP Rewrite Rules and subsequently in Peering Rules to route calls to the proper carriers. The LNP prefix is written to CDRs to identify the selected carrier for post processing and analytics purposes of CDRs. LNP Carrier entries also have an Authoritative flag indicating that the numbers in this block belong to the carrier operating the sip:carrier. This is useful to define your own number blocks, and in case of calls to those numbers reject the calls if the numbers are not assigned to local subscribers (otherwise they would be routed to a peer, which might cause call loops). Finally the Skip Rewrite flag skips executing of LNP Rewrite Rules if no number manipulation is desired for an LNP carrier.

10.1.2. LNP Numbers

LNP Carriers contain one or more LNP Numbers. Those LNP Numbers are defined by a Number entry in E164 format (<cc><ac><sn>) used to match a number against the LNP database. Number matching is performed on a longest match, so you can define number blocks without specifying the full subscriber number (e.g. a called party number 431999123 is going to match an entry 431999 in the LNP Numbers).

For an LNP Numbers entry, an optional Routing Number can be defined. This is useful to translate e.g. premium 900 or toll-free 800 numbers to actual routing numbers. If a Routing Number is defined, the called party number is implicitly replaced by the Routing Number and the call processing is continued with the latter.

An optional Start Date and End Date allows to schedule porting work-flows up-front by populating the LNP database with certain dates, and the entries are only going to become active with those dates. Empty values for start indicate a start date in the past, while empty values for end indicate an end time in the future during processing of a call, allowing to define infinite date ranges. As intervals can overlap, the LNP number record with a start time closest to the current time is selected.

10.1.3. Enabling local LNP support

In order to activate Local LNP during routing, the feature must be activated in config.yml. Set kamailioproxylnpenabled to yes and kamailioproxylnptype to local.

10.1.4. LNP Routing Procedure

10.1.4.1. Calls to non-authoritative Carriers

When a call arrives at the system, the calling and called party numbers are first normalized using the Inbound Rewrite Rules for Caller and Inbound Rewrite Rules for Callee within the rewrite rule set assigned to the calling party (a local subscriber or a peer).

If the called party number is not assigned to a local subscriber, or if the called party is a local subscriber and has the subscriber/domain preference lnp_for_local_sub set, the LNP lookup logic is engaged, otherwise the call proceeds without LNP lookup. The further steps assume that LNP is engaged.

If the call originated from a peer, and the peer preference caller_lnp_lookup is set for this peer, then an LNP lookup is performed using the normalized calling party number. The purpose for that is solely to find the LNP prefix of the calling peer, which is then stored as source_lnp_prefix in the CDR. If the LNP lookup does not return a result (e.g. the calling party number is not populated in the local LNP database), but the peer preference default_lnp_prefix is set for the originating peer, then the value of this preference is stored in source_lnp_prefix of the CDR.

Next, an LNP lookup is performed using the normalized called party number. If no number is found (using a longest match), no further manipulation is performed.

If an LNP number entry is found, and the Routing Number is set, the called party number is replaced by the routing number. Also, if the Authoritative flag is set in the corresponding LNP Carrier, and the called party number is not assigned to a local subscriber, the call is rejected. This ensures that numbers allocated to the system but not assigned to subscribers are dropped instead of routed to a peer.

[Important]

If the system is serving a local subscriber with only the routing number assigned (but not e.g. the premium number mapping to this routing number), the subscriber will not be found and the call will either be rejected if the called party premium number is within an authoritative carrier, or the call will be routed to a peer. This is due to the fact that the subscriber lookup is performed with the dialled number, but not the routing number fetched during LNP. So make sure to assign e.g. the premium number to the local subscriber (optionally in addition to the routing number if necessary using alias numbers) and do not use the LNP routing number mechanism for number mapping to local subscribers.

Next, if the the LNP carrier does not have the Skip Rewriting option set, the LNP Rewrite Rules for Callee are engaged. The rewrite rule set used is the one assigned to the originating peer or subscriber/domain via the rewrite_rule_set preference. The variables available in the match and replace part are, beside the standard variables for rewrite rules:

  • ${callee_lnp_prefix}: The prefix stored in the LNP Carrier
  • ${callee_lnp_basenumber}: The actual number entry causing the match (may be shorter than the called party number due to longest match)

Typically, you would create a rewrite rule to prefix the called party number with the callee_lnp_prefix by matching ^([0-9]+)$ and replacing it by ${callee_lnp_prefix}\1.

Once the LNP processing is completed, the system checks for further preferences to finalize the number manipulation. If the originating local subscriber or peer has the preference lnp_add_npdi set, the Request URI user-part is suffixed with ;npdi. Next, if the preference lnp_to_rn is set, the Request URI user-part is suffixed with ;rn=LNP_ROUTING_NUMBER, where LNP_ROUTING_NUMBER is the Routing Number stored for the number entry in the LNP database, and the originally called number is kept in place. For example, if lnp_to_rn is set and the number 1800123 is called, and this number has a routing number 1555123 in the LNP database, the resulting Request-URI is sip:1800123;rn=1555123@example.org.

Finally, the destination_lnp_prefix in the CDR table is populated either by the prefix defined in the Carrier of the LNP database if a match was found, or by the default_lnp_prefix prefrence of the destination peer or subscriber/domain.

10.1.5. Transit Calls using LNP

If a call originated from a peer and the peer preference force_outbound_calls_to_peer is set to force_nonlocal_lnp (the if callee is not local and is ported selection in the panel), the call is routed back to a peer selected via the peering rules.

This ensures that if a number once belonged to your system and is ported out, but other carriers are still sending calls to you (e.g. selecting you as an anchor network), the affected calls can be routed to the carrier the number got ported to.

10.1.6. CSV Format

The LNP database can be exported to CSV, and in the same format imported back to the system. On import, you can decide whether to drop existing data prior to applying the data from the CSV.

The CSV file format contains the fields in the following order:

carrier_name carrier_prefix number routing_number start end authoritative skip_rewrite

Table 11. LNP CSV Format

Name

Description

Carrier Name

The Name in the LNP Carriers table (string, e.g. My Carrier)

Carrier Prefix

The Prefix in the LNP Carriers table (string, e.g. DD55)

Number

The Number in the LNP Numbers table (E164 number, e.g. 1800666)

Routing Number

The Routing Number in the LNP Numbers table (E164 number or empty, e.g. 1555666)

Start

The Start in the LNP Numbers table (YYYY-MM-DD or empty, e.g. 2016-01-01)

End

The End in the LNP Numbers table (YYYY-MM-DD or empty, e.g. 2016-12-30)

Authoritative

The Authoritative flag in the LNP Carriers table (0 or 1)

Skip Rewrite

The Skip Rewrite flag in the LNP Carriers table (0 or 1)


10.2. External LNP via LNP API

External LNP relies on the Sipwise LNP Daemon (lnpd) which kamailio-proxy is talking to via a defined JSONRPC protocol. The proxy sends the A and B number to lnpd, which in the current release translates it to a SIP Message sent to an external server (typically a Squire SIP-to-INAP gateway. This external gateway is performing an SS7 INAP request to fetch the LNP result, which is passed back as a binary blob in a 3xx response to the lnpd. The lnpd extracts the TCAP body of the response and returns the information back to the proxy.

[Tip]

Sipwise support engineers are advised to have a look at the Wiki page: Sipwise LNP Daemon specifications if they need more details of the communication protocols between lnpd and kamailio-proxy or lnpd and the external gateway.

10.2.1. Enabling LNP lookup via API

In order to activate LNP lookup via API during call routing, the feature must be activated in /etc/ngcp-config/config.yml. Set these parameters:

  • kamailio→proxy→lnp→enabled : yes
  • kamailio→proxy→lnp→type : api
  • lnpd→enabled : yes

There is a possibility to explicitly allow (whitelist) or deny (blacklist) certain number ranges for which an LNP lookup may be done. The relevant configuration parameters are at kamailio→proxy→lnp→lnp_request_whitelist and kamailio→proxy→lnp→lnp_request_blacklist. For each entry in the list a POSIX regex expression may be used, see the following example:

    lnp:
      lnp_request_whitelist:
        - '^9'
        - '^800'
      lnp_request_blacklist:
        - '^1'
        - '^900'
        - '^110'
        - '^112'

Interpretation of the above lists (that are based on numbers represented in national format):

  • whitelist: do LNP lookup for any called number that starts with 9 or 800
  • blacklist: do not perform LNP lookup for any called number that starts with 1, 900, 110 or 112
[Important]

If both whitelist and blacklist are defined, the LNP lookup is only performed when the called number matches any of the whitelist patterns and does not match any of the blacklist patterns.

10.2.2. Redundancy feature

It is possible to set up LNP daemon to provide a kind of redundant service to the Proxy. This means the LNP daemon will send its LNP query to more LNP serving nodes that are predefined in a list. (See Configuration of LNP daemon Section 10.2.3, “Configuration of Sipwise LNP daemon” chapter for details.) The LNP query may happen in 2 ways:

  • round-robin: LNP daemon sends the query to one of the serving nodes then waits for the response for a configurable timeout. If it does not get the response in time, it sends the LNP query to the next serving node.
  • parallel: LNP daemon sends the query to all of the serving nodes then waits for the response, and will accept the first response that it receives.

10.2.3. Configuration of Sipwise LNP daemon

LNP daemon takes its active configuration from /etc/ngcp-lnpd/config.yml file. The file is generated automatically — when a new NGCP configuration is applied (ngcpcfg apply…) — from the main Sipwise NGCP configuration file: /etc/ngcp-config/config.yml and a template: /etc/ngcp-config/template/etc/ngcp-lnpd/config.yml.tt2. System administrators are only expected to modify the lnpd.config section of main configuration file /etc/ngcp-config/config.yml.

A sample LNP daemon configuration file (/etc/ngcp-lnpd/config.yml) looks like:

daemon:
        json-rpc:
                ports:
                        - 54321
                        - 12345
                interfaces:
                        - 127.0.0.1
                        - 192.168.1.90
                        - ::1

        sip:
                port: 5095
                address: 0.0.0.0

        threads: 4
        foreground: false
        pidfile: /tmp/lnpd.pid
        loglevel: 7

instances:
        default:
                module: sigtran
                destination: 192.168.1.99
                from-domain: test.example.com
                headers:
                        - header: INAP-Service-Key
                          value: 2
                reply:
                        tcap: raw-tcap
        redundant:
                module: sigtran
                destinations:
                        - 192.168.1.99
                        - 192.168.1.95
                        - 192.168.1.90
                mechanism: round-robin
                retry-time: 30
                timeout: 5
                from-domain: test.example.com
                headers:
                        - header: INAP-Service-Key
                          value: 2
                reply:
                        tcap: raw-tcap
        parallel:
                module: sigtran
                destinations:
                        - 192.168.1.99
                        - 192.168.1.95
                        - 192.168.1.90
                mechanism: parallel
                retry-time: 30
                timeout: 10
                from-domain: test.example.com
                headers:
                        - header: INAP-Service-Key
                          value: 2
                reply:
                        tcap: raw-tcap
        mock1:
                module: mock-tcap
                numbers:
                        - number: '4311003'
                          routing-number: '4318881003'
                reply:
                        tcap: raw-tcap

The corresponding NGCP main configuration file contains:

    daemon:
      foreground: 'false'
      json-rpc:
        ports:
          - '54321'
          - '12345'
      loglevel: '7'
      sip:
        port: '5095'
      threads: '4'
    instances:
    << These are the same entries as in /etc/ngcp-lnpd/config.yml file >>

Description of configuration parameters in /etc/ngcp-config/config.yml file

  • daemon section:

    • foreground: determines if the LNP daemon runs as foreground or background process
    • json-rpc.ports: port numbers where LNP daemon listens for incoming JSONRPC requests from NGCP Proxy
    • loglevel: how detailed information LNP daemon writes in its log file
    • sip.port: listening port number used for SIP sessions with LNP serving nodes; LNP daemon will listen on first available (shared) IP address that is taken from /etc/ngcp-config/network.yml file
    • threads: number of threads LNP daemon will use internally; this value determines how many requests the daemon can serve in parallel
  • instances section: at least one default instance must be defined here. Others are also useful for providing redundancy, please check redundant and parallel entries above.

    • module: only sigtran is used for normal operations

      [Important]

      The module mock-tcap is only meant for developers. In this case the LNP daemon does not produce a SIP request that it sends to LNP serving nodes, but instead it uses the numbers parameter to match a called number with a routing number. The numbers parameter contains a list of number — routing-number pairs and is used as a database for number lookups. Finally LNP daemon returns the routing number as a response on LNP query.

    • destinations: list of nodes to which LNP daemon sends the LNP query
    • mechanism: either parallel or round-robin, defining the method of redundant queries
    • retry-time: a period of time in seconds while LNP daemon considers an LNP serving node being unreachable after an LNP query timeout
    • timeout: the period of time while LNP daemon waits for a response on an LNP query from one of the LNP serving nodes

      PLEASE NOTE: retry-time and timeout are used with both the parallel and the round-robin redundancy methods

    • from-domain: the domain that will be used in SIP From header when LNP daemon sends the LNP query
    • headers: this is a list of header name — value pairs; these custom headers will be included in SIP request that LNP daemon sends to an LNP serving node
    • reply.tcap: determines the format of reply sent to NGCP Proxy; currently only raw-tcap is supported, which means LNP daemon will not decode the TCAP response it gets from an LNP serving node but it forwards the raw TCAP message body