diff options
-rw-r--r-- | sys/netinet/sctp_indata.c | 11 | ||||
-rw-r--r-- | sys/netinet/sctp_lock_bsd.h | 10 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_sysctl.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_timer.c | 61 | ||||
-rw-r--r-- | sys/netinet/sctp_var.h | 32 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 15 |
7 files changed, 126 insertions, 6 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 8a1d057..5e00d14 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -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++; diff --git a/sys/netinet/sctp_lock_bsd.h b/sys/netinet/sctp_lock_bsd.h index 6d59d35..6db9057 100644 --- a/sys/netinet/sctp_lock_bsd.h +++ b/sys/netinet/sctp_lock_bsd.h @@ -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); \ diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 76ea5f3..5c2a492 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -11381,6 +11381,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag, struct ip *iph; struct udphdr *udp = NULL; struct mbuf *mout; + #ifdef INET6 #ifdef SCTP_DEBUG struct sockaddr_in6 lsa6, fsa6; diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h index f739c96..399bcb0 100644 --- a/sys/netinet/sctp_sysctl.h +++ b/sys/netinet/sctp_sysctl.h @@ -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" diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index a095c4e..73a1877 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -561,6 +561,49 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb, } } +static 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 *stcb, 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 *stcb, /* 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,20 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, 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"); +#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)) { /* diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index 77f2ceb..9340c1c 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -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); \ diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index dc215bd..20865c4 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -922,7 +922,9 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, 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 *addr, uint32_t vrf_id, int holds_lock) 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 *addr, uint32_t vrf_id, int holds_lock) } 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); } |