Least Cost Routing Module
Juha Heinanen
Edited by
Juha Heinanen
Copyright � 2005 Juha Heinanen
_________________________________________________________
Table of Contents
1. User's Guide
1.1. Overview
1.2. Dependencies
1.3. Exported Parameters
1.4. Exported Functions
1.5. FIFO Commands
1.6. Known Limitations
2. TODO
_________________________________________________________
Chapter 1. User's Guide
1.1. Overview
Least cost routing (LCR) module implements two related capabilities:
(1) sequential forwarding of a request to one or more gateways
(functions load_gws and next_gw),
(2) sequential forwarding to contacts if they don't share the
the same qvalue (functions load_contacts and next_contacts).
Gateway selection is based on caller's RPID URI (if available in
caller's RPID AVP after authentication) or From URI and user part of
Request-URI (telephone number). Gateway patterns matching RPID or
From URI and telephone number are ordered for forwarding purpose (1)
according to longest user part match, (2) according to priority, and
(3) randomly.
Each gateway belongs to a gateway group either alone or among other
gateways. All gateways in a group share the same priority.
Gateway and routing information is kept in two tables: gw and lcr.
When a gateway is selected, Request-URI is rewritten with information
from gw table: URI scheme, prefix, IP address, port, and transport
protocol. Valid URI scheme values are NULL = sip, 1 = sip and 2 =
sips. Prefix is appended in front of Request-URI user part.
Currently valid transport protocol values are NULL = none, 1 = udp, 2
= tcp, and 3 = tls.
Table lcr contains prefix of user part of Request-URI, From URI,
gateway group id, and priority. From URI can contain special
characters % and _ matching any number of any characters and any one
character, respectively.
In addition to gw and lcr tables there is third table gw_grp that is
used for administrative purposes only to associate names with gateway
group ids.
_________________________________________________________
1.2. Dependencies
The module depends on the following modules (in the other
words the listed modules must be loaded before this module):
* tm module
* mysql module
_________________________________________________________
1.3. Exported Parameters
LCR module exports the following database related parameters that
have usual purpose:
* db_url (default system default)
* gw_table (default "gw")
* gw_name_column (default "gw_name")
* ip_addr_column (default "ip_addr")
* port_column (default "port")
* uri_scheme_column (default "uri_scheme")
* transport_column (default "transport")
* grp_id_column (default "grp_id")
* lcr_table (default "lcr")
* prefix_column (default "prefix")
* from_uri_column (default "from_uri")
* priority_column (default "priority")
In addition there are parameters that can be used to override names
of the AVPs used by LCR module:
* gw_uri_avp (default "1400")
* contact_avp (default "1401")
* fr_inv_timer_avp (default "fr_inv_timer_avp")
* rpid_avp (default "rpid")
If string value of an AVP parameter contains only digits, the name of
the AVP is int value of the string.
Finally, the parameters used by sequential forwarding:
* fr_inv_timer (default 90)
* fr_inv_timer_next (default 30)
* fr_inv_timer_param (default "")
* fr_inv_timer_next_param (default "")
Function next_contacts() sets tm fr_inv_timer to fr_inv_timer_next
value if, after next contacts, there are still lower qvalue
contacts available, and to fr_inv_timer value if next contacts are
the last ones left. fr_inv_timer_param can define an AVP
overwriting fr_inv_timer value, and similarly, AVP defined by
fr_inv_timer_next_param can overwrite fr_inv_timer_next value.
_________________________________________________________
1.4. Exported Functions
1.4.1. load_gws()
Loads URIs of gateways matching RPID AVP (if available) or From URI
and user part of Request-URI to gw_uri_avp AVPs. Returns 1 or -1
depending on success.
Example:
if (!load_gws()) {
sl_send_reply("500", "Server Internal Error - Cannot load gateways");
break;
};
1.4.2. next_gw()
If called from a route block, replaces Request-URI by the first
gw_uri_avp AVP value and destroys that AVP.
If called from a failure route block, appends a new branch to request,
whose Request-URI is the first gw_uri_avp AVP value, and destroys that
AVP.
Returns 1 on success and -1 if there were no gateways left or if an
error occurred (see syslog).
Must be preceded by successful load_gws() call.
Example from route block:
if (!next_gw()) {
sl_send_reply("503", "Service not available - No gateways");
break;
};
Example from failure route block:
if (!next_gw()) {
t_reply("503", "Service not available - No more gateways");
break;
};
1.4.3. from_gw()
Checks if request came from IP address of a gateway.
Example:
if (from_gw()) {
...
break;
};
1.4.4. to_gw()
Checks if in-dialog request goes to a gateway.
Example:
if (to_gw()) {
...
break;
};
1.4.5. load_contacts()
Loads contacts in destination set in increasing qvalue order as
values of lcr_contact AVP. If all contacts in the destination set
have the same qvalue, load_contacts() does not do anything thus
minimizing performance impact of sequential forking capability when
it is not needed. Returns 1 if loading of contacts succeeded or
there was nothing to do. Returns -1 on error (see syslog).
Example:
if (!load_contacts()) {
sl_send_reply("500", "Server Internal Error - Cannot load contacts");
break;
};
1.4.6. next_contacts()
If called from a route block, replaces Request-URI with the first
lcr_contact AVP value, adds the remaining lcr_contact AVP values with
the same qvalue as branches, and destroys those AVPs. It does
nothing if there are no lcr_contact AVPs. Returns 1 if there were no
errors and -1 if an error occurred (see syslog).
If called from a failure route block, adds the first lcr_contact AVP
value and all following lcr_contact AVP values with the same qvalue
as new branches to request and destroys those AVPs. Returns 1 if new
branches were successfully added and -1 on error (see syslog) or if
there were no more lcr_contact AVPs.
Must be preceded by successful load_contacts() call.
Example from route block:
if (!next_contacts()) {
sl_send_reply("500", "Server Internal Error");
break;
} else {
t_relay();
};
Example from failure route block:
if (next_contacts()) {
t_relay();
};
1.5. FIFO Commands
1.5.1. lcr_reload
Causes lcr module to re-read the contents of gateway table
into memory.
1.5.2. lcr_dump
Causes lcr module to dump the contents of its in-memory gateway
table.
1.6. Known Limitations
There is an unlikely race condition on lcr reload. If a process uses
in memory gw table, which is reloaded at the same time twice through
FIFO, the second reload will delete the original table still in use
by the process.
_________________________________________________________
2.0. TODO
Function load_gws() currently makes an SQL query for the matching
gateways. In order to avoid the query, also lcr table should be
read into memory and the corresponding query should be rewritten in
C.