Home | History | Annotate | Line # | Download | only in netinet
sctp_timer.c revision 1.3.14.2
      1  1.3.14.2  jdolecek /*	$KAME: sctp_timer.c,v 1.30 2005/06/16 18:29:25 jinmei Exp $	*/
      2  1.3.14.2  jdolecek /*	$NetBSD: sctp_timer.c,v 1.3.14.2 2017/12/03 11:39:04 jdolecek Exp $	*/
      3  1.3.14.2  jdolecek 
      4  1.3.14.2  jdolecek /*
      5  1.3.14.2  jdolecek  * Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
      6  1.3.14.2  jdolecek  * All rights reserved.
      7  1.3.14.2  jdolecek  *
      8  1.3.14.2  jdolecek  * Redistribution and use in source and binary forms, with or without
      9  1.3.14.2  jdolecek  * modification, are permitted provided that the following conditions
     10  1.3.14.2  jdolecek  * are met:
     11  1.3.14.2  jdolecek  * 1. Redistributions of source code must retain the above copyright
     12  1.3.14.2  jdolecek  *    notice, this list of conditions and the following disclaimer.
     13  1.3.14.2  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.3.14.2  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     15  1.3.14.2  jdolecek  *    documentation and/or other materials provided with the distribution.
     16  1.3.14.2  jdolecek  * 3. Neither the name of the project nor the names of its contributors
     17  1.3.14.2  jdolecek  *    may be used to endorse or promote products derived from this software
     18  1.3.14.2  jdolecek  *    without specific prior written permission.
     19  1.3.14.2  jdolecek  *
     20  1.3.14.2  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     21  1.3.14.2  jdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  1.3.14.2  jdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  1.3.14.2  jdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     24  1.3.14.2  jdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25  1.3.14.2  jdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26  1.3.14.2  jdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  1.3.14.2  jdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  1.3.14.2  jdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  1.3.14.2  jdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  1.3.14.2  jdolecek  * SUCH DAMAGE.
     31  1.3.14.2  jdolecek  */
     32  1.3.14.2  jdolecek #include <sys/cdefs.h>
     33  1.3.14.2  jdolecek __KERNEL_RCSID(0, "$NetBSD: sctp_timer.c,v 1.3.14.2 2017/12/03 11:39:04 jdolecek Exp $");
     34  1.3.14.2  jdolecek 
     35  1.3.14.2  jdolecek #ifdef _KERNEL_OPT
     36  1.3.14.2  jdolecek #include "opt_inet.h"
     37  1.3.14.2  jdolecek #include "opt_sctp.h"
     38  1.3.14.2  jdolecek #endif /* _KERNEL_OPT */
     39  1.3.14.2  jdolecek 
     40  1.3.14.2  jdolecek #include <sys/param.h>
     41  1.3.14.2  jdolecek #include <sys/systm.h>
     42  1.3.14.2  jdolecek #include <sys/malloc.h>
     43  1.3.14.2  jdolecek #include <sys/mbuf.h>
     44  1.3.14.2  jdolecek #include <sys/domain.h>
     45  1.3.14.2  jdolecek #include <sys/protosw.h>
     46  1.3.14.2  jdolecek #include <sys/socket.h>
     47  1.3.14.2  jdolecek #include <sys/socketvar.h>
     48  1.3.14.2  jdolecek #include <sys/proc.h>
     49  1.3.14.2  jdolecek #include <sys/kernel.h>
     50  1.3.14.2  jdolecek #include <sys/sysctl.h>
     51  1.3.14.2  jdolecek #ifdef INET6
     52  1.3.14.2  jdolecek #include <sys/domain.h>
     53  1.3.14.2  jdolecek #endif
     54  1.3.14.2  jdolecek 
     55  1.3.14.2  jdolecek #include <machine/limits.h>
     56  1.3.14.2  jdolecek 
     57  1.3.14.2  jdolecek #include <net/if.h>
     58  1.3.14.2  jdolecek #include <net/if_types.h>
     59  1.3.14.2  jdolecek #include <net/route.h>
     60  1.3.14.2  jdolecek #include <netinet/in.h>
     61  1.3.14.2  jdolecek #include <netinet/in_systm.h>
     62  1.3.14.2  jdolecek #define _IP_VHL
     63  1.3.14.2  jdolecek #include <netinet/ip.h>
     64  1.3.14.2  jdolecek #include <netinet/in_pcb.h>
     65  1.3.14.2  jdolecek #include <netinet/in_var.h>
     66  1.3.14.2  jdolecek #include <netinet/ip_var.h>
     67  1.3.14.2  jdolecek 
     68  1.3.14.2  jdolecek #ifdef INET6
     69  1.3.14.2  jdolecek #include <netinet/ip6.h>
     70  1.3.14.2  jdolecek #include <netinet6/ip6_var.h>
     71  1.3.14.2  jdolecek #endif /* INET6 */
     72  1.3.14.2  jdolecek 
     73  1.3.14.2  jdolecek #include <netinet/sctp_pcb.h>
     74  1.3.14.2  jdolecek 
     75  1.3.14.2  jdolecek #ifdef IPSEC
     76  1.3.14.2  jdolecek #include <netipsec/ipsec.h>
     77  1.3.14.2  jdolecek #include <netipsec/key.h>
     78  1.3.14.2  jdolecek #endif /* IPSEC */
     79  1.3.14.2  jdolecek #ifdef INET6
     80  1.3.14.2  jdolecek #include <netinet6/sctp6_var.h>
     81  1.3.14.2  jdolecek #endif
     82  1.3.14.2  jdolecek #include <netinet/sctp_var.h>
     83  1.3.14.2  jdolecek #include <netinet/sctp_timer.h>
     84  1.3.14.2  jdolecek #include <netinet/sctputil.h>
     85  1.3.14.2  jdolecek #include <netinet/sctp_output.h>
     86  1.3.14.2  jdolecek #include <netinet/sctp_hashdriver.h>
     87  1.3.14.2  jdolecek #include <netinet/sctp_header.h>
     88  1.3.14.2  jdolecek #include <netinet/sctp_indata.h>
     89  1.3.14.2  jdolecek #include <netinet/sctp_asconf.h>
     90  1.3.14.2  jdolecek 
     91  1.3.14.2  jdolecek #include <netinet/sctp.h>
     92  1.3.14.2  jdolecek #include <netinet/sctp_uio.h>
     93  1.3.14.2  jdolecek 
     94  1.3.14.2  jdolecek #include <net/net_osdep.h>
     95  1.3.14.2  jdolecek 
     96  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
     97  1.3.14.2  jdolecek extern u_int32_t sctp_debug_on;
     98  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
     99  1.3.14.2  jdolecek 
    100  1.3.14.2  jdolecek void
    101  1.3.14.2  jdolecek sctp_audit_retranmission_queue(struct sctp_association *asoc)
    102  1.3.14.2  jdolecek {
    103  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *chk;
    104  1.3.14.2  jdolecek 
    105  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    106  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
    107  1.3.14.2  jdolecek 		printf("Audit invoked on send queue cnt:%d onqueue:%d\n",
    108  1.3.14.2  jdolecek 		    asoc->sent_queue_retran_cnt,
    109  1.3.14.2  jdolecek 		    asoc->sent_queue_cnt);
    110  1.3.14.2  jdolecek 	}
    111  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    112  1.3.14.2  jdolecek 	asoc->sent_queue_retran_cnt = 0;
    113  1.3.14.2  jdolecek 	asoc->sent_queue_cnt = 0;
    114  1.3.14.2  jdolecek 	TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
    115  1.3.14.2  jdolecek 		if (chk->sent == SCTP_DATAGRAM_RESEND) {
    116  1.3.14.2  jdolecek 			asoc->sent_queue_retran_cnt++;
    117  1.3.14.2  jdolecek 		}
    118  1.3.14.2  jdolecek 		asoc->sent_queue_cnt++;
    119  1.3.14.2  jdolecek 	}
    120  1.3.14.2  jdolecek 	TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
    121  1.3.14.2  jdolecek 		if (chk->sent == SCTP_DATAGRAM_RESEND) {
    122  1.3.14.2  jdolecek 			asoc->sent_queue_retran_cnt++;
    123  1.3.14.2  jdolecek 		}
    124  1.3.14.2  jdolecek 	}
    125  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    126  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
    127  1.3.14.2  jdolecek 		printf("Audit completes retran:%d onqueue:%d\n",
    128  1.3.14.2  jdolecek 		    asoc->sent_queue_retran_cnt,
    129  1.3.14.2  jdolecek 		    asoc->sent_queue_cnt);
    130  1.3.14.2  jdolecek 	}
    131  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    132  1.3.14.2  jdolecek }
    133  1.3.14.2  jdolecek 
    134  1.3.14.2  jdolecek int
    135  1.3.14.2  jdolecek sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    136  1.3.14.2  jdolecek     struct sctp_nets *net, uint16_t threshold)
    137  1.3.14.2  jdolecek {
    138  1.3.14.2  jdolecek 	if (net) {
    139  1.3.14.2  jdolecek 		net->error_count++;
    140  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    141  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
    142  1.3.14.2  jdolecek 			printf("Error count for %p now %d thresh:%d\n",
    143  1.3.14.2  jdolecek 			    net, net->error_count,
    144  1.3.14.2  jdolecek 			    net->failure_threshold);
    145  1.3.14.2  jdolecek 		}
    146  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    147  1.3.14.2  jdolecek 		if (net->error_count >= net->failure_threshold) {
    148  1.3.14.2  jdolecek 			/* We had a threshold failure */
    149  1.3.14.2  jdolecek 			if (net->dest_state & SCTP_ADDR_REACHABLE) {
    150  1.3.14.2  jdolecek 				net->dest_state &= ~SCTP_ADDR_REACHABLE;
    151  1.3.14.2  jdolecek 				net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
    152  1.3.14.2  jdolecek 				if (net == stcb->asoc.primary_destination) {
    153  1.3.14.2  jdolecek 					net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
    154  1.3.14.2  jdolecek 				}
    155  1.3.14.2  jdolecek 				sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
    156  1.3.14.2  jdolecek 						stcb,
    157  1.3.14.2  jdolecek 						SCTP_FAILED_THRESHOLD,
    158  1.3.14.2  jdolecek 						(void *)net);
    159  1.3.14.2  jdolecek 			}
    160  1.3.14.2  jdolecek 		}
    161  1.3.14.2  jdolecek 		/*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE
    162  1.3.14.2  jdolecek 		 *********ROUTING CODE
    163  1.3.14.2  jdolecek 		 */
    164  1.3.14.2  jdolecek 		/*********HOLD THIS COMMENT FOR END OF PATCH OF ALTERNATE
    165  1.3.14.2  jdolecek 		 *********ROUTING CODE
    166  1.3.14.2  jdolecek 		 */
    167  1.3.14.2  jdolecek 	}
    168  1.3.14.2  jdolecek 	if (stcb == NULL)
    169  1.3.14.2  jdolecek 		return (0);
    170  1.3.14.2  jdolecek 
    171  1.3.14.2  jdolecek 	if (net) {
    172  1.3.14.2  jdolecek 		if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
    173  1.3.14.2  jdolecek 			stcb->asoc.overall_error_count++;
    174  1.3.14.2  jdolecek 		}
    175  1.3.14.2  jdolecek 	} else {
    176  1.3.14.2  jdolecek 		stcb->asoc.overall_error_count++;
    177  1.3.14.2  jdolecek 	}
    178  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    179  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
    180  1.3.14.2  jdolecek 		printf("Overall error count for %p now %d thresh:%u state:%x\n",
    181  1.3.14.2  jdolecek 		       &stcb->asoc,
    182  1.3.14.2  jdolecek 		       stcb->asoc.overall_error_count,
    183  1.3.14.2  jdolecek 		       (u_int)threshold,
    184  1.3.14.2  jdolecek 		       ((net == NULL) ? (u_int)0 : (u_int)net->dest_state));
    185  1.3.14.2  jdolecek 	}
    186  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    187  1.3.14.2  jdolecek 	/* We specifically do not do >= to give the assoc one more
    188  1.3.14.2  jdolecek 	 * change before we fail it.
    189  1.3.14.2  jdolecek 	 */
    190  1.3.14.2  jdolecek 	if (stcb->asoc.overall_error_count > threshold) {
    191  1.3.14.2  jdolecek 		/* Abort notification sends a ULP notify */
    192  1.3.14.2  jdolecek 		struct mbuf *oper;
    193  1.3.14.2  jdolecek 		MGET(oper, M_DONTWAIT, MT_DATA);
    194  1.3.14.2  jdolecek 		if (oper) {
    195  1.3.14.2  jdolecek 			struct sctp_paramhdr *ph;
    196  1.3.14.2  jdolecek 			u_int32_t *ippp;
    197  1.3.14.2  jdolecek 
    198  1.3.14.2  jdolecek 			oper->m_len = sizeof(struct sctp_paramhdr) +
    199  1.3.14.2  jdolecek 			    sizeof(*ippp);
    200  1.3.14.2  jdolecek 			ph = mtod(oper, struct sctp_paramhdr *);
    201  1.3.14.2  jdolecek 			ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
    202  1.3.14.2  jdolecek 			ph->param_length = htons(oper->m_len);
    203  1.3.14.2  jdolecek 			ippp = (u_int32_t *)(ph + 1);
    204  1.3.14.2  jdolecek 			*ippp = htonl(0x40000001);
    205  1.3.14.2  jdolecek 		}
    206  1.3.14.2  jdolecek 		sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper);
    207  1.3.14.2  jdolecek 		return (1);
    208  1.3.14.2  jdolecek 	}
    209  1.3.14.2  jdolecek 	return (0);
    210  1.3.14.2  jdolecek }
    211  1.3.14.2  jdolecek 
    212  1.3.14.2  jdolecek struct sctp_nets *
    213  1.3.14.2  jdolecek sctp_find_alternate_net(struct sctp_tcb *stcb,
    214  1.3.14.2  jdolecek 			struct sctp_nets *net)
    215  1.3.14.2  jdolecek {
    216  1.3.14.2  jdolecek 	/* Find and return an alternate network if possible */
    217  1.3.14.2  jdolecek 	struct sctp_nets *alt, *mnet;
    218  1.3.14.2  jdolecek 	struct rtentry *rt;
    219  1.3.14.2  jdolecek 	int once;
    220  1.3.14.2  jdolecek 
    221  1.3.14.2  jdolecek 	if (stcb->asoc.numnets == 1) {
    222  1.3.14.2  jdolecek 		/* No others but net */
    223  1.3.14.2  jdolecek 		return (TAILQ_FIRST(&stcb->asoc.nets));
    224  1.3.14.2  jdolecek 	}
    225  1.3.14.2  jdolecek 	mnet = net;
    226  1.3.14.2  jdolecek 	once = 0;
    227  1.3.14.2  jdolecek 
    228  1.3.14.2  jdolecek 	if (mnet == NULL) {
    229  1.3.14.2  jdolecek 		mnet = TAILQ_FIRST(&stcb->asoc.nets);
    230  1.3.14.2  jdolecek 	}
    231  1.3.14.2  jdolecek 	do {
    232  1.3.14.2  jdolecek 		alt = TAILQ_NEXT(mnet, sctp_next);
    233  1.3.14.2  jdolecek 		if (alt == NULL) {
    234  1.3.14.2  jdolecek 			once++;
    235  1.3.14.2  jdolecek 			if (once > 1) {
    236  1.3.14.2  jdolecek 				break;
    237  1.3.14.2  jdolecek 			}
    238  1.3.14.2  jdolecek 			alt = TAILQ_FIRST(&stcb->asoc.nets);
    239  1.3.14.2  jdolecek 		}
    240  1.3.14.2  jdolecek 		rt = rtcache_validate(&alt->ro);
    241  1.3.14.2  jdolecek 		if (rt == NULL) {
    242  1.3.14.2  jdolecek 			alt->src_addr_selected = 0;
    243  1.3.14.2  jdolecek 		}
    244  1.3.14.2  jdolecek 		if (
    245  1.3.14.2  jdolecek 			((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
    246  1.3.14.2  jdolecek 			(rt != NULL) &&
    247  1.3.14.2  jdolecek 			(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))
    248  1.3.14.2  jdolecek 			) {
    249  1.3.14.2  jdolecek 			/* Found a reachable address */
    250  1.3.14.2  jdolecek 			rtcache_unref(rt, &alt->ro);
    251  1.3.14.2  jdolecek 			break;
    252  1.3.14.2  jdolecek 		}
    253  1.3.14.2  jdolecek 		rtcache_unref(rt, &alt->ro);
    254  1.3.14.2  jdolecek 		mnet = alt;
    255  1.3.14.2  jdolecek 	} while (alt != NULL);
    256  1.3.14.2  jdolecek 
    257  1.3.14.2  jdolecek 	if (alt == NULL) {
    258  1.3.14.2  jdolecek 		/* Case where NO insv network exists (dormant state) */
    259  1.3.14.2  jdolecek 		/* we rotate destinations */
    260  1.3.14.2  jdolecek 		once = 0;
    261  1.3.14.2  jdolecek 		mnet = net;
    262  1.3.14.2  jdolecek 		do {
    263  1.3.14.2  jdolecek 			alt = TAILQ_NEXT(mnet, sctp_next);
    264  1.3.14.2  jdolecek 			if (alt == NULL) {
    265  1.3.14.2  jdolecek 				once++;
    266  1.3.14.2  jdolecek 				if (once > 1) {
    267  1.3.14.2  jdolecek 					break;
    268  1.3.14.2  jdolecek 				}
    269  1.3.14.2  jdolecek 				alt = TAILQ_FIRST(&stcb->asoc.nets);
    270  1.3.14.2  jdolecek 			}
    271  1.3.14.2  jdolecek 			if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
    272  1.3.14.2  jdolecek 			    (alt != net)) {
    273  1.3.14.2  jdolecek 				/* Found an alternate address */
    274  1.3.14.2  jdolecek 				break;
    275  1.3.14.2  jdolecek 			}
    276  1.3.14.2  jdolecek 			mnet = alt;
    277  1.3.14.2  jdolecek 		} while (alt != NULL);
    278  1.3.14.2  jdolecek 	}
    279  1.3.14.2  jdolecek 	if (alt == NULL) {
    280  1.3.14.2  jdolecek 		return (net);
    281  1.3.14.2  jdolecek 	}
    282  1.3.14.2  jdolecek 	return (alt);
    283  1.3.14.2  jdolecek }
    284  1.3.14.2  jdolecek 
    285  1.3.14.2  jdolecek static void
    286  1.3.14.2  jdolecek sctp_backoff_on_timeout(struct sctp_tcb *stcb,
    287  1.3.14.2  jdolecek 			struct sctp_nets *net,
    288  1.3.14.2  jdolecek 			int win_probe,
    289  1.3.14.2  jdolecek 			int num_marked)
    290  1.3.14.2  jdolecek {
    291  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    292  1.3.14.2  jdolecek 	int oldRTO;
    293  1.3.14.2  jdolecek 
    294  1.3.14.2  jdolecek 	oldRTO = net->RTO;
    295  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    296  1.3.14.2  jdolecek 	net->RTO <<= 1;
    297  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    298  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER2) {
    299  1.3.14.2  jdolecek 		printf("Timer doubles from %d ms -to-> %d ms\n",
    300  1.3.14.2  jdolecek 		       oldRTO, net->RTO);
    301  1.3.14.2  jdolecek 	}
    302  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    303  1.3.14.2  jdolecek 
    304  1.3.14.2  jdolecek 	if (net->RTO > stcb->asoc.maxrto) {
    305  1.3.14.2  jdolecek 		net->RTO = stcb->asoc.maxrto;
    306  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    307  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER2) {
    308  1.3.14.2  jdolecek 			printf("Growth capped by maxrto %d\n",
    309  1.3.14.2  jdolecek 			       net->RTO);
    310  1.3.14.2  jdolecek 		}
    311  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    312  1.3.14.2  jdolecek 	}
    313  1.3.14.2  jdolecek 
    314  1.3.14.2  jdolecek 
    315  1.3.14.2  jdolecek 	if ((win_probe == 0) && num_marked) {
    316  1.3.14.2  jdolecek 		/* We don't apply penalty to window probe scenarios */
    317  1.3.14.2  jdolecek #ifdef SCTP_CWND_LOGGING
    318  1.3.14.2  jdolecek 		int old_cwnd=net->cwnd;
    319  1.3.14.2  jdolecek #endif
    320  1.3.14.2  jdolecek 		net->ssthresh = net->cwnd >> 1;
    321  1.3.14.2  jdolecek 		if (net->ssthresh < (net->mtu << 1)) {
    322  1.3.14.2  jdolecek 			net->ssthresh = (net->mtu << 1);
    323  1.3.14.2  jdolecek 		}
    324  1.3.14.2  jdolecek 		net->cwnd = net->mtu;
    325  1.3.14.2  jdolecek 		/* floor of 1 mtu */
    326  1.3.14.2  jdolecek 		if (net->cwnd < net->mtu)
    327  1.3.14.2  jdolecek 			net->cwnd = net->mtu;
    328  1.3.14.2  jdolecek #ifdef SCTP_CWND_LOGGING
    329  1.3.14.2  jdolecek 		sctp_log_cwnd(net, net->cwnd-old_cwnd, SCTP_CWND_LOG_FROM_RTX);
    330  1.3.14.2  jdolecek #endif
    331  1.3.14.2  jdolecek 
    332  1.3.14.2  jdolecek 		net->partial_bytes_acked = 0;
    333  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    334  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    335  1.3.14.2  jdolecek 			printf("collapse cwnd to 1MTU ssthresh to %d\n",
    336  1.3.14.2  jdolecek 			       net->ssthresh);
    337  1.3.14.2  jdolecek 		}
    338  1.3.14.2  jdolecek #endif
    339  1.3.14.2  jdolecek 
    340  1.3.14.2  jdolecek 	}
    341  1.3.14.2  jdolecek }
    342  1.3.14.2  jdolecek 
    343  1.3.14.2  jdolecek 
    344  1.3.14.2  jdolecek static int
    345  1.3.14.2  jdolecek sctp_mark_all_for_resend(struct sctp_tcb *stcb,
    346  1.3.14.2  jdolecek 			 struct sctp_nets *net,
    347  1.3.14.2  jdolecek 			 struct sctp_nets *alt,
    348  1.3.14.2  jdolecek 			 int *num_marked)
    349  1.3.14.2  jdolecek {
    350  1.3.14.2  jdolecek 
    351  1.3.14.2  jdolecek 	/*
    352  1.3.14.2  jdolecek 	 * Mark all chunks (well not all) that were sent to *net for retransmission.
    353  1.3.14.2  jdolecek 	 * Move them to alt for there destination as well... We only
    354  1.3.14.2  jdolecek 	 * mark chunks that have been outstanding long enough to have
    355  1.3.14.2  jdolecek 	 * received feed-back.
    356  1.3.14.2  jdolecek 	 */
    357  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *chk, *tp2;
    358  1.3.14.2  jdolecek 	struct sctp_nets *lnets;
    359  1.3.14.2  jdolecek 	struct timeval now, min_wait, tv;
    360  1.3.14.2  jdolecek 	int cur_rto;
    361  1.3.14.2  jdolecek 	int win_probes, non_win_probes, orig_rwnd, audit_tf, num_mk, fir;
    362  1.3.14.2  jdolecek 	unsigned int cnt_mk;
    363  1.3.14.2  jdolecek 	u_int32_t orig_flight;
    364  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    365  1.3.14.2  jdolecek 	u_int32_t tsnfirst, tsnlast;
    366  1.3.14.2  jdolecek #endif
    367  1.3.14.2  jdolecek 
    368  1.3.14.2  jdolecek 	/* none in flight now */
    369  1.3.14.2  jdolecek 	audit_tf = 0;
    370  1.3.14.2  jdolecek 	fir=0;
    371  1.3.14.2  jdolecek 	/* figure out how long a data chunk must be pending
    372  1.3.14.2  jdolecek 	 * before we can mark it ..
    373  1.3.14.2  jdolecek 	 */
    374  1.3.14.2  jdolecek 	SCTP_GETTIME_TIMEVAL(&now);
    375  1.3.14.2  jdolecek 	/* get cur rto in micro-seconds */
    376  1.3.14.2  jdolecek 	cur_rto = (((net->lastsa >> 2) + net->lastsv) >> 1);
    377  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    378  1.3.14.2  jdolecek 	sctp_log_fr(cur_rto, 0, 0, SCTP_FR_T3_MARK_TIME);
    379  1.3.14.2  jdolecek #endif
    380  1.3.14.2  jdolecek 	cur_rto *= 1000;
    381  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    382  1.3.14.2  jdolecek 	sctp_log_fr(cur_rto, 0, 0, SCTP_FR_T3_MARK_TIME);
    383  1.3.14.2  jdolecek #endif
    384  1.3.14.2  jdolecek 	tv.tv_sec = cur_rto / 1000000;
    385  1.3.14.2  jdolecek 	tv.tv_usec = cur_rto % 1000000;
    386  1.3.14.2  jdolecek #ifndef __FreeBSD__
    387  1.3.14.2  jdolecek 	timersub(&now, &tv, &min_wait);
    388  1.3.14.2  jdolecek #else
    389  1.3.14.2  jdolecek 	min_wait = now;
    390  1.3.14.2  jdolecek 	timevalsub(&min_wait, &tv);
    391  1.3.14.2  jdolecek #endif
    392  1.3.14.2  jdolecek 	if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
    393  1.3.14.2  jdolecek 		/*
    394  1.3.14.2  jdolecek 		 * if we hit here, we don't
    395  1.3.14.2  jdolecek 		 * have enough seconds on the clock to account
    396  1.3.14.2  jdolecek 		 * for the RTO. We just let the lower seconds
    397  1.3.14.2  jdolecek 		 * be the bounds and don't worry about it. This
    398  1.3.14.2  jdolecek 		 * may mean we will mark a lot more than we should.
    399  1.3.14.2  jdolecek 		 */
    400  1.3.14.2  jdolecek 		min_wait.tv_sec = min_wait.tv_usec = 0;
    401  1.3.14.2  jdolecek 	}
    402  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    403  1.3.14.2  jdolecek 	sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME);
    404  1.3.14.2  jdolecek 	sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME);
    405  1.3.14.2  jdolecek #endif
    406  1.3.14.2  jdolecek 	if (stcb->asoc.total_flight >= net->flight_size) {
    407  1.3.14.2  jdolecek 		stcb->asoc.total_flight -= net->flight_size;
    408  1.3.14.2  jdolecek 	} else {
    409  1.3.14.2  jdolecek 		audit_tf = 1;
    410  1.3.14.2  jdolecek 		stcb->asoc.total_flight = 0;
    411  1.3.14.2  jdolecek 	}
    412  1.3.14.2  jdolecek         /* Our rwnd will be incorrect here since we are not adding
    413  1.3.14.2  jdolecek 	 * back the cnt * mbuf but we will fix that down below.
    414  1.3.14.2  jdolecek 	 */
    415  1.3.14.2  jdolecek 	orig_rwnd = stcb->asoc.peers_rwnd;
    416  1.3.14.2  jdolecek 	orig_flight = net->flight_size;
    417  1.3.14.2  jdolecek 	stcb->asoc.peers_rwnd += net->flight_size;
    418  1.3.14.2  jdolecek 	net->flight_size = 0;
    419  1.3.14.2  jdolecek 	net->rto_pending = 0;
    420  1.3.14.2  jdolecek 	net->fast_retran_ip= 0;
    421  1.3.14.2  jdolecek 	win_probes = non_win_probes = 0;
    422  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    423  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER2) {
    424  1.3.14.2  jdolecek 		printf("Marking ALL un-acked for retransmission at t3-timeout\n");
    425  1.3.14.2  jdolecek 	}
    426  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    427  1.3.14.2  jdolecek 	/* Now on to each chunk */
    428  1.3.14.2  jdolecek 	num_mk = cnt_mk = 0;
    429  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    430  1.3.14.2  jdolecek 	tsnlast = tsnfirst = 0;
    431  1.3.14.2  jdolecek #endif
    432  1.3.14.2  jdolecek 	chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
    433  1.3.14.2  jdolecek 	for (;chk != NULL; chk = tp2) {
    434  1.3.14.2  jdolecek 		tp2 = TAILQ_NEXT(chk, sctp_next);
    435  1.3.14.2  jdolecek 		if ((compare_with_wrap(stcb->asoc.last_acked_seq,
    436  1.3.14.2  jdolecek 				       chk->rec.data.TSN_seq,
    437  1.3.14.2  jdolecek 				       MAX_TSN)) ||
    438  1.3.14.2  jdolecek 		    (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
    439  1.3.14.2  jdolecek 			/* Strange case our list got out of order? */
    440  1.3.14.2  jdolecek 			printf("Our list is out of order?\n");
    441  1.3.14.2  jdolecek 			TAILQ_REMOVE(&stcb->asoc.sent_queue, chk, sctp_next);
    442  1.3.14.2  jdolecek 			if (chk->data) {
    443  1.3.14.2  jdolecek 				sctp_release_pr_sctp_chunk(stcb, chk, 0xffff,
    444  1.3.14.2  jdolecek 				    &stcb->asoc.sent_queue);
    445  1.3.14.2  jdolecek 				if (chk->flags & SCTP_PR_SCTP_BUFFER) {
    446  1.3.14.2  jdolecek 					stcb->asoc.sent_queue_cnt_removeable--;
    447  1.3.14.2  jdolecek 				}
    448  1.3.14.2  jdolecek 			}
    449  1.3.14.2  jdolecek 			stcb->asoc.sent_queue_cnt--;
    450  1.3.14.2  jdolecek 			sctp_free_remote_addr(chk->whoTo);
    451  1.3.14.2  jdolecek 			sctppcbinfo.ipi_count_chunk--;
    452  1.3.14.2  jdolecek 			if ((int)sctppcbinfo.ipi_count_chunk < 0) {
    453  1.3.14.2  jdolecek 				panic("Chunk count is going negative");
    454  1.3.14.2  jdolecek 			}
    455  1.3.14.2  jdolecek 			SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
    456  1.3.14.2  jdolecek 			sctppcbinfo.ipi_gencnt_chunk++;
    457  1.3.14.2  jdolecek 			continue;
    458  1.3.14.2  jdolecek 		}
    459  1.3.14.2  jdolecek 		if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) {
    460  1.3.14.2  jdolecek 			/* found one to mark:
    461  1.3.14.2  jdolecek 			 * If it is less than DATAGRAM_ACKED it MUST
    462  1.3.14.2  jdolecek 			 * not be a skipped or marked TSN but instead
    463  1.3.14.2  jdolecek 			 * one that is either already set for retransmission OR
    464  1.3.14.2  jdolecek 			 * one that needs retransmission.
    465  1.3.14.2  jdolecek 			 */
    466  1.3.14.2  jdolecek 
    467  1.3.14.2  jdolecek 			/* validate its been outstanding long enough */
    468  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    469  1.3.14.2  jdolecek 			sctp_log_fr(chk->rec.data.TSN_seq,
    470  1.3.14.2  jdolecek 				    chk->sent_rcv_time.tv_sec,
    471  1.3.14.2  jdolecek 				    chk->sent_rcv_time.tv_usec,
    472  1.3.14.2  jdolecek 				    SCTP_FR_T3_MARK_TIME);
    473  1.3.14.2  jdolecek #endif
    474  1.3.14.2  jdolecek 			if (chk->sent_rcv_time.tv_sec > min_wait.tv_sec) {
    475  1.3.14.2  jdolecek 				/* we have reached a chunk that was sent some
    476  1.3.14.2  jdolecek 				 * seconds past our min.. forget it we will
    477  1.3.14.2  jdolecek 				 * find no more to send.
    478  1.3.14.2  jdolecek 				 */
    479  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    480  1.3.14.2  jdolecek 				sctp_log_fr(0,
    481  1.3.14.2  jdolecek 					    chk->sent_rcv_time.tv_sec,
    482  1.3.14.2  jdolecek 					    chk->sent_rcv_time.tv_usec,
    483  1.3.14.2  jdolecek 					    SCTP_FR_T3_STOPPED);
    484  1.3.14.2  jdolecek #endif
    485  1.3.14.2  jdolecek 				continue;
    486  1.3.14.2  jdolecek 			} else if (chk->sent_rcv_time.tv_sec == min_wait.tv_sec) {
    487  1.3.14.2  jdolecek 				/* we must look at the micro seconds to know.
    488  1.3.14.2  jdolecek 				 */
    489  1.3.14.2  jdolecek 				if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) {
    490  1.3.14.2  jdolecek 					/* ok it was sent after our boundary time. */
    491  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    492  1.3.14.2  jdolecek 					sctp_log_fr(0,
    493  1.3.14.2  jdolecek 						    chk->sent_rcv_time.tv_sec,
    494  1.3.14.2  jdolecek 						    chk->sent_rcv_time.tv_usec,
    495  1.3.14.2  jdolecek 						    SCTP_FR_T3_STOPPED);
    496  1.3.14.2  jdolecek #endif
    497  1.3.14.2  jdolecek 					continue;
    498  1.3.14.2  jdolecek 				}
    499  1.3.14.2  jdolecek 			}
    500  1.3.14.2  jdolecek 			if (stcb->asoc.total_flight_count > 0) {
    501  1.3.14.2  jdolecek 				stcb->asoc.total_flight_count--;
    502  1.3.14.2  jdolecek 			}
    503  1.3.14.2  jdolecek 			if ((chk->flags & (SCTP_PR_SCTP_ENABLED|SCTP_PR_SCTP_BUFFER)) == SCTP_PR_SCTP_ENABLED) {
    504  1.3.14.2  jdolecek 				/* Is it expired? */
    505  1.3.14.2  jdolecek 				if ((now.tv_sec > chk->rec.data.timetodrop.tv_sec) ||
    506  1.3.14.2  jdolecek 				    ((chk->rec.data.timetodrop.tv_sec == now.tv_sec) &&
    507  1.3.14.2  jdolecek 				     (now.tv_usec > chk->rec.data.timetodrop.tv_usec))) {
    508  1.3.14.2  jdolecek 					/* Yes so drop it */
    509  1.3.14.2  jdolecek 					if (chk->data) {
    510  1.3.14.2  jdolecek 						sctp_release_pr_sctp_chunk(stcb,
    511  1.3.14.2  jdolecek 						    chk,
    512  1.3.14.2  jdolecek 						    (SCTP_RESPONSE_TO_USER_REQ|SCTP_NOTIFY_DATAGRAM_SENT),
    513  1.3.14.2  jdolecek 						    &stcb->asoc.sent_queue);
    514  1.3.14.2  jdolecek 					}
    515  1.3.14.2  jdolecek 				}
    516  1.3.14.2  jdolecek 				continue;
    517  1.3.14.2  jdolecek 			}
    518  1.3.14.2  jdolecek 			if (chk->sent != SCTP_DATAGRAM_RESEND) {
    519  1.3.14.2  jdolecek  				stcb->asoc.sent_queue_retran_cnt++;
    520  1.3.14.2  jdolecek  				num_mk++;
    521  1.3.14.2  jdolecek 				if (fir == 0) {
    522  1.3.14.2  jdolecek 					fir = 1;
    523  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    524  1.3.14.2  jdolecek 					if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    525  1.3.14.2  jdolecek 						printf("First TSN marked was %x\n",
    526  1.3.14.2  jdolecek 						       chk->rec.data.TSN_seq);
    527  1.3.14.2  jdolecek 					}
    528  1.3.14.2  jdolecek #endif
    529  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    530  1.3.14.2  jdolecek 					tsnfirst = chk->rec.data.TSN_seq;
    531  1.3.14.2  jdolecek #endif
    532  1.3.14.2  jdolecek 				}
    533  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    534  1.3.14.2  jdolecek 				tsnlast = chk->rec.data.TSN_seq;
    535  1.3.14.2  jdolecek 				sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
    536  1.3.14.2  jdolecek 					    0, SCTP_FR_T3_MARKED);
    537  1.3.14.2  jdolecek 
    538  1.3.14.2  jdolecek #endif
    539  1.3.14.2  jdolecek 			}
    540  1.3.14.2  jdolecek 			chk->sent = SCTP_DATAGRAM_RESEND;
    541  1.3.14.2  jdolecek 			/* reset the TSN for striking and other FR stuff */
    542  1.3.14.2  jdolecek 			chk->rec.data.doing_fast_retransmit = 0;
    543  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    544  1.3.14.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER3) {
    545  1.3.14.2  jdolecek 				printf("mark TSN:%x for retransmission\n", chk->rec.data.TSN_seq);
    546  1.3.14.2  jdolecek 			}
    547  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    548  1.3.14.2  jdolecek 			/* Clear any time so NO RTT is being done */
    549  1.3.14.2  jdolecek 			chk->do_rtt = 0;
    550  1.3.14.2  jdolecek 			/* Bump up the count */
    551  1.3.14.2  jdolecek 			if (compare_with_wrap(chk->rec.data.TSN_seq,
    552  1.3.14.2  jdolecek 					      stcb->asoc.t3timeout_highest_marked,
    553  1.3.14.2  jdolecek 					      MAX_TSN)) {
    554  1.3.14.2  jdolecek 				/* TSN_seq > than t3timeout so update */
    555  1.3.14.2  jdolecek 				stcb->asoc.t3timeout_highest_marked = chk->rec.data.TSN_seq;
    556  1.3.14.2  jdolecek 			}
    557  1.3.14.2  jdolecek 			if (alt != net) {
    558  1.3.14.2  jdolecek 				sctp_free_remote_addr(chk->whoTo);
    559  1.3.14.2  jdolecek 				chk->whoTo = alt;
    560  1.3.14.2  jdolecek 				alt->ref_count++;
    561  1.3.14.2  jdolecek 			}
    562  1.3.14.2  jdolecek 			if ((chk->rec.data.state_flags & SCTP_WINDOW_PROBE) !=
    563  1.3.14.2  jdolecek 			    SCTP_WINDOW_PROBE) {
    564  1.3.14.2  jdolecek 				non_win_probes++;
    565  1.3.14.2  jdolecek 			} else {
    566  1.3.14.2  jdolecek 				chk->rec.data.state_flags &= ~SCTP_WINDOW_PROBE;
    567  1.3.14.2  jdolecek 				win_probes++;
    568  1.3.14.2  jdolecek 			}
    569  1.3.14.2  jdolecek 		}
    570  1.3.14.2  jdolecek 		if (chk->sent == SCTP_DATAGRAM_RESEND) {
    571  1.3.14.2  jdolecek 			cnt_mk++;
    572  1.3.14.2  jdolecek 		}
    573  1.3.14.2  jdolecek 	}
    574  1.3.14.2  jdolecek 
    575  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    576  1.3.14.2  jdolecek 	sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
    577  1.3.14.2  jdolecek #endif
    578  1.3.14.2  jdolecek 	/* compensate for the number we marked */
    579  1.3.14.2  jdolecek 	stcb->asoc.peers_rwnd += (num_mk /* * sizeof(struct mbuf)*/);
    580  1.3.14.2  jdolecek 
    581  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    582  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    583  1.3.14.2  jdolecek 		if (num_mk) {
    584  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    585  1.3.14.2  jdolecek 			printf("LAST TSN marked was %x\n", tsnlast);
    586  1.3.14.2  jdolecek #endif
    587  1.3.14.2  jdolecek 			printf("Num marked for retransmission was %d peer-rwd:%ld\n",
    588  1.3.14.2  jdolecek 			       num_mk, (u_long)stcb->asoc.peers_rwnd);
    589  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    590  1.3.14.2  jdolecek 			printf("LAST TSN marked was %x\n", tsnlast);
    591  1.3.14.2  jdolecek #endif
    592  1.3.14.2  jdolecek 			printf("Num marked for retransmission was %d peer-rwd:%d\n",
    593  1.3.14.2  jdolecek 			       num_mk,
    594  1.3.14.2  jdolecek 			       (int)stcb->asoc.peers_rwnd
    595  1.3.14.2  jdolecek 				);
    596  1.3.14.2  jdolecek 		}
    597  1.3.14.2  jdolecek 	}
    598  1.3.14.2  jdolecek #endif
    599  1.3.14.2  jdolecek 	*num_marked = num_mk;
    600  1.3.14.2  jdolecek 	if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) {
    601  1.3.14.2  jdolecek 		printf("Local Audit says there are %d for retran asoc cnt:%d\n",
    602  1.3.14.2  jdolecek 		       cnt_mk, stcb->asoc.sent_queue_retran_cnt);
    603  1.3.14.2  jdolecek #ifndef SCTP_AUDITING_ENABLED
    604  1.3.14.2  jdolecek 		stcb->asoc.sent_queue_retran_cnt = cnt_mk;
    605  1.3.14.2  jdolecek #endif
    606  1.3.14.2  jdolecek 	}
    607  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    608  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER3) {
    609  1.3.14.2  jdolecek 		printf("**************************\n");
    610  1.3.14.2  jdolecek 	}
    611  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    612  1.3.14.2  jdolecek 
    613  1.3.14.2  jdolecek 	/* Now check for a ECN Echo that may be stranded */
    614  1.3.14.2  jdolecek 	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
    615  1.3.14.2  jdolecek 		if ((chk->whoTo == net) &&
    616  1.3.14.2  jdolecek 		    (chk->rec.chunk_id == SCTP_ECN_ECHO)) {
    617  1.3.14.2  jdolecek 			sctp_free_remote_addr(chk->whoTo);
    618  1.3.14.2  jdolecek 			chk->whoTo = alt;
    619  1.3.14.2  jdolecek 			if (chk->sent != SCTP_DATAGRAM_RESEND) {
    620  1.3.14.2  jdolecek 				chk->sent = SCTP_DATAGRAM_RESEND;
    621  1.3.14.2  jdolecek 				stcb->asoc.sent_queue_retran_cnt++;
    622  1.3.14.2  jdolecek 			}
    623  1.3.14.2  jdolecek 			alt->ref_count++;
    624  1.3.14.2  jdolecek 		}
    625  1.3.14.2  jdolecek 	}
    626  1.3.14.2  jdolecek 	if ((orig_rwnd == 0) && (stcb->asoc.total_flight == 0) &&
    627  1.3.14.2  jdolecek 	    (orig_flight <= net->mtu)) {
    628  1.3.14.2  jdolecek 		/*
    629  1.3.14.2  jdolecek 		 * If the LAST packet sent was not acked and our rwnd is 0
    630  1.3.14.2  jdolecek 		 * then we are in a win-probe state.
    631  1.3.14.2  jdolecek 		 */
    632  1.3.14.2  jdolecek 		win_probes = 1;
    633  1.3.14.2  jdolecek 		non_win_probes = 0;
    634  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    635  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    636  1.3.14.2  jdolecek 			printf("WIN_PROBE set via o_rwnd=0 tf=0 and all:%d fit in mtu:%d\n",
    637  1.3.14.2  jdolecek 			       orig_flight, net->mtu);
    638  1.3.14.2  jdolecek 		}
    639  1.3.14.2  jdolecek #endif
    640  1.3.14.2  jdolecek 	}
    641  1.3.14.2  jdolecek 
    642  1.3.14.2  jdolecek 	if (audit_tf) {
    643  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    644  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
    645  1.3.14.2  jdolecek 			printf("Audit total flight due to negative value net:%p\n",
    646  1.3.14.2  jdolecek 			    net);
    647  1.3.14.2  jdolecek 		}
    648  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    649  1.3.14.2  jdolecek 		stcb->asoc.total_flight = 0;
    650  1.3.14.2  jdolecek 		stcb->asoc.total_flight_count = 0;
    651  1.3.14.2  jdolecek 		/* Clear all networks flight size */
    652  1.3.14.2  jdolecek 		TAILQ_FOREACH(lnets, &stcb->asoc.nets, sctp_next) {
    653  1.3.14.2  jdolecek 			lnets->flight_size = 0;
    654  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    655  1.3.14.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
    656  1.3.14.2  jdolecek 				printf("Net:%p c-f cwnd:%d ssthresh:%d\n",
    657  1.3.14.2  jdolecek 				    lnets, lnets->cwnd, lnets->ssthresh);
    658  1.3.14.2  jdolecek 			}
    659  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    660  1.3.14.2  jdolecek 		}
    661  1.3.14.2  jdolecek 		TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
    662  1.3.14.2  jdolecek 			if (chk->sent < SCTP_DATAGRAM_RESEND) {
    663  1.3.14.2  jdolecek 				stcb->asoc.total_flight += chk->book_size;
    664  1.3.14.2  jdolecek 				chk->whoTo->flight_size += chk->book_size;
    665  1.3.14.2  jdolecek 				stcb->asoc.total_flight_count++;
    666  1.3.14.2  jdolecek 			}
    667  1.3.14.2  jdolecek 		}
    668  1.3.14.2  jdolecek 	}
    669  1.3.14.2  jdolecek 	/* Setup the ecn nonce re-sync point. We
    670  1.3.14.2  jdolecek 	 * do this since retranmissions are NOT
    671  1.3.14.2  jdolecek 	 * setup for ECN. This means that do to
    672  1.3.14.2  jdolecek 	 * Karn's rule, we don't know the total
    673  1.3.14.2  jdolecek 	 * of the peers ecn bits.
    674  1.3.14.2  jdolecek 	 */
    675  1.3.14.2  jdolecek 	chk = TAILQ_FIRST(&stcb->asoc.send_queue);
    676  1.3.14.2  jdolecek 	if (chk == NULL) {
    677  1.3.14.2  jdolecek 		stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
    678  1.3.14.2  jdolecek 	} else {
    679  1.3.14.2  jdolecek 		stcb->asoc.nonce_resync_tsn = chk->rec.data.TSN_seq;
    680  1.3.14.2  jdolecek 	}
    681  1.3.14.2  jdolecek 	stcb->asoc.nonce_wait_for_ecne = 0;
    682  1.3.14.2  jdolecek 	stcb->asoc.nonce_sum_check = 0;
    683  1.3.14.2  jdolecek 	/* We return 1 if we only have a window probe outstanding */
    684  1.3.14.2  jdolecek 	if (win_probes && (non_win_probes == 0)) {
    685  1.3.14.2  jdolecek 		return (1);
    686  1.3.14.2  jdolecek 	}
    687  1.3.14.2  jdolecek 	return (0);
    688  1.3.14.2  jdolecek }
    689  1.3.14.2  jdolecek 
    690  1.3.14.2  jdolecek static void
    691  1.3.14.2  jdolecek sctp_move_all_chunks_to_alt(struct sctp_tcb *stcb,
    692  1.3.14.2  jdolecek 			    struct sctp_nets *net,
    693  1.3.14.2  jdolecek 			    struct sctp_nets *alt)
    694  1.3.14.2  jdolecek {
    695  1.3.14.2  jdolecek 	struct sctp_association *asoc;
    696  1.3.14.2  jdolecek 	struct sctp_stream_out *outs;
    697  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *chk;
    698  1.3.14.2  jdolecek 
    699  1.3.14.2  jdolecek 	if (net == alt)
    700  1.3.14.2  jdolecek 		/* nothing to do */
    701  1.3.14.2  jdolecek 		return;
    702  1.3.14.2  jdolecek 
    703  1.3.14.2  jdolecek 	asoc = &stcb->asoc;
    704  1.3.14.2  jdolecek 
    705  1.3.14.2  jdolecek 	/*
    706  1.3.14.2  jdolecek 	 * now through all the streams checking for chunks sent to our
    707  1.3.14.2  jdolecek 	 * bad network.
    708  1.3.14.2  jdolecek 	 */
    709  1.3.14.2  jdolecek 	TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
    710  1.3.14.2  jdolecek 		/* now clean up any chunks here */
    711  1.3.14.2  jdolecek 		TAILQ_FOREACH(chk, &outs->outqueue, sctp_next) {
    712  1.3.14.2  jdolecek 			if (chk->whoTo == net) {
    713  1.3.14.2  jdolecek 				sctp_free_remote_addr(chk->whoTo);
    714  1.3.14.2  jdolecek 				chk->whoTo = alt;
    715  1.3.14.2  jdolecek 				alt->ref_count++;
    716  1.3.14.2  jdolecek 			}
    717  1.3.14.2  jdolecek 		}
    718  1.3.14.2  jdolecek 	}
    719  1.3.14.2  jdolecek 	/* Now check the pending queue */
    720  1.3.14.2  jdolecek 	TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
    721  1.3.14.2  jdolecek 		if (chk->whoTo == net) {
    722  1.3.14.2  jdolecek 			sctp_free_remote_addr(chk->whoTo);
    723  1.3.14.2  jdolecek 			chk->whoTo = alt;
    724  1.3.14.2  jdolecek 			alt->ref_count++;
    725  1.3.14.2  jdolecek 		}
    726  1.3.14.2  jdolecek 	}
    727  1.3.14.2  jdolecek 
    728  1.3.14.2  jdolecek }
    729  1.3.14.2  jdolecek 
    730  1.3.14.2  jdolecek int
    731  1.3.14.2  jdolecek sctp_t3rxt_timer(struct sctp_inpcb *inp,
    732  1.3.14.2  jdolecek 		 struct sctp_tcb *stcb,
    733  1.3.14.2  jdolecek 		 struct sctp_nets *net)
    734  1.3.14.2  jdolecek {
    735  1.3.14.2  jdolecek 	struct sctp_nets *alt;
    736  1.3.14.2  jdolecek 	int win_probe, num_mk;
    737  1.3.14.2  jdolecek 
    738  1.3.14.2  jdolecek 
    739  1.3.14.2  jdolecek #ifdef SCTP_FR_LOGGING
    740  1.3.14.2  jdolecek 	sctp_log_fr(0, 0, 0, SCTP_FR_T3_TIMEOUT);
    741  1.3.14.2  jdolecek #endif
    742  1.3.14.2  jdolecek 	/* Find an alternate and mark those for retransmission */
    743  1.3.14.2  jdolecek 	alt = sctp_find_alternate_net(stcb, net);
    744  1.3.14.2  jdolecek 	win_probe = sctp_mark_all_for_resend(stcb, net, alt, &num_mk);
    745  1.3.14.2  jdolecek 
    746  1.3.14.2  jdolecek 	/* FR Loss recovery just ended with the T3. */
    747  1.3.14.2  jdolecek 	stcb->asoc.fast_retran_loss_recovery = 0;
    748  1.3.14.2  jdolecek 
    749  1.3.14.2  jdolecek 	/* setup the sat loss recovery that prevents
    750  1.3.14.2  jdolecek 	 * satellite cwnd advance.
    751  1.3.14.2  jdolecek 	 */
    752  1.3.14.2  jdolecek  	stcb->asoc.sat_t3_loss_recovery = 1;
    753  1.3.14.2  jdolecek 	stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
    754  1.3.14.2  jdolecek 
    755  1.3.14.2  jdolecek 	/* Backoff the timer and cwnd */
    756  1.3.14.2  jdolecek 	sctp_backoff_on_timeout(stcb, net, win_probe, num_mk);
    757  1.3.14.2  jdolecek 	if (win_probe == 0) {
    758  1.3.14.2  jdolecek 		/* We don't do normal threshold management on window probes */
    759  1.3.14.2  jdolecek 		if (sctp_threshold_management(inp, stcb, net,
    760  1.3.14.2  jdolecek 					      stcb->asoc.max_send_times)) {
    761  1.3.14.2  jdolecek 			/* Association was destroyed */
    762  1.3.14.2  jdolecek 			return (1);
    763  1.3.14.2  jdolecek 		} else {
    764  1.3.14.2  jdolecek 			if (net != stcb->asoc.primary_destination) {
    765  1.3.14.2  jdolecek 				/* send a immediate HB if our RTO is stale */
    766  1.3.14.2  jdolecek 				struct  timeval now;
    767  1.3.14.2  jdolecek 				unsigned int ms_goneby;
    768  1.3.14.2  jdolecek 				SCTP_GETTIME_TIMEVAL(&now);
    769  1.3.14.2  jdolecek 				if (net->last_sent_time.tv_sec) {
    770  1.3.14.2  jdolecek 					ms_goneby = (now.tv_sec - net->last_sent_time.tv_sec) * 1000;
    771  1.3.14.2  jdolecek 				} else {
    772  1.3.14.2  jdolecek 					ms_goneby = 0;
    773  1.3.14.2  jdolecek 				}
    774  1.3.14.2  jdolecek 				if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
    775  1.3.14.2  jdolecek 					/* no recent feed back in an RTO or more, request a RTT update */
    776  1.3.14.2  jdolecek 					sctp_send_hb(stcb, 1, net);
    777  1.3.14.2  jdolecek 				}
    778  1.3.14.2  jdolecek 			}
    779  1.3.14.2  jdolecek 		}
    780  1.3.14.2  jdolecek 	} else {
    781  1.3.14.2  jdolecek 		/*
    782  1.3.14.2  jdolecek 		 * For a window probe we don't penalize the net's but only
    783  1.3.14.2  jdolecek 		 * the association. This may fail it if SACKs are not coming
    784  1.3.14.2  jdolecek 		 * back. If sack's are coming with rwnd locked at 0, we will
    785  1.3.14.2  jdolecek 		 * continue to hold things waiting for rwnd to raise
    786  1.3.14.2  jdolecek 		 */
    787  1.3.14.2  jdolecek 		if (sctp_threshold_management(inp, stcb, NULL,
    788  1.3.14.2  jdolecek 					      stcb->asoc.max_send_times)) {
    789  1.3.14.2  jdolecek 			/* Association was destroyed */
    790  1.3.14.2  jdolecek 			return (1);
    791  1.3.14.2  jdolecek 		}
    792  1.3.14.2  jdolecek 	}
    793  1.3.14.2  jdolecek 	if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
    794  1.3.14.2  jdolecek 		/* Move all pending over too */
    795  1.3.14.2  jdolecek 		sctp_move_all_chunks_to_alt(stcb, net, alt);
    796  1.3.14.2  jdolecek 		/* Was it our primary? */
    797  1.3.14.2  jdolecek 		if ((stcb->asoc.primary_destination == net) && (alt != net)) {
    798  1.3.14.2  jdolecek 			/*
    799  1.3.14.2  jdolecek 			 * Yes, note it as such and find an alternate
    800  1.3.14.2  jdolecek 			 * note: this means HB code must use this to resent
    801  1.3.14.2  jdolecek 			 * the primary if it goes active AND if someone does
    802  1.3.14.2  jdolecek 			 * a change-primary then this flag must be cleared
    803  1.3.14.2  jdolecek 			 * from any net structures.
    804  1.3.14.2  jdolecek 			 */
    805  1.3.14.2  jdolecek 			if (sctp_set_primary_addr(stcb,
    806  1.3.14.2  jdolecek 						 (struct sockaddr *)NULL,
    807  1.3.14.2  jdolecek 						 alt) == 0) {
    808  1.3.14.2  jdolecek 				net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
    809  1.3.14.2  jdolecek 				net->src_addr_selected = 0;
    810  1.3.14.2  jdolecek 			}
    811  1.3.14.2  jdolecek 		}
    812  1.3.14.2  jdolecek 	}
    813  1.3.14.2  jdolecek 	/*
    814  1.3.14.2  jdolecek 	 * Special case for cookie-echo'ed case, we don't do output
    815  1.3.14.2  jdolecek 	 * but must await the COOKIE-ACK before retransmission
    816  1.3.14.2  jdolecek 	 */
    817  1.3.14.2  jdolecek 	if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
    818  1.3.14.2  jdolecek 		/*
    819  1.3.14.2  jdolecek 		 * Here we just reset the timer and start again since we
    820  1.3.14.2  jdolecek 		 * have not established the asoc
    821  1.3.14.2  jdolecek 		 */
    822  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    823  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    824  1.3.14.2  jdolecek 			printf("Special cookie case return\n");
    825  1.3.14.2  jdolecek 		}
    826  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    827  1.3.14.2  jdolecek 		sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
    828  1.3.14.2  jdolecek 		return (0);
    829  1.3.14.2  jdolecek 	}
    830  1.3.14.2  jdolecek 	if (stcb->asoc.peer_supports_prsctp) {
    831  1.3.14.2  jdolecek 		struct sctp_tmit_chunk *lchk;
    832  1.3.14.2  jdolecek 		lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
    833  1.3.14.2  jdolecek 		/* C3. See if we need to send a Fwd-TSN */
    834  1.3.14.2  jdolecek 		if (compare_with_wrap(stcb->asoc.advanced_peer_ack_point,
    835  1.3.14.2  jdolecek 				      stcb->asoc.last_acked_seq, MAX_TSN)) {
    836  1.3.14.2  jdolecek 			/*
    837  1.3.14.2  jdolecek 			 * ISSUE with ECN, see FWD-TSN processing for notes
    838  1.3.14.2  jdolecek 			 * on issues that will occur when the ECN NONCE stuff
    839  1.3.14.2  jdolecek 			 * is put into SCTP for cross checking.
    840  1.3.14.2  jdolecek 			 */
    841  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    842  1.3.14.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    843  1.3.14.2  jdolecek 				printf("Forward TSN time\n");
    844  1.3.14.2  jdolecek 			}
    845  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    846  1.3.14.2  jdolecek 			send_forward_tsn(stcb, &stcb->asoc);
    847  1.3.14.2  jdolecek 			if (lchk) {
    848  1.3.14.2  jdolecek 				/* Assure a timer is up */
    849  1.3.14.2  jdolecek 				sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, lchk->whoTo);
    850  1.3.14.2  jdolecek 			}
    851  1.3.14.2  jdolecek 		}
    852  1.3.14.2  jdolecek 	}
    853  1.3.14.2  jdolecek 	return (0);
    854  1.3.14.2  jdolecek }
    855  1.3.14.2  jdolecek 
    856  1.3.14.2  jdolecek int
    857  1.3.14.2  jdolecek sctp_t1init_timer(struct sctp_inpcb *inp,
    858  1.3.14.2  jdolecek 		  struct sctp_tcb *stcb,
    859  1.3.14.2  jdolecek 		  struct sctp_nets *net)
    860  1.3.14.2  jdolecek {
    861  1.3.14.2  jdolecek 	/* bump the thresholds */
    862  1.3.14.2  jdolecek 	if (stcb->asoc.delayed_connection) {
    863  1.3.14.2  jdolecek 		/* special hook for delayed connection. The
    864  1.3.14.2  jdolecek 		 * library did NOT complete the rest of its
    865  1.3.14.2  jdolecek 		 * sends.
    866  1.3.14.2  jdolecek 		 */
    867  1.3.14.2  jdolecek 		stcb->asoc.delayed_connection = 0;
    868  1.3.14.2  jdolecek 		sctp_send_initiate(inp, stcb);
    869  1.3.14.2  jdolecek 		return (0);
    870  1.3.14.2  jdolecek 	}
    871  1.3.14.2  jdolecek 	if (sctp_threshold_management(inp, stcb, net,
    872  1.3.14.2  jdolecek 				      stcb->asoc.max_init_times)) {
    873  1.3.14.2  jdolecek 		/* Association was destroyed */
    874  1.3.14.2  jdolecek 		return (1);
    875  1.3.14.2  jdolecek 	}
    876  1.3.14.2  jdolecek 	stcb->asoc.dropped_special_cnt = 0;
    877  1.3.14.2  jdolecek 	sctp_backoff_on_timeout(stcb, stcb->asoc.primary_destination, 1, 0);
    878  1.3.14.2  jdolecek 	if (stcb->asoc.initial_init_rto_max < net->RTO) {
    879  1.3.14.2  jdolecek 		net->RTO = stcb->asoc.initial_init_rto_max;
    880  1.3.14.2  jdolecek 	}
    881  1.3.14.2  jdolecek 	if (stcb->asoc.numnets > 1) {
    882  1.3.14.2  jdolecek 		/* If we have more than one addr use it */
    883  1.3.14.2  jdolecek 		struct sctp_nets *alt;
    884  1.3.14.2  jdolecek 		alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination);
    885  1.3.14.2  jdolecek 		if ((alt != NULL) && (alt != stcb->asoc.primary_destination)) {
    886  1.3.14.2  jdolecek 			sctp_move_all_chunks_to_alt(stcb, stcb->asoc.primary_destination, alt);
    887  1.3.14.2  jdolecek 			stcb->asoc.primary_destination = alt;
    888  1.3.14.2  jdolecek 		}
    889  1.3.14.2  jdolecek 	}
    890  1.3.14.2  jdolecek 	/* Send out a new init */
    891  1.3.14.2  jdolecek 	sctp_send_initiate(inp, stcb);
    892  1.3.14.2  jdolecek 	return (0);
    893  1.3.14.2  jdolecek }
    894  1.3.14.2  jdolecek 
    895  1.3.14.2  jdolecek /*
    896  1.3.14.2  jdolecek  * For cookie and asconf we actually need to find and mark for resend,
    897  1.3.14.2  jdolecek  * then increment the resend counter (after all the threshold management
    898  1.3.14.2  jdolecek  * stuff of course).
    899  1.3.14.2  jdolecek  */
    900  1.3.14.2  jdolecek int  sctp_cookie_timer(struct sctp_inpcb *inp,
    901  1.3.14.2  jdolecek 		       struct sctp_tcb *stcb,
    902  1.3.14.2  jdolecek 		       struct sctp_nets *net)
    903  1.3.14.2  jdolecek {
    904  1.3.14.2  jdolecek 	struct sctp_nets *alt;
    905  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *cookie;
    906  1.3.14.2  jdolecek 	/* first before all else we must find the cookie */
    907  1.3.14.2  jdolecek 	TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, sctp_next) {
    908  1.3.14.2  jdolecek 		if (cookie->rec.chunk_id == SCTP_COOKIE_ECHO) {
    909  1.3.14.2  jdolecek 			break;
    910  1.3.14.2  jdolecek 		}
    911  1.3.14.2  jdolecek 	}
    912  1.3.14.2  jdolecek 	if (cookie == NULL) {
    913  1.3.14.2  jdolecek 		if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
    914  1.3.14.2  jdolecek 			/* FOOBAR! */
    915  1.3.14.2  jdolecek 			struct mbuf *oper;
    916  1.3.14.2  jdolecek 			MGET(oper, M_DONTWAIT, MT_DATA);
    917  1.3.14.2  jdolecek 			if (oper) {
    918  1.3.14.2  jdolecek 				struct sctp_paramhdr *ph;
    919  1.3.14.2  jdolecek 				u_int32_t *ippp;
    920  1.3.14.2  jdolecek 
    921  1.3.14.2  jdolecek 				oper->m_len = sizeof(struct sctp_paramhdr) +
    922  1.3.14.2  jdolecek 				    sizeof(*ippp);
    923  1.3.14.2  jdolecek 				ph = mtod(oper, struct sctp_paramhdr *);
    924  1.3.14.2  jdolecek 				ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
    925  1.3.14.2  jdolecek 				ph->param_length = htons(oper->m_len);
    926  1.3.14.2  jdolecek 				ippp = (u_int32_t *)(ph + 1);
    927  1.3.14.2  jdolecek 				*ippp = htonl(0x40000002);
    928  1.3.14.2  jdolecek 			}
    929  1.3.14.2  jdolecek 			sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR,
    930  1.3.14.2  jdolecek 			    oper);
    931  1.3.14.2  jdolecek 		}
    932  1.3.14.2  jdolecek 		return (1);
    933  1.3.14.2  jdolecek 	}
    934  1.3.14.2  jdolecek 	/* Ok we found the cookie, threshold management next */
    935  1.3.14.2  jdolecek 	if (sctp_threshold_management(inp, stcb, cookie->whoTo,
    936  1.3.14.2  jdolecek 	    stcb->asoc.max_init_times)) {
    937  1.3.14.2  jdolecek 		/* Assoc is over */
    938  1.3.14.2  jdolecek 		return (1);
    939  1.3.14.2  jdolecek 	}
    940  1.3.14.2  jdolecek 	/*
    941  1.3.14.2  jdolecek 	 * cleared theshold management now lets backoff the address &
    942  1.3.14.2  jdolecek 	 * select an alternate
    943  1.3.14.2  jdolecek 	 */
    944  1.3.14.2  jdolecek 	stcb->asoc.dropped_special_cnt = 0;
    945  1.3.14.2  jdolecek 	sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0);
    946  1.3.14.2  jdolecek 	alt = sctp_find_alternate_net(stcb, cookie->whoTo);
    947  1.3.14.2  jdolecek 	if (alt != cookie->whoTo) {
    948  1.3.14.2  jdolecek 		sctp_free_remote_addr(cookie->whoTo);
    949  1.3.14.2  jdolecek 		cookie->whoTo = alt;
    950  1.3.14.2  jdolecek 		alt->ref_count++;
    951  1.3.14.2  jdolecek 	}
    952  1.3.14.2  jdolecek 	/* Now mark the retran info */
    953  1.3.14.2  jdolecek 	if (cookie->sent != SCTP_DATAGRAM_RESEND) {
    954  1.3.14.2  jdolecek 		stcb->asoc.sent_queue_retran_cnt++;
    955  1.3.14.2  jdolecek 	}
    956  1.3.14.2  jdolecek 	cookie->sent = SCTP_DATAGRAM_RESEND;
    957  1.3.14.2  jdolecek 	/*
    958  1.3.14.2  jdolecek 	 * Now call the output routine to kick out the cookie again, Note we
    959  1.3.14.2  jdolecek 	 * don't mark any chunks for retran so that FR will need to kick in
    960  1.3.14.2  jdolecek 	 * to move these (or a send timer).
    961  1.3.14.2  jdolecek 	 */
    962  1.3.14.2  jdolecek 	return (0);
    963  1.3.14.2  jdolecek }
    964  1.3.14.2  jdolecek 
    965  1.3.14.2  jdolecek int sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    966  1.3.14.2  jdolecek     struct sctp_nets *net)
    967  1.3.14.2  jdolecek {
    968  1.3.14.2  jdolecek 	struct sctp_nets *alt;
    969  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *strrst, *chk;
    970  1.3.14.2  jdolecek 	struct sctp_stream_reset_req *strreq;
    971  1.3.14.2  jdolecek 	/* find the existing STRRESET */
    972  1.3.14.2  jdolecek 	TAILQ_FOREACH(strrst, &stcb->asoc.control_send_queue,
    973  1.3.14.2  jdolecek 		      sctp_next) {
    974  1.3.14.2  jdolecek 		if (strrst->rec.chunk_id == SCTP_STREAM_RESET) {
    975  1.3.14.2  jdolecek 			/* is it what we want */
    976  1.3.14.2  jdolecek 			strreq = mtod(strrst->data, struct sctp_stream_reset_req *);
    977  1.3.14.2  jdolecek 			if (strreq->sr_req.ph.param_type == ntohs(SCTP_STR_RESET_REQUEST)) {
    978  1.3.14.2  jdolecek 				break;
    979  1.3.14.2  jdolecek 			}
    980  1.3.14.2  jdolecek 		}
    981  1.3.14.2  jdolecek 	}
    982  1.3.14.2  jdolecek 	if (strrst == NULL) {
    983  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
    984  1.3.14.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    985  1.3.14.2  jdolecek 			printf("Strange, strreset timer fires, but I can't find an str-reset?\n");
    986  1.3.14.2  jdolecek 		}
    987  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
    988  1.3.14.2  jdolecek 		return (0);
    989  1.3.14.2  jdolecek 	}
    990  1.3.14.2  jdolecek 	/* do threshold management */
    991  1.3.14.2  jdolecek 	if (sctp_threshold_management(inp, stcb, strrst->whoTo,
    992  1.3.14.2  jdolecek 				      stcb->asoc.max_send_times)) {
    993  1.3.14.2  jdolecek 		/* Assoc is over */
    994  1.3.14.2  jdolecek 		return (1);
    995  1.3.14.2  jdolecek 	}
    996  1.3.14.2  jdolecek 
    997  1.3.14.2  jdolecek 	/*
    998  1.3.14.2  jdolecek 	 * cleared theshold management
    999  1.3.14.2  jdolecek 	 * now lets backoff the address & select an alternate
   1000  1.3.14.2  jdolecek 	 */
   1001  1.3.14.2  jdolecek 	sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0);
   1002  1.3.14.2  jdolecek 	alt = sctp_find_alternate_net(stcb, strrst->whoTo);
   1003  1.3.14.2  jdolecek 	sctp_free_remote_addr(strrst->whoTo);
   1004  1.3.14.2  jdolecek 	strrst->whoTo = alt;
   1005  1.3.14.2  jdolecek 	alt->ref_count++;
   1006  1.3.14.2  jdolecek 
   1007  1.3.14.2  jdolecek 	/* See if a ECN Echo is also stranded */
   1008  1.3.14.2  jdolecek 	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
   1009  1.3.14.2  jdolecek 		if ((chk->whoTo == net) &&
   1010  1.3.14.2  jdolecek 		    (chk->rec.chunk_id == SCTP_ECN_ECHO)) {
   1011  1.3.14.2  jdolecek 			sctp_free_remote_addr(chk->whoTo);
   1012  1.3.14.2  jdolecek 			if (chk->sent != SCTP_DATAGRAM_RESEND) {
   1013  1.3.14.2  jdolecek 				chk->sent = SCTP_DATAGRAM_RESEND;
   1014  1.3.14.2  jdolecek 				stcb->asoc.sent_queue_retran_cnt++;
   1015  1.3.14.2  jdolecek 			}
   1016  1.3.14.2  jdolecek 			chk->whoTo = alt;
   1017  1.3.14.2  jdolecek 			alt->ref_count++;
   1018  1.3.14.2  jdolecek 		}
   1019  1.3.14.2  jdolecek 	}
   1020  1.3.14.2  jdolecek 	if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
   1021  1.3.14.2  jdolecek 		/*
   1022  1.3.14.2  jdolecek 		 * If the address went un-reachable, we need to move
   1023  1.3.14.2  jdolecek 		 * to alternates for ALL chk's in queue
   1024  1.3.14.2  jdolecek 		 */
   1025  1.3.14.2  jdolecek 		sctp_move_all_chunks_to_alt(stcb, net, alt);
   1026  1.3.14.2  jdolecek 	}
   1027  1.3.14.2  jdolecek 	/* mark the retran info */
   1028  1.3.14.2  jdolecek 	if (strrst->sent != SCTP_DATAGRAM_RESEND)
   1029  1.3.14.2  jdolecek 		stcb->asoc.sent_queue_retran_cnt++;
   1030  1.3.14.2  jdolecek 	strrst->sent = SCTP_DATAGRAM_RESEND;
   1031  1.3.14.2  jdolecek 
   1032  1.3.14.2  jdolecek 	/* restart the timer */
   1033  1.3.14.2  jdolecek 	sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, inp, stcb, strrst->whoTo);
   1034  1.3.14.2  jdolecek 	return (0);
   1035  1.3.14.2  jdolecek }
   1036  1.3.14.2  jdolecek 
   1037  1.3.14.2  jdolecek int sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   1038  1.3.14.2  jdolecek     struct sctp_nets *net)
   1039  1.3.14.2  jdolecek {
   1040  1.3.14.2  jdolecek 	struct sctp_nets *alt;
   1041  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *asconf, *chk;
   1042  1.3.14.2  jdolecek 
   1043  1.3.14.2  jdolecek 	/* is this the first send, or a retransmission? */
   1044  1.3.14.2  jdolecek 	if (stcb->asoc.asconf_sent == 0) {
   1045  1.3.14.2  jdolecek 		/* compose a new ASCONF chunk and send it */
   1046  1.3.14.2  jdolecek 		sctp_send_asconf(stcb, net);
   1047  1.3.14.2  jdolecek 	} else {
   1048  1.3.14.2  jdolecek 		/* Retransmission of the existing ASCONF needed... */
   1049  1.3.14.2  jdolecek 
   1050  1.3.14.2  jdolecek 		/* find the existing ASCONF */
   1051  1.3.14.2  jdolecek 		TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
   1052  1.3.14.2  jdolecek 		    sctp_next) {
   1053  1.3.14.2  jdolecek 			if (asconf->rec.chunk_id == SCTP_ASCONF) {
   1054  1.3.14.2  jdolecek 				break;
   1055  1.3.14.2  jdolecek 			}
   1056  1.3.14.2  jdolecek 		}
   1057  1.3.14.2  jdolecek 		if (asconf == NULL) {
   1058  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
   1059  1.3.14.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1060  1.3.14.2  jdolecek 				printf("Strange, asconf timer fires, but I can't find an asconf?\n");
   1061  1.3.14.2  jdolecek 			}
   1062  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
   1063  1.3.14.2  jdolecek 			return (0);
   1064  1.3.14.2  jdolecek 		}
   1065  1.3.14.2  jdolecek 		/* do threshold management */
   1066  1.3.14.2  jdolecek 		if (sctp_threshold_management(inp, stcb, asconf->whoTo,
   1067  1.3.14.2  jdolecek 		    stcb->asoc.max_send_times)) {
   1068  1.3.14.2  jdolecek 			/* Assoc is over */
   1069  1.3.14.2  jdolecek 			return (1);
   1070  1.3.14.2  jdolecek 		}
   1071  1.3.14.2  jdolecek 
   1072  1.3.14.2  jdolecek 		/* PETER? FIX? How will the following code ever run? If
   1073  1.3.14.2  jdolecek 		 * the max_send_times is hit, threshold managment will
   1074  1.3.14.2  jdolecek 		 * blow away the association?
   1075  1.3.14.2  jdolecek 		 */
   1076  1.3.14.2  jdolecek 		if (asconf->snd_count > stcb->asoc.max_send_times) {
   1077  1.3.14.2  jdolecek 			/*
   1078  1.3.14.2  jdolecek 			 * Something is rotten, peer is not responding to
   1079  1.3.14.2  jdolecek 			 * ASCONFs but maybe is to data etc.  e.g. it is not
   1080  1.3.14.2  jdolecek 			 * properly handling the chunk type upper bits
   1081  1.3.14.2  jdolecek 			 * Mark this peer as ASCONF incapable and cleanup
   1082  1.3.14.2  jdolecek 			 */
   1083  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
   1084  1.3.14.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1085  1.3.14.2  jdolecek 				printf("asconf_timer: Peer has not responded to our repeated ASCONFs\n");
   1086  1.3.14.2  jdolecek 			}
   1087  1.3.14.2  jdolecek #endif /* SCTP_DEBUG */
   1088  1.3.14.2  jdolecek 			sctp_asconf_cleanup(stcb, net);
   1089  1.3.14.2  jdolecek 			return (0);
   1090  1.3.14.2  jdolecek 		}
   1091  1.3.14.2  jdolecek 		/*
   1092  1.3.14.2  jdolecek 		 * cleared theshold management
   1093  1.3.14.2  jdolecek 		 * now lets backoff the address & select an alternate
   1094  1.3.14.2  jdolecek 		 */
   1095  1.3.14.2  jdolecek 		sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0);
   1096  1.3.14.2  jdolecek 		alt = sctp_find_alternate_net(stcb, asconf->whoTo);
   1097  1.3.14.2  jdolecek 		sctp_free_remote_addr(asconf->whoTo);
   1098  1.3.14.2  jdolecek 		asconf->whoTo = alt;
   1099  1.3.14.2  jdolecek 		alt->ref_count++;
   1100  1.3.14.2  jdolecek 
   1101  1.3.14.2  jdolecek 		/* See if a ECN Echo is also stranded */
   1102  1.3.14.2  jdolecek 		TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
   1103  1.3.14.2  jdolecek 			if ((chk->whoTo == net) &&
   1104  1.3.14.2  jdolecek 			    (chk->rec.chunk_id == SCTP_ECN_ECHO)) {
   1105  1.3.14.2  jdolecek 				sctp_free_remote_addr(chk->whoTo);
   1106  1.3.14.2  jdolecek 				chk->whoTo = alt;
   1107  1.3.14.2  jdolecek 				if (chk->sent != SCTP_DATAGRAM_RESEND) {
   1108  1.3.14.2  jdolecek 					chk->sent = SCTP_DATAGRAM_RESEND;
   1109  1.3.14.2  jdolecek 					stcb->asoc.sent_queue_retran_cnt++;
   1110  1.3.14.2  jdolecek 				}
   1111  1.3.14.2  jdolecek 				alt->ref_count++;
   1112  1.3.14.2  jdolecek 
   1113  1.3.14.2  jdolecek 			}
   1114  1.3.14.2  jdolecek 		}
   1115  1.3.14.2  jdolecek 		if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
   1116  1.3.14.2  jdolecek 			/*
   1117  1.3.14.2  jdolecek 			 * If the address went un-reachable, we need to move
   1118  1.3.14.2  jdolecek 			 * to alternates for ALL chk's in queue
   1119  1.3.14.2  jdolecek 			 */
   1120  1.3.14.2  jdolecek 			sctp_move_all_chunks_to_alt(stcb, net, alt);
   1121  1.3.14.2  jdolecek 		}
   1122  1.3.14.2  jdolecek 		/* mark the retran info */
   1123  1.3.14.2  jdolecek 		if (asconf->sent != SCTP_DATAGRAM_RESEND)
   1124  1.3.14.2  jdolecek 			stcb->asoc.sent_queue_retran_cnt++;
   1125  1.3.14.2  jdolecek 		asconf->sent = SCTP_DATAGRAM_RESEND;
   1126  1.3.14.2  jdolecek 	}
   1127  1.3.14.2  jdolecek 	return (0);
   1128  1.3.14.2  jdolecek }
   1129  1.3.14.2  jdolecek 
   1130  1.3.14.2  jdolecek /*
   1131  1.3.14.2  jdolecek  * For the shutdown and shutdown-ack, we do not keep one around on the
   1132  1.3.14.2  jdolecek  * control queue. This means we must generate a new one and call the general
   1133  1.3.14.2  jdolecek  * chunk output routine, AFTER having done threshold
   1134  1.3.14.2  jdolecek  * management.
   1135  1.3.14.2  jdolecek  */
   1136  1.3.14.2  jdolecek int
   1137  1.3.14.2  jdolecek sctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   1138  1.3.14.2  jdolecek     struct sctp_nets *net)
   1139  1.3.14.2  jdolecek {
   1140  1.3.14.2  jdolecek 	struct sctp_nets *alt;
   1141  1.3.14.2  jdolecek 	/* first threshold managment */
   1142  1.3.14.2  jdolecek 	if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
   1143  1.3.14.2  jdolecek 		/* Assoc is over */
   1144  1.3.14.2  jdolecek 		return (1);
   1145  1.3.14.2  jdolecek 	}
   1146  1.3.14.2  jdolecek 	/* second select an alternative */
   1147  1.3.14.2  jdolecek 	alt = sctp_find_alternate_net(stcb, net);
   1148  1.3.14.2  jdolecek 
   1149  1.3.14.2  jdolecek 	/* third generate a shutdown into the queue for out net */
   1150  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
   1151  1.3.14.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
   1152  1.3.14.2  jdolecek 		printf("%s:%d sends a shutdown\n",
   1153  1.3.14.2  jdolecek 		       __FILE__,
   1154  1.3.14.2  jdolecek 		       __LINE__
   1155  1.3.14.2  jdolecek 			);
   1156  1.3.14.2  jdolecek 	}
   1157  1.3.14.2  jdolecek #endif
   1158  1.3.14.2  jdolecek 	if (alt) {
   1159  1.3.14.2  jdolecek 		sctp_send_shutdown(stcb, alt);
   1160  1.3.14.2  jdolecek 	} else {
   1161  1.3.14.2  jdolecek 		/* if alt is NULL, there is no dest
   1162  1.3.14.2  jdolecek 		 * to send to??
   1163  1.3.14.2  jdolecek 		 */
   1164  1.3.14.2  jdolecek 		return (0);
   1165  1.3.14.2  jdolecek 	}
   1166  1.3.14.2  jdolecek 	/* fourth restart timer */
   1167  1.3.14.2  jdolecek 	sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt);
   1168  1.3.14.2  jdolecek 	return (0);
   1169  1.3.14.2  jdolecek }
   1170  1.3.14.2  jdolecek 
   1171  1.3.14.2  jdolecek int sctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   1172  1.3.14.2  jdolecek     struct sctp_nets *net)
   1173  1.3.14.2  jdolecek {
   1174  1.3.14.2  jdolecek 	struct sctp_nets *alt;
   1175  1.3.14.2  jdolecek 	/* first threshold managment */
   1176  1.3.14.2  jdolecek 	if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
   1177  1.3.14.2  jdolecek 		/* Assoc is over */
   1178  1.3.14.2  jdolecek 		return (1);
   1179  1.3.14.2  jdolecek 	}
   1180  1.3.14.2  jdolecek 	/* second select an alternative */
   1181  1.3.14.2  jdolecek 	alt = sctp_find_alternate_net(stcb, net);
   1182  1.3.14.2  jdolecek 
   1183  1.3.14.2  jdolecek 	/* third generate a shutdown into the queue for out net */
   1184  1.3.14.2  jdolecek 	sctp_send_shutdown_ack(stcb, alt);
   1185  1.3.14.2  jdolecek 
   1186  1.3.14.2  jdolecek 	/* fourth restart timer */
   1187  1.3.14.2  jdolecek 	sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt);
   1188  1.3.14.2  jdolecek 	return (0);
   1189  1.3.14.2  jdolecek }
   1190  1.3.14.2  jdolecek 
   1191  1.3.14.2  jdolecek static void
   1192  1.3.14.2  jdolecek sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
   1193  1.3.14.2  jdolecek 				  struct sctp_tcb *stcb)
   1194  1.3.14.2  jdolecek {
   1195  1.3.14.2  jdolecek 	struct sctp_stream_out *outs;
   1196  1.3.14.2  jdolecek 	struct sctp_tmit_chunk *chk;
   1197  1.3.14.2  jdolecek 	unsigned int chks_in_queue=0;
   1198  1.3.14.2  jdolecek 
   1199  1.3.14.2  jdolecek 	if ((stcb == NULL) || (inp == NULL))
   1200  1.3.14.2  jdolecek 		return;
   1201  1.3.14.2  jdolecek 	if (TAILQ_EMPTY(&stcb->asoc.out_wheel)) {
   1202  1.3.14.2  jdolecek 		printf("Strange, out_wheel empty nothing on sent/send and  tot=%lu?\n",
   1203  1.3.14.2  jdolecek 		    (u_long)stcb->asoc.total_output_queue_size);
   1204  1.3.14.2  jdolecek 		stcb->asoc.total_output_queue_size = 0;
   1205  1.3.14.2  jdolecek 		return;
   1206  1.3.14.2  jdolecek 	}
   1207  1.3.14.2  jdolecek 	if (stcb->asoc.sent_queue_retran_cnt) {
   1208  1.3.14.2  jdolecek 		printf("Hmm, sent_queue_retran_cnt is non-zero %d\n",
   1209  1.3.14.2  jdolecek 		    stcb->asoc.sent_queue_retran_cnt);
   1210  1.3.14.2  jdolecek 		stcb->asoc.sent_queue_retran_cnt = 0;
   1211  1.3.14.2  jdolecek 	}
   1212  1.3.14.2  jdolecek 	/* Check to see if some data queued, if so report it */
   1213  1.3.14.2  jdolecek 	TAILQ_FOREACH(outs, &stcb->asoc.out_wheel, next_spoke) {
   1214  1.3.14.2  jdolecek 		if (!TAILQ_EMPTY(&outs->outqueue)) {
   1215  1.3.14.2  jdolecek 			TAILQ_FOREACH(chk, &outs->outqueue, sctp_next) {
   1216  1.3.14.2  jdolecek 				chks_in_queue++;
   1217  1.3.14.2  jdolecek 			}
   1218  1.3.14.2  jdolecek 		}
   1219  1.3.14.2  jdolecek 	}
   1220  1.3.14.2  jdolecek 	if (chks_in_queue != stcb->asoc.stream_queue_cnt) {
   1221  1.3.14.2  jdolecek 		printf("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n",
   1222  1.3.14.2  jdolecek 		       stcb->asoc.stream_queue_cnt, chks_in_queue);
   1223  1.3.14.2  jdolecek 	}
   1224  1.3.14.2  jdolecek 	if (chks_in_queue) {
   1225  1.3.14.2  jdolecek 		/* call the output queue function */
   1226  1.3.14.2  jdolecek 		sctp_chunk_output(inp, stcb, 1);
   1227  1.3.14.2  jdolecek 		if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
   1228  1.3.14.2  jdolecek 		    (TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
   1229  1.3.14.2  jdolecek 			/* Probably should go in and make it go back through and add fragments allowed */
   1230  1.3.14.2  jdolecek 			printf("Still nothing moved %d chunks are stuck\n", chks_in_queue);
   1231  1.3.14.2  jdolecek 		}
   1232  1.3.14.2  jdolecek 	} else {
   1233  1.3.14.2  jdolecek 		printf("Found no chunks on any queue tot:%lu\n",
   1234  1.3.14.2  jdolecek 		    (u_long)stcb->asoc.total_output_queue_size);
   1235  1.3.14.2  jdolecek 		stcb->asoc.total_output_queue_size = 0;
   1236  1.3.14.2  jdolecek 	}
   1237  1.3.14.2  jdolecek }
   1238  1.3.14.2  jdolecek 
   1239  1.3.14.2  jdolecek int
   1240  1.3.14.2  jdolecek sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   1241  1.3.14.2  jdolecek     struct sctp_nets *net)
   1242  1.3.14.2  jdolecek {
   1243  1.3.14.2  jdolecek 	int cnt_of_unconf=0;
   1244  1.3.14.2  jdolecek 
   1245  1.3.14.2  jdolecek 	if (net) {
   1246  1.3.14.2  jdolecek 		if (net->hb_responded == 0) {
   1247  1.3.14.2  jdolecek 			sctp_backoff_on_timeout(stcb, net, 1, 0);
   1248  1.3.14.2  jdolecek 		}
   1249  1.3.14.2  jdolecek 		/* Zero PBA, if it needs it */
   1250  1.3.14.2  jdolecek 		if (net->partial_bytes_acked) {
   1251  1.3.14.2  jdolecek 			net->partial_bytes_acked = 0;
   1252  1.3.14.2  jdolecek 		}
   1253  1.3.14.2  jdolecek 	}
   1254  1.3.14.2  jdolecek 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
   1255  1.3.14.2  jdolecek 		if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
   1256  1.3.14.2  jdolecek 		    (net->dest_state & SCTP_ADDR_REACHABLE)) {
   1257  1.3.14.2  jdolecek 			cnt_of_unconf++;
   1258  1.3.14.2  jdolecek 		}
   1259  1.3.14.2  jdolecek 	}
   1260  1.3.14.2  jdolecek 	if ((stcb->asoc.total_output_queue_size > 0) &&
   1261  1.3.14.2  jdolecek 	    (TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
   1262  1.3.14.2  jdolecek 	    (TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
   1263  1.3.14.2  jdolecek 		sctp_audit_stream_queues_for_size(inp, stcb);
   1264  1.3.14.2  jdolecek 	}
   1265  1.3.14.2  jdolecek 	/* Send a new HB, this will do threshold managment, pick a new dest */
   1266  1.3.14.2  jdolecek 	if (sctp_send_hb(stcb, 0, NULL) < 0) {
   1267  1.3.14.2  jdolecek 		return (1);
   1268  1.3.14.2  jdolecek 	}
   1269  1.3.14.2  jdolecek 	if (cnt_of_unconf > 1) {
   1270  1.3.14.2  jdolecek 		/*
   1271  1.3.14.2  jdolecek 		 * this will send out extra hb's up to maxburst if
   1272  1.3.14.2  jdolecek 		 * there are any unconfirmed addresses.
   1273  1.3.14.2  jdolecek 		 */
   1274  1.3.14.2  jdolecek 		int cnt_sent = 1;
   1275  1.3.14.2  jdolecek 		while ((cnt_sent < stcb->asoc.max_burst) && (cnt_of_unconf > 1)) {
   1276  1.3.14.2  jdolecek 			if (sctp_send_hb(stcb, 0, NULL) == 0)
   1277  1.3.14.2  jdolecek 				break;
   1278  1.3.14.2  jdolecek 			cnt_of_unconf--;
   1279  1.3.14.2  jdolecek 			cnt_sent++;
   1280  1.3.14.2  jdolecek 		}
   1281  1.3.14.2  jdolecek 	}
   1282  1.3.14.2  jdolecek 	return (0);
   1283  1.3.14.2  jdolecek }
   1284  1.3.14.2  jdolecek 
   1285  1.3.14.2  jdolecek #define SCTP_NUMBER_OF_MTU_SIZES 18
   1286  1.3.14.2  jdolecek static u_int32_t mtu_sizes[]={
   1287  1.3.14.2  jdolecek 	68,
   1288  1.3.14.2  jdolecek 	296,
   1289  1.3.14.2  jdolecek 	508,
   1290  1.3.14.2  jdolecek 	512,
   1291  1.3.14.2  jdolecek 	544,
   1292  1.3.14.2  jdolecek 	576,
   1293  1.3.14.2  jdolecek 	1006,
   1294  1.3.14.2  jdolecek 	1492,
   1295  1.3.14.2  jdolecek 	1500,
   1296  1.3.14.2  jdolecek 	1536,
   1297  1.3.14.2  jdolecek 	2002,
   1298  1.3.14.2  jdolecek 	2048,
   1299  1.3.14.2  jdolecek 	4352,
   1300  1.3.14.2  jdolecek 	4464,
   1301  1.3.14.2  jdolecek 	8166,
   1302  1.3.14.2  jdolecek 	17914,
   1303  1.3.14.2  jdolecek 	32000,
   1304  1.3.14.2  jdolecek 	65535
   1305  1.3.14.2  jdolecek };
   1306  1.3.14.2  jdolecek 
   1307  1.3.14.2  jdolecek 
   1308  1.3.14.2  jdolecek static u_int32_t
   1309  1.3.14.2  jdolecek sctp_getnext_mtu(struct sctp_inpcb *inp, u_int32_t cur_mtu)
   1310  1.3.14.2  jdolecek {
   1311  1.3.14.2  jdolecek 	/* select another MTU that is just bigger than this one */
   1312  1.3.14.2  jdolecek 	int i;
   1313  1.3.14.2  jdolecek 
   1314  1.3.14.2  jdolecek 	for (i = 0; i < SCTP_NUMBER_OF_MTU_SIZES; i++) {
   1315  1.3.14.2  jdolecek 		if (cur_mtu < mtu_sizes[i]) {
   1316  1.3.14.2  jdolecek 		    /* no max_mtu is bigger than this one */
   1317  1.3.14.2  jdolecek 		    return (mtu_sizes[i]);
   1318  1.3.14.2  jdolecek 		}
   1319  1.3.14.2  jdolecek 	}
   1320  1.3.14.2  jdolecek 	/* here return the highest allowable */
   1321  1.3.14.2  jdolecek 	return (cur_mtu);
   1322  1.3.14.2  jdolecek }
   1323  1.3.14.2  jdolecek 
   1324  1.3.14.2  jdolecek 
   1325  1.3.14.2  jdolecek void sctp_pathmtu_timer(struct sctp_inpcb *inp,
   1326  1.3.14.2  jdolecek 			struct sctp_tcb *stcb,
   1327  1.3.14.2  jdolecek 			struct sctp_nets *net)
   1328  1.3.14.2  jdolecek {
   1329  1.3.14.2  jdolecek 	u_int32_t next_mtu;
   1330  1.3.14.2  jdolecek 	struct rtentry *rt;
   1331  1.3.14.2  jdolecek 
   1332  1.3.14.2  jdolecek 	/* restart the timer in any case */
   1333  1.3.14.2  jdolecek 	next_mtu = sctp_getnext_mtu(inp, net->mtu);
   1334  1.3.14.2  jdolecek 	if (next_mtu <= net->mtu) {
   1335  1.3.14.2  jdolecek 	    /* nothing to do */
   1336  1.3.14.2  jdolecek 	    return;
   1337  1.3.14.2  jdolecek 	}
   1338  1.3.14.2  jdolecek 	rt = rtcache_validate(&net->ro);
   1339  1.3.14.2  jdolecek 	if (rt != NULL) {
   1340  1.3.14.2  jdolecek 		/* only if we have a route and interface do we
   1341  1.3.14.2  jdolecek 		 * set anything. Note we always restart
   1342  1.3.14.2  jdolecek 		 * the timer though just in case it is updated
   1343  1.3.14.2  jdolecek 		 * (i.e. the ifp) or route/ifp is populated.
   1344  1.3.14.2  jdolecek 		 */
   1345  1.3.14.2  jdolecek 		if (rt->rt_ifp != NULL) {
   1346  1.3.14.2  jdolecek 			if (rt->rt_ifp->if_mtu > next_mtu) {
   1347  1.3.14.2  jdolecek 				/* ok it will fit out the door */
   1348  1.3.14.2  jdolecek 				net->mtu = next_mtu;
   1349  1.3.14.2  jdolecek 			}
   1350  1.3.14.2  jdolecek 		}
   1351  1.3.14.2  jdolecek 		rtcache_unref(rt, &net->ro);
   1352  1.3.14.2  jdolecek 	}
   1353  1.3.14.2  jdolecek 	/* restart the timer */
   1354  1.3.14.2  jdolecek 	sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
   1355  1.3.14.2  jdolecek }
   1356  1.3.14.2  jdolecek 
   1357  1.3.14.2  jdolecek void sctp_autoclose_timer(struct sctp_inpcb *inp,
   1358  1.3.14.2  jdolecek 			  struct sctp_tcb *stcb,
   1359  1.3.14.2  jdolecek 			  struct sctp_nets *net)
   1360  1.3.14.2  jdolecek {
   1361  1.3.14.2  jdolecek 	struct timeval tn, *tim_touse;
   1362  1.3.14.2  jdolecek 	struct sctp_association *asoc;
   1363  1.3.14.2  jdolecek 	int ticks_gone_by;
   1364  1.3.14.2  jdolecek 
   1365  1.3.14.2  jdolecek 	SCTP_GETTIME_TIMEVAL(&tn);
   1366  1.3.14.2  jdolecek 	if (stcb->asoc.sctp_autoclose_ticks &&
   1367  1.3.14.2  jdolecek 	    (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
   1368  1.3.14.2  jdolecek 		/* Auto close is on */
   1369  1.3.14.2  jdolecek 		asoc = &stcb->asoc;
   1370  1.3.14.2  jdolecek 		/* pick the time to use */
   1371  1.3.14.2  jdolecek 		if (asoc->time_last_rcvd.tv_sec >
   1372  1.3.14.2  jdolecek 		    asoc->time_last_sent.tv_sec) {
   1373  1.3.14.2  jdolecek 			tim_touse = &asoc->time_last_rcvd;
   1374  1.3.14.2  jdolecek 		} else {
   1375  1.3.14.2  jdolecek 			tim_touse = &asoc->time_last_sent;
   1376  1.3.14.2  jdolecek 		}
   1377  1.3.14.2  jdolecek 		/* Now has long enough transpired to autoclose? */
   1378  1.3.14.2  jdolecek 		ticks_gone_by = ((tn.tv_sec - tim_touse->tv_sec) * hz);
   1379  1.3.14.2  jdolecek 		if ((ticks_gone_by > 0) &&
   1380  1.3.14.2  jdolecek 		    (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) {
   1381  1.3.14.2  jdolecek 			/*
   1382  1.3.14.2  jdolecek 			 * autoclose time has hit, call the output routine,
   1383  1.3.14.2  jdolecek 			 * which should do nothing just to be SURE we don't
   1384  1.3.14.2  jdolecek 			 * have hanging data. We can then safely check the
   1385  1.3.14.2  jdolecek 			 * queues and know that we are clear to send shutdown
   1386  1.3.14.2  jdolecek 			 */
   1387  1.3.14.2  jdolecek 			sctp_chunk_output(inp, stcb, 9);
   1388  1.3.14.2  jdolecek 			/* Are we clean? */
   1389  1.3.14.2  jdolecek 			if (TAILQ_EMPTY(&asoc->send_queue) &&
   1390  1.3.14.2  jdolecek 			    TAILQ_EMPTY(&asoc->sent_queue)) {
   1391  1.3.14.2  jdolecek 				/*
   1392  1.3.14.2  jdolecek 				 * there is nothing queued to send,
   1393  1.3.14.2  jdolecek 				 * so I'm done...
   1394  1.3.14.2  jdolecek 				 */
   1395  1.3.14.2  jdolecek 				if (SCTP_GET_STATE(asoc) !=
   1396  1.3.14.2  jdolecek 				    SCTP_STATE_SHUTDOWN_SENT) {
   1397  1.3.14.2  jdolecek 					/* only send SHUTDOWN 1st time thru */
   1398  1.3.14.2  jdolecek #ifdef SCTP_DEBUG
   1399  1.3.14.2  jdolecek 					if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
   1400  1.3.14.2  jdolecek 						printf("%s:%d sends a shutdown\n",
   1401  1.3.14.2  jdolecek 						       __FILE__,
   1402  1.3.14.2  jdolecek 						       __LINE__
   1403  1.3.14.2  jdolecek 							);
   1404  1.3.14.2  jdolecek 					}
   1405  1.3.14.2  jdolecek #endif
   1406  1.3.14.2  jdolecek 					sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
   1407  1.3.14.2  jdolecek 					asoc->state = SCTP_STATE_SHUTDOWN_SENT;
   1408  1.3.14.2  jdolecek 					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
   1409  1.3.14.2  jdolecek 					    stcb->sctp_ep, stcb,
   1410  1.3.14.2  jdolecek 					    asoc->primary_destination);
   1411  1.3.14.2  jdolecek 					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
   1412  1.3.14.2  jdolecek 					    stcb->sctp_ep, stcb,
   1413  1.3.14.2  jdolecek 					    asoc->primary_destination);
   1414  1.3.14.2  jdolecek 				}
   1415  1.3.14.2  jdolecek 			}
   1416  1.3.14.2  jdolecek 		} else {
   1417  1.3.14.2  jdolecek 			/*
   1418  1.3.14.2  jdolecek 			 * No auto close at this time, reset t-o to
   1419  1.3.14.2  jdolecek 			 * check later
   1420  1.3.14.2  jdolecek 			 */
   1421  1.3.14.2  jdolecek 			int tmp;
   1422  1.3.14.2  jdolecek 			/* fool the timer startup to use the time left */
   1423  1.3.14.2  jdolecek 			tmp = asoc->sctp_autoclose_ticks;
   1424  1.3.14.2  jdolecek 			asoc->sctp_autoclose_ticks -= ticks_gone_by;
   1425  1.3.14.2  jdolecek 			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
   1426  1.3.14.2  jdolecek 					 net);
   1427  1.3.14.2  jdolecek 			/* restore the real tick value */
   1428  1.3.14.2  jdolecek 			asoc->sctp_autoclose_ticks = tmp;
   1429  1.3.14.2  jdolecek 		}
   1430  1.3.14.2  jdolecek 	}
   1431  1.3.14.2  jdolecek }
   1432  1.3.14.2  jdolecek 
   1433  1.3.14.2  jdolecek void
   1434  1.3.14.2  jdolecek sctp_iterator_timer(struct sctp_iterator *it)
   1435  1.3.14.2  jdolecek {
   1436  1.3.14.2  jdolecek 	int cnt= 0;
   1437  1.3.14.2  jdolecek 	/* only one iterator can run at a
   1438  1.3.14.2  jdolecek 	 * time. This is the only way we
   1439  1.3.14.2  jdolecek 	 * can cleanly pull ep's from underneath
   1440  1.3.14.2  jdolecek 	 * all the running interators when a
   1441  1.3.14.2  jdolecek 	 * ep is freed.
   1442  1.3.14.2  jdolecek 	 */
   1443  1.3.14.2  jdolecek  	SCTP_ITERATOR_LOCK();
   1444  1.3.14.2  jdolecek 	if (it->inp == NULL) {
   1445  1.3.14.2  jdolecek 		/* iterator is complete */
   1446  1.3.14.2  jdolecek 	done_with_iterator:
   1447  1.3.14.2  jdolecek 		SCTP_ITERATOR_UNLOCK();
   1448  1.3.14.2  jdolecek 		SCTP_INP_INFO_WLOCK();
   1449  1.3.14.2  jdolecek 		LIST_REMOVE(it, sctp_nxt_itr);
   1450  1.3.14.2  jdolecek 		/* stopping the callout is not needed, in theory,
   1451  1.3.14.2  jdolecek 		 * but I am paranoid.
   1452  1.3.14.2  jdolecek 		 */
   1453  1.3.14.2  jdolecek 		SCTP_INP_INFO_WUNLOCK();
   1454  1.3.14.2  jdolecek 		callout_stop(&it->tmr.timer);
   1455  1.3.14.2  jdolecek 		if (it->function_atend != NULL) {
   1456  1.3.14.2  jdolecek 			(*it->function_atend)(it->pointer, it->val);
   1457  1.3.14.2  jdolecek 		}
   1458  1.3.14.2  jdolecek 		callout_destroy(&it->tmr.timer);
   1459  1.3.14.2  jdolecek 		free(it, M_PCB);
   1460  1.3.14.2  jdolecek 		return;
   1461  1.3.14.2  jdolecek 	}
   1462  1.3.14.2  jdolecek  select_a_new_ep:
   1463  1.3.14.2  jdolecek 	SCTP_INP_WLOCK(it->inp);
   1464  1.3.14.2  jdolecek 	while ((it->pcb_flags) && ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) {
   1465  1.3.14.2  jdolecek 		/* we do not like this ep */
   1466  1.3.14.2  jdolecek 		if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
   1467  1.3.14.2  jdolecek 			SCTP_INP_WUNLOCK(it->inp);
   1468  1.3.14.2  jdolecek 			goto done_with_iterator;
   1469  1.3.14.2  jdolecek 		}
   1470  1.3.14.2  jdolecek 		SCTP_INP_WUNLOCK(it->inp);
   1471  1.3.14.2  jdolecek 		it->inp = LIST_NEXT(it->inp, sctp_list);
   1472  1.3.14.2  jdolecek 		if (it->inp == NULL) {
   1473  1.3.14.2  jdolecek 			goto done_with_iterator;
   1474  1.3.14.2  jdolecek 		}
   1475  1.3.14.2  jdolecek 		SCTP_INP_WLOCK(it->inp);
   1476  1.3.14.2  jdolecek 	}
   1477  1.3.14.2  jdolecek 	if ((it->inp->inp_starting_point_for_iterator != NULL) &&
   1478  1.3.14.2  jdolecek 	    (it->inp->inp_starting_point_for_iterator != it)) {
   1479  1.3.14.2  jdolecek 		printf("Iterator collision, we must wait for other iterator at %p\n",
   1480  1.3.14.2  jdolecek 		       it->inp);
   1481  1.3.14.2  jdolecek 		SCTP_INP_WUNLOCK(it->inp);
   1482  1.3.14.2  jdolecek 		goto start_timer_return;
   1483  1.3.14.2  jdolecek 	}
   1484  1.3.14.2  jdolecek 	/* now we do the actual write to this guy */
   1485  1.3.14.2  jdolecek 	it->inp->inp_starting_point_for_iterator = it;
   1486  1.3.14.2  jdolecek 	SCTP_INP_WUNLOCK(it->inp);
   1487  1.3.14.2  jdolecek 	SCTP_INP_RLOCK(it->inp);
   1488  1.3.14.2  jdolecek 	/* if we reach here we found a inp acceptable, now through each
   1489  1.3.14.2  jdolecek 	 * one that has the association in the right state
   1490  1.3.14.2  jdolecek 	 */
   1491  1.3.14.2  jdolecek 	if (it->stcb == NULL) {
   1492  1.3.14.2  jdolecek 		it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
   1493  1.3.14.2  jdolecek 	}
   1494  1.3.14.2  jdolecek 	if (it->stcb->asoc.stcb_starting_point_for_iterator == it) {
   1495  1.3.14.2  jdolecek 		it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
   1496  1.3.14.2  jdolecek 	}
   1497  1.3.14.2  jdolecek 	while (it->stcb) {
   1498  1.3.14.2  jdolecek 		SCTP_TCB_LOCK(it->stcb);
   1499  1.3.14.2  jdolecek 		if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
   1500  1.3.14.2  jdolecek 			SCTP_TCB_UNLOCK(it->stcb);
   1501  1.3.14.2  jdolecek 			it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
   1502  1.3.14.2  jdolecek 			continue;
   1503  1.3.14.2  jdolecek 		}
   1504  1.3.14.2  jdolecek 		cnt++;
   1505  1.3.14.2  jdolecek 		/* run function on this one */
   1506  1.3.14.2  jdolecek 		SCTP_INP_RUNLOCK(it->inp);
   1507  1.3.14.2  jdolecek 		(*it->function_toapply)(it->inp, it->stcb, it->pointer, it->val);
   1508  1.3.14.2  jdolecek 		sctp_chunk_output(it->inp, it->stcb, 1);
   1509  1.3.14.2  jdolecek 		SCTP_TCB_UNLOCK(it->stcb);
   1510  1.3.14.2  jdolecek 		/* see if we have limited out */
   1511  1.3.14.2  jdolecek 		if (cnt > SCTP_MAX_ITERATOR_AT_ONCE) {
   1512  1.3.14.2  jdolecek 			it->stcb->asoc.stcb_starting_point_for_iterator = it;
   1513  1.3.14.2  jdolecek 		start_timer_return:
   1514  1.3.14.2  jdolecek 			SCTP_ITERATOR_UNLOCK();
   1515  1.3.14.2  jdolecek 			sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, (struct sctp_inpcb *)it, NULL, NULL);
   1516  1.3.14.2  jdolecek 			return;
   1517  1.3.14.2  jdolecek 		}
   1518  1.3.14.2  jdolecek 		SCTP_INP_RLOCK(it->inp);
   1519  1.3.14.2  jdolecek 		it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
   1520  1.3.14.2  jdolecek 	}
   1521  1.3.14.2  jdolecek 	/* if we reach here, we ran out of stcb's in the inp we are looking at */
   1522  1.3.14.2  jdolecek 	SCTP_INP_RUNLOCK(it->inp);
   1523  1.3.14.2  jdolecek 	SCTP_INP_WLOCK(it->inp);
   1524  1.3.14.2  jdolecek 	it->inp->inp_starting_point_for_iterator = NULL;
   1525  1.3.14.2  jdolecek 	SCTP_INP_WUNLOCK(it->inp);
   1526  1.3.14.2  jdolecek 	if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
   1527  1.3.14.2  jdolecek 		it->inp = NULL;
   1528  1.3.14.2  jdolecek 	} else {
   1529  1.3.14.2  jdolecek 		SCTP_INP_INFO_RLOCK();
   1530  1.3.14.2  jdolecek 		it->inp = LIST_NEXT(it->inp, sctp_list);
   1531  1.3.14.2  jdolecek 		SCTP_INP_INFO_RUNLOCK();
   1532  1.3.14.2  jdolecek 	}
   1533  1.3.14.2  jdolecek 	if (it->inp == NULL) {
   1534  1.3.14.2  jdolecek 		goto done_with_iterator;
   1535  1.3.14.2  jdolecek 	}
   1536  1.3.14.2  jdolecek 	goto select_a_new_ep;
   1537  1.3.14.2  jdolecek }
   1538