Browse Source

tm: documented failure_reply_mode

- control how branches are managed for serial forking, i.e.,
  failure_route handling
Daniel-Constantin Mierla 15 năm trước cách đây
mục cha
commit
1a33a975c0
2 tập tin đã thay đổi với 171 bổ sung79 xóa
  1. 117 79
      modules/tm/README
  2. 54 0
      modules/tm/doc/params.xml

+ 117 - 79
modules/tm/README

@@ -57,6 +57,7 @@ Juha Heinanen
         1.4.35. default_reason (string)
         1.4.36. disable_6xx_block (integer)
         1.4.37. local_ack_mode (integer)
+        1.4.38. failure_reply_mode (integer)
 
    1.5. Functions
 
@@ -1153,12 +1154,49 @@ Note
 modparam("tm", "local_ack_mode", 1)
 ...
 
+1.4.38. failure_reply_mode (integer)
+
+   It controls how branches are managed and replies are selected for
+   failure_route handling: keep all, drop all, drop last branches in SIP
+   serial forking handling.
+
+   To control per transaction see t_drop_replies().
+
+   It has 4 possible values:
+     * 0 - all branches are kept, no matter a new leg of serial forking
+       has been started. Beware that if the new leg fails, you may get in
+       failure_route a reply code from a branch of previous serial forking
+       legs (e.g., if in first leg you got a 3xx, then you handled the
+       redirection in failure route, sent to a new destination and this
+       one timeout, you will get again the 3xx). Use t_drop_replies() on
+       per transaction fashion to control the behavior you want. It is the
+       default behaviour comming from SER 2.1.x.
+     * 1 - all branches are discarded by default. You can still overwrite
+       the behaviour via t_drop_replies()
+     * 2 - by default only the branches of previous leg of serial forking
+       are discarded
+     * 3 - all previous branches are discarded if there is a new serial
+       forking leg. This is the default behaviour coming from Kamailio
+       1.5.x. Use this mode if you don't want to handle in a per
+       transaction fashion with t_drop_replies(). It ensures that you will
+       get the winning reply from the branches of last serial forking step
+       (e.g., if in first step you get 3xx, then you forward to a new
+       destination, you will get in failure_route the reply coming from
+       that destination or a local timeout).
+
+   The default value is 0.
+
+   Example 38. Set failure_reply_mode parameter
+...
+modparam("tm", "failure_reply_mode", 3)
+...
+
 1.5. Functions
 
    Revision History
    Revision $Revision$ $Date$
 
-1.5.1. t_relay_to_udp(ip, port), t_relay_to_udp(), t_relay_to_tcp(ip, port)
+1.5.1.  t_relay_to_udp(ip, port), t_relay_to_udp(), t_relay_to_tcp(ip, port)
 t_relay_to_tcp() t_relay_to_tls(ip, port) t_relay_to_tls()
 t_relay_to_sctp(ip, port) t_relay_to_sctp()
 
@@ -1178,7 +1216,7 @@ t_relay_to_sctp(ip, port) t_relay_to_sctp()
    derived from the message uri (using sip sepcific DNS lookups), but with
    the protocol corresponding to the function name.
 
-   Example 38. t_relay_to_udp usage
+   Example 39. t_relay_to_udp usage
 ...
 if (src_ip==10.0.0.0/8)
         t_relay_to_udp("1.2.3.4", "5060"); # sent to 1.2.3.4:5060 over udp
@@ -1186,7 +1224,7 @@ else
         t_relay_to_tcp(); # relay to msg. uri, but over tcp
 ...
 
-1.5.2. t_relay() t_relay(host, port)
+1.5.2.  t_relay() t_relay(host, port)
 
    Relay a message statefully either to the destination indicated in the
    current URI (if called without any parameters) or to the specified host
@@ -1205,7 +1243,7 @@ else
    Returns a negative value on failure--you may still want to send a
    negative reply upstream statelessly not to leave upstream UAC in lurch.
 
