Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Feb 2009 17:57:28 +0000 (UTC)
From:      Randall Stewart <rrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r188524 - in stable/7/sys: . netinet
Message-ID:  <200902121757.n1CHvSVo062783@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rrs
Date: Thu Feb 12 17:57:28 2009
New Revision: 188524
URL: http://svn.freebsd.org/changeset/base/188524

Log:
  MFC of 182367 and 182403
  
  - Make strict-sacks be the default.
  - Change it so that without INVARIANTs there are
    no panics in SCTP.
  - sctp_timer changes so that we have a recovery mechanism
    when the sent list is out of order.
  
  <AND>
  
  Fixes compile error when INVARIANTs is on. Adds an
  empty goto to keep the compiler happy.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/netinet/sctp_indata.c
  stable/7/sys/netinet/sctp_lock_bsd.h
  stable/7/sys/netinet/sctp_output.c
  stable/7/sys/netinet/sctp_sysctl.h
  stable/7/sys/netinet/sctp_timer.c
  stable/7/sys/netinet/sctp_timer.h
  stable/7/sys/netinet/sctp_var.h
  stable/7/sys/netinet/sctputil.c

Modified: stable/7/sys/netinet/sctp_indata.c
==============================================================================
--- stable/7/sys/netinet/sctp_indata.c	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_indata.c	Thu Feb 12 17:57:28 2009	(r188524)
@@ -386,12 +386,21 @@ abandon:
 				if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
 					goto abandon;
 				} else {
+#ifdef INVARIANTS
 					if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) {
 						panic("This should not happen control_pdapi NULL?");
 					}
 					/* if we did not panic, it was a EOM */
 					panic("Bad chunking ??");
-					return;
+#else
+					if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) {
+						SCTP_PRINTF("This should not happen control_pdapi NULL?\n");
+					}
+					SCTP_PRINTF("Bad chunking ??\n");
+					SCTP_PRINTF("Dumping re-assembly queue this will probably hose the association\n");
+
+#endif
+					goto abandon;
 				}
 			}
 			cntDel++;

Modified: stable/7/sys/netinet/sctp_lock_bsd.h
==============================================================================
--- stable/7/sys/netinet/sctp_lock_bsd.h	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_lock_bsd.h	Thu Feb 12 17:57:28 2009	(r188524)
@@ -365,14 +365,20 @@ extern int sctp_logoff_stuff;
                 do { \
   	               atomic_add_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \
 	        } while (0)
-
+#ifdef INVARIANTS
 #define SCTP_DECR_CHK_COUNT() \
                 do { \
                        if(SCTP_BASE_INFO(ipi_count_chunk) == 0) \
                              panic("chunk count to 0?");    \
   	               atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \
 	        } while (0)
