Kamailio - Routing using the carrierroute module

How CarrierRoute Works

At first glance, the carrierroute module is far more difficult than its alternatives such as the dispatcher module. In reality, its actually quite simple once you play around with its capabilities enough. One of the more interesting ones is load balancing.

The carrierroute module relies heavily on the DB for its abilities. It separates its routing into different carrier lists. Each carrier list can have its own purpose. You can have a carrier list for routing to all of your PBXs or a list of all your SIP providers. Within these carrier lists, you can further organize your gateways into domains.

Domains allow you to further narrow down your lists. Imagine you have a carrier list that contains all of your PBXs. Some PBXs need to have an alternative destination if the main PBX cannot be reached. Using domains, you can specify a list of alternative destinations.

When choosing the destination, carrierroute uses a combination of the carrier, domain and DID. Basically, if the number is in the carrier and domain list, it will route the call to whatever gateway is set for that particular DID.

The rest of this post will go through setting up carrierroute and using it to route calls to a PBX.

Setting Up

To use the carrierroute module, you’ll either need to compile it into Kamailio or install the necessary package. If you originally installed Kamailio using a package manager like aptitude then you can install it using:

# apt-get install kamailio-carrierroute-modules

If you installed Kamailio from source, it’s a bit more work to get carrierroute installed but not much. First go to the source directory for Kamailio. Open the modules.lst with your text editor of choice:

# vim modules.lst

Find the line that starts with include_modules. It probably has a line like this already:

include_modules= db_mysql

After the db_mysql, append carrierroute so it look like this:

include_modules= db_mysql carrierroute

Save and exit. Make the files now.

# make all 
# make install

Now that you have the carrierroute module installed, let’s get the database setup.

Add Database Data

Carrierroute uses a few database tables. The main ones include:

  • carrierroute - Routing rules are stored here
  • domain_name - Contains list of domain
  • carrier_name - Contains list of carriers

To start, we will need a carrier, domain and at least 1 routing rule. Let’s insert our first carrier entry:

INSERT INTO carrier_name (carrier) VALUES (“PBXs”);

Next, insert our first domain:

INSERT INTO domain_name (domain) VALUES (“Main”);

Lastly, insert our first routing rule. You can modify the scan_prefix, rewrite_host and description to whatever you want.

INSERT INTO carrierroute (carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host, rewrite_prefix, rewrite_suffix, description) VALUES (1, 1, “131355512344”, 0, 0, 1, 0, “pbx1.thyrusgorges.com”, “”, “”, “first route entry”);

With those inserts, we just accomplished a few things. We’ve successfully set up our primary carrier, PBXs. This will be associated with all of our PBX endpoints. Main was setup as the primary domain responsible for our PBXs carrier. Lastly, we setup a simple route to a PBX.

The last insert statement is the most important. With it, we added a routing rule for the DID, 1-313-555-1234. This DID belongs to carrier 1. The reason we put 1 as the carrier value instead of PBXs is because the database entry wants to know the ID of the carrier. PBXs was the first entry in our carrier_name table so naturally it would have the ID of 1. The same applies for the domain value. It was the first domain inserted so it will have an ID of 1.

Now if you wanted a list of failover endpoints inside the PBXs list, you could create a second domain called failover and add another entry into the carrierroute table. Except instead of domain being 1, it would be whatever ID was assigned to the failover domain. I’ll leave that as an exercise to the reader.

Flags and mask I won’t go into detail about since we won’t be using them. We choose 0 so they would match against all values. The prob or probability field is also quite important. Using this field, you can specify how often this particular route should be chosen.

For example, our DID might need to be load balanced because it receives so much traffic. We can insert the same route several times but each time the probability is different. It is important to note that all of the probabilities for a route should add up to 1.

If you have 2 routes and one has a probability of .3 and the other .5, this won’t come out as 1. Kamailio will do some internal logic so the probabilities add up to 1. While it is safe to do this, I do not recommend doing this since it might cause unexpected behavior.

The rewrite_host is the endpoint for the DID or scan_prefix we specified. In our example, we will route 1-313-555-1234 to pbx1.thyrusgorges.com. Lastly, we aren’t using rewrite_prefix or rewrite_suffix but these can be used if you need to append a value to either side of the scan_prefix/DID.

We’re done with the database now. Let’s work on our Kamailio config file now.

Modifying Kamailio.cfg

Before we can do anything, we need to tell Kamailio to use the carrierroute module. Open up the config in your favorite text editor and find the load module section. Go to the bottom and append this:

loadmodule “carrierroute.so”

Also, if you don’t have the TM module loaded, load it before carrierroute since it requires it.

loadmodule “tm.so”

Quick tip, you don’t actually have to include the .so at the end.

With the module loaded, let’s set some parameters for it. Find the module parameter section and append this at the end:

modparam("carrierroute", "config_source", "db" )
modparam("carrierroute", "db_url", DB_URL)
modparam("carrierroute", "carrierroute_table", "carrierroute")

All we did with these parameters was tell carrierroute that it should go to the database for its configuration. We told it how to access the database and what table it should use. If you don’t have DB_URL defined, go to the top of your config file and add this:

#!define DB_URL mysql://kamailio:password@localhost/kamailio

Be sure to replace password with your password.

The last thing we need to do is add a new named routing block that will contain our carrierroute code. In the file, make sure you comment out or remove any routes that handle sending traffic. I commented out the PSTN, SIPOUT, PRESENCE, REGISTRAR and LOCATION routes. At the bottom of the request_route, add a new route like so:


Go to the bottom of the file and add this[1]:

route {
 # route calls based on hash over callid
 # choose route domain 0 of the default carrier
 if(!cr_route("PBXs", "0", "$rU", "$rU", "call_id")){
     sl_send_reply("403", "Not allowed");
 } else {
     # In case of failure, re-route the request
     # Relay the request to the gateway

And add the failure route[1]:

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_route("PBXs", "1", "$rU", "$rU", "call_id")){
         t_reply("403", "Not allowed");
     } else {

In the CARRIER route, we attempt to route based upon the call_id and the username in the Request URI. This is done using the cr_route function. The username will be the scan_prefix value we specified in the carrierroute table. If we can’t route the request, we send back a 403 reply and go to the failure route.

In the failure route, we change the URI back to its original value and check the status code. If the status code matches the regular expression, we attempt to route out of a secondary domain. If that still doesn’t work, we attempt a second failure route.

Save and exit the file. With the config file finished reload Kamailio:

# kamctl restart

Now perform some test calls ! Remember, you can always point a softphone at your proxy and dial the numbers in your carrierroute table to verify routing it’s working as expected.

Question or comment ? Let me know on twitter or email.