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);
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to