changeset 10212:1abfeb13f29b

PSARC 2009/411 API for per endpoint sctp statistics. 6808307 need access to the included SCTP counters
author George Shepherd <George.Shepherd@Sun.COM>
date Thu, 30 Jul 2009 10:07:41 -0700
parents 8b17464a5cbb
children 167616def81b
files usr/src/uts/common/inet/sctp/sctp_asconf.c usr/src/uts/common/inet/sctp/sctp_common.c usr/src/uts/common/inet/sctp/sctp_impl.h usr/src/uts/common/inet/sctp/sctp_input.c usr/src/uts/common/inet/sctp/sctp_opt_data.c usr/src/uts/common/inet/sctp/sctp_output.c usr/src/uts/common/inet/sctp/sctp_timer.c usr/src/uts/common/netinet/sctp.h
diffstat 8 files changed, 127 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/sctp/sctp_asconf.c	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_asconf.c	Thu Jul 30 10:07:41 2009 -0700
@@ -881,7 +881,7 @@
 
 	fp->strikes++;
 	sctp->sctp_strikes++;
-	SCTP_CALC_RXT(fp, sctp->sctp_rto_max);
+	SCTP_CALC_RXT(sctp, fp);
 
 	nfp = sctp_rotate_faddr(sctp, fp);
 	sctp->sctp_cchunk_pend = 0;
--- a/usr/src/uts/common/inet/sctp/sctp_common.c	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_common.c	Thu Jul 30 10:07:41 2009 -0700
@@ -203,6 +203,7 @@
 		if (fp->rto > sctp->sctp_rto_max) {
 			fp->rto = sctp->sctp_rto_max;
 		}
+		SCTP_MAX_RTO(sctp, fp);
 	}
 
 	/*
@@ -1864,6 +1865,7 @@
 	}
 	fp->cwnd = sctps->sctps_slow_start_initial * fp->sfa_pmss;
 	fp->rto = MIN(sctp->sctp_rto_initial, sctp->sctp_init_rto_max);
+	SCTP_MAX_RTO(sctp, fp);
 	fp->srtt = -1;
 	fp->rtt_updates = 0;
 	fp->strikes = 0;
--- a/usr/src/uts/common/inet/sctp/sctp_impl.h	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_impl.h	Thu Jul 30 10:07:41 2009 -0700
@@ -167,10 +167,24 @@
 		(fp)->timer_running = 0;		\
 	}
 
-#define	SCTP_CALC_RXT(fp, max)		\
-{					\
-	if (((fp)->rto <<= 1) > (max))	\
-		(fp)->rto = (max);	\
+/* For per endpoint association statistics */
+#define	SCTP_MAX_RTO(sctp, fp) {			\
+	/*						\
+	 * Record the maximum observed RTO,		\
+	 * sctp_maxrto is zeroed elsewhere		\
+	 * at the end of each stats request.		\
+	 */						\
+	(sctp)->sctp_maxrto =				\
+	    MAX((sctp)->sctp_maxrto, (fp)->rto);	\
+	DTRACE_PROBE2(sctp__maxrto, sctp_t *,		\
+	    sctp, struct sctp_faddr_s, fp);		\
+}
+
+#define	SCTP_CALC_RXT(sctp, fp)				\
+{							\
+	if (((fp)->rto <<= 1) > (sctp)->sctp_rto_max)	\
+		(fp)->rto = (sctp)->sctp_rto_max;	\
+	SCTP_MAX_RTO(sctp, fp);				\
 }
 
 
@@ -938,6 +952,25 @@
 
 	pid_t		sctp_cpid;	/* Process id when this was opened */
 	uint64_t	sctp_open_time;	/* time when this was opened */
