# &adminguide;

## Overview

A module which provides routing, balancing and blocklisting capabilities.

The module provides routing, balancing and blocklisting capabilities. It reads routing entries from a database source or from a config file at &kamailio; startup. It can use one routing tree (for one carrier), or if needed, for every user a different routing tree (unique for each carrier) for number prefix based routing. It supports several route tree domains, e.g. for fallback routes or different routing rules for VoIP and PSTN targets.

Based on the tree, the module decides which number prefixes are forwarded to which gateway. It can also distribute the traffic by ratio parameters. Furthermore, the requests can be distributed by a hash function to predictable destinations. The hash source is configurable, two different hash functions are available.

This module scales up to more than a few million users, and is able to handle more than several hundred thousand routing table entries. We received reports of some setups that used more than a million routing table entries. It also supports a large number of carriers and domains which can be efficiently looked up in most of the cases (see below for more informations). In load balancing scenarios the usage of the config file mode is recommended, to avoid the additional complexity that the database driven routing creates.

Routing tables can be reloaded and edited (in config file mode) with the RPC interface, the config file is updated according to the changes. This is not implemented for the db interface, because it is easier to do the changes directly on the db. But the reload and dump functions work of course here as well.

Some module functionality is not fully available in the config file mode, as it is not possible to specify all information that can be stored in the database tables in the config file. Further information about these limitations is given in a later sections. For user based routing or LCR you should use the database mode.

In database mode, this module supports names and IDs for the carriers and domains. When using IDs for the routing functions, efficient binary search is used to find the needed data structures. If you are using constant strings as parameter, these will be converted to IDs during the fixup procedure using learner search to find the needed data structures. So from a performance point of view it is better to pass only IDs in the routing functions.

Basically this module could be used as a replacement for the lcr and the dispatcher module, if you have certain flexibility, integration and/or performance requirements that can not be satisfied with these modules. But for smaller installations it probably make more sense to use the lcr and dispatcher module.

Starting with version 3.1 , if you want to use this module in failure routes, it is not needed to callappend_branch() after rewriting the request URI in order to relay the message to the new target. It also supports the usage of database drived failure routing decisions using the carrierfailureroute table.

## Dependencies

### &kamailio; Modules

The following module must be loaded before this module:

- a database module, when a database is used as configuration data source. Only SQL based databases are supported, as this module needs the capability to issue raw queries. It is not possible to use the dbtext module at the moment.

- The tm module, when you want to use the $T_reply_code pseudo-variable in the cr_next_domain function.

## Parameters

### `subscriber_table` (string)

The name of the table containing the subscribers

Default value is subscriber.

#### Set `subscriber_table` parameter

    ...
    modparam("carrierroute", "subscriber_table", "subscriber")
    ...

### `subscriber_user_col` (string)

The name of the column in the subscriber table containing the usernames.

Default value is username.

#### Set `subscriber_user_col` parameter

    ...
    modparam("carrierroute", "subscriber_user_col", "username")
    ...

### `subscriber_domain_col` (string)

The name of the column in the subscriber table containing the domain of the subscriber.

Default value is domain.

#### Set `subscriber_domain_col` parameter

    ...
    modparam("carrierroute", "subscriber_domain_col", "domain")
    ...

### `subscriber_carrier_col` (string)

The name of the column in the subscriber table containing the carrier id of the subscriber.

Default value is cr_preferred_carrier.

#### Set `subscriber_carrier_col` parameter

    ...
    modparam("carrierroute", "subscriber_carrier_col", "cr_preferred_carrier")
    ...

### `config_source` (string)

Specifies whether the module loads its config data from a file or from a database. Possible values are file and db.

Default value is file.

#### Set `config_source` parameter

    ...
    modparam("carrierroute", "config_source", "file")
    ...

### `config_file` (string)

Specifies the path to the config file. The file has to be owned by the user and group used to run &kamailio;.

Default value is /etc/kamailio/carrierroute.conf.

#### Set `config_file` parameter

    ...
    modparam("carrierroute", "config_file", "/etc/kamailio/carrierroute.conf")
    ...

### `default_tree` (string)

The name of the carrier tree used per default (if the current subscriber has no preferred tree)

Default value is default.

#### Set `default_tree` parameter

    ...
    modparam("carrierroute", "default_tree", "default")
    ...

### `use_domain` (int)

When using tree lookup per user, this parameter specifies whether to use the domain part for user matching or not. This parameter is tunable via the ser cfg framework.

Default value is 0.

#### Set `use_domain` parameter

    ...
    modparam("carrierroute", "use_domain", 0)
    ...