-   Example 39. t_relay usage
+   Example 40. t_relay usage
 ...
 if (!t_relay())
 {
@@ -1214,7 +1252,7 @@ if (!t_relay())
 };
 ...
 
-1.5.3. t_on_failure(failure_route)
+1.5.3.  t_on_failure(failure_route)
 
    Sets failure routing block, to which control is passed after a
    transaction completed with a negative result but before sending a final
@@ -1234,7 +1272,7 @@ if (!t_relay())
    Meaning of the parameters is as follows:
      * failure_route - Failure route block to be called.
 
-   Example 40. t_on_failure usage
+   Example 41. t_on_failure usage
 ...
 route {
     t_on_failure("1");
@@ -1251,7 +1289,7 @@ failure_route[1] {
    See test/onr.cfg for a more complex example of combination of serial
    with parallel forking.
 
-1.5.4. t_on_reply(onreply_route)
+1.5.4.  t_on_reply(onreply_route)
 
    Sets the reply routing block, to which control is passed when a reply
    for the current transaction is received. Note that the set of commands
@@ -1260,7 +1298,7 @@ failure_route[1] {
    Meaning of the parameters is as follows:
      * onreply_route - Onreply route block to be called.
 
-   Example 41. t_on_reply usage
+   Example 42. t_on_reply usage
 ...
 loadmodule "/usr/local/lib/ser/modules/nathelper.so"
 ...
@@ -1281,7 +1319,7 @@ es');
         }
 }
 
-1.5.5. t_on_branch(branch_route)
+1.5.5.  t_on_branch(branch_route)
 
    Sets the branch routing block, to which control is passed after forking
    (when a new branch is created). For now branch routes are intended only
@@ -1292,7 +1330,7 @@ es');
    Meaning of the parameters is as follows:
      * branch_route - branch route block to be called.
 
-   Example 42. t_on_branch usage
+   Example 43. t_on_branch usage
 ...
 route {
         t_on_branch("1");
@@ -1305,12 +1343,12 @@ branch_route[1] {
         }
 }
 
-1.5.6. append_branch()
+1.5.6.  append_branch()
 
    Similarly to t_fork_to, it extends destination set by a new entry. The
    difference is that current URI is taken as new entry.
 
-   Example 43. append_branch usage
+   Example 44. append_branch usage
 ...
 set_user("john");
 t_fork();
@@ -1319,13 +1357,13 @@ t_fork();
 t_relay();
 ...
 
-1.5.7. t_newtran()
+1.5.7.  t_newtran()
 
    Creates a new transaction, returns a negative value on error. This is
    the only way a script can add a new transaction in an atomic way.
    Typically, it is used to deploy a UAS.
 
-   Example 44. t_newtran usage
+   Example 45. t_newtran usage
 ...
 if (t_newtran()) {
     log("UAS logic");
@@ -1335,7 +1373,7 @@ if (t_newtran()) {
 
    See test/uas.cfg for more examples.
 
-1.5.8. t_reply(code, reason_phrase)
+1.5.8.  t_reply(code, reason_phrase)
 
    Sends a stateful reply after a transaction has been established. See
    t_newtran for usage.
@@ -1344,12 +1382,12 @@ if (t_newtran()) {
      * code - Reply code number.
      * reason_phrase - Reason string.
 
-   Example 45. t_reply usage
+   Example 46. t_reply usage
 ...
 t_reply("404", "Not found");
 ...
 
-1.5.9. t_lookup_request()
+1.5.9.  t_lookup_request()
 
    Checks if a transaction exists. Returns a positive value if so,
    negative otherwise. Most likely you will not want to use it, as a
@@ -1357,33 +1395,33 @@ t_reply("404", "Not found");
    none was found. However this is safely (atomically) done using
    t_newtran.
 
-   Example 46. t_lookup_request usage
+   Example 47. t_lookup_request usage
 ...
 if (t_lookup_request()) {
     ...
 };
 ...
 
-1.5.10. t_retransmit_reply()
+1.5.10.  t_retransmit_reply()
 
    Retransmits a reply sent previously by UAS transaction.
 
-   Example 47. t_retransmit_reply usage
+   Example 48. t_retransmit_reply usage
 ...
 t_retransmit_reply();
 ...
 
-1.5.11. t_release()
+1.5.11.  t_release()
 
    Remove transaction from memory (it will be first put on a wait timer to
    absorb delayed messages).
 
-   Example 48. t_release usage
+   Example 49. t_release usage
 ...
 t_release();
 ...
 
-1.5.12. t_forward_nonack() t_forward_nonack(ip, port)
+1.5.12.  t_forward_nonack() t_forward_nonack(ip, port)
 t_forward_nonack_udp(ip, port) t_forward_nonack_tcp(ip, port)
 t_forward_nonack_tls(ip, port) t_forward_nonack_sctp(ip, port)
 
@@ -1393,12 +1431,12 @@ t_forward_nonack_tls(ip, port) t_forward_nonack_sctp(ip, port)
      * ip - IP address where the message should be sent.
      * port - Port number.
 
-   Example 49. t_forward_nonack usage
+   Example 50. t_forward_nonack usage
 ...
 t_forward_nonack("1.2.3.4", "5060");
 ...
 
-1.5.13. t_set_fr(fr_inv_timeout [, fr_timeout])
+1.5.13.  t_set_fr(fr_inv_timeout [, fr_timeout])
 
    Sets the fr_inv_timeout and optionally fr_timeout for the current
    transaction or for transactions created during the same script
@@ -1416,7 +1454,7 @@ t_forward_nonack("1.2.3.4", "5060");
 
    See also: fr_timer, fr_inv_timer, t_reset_fr().
 
-   Example 50. t_set_fr usage
+   Example 51. t_set_fr usage
 ...
 route {
         t_set_fr(10000); # set only fr invite timeout to 10s
@@ -1432,7 +1470,7 @@ branch_route[1] {
         }
 }
 
-1.5.14. t_reset_fr()
+1.5.14.  t_reset_fr()
 
    Resets the fr_inv_timer and fr_timer for the current transaction to the
    default values (set using the tm module parameters fr_inv_timer and
@@ -1443,7 +1481,7 @@ branch_route[1] {
 
    See also: fr_timer, fr_inv_timer, t_set_fr.
 
-   Example 51. t_reset_fr usage
+   Example 52. t_reset_fr usage
 ...
 route {
 ...
@@ -1451,7 +1489,7 @@ route {
 ...
 }
 
-1.5.15. t_set_max_lifetime(inv_lifetime, noninv_lifetime)
+1.5.15.  t_set_max_lifetime(inv_lifetime, noninv_lifetime)
 
    Sets the maximum lifetime for the current INVITE or non-INVITE
    transaction, or for transactions created during the same script
@@ -1469,7 +1507,7 @@ route {
 
    See also: max_inv_lifetime, max_noninv_lifetime, t_reset_max_lifetime.
 
-   Example 52. t_set_max_lifetime usage
+   Example 53. t_set_max_lifetime usage
 ...
 route {
     if (src_ip=1.2.3.4)
@@ -1480,7 +1518,7 @@ route {
                                           # INVITE and to 15s if not
 }
 
-1.5.16. t_reset_max_lifetime()
+1.5.16.  t_reset_max_lifetime()
 
    Resets the the maximum lifetime for the current INVITE or non-INVITE
    transaction to the default value (set using the tm module parameter
@@ -1491,7 +1529,7 @@ route {
 
    See also: max_inv_lifetime, max_noninv_lifetime, t_set_max_lifetime.
 
-   Example 53. t_reset_max_lifetime usage
+   Example 54. t_reset_max_lifetime usage
 ...
 route {
 ...
@@ -1499,7 +1537,7 @@ route {
 ...
 }
 
-1.5.17. t_set_retr(retr_t1_interval, retr_t2_interval)
+1.5.17.  t_set_retr(retr_t1_interval, retr_t2_interval)
 
    Sets the retr_t1_interval and retr_t2_interval for the current
    transaction or for transactions created during the same script
@@ -1529,7 +1567,7 @@ route {
 
    See also: retr_timer1, retr_timer2, t_reset_retr().
 
-   Example 54. t_set_retr usage
+   Example 55. t_set_retr usage
 ...
 route {
         t_set_retr(250, 0); # set only T1 to 250 ms
@@ -1545,7 +1583,7 @@ branch_route[1] {
         }
 }
 
-1.5.18. t_reset_retr()
+1.5.18.  t_reset_retr()
 
    Resets the retr_timer1 and retr_timer2 for the current transaction to
    the default values (set using the tm module parameters retr_timer1 and
@@ -1556,7 +1594,7 @@ branch_route[1] {
 
    See also: retr_timer1, retr_timer2, t_set_retr.
 
-   Example 55. t_reset_retr usage
+   Example 56. t_reset_retr usage
 ...
 route {
 ...
@@ -1564,7 +1602,7 @@ route {
 ...
 }
 
-1.5.19. t_set_auto_inv_100(0|1)
+1.5.19.  t_set_auto_inv_100(0|1)
 
    Switch automatically sending 100 replies to INVITEs on/off on a per
    transaction basis. It overrides the auto_inv_100 value for the current
@@ -1572,7 +1610,7 @@ route {
 
    See also: auto_inv_100.
 
-   Example 56. t_set_auto_inv_100 usage
+   Example 57. t_set_auto_inv_100 usage
 ...
 route {
 ...
@@ -1581,12 +1619,12 @@ route {
 ...
 }
 
-1.5.20. t_branch_timeout()
+1.5.20.  t_branch_timeout()
 
    Returns true if the failure route is executed for a branch that did
    timeout. It can be used only from the failure_route.
 
-   Example 57. t_branch_timeout usage
+   Example 58. t_branch_timeout usage
 ...
 failure_route[0]{
         if (t_branch_timeout()){
@@ -1595,13 +1633,13 @@ failure_route[0]{
         }
 }
 
-1.5.21. t_branch_replied()
+1.5.21.  t_branch_replied()
 
    Returns true if the failure route is executed for a branch that did
    receive at least one reply in the past (the "current" reply is not
    taken into account). It can be used only from the failure_route.
 
-   Example 58. t_branch_replied usage
+   Example 59. t_branch_replied usage
 ...
 failure_route[0]{
         if (t_branch_timeout()){
@@ -1613,12 +1651,12 @@ failure_route[0]{
         }
 }
 
-1.5.22. t_any_timeout()
+1.5.22.  t_any_timeout()
 
    Returns true if at least one of the current transactions branches did
    timeout.
 
-   Example 59. t_any_timeout usage
+   Example 60. t_any_timeout usage
 ...
 failure_route[0]{
         if (!t_branch_timeout()){
@@ -1629,13 +1667,13 @@ failure_route[0]{
         }
 }
 
-1.5.23. t_any_replied()
+1.5.23.  t_any_replied()
 
    Returns true if at least one of the current transactions branches did
    receive some reply in the past. If called from a failure or onreply
    route, the "current" reply is not taken into account.
 
-   Example 60. t_any_replied usage
+   Example 61. t_any_replied usage
 ...
 onreply_route[0]{
         if (!t_any_replied()){
@@ -1644,12 +1682,12 @@ onreply_route[0]{
         }
 }
 
-1.5.24. t_grep_status("code")
+1.5.24.  t_grep_status("code")
 
    Returns true if "code" is the final reply received (or locally
    generated) in at least one of the current transactions branches.
 
-   Example 61. t_grep_status usage
+   Example 62. t_grep_status usage
 ...
 onreply_route[0]{
         if (t_grep_status("486")){
@@ -1658,11 +1696,11 @@ onreply_route[0]{
         }
 }
 
-1.5.25. t_is_canceled()
+1.5.25.  t_is_canceled()
 
    Returns true if the current transaction was canceled.
 
-   Example 62. t_is_canceled usage
+   Example 63. t_is_canceled usage
 ...
 failure_route[0]{
         if (t_is_canceled()){
@@ -1671,12 +1709,12 @@ failure_route[0]{
         }
 }
 
-1.5.26. t_is_expired()
+1.5.26.  t_is_expired()
 
    Returns true if the current transaction has already been expired, i.e.
    the max_inv_lifetime/max_noninv_lifetime interval has already elapsed.
 
-   Example 63. t_is_expired usage
+   Example 64. t_is_expired usage
 ...
 failure_route[0]{
         if (t_is_expired()){
@@ -1685,7 +1723,7 @@ failure_route[0]{
         }
 }
 
-1.5.27. t_relay_cancel()
+1.5.27.  t_relay_cancel()
 
    Forwards the CANCEL if the corresponding INVITE transaction exists. The
    function is supposed to be used at the very beginning of the script,
@@ -1697,7 +1735,7 @@ failure_route[0]{
    CANCELs were successfully sent to the pending branches, true if the
    INVITE was not found, and false in case of any error.
 
-   Example 64. t_relay_cancel usage
+   Example 65. t_relay_cancel usage
 if (method == CANCEL) {
         if (!t_relay_cancel()) {  # implicit drop if relaying was successful,
                                   # nothing to do
@@ -1710,7 +1748,7 @@ if (method == CANCEL) {
         # do the same as for INVITEs
 }
 
-1.5.28. t_lookup_cancel(), t_lookup_cancel(1)
+1.5.28.  t_lookup_cancel(), t_lookup_cancel(1)
 
    Returns true if the corresponding INVITE transaction exists for a
    CANCEL request. The function can be called at the beginning of the
@@ -1724,7 +1762,7 @@ if (method == CANCEL) {
    overwritten with the flags of the INVITE. isflagset() can be used to
    check the flags of the previously forwarded INVITE in this case.
 
-   Example 65. t_lookup_cancel usage
+   Example 66. t_lookup_cancel usage
 if (method == CANCEL) {
         if (t_lookup_cancel()) {
                 log("INVITE transaction exists");
@@ -1742,7 +1780,7 @@ if (method == CANCEL) {
         # do the same as for INVITEs
 }
 
-1.5.29. t_drop_replies([mode])
+1.5.29.  t_drop_replies([mode])
 
    Drops all the previously received replies in failure_route block to
    make sure that none of them is picked up again.
@@ -1754,7 +1792,7 @@ if (method == CANCEL) {
    Dropping replies works only if a new branch is added to the
    transaction, or it is explicitly replied in the script!
 
-   Example 66. t_drop_replies() usage
+   Example 67. t_drop_replies() usage
 ...
 failure_route[0]{
         if (t_check_status("5[0-9][0-9]")){
@@ -1770,7 +1808,7 @@ failure_route[0]{
         }
 }
 
-1.5.30. t_save_lumps()
+1.5.30.  t_save_lumps()
 
    Forces the modifications of the processed SIP message to be saved in
    shared memory before t_relay() is called. The new branches which are
@@ -1785,7 +1823,7 @@ failure_route[0]{
    The transaction must be created by t_newtran() before calling
    t_save_lumps().
 
-   Example 67. t_save_lumps() usage
+   Example 68. t_save_lumps() usage
 route {
         ...
         t_newtran();
@@ -1810,7 +1848,7 @@ failure_route[1] {
         t_relay();
 }
 
-1.5.31. t_load_contacts()
+1.5.31.  t_load_contacts()
 
    This is the first of the two functions that can be used to implement
    serial/parallel forking based on the q value of individual branches in
@@ -1855,7 +1893,7 @@ failure_route[1] {
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 68. t_load_contacts usage
+   Example 69. t_load_contacts usage
 ...
 if (!t_load_contacts()) {
         sl_send_reply("500", "Server Internal Error - Cannot load contacts");
@@ -1863,7 +1901,7 @@ if (!t_load_contacts()) {
 };
 ...
 
-1.5.32. t_next_contacts()
+1.5.32.  t_next_contacts()
 
    The function t_next_contacts is the second of the two functions that
    can be used to implement serial/parallel forking based on the q value
@@ -1907,7 +1945,7 @@ if (!t_load_contacts()) {
    especially if you expect to have many serially forked branches. See the
    documentation of that parameter for more details.
 
-   Example 69. t_next_contacts usage
+   Example 70. t_next_contacts usage
 ...
 # First call after t_load_contacts() when transaction does not exist yet
 # and contacts should be available
@@ -1926,7 +1964,7 @@ if (!t_next_contacts()) {
 };
 ...
 
-1.5.33. t_check_trans()
+1.5.33.  t_check_trans()
 
    t_check_trans() can be used to quickly check if a message belongs or is
    related to a transaction. It behaves differently for different types of
@@ -1971,12 +2009,12 @@ Note
 
    See also: t_lookup_request(), t_lookup_cancel().
 
-   Example 70. t_check_trans usage
+   Example 71. t_check_trans usage
 if ( method == "CANCEL" && !t_check_trans())
         sl_reply("403", "cancel out of the blue forbidden");
 # note: in this example t_check_trans() can be replaced by t_lookup_cancel()
 
-1.5.34. t_set_disable_6xx(0|1)
+1.5.34.  t_set_disable_6xx(0|1)
 
    Turn off/on 6xx replies special rfc conformant handling on a per
    transaction basis. If turned off (t_set_disable_6xx("1")) 6XXs will be
@@ -1986,7 +2024,7 @@ if ( method == "CANCEL" && !t_check_trans())
 
    See also: disable_6xx_block.
 
-   Example 71. t_set_disable_6xx usage
+   Example 72. t_set_disable_6xx usage
 ...
 route {
 ...
@@ -1995,13 +2033,13 @@ route {
 ...
 }
 
-1.5.35. t_set_disable_failover(0|1)
+1.5.35.  t_set_disable_failover(0|1)
 
    Turn off/on dns failover on a per transaction basis.
 
    See also: use_dns_failover.
 
-   Example 72. t_set_disable_failover usage
+   Example 73. t_set_disable_failover usage
 ...
 route {
 ...
@@ -2010,7 +2048,7 @@ route {
 ...
 }
 
-1.5.36. t_replicate(params)
+1.5.36.  t_replicate(params)
 
    Replicate the SIP request to a specific address.
 
@@ -2032,7 +2070,7 @@ route {
      * hostport - address in "host:port" format. It can be given via an
        AVP.
 
-   Example 73. t_replicate usage
+   Example 74. t_replicate usage
 ...
 # sent to 1.2.3.4:5060 over tcp
 t_replicate("sip:1.2.3.4:5060;transport=tcp");
@@ -2045,7 +2083,7 @@ t_replicate("sip:$var(h);transport=tls");
 t_replicate_to_udp("1.2.3.4", "5060");
 ...
 
-1.5.37. t_relay_to(proxy, flags)
+1.5.37.  t_relay_to(proxy, flags)
 
    Forward the SIP request to a specific address, controlling internal
    behavior via flags.
@@ -2067,7 +2105,7 @@ t_replicate_to_udp("1.2.3.4", "5060");
             effect anymore).
           + 0x04 - disable dns failover.
 
-   Example 74. t_replicate usage
+   Example 75. t_replicate usage
 ...
 # sent to 1.2.3.4:5060 over tcp
 t_relay_to("tcp:1.2.3.4:5060");
@@ -2148,7 +2186,7 @@ end of body
 
 1.6.2. Functions
 
-1.6.2.1. register_tmcb(cb_type, cb_func)
+1.6.2.1.  register_tmcb(cb_type, cb_func)
 
    For programmatic use only--register a function to be called back on an
    event. See t_hooks.h for more details.
@@ -2157,7 +2195,7 @@ end of body
      * cb_type - Callback type.
      * cb_func - Callback function.
 
-1.6.2.2. load_tm(*import_structure)
+1.6.2.2.  load_tm(*import_structure)
 
    For programmatic use only--import exported TM functions. See the acc
    module for an example of use.
@@ -2165,7 +2203,7 @@ end of body
    Meaning of the parameters is as follows:
      * import_structure - Pointer to the import structure.
 
-1.6.2.3. int t_suspend(struct sip_msg *msg, unsigned int *hash_index,
+1.6.2.3.  int t_suspend(struct sip_msg *msg, unsigned int *hash_index,
 unsigned int *label)
 
    For programmatic use only. This function together with t_continue() can
@@ -2203,7 +2241,7 @@ unsigned int *label)
    t_suspend() should return 0 to make sure that the script processing
    does not continue.
 
-1.6.2.4. int t_continue(unsigned int hash_index, unsigned int label, struct
+1.6.2.4.  int t_continue(unsigned int hash_index, unsigned int label, struct
 action *route)
 
    For programmatic use only. This function is the pair of t_suspend(),
@@ -2219,7 +2257,7 @@ action *route)
 
    Return value: 0 - success, <0 - error.
 
-1.6.2.5. int t_cancel_suspend(unsigned int hash_index, unsigned int label)
+1.6.2.5.  int t_cancel_suspend(unsigned int hash_index, unsigned int label)
 
    For programmatic use only. This function is for revoking t_suspend()
    from the same process as it was executed before. t_cancel_suspend() can

+ 54 - 0
modules/tm/doc/params.xml

@@ -1186,6 +1186,60 @@ modparam("tm", "disable_6xx_block", 1)
 		<programlisting>
 ...
 modparam("tm", "local_ack_mode", 1)
+...
+	    </programlisting>
+	</example>
+	</section>
+	
+	<section id="failure_reply_mode">
+	<title><varname>failure_reply_mode</varname> (integer)</title>
+	<para>
+		It controls how branches are managed and replies are selected for
+		failure_route handling: keep all, drop all, drop last branches in
+		SIP serial forking handling.
+	</para>
+	<para>
+		To control per transaction see <function>t_drop_replies()</function>.
+	</para>
+	<para> It has 4 possible values:</para>
+	<itemizedlist>
+		<listitem><para>
+		<emphasis>0</emphasis> - all branches are kept, no matter a new leg of
+		serial forking has been started. Beware that if the new leg fails, you
+		may get in failure_route a reply code from a branch of previous serial
+		forking legs (e.g., if in first leg you got a 3xx, then you handled
+		the redirection in failure route, sent to a new destination and this
+		one timeout, you will get again the 3xx). Use t_drop_replies() on per
+		transaction fashion to control the behavior you want. It is the
+		default behaviour comming from SER 2.1.x.
+		</para></listitem>
+		<listitem><para>
+		<emphasis>1</emphasis> - all branches are discarded by default. You
+		can still overwrite the behaviour via t_drop_replies()
+		</para></listitem>
+		<listitem><para>
+		<emphasis>2</emphasis> - by default only the branches of previous leg
+		of serial forking are discarded
+		</para></listitem>
+		<listitem><para>
+		<emphasis>3</emphasis> - all previous branches are discarded if there
+		is a new serial forking leg. This is the default behaviour coming from
+		Kamailio 1.5.x. Use this mode if you don't want to handle in a per
+		transaction fashion with t_drop_replies(). It ensures that you will
+		get the winning reply from the branches of last serial forking step
+		(e.g., if in first step you get 3xx, then you forward to a new
+		destination, you will get in failure_route the reply coming from that
+		destination or a local timeout).
+		</para></listitem>
+	</itemizedlist>
+	<para>
+		The default value is 0.
+	</para>
+	<example>
+		<title>Set <varname>failure_reply_mode</varname> parameter</title>
+		<programlisting>
+...
+modparam("tm", "failure_reply_mode", 3)
 ...
 	    </programlisting>
 	</example>