The sip:provider PRO 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).
![]() | |
The reader may find a generic call flow in General Call Setup description Section 2.1.2.1, “General Call Setup”. |
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 Settings→Number Porting or via the API. The LNP configuration can be populated individually or via CSV import/export both on the panel and the API.
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:provider PRO. 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.
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.
In order to activate Local LNP during routing, the feature must be activated in config.yml. Set kamailio→proxy→lnp→enabled to yes and kamailio→proxy→lnp→type to local.
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.
![]() | |
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.
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.
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) |
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.
![]() | |
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. |
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):
![]() | |
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. |
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 11.2.3, “Configuration of Sipwise LNP daemon” chapter for details.) The LNP query may happen in 2 ways:
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
![]() | |
The module |
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