### `fallback_default` (int)

This parameter defines the behaviour when using user-based tree lookup. If the user has a non-existing tree set and fallback_default is set to 1, the default tree is used. Otherwise, cr_user_rewrite_uri returns an error. This parameter is tunable via the ser cfg framework.

Default value is 1.

#### Set `fallback_default` parameter

    ...
    modparam("carrierroute", "fallback_default", 1)
    ...

### `fetch_rows` (integer)

The number of the rows to be fetched at once from database when loading the routing data. This value can be used to tune the load time at startup. For 1MB of private memory (default) it should be below 3750. The database driver must support the fetch_result() capability. This parameter is tunable via the ser cfg framework.

Default value is 2000.

#### Set `fetch_rows` parameter

    ...
    modparam("carrierroute", "fetch_rows", 3000)
    ...

### `db_load_description` (integer)

Toggle on/off loading in memory the description column in the carrierroute/carrierfailureroute database tables. This reduces the shared memory used by the module.

Default value is 1.

#### Unset `db_load_description` parameter

    ...
    modparam("carrierroute", "db_load_description", 0)
    ...

### `match_mode` (integer)

The number of individual characters that are used for matching. Valid values are 10 or 128. When you specify 10, only digits will be used for matching, this operation mode is equivalent to the old behaviour. When configured with 128, all standard ascii chars are available for matching. Please be aware that memory requirements for storing the routing tree in shared memory will also increase by a factor of 12.8.

Default value is 10.

#### Set `match_mode` parameter

    ...
    modparam("carrierroute", "match_mode", 10)
    ...

### `avoid_failed_destinations` (integer)

Integer parameter to toggle on/off the possibility that in the failurerouting cases destinations that previously failed are avoided. Possible values are 0 (off), 1 (on). Also see cr_route section.

Default value is 1.

#### Set `avoid_failed_destinations` parameter

    ...
    modparam("carrierroute", "avoid_failed_destinations", 0)
    ...

## Functions

Previous versions of carrierroute had some more function. All the old semantics can be achieved by using the few new functions like this:

    cr_rewrite_uri(domain, hash_source)
    -> cr_route("default", domain, "$rU", "$rU", hash_source)

    cr_rewrite_by_to(domain, hash_source)
    -> cr_route("default", domain, "$tU", "$rU", hash_source)

    cr_rewrite_by_from(domain, hash_source)
    -> cr_route("default", domain, "$fU", "$rU", hash_source)

    cr_user_rewrite_uri(uri, domain)
    -> cr_user_carrier(user, domain, "$avp(tree_avp)")
    -> cr_route("$avp(tree_avp)", domain, "$rU", "$rU", "call_id")

    cr_tree_rewrite_uri(tree, domain)
    -> cr_route(tree, domain, "$rU", "$rU", "call_id")

### `cr_user_carrier(user, domain, dstvar)`

This function loads the carrier and stores it in a config variable. It cannot be used in the config file mode, as it needs a mapping of the given user to a certain carrier. The is drived from a database entry belonging to the user parameter. This mapping must be available in the table that is specified in the subscriber_table variable. This data is not cached in memory, that means for every execution of this function a database query will be done.

Meaning of the parameters is as follows:

- user - Name of the user for the carrier tree lookup. Additional to a string any pseudo-variable could be used as input.

- domain - Name of the routing domain to be used. Additional to a string any pseudo-variable could be used as input.

- dstvar - Name of the writable config variable (e.g., an AVP) where to store the carrier id.

### `cr_route(carrier, domain, prefix_matching, rewrite_user, hash_source, descavp)`

This function searches for the longest match for the user given in prefix_matching with the given domain in the given carrier tree. The Request URI is rewritten using rewrite_user and the given hash source and algorithm. Returns -1 if there is no data found or an empty rewrite host on the longest match is found. On success, it also stores the carrier description in the given AVP (if present). This is useful if you need some additional informations that belongs to each gw, like the destination uri, force socket or any arbitrary info.

Depending on the value of the avoid_failed_destinations module parameter, the function pays special attention to the failurerouting cases, so that any destination that has failed to provide a successful response will not be reused in a subsequent call of this function. This situation can appear when different route domains contain a set of common gateways.

This function is only usable with rewrite_user and prefix_matching containing a valid string. This string needs to be numerical if the match_mode parameter is set to 10. It uses the standard CRC32 algorithm to calculate the hash values.

