From 21f7d6c524a91477113e6af61d068cbaa64984d8 Mon Sep 17 00:00:00 2001 From: rrs Date: Fri, 11 Jun 2010 03:13:19 +0000 Subject: [PATCH] MFC: Fix a number of bugs and race conditions. r208160: Bring back of the iterator thread. It now properly handles VNETS having only one thread. The old timer based code was full of LOR's and other issues. r208852: Cleanup bug. Basically when an un-accepted socket was hanging on a closed listener, we would leak the inp never cleaning it up r208853: Enhance the use under invarients of the audit for locks function and fix a bug where a close collision with a cookie being processed would cause a crash. r208854: Use the proper increment macros when working with the sent_queue_retran_cnt r208855: Align comments properly, Fix a bug where we were NOT looking at the resend markings for control chunks and also not decrementing the retran count which caused extra calls to retransmission. Alos add a valid no locks call to the output routine. r208856: Spacing issues in auth/bsd addr. r208857: Get rid of a windows ifdef that somehow leaked in r208863: Missing error leg returns in some failure cases r208864: LOR fix between the iterator and sctp_inpcb_close r208874: Don't call the sctp_inpcb_free from abort an association since you don't know what locks you hold and a timer will take care of the situation when the gone flag is set r208875: sctp_inpcb_free bug - a socket under the right situation could get stuck (from the accept queue) and never start the proper cleanup timer) r208876: Further enhance invariant lock validation, Fix a bug where a closed socket and a INIT-ACK could collide and cause a crash r208878: Clear up another bug in sctp_inpcb_free where we would end up due to a race in freeing hit a destroy of a contended lock. r208879: Optimize the cleanup and make some additional fixes in the sysctl code so that it won't reference a GONE INP and crash us r208883 & r208891: Fix so we don't open a hole between a sock lock and a call to socantrcvmore.. we could before hit a race that would kill the socket underneath us leading to a crash r208897: CUM-ACK calculation was messed up. So basically large message got broken from the original NR_sack integration. r208902: Make sure that we don't move a bit to the NR array that is behind the cum-ack r208952: Use both bit maps to calculte the cum-ack. r208953: Fix bug having to do with freeing an sctp_inpcb_free(). 1) make sure not to remove the flag until you get the lock again. 2) make sure all log_closing calls hold the lock. 3) Release all the locks when everthing is done and call callout_drain not callout_stop.. r208970: Fix some places on user allocation of a new sctp_inpcb where we run out of resource that we make sure to NULL the so_pcb pointer. Approved by: re - (bz@freebsd.org) git-svn-id: svn://svn.freebsd.org/base/stable/8@209028 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/netinet/sctp_auth.c | 10 +- sys/netinet/sctp_bsd_addr.c | 64 +++++--- sys/netinet/sctp_bsd_addr.h | 3 +- sys/netinet/sctp_constants.h | 7 +- sys/netinet/sctp_indata.c | 36 +++-- sys/netinet/sctp_input.c | 33 +++- sys/netinet/sctp_lock_bsd.h | 55 +++++-- sys/netinet/sctp_output.c | 36 +++-- sys/netinet/sctp_pcb.c | 290 ++++++++++++++++++++--------------- sys/netinet/sctp_pcb.h | 15 +- sys/netinet/sctp_structs.h | 17 ++ sys/netinet/sctp_sysctl.c | 13 +- sys/netinet/sctp_timer.c | 140 ----------------- sys/netinet/sctp_usrreq.c | 8 + sys/netinet/sctputil.c | 117 ++++++-------- 15 files changed, 421 insertions(+), 423 deletions(-) diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c index 928f572cb..3341c5065 100644 --- a/sys/netinet/sctp_auth.c +++ b/sys/netinet/sctp_auth.c @@ -895,9 +895,9 @@ static inline int sctp_get_hmac_block_len(uint16_t hmac_algo) { switch (hmac_algo) { - case SCTP_AUTH_HMAC_ID_SHA1: + case SCTP_AUTH_HMAC_ID_SHA1: #ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: + case SCTP_AUTH_HMAC_ID_SHA224: #endif return (64); #ifdef HAVE_SHA2 @@ -918,7 +918,7 @@ static void sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t * ctx) { switch (hmac_algo) { - case SCTP_AUTH_HMAC_ID_SHA1: + case SCTP_AUTH_HMAC_ID_SHA1: SHA1_Init(&ctx->sha1); break; #ifdef HAVE_SHA224 @@ -948,7 +948,7 @@ sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t * ctx, uint8_t * text, uint32_t textlen) { switch (hmac_algo) { - case SCTP_AUTH_HMAC_ID_SHA1: + case SCTP_AUTH_HMAC_ID_SHA1: SHA1_Update(&ctx->sha1, text, textlen); break; #ifdef HAVE_SHA224 @@ -978,7 +978,7 @@ sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t * ctx, uint8_t * digest) { switch (hmac_algo) { - case SCTP_AUTH_HMAC_ID_SHA1: + case SCTP_AUTH_HMAC_ID_SHA1: SHA1_Final(digest, &ctx->sha1); break; #ifdef HAVE_SHA224 diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c index e508a4ab9..4c5a9aa6c 100644 --- a/sys/netinet/sctp_bsd_addr.c +++ b/sys/netinet/sctp_bsd_addr.c @@ -49,16 +49,6 @@ __FBSDID("$FreeBSD$"); #include /* Declare all of our malloc named types */ - -/* Note to Michael/Peter for mac-os, - * I think mac has this too since I - * do see the M_PCB type, so I - * will also put in the mac file the - * MALLOC_DECLARE. If this does not - * work for mac uncomment the defines for - * the strings that we use in Panda, I put - * them in comments in the mac-os file. - */ MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor"); MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array"); MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array"); @@ -79,47 +69,77 @@ MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list"); MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control"); MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option"); -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) +/* Global NON-VNET structure that controls the iterator */ +struct iterator_control sctp_it_ctl; +static int __sctp_thread_based_iterator_started = 0; + + +static void +sctp_cleanup_itqueue(void) +{ + struct sctp_iterator *it; + + while ((it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead)) != NULL) { + if (it->function_atend != NULL) { + (*it->function_atend) (it->pointer, it->val); + } + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); + SCTP_FREE(it, SCTP_M_ITER); + } +} + + void sctp_wakeup_iterator(void) { - wakeup(&SCTP_BASE_INFO(iterator_running)); + wakeup(&sctp_it_ctl.iterator_running); } static void sctp_iterator_thread(void *v) { - CURVNET_SET((struct vnet *)v); SCTP_IPI_ITERATOR_WQ_LOCK(); - SCTP_BASE_INFO(iterator_running) = 0; while (1) { - msleep(&SCTP_BASE_INFO(iterator_running), - &SCTP_BASE_INFO(ipi_iterator_wq_mtx), + msleep(&sctp_it_ctl.iterator_running, + &sctp_it_ctl.ipi_iterator_wq_mtx, 0, "waiting_for_work", 0); - if (SCTP_BASE_INFO(threads_must_exit)) { + if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) { SCTP_IPI_ITERATOR_WQ_DESTROY(); + SCTP_ITERATOR_LOCK_DESTROY(); + sctp_cleanup_itqueue(); + __sctp_thread_based_iterator_started = 0; kthread_exit(); } sctp_iterator_worker(); } - CURVNET_RESTORE(); } void sctp_startup_iterator(void) { + if (__sctp_thread_based_iterator_started) { + /* You only get one */ + return; + } + /* init the iterator head */ + __sctp_thread_based_iterator_started = 1; + sctp_it_ctl.iterator_running = 0; + sctp_it_ctl.iterator_flags = 0; + sctp_it_ctl.cur_it = NULL; + SCTP_ITERATOR_LOCK_INIT(); + SCTP_IPI_ITERATOR_WQ_INIT(); + TAILQ_INIT(&sctp_it_ctl.iteratorhead); + int ret; ret = kproc_create(sctp_iterator_thread, - (void *)curvnet, - &SCTP_BASE_INFO(thread_proc), + (void *)NULL, + &sctp_it_ctl.thread_proc, RFPROC, SCTP_KTHREAD_PAGES, SCTP_KTRHEAD_NAME); } -#endif - #ifdef INET6 void diff --git a/sys/netinet/sctp_bsd_addr.h b/sys/netinet/sctp_bsd_addr.h index 2260cf93a..ae2fa5259 100644 --- a/sys/netinet/sctp_bsd_addr.h +++ b/sys/netinet/sctp_bsd_addr.h @@ -37,12 +37,11 @@ __FBSDID("$FreeBSD$"); #if defined(_KERNEL) || defined(__Userspace__) -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) +extern struct iterator_control sctp_it_ctl; void sctp_wakeup_iterator(void); void sctp_startup_iterator(void); -#endif #ifdef INET6 void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa); diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index 7eae6774d..078981de3 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -87,10 +87,6 @@ __FBSDID("$FreeBSD$"); /* #define SCTP_AUDITING_ENABLED 1 used for debug/auditing */ #define SCTP_AUDIT_SIZE 256 -/* temporary disabled since it does not work with VNET. */ -#if 0 -#define SCTP_USE_THREAD_BASED_ITERATOR 1 -#endif #define SCTP_KTRHEAD_NAME "sctp_iterator" #define SCTP_KTHREAD_PAGES 0 @@ -572,7 +568,6 @@ __FBSDID("$FreeBSD$"); #define SCTP_TIMER_TYPE_EVENTWAKE 13 #define SCTP_TIMER_TYPE_STRRESET 14 #define SCTP_TIMER_TYPE_INPKILL 15 -#define SCTP_TIMER_TYPE_ITERATOR 16 #define SCTP_TIMER_TYPE_EARLYFR 17 #define SCTP_TIMER_TYPE_ASOCKILL 18 #define SCTP_TIMER_TYPE_ADDR_WQ 19 @@ -899,7 +894,7 @@ __FBSDID("$FreeBSD$"); /* third argument */ #define SCTP_CALLED_DIRECTLY_NOCMPSET 0 #define SCTP_CALLED_AFTER_CMPSET_OFCLOSE 1 - +#define SCTP_CALLED_FROM_INPKILL_TIMER 2 /* second argument */ #define SCTP_FREE_SHOULD_USE_ABORT 1 #define SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE 0 diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index a8525f09a..e79264819 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -289,12 +289,20 @@ sctp_build_ctl_cchunk(struct sctp_inpcb *inp, static void sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn) { - uint32_t gap, i; + uint32_t gap, i, cumackp1; int fnd = 0; if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { return; } + cumackp1 = asoc->cumulative_tsn + 1; + if (compare_with_wrap(cumackp1, tsn, MAX_TSN)) { + /* + * this tsn is behind the cum ack and thus we don't need to + * worry about it being moved from one to the other. + */ + return; + } SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { printf("gap:%x tsn:%x\n", gap, tsn); @@ -2245,15 +2253,19 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb) /* * Now we also need to check the mapping array in a couple of ways. * 1) Did we move the cum-ack point? + * + * When you first glance at this you might think that all entries that + * make up the postion of the cum-ack would be in the nr-mapping + * array only.. i.e. things up to the cum-ack are always + * deliverable. Thats true with one exception, when its a fragmented + * message we may not deliver the data until some threshold (or all + * of it) is in place. So we must OR the nr_mapping_array and + * mapping_array to get a true picture of the cum-ack. */ struct sctp_association *asoc; int at; + uint8_t val; int slide_from, slide_end, lgap, distance; - - /* EY nr_mapping array variables */ - /* int nr_at; */ - /* int nr_last_all_ones = 0; */ - /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */ uint32_t old_cumack, old_base, old_highest, highest_tsn; asoc = &stcb->asoc; @@ -2268,11 +2280,12 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb) */ at = 0; for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { - if (asoc->nr_mapping_array[slide_from] == 0xff) { + val = asoc->nr_mapping_array[slide_from] | asoc->mapping_array[slide_from]; + if (val == 0xff) { at += 8; } else { /* there is a 0 bit */ - at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]]; + at += sctp_map_lookup_tab[val]; break; } } @@ -3849,7 +3862,8 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, sctp_total_flight_decrease(stcb, tp1); /* Now mark for resend */ tp1->sent = SCTP_DATAGRAM_RESEND; - asoc->sent_queue_retran_cnt++; + sctp_ucount_incr(asoc->sent_queue_retran_cnt); + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP, tp1->whoTo->flight_size, @@ -4262,7 +4276,7 @@ again: sctp_flight_size_increase(tp1); sctp_total_flight_increase(stcb, tp1); } else if (tp1->sent == SCTP_DATAGRAM_RESEND) { - asoc->sent_queue_retran_cnt++; + sctp_ucount_incr(asoc->sent_queue_retran_cnt); } } } @@ -5263,7 +5277,7 @@ again: sctp_flight_size_increase(tp1); sctp_total_flight_increase(stcb, tp1); } else if (tp1->sent == SCTP_DATAGRAM_RESEND) { - asoc->sent_queue_retran_cnt++; + sctp_ucount_incr(asoc->sent_queue_retran_cnt); } } } diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 8b5df020f..8b2a9d598 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -3067,7 +3067,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, struct sctp_nets *net, uint8_t flg) { switch (desc->chunk_type) { - case SCTP_DATA: + case SCTP_DATA: /* find the tsn to resend (possibly */ { uint32_t tsn; @@ -4534,7 +4534,8 @@ process_control_chunks: if ((stcb) && (stcb->asoc.total_output_queue_size)) { ; } else { - if (locked_tcb) { + if (locked_tcb != stcb) { + /* Very unlikely */ SCTP_TCB_UNLOCK(locked_tcb); } *offset = length; @@ -4861,6 +4862,10 @@ process_control_chunks: } else { if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ + abend: + if (stcb) { + SCTP_TCB_UNLOCK(stcb); + } *offset = length; return (NULL); } @@ -4908,6 +4913,11 @@ process_control_chunks: if (linp) { SCTP_ASOC_CREATE_LOCK(linp); + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { + SCTP_ASOC_CREATE_UNLOCK(linp); + goto abend; + } } if (netp) { ret_buf = @@ -5408,16 +5418,25 @@ sctp_process_ecn_marked_b(struct sctp_tcb *stcb, struct sctp_nets *net, } #ifdef INVARIANTS -static void -sctp_validate_no_locks(struct sctp_inpcb *inp) +#ifdef __GNUC__ +__attribute__((noinline)) +#endif + void + sctp_validate_no_locks(struct sctp_inpcb *inp) { - struct sctp_tcb *stcb; + struct sctp_tcb *lstcb; - LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { - if (mtx_owned(&stcb->tcb_mtx)) { + LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { + if (mtx_owned(&lstcb->tcb_mtx)) { panic("Own lock on stcb at return from input"); } } + if (mtx_owned(&inp->inp_create_mtx)) { + panic("Own create lock on inp"); + } + if (mtx_owned(&inp->inp_mtx)) { + panic("Own inp lock on inp"); + } } #endif diff --git a/sys/netinet/sctp_lock_bsd.h b/sys/netinet/sctp_lock_bsd.h index 6db9057ef..dd9c2ce57 100644 --- a/sys/netinet/sctp_lock_bsd.h +++ b/sys/netinet/sctp_lock_bsd.h @@ -107,42 +107,36 @@ extern int sctp_logoff_stuff; #define SCTP_INP_INFO_WUNLOCK() rw_wunlock(&SCTP_BASE_INFO(ipi_ep_mtx)) -#define SCTP_IPI_ADDR_INIT() \ +#define SCTP_IPI_ADDR_INIT() \ rw_init(&SCTP_BASE_INFO(ipi_addr_mtx), "sctp-addr") - #define SCTP_IPI_ADDR_DESTROY() do { \ if(rw_wowned(&SCTP_BASE_INFO(ipi_addr_mtx))) { \ rw_wunlock(&SCTP_BASE_INFO(ipi_addr_mtx)); \ } \ rw_destroy(&SCTP_BASE_INFO(ipi_addr_mtx)); \ } while (0) - - - #define SCTP_IPI_ADDR_RLOCK() do { \ rw_rlock(&SCTP_BASE_INFO(ipi_addr_mtx)); \ } while (0) - #define SCTP_IPI_ADDR_WLOCK() do { \ rw_wlock(&SCTP_BASE_INFO(ipi_addr_mtx)); \ } while (0) - #define SCTP_IPI_ADDR_RUNLOCK() rw_runlock(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ADDR_WUNLOCK() rw_wunlock(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ITERATOR_WQ_INIT() \ - mtx_init(&SCTP_BASE_INFO(ipi_iterator_wq_mtx), "sctp-it-wq", "sctp_it_wq", MTX_DEF) + mtx_init(&sctp_it_ctl.ipi_iterator_wq_mtx, "sctp-it-wq", "sctp_it_wq", MTX_DEF) #define SCTP_IPI_ITERATOR_WQ_DESTROY() \ - mtx_destroy(&SCTP_BASE_INFO(ipi_iterator_wq_mtx)) + mtx_destroy(&sctp_it_ctl.ipi_iterator_wq_mtx) #define SCTP_IPI_ITERATOR_WQ_LOCK() do { \ - mtx_lock(&SCTP_BASE_INFO(ipi_iterator_wq_mtx)); \ + mtx_lock(&sctp_it_ctl.ipi_iterator_wq_mtx); \ } while (0) -#define SCTP_IPI_ITERATOR_WQ_UNLOCK() mtx_unlock(&SCTP_BASE_INFO(ipi_iterator_wq_mtx)) +#define SCTP_IPI_ITERATOR_WQ_UNLOCK() mtx_unlock(&sctp_it_ctl.ipi_iterator_wq_mtx) #define SCTP_IP_PKTLOG_INIT() \ @@ -191,6 +185,13 @@ extern int sctp_logoff_stuff; #define SCTP_INP_LOCK_DESTROY(_inp) \ mtx_destroy(&(_inp)->inp_mtx) +#define SCTP_INP_LOCK_CONTENDED(_inp) ((_inp)->inp_mtx.mtx_lock & MTX_CONTESTED) + +#define SCTP_INP_READ_CONTENDED(_inp) ((_inp)->inp_rdata_mtx.mtx_lock & MTX_CONTESTED) + +#define SCTP_ASOC_CREATE_LOCK_CONTENDED(_inp) ((_inp)->inp_create_mtx.mtx_lock & MTX_CONTESTED) + + #define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ mtx_destroy(&(_inp)->inp_create_mtx) @@ -300,25 +301,45 @@ extern int sctp_logoff_stuff; #endif #define SCTP_ITERATOR_LOCK_INIT() \ - mtx_init(&SCTP_BASE_INFO(it_mtx), "sctp-it", "iterator", MTX_DEF) + mtx_init(&sctp_it_ctl.it_mtx, "sctp-it", "iterator", MTX_DEF) #ifdef INVARIANTS #define SCTP_ITERATOR_LOCK() \ do { \ - if (mtx_owned(&SCTP_BASE_INFO(it_mtx))) \ + if (mtx_owned(&sctp_it_ctl.it_mtx)) \ panic("Iterator Lock"); \ - mtx_lock(&SCTP_BASE_INFO(it_mtx)); \ + mtx_lock(&sctp_it_ctl.it_mtx); \ } while (0) #else #define SCTP_ITERATOR_LOCK() \ do { \ - mtx_lock(&SCTP_BASE_INFO(it_mtx)); \ + mtx_lock(&sctp_it_ctl.it_mtx); \ } while (0) #endif -#define SCTP_ITERATOR_UNLOCK() mtx_unlock(&SCTP_BASE_INFO(it_mtx)) -#define SCTP_ITERATOR_LOCK_DESTROY() mtx_destroy(&SCTP_BASE_INFO(it_mtx)) +#define SCTP_ITERATOR_UNLOCK() mtx_unlock(&sctp_it_ctl.it_mtx) +#define SCTP_ITERATOR_LOCK_DESTROY() mtx_destroy(&sctp_it_ctl.it_mtx) + + +#define SCTP_WQ_ADDR_INIT() do { \ + mtx_init(&SCTP_BASE_INFO(wq_addr_mtx), "sctp-addr-wq","sctp_addr_wq",MTX_DEF); \ + } while (0) + +#define SCTP_WQ_ADDR_DESTROY() do { \ + if(mtx_owned(&SCTP_BASE_INFO(wq_addr_mtx))) { \ + mtx_unlock(&SCTP_BASE_INFO(wq_addr_mtx)); \ + } \ + mtx_destroy(&SCTP_BASE_INFO(wq_addr_mtx)); \ + } while (0) + +#define SCTP_WQ_ADDR_LOCK() do { \ + mtx_lock(&SCTP_BASE_INFO(wq_addr_mtx)); \ +} while (0) +#define SCTP_WQ_ADDR_UNLOCK() do { \ + mtx_unlock(&SCTP_BASE_INFO(wq_addr_mtx)); \ +} while (0) + #define SCTP_INCR_EP_COUNT() \ diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 96a45754b..011842f45 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -3053,32 +3053,32 @@ sctp_source_address_selection(struct sctp_inpcb *inp, * it out * zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz * For V4 - *------------------------------------------ + * ------------------------------------------ * source * dest * result * ----------------------------------------- * Private * Global * NAT * ----------------------------------------- * Private * Private * No problem * ----------------------------------------- - * Global * Private * Huh, How will this work? + * Global * Private * Huh, How will this work? * ----------------------------------------- - * Global * Global * No Problem - *------------------------------------------ + * Global * Global * No Problem + *------------------------------------------ * zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz * For V6 - *------------------------------------------ + *------------------------------------------ * source * dest * result * ----------------------------------------- * Linklocal * Global * * ----------------------------------------- * Linklocal * Linklocal * No problem * ----------------------------------------- - * Global * Linklocal * Huh, How will this work? + * Global * Linklocal * Huh, How will this work? * ----------------------------------------- - * Global * Global * No Problem - *------------------------------------------ + * Global * Global * No Problem + *------------------------------------------ * zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz - * + * * And then we add to that what happens if there are multiple addresses * assigned to an interface. Remember the ifa on a ifn is a linked * list of addresses. So one interface can have more than one IP @@ -3091,13 +3091,13 @@ sctp_source_address_selection(struct sctp_inpcb *inp, * Decisions: * * - count the number of addresses on the interface. - * - if it is one, no problem except case . - * For we will assume a NAT out there. + * - if it is one, no problem except case . + * For we will assume a NAT out there. * - if there are more than one, then we need to worry about scope P * or G. We should prefer G -> G and P -> P if possible. * Then as a secondary fall back to mixed types G->P being a last * ditch one. - * - The above all works for bound all, but bound specific we need to + * - The above all works for bound all, but bound specific we need to * use the same concept but instead only consider the bound * addresses. If the bound set is NOT assigned to the interface then * we must use rotation amongst the bound addresses.. @@ -8913,6 +8913,9 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, if ((chk->rec.chunk_id.id == SCTP_COOKIE_ECHO) || (chk->rec.chunk_id.id == SCTP_STREAM_RESET) || (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN)) { + if (chk->sent != SCTP_DATAGRAM_RESEND) { + continue; + } if (chk->rec.chunk_id.id == SCTP_STREAM_RESET) { if (chk != asoc->str_reset) { /* @@ -8973,7 +8976,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, /* (void)SCTP_GETTIME_TIMEVAL(&chk->whoTo->last_sent_time); */ *cnt_out += 1; chk->sent = SCTP_DATAGRAM_SENT; - /* sctp_ucount_decr(asoc->sent_queue_retran_cnt); */ + sctp_ucount_decr(stcb->asoc.sent_queue_retran_cnt); if (fwd_tsn == 0) { return (0); } else { @@ -13426,6 +13429,13 @@ out_unlocked: panic("Leaving with tcb send mtx owned?"); } } +#endif +#ifdef INVARIANTS + if (inp) { + sctp_validate_no_locks(inp); + } else { + printf("Warning - inp is NULL so cant validate locks\n"); + } #endif if (top) { sctp_m_freem(top); diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index bbf62e487..b5ca4b530 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -692,13 +692,11 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); wi->ifa = sctp_ifap; wi->action = SCTP_ADD_IP_ADDRESS; - SCTP_IPI_ITERATOR_WQ_LOCK(); - /* - * Should this really be a tailq? As it is we will process - * the newest first :-0 - */ + + SCTP_WQ_ADDR_LOCK(); LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); - SCTP_IPI_ITERATOR_WQ_UNLOCK(); + SCTP_WQ_ADDR_UNLOCK(); + sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, @@ -806,13 +804,13 @@ out_now: (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); wi->ifa = sctp_ifap; wi->action = SCTP_DEL_IP_ADDRESS; - SCTP_IPI_ITERATOR_WQ_LOCK(); + SCTP_WQ_ADDR_LOCK(); /* * Should this really be a tailq? As it is we will process * the newest first :-0 */ LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); - SCTP_IPI_ITERATOR_WQ_UNLOCK(); + SCTP_WQ_ADDR_UNLOCK(); sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, @@ -2298,7 +2296,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) if (inp->sctp_asocidhash == NULL) { SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_INP_INFO_WUNLOCK(); - return error; + return (ENOBUFS); } #ifdef IPSEC { @@ -2340,6 +2338,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) * in protosw */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); + so->so_pcb = NULL; SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (EOPNOTSUPP); } @@ -2358,6 +2357,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) if (inp->sctp_tcbhash == NULL) { SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n"); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); + so->so_pcb = NULL; SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); } @@ -3017,57 +3017,68 @@ continue_anyway: static void -sctp_iterator_inp_being_freed(struct sctp_inpcb *inp, struct sctp_inpcb *inp_next) +sctp_iterator_inp_being_freed(struct sctp_inpcb *inp) { - struct sctp_iterator *it; + struct sctp_iterator *it, *nit; /* * We enter with the only the ITERATOR_LOCK in place and a write * lock on the inp_info stuff. */ - + it = sctp_it_ctl.cur_it; + if (it && (it->vn != curvnet)) { + /* Its not looking at our VNET */ + return; + } + if (it && (it->inp == inp)) { + /* + * This is tricky and we hold the iterator lock, but when it + * returns and gets the lock (when we release it) the + * iterator will try to operate on inp. We need to stop that + * from happening. But of course the iterator has a + * reference on the stcb and inp. We can mark it and it will + * stop. + * + * If its a single iterator situation, we set the end iterator + * flag. Otherwise we set the iterator to go to the next + * inp. + * + */ + if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { + sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; + } else { + sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_INP; + } + } /* - * Go through all iterators, we must do this since it is possible - * that some iterator does NOT have the lock, but is waiting for it. - * And the one that had the lock has either moved in the last - * iteration or we just cleared it above. We need to find all of - * those guys. The list of iterators should never be very big - * though. + * Now go through and remove any single reference to our inp that + * may be still pending on the list */ - TAILQ_FOREACH(it, &SCTP_BASE_INFO(iteratorhead), sctp_nxt_itr) { - if (it == inp->inp_starting_point_for_iterator) - /* skip this guy, he's special */ + SCTP_IPI_ITERATOR_WQ_LOCK(); + it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead); + while (it) { + nit = TAILQ_NEXT(it, sctp_nxt_itr); + if (it->vn != curvnet) { + it = nit; continue; + } if (it->inp == inp) { - /* - * This is tricky and we DON'T lock the iterator. - * Reason is he's running but waiting for me since - * inp->inp_starting_point_for_iterator has the lock - * on me (the guy above we skipped). This tells us - * its is not running but waiting for - * inp->inp_starting_point_for_iterator to be - * released by the guy that does have our INP in a - * lock. - */ + /* This one points to me is it inp specific? */ if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { - it->inp = NULL; - it->stcb = NULL; + /* Remove and free this one */ + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, + it, sctp_nxt_itr); + if (it->function_atend != NULL) { + (*it->function_atend) (it->pointer, it->val); + } + SCTP_FREE(it, SCTP_M_ITER); } else { - /* set him up to do the next guy not me */ - it->inp = inp_next; - it->stcb = NULL; + it->inp = LIST_NEXT(it->inp, sctp_list); } } + it = nit; } - it = inp->inp_starting_point_for_iterator; - if (it) { - if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { - it->inp = NULL; - } else { - it->inp = inp_next; - } - it->stcb = NULL; - } + SCTP_IPI_ITERATOR_WQ_UNLOCK(); } /* release sctp_inpcb unbind the port */ @@ -3083,12 +3094,11 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) * all associations. d) finally the ep itself. */ struct sctp_pcb *m; - struct sctp_inpcb *inp_save; struct sctp_tcb *asoc, *nasoc; struct sctp_laddr *laddr, *nladdr; struct inpcb *ip_pcb; struct socket *so; - + int being_refed = 0; struct sctp_queued_to_read *sq; @@ -3099,12 +3109,21 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 0); #endif - SCTP_ITERATOR_LOCK(); + if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) { + /* + * Once we are in we can remove the flag from = 1 is only + * passed from the actual closing routines that are called + * via the sockets layer. + */ + SCTP_ITERATOR_LOCK(); + /* mark any iterators on the list or being processed */ + sctp_iterator_inp_being_freed(inp); + SCTP_ITERATOR_UNLOCK(); + } so = inp->sctp_socket; if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { /* been here before.. eeks.. get out of here */ SCTP_PRINTF("This conflict in free SHOULD not be happening! from %d, imm %d\n", from, immediate); - SCTP_ITERATOR_UNLOCK(); #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 1); #endif @@ -3114,19 +3133,15 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) SCTP_INP_INFO_WLOCK(); SCTP_INP_WLOCK(inp); - /* First time through we have the socket lock, after that no more. */ if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) { - /* - * Once we are in we can remove the flag from = 1 is only - * passed from the actual closing routines that are called - * via the sockets layer. - */ inp->sctp_flags &= ~SCTP_PCB_FLAGS_CLOSE_IP; /* socket is gone, so no more wakeups allowed */ inp->sctp_flags |= SCTP_PCB_FLAGS_DONT_WAKE; inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT; inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT; + } + /* First time through we have the socket lock, after that no more. */ sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL, SCTP_FROM_SCTP_PCB + SCTP_LOC_1); @@ -3152,8 +3167,17 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) nasoc = LIST_NEXT(asoc, sctp_tcblist); if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { /* Skip guys being freed */ - /* asoc->sctp_socket = NULL; FIXME MT */ cnt_in_sd++; + if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) { + /* + * Special case - we did not start a + * kill timer on the asoc due to it + * was not closed. So go ahead and + * start it now. + */ + asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; + sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL); + } SCTP_TCB_UNLOCK(asoc); continue; } @@ -3314,14 +3338,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) } /* now is there some left in our SHUTDOWN state? */ if (cnt_in_sd) { - SCTP_INP_WUNLOCK(inp); - SCTP_ASOC_CREATE_UNLOCK(inp); - SCTP_INP_INFO_WUNLOCK(); - SCTP_ITERATOR_UNLOCK(); #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 2); #endif inp->sctp_socket = NULL; + SCTP_INP_WUNLOCK(inp); + SCTP_ASOC_CREATE_UNLOCK(inp); + SCTP_INP_INFO_WUNLOCK(); return; } } @@ -3344,6 +3367,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) asoc = nasoc) { nasoc = LIST_NEXT(asoc, sctp_tcblist); if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { + if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) { + asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; + sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL); + } cnt++; continue; } @@ -3392,38 +3419,62 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) if (cnt) { /* Ok we have someone out there that will kill us */ (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); - SCTP_INP_WUNLOCK(inp); - SCTP_ASOC_CREATE_UNLOCK(inp); - SCTP_INP_INFO_WUNLOCK(); - SCTP_ITERATOR_UNLOCK(); #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 3); #endif + SCTP_INP_WUNLOCK(inp); + SCTP_ASOC_CREATE_UNLOCK(inp); + SCTP_INP_INFO_WUNLOCK(); return; } - if ((inp->refcount) || (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { + if (SCTP_INP_LOCK_CONTENDED(inp)) + being_refed++; + if (SCTP_INP_READ_CONTENDED(inp)) + being_refed++; + if (SCTP_ASOC_CREATE_LOCK_CONTENDED(inp)) + being_refed++; + + if ((inp->refcount) || + (being_refed) || + (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); +#ifdef SCTP_LOG_CLOSING + sctp_log_closing(inp, NULL, 4); +#endif sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL); SCTP_INP_WUNLOCK(inp); SCTP_ASOC_CREATE_UNLOCK(inp); SCTP_INP_INFO_WUNLOCK(); - SCTP_ITERATOR_UNLOCK(); -#ifdef SCTP_LOG_CLOSING - sctp_log_closing(inp, NULL, 4); -#endif return; } - (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); inp->sctp_ep.signature_change.type = 0; inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_ALLGONE; + /* + * Remove it from the list .. last thing we need a lock for. + */ + LIST_REMOVE(inp, sctp_list); + SCTP_INP_WUNLOCK(inp); + SCTP_ASOC_CREATE_UNLOCK(inp); + SCTP_INP_INFO_WUNLOCK(); + /* + * Now we release all locks. Since this INP cannot be found anymore + * except possbily by the kill timer that might be running. We call + * the drain function here. It should hit the case were it sees the + * ACTIVE flag cleared and exit out freeing us to proceed and + * destroy everything. + */ + if (from != SCTP_CALLED_FROM_INPKILL_TIMER) { + (void)SCTP_OS_TIMER_STOP_DRAIN(&inp->sctp_ep.signature_change.timer); + } else { + /* Probably un-needed */ + (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); + } #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 5); #endif - (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); - inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NONE; - /* Clear the read queue */ + if ((inp->sctp_asocidhash) != NULL) { SCTP_HASH_FREE(inp->sctp_asocidhash, inp->hashasocidmark); inp->sctp_asocidhash = NULL; @@ -3494,11 +3545,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) shared_key = LIST_FIRST(&inp->sctp_ep.shared_keys); } - inp_save = LIST_NEXT(inp, sctp_list); - LIST_REMOVE(inp, sctp_list); - - /* fix any iterators only after out of the list */ - sctp_iterator_inp_being_freed(inp, inp_save); /* * if we have an address list the following will free the list of * ifaddr's that are set into this ep. Again macro limitations here, @@ -3531,8 +3577,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) SCTP_INP_LOCK_DESTROY(inp); SCTP_INP_READ_DESTROY(inp); SCTP_ASOC_CREATE_LOCK_DESTROY(inp); - SCTP_INP_INFO_WUNLOCK(); - SCTP_ITERATOR_UNLOCK(); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_DECR_EP_COUNT(); } @@ -4581,8 +4625,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre * Someone holds a reference OR the socket is unaccepted * yet. */ - if (stcb->asoc.refcnt) + if ((stcb->asoc.refcnt) || + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { + stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); + } SCTP_TCB_UNLOCK(stcb); if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) @@ -4645,8 +4693,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre SS_ISCONFIRMING | SS_ISCONNECTED); } - SOCK_UNLOCK(so); - socantrcvmore(so); + socantrcvmore_locked(so); sctp_sowwakeup(inp, so); sctp_sorwakeup(inp, so); SCTP_SOWAKEUP(so); @@ -5436,8 +5483,6 @@ sctp_pcb_init() /* init the empty list of (All) Endpoints */ LIST_INIT(&SCTP_BASE_INFO(listhead)); - /* init the iterator head */ - TAILQ_INIT(&SCTP_BASE_INFO(iteratorhead)); /* init the hash table of endpoints */ TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &SCTP_BASE_SYSCTL(sctp_hashtblsize)); @@ -5500,16 +5545,15 @@ sctp_pcb_init() /* Master Lock INIT for info structure */ SCTP_INP_INFO_LOCK_INIT(); SCTP_STATLOG_INIT_LOCK(); - SCTP_ITERATOR_LOCK_INIT(); SCTP_IPI_COUNT_INIT(); SCTP_IPI_ADDR_INIT(); - SCTP_IPI_ITERATOR_WQ_INIT(); #ifdef SCTP_PACKET_LOGGING SCTP_IP_PKTLOG_INIT(); #endif LIST_INIT(&SCTP_BASE_INFO(addr_wq)); + SCTP_WQ_ADDR_INIT(); /* not sure if we need all the counts */ SCTP_BASE_INFO(ipi_count_ep) = 0; /* assoc/tcb zone info */ @@ -5537,11 +5581,7 @@ sctp_pcb_init() LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]); } -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) - SCTP_BASE_INFO(iterator_running) = 0; - SCTP_BASE_INFO(threads_must_exit) = 0; sctp_startup_iterator(); -#endif /* * INIT the default VRF which for BSD is the only one, other O/S's @@ -5565,30 +5605,49 @@ sctp_pcb_finish(void) struct sctpvtaghead *chain; struct sctp_tagblock *twait_block, *prev_twait_block; struct sctp_laddr *wi; - struct sctp_iterator *it; int i; -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) - SCTP_BASE_INFO(threads_must_exit) = 1; - /* Wake the thread up so it will exit now */ - sctp_wakeup_iterator(); + /* + * Free BSD the it thread never exits but we do clean up. The only + * way freebsd reaches here if we have VRF's but we still add the + * ifdef to make it compile on old versions. + */ + { + struct sctp_iterator *it, *nit; + + SCTP_IPI_ITERATOR_WQ_LOCK(); + it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead); + while (it) { + nit = TAILQ_NEXT(it, sctp_nxt_itr); + if (it->vn != curvnet) { + it = nit; + continue; + } + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, + it, sctp_nxt_itr); + if (it->function_atend != NULL) { + (*it->function_atend) (it->pointer, it->val); + } + SCTP_FREE(it, SCTP_M_ITER); + it = nit; + } + SCTP_IPI_ITERATOR_WQ_UNLOCK(); + SCTP_ITERATOR_LOCK(); + if ((sctp_it_ctl.cur_it) && + (sctp_it_ctl.cur_it->vn == curvnet)) { + sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; + } + SCTP_ITERATOR_UNLOCK(); + } -#endif SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer)); - SCTP_IPI_ITERATOR_WQ_LOCK(); + SCTP_WQ_ADDR_LOCK(); while ((wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq))) != NULL) { LIST_REMOVE(wi, sctp_nxt_addr); SCTP_DECR_LADDR_COUNT(); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi); } - SCTP_IPI_ITERATOR_WQ_UNLOCK(); - while ((it = TAILQ_FIRST(&SCTP_BASE_INFO(iteratorhead))) != NULL) { - if (it->function_atend != NULL) { - (*it->function_atend) (it->pointer, it->val); - } - TAILQ_REMOVE(&SCTP_BASE_INFO(iteratorhead), it, sctp_nxt_itr); - SCTP_FREE(it, SCTP_M_ITER); - } + SCTP_WQ_ADDR_UNLOCK(); /* * free the vrf/ifn/ifa lists and hashes (be sure address monitor is @@ -5640,10 +5699,11 @@ sctp_pcb_finish(void) SCTP_IP_PKTLOG_DESTROY(); #endif SCTP_IPI_ADDR_DESTROY(); - SCTP_ITERATOR_LOCK_DESTROY(); SCTP_STATLOG_DESTROY(); SCTP_INP_INFO_LOCK_DESTROY(); + SCTP_WQ_ADDR_DESTROY(); + SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_ep)); SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asoc)); SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_laddr)); @@ -6632,6 +6692,7 @@ sctp_initiate_iterator(inp_func inpf, it->asoc_state = asoc_state; it->function_inp_end = inpe; it->no_chunk_output = chunk_output_off; + it->vn = curvnet; if (s_inp) { it->inp = s_inp; it->iterator_flags = SCTP_ITERATOR_DO_SINGLE_INP; @@ -6647,22 +6708,11 @@ sctp_initiate_iterator(inp_func inpf, if (it->inp) { SCTP_INP_INCR_REF(it->inp); } - TAILQ_INSERT_TAIL(&SCTP_BASE_INFO(iteratorhead), it, sctp_nxt_itr); -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) - if (SCTP_BASE_INFO(iterator_running) == 0) { + TAILQ_INSERT_TAIL(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); + if (sctp_it_ctl.iterator_running == 0) { sctp_wakeup_iterator(); } SCTP_IPI_ITERATOR_WQ_UNLOCK(); -#else - if (it->inp) - SCTP_INP_DECR_REF(it->inp); - SCTP_IPI_ITERATOR_WQ_UNLOCK(); - /* Init the timer */ - SCTP_OS_TIMER_INIT(&it->tmr.timer); - /* add to the list of all iterators */ - sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, (struct sctp_inpcb *)it, - NULL, NULL); -#endif /* sa_ignore MEMLEAK {memory is put on the tailq for the iterator} */ return (0); } diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 1a468f863..318b01258 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -177,8 +177,6 @@ struct sctp_epinfo { struct sctppcbhead listhead; struct sctpladdr addr_wq; - struct sctpiterators iteratorhead; - int threads_must_exit; /* ep zone info */ sctp_zone_t ipi_zone_ep; sctp_zone_t ipi_zone_asoc; @@ -191,10 +189,10 @@ struct sctp_epinfo { sctp_zone_t ipi_zone_asconf_ack; struct rwlock ipi_ep_mtx; - struct mtx it_mtx; struct mtx ipi_iterator_wq_mtx; struct rwlock ipi_addr_mtx; struct mtx ipi_pktlog_mtx; + struct mtx wq_addr_mtx; uint32_t ipi_count_ep; /* assoc/tcb zone info */ @@ -228,14 +226,9 @@ struct sctp_epinfo { uint32_t ipi_free_chunks; uint32_t ipi_free_strmoq; - struct sctpvtaghead vtag_timewait[SCTP_STACK_VTAG_HASH_SIZE]; /* address work queue handling */ -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) - uint32_t iterator_running; - SCTP_PROCESS_STRUCT thread_proc; -#endif struct sctp_timer addr_wq_timer; }; @@ -628,5 +621,11 @@ sctp_initiate_iterator(inp_func inpf, struct sctp_inpcb *, uint8_t co_off); +#ifdef INVARIANTS +void + sctp_validate_no_locks(struct sctp_inpcb *inp); + +#endif + #endif /* _KERNEL */ #endif /* !__sctp_pcb_h__ */ diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index cd798b521..ed443011a 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -108,9 +108,11 @@ typedef void (*end_func) (void *ptr, uint32_t val); struct sctp_iterator { TAILQ_ENTRY(sctp_iterator) sctp_nxt_itr; + struct vnet *vn; struct sctp_timer tmr; struct sctp_inpcb *inp; /* current endpoint */ struct sctp_tcb *stcb; /* current* assoc */ + struct sctp_inpcb *next_inp; /* special hook to skip to */ asoc_func function_assoc; /* per assoc function */ inp_func function_inp; /* per endpoint function */ inp_func function_inp_end; /* end INP function */ @@ -129,6 +131,7 @@ struct sctp_iterator { #define SCTP_ITERATOR_DO_ALL_INP 0x00000001 #define SCTP_ITERATOR_DO_SINGLE_INP 0x00000002 + TAILQ_HEAD(sctpiterators, sctp_iterator); struct sctp_copy_all { @@ -145,6 +148,20 @@ struct sctp_asconf_iterator { int cnt; }; +struct iterator_control { + struct mtx ipi_iterator_wq_mtx; + struct mtx it_mtx; + SCTP_PROCESS_STRUCT thread_proc; + struct sctpiterators iteratorhead; + struct sctp_iterator *cur_it; + uint32_t iterator_running; + uint32_t iterator_flags; +}; + +#define SCTP_ITERATOR_MUST_EXIT 0x00000001 +#define SCTP_ITERATOR_STOP_CUR_IT 0x00000002 +#define SCTP_ITERATOR_STOP_CUR_INP 0x00000004 + struct sctp_net_route { sctp_rtentry_t *ro_rt; void *ro_lle; diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index c9967eae0..9ba7dd40b 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -331,6 +331,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) struct xsctp_inpcb xinpcb; struct xsctp_tcb xstcb; struct xsctp_raddr xraddr; + struct socket *so; number_of_endpoints = 0; number_of_local_addresses = 0; @@ -369,6 +370,10 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) } LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { SCTP_INP_RLOCK(inp); + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { + /* if its allgone it is being freed - skip it */ + goto skip; + } xinpcb.last = 0; xinpcb.local_port = ntohs(inp->sctp_lport); xinpcb.flags = inp->sctp_flags; @@ -377,13 +382,14 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) xinpcb.total_recvs = inp->total_recvs; xinpcb.total_nospaces = inp->total_nospaces; xinpcb.fragmentation_point = inp->sctp_frag_point; - if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || + so = inp->sctp_socket; + if ((so == NULL) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { xinpcb.qlen = 0; xinpcb.maxqlen = 0; } else { - xinpcb.qlen = inp->sctp_socket->so_qlen; - xinpcb.maxqlen = inp->sctp_socket->so_qlimit; + xinpcb.qlen = so->so_qlen; + xinpcb.maxqlen = so->so_qlimit; } SCTP_INP_INCR_REF(inp); SCTP_INP_RUNLOCK(inp); @@ -501,6 +507,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) if (error) { return error; } +skip: SCTP_INP_INFO_RLOCK(); } SCTP_INP_INFO_RUNLOCK(); diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 334401838..646c1127c 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -1880,143 +1880,3 @@ sctp_autoclose_timer(struct sctp_inpcb *inp, } } } - -void -sctp_iterator_timer(struct sctp_iterator *it) -{ - int iteration_count = 0; - int inp_skip = 0; - - /* - * only one iterator can run at a time. This is the only way we can - * cleanly pull ep's from underneath all the running interators when - * a ep is freed. - */ - SCTP_ITERATOR_LOCK(); - if (it->inp == NULL) { - /* iterator is complete */ -done_with_iterator: - SCTP_ITERATOR_UNLOCK(); - SCTP_INP_INFO_WLOCK(); - TAILQ_REMOVE(&SCTP_BASE_INFO(iteratorhead), it, sctp_nxt_itr); - /* stopping the callout is not needed, in theory */ - SCTP_INP_INFO_WUNLOCK(); - (void)SCTP_OS_TIMER_STOP(&it->tmr.timer); - if (it->function_atend != NULL) { - (*it->function_atend) (it->pointer, it->val); - } - SCTP_FREE(it, SCTP_M_ITER); - return; - } -select_a_new_ep: - SCTP_INP_WLOCK(it->inp); - while (((it->pcb_flags) && - ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || - ((it->pcb_features) && - ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { - /* endpoint flags or features don't match, so keep looking */ - if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { - SCTP_INP_WUNLOCK(it->inp); - goto done_with_iterator; - } - SCTP_INP_WUNLOCK(it->inp); - it->inp = LIST_NEXT(it->inp, sctp_list); - if (it->inp == NULL) { - goto done_with_iterator; - } - SCTP_INP_WLOCK(it->inp); - } - if ((it->inp->inp_starting_point_for_iterator != NULL) && - (it->inp->inp_starting_point_for_iterator != it)) { - SCTP_PRINTF("Iterator collision, waiting for one at %p\n", - it->inp); - SCTP_INP_WUNLOCK(it->inp); - goto start_timer_return; - } - /* mark the current iterator on the endpoint */ - it->inp->inp_starting_point_for_iterator = it; - SCTP_INP_WUNLOCK(it->inp); - SCTP_INP_RLOCK(it->inp); - /* now go through each assoc which is in the desired state */ - if (it->done_current_ep == 0) { - if (it->function_inp != NULL) - inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val); - it->done_current_ep = 1; - } - if (it->stcb == NULL) { - /* run the per instance function */ - it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list); - } - SCTP_INP_RUNLOCK(it->inp); - if ((inp_skip) || it->stcb == NULL) { - if (it->function_inp_end != NULL) { - inp_skip = (*it->function_inp_end) (it->inp, - it->pointer, - it->val); - } - goto no_stcb; - } - if ((it->stcb) && - (it->stcb->asoc.stcb_starting_point_for_iterator == it)) { - it->stcb->asoc.stcb_starting_point_for_iterator = NULL; - } - while (it->stcb) { - SCTP_TCB_LOCK(it->stcb); - if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) { - /* not in the right state... keep looking */ - SCTP_TCB_UNLOCK(it->stcb); - goto next_assoc; - } - /* mark the current iterator on the assoc */ - it->stcb->asoc.stcb_starting_point_for_iterator = it; - /* see if we have limited out the iterator loop */ - iteration_count++; - if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) { - start_timer_return: - /* set a timer to continue this later */ - if (it->stcb) - SCTP_TCB_UNLOCK(it->stcb); - sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, - (struct sctp_inpcb *)it, NULL, NULL); - SCTP_ITERATOR_UNLOCK(); - return; - } - /* run function on this one */ - (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val); - - /* - * we lie here, it really needs to have its own type but - * first I must verify that this won't effect things :-0 - */ - if (it->no_chunk_output == 0) - sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); - - SCTP_TCB_UNLOCK(it->stcb); -next_assoc: - it->stcb = LIST_NEXT(it->stcb, sctp_tcblist); - if (it->stcb == NULL) { - if (it->function_inp_end != NULL) { - inp_skip = (*it->function_inp_end) (it->inp, - it->pointer, - it->val); - } - } - } -no_stcb: - /* done with all assocs on this endpoint, move on to next endpoint */ - it->done_current_ep = 0; - SCTP_INP_WLOCK(it->inp); - it->inp->inp_starting_point_for_iterator = NULL; - SCTP_INP_WUNLOCK(it->inp); - if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { - it->inp = NULL; - } else { - SCTP_INP_INFO_RLOCK(); - it->inp = LIST_NEXT(it->inp, sctp_list); - SCTP_INP_INFO_RUNLOCK(); - } - if (it->inp == NULL) { - goto done_with_iterator; - } - goto select_a_new_ep; -} diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index ed2a95df4..bb590e97a 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -4678,6 +4678,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr) struct sockaddr_in *sin; SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); + if (sin == NULL) + return (ENOMEM); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_port = ((struct sockaddr_in *)&store)->sin_port; @@ -4691,6 +4693,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr) struct sockaddr_in6 *sin6; SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6); + if (sin6 == NULL) + return (ENOMEM); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port; @@ -4756,6 +4760,8 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr) * Do the malloc first in case it blocks. */ SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); + if (sin == NULL) + return (ENOMEM); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); inp = (struct sctp_inpcb *)so->so_pcb; @@ -4858,6 +4864,8 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr) return (ENOTCONN); } SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); + if (sin == NULL) + return (ENOMEM); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 04f76732c..dea903603 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -48,19 +48,14 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #define NUMBER_OF_MTU_SIZES 18 -#if defined(__Windows__) && !defined(SCTP_LOCAL_TRACE_BUF) -#include "eventrace_netinet.h" -#include "sctputil.tmh" /* this is the file that will be auto - * generated */ -#else #ifndef KTR_SCTP #define KTR_SCTP KTR_SUBSYS #endif -#endif void sctp_sblog(struct sockbuf *sb, @@ -1255,7 +1250,6 @@ sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) } -#if defined(SCTP_USE_THREAD_BASED_ITERATOR) static void sctp_iterator_work(struct sctp_iterator *it) { @@ -1277,27 +1271,23 @@ done_with_iterator: return; } select_a_new_ep: - SCTP_INP_WLOCK(it->inp); + SCTP_INP_RLOCK(it->inp); while (((it->pcb_flags) && ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || ((it->pcb_features) && ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { /* endpoint flags or features don't match, so keep looking */ if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { - SCTP_INP_WUNLOCK(it->inp); + SCTP_INP_RUNLOCK(it->inp); goto done_with_iterator; } - SCTP_INP_WUNLOCK(it->inp); + SCTP_INP_RUNLOCK(it->inp); it->inp = LIST_NEXT(it->inp, sctp_list); if (it->inp == NULL) { goto done_with_iterator; } - SCTP_INP_WLOCK(it->inp); + SCTP_INP_RLOCK(it->inp); } - - SCTP_INP_WUNLOCK(it->inp); - SCTP_INP_RLOCK(it->inp); - /* now go through each assoc which is in the desired state */ if (it->done_current_ep == 0) { if (it->function_inp != NULL) @@ -1330,13 +1320,34 @@ select_a_new_ep: /* Pause to let others grab the lock */ atomic_add_int(&it->stcb->asoc.refcnt, 1); SCTP_TCB_UNLOCK(it->stcb); - SCTP_INP_INCR_REF(it->inp); SCTP_INP_RUNLOCK(it->inp); SCTP_ITERATOR_UNLOCK(); SCTP_ITERATOR_LOCK(); + if (sctp_it_ctl.iterator_flags) { + /* We won't be staying here */ + SCTP_INP_DECR_REF(it->inp); + atomic_add_int(&it->stcb->asoc.refcnt, -1); + if (sctp_it_ctl.iterator_flags & + SCTP_ITERATOR_MUST_EXIT) { + goto done_with_iterator; + } + if (sctp_it_ctl.iterator_flags & + SCTP_ITERATOR_STOP_CUR_IT) { + sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT; + goto done_with_iterator; + } + if (sctp_it_ctl.iterator_flags & + SCTP_ITERATOR_STOP_CUR_INP) { + sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP; + goto no_stcb; + } + /* If we reach here huh? */ + printf("Unknown it ctl flag %x\n", + sctp_it_ctl.iterator_flags); + sctp_it_ctl.iterator_flags = 0; + } SCTP_INP_RLOCK(it->inp); - SCTP_INP_DECR_REF(it->inp); SCTP_TCB_LOCK(it->stcb); atomic_add_int(&it->stcb->asoc.refcnt, -1); @@ -1368,8 +1379,6 @@ next_assoc: no_stcb: /* done with all assocs on this endpoint, move on to next endpoint */ it->done_current_ep = 0; - SCTP_INP_WLOCK(it->inp); - SCTP_INP_WUNLOCK(it->inp); if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { it->inp = NULL; } else { @@ -1390,27 +1399,28 @@ sctp_iterator_worker(void) /* This function is called with the WQ lock in place */ - SCTP_BASE_INFO(iterator_running) = 1; -again: - it = TAILQ_FIRST(&SCTP_BASE_INFO(iteratorhead)); + sctp_it_ctl.iterator_running = 1; + sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead); while (it) { /* now lets work on this one */ - TAILQ_REMOVE(&SCTP_BASE_INFO(iteratorhead), it, sctp_nxt_itr); + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); SCTP_IPI_ITERATOR_WQ_UNLOCK(); + CURVNET_SET(it->vn); sctp_iterator_work(it); + + CURVNET_RESTORE(); SCTP_IPI_ITERATOR_WQ_LOCK(); + if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) { + sctp_it_ctl.cur_it = NULL; + break; + } /* sa_ignore FREED_MEMORY */ - it = TAILQ_FIRST(&SCTP_BASE_INFO(iteratorhead)); - } - if (TAILQ_FIRST(&SCTP_BASE_INFO(iteratorhead))) { - goto again; + sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead); } - SCTP_BASE_INFO(iterator_running) = 0; + sctp_it_ctl.iterator_running = 0; return; } -#endif - static void sctp_handle_addr_wq(void) @@ -1431,7 +1441,8 @@ sctp_handle_addr_wq(void) } LIST_INIT(&asc->list_of_work); asc->cnt = 0; - SCTP_IPI_ITERATOR_WQ_LOCK(); + + SCTP_WQ_ADDR_LOCK(); wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq)); while (wi != NULL) { LIST_REMOVE(wi, sctp_nxt_addr); @@ -1439,7 +1450,8 @@ sctp_handle_addr_wq(void) asc->cnt++; wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq)); } - SCTP_IPI_ITERATOR_WQ_UNLOCK(); + SCTP_WQ_ADDR_UNLOCK(); + if (asc->cnt == 0) { SCTP_FREE(asc, SCTP_M_ASC_IT); } else { @@ -1470,7 +1482,6 @@ sctp_timeout_handler(void *t) #endif int did_output, type; - struct sctp_iterator *it = NULL; tmr = (struct sctp_timer *)t; inp = (struct sctp_inpcb *)tmr->ep; @@ -1509,10 +1520,6 @@ sctp_timeout_handler(void *t) } /* if this is an iterator timeout, get the struct and clear inp */ tmr->stopped_from = 0xa003; - if (tmr->type == SCTP_TIMER_TYPE_ITERATOR) { - it = (struct sctp_iterator *)inp; - inp = NULL; - } type = tmr->type; if (inp) { SCTP_INP_INCR_REF(inp); @@ -1611,10 +1618,6 @@ sctp_timeout_handler(void *t) case SCTP_TIMER_TYPE_ADDR_WQ: sctp_handle_addr_wq(); break; - case SCTP_TIMER_TYPE_ITERATOR: - SCTP_STAT_INCR(sctps_timoiterator); - sctp_iterator_timer(it); - break; case SCTP_TIMER_TYPE_SEND: if ((stcb == NULL) || (inp == NULL)) { break; @@ -1895,7 +1898,7 @@ sctp_timeout_handler(void *t) SCTP_INP_DECR_REF(inp); sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3); sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, - SCTP_CALLED_DIRECTLY_NOCMPSET); + SCTP_CALLED_FROM_INPKILL_TIMER); inp = NULL; goto out_no_decr; default: @@ -1962,15 +1965,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, tmr = &SCTP_BASE_INFO(addr_wq_timer); to_ticks = SCTP_ADDRESS_TICK_DELAY; break; - case SCTP_TIMER_TYPE_ITERATOR: - { - struct sctp_iterator *it; - - it = (struct sctp_iterator *)inp; - tmr = &it->tmr; - to_ticks = SCTP_ITERATOR_TICKS; - } - break; case SCTP_TIMER_TYPE_SEND: /* Here we use the RTO timer */ { @@ -2327,14 +2321,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, tmr = &net->fr_timer; SCTP_STAT_INCR(sctps_earlyfrstop); break; - case SCTP_TIMER_TYPE_ITERATOR: - { - struct sctp_iterator *it; - - it = (struct sctp_iterator *)inp; - tmr = &it->tmr; - } - break; case SCTP_TIMER_TYPE_SEND: if ((stcb == NULL) || (net == NULL)) { return; @@ -3837,13 +3823,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif - } else { - if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { - if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) { - sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, - SCTP_CALLED_DIRECTLY_NOCMPSET); - } - } } } @@ -4215,7 +4194,7 @@ void sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh) { switch (iph->ip_v) { - case IPVERSION: + case IPVERSION: { struct sockaddr_in lsa, fsa; @@ -6154,13 +6133,13 @@ sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id) atomic_add_int(&ifa->refcount, 1); /* Now add it to the work queue */ - SCTP_IPI_ITERATOR_WQ_LOCK(); + SCTP_WQ_ADDR_LOCK(); /* * Should this really be a tailq? As it is we will process the * newest first :-0 */ LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); - SCTP_IPI_ITERATOR_WQ_UNLOCK(); + SCTP_WQ_ADDR_UNLOCK(); sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, -- 2.45.0