Load balancing traffic with Kamailio v4.1

Load balancing traffic with Kamailio

Note: We assume you have Asterisk/Freeswitch setup to handle inbound traffic from Kamailio

In part 3 of our Kamailio series we will explain how to load balance calls from users between several different media servers. For this part in the series we will use the “dispatcher” module. The dispatcher module provides us with several different ways to load balance calls from round-robin to weight based routing.

Getting Started

For this tutorial, you’ll only need one thing besides Kamailio and that is a list of media servers. If you don’t have any media servers, we recommend using Freeswitch and/or Asterisk.

Configuring Kamailio

By default, Kamailio does not load the dispatcher module or any of the modules respective settings. Let’s start with loading the module into Kamailio. Open up your kamailio configuration file (/etc/kamailio/kamailio.cfg), find the load modules section and add the following line:

 loadmodule “dispatcher.so”

Scroll down further in the file until you locate the module parameters section. Go the bottom of that list and add the following:

modparam("dispatcher", "db_url", "mysql://kamailioro:kamailioro@localhost/kamailio")
modparam("dispatcher", "table_name", "dispatcher")
modparam("dispatcher", "flags", 2)
modparam("dispatcher", "dst_avp", "$avp(AVP_DST)")
modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)")
modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)")

Save the file and restart Kamailio to make sure there are no errors. You can restart kamailio with:

# kamctl restart

If that didn’t work, go back and make sure you have everything entered properly. Once it’s running with no problem open back up the configuration file and proceed to the “request_route” section. Comment out the following line by appending a “#” pound symbol to the front of it.

 route(PSTN);

Right below add the following line:

 route(DISPATCHER);

It’s time to add the actual code that will do the dispatching. Go to the code block below “route[RELAY]” and add the following:

route[DISPATCHER] {
  # round robin dispatching on gateways group '1'
  if(!ds_select_dst("1", "4"))
  {
    send_reply("404", "No destination");
    exit;
  }
  xlog(“ —— DISPATCH: going to <$ru> via <$du>n");
  route(RELAY);
  exit;
}

In the above code, we chose to use the round-robin algorithm for routing calls. Basically, our calls will cycle between the media servers we chose to setup. If we have 2 media servers setup our calls will process like so, call 1 will go out of MS1, call 2 out of MS2, call 3 out of MS1 and so on.

With the dispatching code in place, we’ll need to add the actual destinations into the Kamailio database. Login to your MySQL database and execute the following commands. You can replace the destination and description with your media servers.

mysql> INSERT into dispatcher (setid, destination, flags, priority, attrs, description) VALUES (1, “sip:asterisk.example.com:5060”, 0, 0, "", "Endpoint: Asterisk Media Server");
mysql> INSERT into dispatcher (setid, destination, flags, priority, attrs, description) VALUES (1, “sip:freeswitch.example.net:5060”, 0, 0, "", "Endpoint: Freeswitch Media server");

With that completed, we’ll need to reload Kamailio. Since we haven’t restarted Kamailio since adding the dispatch route let’s just restart Kamailio using the same command as before. However, if you restarted Kamailio since adding the dispatch route you can just use the following command to reload the dispatcher info.

# kamctl dispatcher reload

Now that the routes are loaded into Kamailio, all you’ll need to do is push some calls through to Kamailio and they will be routed in a round-robin fashion like we stated above.

Reference

  • Dispatcher Modules Documentation – http://kamailio.org/docs/modules/4.1.x/modules/dispatcher.html

 

Least-Cost Routing with Kamailio v4.1

The goal of this document is to explain how to get Kamailio to route traffic to the carrier with the least cost. This is part 2 in our Kamailio series.

 Getting Started

You don’t need much for this tutorial. All you’ll need is 2 carrier endpoints and their rates for calling a certain area code. Other than a Kamailio server, you can proceed with the rest of the tutorial.

 Configuring Kamailio 

Before we start setting up the LCR module, we first need to make some changes to the Kamailio configuration file. First off, we will need to modify the listen parameter. Open up your Kamailio configuration (kamailio.cfg) and look for the “listen” line.

If your Kamailio instance is behind a firewall make your line look like this:

listen=udp:<internal address>:5060 advertise <external address>:5060

Else if your Kamailio instance is on the public internet make it look like this:

listen=udp:<external address>:5060

By default Kamailio does not load the LCR module so we will need to add it.  In the same config file, locate the section where it says “loadmodule” and go to the bottom of that list and add:

loadmodule “lcr.so”

We can now begin setting up the LCRs module parameters.

Configuring LCR Module 

Now that we’ve configured Kamailio, we need to configure the LCR module. Back in the configuration file, look for the module parameters section.  At the bottom of that section, add the following values:

modparam("lcr", "db_url", "mysql://kamailioro:kamailioro@localhost/kamailio")
modparam("lcr", "gw_uri_avp", "$avp(i:709)")
modparam("lcr", "ruri_user_avp", "$avp(i:500)")
modparam("lcr", "tag_avp", "$avp(lcr_tag)")
modparam("lcr", "flags_avp", "$avp(i:712)")
modparam("lcr", "lcr_id_avp", "$avp(s:lcr_id_avp)")
modparam("lcr", "defunct_gw_avp", "$avp(s:defunct_gw_avp)")

With the module configured, it’s time to setup the actual routing of the SIP requests. In the “request_route” above the line that says:

 # dispatch request to foreign domains

Add the following line:

 route(LCR);

Then add a new route using the code below, put this at the end of the file:

route[LCR] {
if (status=="200")
{
  xlog("LCR: Inside the LCR routen");
}

if(method=="INVITE")
{
  xlog("We got an invite");
  if(!load_gws(1, $rU, $var(caller_uri))) {
    xlog("Couldn't load gateways");
    sl_send_reply("500", "Server Internal Error - Cannot load gateways");
    exit;
  } else {
        xlog("GW Selected '$avp(i:709)'n");
        xlog("Domain of destination: $ddn");
        xlog("To URI: $tun");
  }

  if(!next_gw()) {
    xlog("Couldn't proceed to next gateway");
    sl_send_reply("503", "Service not available, no gateways found");
    exit;
  } else {
        xlog("Calling the first matched gatewayn");
        xlog("ruri_user_avp: '$avp(i:500)'n");
        xlog("To URI after next_gw: $tun");
        xlog("Request URI: $rUn");

  }

}
}

 

Adding LCR Data

With our routing code in place, we need to add some data to LCR tables. Before we do that let’s go over what tables the LCR module uses and how they all fit together.

There are 3 tables that the LCR module uses:

  • lcr_gw  – holds the gateways or endpoints where we can send our requests
  • lcr_rule – holds all the rules we will match against. Our area codes. 
  • lcr_rule_target – holds the rule to gateway matchings.

The most important table is the lcr_rule_target table. In this table, we take the ID of the rule from the lcr_rule table and connect it to the ID of the gateway we want all requests to go out of of it the request matches that rule.

For instance, if we setup a rule in the table that matches all request that start with 734 with an ID of 12, we can match that to a gateway ID in the lcr_rule_target table. So when a request comes in that starts with 734, it will be sent to that gateway.

For this example, we will be using 734 as the area code and 192.168.1.112 as the carrier. You can replace these values with your own in the steps below.

  1.   Login to MySQL
 # mysql -u root -p
  1.   Connect to the Kamailio DB
 mysql> use kamailio;
  1.   Let’s insert a gateway.
mysql> INSERT INTO lcr_gw (lcr_id, gw_name, ip_addr, port, uri_scheme, transport, strip, flags) VALUES (1, “Carrier1”, “192.168.1.112”, 5060, 1, 1, 0, 1);
  1.   Next let’s add an LCR rule.
mysql> INSERT INTO lcr_rule (lcr_id, prefix, stopper, enabled) VALUES (1, “734”, 1, 1);
  1.   Finally let’s add rule to gateway matching.
mysql> INSERT INTO lcr_rule_target (lcr_id, rule_id, gw_id, priority, weight) VALUES (1, 1, 1, 1, 1);

Repeat these steps for each of your carriers. Increase the weight for the carrier with the cheaper weight.

Testing Kamailio

Before we begin testing we need to make sure a few other things are in order. You’ll need to make sure that your ITSP knows you’re going to be sending traffic from your Kamailio IP address. You’ll also need a SIP phone pointed at Kamailio or have Kamailio setup as a trunk in a PBX.

With that said, we need to refresh what Kamailio has in memory. We can do this with:

# kamctl lcr reload

 

Now just call that area code from a phone and your call should go out of the carrier with the higher weight.