If flags and masks values are specified in the routing rule, they will be compared by this function to the message flags. Specify a flag and mask value of 0 to match to all possible message flags (this is the default value). If flags and mask are not zero, and no match to the message flags is possible, no routing will be done. The calculation of the hash and the load-balancing is done after the flags matching.

Meaning of the parameters is as follows:

- carrier - The routing tree to be used. It must be string containing either carrier id (nummeric) or carrier name (arbitrary string). It also accepts any pseudo-variable as input.

- domain - Name of the routing domain to be used. it must be string containing either domain id (nummeric) or domain name (arbitrary string). It also accepts any pseudo-variable as input.

- prefix_matching - User name to be used for prefix matching in the routing tree. It also accepts any pseudo-variable as input

- rewrite_user - The user name to be used for applying the rewriting rule. Usually this is the user part of the request URI. It also accepts any pseudo-variable as input

- hash_source - The hash values of the destination set, it must be a contiguous range starting at 1, limited by the configuration parameter max_targets. Possible values for hash_source are: call_id, from_uri, from_user, to_uri, to_user and rand.

- decsavp - AVP where to store the description. This parameter is optional.

### `cr_nofallback_route(carrier, domain, prefix_matching, rewrite_user, hash_source, descavp)`

This function searches for the longest match for the user given in prefix_matching with the given domain in the given carrier tree. The Request URI is rewritten using rewrite_user and the given hash source and algorithm. Returns -1 if there is no data found or an empty rewrite host on the longest match is found. On success it also stores the carrier description in the given AVP (if present). This is useful if you need some additional informations that belongs to each gw, like the destination uri, force socket or any arbitrary info.

This function is only usable with rewrite_user and prefix_matching containing a valid string. This string needs to be numerical if the match_mode parameter is set to 10.

It uses the standard CRC32 algorithm to calculate the hash values. In contrast to the normal cr_route function, the backup rules of (now obsolete) cr_prime_route is used. This means none of the configured probabilities will be used, only a fixed hash distribution is used. This makes sense to distribute incoming register requests e.g. to a bunch of registrar servers. If one of the hash targets is not available and backup rule is configured, the function will return -1.

Meaning of the parameters is as follows:

- carrier - The routing tree to be used. It must be string containing either carrier id (nummeric) or carrier name (arbitrary string). It also accepts any pseudo-variable as input.

- domain - Name of the routing domain to be used. it must be string containing either domain id (nummeric) or domain name (arbitrary string). It also accepts any pseudo-variable as input

- prefix_matching - User name to be used for prefix matching in the routing tree. It also accepts any pseudo-variable as input

- rewrite_user - The user name to be used for applying the rewriting rule. Usually this is the user part of the request URI. It also accepts any pseudo-variable as input

- hash_source - The hash values of the destination set, it must be a contiguous range starting at 1, limited by the configuration parameter max_targets. Possible values for hash_source are: call_id, from_uri, from_user, to_uri, to_user and rand.

- decsavp - AVP where to store the description. This parameter is optional.

### `cr_next_domain(carrier, domain, prefix_matching, host, reply_code, dstavp)`

This function searches for the longest match for the user given in prefix_matching with the given domain in the given carrier failure tree. It tries to find a next domain matching the given host, reply_code and the message flags. The matching is done in this order: host then reply_code and then flags. The more wildcards in reply_code and the more bits used in flags, the lower the priority will be. Returns -1, if there is no data found or if the next_domain on the longest match is empty. Otherwise the next domain is stored in the given variable.

This function is only usable if rewrite_user and prefix_matching contains a valid string. This string must be numerical if the match_mode parameter is set to 10.

Meaning of the parameters is as follows:

- carrier - The routing tree to be used. It must be string containing either carrier id (nummeric) or carrier name (arbitrary string). It also accepts any pseudo-variable as input.

- domain - Name of the routing domain to be used. it must be string containing either domain id (nummeric) or domain name (arbitrary string). It also accepts any pseudo-variable as input.

- prefix_matching - User name to be used for prefix matching in the routing tree. It also accepts any pseudo-variable as input.

- host - The host name to be used for failure route rule matching. Usually this is the last tried routing destination stored in an avp by cr_route. It also accepts any pseudo-variable as input

- reply_code - The reply code to be used for failure route rule matching. It also accepts any pseudo-variable as input

- dstavp - Name of the AVP where to store the next routing domain.

## Configuration examples