-
+#else
+#define SCTP_DECR_CHK_COUNT() \
+                do { \
+                       if(SCTP_BASE_INFO(ipi_count_chunk) != 0) \
+  	               atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \
+	        } while (0)
+#endif
 #define SCTP_INCR_READQ_COUNT() \
                 do { \
 		       atomic_add_int(&SCTP_BASE_INFO(ipi_count_readq),1); \

Modified: stable/7/sys/netinet/sctp_output.c
==============================================================================
--- stable/7/sys/netinet/sctp_output.c	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_output.c	Thu Feb 12 17:57:28 2009	(r188524)
@@ -11381,6 +11381,7 @@ sctp_send_operr_to(struct mbuf *m, int i
 	struct ip *iph;
 	struct udphdr *udp = NULL;
 	struct mbuf *mout;
+
 #ifdef INET6
 #ifdef SCTP_DEBUG
 	struct sockaddr_in6 lsa6, fsa6;

Modified: stable/7/sys/netinet/sctp_sysctl.h
==============================================================================
--- stable/7/sys/netinet/sctp_sysctl.h	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_sysctl.h	Thu Feb 12 17:57:28 2009	(r188524)
@@ -152,7 +152,7 @@ struct sctp_sysctl {
 #define SCTPCTL_STRICT_SACKS_DESC	"Enable SCTP Strict SACK checking"
 #define SCTPCTL_STRICT_SACKS_MIN	0
 #define SCTPCTL_STRICT_SACKS_MAX	1
-#define SCTPCTL_STRICT_SACKS_DEFAULT	0
+#define SCTPCTL_STRICT_SACKS_DEFAULT	1
 
 /* loopback_nocsum: Enable NO Csum on packets sent on loopback */
 #define SCTPCTL_LOOPBACK_NOCSUM_DESC	"Enable NO Csum on packets sent on loopback"

Modified: stable/7/sys/netinet/sctp_timer.c
==============================================================================
--- stable/7/sys/netinet/sctp_timer.c	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_timer.c	Thu Feb 12 17:57:28 2009	(r188524)
@@ -561,6 +561,49 @@ sctp_backoff_on_timeout(struct sctp_tcb 
 	}
 }
 
+void
+sctp_recover_sent_list(struct sctp_tcb *stcb)
+{
+	struct sctp_tmit_chunk *chk, *tp2;
+	struct sctp_association *asoc;
+
+	asoc = &stcb->asoc;
+	chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
+	for (; chk != NULL; chk = tp2) {
+		tp2 = TAILQ_NEXT(chk, sctp_next);
+		if ((compare_with_wrap(stcb->asoc.last_acked_seq,
+		    chk->rec.data.TSN_seq,
+		    MAX_TSN)) ||
+		    (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
+
+			SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n",
+			    chk, chk->rec.data.TSN_seq, stcb->asoc.last_acked_seq);
+			TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
+			if (chk->pr_sctp_on) {
+				if (asoc->pr_sctp_cnt != 0)
+					asoc->pr_sctp_cnt--;
+			}
+			if (chk->data) {
+				/* sa_ignore NO_NULL_CHK */
+				sctp_free_bufspace(stcb, asoc, chk, 1);
+				sctp_m_freem(chk->data);
+				if (PR_SCTP_BUF_ENABLED(chk->flags)) {
+					asoc->sent_queue_cnt_removeable--;
+				}
+			}
+			chk->data = NULL;
+			asoc->sent_queue_cnt--;
+			sctp_free_a_chunk(stcb, chk);
+		}
+	}
+	SCTP_PRINTF("after recover order is as follows\n");
+	chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
+	for (; chk != NULL; chk = tp2) {
+		tp2 = TAILQ_NEXT(chk, sctp_next);
+		SCTP_PRINTF("chk:%p TSN:%x\n", chk, chk->rec.data.TSN_seq);
+	}
+}
+
 static int
 sctp_mark_all_for_resend(struct sctp_tcb *stcb,
     struct sctp_nets *net,
@@ -583,6 +626,7 @@ sctp_mark_all_for_resend(struct sctp_tcb
 	unsigned int cnt_mk;
 	uint32_t orig_flight, orig_tf;
 	uint32_t tsnlast, tsnfirst;
+	int recovery_cnt = 0;
 
 
 	/* none in flight now */
@@ -635,6 +679,7 @@ sctp_mark_all_for_resend(struct sctp_tcb
 	/* Now on to each chunk */
 	num_mk = cnt_mk = 0;
 	tsnfirst = tsnlast = 0;
+start_again:
 	chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
 	for (; chk != NULL; chk = tp2) {
 		tp2 = TAILQ_NEXT(chk, sctp_next);
@@ -643,8 +688,22 @@ sctp_mark_all_for_resend(struct sctp_tcb
 		    MAX_TSN)) ||
 		    (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
 			/* Strange case our list got out of order? */
-			SCTP_PRINTF("Our list is out of order?\n");
-			panic("Out of order list");
+			SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x",
+			    (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq);
+			recovery_cnt++;
+#ifdef INVARIANTS
+			panic("last acked >= chk on sent-Q");
+			/* to keep compiler happy */
+			goto start_again;
+#else
+			SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt);
+			sctp_recover_sent_list(stcb);
+			if (recovery_cnt < 10) {
+				goto start_again;
+			} else {
+				SCTP_PRINTF("Recovery fails %d times??\n", recovery_cnt);
+			}
+#endif
 		}
 		if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) {
 			/*

Modified: stable/7/sys/netinet/sctp_timer.h
==============================================================================
--- stable/7/sys/netinet/sctp_timer.h	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_timer.h	Thu Feb 12 17:57:28 2009	(r188524)
@@ -99,6 +99,8 @@ void sctp_audit_retranmission_queue(stru
 
 void sctp_iterator_timer(struct sctp_iterator *it);
 
+void sctp_recover_sent_list(struct sctp_tcb *stcb);
+
 
 #endif
 #endif

Modified: stable/7/sys/netinet/sctp_var.h
==============================================================================
--- stable/7/sys/netinet/sctp_var.h	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctp_var.h	Thu Feb 12 17:57:28 2009	(r188524)
@@ -160,6 +160,9 @@ extern struct pr_usrreqs sctp_usrreqs;
 	} \
 }
 
+#ifdef INVARIANTS
+
+
 #define sctp_sbfree(ctl, stcb, sb, m) { \
 	uint32_t val; \
 	val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \
@@ -186,6 +189,35 @@ extern struct pr_usrreqs sctp_usrreqs;
 }
 
 
+#else
+
+#define sctp_sbfree(ctl, stcb, sb, m) { \
+	uint32_t val; \
+	val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \
+	if (val < SCTP_BUF_LEN((m))) { \
+	    (sb)->sb_cc = 0;\
+	} \
+	val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(MSIZE)); \
+	if (val < MSIZE) { \
+	    (sb)->sb_mbcnt = 0; \
+	} \
+	if (((ctl)->do_not_ref_stcb == 0) && stcb) {\
+	  val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-(SCTP_BUF_LEN((m)))); \
+	  if (val < SCTP_BUF_LEN((m))) {\
+	      (stcb)->asoc.sb_cc = 0; \
+	  } \
+	  val = atomic_fetchadd_int(&(stcb)->asoc.my_rwnd_control_len,-(MSIZE)); \
+	  if (val < MSIZE) { \
+	     (stcb)->asoc.my_rwnd_control_len = 0; \
+	  } \
+	} \
+	if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
+	    SCTP_BUF_TYPE(m) != MT_OOBDATA) \
+		atomic_subtract_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \
+}
+
+#endif
+
 #define sctp_sballoc(stcb, sb, m) { \
 	atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \
 	atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \

Modified: stable/7/sys/netinet/sctputil.c
==============================================================================
--- stable/7/sys/netinet/sctputil.c	Thu Feb 12 17:31:39 2009	(r188523)
+++ stable/7/sys/netinet/sctputil.c	Thu Feb 12 17:57:28 2009	(r188524)
@@ -922,7 +922,9 @@ sctp_init_asoc(struct sctp_inpcb *m, str
 			asoc->my_vtag = override_tag;
 		} else {
 			SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
+#ifdef INVARIANTS
 			panic("Huh is_in_timewait fails");
+#endif
 			return (ENOMEM);
 		}
 
@@ -4848,6 +4850,7 @@ sctp_find_ifa_by_addr(struct sockaddr *a
 
 	vrf = sctp_find_vrf(vrf_id);
 	if (vrf == NULL) {
+stage_right:
 		if (holds_lock == 0)
 			SCTP_IPI_ADDR_RUNLOCK();
 		return (NULL);
@@ -4868,7 +4871,13 @@ sctp_find_ifa_by_addr(struct sockaddr *a
 	}
 	LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
 		if (sctp_ifap == NULL) {
+#ifdef INVARIANTS
 			panic("Huh LIST_FOREACH corrupt");
+			goto stage_right;
+#else
+			SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n");
+			goto stage_right;
+#endif
 		}
 		if (addr->sa_family != sctp_ifap->address.sa.sa_family)
 			continue;
@@ -5918,7 +5927,12 @@ out:
 		 * the atomic add to the refcnt.
 		 */
 		if (stcb == NULL) {
+#ifdef INVARIANTS
 			panic("stcb for refcnt has gone NULL?");
+			goto stage_left;
+#else
+			goto stage_left;
+#endif
 		}
 		atomic_add_int(&stcb->asoc.refcnt, -1);
 		freecnt_applied = 0;
@@ -5940,6 +5954,7 @@ out:
 			    so->so_rcv.sb_cc);
 		}
 	}
+stage_left:
 	if (wakeup_read_socket) {
 		sctp_sorwakeup(inp, so);
 	}



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