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

Log:
  MFC r269945:
  
  Add support for the SCTP_PR_STREAM_STATUS and SCTP_PR_ASSOC_STATUS
  socket options. This includes managing the correspoing stat counters.
  Add the SCTP_DETAILED_STR_STATS kernel option to control per policy
  counters on every stream. The default is off and only an aggregated
  counter is available. This is sufficient for the RTCWeb usecase.

Modified:
  stable/10/lib/libc/net/sctp_sys_calls.c
  stable/10/sys/conf/options
  stable/10/sys/netinet/sctp.h
  stable/10/sys/netinet/sctp_input.c
  stable/10/sys/netinet/sctp_output.c
  stable/10/sys/netinet/sctp_structs.h
  stable/10/sys/netinet/sctp_uio.h
  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 20:22:12 2014        
(r270362)
+++ stable/10/lib/libc/net/sctp_sys_calls.c     Fri Aug 22 20:26:20 2014        
(r270363)
@@ -377,6 +377,12 @@ sctp_opt_info(int sd, sctp_assoc_t id, i
        case SCTP_ENABLE_STREAM_RESET:
                ((struct sctp_assoc_value *)arg)->assoc_id = id;
                break;
+       case SCTP_PR_STREAM_STATUS:
+               ((struct sctp_prstatus *)arg)->sprstat_assoc_id = id;
+               break;
+       case SCTP_PR_ASSOC_STATUS:
+               ((struct sctp_prstatus *)arg)->sprstat_assoc_id = id;
+               break;
        default:
                break;
        }

Modified: stable/10/sys/conf/options
==============================================================================
--- stable/10/sys/conf/options  Fri Aug 22 20:22:12 2014        (r270362)
+++ stable/10/sys/conf/options  Fri Aug 22 20:26:20 2014        (r270363)
@@ -459,6 +459,7 @@ SCTP_LTRACE_ERRORS  opt_sctp.h # Log to K
 SCTP_USE_PERCPU_STAT   opt_sctp.h # Use per cpu stats.
 SCTP_MCORE_INPUT       opt_sctp.h # Have multiple input threads for input mbufs
 SCTP_LOCAL_TRACE_BUF   opt_sctp.h # Use tracebuffer exported via sysctl
+SCTP_DETAILED_STR_STATS        opt_sctp.h # Use per PR-SCTP policy stream stats
 #
 #
 #