### Configuration example - Routing to default tree

    ...
    route {
        # route calls based on hash over callid
        # choose route domain 0 of the default carrier

        if(!cr_route("default", "0", "$rU", "$rU", "call_id")){
            sl_send_reply("403", "Not allowed");
        } else {
            # In case of failure, re-route the request
            t_on_failure("1");
            # Relay the request to the gateway
            t_relay();
        }
    }

    failure_route[1] {
        revert_uri();
        # In case of failure, send it to an alternative route:
        if (t_check_status("408|5[0-9][0-9]")) {
        #choose route domain 1 of the default carrier
        if(!cr_route("default", "1", "$rU", "$rU", "call_id")){
                t_reply("403", "Not allowed");
            } else {
                t_on_failure("2");
                t_relay();
            }
        }
    }

    failure_route[2] {
        # further processing
    }

### Configuration example - Routing to user tree

    ...
    route[1] {
        cr_user_carrier("$fU", "$fd", "$avp(s:carrier)");

        # just an example domain
        $avp(s:domain)="start";
        if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", "$rU", "$rU",
                "call_id")) {
            xlog("L_ERR", "cr_route failed\n");
            exit;
        }
        # if you store also the port as part of the rewrite host,
        # otherwise you can just use $rd later
        $avp(s:host)= $rd+":"+$rp;
        t_on_failure("1");
            if (!t_relay()) {
                sl_reply_error();
        };
    }

    failure_route[1] {
        revert_uri();
        if (!cr_next_domain("$avp(s:carrier)", "$avp(s:domain)", "$rU",
                "$avp(s:host)", "$T_reply_code", "$avp(s:domain)")) {
            xlog("L_ERR", "cr_next_domain failed\n");
            exit;
        }
        if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", "$rU", "$rU",
                "call_id")) {
            xlog("L_ERR", "cr_route failed\n");
            exit;
        }
        $avp(s:host)= $rd+":"+$rp;
        t_on_failure("1");
        if (!t_relay()) {
            xlog("L_ERR", "t_relay failed\n");
            exit;
        };
    }
    ...

### Configuration example - module configuration

The following config file specifies within the default carrier two domains, each with a prefix that contains two hosts. It is not possible to specify another carrier if you use the config file as data source.

All traffic will be equally distributed between the hosts, both are active. The hash algorithm will working over the [1,2] set, messages hashed to one will go to the first host, the other to the second one. Don't use a hash index value of zero. If you omit the hash completely, the module gives them an autogenerated value, starting from one.

Use the NULL prefix to specify an empty prefix in the config file. Please note that the prefix is matched against the request URI (or to URI), if they did not contain a valid (numerical) URI, no match is possible. So for load-balancing purposes e.g. for your registrars, you should use an empty prefix.

    ...
    domain proxy {
       prefix 49 {
         max_targets = 2
          target proxy1.localdomain {
             prob = 0.500000
             hash_index = 1
             status = 1
             comment = "test target 1"
          }
          target proxy2.localdomain {
             prob = 0.500000
             hash_index = 2
             status = 1
             comment = "test target 2"
          }
       }
    }

    domain register {
       prefix NULL {
         max_targets = 2
          target register1.localdomain {
             prob = 0.500000
             hash_index = 1
             status = 1
             comment = "test target 1"
          }
          target register2.localdomain {
             prob = 0.500000
             hash_index = 2
             status = 1
             comment = "test target 2"
          }
       }
    }
    ...

## Installation and Running

### Database setup

Before running &kamailio; with carrierroute, you have to set up the database table where the module will store the routing data. For that, if the table was not created by the installation script or you choose to install everything by yourself you can use the carrierroute-create.sql SQL script in the database directories in the kamailio/scripts folder as template. Database and table name can be set with module parameters so they can be changed, but the name of the columns must be as they are in the SQL script. You can also find the complete database documentation on the project webpage, &kamailiodbdocs;. The flags and mask columns have the same function as in the carrierfailureroute table. A zero value in the flags and mask column means that any message flags will match this rule.

For a minimal configuration either use the config file given above, or insert some data into the tables of the module.

### Database examples

