aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt14
-rw-r--r--include/net/sctp/constants.h1
-rw-r--r--include/net/sctp/structs.h20
-rw-r--r--include/net/sctp/user.h11
-rw-r--r--net/sctp/associola.c37
-rw-r--r--net/sctp/outqueue.c6
-rw-r--r--net/sctp/sm_sideeffect.c33
-rw-r--r--net/sctp/socket.c101
-rw-r--r--net/sctp/sysctl.c9
-rw-r--r--net/sctp/transport.c4
10 files changed, 221 insertions, 15 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 5f3ef7f7fcec..406a5226220d 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1440,6 +1440,20 @@ path_max_retrans - INTEGER
1440 1440
1441 Default: 5 1441 Default: 5
1442 1442
1443pf_retrans - INTEGER
1444 The number of retransmissions that will be attempted on a given path
1445 before traffic is redirected to an alternate transport (should one
1446 exist). Note this is distinct from path_max_retrans, as a path that
1447 passes the pf_retrans threshold can still be used. Its only
1448 deprioritized when a transmission path is selected by the stack. This
1449 setting is primarily used to enable fast failover mechanisms without
1450 having to reduce path_max_retrans to a very low value. See:
1451 http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt
1452 for details. Note also that a value of pf_retrans > path_max_retrans
1453 disables this feature
1454
1455 Default: 0
1456
1443rto_initial - INTEGER 1457rto_initial - INTEGER
1444 The initial round trip timeout value in milliseconds that will be used 1458 The initial round trip timeout value in milliseconds that will be used
1445 in calculating round trip times. This is the initial time interval 1459 in calculating round trip times. This is the initial time interval
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 942b864f6135..d053d2e99876 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -334,6 +334,7 @@ typedef enum {
334typedef enum { 334typedef enum {
335 SCTP_TRANSPORT_UP, 335 SCTP_TRANSPORT_UP,
336 SCTP_TRANSPORT_DOWN, 336 SCTP_TRANSPORT_DOWN,
337 SCTP_TRANSPORT_PF,
337} sctp_transport_cmd_t; 338} sctp_transport_cmd_t;
338 339
339/* These are the address scopes defined mainly for IPv4 addresses 340/* These are the address scopes defined mainly for IPv4 addresses
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 536e439ddf1d..fc5e60016e37 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -161,6 +161,12 @@ extern struct sctp_globals {
161 int max_retrans_path; 161 int max_retrans_path;
162 int max_retrans_init; 162 int max_retrans_init;
163 163
164 /* Potentially-Failed.Max.Retrans sysctl value
165 * taken from:
166 * http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05
167 */
168 int pf_retrans;
169
164 /* 170 /*
165 * Policy for preforming sctp/socket accounting 171 * Policy for preforming sctp/socket accounting
166 * 0 - do socket level accounting, all assocs share sk_sndbuf 172 * 0 - do socket level accounting, all assocs share sk_sndbuf
@@ -258,6 +264,7 @@ extern struct sctp_globals {
258#define sctp_sndbuf_policy (sctp_globals.sndbuf_policy) 264#define sctp_sndbuf_policy (sctp_globals.sndbuf_policy)
259#define sctp_rcvbuf_policy (sctp_globals.rcvbuf_policy) 265#define sctp_rcvbuf_policy (sctp_globals.rcvbuf_policy)
260#define sctp_max_retrans_path (sctp_globals.max_retrans_path) 266#define sctp_max_retrans_path (sctp_globals.max_retrans_path)
267#define sctp_pf_retrans (sctp_globals.pf_retrans)
261#define sctp_max_retrans_init (sctp_globals.max_retrans_init) 268#define sctp_max_retrans_init (sctp_globals.max_retrans_init)
262#define sctp_sack_timeout (sctp_globals.sack_timeout) 269#define sctp_sack_timeout (sctp_globals.sack_timeout)
263#define sctp_hb_interval (sctp_globals.hb_interval) 270#define sctp_hb_interval (sctp_globals.hb_interval)
@@ -990,10 +997,15 @@ struct sctp_transport {
990 997
991 /* This is the max_retrans value for the transport and will 998 /* This is the max_retrans value for the transport and will
992 * be initialized from the assocs value. This can be changed 999 * be initialized from the assocs value. This can be changed
993 * using SCTP_SET_PEER_ADDR_PARAMS socket option. 1000 * using the SCTP_SET_PEER_ADDR_PARAMS socket option.
994 */ 1001 */
995 __u16 pathmaxrxt; 1002 __u16 pathmaxrxt;
996 1003
1004 /* This is the partially failed retrans value for the transport
1005 * and will be initialized from the assocs value. This can be changed
1006 * using the SCTP_PEER_ADDR_THLDS socket option
1007 */
1008 int pf_retrans;
997 /* PMTU : The current known path MTU. */ 1009 /* PMTU : The current known path MTU. */
998 __u32 pathmtu; 1010 __u32 pathmtu;
999 1011
@@ -1664,6 +1676,12 @@ struct sctp_association {
1664 */ 1676 */
1665 int max_retrans; 1677 int max_retrans;
1666 1678
1679 /* This is the partially failed retrans value for the transport
1680 * and will be initialized from the assocs value. This can be
1681 * changed using the SCTP_PEER_ADDR_THLDS socket option
1682 */
1683 int pf_retrans;
1684
1667 /* Maximum number of times the endpoint will retransmit INIT */ 1685 /* Maximum number of times the endpoint will retransmit INIT */
1668 __u16 max_init_attempts; 1686 __u16 max_init_attempts;
1669 1687
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 0842ef00b2fe..1b02d7ad453b 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -93,6 +93,7 @@ typedef __s32 sctp_assoc_t;
93#define SCTP_GET_ASSOC_NUMBER 28 /* Read only */ 93#define SCTP_GET_ASSOC_NUMBER 28 /* Read only */
94#define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */ 94#define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */
95#define SCTP_AUTO_ASCONF 30 95#define SCTP_AUTO_ASCONF 30
96#define SCTP_PEER_ADDR_THLDS 31
96 97
97/* Internal Socket Options. Some of the sctp library functions are 98/* Internal Socket Options. Some of the sctp library functions are
98 * implemented using these socket options. 99 * implemented using these socket options.
@@ -649,6 +650,7 @@ struct sctp_paddrinfo {
649 */ 650 */
650enum sctp_spinfo_state { 651enum sctp_spinfo_state {
651 SCTP_INACTIVE, 652 SCTP_INACTIVE,
653 SCTP_PF,
652 SCTP_ACTIVE, 654 SCTP_ACTIVE,
653 SCTP_UNCONFIRMED, 655 SCTP_UNCONFIRMED,
654 SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ 656 SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
@@ -741,4 +743,13 @@ typedef struct {
741 int sd; 743 int sd;
742} sctp_peeloff_arg_t; 744} sctp_peeloff_arg_t;
743 745
746/*
747 * Peer Address Thresholds socket option
748 */
749struct sctp_paddrthlds {
750 sctp_assoc_t spt_assoc_id;
751 struct sockaddr_storage spt_address;
752 __u16 spt_pathmaxrxt;
753 __u16 spt_pathpfthld;
754};
744#endif /* __net_sctp_user_h__ */ 755#endif /* __net_sctp_user_h__ */
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 8cf348e62e74..ebaef3ed6065 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -124,6 +124,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
124 * socket values. 124 * socket values.
125 */ 125 */
126 asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; 126 asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
127 asoc->pf_retrans = sctp_pf_retrans;
128
127 asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial); 129 asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial);
128 asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max); 130 asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
129 asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min); 131 asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min);
@@ -686,6 +688,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
686 /* Set the path max_retrans. */ 688 /* Set the path max_retrans. */
687 peer->pathmaxrxt = asoc->pathmaxrxt; 689 peer->pathmaxrxt = asoc->pathmaxrxt;
688 690
691 /* And the partial failure retrnas threshold */
692 peer->pf_retrans = asoc->pf_retrans;
693
689 /* Initialize the peer's SACK delay timeout based on the 694 /* Initialize the peer's SACK delay timeout based on the
690 * association configured value. 695 * association configured value.
691 */ 696 */
@@ -841,6 +846,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
841 struct sctp_ulpevent *event; 846 struct sctp_ulpevent *event;
842 struct sockaddr_storage addr; 847 struct sockaddr_storage addr;
843 int spc_state = 0; 848 int spc_state = 0;
849 bool ulp_notify = true;
844 850
845 /* Record the transition on the transport. */ 851 /* Record the transition on the transport. */
846 switch (command) { 852 switch (command) {
@@ -854,6 +860,14 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
854 spc_state = SCTP_ADDR_CONFIRMED; 860 spc_state = SCTP_ADDR_CONFIRMED;
855 else 861 else
856 spc_state = SCTP_ADDR_AVAILABLE; 862 spc_state = SCTP_ADDR_AVAILABLE;
863 /* Don't inform ULP about transition from PF to
864 * active state and set cwnd to 1, see SCTP
865 * Quick failover draft section 5.1, point 5
866 */
867 if (transport->state == SCTP_PF) {
868 ulp_notify = false;
869 transport->cwnd = 1;
870 }
857 transport->state = SCTP_ACTIVE; 871 transport->state = SCTP_ACTIVE;
858 break; 872 break;
859 873
@@ -872,6 +886,11 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
872 spc_state = SCTP_ADDR_UNREACHABLE; 886 spc_state = SCTP_ADDR_UNREACHABLE;
873 break; 887 break;
874 888
889 case SCTP_TRANSPORT_PF:
890 transport->state = SCTP_PF;
891 ulp_notify = false;
892 break;
893
875 default: 894 default:
876 return; 895 return;
877 } 896 }
@@ -879,12 +898,15 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
879 /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the 898 /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the
880 * user. 899 * user.
881 */ 900 */
882 memset(&addr, 0, sizeof(struct sockaddr_storage)); 901 if (ulp_notify) {
883 memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len); 902 memset(&addr, 0, sizeof(struct sockaddr_storage));
884 event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 903 memcpy(&addr, &transport->ipaddr,
885 0, spc_state, error, GFP_ATOMIC); 904 transport->af_specific->sockaddr_len);
886 if (event) 905 event = sctp_ulpevent_make_peer_addr_change(asoc, &addr,
887 sctp_ulpq_tail_event(&asoc->ulpq, event); 906 0, spc_state, error, GFP_ATOMIC);
907 if (event)
908 sctp_ulpq_tail_event(&asoc->ulpq, event);
909 }
888 910
889 /* Select new active and retran paths. */ 911 /* Select new active and retran paths. */
890 912
@@ -900,7 +922,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
900 transports) { 922 transports) {
901 923
902 if ((t->state == SCTP_INACTIVE) || 924 if ((t->state == SCTP_INACTIVE) ||
903 (t->state == SCTP_UNCONFIRMED)) 925 (t->state == SCTP_UNCONFIRMED) ||
926 (t->state == SCTP_PF))
904 continue; 927 continue;
905 if (!first || t->last_time_heard > first->last_time_heard) { 928 if (!first || t->last_time_heard > first->last_time_heard) {
906 second = first; 929 second = first;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index a0fa19f5650c..e7aa177c9522 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -792,7 +792,8 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
792 if (!new_transport) 792 if (!new_transport)
793 new_transport = asoc->peer.active_path; 793 new_transport = asoc->peer.active_path;
794 } else if ((new_transport->state == SCTP_INACTIVE) || 794 } else if ((new_transport->state == SCTP_INACTIVE) ||
795 (new_transport->state == SCTP_UNCONFIRMED)) { 795 (new_transport->state == SCTP_UNCONFIRMED) ||
796 (new_transport->state == SCTP_PF)) {
796 /* If the chunk is Heartbeat or Heartbeat Ack, 797 /* If the chunk is Heartbeat or Heartbeat Ack,
797 * send it to chunk->transport, even if it's 798 * send it to chunk->transport, even if it's
798 * inactive. 799 * inactive.
@@ -987,7 +988,8 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
987 new_transport = chunk->transport; 988 new_transport = chunk->transport;
988 if (!new_transport || 989 if (!new_transport ||
989 ((new_transport->state == SCTP_INACTIVE) || 990 ((new_transport->state == SCTP_INACTIVE) ||
990 (new_transport->state == SCTP_UNCONFIRMED))) 991 (new_transport->state == SCTP_UNCONFIRMED) ||
992 (new_transport->state == SCTP_PF)))
991 new_transport = asoc->peer.active_path; 993 new_transport = asoc->peer.active_path;
992 if (new_transport->state == SCTP_UNCONFIRMED) 994 if (new_transport->state == SCTP_UNCONFIRMED)
993 continue; 995 continue;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 8716da1a8592..fe99628e1257 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -76,6 +76,8 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
76 sctp_cmd_seq_t *commands, 76 sctp_cmd_seq_t *commands,
77 gfp_t gfp); 77 gfp_t gfp);
78 78
79static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
80 struct sctp_transport *t);
79/******************************************************************** 81/********************************************************************
80 * Helper functions 82 * Helper functions
81 ********************************************************************/ 83 ********************************************************************/
@@ -470,7 +472,8 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = {
470 * notification SHOULD be sent to the upper layer. 472 * notification SHOULD be sent to the upper layer.
471 * 473 *
472 */ 474 */
473static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, 475static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
476 struct sctp_association *asoc,
474 struct sctp_transport *transport, 477 struct sctp_transport *transport,
475 int is_hb) 478 int is_hb)
476{ 479{
@@ -495,6 +498,23 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
495 transport->error_count++; 498 transport->error_count++;
496 } 499 }
497 500
501 /* If the transport error count is greater than the pf_retrans
502 * threshold, and less than pathmaxrtx, then mark this transport
503 * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1,
504 * point 1
505 */
506 if ((transport->state != SCTP_PF) &&
507 (asoc->pf_retrans < transport->pathmaxrxt) &&
508 (transport->error_count > asoc->pf_retrans)) {
509
510 sctp_assoc_control_transport(asoc, transport,
511 SCTP_TRANSPORT_PF,
512 0);
513
514 /* Update the hb timer to resend a heartbeat every rto */
515 sctp_cmd_hb_timer_update(commands, transport);
516 }
517
498 if (transport->state != SCTP_INACTIVE && 518 if (transport->state != SCTP_INACTIVE &&
499 (transport->error_count > transport->pathmaxrxt)) { 519 (transport->error_count > transport->pathmaxrxt)) {
500 SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", 520 SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
@@ -699,6 +719,10 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
699 SCTP_HEARTBEAT_SUCCESS); 719 SCTP_HEARTBEAT_SUCCESS);
700 } 720 }
701 721
722 if (t->state == SCTP_PF)
723 sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
724 SCTP_HEARTBEAT_SUCCESS);
725
702 /* The receiver of the HEARTBEAT ACK should also perform an 726 /* The receiver of the HEARTBEAT ACK should also perform an
703 * RTT measurement for that destination transport address 727 * RTT measurement for that destination transport address
704 * using the time value carried in the HEARTBEAT ACK chunk. 728 * using the time value carried in the HEARTBEAT ACK chunk.
@@ -1565,8 +1589,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1565 1589
1566 case SCTP_CMD_STRIKE: 1590 case SCTP_CMD_STRIKE:
1567 /* Mark one strike against a transport. */ 1591 /* Mark one strike against a transport. */
1568 sctp_do_8_2_transport_strike(asoc, cmd->obj.transport, 1592 sctp_do_8_2_transport_strike(commands, asoc,
1569 0); 1593 cmd->obj.transport, 0);
1570 break; 1594 break;
1571 1595
1572 case SCTP_CMD_TRANSPORT_IDLE: 1596 case SCTP_CMD_TRANSPORT_IDLE:
@@ -1576,7 +1600,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1576 1600
1577 case SCTP_CMD_TRANSPORT_HB_SENT: 1601 case SCTP_CMD_TRANSPORT_HB_SENT:
1578 t = cmd->obj.transport; 1602 t = cmd->obj.transport;
1579 sctp_do_8_2_transport_strike(asoc, t, 1); 1603 sctp_do_8_2_transport_strike(commands, asoc,
1604 t, 1);
1580 t->hb_sent = 1; 1605 t->hb_sent = 1;
1581 break; 1606 break;
1582 1607
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5d488cdcf679..5e259817a7f3 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3478,6 +3478,56 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
3478} 3478}
3479 3479
3480 3480
3481/*
3482 * SCTP_PEER_ADDR_THLDS
3483 *
3484 * This option allows us to alter the partially failed threshold for one or all
3485 * transports in an association. See Section 6.1 of:
3486 * http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt
3487 */
3488static int sctp_setsockopt_paddr_thresholds(struct sock *sk,
3489 char __user *optval,
3490 unsigned int optlen)
3491{
3492 struct sctp_paddrthlds val;
3493 struct sctp_transport *trans;
3494 struct sctp_association *asoc;
3495
3496 if (optlen < sizeof(struct sctp_paddrthlds))
3497 return -EINVAL;
3498 if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval,
3499 sizeof(struct sctp_paddrthlds)))
3500 return -EFAULT;
3501
3502
3503 if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) {
3504 asoc = sctp_id2assoc(sk, val.spt_assoc_id);
3505 if (!asoc)
3506 return -ENOENT;
3507 list_for_each_entry(trans, &asoc->peer.transport_addr_list,
3508 transports) {
3509 if (val.spt_pathmaxrxt)
3510 trans->pathmaxrxt = val.spt_pathmaxrxt;
3511 trans->pf_retrans = val.spt_pathpfthld;
3512 }
3513
3514 if (val.spt_pathmaxrxt)
3515 asoc->pathmaxrxt = val.spt_pathmaxrxt;
3516 asoc->pf_retrans = val.spt_pathpfthld;
3517 } else {
3518 trans = sctp_addr_id2transport(sk, &val.spt_address,
3519 val.spt_assoc_id);
3520 if (!trans)
3521 return -ENOENT;
3522
3523 if (val.spt_pathmaxrxt)
3524 trans->pathmaxrxt = val.spt_pathmaxrxt;
3525 trans->pf_retrans = val.spt_pathpfthld;
3526 }
3527
3528 return 0;
3529}
3530
3481/* API 6.2 setsockopt(), getsockopt() 3531/* API 6.2 setsockopt(), getsockopt()
3482 * 3532 *
3483 * Applications use setsockopt() and getsockopt() to set or retrieve 3533 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3627,6 +3677,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
3627 case SCTP_AUTO_ASCONF: 3677 case SCTP_AUTO_ASCONF:
3628 retval = sctp_setsockopt_auto_asconf(sk, optval, optlen); 3678 retval = sctp_setsockopt_auto_asconf(sk, optval, optlen);
3629 break; 3679 break;
3680 case SCTP_PEER_ADDR_THLDS:
3681 retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen);
3682 break;
3630 default: 3683 default:
3631 retval = -ENOPROTOOPT; 3684 retval = -ENOPROTOOPT;
3632 break; 3685 break;
@@ -5498,6 +5551,51 @@ static int sctp_getsockopt_assoc_ids(struct sock *sk, int len,
5498 return 0; 5551 return 0;
5499} 5552}
5500 5553
5554/*
5555 * SCTP_PEER_ADDR_THLDS
5556 *
5557 * This option allows us to fetch the partially failed threshold for one or all
5558 * transports in an association. See Section 6.1 of:
5559 * http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt
5560 */
5561static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
5562 char __user *optval,
5563 int len,
5564 int __user *optlen)
5565{
5566 struct sctp_paddrthlds val;
5567 struct sctp_transport *trans;
5568 struct sctp_association *asoc;
5569
5570 if (len < sizeof(struct sctp_paddrthlds))
5571 return -EINVAL;
5572 len = sizeof(struct sctp_paddrthlds);
5573 if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval, len))
5574 return -EFAULT;
5575
5576 if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) {
5577 asoc = sctp_id2assoc(sk, val.spt_assoc_id);
5578 if (!asoc)
5579 return -ENOENT;
5580
5581 val.spt_pathpfthld = asoc->pf_retrans;
5582 val.spt_pathmaxrxt = asoc->pathmaxrxt;
5583 } else {
5584 trans = sctp_addr_id2transport(sk, &val.spt_address,
5585 val.spt_assoc_id);
5586 if (!trans)
5587 return -ENOENT;
5588
5589 val.spt_pathmaxrxt = trans->pathmaxrxt;
5590 val.spt_pathpfthld = trans->pf_retrans;
5591 }
5592
5593 if (put_user(len, optlen) || copy_to_user(optval, &val, len))
5594 return -EFAULT;
5595
5596 return 0;
5597}
5598
5501SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, 5599SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5502 char __user *optval, int __user *optlen) 5600 char __user *optval, int __user *optlen)
5503{ 5601{
@@ -5636,6 +5734,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5636 case SCTP_AUTO_ASCONF: 5734 case SCTP_AUTO_ASCONF:
5637 retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen); 5735 retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen);
5638 break; 5736 break;
5737 case SCTP_PEER_ADDR_THLDS:
5738 retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen);
5739 break;
5639 default: 5740 default:
5640 retval = -ENOPROTOOPT; 5741 retval = -ENOPROTOOPT;
5641 break; 5742 break;
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index e5fe639c89e7..2b2bfe933ff1 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -141,6 +141,15 @@ static ctl_table sctp_table[] = {
141 .extra2 = &int_max 141 .extra2 = &int_max
142 }, 142 },
143 { 143 {
144 .procname = "pf_retrans",
145 .data = &sctp_pf_retrans,
146 .maxlen = sizeof(int),
147 .mode = 0644,
148 .proc_handler = proc_dointvec_minmax,
149 .extra1 = &zero,
150 .extra2 = &int_max
151 },
152 {
144 .procname = "max_init_retransmits", 153 .procname = "max_init_retransmits",
145 .data = &sctp_max_retrans_init, 154 .data = &sctp_max_retrans_init,
146 .maxlen = sizeof(int), 155 .maxlen = sizeof(int),
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index a6b7ee9ce28a..d1c652ed2f3d 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -87,6 +87,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
87 87
88 /* Initialize the default path max_retrans. */ 88 /* Initialize the default path max_retrans. */
89 peer->pathmaxrxt = sctp_max_retrans_path; 89 peer->pathmaxrxt = sctp_max_retrans_path;
90 peer->pf_retrans = sctp_pf_retrans;
90 91
91 INIT_LIST_HEAD(&peer->transmitted); 92 INIT_LIST_HEAD(&peer->transmitted);
92 INIT_LIST_HEAD(&peer->send_ready); 93 INIT_LIST_HEAD(&peer->send_ready);
@@ -595,7 +596,8 @@ unsigned long sctp_transport_timeout(struct sctp_transport *t)
595{ 596{
596 unsigned long timeout; 597 unsigned long timeout;
597 timeout = t->rto + sctp_jitter(t->rto); 598 timeout = t->rto + sctp_jitter(t->rto);
598 if (t->state != SCTP_UNCONFIRMED) 599 if ((t->state != SCTP_UNCONFIRMED) &&
600 (t->state != SCTP_PF))
599 timeout += t->hbinterval; 601 timeout += t->hbinterval;
600 timeout += jiffies; 602 timeout += jiffies;
601 return timeout; 603 return timeout;