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@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@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)