sctp: add support for Primary Path Switchover
authorXin Long <lucien.xin@gmail.com>
Fri, 8 Nov 2019 05:20:35 +0000 (13:20 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Nov 2019 22:18:32 +0000 (14:18 -0800)
This is a new feature defined in section 5 of rfc7829: "Primary Path
Switchover". By introducing a new tunable parameter:

  Primary.Switchover.Max.Retrans (PSMR)

The primary path will be changed to another active path when the path
error counter on the old primary path exceeds PSMR, so that "the SCTP
sender is allowed to continue data transmission on a new working path
even when the old primary destination address becomes active again".

This patch is to add this tunable parameter, 'ps_retrans' per netns,
sock, asoc and transport. It also allows a user to change ps_retrans
per netns by sysctl, and ps_retrans per sock/asoc/transport will be
initialized with it.

The check will be done in sctp_do_8_2_transport_strike() when this
feature is enabled.

Note this feature is disabled by initializing 'ps_retrans' per netns
as 0xffff by default, and its value can't be less than 'pf_retrans'
when changing by sysctl.

v3->v4:
  - add define SCTP_PS_RETRANS_MAX 0xffff, and use it on extra2 of
    sysctl 'ps_retrans'.
  - add a new entry for ps_retrans on ip-sysctl.txt.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/ip-sysctl.txt
include/net/netns/sctp.h
include/net/sctp/constants.h
include/net/sctp/structs.h
net/sctp/associola.c
net/sctp/protocol.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/sysctl.c

index 0b0feb5b6b0096d1f0d5d8d23a4fbc1f2e3fcae1..099a55bd1432d22a0660a2ab539703bcdec91c28 100644 (file)
@@ -2195,6 +2195,18 @@ pf_retrans - INTEGER
 
        Default: 0
 
+ps_retrans - INTEGER
+       Primary.Switchover.Max.Retrans (PSMR), it's a tunable parameter coming
+       from section-5 "Primary Path Switchover" in rfc7829.  The primary path
+       will be changed to another active path when the path error counter on
+       the old primary path exceeds PSMR, so that "the SCTP sender is allowed
+       to continue data transmission on a new working path even when the old
+       primary destination address becomes active again".   Note this feature
+       is disabled by initializing 'ps_retrans' per netns as 0xffff by default,
+       and its value can't be less than 'pf_retrans' when changing by sysctl.
+
+       Default: 0xffff
+
 rto_initial - INTEGER
        The initial round trip timeout value in milliseconds that will be used
        in calculating round trip times.  This is the initial time interval
index 18c3ddae77a3b0d9552acea24ca2eba0a7f56a90..d8d02e4188d18f0931ae4a01e22ec2632251a704 100644 (file)
@@ -89,6 +89,12 @@ struct netns_sctp {
         */
        int pf_retrans;
 
+       /* Primary.Switchover.Max.Retrans sysctl value
+        * taken from:
+        * https://tools.ietf.org/html/rfc7829
+        */
+       int ps_retrans;
+
        /*
         * Disable Potentially-Failed feature, the feature is enabled by default
         * pf_enable    -  0  : disable pf
index e88b77a34cb1ef73bcd5e23eabcaa5d382300f20..15b4d9aec7ff278e67a7183f10c14be237227d6b 100644 (file)
@@ -296,6 +296,8 @@ enum {
 };
 #define SCTP_PF_EXPOSE_MAX     SCTP_PF_EXPOSE_ENABLE
 
+#define SCTP_PS_RETRANS_MAX    0xffff
+
 /* These return values describe the success or failure of a number of
  * routines which form the lower interface to SCTP_outqueue.
  */
index 9a43738774d739f1b29f083f453342afcfe2320f..3cc913f328cdb3b6e26d5990a896abf354674277 100644 (file)
@@ -184,7 +184,8 @@ struct sctp_sock {
        __u32 flowlabel;
        __u8  dscp;
 
-       int pf_retrans;
+       __u16 pf_retrans;
+       __u16 ps_retrans;
 
        /* The initial Path MTU to use for new associations. */
        __u32 pathmtu;
@@ -897,7 +898,9 @@ struct sctp_transport {
         * and will be initialized from the assocs value.  This can be changed
         * using the SCTP_PEER_ADDR_THLDS socket option
         */
-       int pf_retrans;
+       __u16 pf_retrans;
+       /* Used for primary path switchover. */
+       __u16 ps_retrans;
        /* PMTU       : The current known path MTU.  */
        __u32 pathmtu;
 
@@ -1773,7 +1776,9 @@ struct sctp_association {
         * and will be initialized from the assocs value.  This can be
         * changed using the SCTP_PEER_ADDR_THLDS socket option
         */
-       int pf_retrans;
+       __u16 pf_retrans;
+       /* Used for primary path switchover. */
+       __u16 ps_retrans;
 
        /* Maximum number of times the endpoint will retransmit INIT  */
        __u16 max_init_attempts;
index ad7a74e942d3f9b453c2bdcff5adf7dc6f7cccc3..8f8d18abd013a4cfc6105dca75fa83cda166c662 100644 (file)
@@ -86,6 +86,7 @@ static struct sctp_association *sctp_association_init(
         */
        asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
        asoc->pf_retrans  = sp->pf_retrans;
+       asoc->ps_retrans  = sp->ps_retrans;
        asoc->pf_expose   = sp->pf_expose;
 
        asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial);
@@ -628,6 +629,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 
        /* And the partial failure retrans threshold */
        peer->pf_retrans = asoc->pf_retrans;
+       /* And the primary path switchover retrans threshold */
+       peer->ps_retrans = asoc->ps_retrans;
 
        /* Initialize the peer's SACK delay timeout based on the
         * association configured value.
index f86be7bf09725c41abc8580f4604f70f7d51d76b..fbbf19128c2d752d05cf7694a54912a6d54bc69f 100644 (file)
@@ -1217,6 +1217,9 @@ static int __net_init sctp_defaults_init(struct net *net)
        /* Max.Burst                - 4 */
        net->sctp.max_burst                     = SCTP_DEFAULT_MAX_BURST;
 
+       /* Disable of Primary Path Switchover by default */
+       net->sctp.ps_retrans = SCTP_PS_RETRANS_MAX;
+
        /* Enable pf state by default */
        net->sctp.pf_enable = 1;
 
index e52b2128e43b8706ddbec3d6b77388e24402c1c9..acd737d4c0e0a938895ed10fc8aa39e3f908b64f 100644 (file)
@@ -567,6 +567,11 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands,
                                             SCTP_FAILED_THRESHOLD);
        }
 
+       if (transport->error_count > transport->ps_retrans &&
+           asoc->peer.primary_path == transport &&
+           asoc->peer.active_path != transport)
+               sctp_assoc_set_primary(asoc, asoc->peer.active_path);
+
        /* E2) For the destination address for which the timer
         * expires, set RTO <- RTO * 2 ("back off the timer").  The
         * maximum value discussed in rule C7 above (RTO.max) may be
index 74c4e62ac7416ae1966db8bf5d13ed9fa8501316..64452ee410daa427c2174c7bb43155bdf838b3f0 100644 (file)
@@ -5078,6 +5078,7 @@ static int sctp_init_sock(struct sock *sk)
        sp->hbinterval  = net->sctp.hb_interval;
        sp->pathmaxrxt  = net->sctp.max_retrans_path;
        sp->pf_retrans  = net->sctp.pf_retrans;
+       sp->ps_retrans  = net->sctp.ps_retrans;
        sp->pf_expose   = net->sctp.pf_expose;
        sp->pathmtu     = 0; /* allow default discovery */
        sp->sackdelay   = net->sctp.sack_timeout;
index 5d1ad44a29d1da6143b2b6872cd754de75187eb4..4740aa70e6528981c4eee414e16d223d0f544151 100644 (file)
@@ -35,6 +35,7 @@ static int rto_beta_min = 0;
 static int rto_alpha_max = 1000;
 static int rto_beta_max = 1000;
 static int pf_expose_max = SCTP_PF_EXPOSE_MAX;
+static int ps_retrans_max = SCTP_PS_RETRANS_MAX;
 
 static unsigned long max_autoclose_min = 0;
 static unsigned long max_autoclose_max =
@@ -213,7 +214,16 @@ static struct ctl_table sctp_net_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
                .extra1         = SYSCTL_ZERO,
-               .extra2         = SYSCTL_INT_MAX,
+               .extra2         = &init_net.sctp.ps_retrans,
+       },
+       {
+               .procname       = "ps_retrans",
+               .data           = &init_net.sctp.ps_retrans,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &init_net.sctp.pf_retrans,
+               .extra2         = &ps_retrans_max,
        },
        {
                .procname       = "sndbuf_policy",