diff options
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/associola.c | 37 | ||||
| -rw-r--r-- | net/sctp/outqueue.c | 6 | ||||
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 33 | ||||
| -rw-r--r-- | net/sctp/socket.c | 101 | ||||
| -rw-r--r-- | net/sctp/sysctl.c | 9 | ||||
| -rw-r--r-- | net/sctp/transport.c | 4 |
6 files changed, 176 insertions, 14 deletions
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 | ||
| 79 | static 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 | */ |
| 473 | static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | 475 | static 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 | */ | ||
| 3488 | static 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 | */ | ||
| 5561 | static 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 | |||
| 5501 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5599 | SCTP_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; |
