carrierroute

Jonas Appel

   1&1 Internet AG

Henning Westerholt

   1&1 Internet AG

   Copyright © 2007 1&1 Internet AG
     __________________________________________________________

   Table of Contents
   1. User's Guide

        1.1. Overview
        1.2. Dependencies

              1.2.1. OpenSER Modules
              1.2.2. External Libraries or Applications

        1.3. Exported Parameters

              1.3.1. db_url (string)
              1.3.2. db_table (string)
              1.3.3. id_column (string)
              1.3.4. carrier_column (string)
              1.3.5. scan_prefix_column (string)
              1.3.6. domain_column (string)
              1.3.7. prob_column (string)
              1.3.8. rewrite_host_column (string)
              1.3.9. strip_column (string)
              1.3.10. comment_column (string)
              1.3.11. carrier_table (string)
              1.3.12. rewrite_prefix_column (string)
              1.3.13. rewrite_suffix_column (string)
              1.3.14. carrier_id_col (string)
              1.3.15. carrier_name_col (string)
              1.3.16. subscriber_table (string)
              1.3.17. subscriber_user_col (string)
              1.3.18. subscriber_domain_col (string)
              1.3.19. subscriber_carrier_col (string)
              1.3.20. config_source (string)
              1.3.21. config_file (string)
              1.3.22. default_tree (string)
              1.3.23. use_domain (int)
              1.3.24. fallback_default (int)

        1.4. Exported Functions

              1.4.1. cr_rewrite_uri (string domain, int
                      hash_source)

              1.4.2. cr_prime_balance_uri (string domain, int
                      hash_source)

              1.4.3. cr_rewrite_by_to (string domain, int
                      hash_source)

              1.4.4. cr_prime_balance_by_to (string domain, int
                      hash_source)

              1.4.5. cr_prime_balance_by_from (string domain, int
                      hash_source)

              1.4.6. cr_user_rewrite_uri (string uri, string
                      domain)

              1.4.7. cr_tree_rewrite_uri (string tree, string
                      domain)

        1.5. MI Commands

              1.5.1. cr_reload_routes
              1.5.2. cr_dump_routes
              1.5.3. cr_replace_host
              1.5.4. cr_deactivate_host
              1.5.5. cr_activate_host
              1.5.6. cr_add_host
              1.5.7. cr_delete_host

        1.6. Examples
        1.7. Installation & Running

              1.7.1. Database setup

   2. Developer's Guide
   3. Frequently Asked Questions

   List of Examples
   1-1. Set db_url parameter
   1-2. Set db_table parameter
   1-3. Set id_column parameter
   1-4. Set carrier_column parameter
   1-5. Set scan_prefix_column parameter
   1-6. Set domain_column parameter
   1-7. Set prob_column parameter
   1-8. Set rewrite_host_column parameter
   1-9. Set strip_column parameter
   1-10. Set comment_column parameter
   1-11. Set carrier_table parameter
   1-12. Set rewrite_prefix_column parameter
   1-13. Set rewrite_suffix_column parameter
   1-14. Set id_col parameter
   1-15. Set carrier_name_col parameter
   1-16. Set subscriber_table parameter
   1-17. Set subscriber_user_col parameter
   1-18. Set subscriber_domain_col parameter
   1-19. Set subscriber_carrier_col parameter
   1-20. Set config_source parameter
   1-21. Set config_file parameter
   1-22. Set default_tree parameter
   1-23. Set use_domain parameter
   1-24. Set fallback_default parameter
   1-25. cr_replace_host usage
   1-26. cr_deactivate_host usage
   1-27. cr_activate_host usage
   1-28. cr_add_host usage
   1-29. cr_delete_host usage
   1-30. Configuration example - OpenSER script
   1-31. Configuration example - module configuration
   1-32. Example database content - carrierroute table
   1-33. Example database content - route_tree table
   1-34. Necessary extensions for the user table
     __________________________________________________________

Chapter 1. User's Guide

1.1. Overview

   A module which provides routing, balancing and blacklisting
   capabilities.

   The module provides routing, balancing and blacklisting
   capabilities. It reads routing entries from a database source
   or from a config file at OpenSER startup. It can uses 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 failback 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 funcion to predictable destinations. The
   hash source is configurable, two different hash functions are
   available.

   This modules scales up to more than a few million users, and is
   able to handle more than several hundred thousand routing table
   entries. It should be able to handle more, but this is not that
   much tested at the moment. In load balancing scenarios the
   usage of the config file mode is recommended, to avoid the
   additional complexity that the database driven routing creates.
   Please note: although the routing tree is stored in shared
   memory, for the initial loading from the database on startup
   private memory is allocated. Thus you'll probably need to
   increase the private memory pool size. For 40.000 routing rules
   a "PKG_MEM_POOL_SIZE" of 10 MB is sufficient.

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

   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 later
   sections. For user based routing or LCR you should use the
   database mode.

   Basically this module could be used as an replacement for the
   lcr and the dispatcher module, if you have certain performance,
   flexibility and/or integration requirements that these modules
   don't handle properly. But for small installations it probably
   make more sense to use the lcr and dispatcher module.

   If you want to use this module in failure routes, then you need
   to call "append_branch()" after rewriting the request URI in
   order to relay the message to the new target.
     __________________________________________________________

1.2. Dependencies

1.2.1. OpenSER 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. Its
       not possible to use the dbtext or db_berkeley module at the
       moment.
     __________________________________________________________

1.2.2. External Libraries or Applications

   The following libraries or applications must be installed
   before running OpenSER with this module loaded:

     * libconfuse, a configuration file parser library.
     __________________________________________________________

1.3. Exported Parameters

1.3.1. db_url (string)

   Url to the database containing the routing data.

   Default value is
   "mysql://openserro:openserro@localhost/openser".

   Example 1-1. Set db_url parameter
