Commit 34515e94 authored by Xin Long's avatar Xin Long Committed by David S. Miller

sctp: add support for Primary Path Switchover

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: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8d2a6935
...@@ -2195,6 +2195,18 @@ pf_retrans - INTEGER ...@@ -2195,6 +2195,18 @@ pf_retrans - INTEGER
Default: 0 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 rto_initial - INTEGER
The initial round trip timeout value in milliseconds that will be used The initial round trip timeout value in milliseconds that will be used
in calculating round trip times. This is the initial time interval in calculating round trip times. This is the initial time interval
......
...@@ -89,6 +89,12 @@ struct netns_sctp { ...@@ -89,6 +89,12 @@ struct netns_sctp {
*/ */
int pf_retrans; 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 * Disable Potentially-Failed feature, the feature is enabled by default
* pf_enable - 0 : disable pf * pf_enable - 0 : disable pf
......
...@@ -296,6 +296,8 @@ enum { ...@@ -296,6 +296,8 @@ enum {
}; };
#define SCTP_PF_EXPOSE_MAX SCTP_PF_EXPOSE_ENABLE #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 /* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue. * routines which form the lower interface to SCTP_outqueue.
*/ */
......
...@@ -184,7 +184,8 @@ struct sctp_sock { ...@@ -184,7 +184,8 @@ struct sctp_sock {
__u32 flowlabel; __u32 flowlabel;
__u8 dscp; __u8 dscp;
int pf_retrans; __u16 pf_retrans;
__u16 ps_retrans;
/* The initial Path MTU to use for new associations. */ /* The initial Path MTU to use for new associations. */
__u32 pathmtu; __u32 pathmtu;
...@@ -897,7 +898,9 @@ struct sctp_transport { ...@@ -897,7 +898,9 @@ struct sctp_transport {
* and will be initialized from the assocs value. This can be changed * and will be initialized from the assocs value. This can be changed
* using the SCTP_PEER_ADDR_THLDS socket option * 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. */ /* PMTU : The current known path MTU. */
__u32 pathmtu; __u32 pathmtu;
...@@ -1773,7 +1776,9 @@ struct sctp_association { ...@@ -1773,7 +1776,9 @@ struct sctp_association {
* and will be initialized from the assocs value. This can be * and will be initialized from the assocs value. This can be
* changed using the SCTP_PEER_ADDR_THLDS socket option * 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 */ /* Maximum number of times the endpoint will retransmit INIT */
__u16 max_init_attempts; __u16 max_init_attempts;
......
...@@ -86,6 +86,7 @@ static struct sctp_association *sctp_association_init( ...@@ -86,6 +86,7 @@ static struct sctp_association *sctp_association_init(
*/ */
asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
asoc->pf_retrans = sp->pf_retrans; asoc->pf_retrans = sp->pf_retrans;
asoc->ps_retrans = sp->ps_retrans;
asoc->pf_expose = sp->pf_expose; asoc->pf_expose = sp->pf_expose;
asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial); 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, ...@@ -628,6 +629,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* And the partial failure retrans threshold */ /* And the partial failure retrans threshold */
peer->pf_retrans = asoc->pf_retrans; 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 /* Initialize the peer's SACK delay timeout based on the
* association configured value. * association configured value.
......
...@@ -1217,6 +1217,9 @@ static int __net_init sctp_defaults_init(struct net *net) ...@@ -1217,6 +1217,9 @@ static int __net_init sctp_defaults_init(struct net *net)
/* Max.Burst - 4 */ /* Max.Burst - 4 */
net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; 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 */ /* Enable pf state by default */
net->sctp.pf_enable = 1; net->sctp.pf_enable = 1;
......
...@@ -567,6 +567,11 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands, ...@@ -567,6 +567,11 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands,
SCTP_FAILED_THRESHOLD); 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 /* E2) For the destination address for which the timer
* expires, set RTO <- RTO * 2 ("back off the timer"). The * expires, set RTO <- RTO * 2 ("back off the timer"). The
* maximum value discussed in rule C7 above (RTO.max) may be * maximum value discussed in rule C7 above (RTO.max) may be
......
...@@ -5078,6 +5078,7 @@ static int sctp_init_sock(struct sock *sk) ...@@ -5078,6 +5078,7 @@ static int sctp_init_sock(struct sock *sk)
sp->hbinterval = net->sctp.hb_interval; sp->hbinterval = net->sctp.hb_interval;
sp->pathmaxrxt = net->sctp.max_retrans_path; sp->pathmaxrxt = net->sctp.max_retrans_path;
sp->pf_retrans = net->sctp.pf_retrans; sp->pf_retrans = net->sctp.pf_retrans;
sp->ps_retrans = net->sctp.ps_retrans;
sp->pf_expose = net->sctp.pf_expose; sp->pf_expose = net->sctp.pf_expose;
sp->pathmtu = 0; /* allow default discovery */ sp->pathmtu = 0; /* allow default discovery */
sp->sackdelay = net->sctp.sack_timeout; sp->sackdelay = net->sctp.sack_timeout;
......
...@@ -35,6 +35,7 @@ static int rto_beta_min = 0; ...@@ -35,6 +35,7 @@ static int rto_beta_min = 0;
static int rto_alpha_max = 1000; static int rto_alpha_max = 1000;
static int rto_beta_max = 1000; static int rto_beta_max = 1000;
static int pf_expose_max = SCTP_PF_EXPOSE_MAX; 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_min = 0;
static unsigned long max_autoclose_max = static unsigned long max_autoclose_max =
...@@ -213,7 +214,16 @@ static struct ctl_table sctp_net_table[] = { ...@@ -213,7 +214,16 @@ static struct ctl_table sctp_net_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_minmax, .proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO, .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", .procname = "sndbuf_policy",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment