Hello All,
I am having a problem with the t_on_failure failure route using SER.
I have been using SER for 2+ years now and am servicing 5000+ voip
customers but now we are moving to a PSTN termination partner who does
not have redundant gateways. So I would like to setup SER so that I
have call route advance to a 2nd PSTN carrier if the 1st fails.
However, I am running into some snags...
With my configuration the call is processed correctly if the 1st PSTN
carrier takes the call. However, when the failover happens then I get
some odd behavior. The call is initially setup correctly with the
failover carrier, but then it hangs up after about 5-7 seconds and a new
call comes in to the called number, and a loop begins where this same
call keeps coming in one after another until SER is restarted.
I do get the following errors on the SER console.
0(17304) forward_req: ERROR: cannot forward to af 2, proto 2 no
corresponding listening socket
0(17304) Warning: sl_send_reply: I won't send a reply for ACK!!
0(17304) ERROR: sl_reply_error used: I'm terribly sorry, server error
occurred (7/SL)
It almost seems as if the the 1st route PSTN carrier is not accepting my
ACK when I send it in response to the 403 Forbidden that they send to
me. Then they just keep sending the 403 Forbidden over and over again.
Each time that they do that then SER processes it as a failed call and
starts a new call to the secondary PSTN carrier. Does this sound
possible? Or am I way off base here?
I have attached my basic lab test SER cfg that I have been using to test
with. Perhaps someone can tell me what I might be doing incorrectly?
Or - Is there a better way to do this? ie. With AVP-Pops? If so, does
anyone have a sample configuration that I can look at?
Thanks so much for any help provided!!
Darren Nay
Ionosphere, Inc.
dnay(a)ionosphere.net
+1 864-678-3158
# ----------- global configuration parameters ------------------------
debug=3 # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no # (cmd line: -E)
memlog=0
#uncomment for debug mode
debug=3
fork=no
log_stderror=yes
#Bind IP
listen=XX.XX.XX.XX
check_via=no # (cmd. line: -v)
dns=yes # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
port=5060
children=5
mhomed=no # multi-homed?
fifo="/tmp/ser_fifo"
# ------------------ module loading ----------------------------------
loadmodule "/usr/local/lib/ser/modules/nathelper.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/xlog.so"
# ----------------- setting module-specific parameters ---------------
# -- timers --
modparam("tm", "wt_timer", 10)
modparam("tm", "retr_timer1p1", 2)
# -- usrloc params --
modparam("usrloc", "db_mode", 0)
# -- rr params --
modparam("rr", "enable_full_lr", 1)
# -- Nathelper --
modparam("registrar", "nat_flag", 6)
modparam("nathelper", "natping_interval", 10)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "rtpproxy_disable", 1)
alias=proxy.ionosphere.net
# ------------------------- request routing logic -------------------
# main routing logic
route {
# initial sanity checks -- messages with
# max_forwards==0, or excessively long requests
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
break;
};
if (msg:len > max_len) {
sl_send_reply("513", "Message too big");
break;
};
# Nathelper
if (method == "REGISTER" ||
!search("^Record-Route:.*XX.XX.XX.XX")) {
fix_nated_contact(); # Rewrite contact with source IP of signaling
force_rport();
setflag(6);
};
# we record-route all messages -- to make sure that
# subsequent messages will go through our proxy; that's
# particularly good if upstream and downstream entities
# use different transport protocol
if (!method=="REGISTER") record_route();
# loose-route processing
if (loose_route()) {
route(1);
break;
};
lookup("aliases");
if (!uri==myself) {
route(1);
break;
};
# if the request is for other domain use UsrLoc
# (in case, it does not work, use the following command
# with proper names and addresses in it)
if (uri==myself) {
if (method=="REGISTER") {
fix_nated_register();
save("location");
break;
};
};
### Process URI routing
# Now we determine if called number is on
# or off net and route accordingly
if (!lookup("location")) {
route(2); # Nothing found - Route Off-Net
} else {
route(1); # Direct match - Route On-Net
};
}
#
# No direct route via location or location_novm (Off-Net Route)
#
route[2]
{
t_on_failure("2");
#Send the call to Level3
rewritehostport("XX.XX.XX.XX:5060");
if (!t_relay()) {
sl_reply_error();
};
break;
}
#
# Direct route found via location or location_novm (On-Net Route)
#
route[1]
{
# !! Nathelper
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)"
&& !search("^Route:")) {
sl_send_reply("479", "We don't forward to private IP
addresses");
break;
};
# if client or server know to be behind a NAT, enable relay
if (isflagset(6)) {
# NAT processing of replies; apply to all transactions (for example,
# re-INVITEs from public to private UA are hard to identify as
# NATed at the moment of request processing); look at replies
t_on_reply("1");
append_hf("P-Behind-NAT: Yes\r\n");
};
# send it out now; use stateful forwarding as it works reliably
# even for UDP2TCP
if (!t_relay()) {
sl_reply_error();
};
}
onreply_route[1] {
if (status =~ "(183)|(180)|2[0-9][0-9]") {
fix_nated_contact();
};
if (nat_uac_test("1")) {
fix_nated_contact();
};
break;
}
failure_route[2] {
# forwarding failed try again at another destination
rewritehostport("XX.XX.XX.XX:5060");
append_branch();
t_relay();
break;
}