+
+	/* additional source data for per endpoint association statistics */
+	uint64_t	sctp_outseqtsns;	/* TSN rx > expected TSN */
+	uint64_t	sctp_osacks;		/* total sacks sent */
+	uint64_t	sctp_isacks;		/* total sacks received */
+	uint64_t	sctp_idupchunks;	/* rx dups, ord or unord */
+	uint64_t	sctp_gapcnt;		/* total gap acks rx */
+
+	/*
+	 * When non-zero, this is the maximum observed RTO since assoc stats
+	 * were last requested. When zero, no RTO update has occurred since
+	 * the previous user request for stats on this endpoint.
+	 */
+	int	sctp_maxrto;
+	/*
+	 * The stored value of sctp_maxrto passed to user during the previous
+	 * user request for stats on this endpoint.
+	 */
+	int	sctp_prev_maxrto;
 } sctp_t;
 
 #define	SCTP_TXQ_LEN(sctp)	((sctp)->sctp_unsent + (sctp)->sctp_unacked)
--- a/usr/src/uts/common/inet/sctp/sctp_input.c	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_input.c	Thu Jul 30 10:07:41 2009 -0700
@@ -1201,6 +1201,7 @@
 			(sctp)->sctp_force_sack = 1;			\
 	} else if (SEQ_GT(tsn, sctp->sctp_ftsn)) {			\
 		/* Got a gap; record it */				\
+		BUMP_LOCAL(sctp->sctp_outseqtsns);			\
 		dprint(2, ("data_chunk: acking gap %x\n", tsn));	\
 		sctp_ack_add(&sctp->sctp_sack_info, tsn,		\
 		    &sctp->sctp_sack_gaps);				\
@@ -1217,6 +1218,7 @@
 	/* Check for duplicates */
 	if (SEQ_LT(tsn, sctp->sctp_ftsn)) {
 		dprint(4, ("sctp_data_chunk: dropping duplicate\n"));
+		BUMP_LOCAL(sctp->sctp_idupchunks);
 		sctp->sctp_force_sack = 1;
 		sctp_add_dup(dc->sdh_tsn, dups);
 		return;
@@ -1230,6 +1232,7 @@
 				dprint(4,
 				    ("sctp_data_chunk: dropping dup > "
 				    "cumtsn\n"));
+				BUMP_LOCAL(sctp->sctp_idupchunks);
 				sctp->sctp_force_sack = 1;
 				sctp_add_dup(dc->sdh_tsn, dups);
 				return;
@@ -1617,6 +1620,7 @@
 	}
 
 	BUMP_LOCAL(sctp->sctp_obchunks);
+	BUMP_LOCAL(sctp->sctp_osacks);
 }
 
 mblk_t *
@@ -2514,6 +2518,7 @@
 	sctp_stack_t		*sctps = sctp->sctp_sctps;
 
 	BUMP_LOCAL(sctp->sctp_ibchunks);
+	BUMP_LOCAL(sctp->sctp_isacks);
 	chunklen = ntohs(sch->sch_len);
 	if (chunklen < (sizeof (*sch) + sizeof (*sc)))
 		return (0);
@@ -2574,6 +2579,7 @@
 			 */
 			fp = sctp->sctp_current;
 			fp->rto = fp->srtt + 4 * fp->rttvar;
+			SCTP_MAX_RTO(sctp, fp);
 			/* Resend the ZWP */
 			pkt = sctp_rexmit_packet(sctp, &meta, &mp1, fp,
 			    &pkt_len);
@@ -2596,6 +2602,7 @@
 			 */
 			fp = sctp->sctp_current;
 			fp->rto = fp->srtt + 4 * fp->rttvar;
+			SCTP_MAX_RTO(sctp, fp);
 			sctp->sctp_zero_win_probe = B_FALSE;
 			/* This is probably not required */
 			if (!sctp->sctp_rexmitting) {
@@ -2615,6 +2622,7 @@
 		}
 	}
 	num_gaps = ntohs(sc->ssc_numfrags);