#### Example database content - carrierroute table

    ...
    +----+---------+--------+-------------+-------+------+---------------+
    | id | carrier | domain | scan_prefix | flags | prob | rewrite_host  |
    +----+---------+--------+-------------+-------+------+---------------+
    | 1  |       1 |      1 | 49          |     0 |  0.5 | de-1.carrier1 |
    | 2  |       1 |      1 | 49          |     0 |  0.5 | de-2.carrier1 |
    | 3  |       1 |      1 | 49          |    16 |    1 | de-3.carrier1 |
    | 4  |       1 |      1 |             |     0 |    1 | gw.carrier1-1 |
    | 5  |       1 |      2 | 49          |     0 |    1 | gw.carrier1-1 |
    | 6  |       1 |      3 |             |     0 |    1 | gw.carrier1-2 |
    | 7  |       1 |      4 |             |     0 |    1 | gw.carrier1-3 |
    | 8  |       2 |      1 | 49          |     0 |  0.5 | de-1.carrier2 |
    | 9  |       2 |      1 | 49          |     0 |  0.5 | de-2.carrier2 |
    | 10 |       2 |      1 |             |     0 |    1 | gw.carrier2   |
    | 11 |       2 |      2 | 49          |     0 |    1 | gw.carrier2   |
    | 12 |       3 |      8 | 49          |     0 |    1 | de-gw.default |
    | 13 |       3 |      8 |             |     0 |    1 | gw.default    |
    +----+---------+--------+-------------+-------+------+---------------+
    ...

This table contains three routes to two gateways for the 49 prefix, and a default route for other prefixes over carrier 2 and carrier 1. The gateways for the default carrier will be used for functions that don't support the user specific carrier lookup. The routing rules for carrier 1 and carrier 2 for the 49 prefix contains an additional rule with the domain 2, that can be used for example as fallback if the gateways in domain 1 are not reachable. Two more fallback rules (domain 3 and 4) for carrier 1 are also supplied to support the functionality of the carrierfailureroute table example that is provided in the next section.

This table provides also a carrier 1 routing rule for the 49 prefix, that is only chosen if some message flags are set. If this flags are not set, the other two rules are used. The strip, mask and comment columns are omitted for brevity.

#### Example database content - simple carrierfailureroute table

    ...
    +----+---------+--------+---------------+------------+-------------+
    | id | carrier | domain | host_name     | reply_code | next_domain |
    +----+---------+--------+---------------+------------+-------------+
    |  1 |       1 | 1      | gw.carrier1-2 | ...        | 3           |
    |  2 |       1 | 1      | gw.carrier1-3 | ...        | 2           |
    +----+---------+--------+---------------+------------+-------------+
    ...

This table contains two failure routes for the gw.carrier1-1 and -2 gateways. For any (failure) reply code the respective next domain is chosen. After that no more failure routes are available, an error will be returned from the cr_next_domain function. Not all table columns are shown here for brevity.

For each failure route domain and carrier that is added to the carrierfailureroute table there must be at least one corresponding entry in the carrierroute table, otherwise the module will not load the routing data.

#### Example database content - more complex carrierfailureroute table

    ...
    +----+---------+-----------+------------+--------+-----+-------------+
    | id | domain  | host_name | reply_code | flags | mask | next_domain |
    +----+---------+-----------+------------+-------+------+-------------+
    |  1 |      99 |           | 408        |    16 |   16 |             |
    |  2 |      99 | gw1       | 404        |     0 |    0 | 100         |
    |  3 |      99 | gw2       | 50.        |     0 |    0 | 100         |
    |  4 |      99 |           | 404        |  2048 | 2112 | 101         |
    +----+---------+-----------+------------+-------+------+-------------+
    ...

This table contains four failure routes that shows the usage of more advanced features. The first route matches to a 408, and to some flag for example that indicates that ringing has happened. If this flag is set, there will be no further forwarding, because next_domain is empty. In the second and third routes are certain gateway errors matched, if this errors have occurred, then the next domain will be chosen. Note that the reply_code must be 3 characters wide, and only the "." character is accepted as wildcard. The last route does forwarding according some flags, e.g. the customer came from a certain carrier, and has call-forwarding deactivated. In order to use the routing that is specified above, a matching carrierroute table must be provided, that holds domain entries for this routing rules. Not all table columns are shown here for brevity.

#### Example database content - carrier_name table

    ...
    +----+----------+
    | id | carrier  |
    +----+----------+
    |  1 | carrier1 |
    |  2 | carrier2 |
    |  3 | default  |
    +----+----------+
    ...

This table contains the mapping of the carrier id to actual names.

#### Example database content - domain_name table

    ...
    +----+----------+
    | id | domain   |
    +----+----------+
    |  1 | domain1  |
    |  2 | domain2  |
    |  3 | domain3  |
    +----+----------+
    ...

This table contains the mapping of the domain id to actual names.

### User specific routing

For a functional routing the cr_preferred_carrier column must be added to the subscriber table (or to the table and column that you specified as module parameter) to choose the actual carrier for the users.

#### Necessary extensions for the user table

Suggested changes:

    ...
    ALTER TABLE subscriber ADD cr_preferred_carrier int(10) default NULL;
    ...