Author: tuexen
Date: Fri Aug 22 20:01:35 2014
New Revision: 270357
URL: http://svnweb.freebsd.org/changeset/base/270357

Log:
  MFC r269448:
  
  Add support for the SCTP_PR_SUPPORTED socket option as specified in
  http://tools.ietf.org/html/draft-ietf-tsvwg-sctp-prpolicies
  Add also a sysctl controlling the default of the end-points.

Modified:
  stable/10/lib/libc/net/sctp_sys_calls.c
  stable/10/sys/netinet/sctp.h
  stable/10/sys/netinet/sctp_indata.c
  stable/10/sys/netinet/sctp_input.c
  stable/10/sys/netinet/sctp_output.c
  stable/10/sys/netinet/sctp_pcb.c
  stable/10/sys/netinet/sctp_pcb.h
  stable/10/sys/netinet/sctp_peeloff.c
  stable/10/sys/netinet/sctp_structs.h
  stable/10/sys/netinet/sctp_sysctl.c
  stable/10/sys/netinet/sctp_sysctl.h
  stable/10/sys/netinet/sctp_timer.c
  stable/10/sys/netinet/sctp_usrreq.c
  stable/10/sys/netinet/sctputil.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/sctp_sys_calls.c
==============================================================================
--- stable/10/lib/libc/net/sctp_sys_calls.c     Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/lib/libc/net/sctp_sys_calls.c     Fri Aug 22 20:01:35 2014        
(r270357)
@@ -353,6 +353,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, i
        case SCTP_ECN_SUPPORTED:
                ((struct sctp_assoc_value *)arg)->assoc_id = id;
                break;
+       case SCTP_PR_SUPPORTED:
+               ((struct sctp_assoc_value *)arg)->assoc_id = id;
+               break;
        case SCTP_MAX_BURST:
                ((struct sctp_assoc_value *)arg)->assoc_id = id;
                break;

Modified: stable/10/sys/netinet/sctp.h
==============================================================================
--- stable/10/sys/netinet/sctp.h        Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp.h        Fri Aug 22 20:01:35 2014        
(r270357)
@@ -122,6 +122,7 @@ struct sctp_paramhdr {
 #define SCTP_PEER_ADDR_THLDS            0x00000023
 #define SCTP_REMOTE_UDP_ENCAPS_PORT     0x00000024
 #define SCTP_ECN_SUPPORTED              0x00000025
+#define SCTP_PR_SUPPORTED               0x00000026
 
 /*
  * read-only options

Modified: stable/10/sys/netinet/sctp_indata.c
==============================================================================
--- stable/10/sys/netinet/sctp_indata.c Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_indata.c Fri Aug 22 20:01:35 2014        
(r270357)
@@ -2960,7 +2960,7 @@ sctp_strike_gap_ack_chunks(struct sctp_t
                                num_dests_sacked++;
                }
        }
-       if (stcb->asoc.peer_supports_prsctp) {
+       if (stcb->asoc.prsctp_supported) {
                (void)SCTP_GETTIME_TIMEVAL(&now);
        }
        TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
@@ -2981,7 +2981,7 @@ sctp_strike_gap_ack_chunks(struct sctp_t
                        /* done */
                        break;
                }