...
modparam("carrierroute", "db_url", "dbdriver://username:password@dbhost/
dbname")
...
     __________________________________________________________

1.3.2. db_table (string)

   Name of the table where the routing data is stored.

   Default value is "carrierroute".

   Example 1-2. Set db_table parameter
...
modparam("carrierroute", "db_table", "carrierroute")
...
     __________________________________________________________

1.3.3. id_column (string)

   Name of the column containing the id identifier.

   Default value is "id".

   Example 1-3. Set id_column parameter
...
modparam("carrierroute", "id_column", "id")
...
     __________________________________________________________

1.3.4. carrier_column (string)

   Name of the column containing the carrier id.

   Default value is "carrier".

   Example 1-4. Set carrier_column parameter
...
modparam("carrierroute", "carrier_column", "carrier")
...
     __________________________________________________________

1.3.5. scan_prefix_column (string)

   Name of column containing the scan prefixes. Scan prexies
   define the matching portion of a phone number, e.g. we have the
   scan prefixes 49721 and 49, the called number is 49721913740,
   it matches 49721, because the longest match is taken. If no
   prefix matches, the number is not routed. To prevent this, an
   empty prefix value of NULL could be added.

   Default value is "scan_prefix".

   Example 1-5. Set scan_prefix_column parameter
...
modparam("carrierroute", "scan_prefix_column", "scan_prefix")
...
     __________________________________________________________

1.3.6. domain_column (string)

   Name of column containing the rule domain. You can define
   several routing domains to have different routing rules. Maybe
   you use domain 0 for normal routing and domain 1 if domain 0
   failed.

   Default value is "domain".

   Example 1-6. Set domain_column parameter
...
modparam("carrierroute", "domain_column", "domain")
...
     __________________________________________________________

1.3.7. prob_column (string)

   Name of column containing probability. The probability value is
   used to distribute the traffic between several gateways. Let's
   say 70 % of the traffic shall be routed to gateway A, the other
   30 % shall be routed to gateway B, we define a rule for gateway
   A with a prob value of 0.7 and a rule for gateway B with a prob
   value of 0.3.

   If all probabilities for a given prefix, tree and domain don't
   add to 100%, the prefix values will be adjusted according the
   given prob values. E.g. if three hosts with prob values of 0.5,
   0.5 and 0.4 are defined, the resulting probabilities are
   35.714, 35.714 and 28.571%. But its better to choose meaningful
   values in the first place because of clarity.

   Default value is "prob".

   Example 1-7. Set prob_column parameter
...
modparam("carrierroute", "prob_column", "prob")
...
     __________________________________________________________

1.3.8. rewrite_host_column (string)

   Name of column containing rewrite host value. An empty field
   represents a blacklist entry, anything else is put as domain
   part into the Request URI of the SIP message.

   Default value is "rewrite_host".

   Example 1-8. Set rewrite_host_column parameter
...
modparam("carrierroute", "rewrite_host_column", "rewrite_host")
...
     __________________________________________________________

1.3.9. strip_column (string)

   Name of the column containing the number of digits to be
   stripped of the userpart of an URI before prepending
   rewrite_prefix.

   Default value is "strip".

   Example 1-9. Set strip_column parameter
...
modparam("carrierroute", "strip_column", "strip")
...
     __________________________________________________________

1.3.10. comment_column (string)

   Name of the column containing an optional comment (useful in
   large routing tables) The comment is also displayed by the fifo
   cmd "cr_dump_routes".

   Default value is "comment".

   Example 1-10. Set comment_column parameter
...
modparam("carrierroute", "comment_column", "comment")
...
     __________________________________________________________

1.3.11. carrier_table (string)

   The name of the table containing the existing carriers,
   consisting of the ids and corresponding names.

   Default value is "route_tree".

   Example 1-11. Set carrier_table parameter
...
modparam("carrierroute", "carrier_table", "route_tree")
...
     __________________________________________________________

1.3.12. rewrite_prefix_column (string)

   Name of column containing rewrite prefixes. Here you can define
   a rewrite prefix for the localpart of the SIP URI.

   Default value is "rewrite_prefix".

   Example 1-12. Set rewrite_prefix_column parameter
...
modparam("carrierroute", "rewrite_prefix_column", "rewrite_prefix")
...
     __________________________________________________________

1.3.13. rewrite_suffix_column (string)

   Name of column containing rewrite suffixes. Here you can define
   a rewrite suffix for the localpart of the SIP URI.

   Default value is "rewrite_suffix".

   Example 1-13. Set rewrite_suffix_column parameter
                            ...
                            modparam("carrierroute", "rewrite_suffix_col
umn", "rewrite_suffix")
                            ...
     __________________________________________________________

1.3.14. carrier_id_col (string)

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

   Default value is "id".

   Example 1-14. Set id_col parameter
...
modparam("carrierroute", "carrier_id_col", "id")
...
     __________________________________________________________

1.3.15. carrier_name_col (string)

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

   Default value is "carrier".

   Example 1-15. Set carrier_name_col parameter
...
modparam("carrierroute", "carrier_name_col", "carrier")
...
     __________________________________________________________

1.3.16. subscriber_table (string)

   The name of the table containing the subscribers

   Default value is "subscriber".

   Example 1-16. Set subscriber_table parameter
...
modparam("carrierroute", "subscriber_table", "subscriber")
...
     __________________________________________________________

1.3.17. subscriber_user_col (string)

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

   Default value is "username".

   Example 1-17. Set subscriber_user_col parameter
...
modparam("carrierroute", "subscriber_user_col", "username")
...
     __________________________________________________________

1.3.18. subscriber_domain_col (string)

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

   Default value is "domain".

   Example 1-18. Set subscriber_domain_col parameter
...
modparam("carrierroute", "subscriber_domain_col", "domain")
...
     __________________________________________________________

1.3.19. 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".

   Example 1-19. Set subscriber_carrier_col parameter
...
modparam("carrierroute", "subscriber_carrier_col", "cr_preferred_carrier
")
...
     __________________________________________________________

1.3.20. config_source (string)

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

   Default value is "file".

   Example 1-20. Set config_source parameter
...
modparam("carrierroute", "config_source", "file")
...
     __________________________________________________________

1.3.21. config_file (string)

   Specifies the path to the config file.

   Default value is "/etc/openser/carrierroute.conf".

   Example 1-21. Set config_file parameter
...
modparam("carrierroute", "config_file", "/etc/openser/carrierroute.conf"
)
...
     __________________________________________________________

1.3.22. default_tree (string)

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

   Default value is "default".

   Example 1-22. Set default_tree parameter
...
modparam("carrierroute", "default_tree", "default")
...
     __________________________________________________________

1.3.23. use_domain (int)

   When using tree lookup per user, this parameter specifies
   whether to use the domain part for user matching or not.

   Default value is "0".

   Example 1-23. Set use_domain parameter
...
modparam("carrierroute", "use_domain", 0)
...
     __________________________________________________________

1.3.24. 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.

   Default value is "1".

   Example 1-24. Set fallback_default parameter
...
modparam("carrierroute", "fallback_default", 1)
...
     __________________________________________________________

1.4. Exported Functions

   All functions needs a string value to specify a certain tree
   domain or tree. Its further necessary to specify source of the
   hashing algorithm. If this parameter is ommited like in the
   cr_user_rewrite_uri and cr_tree_rewrite_uri functions, a
   default hash source, the call id, is choosen.
     __________________________________________________________

1.4.1. cr_rewrite_uri (string domain, int hash_source)

   This function searches for the longest match for the Request
   URI at the given domain in the default tree and rewrites the
   Request URI. Returns -1 if there is no data found or an empty
   rewrite host on the longest match is found. This function is
   only usable with requests that contains a valid numerical
   request URI, e.g. INVITEs.

   Meaning of the parameters is as follows:

     * domain - Name of the routing domain to be used.
     * hash_source - The hash values of the destination set 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 and
       to_user.
     __________________________________________________________

1.4.2. cr_prime_balance_uri (string domain, int hash_source)

   Balances the request URI to the desination set given by domain
   in the default tree. The hash_source defines the parameter
   which is passed to the hash function. Return codes are the same
   as for cr_rewrite_uri. This function is only usable with
   requests that contains a valid numerical request URI, e.g.
   INVITEs.

   Meaning of the parameters is as follows:

     * domain - Name of the routing domain to be used.
     * hash_source - The hash values of the destination set must
       be a contiguous range starting at 1, limited by the
       configuration parameter max_targets. Possible values for
       hash_source are: from_user and to_user.
     __________________________________________________________

1.4.3. cr_rewrite_by_to (string domain, int hash_source)

   Like cr_rewrite_uri, except that the to URI is used for prefix
   matching instead the request URI. Return codes are the same as
   for cr_rewrite_uri. This function is usable on requests that
   don't contain a valid request URI, like REGISTERs.

   Meaning of the parameters is as follows:

     * domain - Name of the routing domain to be used.
     * hash_source - The hash values of the destination set 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 and
       to_user.
     __________________________________________________________

1.4.4. cr_prime_balance_by_to (string domain, int hash_source)

   Like cr_prime_balance_uri, except that the to URI is used for
   prefix matching instead the request URI. Return codes are the
   same as for cr_rewrite_uri. This function is usable on requests
   that don't contain a valid request URI, like REGISTERs.

   Meaning of the parameters is as follows:

     * domain - Name of the routing domain to be used.
     * hash_source - The hash values of the destination set must
       be a contiguous range starting at 1, limited by the
       configuration parameter max_targets. Possible values for
       hash_source are: from_user and to_user.
     __________________________________________________________

1.4.5. cr_prime_balance_by_from (string domain, int hash_source)

   Like cr_prime_balance_uri, except that the from URI is used for
   prefix matching instead the request URI. Return codes are the
   same as for cr_rewrite_uri. This function is usable on requests
   that don't contain a valid request URI, like REGISTERs.

   Meaning of the parameters is as follows:

     * domain - Name of the routing domain to be used.
     * hash_source - The hash values of the destination set must
       be a contiguous range starting at 1, limited by the
       configuration parameter max_targets. Possible values for
       hash_source are: from_user and to_user.
     __________________________________________________________

1.4.6. cr_user_rewrite_uri (string uri, string domain)

   Rewrites the request URI, the given URI is used to determine
   the carrier tree to be used. The carrier is derived from a
   database entry belonging to the user part of the URI. The
   domain identifies the routing domain inside the carrier tree.
   This function cannot be used in the config file mode, as it
   needs a mapping of the given user to a certain carrier.

   Meaning of the parameters is as follows:

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

1.4.7. cr_tree_rewrite_uri (string tree, string domain)

   Rewrites the request URI, using the carrier tree specified by
   the tree parameter with the given domain. The call id is used
   as hash source.

   Meaning of the parameters is as follows:

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

1.5. MI Commands

   All commands understand the "-?" parameter to print a short
   help message. The options have to be quoted as one string to be
   passed to MI interface. Each option except host and new host
   can be wildcarded by * (but only * and not things like "-d
   prox*").
     __________________________________________________________

1.5.1. cr_reload_routes

   This command reloads the routing data from the data source.

   Important: When new domains have been added, a restart of the
   server must be done, because the mapping of the ids used in the
   config script cannot be updated at runtime at the moment. So a
   reload could result in a wrong routing behaviour, because the
   ids used in the script could differ from the one used
   internally from the server. Modifying of already existing
   domains is no problem.
     __________________________________________________________

1.5.2. cr_dump_routes

   This command prints the route rules on the command line.
     __________________________________________________________

1.5.3. cr_replace_host

   This command can replace the rewrite_host of a route rule, it
   is only usable in file mode. Following options are possible:

     * -d - the domain containing the host
     * -p - the prefix containing the host
     * -h - the host to be replaced
     * -t - the new host

   Use the "null" prefix to specify an empty prefix.

   Example 1-25. cr_replace_host usage
...
openserctl fifo cr_replace_host "-d proxy -p 49 -h proxy1 -t proxy2"
...
     __________________________________________________________

1.5.4. cr_deactivate_host

   This command deactivates the specified host, i.e. it sets its
   status to 0. It is only usable in file mode. Following options
   are possible:

     * -d - the domain containing the host
     * -p - the prefix containing the host
     * -h - the host to be deactivated
     * -t - the new host used as backup

   When -t (new_host) is specified, the portion of traffic for the
   deactivated host is routed to the host given by -t. This is
   indicated in the output of dump_routes. The backup route is
   deactivated if the host is activated again.

   Use the "null" prefix to specify an empty prefix.

   Example 1-26. cr_deactivate_host usage
...
openserctl fifo cr_deactivate_host "-d proxy -p 49 -h proxy1"
...
     __________________________________________________________

1.5.5. cr_activate_host

   This command activates the specified host, i.e. it sets its
   status to 1. It is only usable in file mode. Following options
   are possible:

     * -d - the domain containing the host
     * -p - the prefix containing the host
     * -h - the host to be activated

   Use the "null" prefix to specify an empty prefix.

   Example 1-27. cr_activate_host usage
...
openserctl fifo cr_activate_host "-d proxy -p 49 -h proxy1"
...
     __________________________________________________________

1.5.6. cr_add_host

   This command adds a route rule, it is only usable in file mode.
   Following options are possible:

     * -d - the domain containing the host
     * -p - the prefix containing the host
     * -h - the host to be added
     * -w - the weight of the rule
     * -P - an optional rewrite prefix
     * -S - an optional rewrite suffix
     * -i - an optional hash index
     * -s - an optional strip value

   Use the "null" prefix to specify an empty prefix.

   Example 1-28. cr_add_host usage
...
openserctl fifo cr_add_host "-d proxy -p 49 -h proxy1 -w 0.25"
...
     __________________________________________________________

1.5.7. cr_delete_host

   This command delete the specified hosts or rules, i.e. remove
   them from the route tree. It is only usable in file mode.
   Following options are possible:

     * -d - the domain containing the host
     * -p - the prefix containing the host
     * -h - the host to be added
     * -w - the weight of the rule
     * -P - an optional rewrite prefix
     * -S - an optional rewrite suffix
     * -i - an optional hash index
     * -s - an optional strip value

   Use the "null" prefix to specify an empty prefix.

   Example 1-29. cr_delete_host usage
...
openserctl fifo cr_delete_host "-d proxy -p 49 -h proxy1 -w 0.25"
...
     __________________________________________________________

1.6. Examples

   Example 1-30. Configuration example - OpenSER script
...
route {
        # do something with the message, for example..
        if (loose_route()) { t_relay(); return; };
        # do more stuff..

        # route calls based on hash over callid
        # choose route domain 0 of the default carrier
        if(!cr_rewrite_uri("0", "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] {
        # 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_rewrite_uri("1", "call_id")){
                        t_reply("403", "Not allowed");
                } else {
                        t_on_failure("2");
                        t_relay();
                }
        }
}

failure_route[2] {
        # further processing
}
...

   Example 1-31. Configuration example - module configuration

   The following config file specifies within the default carrier
   two domains, each with an 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
   ommit the hash completly, the module gives them a 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 loadbalancing
   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"
      }
   }
}
...
     __________________________________________________________

1.7. Installation & Running

1.7.1. Database setup

   Before running OpenSER with carrierroute, you have to setup 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 openser/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,
   http://www.openser.org/docs/db-tables/openser-db-devel.html.

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

   Example 1-32. Example database content - carrierroute table
...
+----+---------+-------------+--------+------+-------+---------------+
| id | carrier | scan_prefix | domain | prob | strip | rewrite_host  |
+----+---------+-------------+--------+------+-------+---------------+
| 1  |       1 | 49          | 0      |  0.5 | 0     | de-1.carrier1 |
| 2  |       1 | 49          | 0      |  0.5 | 0     | de-2.carrier1 |
| 3  |       1 |             | 0      |    1 | 0     | gw.carrier1   |
| 5  |       1 | 49          | 1      |    1 | 0     | gw.carrier1   |
| 6  |       2 | 49          | 0      |  0.5 | 0     | de-1.carrier2 |
| 7  |       2 | 49          | 0      |  0.5 | 0     | de-2.carrier2 |
| 8  |       2 |             | 0      |    1 | 0     | gw.carrier2   |
| 9  |       2 | 49          | 1      |    1 | 0     | gw.carrier2   |
| 10 |       3 | 49          | 0      |    1 | 0     | de-gw.default |
| 11 |       3 |             | 0      |    1 | 0     | gw.default    |
+----+---------+-------------+--------+------+-------+---------------+
...

   This table contains two 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 a additional rule with the domain 1, that
   can be used for example as fallback if the gateways in domain 0
   are not reachable.

   Example 1-33. Example database content - route_tree table
...
+----+----------+
| id | carrier  |
+----+----------+
|  1 | carrier1 |
|  2 | carrier2 |
|  3 | default  |
+----+----------+
...

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

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

   Example 1-34. Necessary extensions for the user table

   Suggested changes:
...
ALTER TABLE subscriber ADD cr_preferred_carrier int(10) default NULL;
...
     __________________________________________________________

Chapter 2. Developer's Guide

   The module does not provide any API to use in other OpenSER
   modules.
     __________________________________________________________

Chapter 3. Frequently Asked Questions

   3.1. Where can I find more about OpenSER?
   3.2. Where can I post a question about this module?
   3.3. How can I report a bug?

   3.1. Where can I find more about OpenSER?

   Take a look at http://www.openser.org/.

   3.2. Where can I post a question about this module?

   First at all check if your question was already answered on one
   of our mailing lists:

     * User Mailing List -
       http://lists.openser.org/cgi-bin/mailman/listinfo/users
     * Developer Mailing List -
       http://lists.openser.org/cgi-bin/mailman/listinfo/devel

   E-mails regarding any stable OpenSER release should be sent to
   <users@lists.openser.org> and e-mails regarding development
   versions should be sent to <devel@lists.openser.org>.

   If you want to keep the mail private, send it to
   <team@lists.openser.org>.

   3.3. How can I report a bug?

   Please follow the guidelines provided at:
   http://sourceforge.net/tracker/?group_id=139143.
