Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Aug 2014 20:26:21 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r270363 - in stable/10: lib/libc/net sys/conf sys/netinet
Message-ID:  <201408222026.s7MKQLWb044832@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408222026.s7MKQLWb044832>