Modified: stable/10/sys/netinet/sctp.h
==============================================================================
--- stable/10/sys/netinet/sctp.h        Fri Aug 22 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctp.h        Fri Aug 22 20:26:20 2014        
(r270363)
@@ -140,6 +140,8 @@ struct sctp_paramhdr {
 #define SCTP_GET_ASSOC_NUMBER           0x00000104     /* ro */
 #define SCTP_GET_ASSOC_ID_LIST          0x00000105     /* ro */
 #define SCTP_TIMEOUTS                   0x00000106
+#define SCTP_PR_STREAM_STATUS           0x00000107
+#define SCTP_PR_ASSOC_STATUS            0x00000108
 
 /*
  * user socket options: BSD implementation specific

Modified: stable/10/sys/netinet/sctp_input.c
==============================================================================
--- stable/10/sys/netinet/sctp_input.c  Fri Aug 22 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctp_input.c  Fri Aug 22 20:26:20 2014        
(r270363)
@@ -1469,6 +1469,11 @@ sctp_process_cookie_existing(struct mbuf
        int spec_flag = 0;
        uint32_t how_indx;
 
+#if defined(SCTP_DETAILED_STR_STATS)
+       int j;
+
+#endif
+
        net = *netp;
        /* I know that the TCB is non-NULL from the caller */
        asoc = &stcb->asoc;
@@ -1931,6 +1936,15 @@ sctp_process_cookie_existing(struct mbuf
                sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
                for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
                        stcb->asoc.strmout[i].chunks_on_queues = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+                       for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
+                               asoc->strmout[i].abandoned_sent[j] = 0;
+                               asoc->strmout[i].abandoned_unsent[j] = 0;
+                       }
+#else
+                       asoc->strmout[i].abandoned_sent[0] = 0;
+                       asoc->strmout[i].abandoned_unsent[0] = 0;
+#endif
                        stcb->asoc.strmout[i].stream_no = i;
                        stcb->asoc.strmout[i].next_sequence_send = 0;
                        stcb->asoc.strmout[i].last_msg_incomplete = 0;

Modified: stable/10/sys/netinet/sctp_output.c
==============================================================================
--- stable/10/sys/netinet/sctp_output.c Fri Aug 22 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctp_output.c Fri Aug 22 20:26:20 2014        
(r270363)
@@ -3618,6 +3618,11 @@ sctp_process_cmsgs_for_init(struct sctp_
                                        struct sctp_stream_out *tmp_str;
                                        unsigned int i;
 
+#if defined(SCTP_DETAILED_STR_STATS)
+                                       int j;
+
+#endif
+
                                        /* Default is NOT correct */
                                        SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, 
default:%d pre_open:%d\n",
                                            stcb->asoc.streamoutcnt, 
stcb->asoc.pre_open_streams);
@@ -3638,6 +3643,15 @@ sctp_process_cmsgs_for_init(struct sctp_
                                                
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
                                                
stcb->asoc.strmout[i].chunks_on_queues = 0;
                                                
stcb->asoc.strmout[i].next_sequence_send = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+                                               for (j = 0; j < 
SCTP_PR_SCTP_MAX + 1; j++) {
+                                                       
stcb->asoc.strmout[i].abandoned_sent[j] = 0;
+                                                       
stcb->asoc.strmout[i].abandoned_unsent[j] = 0;
+                                               }
+#else
+                                               
stcb->asoc.strmout[i].abandoned_sent[0] = 0;
+                                               
stcb->asoc.strmout[i].abandoned_unsent[0] = 0;
+#endif
                                                stcb->asoc.strmout[i].stream_no 
= i;
                                                
stcb->asoc.strmout[i].last_msg_incomplete = 0;
                                                
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
@@ -11923,6 +11937,11 @@ sctp_send_str_reset_req(struct sctp_tcb 
                struct sctp_stream_queue_pending *sp, *nsp;
                int i;
 
+#if defined(SCTP_DETAILED_STR_STATS)
+               int j;
+
+#endif
+
                oldstream = stcb->asoc.strmout;
                /* get some more */
                SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
@@ -11968,6 +11987,15 @@ sctp_send_str_reset_req(struct sctp_tcb 
                for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt 
+ adding_o); i++) {
                        TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
                        stcb->asoc.strmout[i].chunks_on_queues = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+                       for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
+                               stcb->asoc.strmout[i].abandoned_sent[j] = 0;
+                               stcb->asoc.strmout[i].abandoned_unsent[j] = 0;
+                       }
+#else
+                       stcb->asoc.strmout[i].abandoned_sent[0] = 0;
+                       stcb->asoc.strmout[i].abandoned_unsent[0] = 0;
+#endif
                        stcb->asoc.strmout[i].next_sequence_send = 0x0;
                        stcb->asoc.strmout[i].stream_no = i;
                        stcb->asoc.strmout[i].last_msg_incomplete = 0;

Modified: stable/10/sys/netinet/sctp_structs.h
==============================================================================
--- stable/10/sys/netinet/sctp_structs.h        Fri Aug 22 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctp_structs.h        Fri Aug 22 20:26:20 2014        
(r270363)
@@ -587,6 +587,14 @@ struct sctp_stream_out {
        struct sctp_streamhead outqueue;
        union scheduling_parameters ss_params;
        uint32_t chunks_on_queues;
+#if defined(SCTP_DETAILED_STR_STATS)
+       uint32_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1];
+       uint32_t abandoned_sent[SCTP_PR_SCTP_MAX + 1];
+#else
+       /* Only the aggregation */
+       uint32_t abandoned_unsent[1];
+       uint32_t abandoned_sent[1];
+#endif
        uint16_t stream_no;
        uint16_t next_sequence_send;    /* next one I expect to send out */
        uint8_t last_msg_incomplete;
@@ -1211,6 +1219,8 @@ struct sctp_association {
        uint32_t timoshutdownack;
        struct timeval start_time;
        struct timeval discontinuity_time;
+       uint64_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1];
+       uint64_t abandoned_sent[SCTP_PR_SCTP_MAX + 1];
 };
 
 #endif

Modified: stable/10/sys/netinet/sctp_uio.h
==============================================================================
--- stable/10/sys/netinet/sctp_uio.h    Fri Aug 22 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctp_uio.h    Fri Aug 22 20:26:20 2014        
(r270363)
@@ -249,18 +249,23 @@ struct sctp_snd_all_completes {
                                        SCTP_SACK_IMMEDIATELY)) != 0)
 /* for the endpoint */
 