+	UPDATE_LOCAL(sctp->sctp_gapcnt, num_gaps);
 	if (num_gaps == 0 || mp == NULL || !SCTP_CHUNK_ISSENT(mp) ||
 	    chunklen < (sizeof (*sch) + sizeof (*sc) +
 	    num_gaps * sizeof (*ssf))) {
--- a/usr/src/uts/common/inet/sctp/sctp_opt_data.c	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_opt_data.c	Thu Jul 30 10:07:41 2009 -0700
@@ -884,6 +884,53 @@
 		case SCTP_PRSCTP:
 			*i1 = sctp->sctp_prsctp_aware ? 1 : 0;
 			break;
+
+		case SCTP_GET_ASSOC_STATS: {
+			sctp_assoc_stats_t *sas;
+
+			if (buflen < sizeof (sctp_assoc_stats_t)) {
+				retval = EINVAL;
+				break;
+			}
+
+			sas = (sctp_assoc_stats_t *)ptr;
+
+			/*
+			 * Copy the current stats to the stats struct.
+			 */
+			sas->sas_rtxchunks =  sctp->sctp_rxtchunks;
+			sas->sas_gapcnt = sctp->sctp_gapcnt;
+			sas->sas_outseqtsns = sctp->sctp_outseqtsns;
+			sas->sas_osacks = sctp->sctp_osacks;
+			sas->sas_isacks = sctp->sctp_isacks;
+			sas->sas_octrlchunks = sctp->sctp_obchunks;
+			sas->sas_ictrlchunks = sctp->sctp_ibchunks;
+			sas->sas_oodchunks = sctp->sctp_odchunks;
+			sas->sas_iodchunks = sctp->sctp_idchunks;
+			sas->sas_ouodchunks = sctp->sctp_oudchunks;
+			sas->sas_iuodchunks = sctp->sctp_iudchunks;
+			sas->sas_idupchunks = sctp->sctp_idupchunks;
+
+			/*
+			 * Copy out the maximum observed RTO since the
+			 * time this data was last requested
+			 */
+			if (sctp->sctp_maxrto == 0) {
+				/* unchanged during obervation period */
+				sas->sas_maxrto = sctp->sctp_prev_maxrto;
+			} else {
+				/* record new period maximum */
+				sas->sas_maxrto = sctp->sctp_maxrto;
+			}
+			/* Record the value sent to the user this period */
+			sctp->sctp_prev_maxrto = sas->sas_maxrto;
+
+			/* Mark beginning of a new observation period */
+			sctp->sctp_maxrto = 0;
+
+			*optlen = sizeof (sctp_assoc_stats_t);
+			break;
+		}
 		case SCTP_I_WANT_MAPPED_V4_ADDR:
 		case SCTP_MAXSEG:
 		case SCTP_DISABLE_FRAGMENTS:
--- a/usr/src/uts/common/inet/sctp/sctp_output.c	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_output.c	Thu Jul 30 10:07:41 2009 -0700
@@ -1817,7 +1817,7 @@
 		oldfp->strikes++;
 		sctp->sctp_strikes++;
 
-		SCTP_CALC_RXT(oldfp, sctp->sctp_rto_max);
+		SCTP_CALC_RXT(sctp, oldfp);
 		if (oldfp != fp && oldfp->suna != 0)
 			SCTP_FADDR_TIMER_RESTART(sctp, oldfp, fp->rto);
 		SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto);
@@ -2032,7 +2032,7 @@
 restart_timer:
 	oldfp->strikes++;
 	sctp->sctp_strikes++;