-               if (stcb->asoc.peer_supports_prsctp) {
+               if (stcb->asoc.prsctp_supported) {
                        if ((PR_SCTP_TTL_ENABLED(tp1->flags)) && tp1->sent < 
SCTP_DATAGRAM_ACKED) {
                                /* Is it expired? */
                                if (timevalcmp(&now, &tp1->rec.data.timetodrop, 
>)) {
@@ -3235,7 +3235,7 @@ sctp_strike_gap_ack_chunks(struct sctp_t
                        /* remove from the total flight */
                        sctp_total_flight_decrease(stcb, tp1);
 
-                       if ((stcb->asoc.peer_supports_prsctp) &&
+                       if ((stcb->asoc.prsctp_supported) &&
                            (PR_SCTP_RTX_ENABLED(tp1->flags))) {
                                /*
                                 * Has it been retransmitted tv_sec times? -
@@ -3380,7 +3380,7 @@ sctp_try_advance_peer_ack_point(struct s
        struct timeval now;
        int now_filled = 0;
 
-       if (asoc->peer_supports_prsctp == 0) {
+       if (asoc->prsctp_supported == 0) {
                return (NULL);
        }
        TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
@@ -4042,7 +4042,7 @@ again:
                asoc->advanced_peer_ack_point = cumack;
        }
        /* PR-Sctp issues need to be addressed too */
-       if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) {
+       if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) {
                struct sctp_tmit_chunk *lchk;
                uint32_t old_adv_peer_ack_point;
 
@@ -4479,7 +4479,7 @@ sctp_handle_sack(struct mbuf *m, int off
                        sctp_free_bufspace(stcb, asoc, tp1, 1);
                        sctp_m_freem(tp1->data);
                        tp1->data = NULL;
-                       if (asoc->peer_supports_prsctp && 
PR_SCTP_BUF_ENABLED(tp1->flags)) {
+                       if (asoc->prsctp_supported && 
PR_SCTP_BUF_ENABLED(tp1->flags)) {
                                asoc->sent_queue_cnt_removeable--;
                        }
                }
@@ -4891,7 +4891,7 @@ again:
                asoc->advanced_peer_ack_point = cum_ack;
        }
        /* C2. try to further move advancedPeerAckPoint ahead */
-       if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) {
+       if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) {
                struct sctp_tmit_chunk *lchk;
                uint32_t old_adv_peer_ack_point;
 

Modified: stable/10/sys/netinet/sctp_input.c
==============================================================================
--- stable/10/sys/netinet/sctp_input.c  Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_input.c  Fri Aug 22 20:01:35 2014        
(r270357)
@@ -1082,7 +1082,7 @@ sctp_process_unrecog_chunk(struct sctp_t
                sctp_asconf_cleanup(stcb, net);
                break;
        case SCTP_FORWARD_CUM_TSN:
-               stcb->asoc.peer_supports_prsctp = 0;
+               stcb->asoc.prsctp_supported = 0;
                break;
        default:
                SCTPDBG(SCTP_DEBUG_INPUT2,
@@ -1106,7 +1106,7 @@ sctp_process_unrecog_param(struct sctp_t
        switch (ntohs(pbad->param_type)) {
                /* pr-sctp draft */
        case SCTP_PRSCTP_SUPPORTED:
-               stcb->asoc.peer_supports_prsctp = 0;
+               stcb->asoc.prsctp_supported = 0;
                break;
        case SCTP_SUPPORTED_CHUNK_EXT:
                break;
@@ -2786,6 +2786,7 @@ sctp_handle_cookie_echo(struct mbuf *m, 
                        inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
                        inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
                        inp->ecn_supported = (*inp_p)->ecn_supported;
+                       inp->prsctp_supported = (*inp_p)->prsctp_supported;
                        inp->partial_delivery_point = 
(*inp_p)->partial_delivery_point;
                        inp->sctp_context = (*inp_p)->sctp_context;
                        inp->local_strreset_support = 
(*inp_p)->local_strreset_support;

Modified: stable/10/sys/netinet/sctp_output.c
==============================================================================
--- stable/10/sys/netinet/sctp_output.c Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_output.c Fri Aug 22 20:01:35 2014        
(r270357)
@@ -4792,13 +4792,14 @@ sctp_send_initiate(struct sctp_inpcb *in
                ph->param_length = htons(parameter_len);
                chunk_len += parameter_len;
        }
-       /* And now tell the peer we do support PR-SCTP. */
-       parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
-       ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
-       ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
-       ph->param_length = htons(parameter_len);
-       chunk_len += parameter_len;
-
+       /* PR-SCTP supported parameter */
+       if (stcb->asoc.prsctp_supported == 1) {
+               parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+               ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+               ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
+               ph->param_length = htons(parameter_len);
+               chunk_len += parameter_len;
+       }
        /* Add NAT friendly parameter. */
        if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
                parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
@@ -4813,7 +4814,9 @@ sctp_send_initiate(struct sctp_inpcb *in
        pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
        pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
        pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
-       pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+       if (stcb->asoc.prsctp_supported == 1) {
+               pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+       }
        pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
        pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
        if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
@@ -5890,13 +5893,15 @@ do_a_abort:
                ph->param_length = htons(parameter_len);
                chunk_len += parameter_len;
        }
-       /* And now tell the peer we do pr-sctp */
-       parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
-       ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
-       ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
-       ph->param_length = htons(parameter_len);
-       chunk_len += parameter_len;
-
+       /* PR-SCTP supported parameter */
+       if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
+           ((asoc == NULL) && (inp->prsctp_supported == 1))) {
+               parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+               ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+               ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
+               ph->param_length = htons(parameter_len);
+               chunk_len += parameter_len;
+       }
        /* Add NAT friendly parameter */
        if (nat_friendly) {
                parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
@@ -5911,7 +5916,10 @@ do_a_abort:
        pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
        pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
        pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
-       pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+       if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
+           ((asoc == NULL) && (inp->prsctp_supported == 1))) {
+               pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+       }
        pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
        pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
        if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
@@ -6093,7 +6101,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
        struct sctp_tmit_chunk *chk, *nchk;
 
        SCTP_TCB_LOCK_ASSERT(stcb);
-       if ((asoc->peer_supports_prsctp) &&
+       if ((asoc->prsctp_supported) &&
            (asoc->sent_queue_cnt_removeable > 0)) {
                TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
                        /*
@@ -12948,7 +12956,7 @@ skip_preblock:
                                continue;
                        }
                        /* PR-SCTP? */
-                       if ((asoc->peer_supports_prsctp) && 
(asoc->sent_queue_cnt_removeable > 0)) {
+                       if ((asoc->prsctp_supported) && 
(asoc->sent_queue_cnt_removeable > 0)) {
                                /*
                                 * This is ugly but we must assure locking
                                 * order

Modified: stable/10/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.c    Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_pcb.c    Fri Aug 22 20:01:35 2014        
(r270357)
@@ -2484,6 +2484,7 @@ sctp_inpcb_alloc(struct socket *so, uint
        inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
        inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
        inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable);
+       inp->prsctp_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pr_enable);
        /* init the small hash table we use to track asocid <-> tcb */
        inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, 
&inp->hashasocidmark);
        if (inp->sctp_asocidhash == NULL) {
@@ -6082,6 +6083,7 @@ sctp_load_addresses_from_init(struct sct
        uint32_t keylen;
        int got_random = 0, got_hmacs = 0, got_chklist = 0;
        uint8_t ecn_supported;
+       uint8_t prsctp_supported;
 
 #ifdef INET
        struct sockaddr_in sin;
@@ -6112,6 +6114,7 @@ sctp_load_addresses_from_init(struct sct
        }
        /* Turn off ECN until we get through all params */
        ecn_supported = 0;
+       prsctp_supported = 0;
        TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
                /* mark all addresses that we have currently on the list */
                net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
@@ -6436,7 +6439,7 @@ sctp_load_addresses_from_init(struct sct
                        stcb->asoc.peer_supports_nat = 1;
                } else if (ptype == SCTP_PRSCTP_SUPPORTED) {
                        /* Peer supports pr-sctp */
-                       stcb->asoc.peer_supports_prsctp = 1;
+                       prsctp_supported = 1;
                } else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
                        /* A supported extension chunk */
                        struct sctp_supported_chunk_types_param *pr_supported;
@@ -6449,7 +6452,6 @@ sctp_load_addresses_from_init(struct sct
                                return (-25);
                        }
                        stcb->asoc.peer_supports_asconf = 0;
-                       stcb->asoc.peer_supports_prsctp = 0;
                        stcb->asoc.peer_supports_pktdrop = 0;
                        stcb->asoc.peer_supports_strreset = 0;
                        stcb->asoc.peer_supports_nr_sack = 0;
@@ -6463,7 +6465,7 @@ sctp_load_addresses_from_init(struct sct
                                        stcb->asoc.peer_supports_asconf = 1;
                                        break;
                                case SCTP_FORWARD_CUM_TSN:
-                                       stcb->asoc.peer_supports_prsctp = 1;
+                                       prsctp_supported = 1;
                                        break;
                                case SCTP_PACKET_DROPPED:
                                        stcb->asoc.peer_supports_pktdrop = 1;
@@ -6613,6 +6615,7 @@ next_param:
                }
        }
        stcb->asoc.ecn_supported &= ecn_supported;
+       stcb->asoc.prsctp_supported &= prsctp_supported;
        /* validate authentication required parameters */
        if (got_random && got_hmacs) {
                stcb->asoc.peer_supports_auth = 1;

Modified: stable/10/sys/netinet/sctp_pcb.h
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.h    Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_pcb.h    Fri Aug 22 20:01:35 2014        
(r270357)
@@ -407,6 +407,7 @@ struct sctp_inpcb {
        uint8_t local_strreset_support;
        uint32_t sctp_cmt_on_off;
        uint8_t ecn_supported;
+       uint8_t prsctp_supported;
        struct sctp_nonpad_sndrcvinfo def_send;
        /*-
         * These three are here for the sosend_dgram

Modified: stable/10/sys/netinet/sctp_peeloff.c
==============================================================================
--- stable/10/sys/netinet/sctp_peeloff.c        Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_peeloff.c        Fri Aug 22 20:01:35 2014        
(r270357)
@@ -119,6 +119,7 @@ sctp_do_peeloff(struct socket *head, str
        n_inp->sctp_frag_point = inp->sctp_frag_point;
        n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
        n_inp->ecn_supported = inp->ecn_supported;
+       n_inp->prsctp_supported = inp->prsctp_supported;
        n_inp->partial_delivery_point = inp->partial_delivery_point;
        n_inp->sctp_context = inp->sctp_context;
        n_inp->local_strreset_support = inp->local_strreset_support;

Modified: stable/10/sys/netinet/sctp_structs.h
==============================================================================
--- stable/10/sys/netinet/sctp_structs.h        Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_structs.h        Fri Aug 22 20:01:35 2014        
(r270357)
@@ -1150,8 +1150,9 @@ struct sctp_association {
         * sum is updated as well.
         */
 
-       /* Flag to tell if ECN is allowed */
+       /* Flags whether an extension is supported or not */
        uint8_t ecn_supported;
+       uint8_t prsctp_supported;
 
        /* Did the peer make the stream config (add out) request */
        uint8_t peer_req_out;
@@ -1160,8 +1161,6 @@ struct sctp_association {
        uint8_t peer_supports_asconf;
        /* EY - flag to indicate if peer can do nr_sack */
        uint8_t peer_supports_nr_sack;
-       /* pr-sctp support flag */
-       uint8_t peer_supports_prsctp;
        /* peer authentication support flag */
        uint8_t peer_supports_auth;
        /* stream resets are supported by the peer */

Modified: stable/10/sys/netinet/sctp_sysctl.c
==============================================================================
--- stable/10/sys/netinet/sctp_sysctl.c Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_sysctl.c Fri Aug 22 20:01:35 2014        
(r270357)
@@ -55,6 +55,7 @@ sctp_init_sysctls()
        SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = 
SCTPCTL_MULTIPLEASCONFS_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
+       SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
        SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
@@ -602,6 +603,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
                RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), 
SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), 
SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), 
SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
+               RANGECHK(SCTP_BASE_SYSCTL(sctp_pr_enable), 
SCTPCTL_PR_ENABLE_MIN, SCTPCTL_PR_ENABLE_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), 
SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), 
SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
                RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), 
SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
@@ -863,6 +865,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT
     &SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, "IU",
     SCTPCTL_ECN_ENABLE_DESC);
 
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pr_enable, CTLTYPE_UINT | 
CTLFLAG_RW,
+    &SCTP_BASE_SYSCTL(sctp_pr_enable), 0, sysctl_sctp_check, "IU",
+    SCTPCTL_PR_ENABLE_DESC);
+
 SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | 
CTLFLAG_RW,
     &SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU",
     SCTPCTL_STRICT_SACKS_DESC);

Modified: stable/10/sys/netinet/sctp_sysctl.h
==============================================================================
--- stable/10/sys/netinet/sctp_sysctl.h Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_sysctl.h Fri Aug 22 20:01:35 2014        
(r270357)
@@ -45,6 +45,7 @@ struct sctp_sysctl {
        uint32_t sctp_auto_asconf;
        uint32_t sctp_multiple_asconfs;
        uint32_t sctp_ecn_enable;
+       uint32_t sctp_pr_enable;
        uint32_t sctp_fr_max_burst_default;
        uint32_t sctp_strict_sacks;
        uint32_t sctp_peer_chunk_oh;
@@ -154,6 +155,12 @@ struct sctp_sysctl {
 #define SCTPCTL_ECN_ENABLE_MAX         1
 #define SCTPCTL_ECN_ENABLE_DEFAULT     1
 
+/* pr_enable: Enable PR-SCTP */
+#define SCTPCTL_PR_ENABLE_DESC         "Enable PR-SCTP"
+#define SCTPCTL_PR_ENABLE_MIN          0
+#define SCTPCTL_PR_ENABLE_MAX          1
+#define SCTPCTL_PR_ENABLE_DEFAULT      1
+
 /* strict_sacks: Enable SCTP Strict SACK checking */
 #define SCTPCTL_STRICT_SACKS_DESC      "Enable SCTP Strict SACK checking"
 #define SCTPCTL_STRICT_SACKS_MIN       0

Modified: stable/10/sys/netinet/sctp_timer.c
==============================================================================
--- stable/10/sys/netinet/sctp_timer.c  Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_timer.c  Fri Aug 22 20:01:35 2014        
(r270357)
@@ -445,7 +445,7 @@ sctp_recover_sent_list(struct sctp_tcb *
                                sctp_free_bufspace(stcb, asoc, chk, 1);
                                sctp_m_freem(chk->data);
                                chk->data = NULL;
-                               if (asoc->peer_supports_prsctp && 
PR_SCTP_BUF_ENABLED(chk->flags)) {
+                               if (asoc->prsctp_supported && 
PR_SCTP_BUF_ENABLED(chk->flags)) {
                                        asoc->sent_queue_cnt_removeable--;
                                }
                        }
@@ -600,7 +600,7 @@ start_again:
                                        continue;
                                }
                        }
-                       if (stcb->asoc.peer_supports_prsctp && 
PR_SCTP_TTL_ENABLED(chk->flags)) {
+                       if (stcb->asoc.prsctp_supported && 
PR_SCTP_TTL_ENABLED(chk->flags)) {
                                /* Is it expired? */
                                if (timevalcmp(&now, &chk->rec.data.timetodrop, 
>)) {
                                        /* Yes so drop it */
@@ -614,7 +614,7 @@ start_again:
                                        continue;
                                }
                        }
-                       if (stcb->asoc.peer_supports_prsctp && 
PR_SCTP_RTX_ENABLED(chk->flags)) {
+                       if (stcb->asoc.prsctp_supported && 
PR_SCTP_RTX_ENABLED(chk->flags)) {
                                /* Has it been retransmitted tv_sec times? */
                                if (chk->snd_count > 
chk->rec.data.timetodrop.tv_sec) {
                                        if (chk->data) {
@@ -957,7 +957,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
                sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
                return (0);
        }
-       if (stcb->asoc.peer_supports_prsctp) {
+       if (stcb->asoc.prsctp_supported) {
                struct sctp_tmit_chunk *lchk;
 
                lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);

Modified: stable/10/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/10/sys/netinet/sctp_usrreq.c Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctp_usrreq.c Fri Aug 22 20:01:35 2014        
(r270357)
@@ -3321,6 +3321,33 @@ flags_out:
                        }
                        break;
                }
+       case SCTP_PR_SUPPORTED:
+               {
+                       struct sctp_assoc_value *av;
+
+                       SCTP_CHECK_AND_CAST(av, optval, struct 
sctp_assoc_value, *optsize);
+                       SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+                       if (stcb) {
+                               av->assoc_value = stcb->asoc.prsctp_supported;
+                               SCTP_TCB_UNLOCK(stcb);
+                       } else {
+                               if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) 
||
+                                   (inp->sctp_flags & 
SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                                   (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                                       SCTP_INP_RLOCK(inp);
+                                       av->assoc_value = inp->prsctp_supported;
+                                       SCTP_INP_RUNLOCK(inp);
+                               } else {
+                                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
+                                       error = EINVAL;
+                               }
+                       }
+                       if (error == 0) {
+                               *optsize = sizeof(struct sctp_assoc_value);
+                       }
+                       break;
+               }
        case SCTP_ENABLE_STREAM_RESET:
                {
                        struct sctp_assoc_value *av;
@@ -5913,6 +5940,35 @@ sctp_setopt(struct socket *so, int optna
                        }
                        break;
                }
+       case SCTP_PR_SUPPORTED:
+               {
+                       struct sctp_assoc_value *av;
+
+                       SCTP_CHECK_AND_CAST(av, optval, struct 
sctp_assoc_value, optsize);
+                       SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+                       if (stcb) {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                               SCTP_TCB_UNLOCK(stcb);
+                       } else {
+                               if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) 
||
+                                   (inp->sctp_flags & 
SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                                   (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                                       SCTP_INP_WLOCK(inp);
+                                       if (av->assoc_value == 0) {
+                                               inp->prsctp_supported = 0;
+                                       } else {
+                                               inp->prsctp_supported = 1;
+                                       }
+                                       SCTP_INP_WUNLOCK(inp);
+                               } else {
+                                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
+                                       error = EINVAL;
+                               }
+                       }
+                       break;
+               }
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
ENOPROTOOPT);
                error = ENOPROTOOPT;

Modified: stable/10/sys/netinet/sctputil.c
==============================================================================
--- stable/10/sys/netinet/sctputil.c    Fri Aug 22 19:57:39 2014        
(r270356)
+++ stable/10/sys/netinet/sctputil.c    Fri Aug 22 20:01:35 2014        
(r270357)
@@ -905,6 +905,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
        asoc->cookie_life = inp->sctp_ep.def_cookie_life;
        asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
        asoc->ecn_supported = inp->ecn_supported;
+       asoc->prsctp_supported = inp->prsctp_supported;
        asoc->sctp_nr_sack_on_off = (uint8_t) 
SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
        asoc->sctp_cmt_pf = (uint8_t) 0;
        asoc->sctp_frag_point = inp->sctp_frag_point;
@@ -2620,7 +2621,7 @@ sctp_notify_assoc_change(uint16_t state,
                if (notif_len > sizeof(struct sctp_assoc_change)) {
                        if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) 
{
                                i = 0;
-                               if (stcb->asoc.peer_supports_prsctp) {
+                               if (stcb->asoc.prsctp_supported) {
                                        sac->sac_info[i++] = 
SCTP_ASSOC_SUPPORTS_PR;
                                }
                                if (stcb->asoc.peer_supports_auth) {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to