-/* The lower byte is an enumeration of PR-SCTP policies */
+/* The lower four bits is an enumeration of PR-SCTP policies */
 #define SCTP_PR_SCTP_NONE 0x0000/* Reliable transfer */
 #define SCTP_PR_SCTP_TTL  0x0001/* Time based PR-SCTP */
 #define SCTP_PR_SCTP_BUF  0x0002/* Buffer based PR-SCTP */
 #define SCTP_PR_SCTP_RTX  0x0003/* Number of retransmissions based PR-SCTP */
+#define SCTP_PR_SCTP_MAX  SCTP_PR_SCTP_RTX
+#define SCTP_PR_SCTP_ALL  0x000f/* Used for aggregated stats */
 
 #define PR_SCTP_POLICY(x)         ((x) & 0x0f)
-#define PR_SCTP_ENABLED(x)        (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE)
+#define PR_SCTP_ENABLED(x)        ((PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE) && 
\
+                                   (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_ALL))
 #define PR_SCTP_TTL_ENABLED(x)    (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL)
 #define PR_SCTP_BUF_ENABLED(x)    (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF)
 #define PR_SCTP_RTX_ENABLED(x)    (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX)
-#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_RTX)
+#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_MAX)
+#define PR_SCTP_VALID_POLICY(x)   (PR_SCTP_POLICY(x) <= SCTP_PR_SCTP_MAX)
+
 /* Stat's */
 struct sctp_pcbinfo {
        uint32_t ep_count;
@@ -720,6 +725,14 @@ struct sctp_udpencaps {
        uint16_t sue_port;
 };
 
+struct sctp_prstatus {
+       sctp_assoc_t sprstat_assoc_id;
+       uint16_t sprstat_sid;
+       uint16_t sprstat_policy;
+       uint64_t sprstat_abandoned_unsent;
+       uint64_t sprstat_abandoned_sent;
+};
+
 struct sctp_cwnd_args {
        struct sctp_nets *net;  /* network to *//* FIXME: LP64 issue */
        uint32_t cwnd_new_value;/* cwnd in k */

Modified: stable/10/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/10/sys/netinet/sctp_usrreq.c Fri Aug 22 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctp_usrreq.c Fri Aug 22 20:26:20 2014        
(r270363)
@@ -3510,6 +3510,72 @@ flags_out:
                        }
                        break;
                }