-	SCTP_CALC_RXT(oldfp, sctp->sctp_rto_max);
+	SCTP_CALC_RXT(sctp, oldfp);
 	/*
 	 * If there is still some data in the oldfp, restart the
 	 * retransmission timer.  If there is no data, the heartbeat will
--- a/usr/src/uts/common/inet/sctp/sctp_timer.c	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/inet/sctp/sctp_timer.c	Thu Jul 30 10:07:41 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -506,8 +506,7 @@
 						    sctp->sctp_rto_initial;
 						goto dead_addr;
 					} else {
-						SCTP_CALC_RXT(fp,
-						    sctp->sctp_rto_max);
+						SCTP_CALC_RXT(sctp, fp);
 						fp->hb_expiry = now + fp->rto;
 					}
 					break;
@@ -571,7 +570,6 @@
 sctp_rexmit_timer(sctp_t *sctp, sctp_faddr_t *fp)
 {
 	mblk_t 		*mp;
-	uint32_t	rto_max = sctp->sctp_rto_max;
 	sctp_stack_t	*sctps = sctp->sctp_sctps;
 
 	ASSERT(fp != NULL);
@@ -649,7 +647,6 @@
 			BUMP_MIB(&sctps->sctps_mib, sctpTimRetrans);
 			sctp_add_sendq(sctp, mp);
 		}
-		rto_max = sctp->sctp_init_rto_max;
 		break;
 	case SCTPS_COOKIE_ECHOED: {
 		ipha_t *iph;
@@ -668,7 +665,6 @@
 			iph->ipha_ident = 0;
 		sctp_add_sendq(sctp, mp);
 		BUMP_MIB(&sctps->sctps_mib, sctpTimRetrans);
-		rto_max = sctp->sctp_init_rto_max;
 		break;
 	}
 	case SCTPS_SHUTDOWN_SENT:
@@ -693,7 +689,7 @@
 
 	fp->strikes++;
 	sctp->sctp_strikes++;
-	SCTP_CALC_RXT(fp, rto_max);
+	SCTP_CALC_RXT(sctp, fp);
 
 	SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto);
 }
@@ -744,6 +740,7 @@
 		fp->rto = sctp->sctp_rto_max;
 	}
 
+	SCTP_MAX_RTO(sctp, fp);
 	fp->rtt_updates++;
 }
 
--- a/usr/src/uts/common/netinet/sctp.h	Thu Jul 30 09:40:30 2009 -0600
+++ b/usr/src/uts/common/netinet/sctp.h	Thu Jul 30 10:07:41 2009 -0700
@@ -79,6 +79,11 @@
 #define	SCTP_PRSCTP			23
 
 /*
+ * SCTP socket option used to read per endpoint association statistics.
+ */
+#define	SCTP_GET_ASSOC_STATS		24
+
+/*
  * Ancillary data identifiers
  */
 #define	SCTP_SNDRCV		0x100
@@ -481,6 +486,27 @@
 };
 
 /*
+ * A socket user request reads local per endpoint association stats.
+ * All stats are counts except sas_maxrto, which is the max value
+ * since the last user request for stats on this endpoint.
+ */
+typedef struct sctp_assoc_stats {
+	uint64_t	sas_rtxchunks; /* Retransmitted Chunks */
+	uint64_t	sas_gapcnt; /* Gap Acknowledgements Received */
+	uint64_t	sas_maxrto; /* Maximum Observed RTO this period */
+	uint64_t	sas_outseqtsns; /* TSN received > next expected */
+	uint64_t	sas_osacks; /* SACKs sent */
+	uint64_t	sas_isacks; /* SACKs received */
+	uint64_t	sas_octrlchunks; /* Control chunks sent - no dups */
+	uint64_t	sas_ictrlchunks; /* Control chunks received - no dups */
+	uint64_t	sas_oodchunks; /* Ordered data chunks sent */
+	uint64_t	sas_iodchunks; /* Ordered data chunks received */
+	uint64_t	sas_ouodchunks; /* Unordered data chunks sent */
+	uint64_t	sas_iuodchunks; /* Unordered data chunks received */
+	uint64_t	sas_idupchunks; /* Dups received (ordered+unordered) */
+} sctp_assoc_stats_t;
+
+/*
  * Private ioctl option structure
  */
 struct sctpopt {