Hi,
I have a Kamailio running as Load Balancer and it works great but since
a couple of weeks I kept noticing 404s in Homer and when looked into it
they came from Kamailio.
```
route[LOADBALANCE] {
#ds_select_dst(destination_set, algorithm) function chooses the
destination for the call. For this it can use a lot of algorithms.
#Alg. 0 is the default one that does the the choosing over the call
ID hash
#Alg. 4 is a Round-Robin
#Alg. 10 is the one that chooses the destination based on the minimum
load of all destinations
if(!ds_select_dst("1", "4"))
{
#if we are here that means no destination is available. We notify
the user by 404 and exit the script.
xlog("L_NOTICE", "No destination available!");
send_reply("404", "No destination");
exit;
}
xlog("L_NOTICE", "Routing call to <$ru> via <$du>\n");
#set the no_reply_recieved timeout to 2 second ... adjust the value
to your need
#note: The first value "0" is invite timeout .. we do not need to
change it
#This means that is the selected media server fails to respond within
2 seconds the failure_route "MANAGE_FAILURE" is called
#note: this implies that ale the signaling from media servers on the
way back to the user goes through the proxy as well
t_set_fr(0,2000);
t_on_failure("MANAGE_FAILURE");
return;
}
```
The two asterisks behind it seem fine and I can’t really see why this
started happening. Also I thing that returning 404 might be misleading,
wouldn’t it be better if I would return 503 instead?
I enabled debugging in Kamailio but can’t really seem to notice
anything wrong here:
```
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/udp_server.c:491]: udp_rcv_loop(): received on udp socket:
(106/100/1104) [[INVITE sip:431230123@213.137.140.230:5060 SIP/2.0 0D
0A Via: SIP/2.0/UDP 196.27.235.76:5060;branch=z9h]]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:604]: parse_msg(): SIP Request:
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:606]: parse_msg(): method: <INVITE>
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:608]: parse_msg(): uri:
<sip:431230123@213.137.140.230:5060>
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:610]: parse_msg(): version: <SIP/2.0>
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/parse_via.c:1303]: parse_via_param(): Found param type 232,
<branch> = <z9hG4bK0080827005DD9C0D8E963B2EA293>; state=16
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/parse_via.c:2639]: parse_via(): end of header reached,
state=5
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:492]: parse_headers(): Via found, flags=2
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:494]: parse_headers(): this is the first via
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/parse_addr_spec.c:864]: parse_addr_spec(): end of header
reached, state=10
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:171]: get_hdr_field(): <To> [52];
uri=[sip:431230123@213.137.140.230]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:172]: get_hdr_field(): to body ["431230123"
<sip:431230123@213.137.140.230>
Feb 15 09:50:28 wlb kamailio[6659]: ]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:152]: get_hdr_field(): cseq <CSeq>: <36825>
<INVITE>
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/receive.c:200]: receive_msg(): --- received sip message - request
- call-id: [2610e00004f5-5c66843f-6400386f-2c1b8100-6c4782(a)127.0.0.1] -
cseq: [36825 INVITE]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/receive.c:248]: receive_msg(): preparing to run routing scripts...
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/parse_addr_spec.c:185]: parse_to_param(): add param:
tag=0080827005DD9C0D8E96C55CF6CD
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/parse_addr_spec.c:864]: parse_addr_spec(): end of header
reached, state=29
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: siptrace
[siptrace.c:507]: sip_trace_store_db(): database connection not
initialized
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: siptrace
[siptrace_hep.c:498]: pipport2su(): the port string is 5060
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: siptrace
[siptrace_hep.c:498]: pipport2su(): the port string is 5060
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/proxy.c:264]: mk_proxy(): doing DNS lookup...
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: siptrace
[siptrace_hep.c:302]: trace_send_hep2_duplicate(): setting up the
socket_info
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) NOTICE: <script>: Tracing
6(6668) DEBUG: maxfwd [mf_funcs.c:74]: is_maxfwd_present(): value = 70
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:183]: get_hdr_field(): content_length=355
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/parser/msg_parser.c:89]: get_hdr_field(): found end of header
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: sanity
[sanity_mod.c:256]: w_sanity_check(): sanity checks result: 1
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/socket_info.c:559]: grep_sock_info(): checking if host==us: 14==9
&& [213.137.140.230] == [127.0.0.1]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/socket_info.c:566]: grep_sock_info(): checking if port 5060
(advertise 0) matches port 5060
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/socket_info.c:559]: grep_sock_info(): checking if host==us: 14==14
&& [213.137.140.230] == [213.137.140.230]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: <core>
[core/socket_info.c:566]: grep_sock_info(): checking if port 5060
(advertise 0) matches port 5060
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) NOTICE: <script>: OPTIONS
from 196.27.235.76:5060
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: siputils
[checks.c:120]: has_totag(): no totag
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: tm
[t_lookup.c:1018]: t_check_msg(): msg (0x7f7e7edd3be8) id=6845 global
id=6844 T start=(nil)
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: tm [t_lookup.c:476]:
t_lookup_request(): start searching: hash=29308, isACK=0
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: tm [t_lookup.c:435]:
matching_3261(): RFC3261 transaction matching failed
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: tm [t_lookup.c:659]:
t_lookup_request(): no transaction found
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: tm
[t_lookup.c:1087]: t_check_msg(): msg (0x7f7e7edd3be8) id=6845 global
id=6845 T end=(nil)
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: rr [loose.c:1209]:
is_direction(): param ftag not found
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: dispatcher
[dispatch.c:1832]: ds_select_dst_limit(): set [1]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) DEBUG: dispatcher
[dispatch.c:1935]: ds_select_dst_limit(): alg hash [1]
Feb 15 09:50:28 wlb kamailio[6659]: 6(6668) NOTICE: <script>: No
destination available! 6(6668) DEBUG: sl [sl.c:282]: send_reply(): reply
in stateless mode (sl)
```
My kamailio.cfg
```
#!KAMAILIO
#
# sample config file for dispatcher module
# - load balancing of VoIP calls with round robin
# - no TPC listening
# - don't dispatch REGISTER and presence requests
#
# Kamailio (OpenSER) SIP Server v3.2
# - web:
http://www.kamailio.org
# - git:
http://sip-router.org
#
# Direct your questions about this file to:
sr-users(a)lists.sip-router.org
#
# Refer to the Core CookBook at
http://www.kamailio.org/dokuwiki/doku.php
# for an explanation of possible statements, functions and parameters.
#
# Several features can be enabled using '#!define WITH_FEATURE'
directives:
#
# *** To run in debug mode:
# - define WITH_DEBUG
#
####### Global Parameters #########
#!define WITH_HOMER
#!define WITH_DEBUG
#!ifdef WITH_DEBUG
debug=4
log_stderror=yes
#!else
debug=2
log_stderror=no
#!endif
memdbg=5
memlog=5
log_facility=LOG_LOCAL0
fork=yes
children=4
/* comment the next line to enable TCP */
disable_tcp=yes
/* uncomment the next line to disable the auto discovery of local
aliases
based on revers DNS on IPs (default on) */
auto_aliases=yes
/* add local domain aliases */
port=5060
/* uncomment and configure the following line if you want Kamailio to
bind on a specific interface/port/proto (default bind on all
available) */
# listen=udp:127.0.0.1:5060
sip_warning=no
####### Modules Section ########
#set module path
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/"
# loadmodule "db_mysql.so"
# loadmodule "mi_fifo.so"
loadmodule "jsonrpcs.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "acc.so"
loadmodule "counters.so"
loadmodule "dispatcher.so"
#!ifdef WITH_HOMER
loadmodule "siptrace.so"
#!endif
#loadmodule "kex.so"
#loadmodule "tm.so"
#loadmodule "tmx.so"
#loadmodule "sl.so"
#loadmodule "rr.so"
#loadmodule "pv.so"
#loadmodule "maxfwd.so"
#loadmodule "textops.so"
#loadmodule "siputils.so"
#loadmodule "xlog.so"
#loadmodule "sanity.so"
## loadmodule "ctl.so"
#loadmodule "mi_rpc.so"
#loadmodule "acc.so"
# ----- acc params -----
modparam("acc", "log_flag", 1)
modparam("acc", "failed_transaction_flag", 3)
modparam("acc", "log_extra",
"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si")
#!ifdef WITH_HOMER
# check IP and port of your capture node
modparam("siptrace", "duplicate_uri",
"sip:213.136.47.31:9060")
modparam("siptrace", "hep_mode_on", 1)
modparam("siptrace", "trace_to_database", 0)
modparam("siptrace", "trace_flag", 22)
modparam("siptrace", "trace_on", 1)
#!endif
# ----------------- setting module-specific parameters ---------------
# modparam("dispatcher", "db_url", DBURL)
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)")
modparam("dispatcher", "sock_avp", "$avp(dssocket)")
modparam("dispatcher", "attrs_avp", "$avp(dsattrs)")
#set next two parameters if you want to enable balance alg. no. 10
#modparam("dispatcher", "dstid_avp", "$avp(dsdstid)")
#modparam("dispatcher", "ds_hash_size", 8)
modparam("dispatcher", "ds_ping_interval", 20)
modparam("dispatcher", "ds_ping_from",
"sip:kamailio@example.com")
#modparam("dispatcher", "ds_ping_method", "INFO")
modparam("dispatcher", "ds_probing_mode", 1)
modparam("dispatcher", "ds_probing_threshold", 1)
#configure codes or classes of SIP replies to list only allowed replies
(i.e. when temporarily unavailable=480)
modparam("dispatcher", "ds_ping_reply_codes",
"class=2;code=480;code=404")
####### Routing Logic ########
# main request routing logic
route {
#!ifdef WITH_HOMER
#start duplicate the SIP message now
sip_trace();
setflag(22);
xlog("L_NOTICE","Tracing");
#!endif
# per request initial checks
route(REQINIT);
# handle requests within SIP dialogs
route(WITHINDLG);
# CANCEL processing
if (is_method("CANCEL"))
{
if (t_check_trans())
t_relay();
exit;
}
t_check_trans();
# record routing for dialog forming requests (in case they are
routed)
# - remove preloaded route headers
remove_hf("Route");
if (is_method("INVITE|SUBSCRIBE"))
record_route();
#if (is_method("INVITE"))
#{
# ds_select_domain("1","4");
# #sl_send_reply("300","Redirect");
# #t_relay();
# exit;
#}
# account only INVITEs
if (is_method("INVITE"))
{
setflag(1); # do accounting
}
# handle presence related requests
route(PRESENCE);
# handle registrations
route(REGISTRAR);
if ($rU==$null)
{
# request with no Username in RURI
sl_send_reply("484","Address Incomplete");
exit;
}
route(LOADBALANCE);
route(RELAY);
}
# Per SIP request initial checks
route[REQINIT] {
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if(!sanity_check("1511", "7"))
{
xlog("Malformed SIP message from $si:$sp\n");
exit;
}
# Reply to options
if (uri==myself) {
xlog("L_NOTICE","OPTIONS from $si:$sp\n");
if ((method==OPTIONS) && (! uri=~"sip:.*[@]+.*")) {
xlog("L_NOTICE","answering options $si:$sp\n");
options_reply();
}
}
}
# Handle requests within SIP dialogs
route[WITHINDLG] {
if (has_totag()) {
# sequential request withing a dialog should
# take the path determined by record-routing
if (loose_route()) {
if (is_method("BYE")) {
setflag(1); # do accounting ...
setflag(3); # ... even if the transaction fails
}
route(RELAY);
} else {
if (is_method("SUBSCRIBE") && uri == myself) {
# in-dialog subscribe requests
route(PRESENCE);
exit;
}
if ( is_method("ACK") ) {
if ( t_check_trans() ) {
# non loose-route, but stateful ACK;
# must be ACK after a 487 or e.g. 404 from upstream server
t_relay();
exit;
} else {
# ACK without matching transaction ... ignore and discard.
exit;
}
}
sl_send_reply("404","Not here");
}
exit;
}
}
# Handle SIP registrations
route[REGISTRAR] {
if(!is_method("REGISTER"))
return;
#sl_send_reply("404", "No registrar");
#t_relay();
if(!ds_select_dst("1", "4"))
{
sl_send_reply("404", "No registrar");
exit;
}
forward();
exit;
}
# Presence server route
route[PRESENCE] {
if(!is_method("PUBLISH|SUBSCRIBE"))
return;
sl_send_reply("404", "Not here");
exit;
}
route[LOADBALANCE] {
#ds_select_dst(destination_set, algorithm) function chooses the
destination for the call. For this it can use a lot of algorithms.
#Alg. 0 is the default one that does the the choosing over the call
ID hash
#Alg. 4 is a Round-Robin
#Alg. 10 is the one that chooses the destination based on the minimum
load of all destinations
if(!ds_select_dst("1", "4"))
{
#if we are here that means no destination is available. We notify
the user by 404 and exit the script.
xlog("L_NOTICE", "No destination available!");
send_reply("404", "No destination");
exit;
}
xlog("L_NOTICE", "Routing call to <$ru> via <$du>\n");
#set the no_reply_recieved timeout to 2 second ... adjust the value
to your need
#note: The first value "0" is invite timeout .. we do not need to
change it
#This means that is the selected media server fails to respond within
2 seconds the failure_route "MANAGE_FAILURE" is called
#note: this implies that ale the signaling from media servers on the
way back to the user goes through the proxy as well
t_set_fr(0,2000);
t_on_failure("MANAGE_FAILURE");
return;
}
# manage failure routing cases
failure_route[MANAGE_FAILURE] {
# route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
xlog("L_NOTICE", "Media server $du failed to answer, selecting other
one!");
# next DST - only for 500 reply or local timeout (set by t_set_fr())
if (t_check_status("500") || t_branch_timeout() ||
!t_branch_replied())
{
#we mark the destination Inactive and Probing
ds_mark_dst("ip");
#select the new destination
if(ds_next_dst())
{
#again set local timeout for reply
t_set_fr(0,2000);
t_on_failure("MANAGE_FAILURE");
route(RELAY);
exit;
}
else
{
#last available node failed to reply, no other destinations
available
send_reply("404", "No destination");
exit;
}
}
}
route[RELAY] {
xlog("L_NOTICE", "going to <$ru> via <$du>");
if (!t_relay()) {
sl_reply_error();
}
exit;
}
```
and my dispatcher.list
```
# line format
# id(int,auto) setid(int) destination(string) flags(int) priority(int)
attrs(string) description(string)
1 sip:196.27.235.76:5060
1 sip:213.137.140.230:5060
```
any help to understand these issues would be greatly appreciated.
Cris
---
Cristian Livadaru
LcX IT Solutions
Web:
http://lcx.at/
Tel: +43 1 37 37 37
Fax: +43 1 37 37 37 - 25
**24/7 Support: 0900 474 455** (1,81€/Min)