+       case SCTP_PR_STREAM_STATUS:
+               {
+                       struct sctp_prstatus *sprstat;
+                       uint16_t sid;
+                       uint16_t policy;
+
+                       SCTP_CHECK_AND_CAST(sprstat, optval, struct 
sctp_prstatus, *optsize);
+                       SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
+
+                       sid = sprstat->sprstat_sid;
+                       policy = sprstat->sprstat_policy;
+#if defined(SCTP_DETAILED_STR_STATS)
+                       if ((stcb != NULL) &&
+                           (policy != SCTP_PR_SCTP_NONE) &&
+                           (sid < stcb->asoc.streamoutcnt) &&
+                           ((policy == SCTP_PR_SCTP_ALL) ||
+                           (PR_SCTP_VALID_POLICY(policy)))) {
+#else
+                       if ((stcb != NULL) &&
+                           (policy != SCTP_PR_SCTP_NONE) &&
+                           (sid < stcb->asoc.streamoutcnt) &&
+                           (policy == SCTP_PR_SCTP_ALL)) {
+#endif
+                               if (policy == SCTP_PR_SCTP_ALL) {
+                                       sprstat->sprstat_abandoned_unsent = 
stcb->asoc.strmout[sid].abandoned_unsent[0];
+                                       sprstat->sprstat_abandoned_sent = 
stcb->asoc.strmout[sid].abandoned_sent[0];
+                               } else {
+                                       sprstat->sprstat_abandoned_unsent = 
stcb->asoc.strmout[sid].abandoned_unsent[policy];
+                                       sprstat->sprstat_abandoned_sent = 
stcb->asoc.strmout[sid].abandoned_sent[policy];
+                               }
+                               SCTP_TCB_UNLOCK(stcb);
+                               *optsize = sizeof(struct sctp_prstatus);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+                       break;
+               }
+       case SCTP_PR_ASSOC_STATUS:
+               {
+                       struct sctp_prstatus *sprstat;
+                       uint16_t policy;
+
+                       SCTP_CHECK_AND_CAST(sprstat, optval, struct 
sctp_prstatus, *optsize);
+                       SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
+
+                       policy = sprstat->sprstat_policy;
+                       if ((stcb != NULL) &&
+                           (policy != SCTP_PR_SCTP_NONE) &&
+                           ((policy == SCTP_PR_SCTP_ALL) ||
+                           (PR_SCTP_VALID_POLICY(policy)))) {
+                               if (policy == SCTP_PR_SCTP_ALL) {
+                                       sprstat->sprstat_abandoned_unsent = 
stcb->asoc.abandoned_unsent[0];
+                                       sprstat->sprstat_abandoned_sent = 
stcb->asoc.abandoned_sent[0];
+                               } else {
+                                       sprstat->sprstat_abandoned_unsent = 
stcb->asoc.abandoned_unsent[policy];
+                                       sprstat->sprstat_abandoned_sent = 
stcb->asoc.abandoned_sent[policy];
+                               }
+                               SCTP_TCB_UNLOCK(stcb);
+                               *optsize = sizeof(struct sctp_prstatus);
+                       } 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 20:22:12 2014        
(r270362)
+++ stable/10/sys/netinet/sctputil.c    Fri Aug 22 20:26:20 2014        
(r270363)
@@ -896,6 +896,11 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
         */
        int i;
 
+#if defined(SCTP_DETAILED_STR_STATS)
+       int j;
+
+#endif
+
        asoc = &stcb->asoc;
        /* init all variables to a known value. */
        SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
@@ -1056,6 +1061,15 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
                asoc->strmout[i].next_sequence_send = 0x0;
                TAILQ_INIT(&asoc->strmout[i].outqueue);
                asoc->strmout[i].chunks_on_queues = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+               for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
+                       asoc->strmout[i].abandoned_sent[j] = 0;
+                       asoc->strmout[i].abandoned_unsent[j] = 0;
+               }
+#else
+               asoc->strmout[i].abandoned_sent[0] = 0;
+               asoc->strmout[i].abandoned_unsent[0] = 0;
+#endif
                asoc->strmout[i].stream_no = i;
                asoc->strmout[i].last_msg_incomplete = 0;
                asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
@@ -1111,6 +1125,10 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
        asoc->timoshutdownack = 0;
        (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time);
        asoc->discontinuity_time = asoc->start_time;
+       for (i = 0; i < SCTP_PR_SCTP_MAX + 1; i++) {
+               asoc->abandoned_unsent[i] = 0;
+               asoc->abandoned_sent[i] = 0;
+       }
        /*
         * sa_ignore MEMLEAK {memory is put in the assoc mapping array and
         * freed later when the association is freed.
@@ -4713,6 +4731,21 @@ sctp_release_pr_sctp_chunk(struct sctp_t
 
        stream = tp1->rec.data.stream_number;
        seq = tp1->rec.data.stream_seq;
+       if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
+               stcb->asoc.abandoned_sent[0]++;
+               stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
+               stcb->asoc.strmout[stream].abandoned_sent[0]++;
+#if defined(SCTP_DETAILED_STR_STATS)
+               
stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
+#endif
+       } else {
+               stcb->asoc.abandoned_unsent[0]++;
+               stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
+               stcb->asoc.strmout[stream].abandoned_unsent[0]++;
+#if defined(SCTP_DETAILED_STR_STATS)
+               
stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
+#endif
+       }
        do {
                ret_sz += tp1->book_size;
                if (tp1->data != NULL) {
_______________________________________________
[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