sctp_timer.c revision 172156
1163953Srrs/*-
2169382Srrs * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3163953Srrs *
4163953Srrs * Redistribution and use in source and binary forms, with or without
5163953Srrs * modification, are permitted provided that the following conditions are met:
6163953Srrs *
7163953Srrs * a) Redistributions of source code must retain the above copyright notice,
8163953Srrs *   this list of conditions and the following disclaimer.
9163953Srrs *
10163953Srrs * b) Redistributions in binary form must reproduce the above copyright
11163953Srrs *    notice, this list of conditions and the following disclaimer in
12163953Srrs *   the documentation and/or other materials provided with the distribution.
13163953Srrs *
14163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its
15163953Srrs *    contributors may be used to endorse or promote products derived
16163953Srrs *    from this software without specific prior written permission.
17163953Srrs *
18163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28163953Srrs * THE POSSIBILITY OF SUCH DAMAGE.
29163953Srrs */
30163953Srrs
31163953Srrs/* $KAME: sctp_timer.c,v 1.29 2005/03/06 16:04:18 itojun Exp $	 */
32163953Srrs
33163953Srrs#include <sys/cdefs.h>
34163953Srrs__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 172156 2007-09-13 10:36:43Z rrs $");
35163953Srrs
36163953Srrs#define _IP_VHL
37166086Srrs#include <netinet/sctp_os.h>
38163953Srrs#include <netinet/sctp_pcb.h>
39163953Srrs#ifdef INET6
40163953Srrs#include <netinet6/sctp6_var.h>
41163953Srrs#endif
42163953Srrs#include <netinet/sctp_var.h>
43167598Srrs#include <netinet/sctp_sysctl.h>
44163953Srrs#include <netinet/sctp_timer.h>
45163953Srrs#include <netinet/sctputil.h>
46163953Srrs#include <netinet/sctp_output.h>
47163953Srrs#include <netinet/sctp_header.h>
48163953Srrs#include <netinet/sctp_indata.h>
49163953Srrs#include <netinet/sctp_asconf.h>
50163953Srrs#include <netinet/sctp_input.h>
51163953Srrs#include <netinet/sctp.h>
52163953Srrs#include <netinet/sctp_uio.h>
53163953Srrs
54163953Srrs
55163953Srrs
56163953Srrsvoid
57163953Srrssctp_early_fr_timer(struct sctp_inpcb *inp,
58163953Srrs    struct sctp_tcb *stcb,
59163953Srrs    struct sctp_nets *net)
60163953Srrs{
61163953Srrs	struct sctp_tmit_chunk *chk, *tp2;
62163953Srrs	struct timeval now, min_wait, tv;
63163953Srrs	unsigned int cur_rtt, cnt = 0, cnt_resend = 0;
64163953Srrs
65163953Srrs	/* an early FR is occuring. */
66169378Srrs	(void)SCTP_GETTIME_TIMEVAL(&now);
67163953Srrs	/* get cur rto in micro-seconds */
68163953Srrs	if (net->lastsa == 0) {
69163953Srrs		/* Hmm no rtt estimate yet? */
70163953Srrs		cur_rtt = stcb->asoc.initial_rto >> 2;
71163953Srrs	} else {
72163953Srrs
73163953Srrs		cur_rtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
74163953Srrs	}
75163953Srrs	if (cur_rtt < sctp_early_fr_msec) {
76163953Srrs		cur_rtt = sctp_early_fr_msec;
77163953Srrs	}
78163953Srrs	cur_rtt *= 1000;
79163953Srrs	tv.tv_sec = cur_rtt / 1000000;
80163953Srrs	tv.tv_usec = cur_rtt % 1000000;
81163953Srrs	min_wait = now;
82163953Srrs	timevalsub(&min_wait, &tv);
83163953Srrs	if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
84163953Srrs		/*
85163953Srrs		 * if we hit here, we don't have enough seconds on the clock
86163953Srrs		 * to account for the RTO. We just let the lower seconds be
87163953Srrs		 * the bounds and don't worry about it. This may mean we
88163953Srrs		 * will mark a lot more than we should.
89163953Srrs		 */
90163953Srrs		min_wait.tv_sec = min_wait.tv_usec = 0;
91163953Srrs	}
92163953Srrs	chk = TAILQ_LAST(&stcb->asoc.sent_queue, sctpchunk_listhead);
93163953Srrs	for (; chk != NULL; chk = tp2) {
94163953Srrs		tp2 = TAILQ_PREV(chk, sctpchunk_listhead, sctp_next);
95163953Srrs		if (chk->whoTo != net) {
96163953Srrs			continue;
97163953Srrs		}
98163953Srrs		if (chk->sent == SCTP_DATAGRAM_RESEND)
99163953Srrs			cnt_resend++;
100163953Srrs		else if ((chk->sent > SCTP_DATAGRAM_UNSENT) &&
101163953Srrs		    (chk->sent < SCTP_DATAGRAM_RESEND)) {
102163953Srrs			/* pending, may need retran */
103163953Srrs			if (chk->sent_rcv_time.tv_sec > min_wait.tv_sec) {
104163953Srrs				/*
105163953Srrs				 * we have reached a chunk that was sent
106163953Srrs				 * some seconds past our min.. forget it we
107163953Srrs				 * will find no more to send.
108163953Srrs				 */
109163953Srrs				continue;
110163953Srrs			} else if (chk->sent_rcv_time.tv_sec == min_wait.tv_sec) {
111163953Srrs				/*
112163953Srrs				 * we must look at the micro seconds to
113163953Srrs				 * know.
114163953Srrs				 */
115163953Srrs				if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) {
116163953Srrs					/*
117163953Srrs					 * ok it was sent after our boundary
118163953Srrs					 * time.
119163953Srrs					 */
120163953Srrs					continue;
121163953Srrs				}
122163953Srrs			}
123170744Srrs			if (sctp_logging_level & SCTP_EARLYFR_LOGGING_ENABLE) {
124170744Srrs				sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
125170744Srrs				    4, SCTP_FR_MARKED_EARLY);
126170744Srrs			}
127163953Srrs			SCTP_STAT_INCR(sctps_earlyfrmrkretrans);
128163953Srrs			chk->sent = SCTP_DATAGRAM_RESEND;
129163953Srrs			sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
130163953Srrs			/* double book size since we are doing an early FR */
131163953Srrs			chk->book_size_scale++;
132163953Srrs			cnt += chk->send_size;
133163953Srrs			if ((cnt + net->flight_size) > net->cwnd) {
134163953Srrs				/* Mark all we could possibly resend */
135163953Srrs				break;
136163953Srrs			}
137163953Srrs		}
138163953Srrs	}
139163953Srrs	if (cnt) {
140163953Srrs		/*
141171440Srrs		 * JRS - Use the congestion control given in the congestion
142171440Srrs		 * control module
143163953Srrs		 */
144171440Srrs		stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer(inp, stcb, net);
145163953Srrs	} else if (cnt_resend) {
146172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
147163953Srrs	}
148163953Srrs	/* Restart it? */
149163953Srrs	if (net->flight_size < net->cwnd) {
150163953Srrs		SCTP_STAT_INCR(sctps_earlyfrstrtmr);
151163953Srrs		sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
152163953Srrs	}
153163953Srrs}
154163953Srrs
155163953Srrsvoid
156163953Srrssctp_audit_retranmission_queue(struct sctp_association *asoc)
157163953Srrs{
158163953Srrs	struct sctp_tmit_chunk *chk;
159163953Srrs
160169420Srrs	SCTPDBG(SCTP_DEBUG_TIMER4, "Audit invoked on send queue cnt:%d onqueue:%d\n",
161169420Srrs	    asoc->sent_queue_retran_cnt,
162169420Srrs	    asoc->sent_queue_cnt);
163163953Srrs	asoc->sent_queue_retran_cnt = 0;
164163953Srrs	asoc->sent_queue_cnt = 0;
165163953Srrs	TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
166163953Srrs		if (chk->sent == SCTP_DATAGRAM_RESEND) {
167163953Srrs			sctp_ucount_incr(asoc->sent_queue_retran_cnt);
168163953Srrs		}
169163953Srrs		asoc->sent_queue_cnt++;
170163953Srrs	}
171163953Srrs	TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
172163953Srrs		if (chk->sent == SCTP_DATAGRAM_RESEND) {
173163953Srrs			sctp_ucount_incr(asoc->sent_queue_retran_cnt);
174163953Srrs		}
175163953Srrs	}
176169420Srrs	SCTPDBG(SCTP_DEBUG_TIMER4, "Audit completes retran:%d onqueue:%d\n",
177169420Srrs	    asoc->sent_queue_retran_cnt,
178169420Srrs	    asoc->sent_queue_cnt);
179163953Srrs}
180163953Srrs
181163953Srrsint
182163953Srrssctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
183163953Srrs    struct sctp_nets *net, uint16_t threshold)
184163953Srrs{
185163953Srrs	if (net) {
186163953Srrs		net->error_count++;
187169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER4, "Error count for %p now %d thresh:%d\n",
188169420Srrs		    net, net->error_count,
189169420Srrs		    net->failure_threshold);
190163953Srrs		if (net->error_count > net->failure_threshold) {
191163953Srrs			/* We had a threshold failure */
192163953Srrs			if (net->dest_state & SCTP_ADDR_REACHABLE) {
193163953Srrs				net->dest_state &= ~SCTP_ADDR_REACHABLE;
194163953Srrs				net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
195167598Srrs				net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
196163953Srrs				if (net == stcb->asoc.primary_destination) {
197163953Srrs					net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
198163953Srrs				}
199171440Srrs				/*
200171440Srrs				 * JRS 5/14/07 - If a destination is
201171440Srrs				 * unreachable, the PF bit is turned off.
202171440Srrs				 * This allows an unambiguous use of the PF
203171440Srrs				 * bit for destinations that are reachable
204171440Srrs				 * but potentially failed. If the
205171440Srrs				 * destination is set to the unreachable
206171440Srrs				 * state, also set the destination to the PF
207171440Srrs				 * state.
208171440Srrs				 */
209171440Srrs				/*
210171440Srrs				 * Add debug message here if destination is
211171440Srrs				 * not in PF state.
212171440Srrs				 */
213171440Srrs				/* Stop any running T3 timers here? */
214171477Srrs				if (sctp_cmt_on_off && sctp_cmt_pf) {
215171440Srrs					net->dest_state &= ~SCTP_ADDR_PF;
216171440Srrs					SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
217171440Srrs					    net);
218171440Srrs				}
219163953Srrs				sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
220163953Srrs				    stcb,
221163953Srrs				    SCTP_FAILED_THRESHOLD,
222172090Srrs				    (void *)net, SCTP_SO_NOT_LOCKED);
223163953Srrs			}
224163953Srrs		}
225163953Srrs		/*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE
226163953Srrs		 *********ROUTING CODE
227163953Srrs		 */
228163953Srrs		/*********HOLD THIS COMMENT FOR END OF PATCH OF ALTERNATE
229163953Srrs		 *********ROUTING CODE
230163953Srrs		 */
231163953Srrs	}
232163953Srrs	if (stcb == NULL)
233163953Srrs		return (0);
234163953Srrs
235163953Srrs	if (net) {
236163953Srrs		if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
237171943Srrs			if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
238171943Srrs				sctp_misc_ints(SCTP_THRESHOLD_INCR,
239171943Srrs				    stcb->asoc.overall_error_count,
240171943Srrs				    (stcb->asoc.overall_error_count + 1),
241171943Srrs				    SCTP_FROM_SCTP_TIMER,
242171943Srrs				    __LINE__);
243171943Srrs			}
244163953Srrs			stcb->asoc.overall_error_count++;
245163953Srrs		}
246163953Srrs	} else {
247171943Srrs		if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
248171943Srrs			sctp_misc_ints(SCTP_THRESHOLD_INCR,
249171943Srrs			    stcb->asoc.overall_error_count,
250171943Srrs			    (stcb->asoc.overall_error_count + 1),
251171943Srrs			    SCTP_FROM_SCTP_TIMER,
252171943Srrs			    __LINE__);
253171943Srrs		}
254163953Srrs		stcb->asoc.overall_error_count++;
255163953Srrs	}
256169420Srrs	SCTPDBG(SCTP_DEBUG_TIMER4, "Overall error count for %p now %d thresh:%u state:%x\n",
257169420Srrs	    &stcb->asoc, stcb->asoc.overall_error_count,
258169420Srrs	    (uint32_t) threshold,
259169420Srrs	    ((net == NULL) ? (uint32_t) 0 : (uint32_t) net->dest_state));
260163953Srrs	/*
261163953Srrs	 * We specifically do not do >= to give the assoc one more change
262163953Srrs	 * before we fail it.
263163953Srrs	 */
264163953Srrs	if (stcb->asoc.overall_error_count > threshold) {
265163953Srrs		/* Abort notification sends a ULP notify */
266163953Srrs		struct mbuf *oper;
267163953Srrs
268163953Srrs		oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
269163953Srrs		    0, M_DONTWAIT, 1, MT_DATA);
270163953Srrs		if (oper) {
271163953Srrs			struct sctp_paramhdr *ph;
272163953Srrs			uint32_t *ippp;
273163953Srrs
274165647Srrs			SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
275163953Srrs			    sizeof(uint32_t);
276163953Srrs			ph = mtod(oper, struct sctp_paramhdr *);
277163953Srrs			ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
278165647Srrs			ph->param_length = htons(SCTP_BUF_LEN(oper));
279163953Srrs			ippp = (uint32_t *) (ph + 1);
280165220Srrs			*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1);
281163953Srrs		}
282165220Srrs		inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1;
283172090Srrs		sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper, SCTP_SO_NOT_LOCKED);
284163953Srrs		return (1);
285163953Srrs	}
286163953Srrs	return (0);
287163953Srrs}
288163953Srrs
289163953Srrsstruct sctp_nets *
290163953Srrssctp_find_alternate_net(struct sctp_tcb *stcb,
291163953Srrs    struct sctp_nets *net,
292171440Srrs    int mode)
293163953Srrs{
294163953Srrs	/* Find and return an alternate network if possible */
295171440Srrs	struct sctp_nets *alt, *mnet, *min_errors_net = NULL, *max_cwnd_net = NULL;
296163953Srrs	int once;
297163953Srrs
298171440Srrs	/* JRS 5/14/07 - Initialize min_errors to an impossible value. */
299171440Srrs	int min_errors = -1;
300171440Srrs	uint32_t max_cwnd = 0;
301171440Srrs
302163953Srrs	if (stcb->asoc.numnets == 1) {
303163953Srrs		/* No others but net */
304163953Srrs		return (TAILQ_FIRST(&stcb->asoc.nets));
305163953Srrs	}
306171440Srrs	/*
307171440Srrs	 * JRS 5/14/07 - If mode is set to 2, use the CMT PF find alternate
308171440Srrs	 * net algorithm. This algorithm chooses the active destination (not
309171440Srrs	 * in PF state) with the largest cwnd value. If all destinations are
310171440Srrs	 * in PF state, unreachable, or unconfirmed, choose the desination
311171440Srrs	 * that is in PF state with the lowest error count. In case of a
312171440Srrs	 * tie, choose the destination that was most recently active.
313171440Srrs	 */
314171440Srrs	if (mode == 2) {
315163953Srrs		TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) {
316171440Srrs			/*
317171440Srrs			 * JRS 5/14/07 - If the destination is unreachable
318171440Srrs			 * or unconfirmed, skip it.
319171440Srrs			 */
320163953Srrs			if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) ||
321171440Srrs			    (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) {
322171440Srrs				continue;
323171440Srrs			}
324171440Srrs			/*
325171440Srrs			 * JRS 5/14/07 -  If the destination is reachable
326171440Srrs			 * but in PF state, compare the error count of the
327171440Srrs			 * destination to the minimum error count seen thus
328171440Srrs			 * far. Store the destination with the lower error
329171440Srrs			 * count.  If the error counts are equal, store the
330171440Srrs			 * destination that was most recently active.
331171440Srrs			 */
332171440Srrs			if (mnet->dest_state & SCTP_ADDR_PF) {
333171440Srrs				/*
334171440Srrs				 * JRS 5/14/07 - If the destination under
335171440Srrs				 * consideration is the current destination,
336171440Srrs				 * work as if the error count is one higher.
337171440Srrs				 * The actual error count will not be
338171440Srrs				 * incremented until later in the t3
339171440Srrs				 * handler.
340171440Srrs				 */
341171440Srrs				if (mnet == net) {
342171440Srrs					if (min_errors == -1) {
343171440Srrs						min_errors = mnet->error_count + 1;
344171440Srrs						min_errors_net = mnet;
345171440Srrs					} else if (mnet->error_count + 1 < min_errors) {
346171440Srrs						min_errors = mnet->error_count + 1;
347171440Srrs						min_errors_net = mnet;
348171440Srrs					} else if (mnet->error_count + 1 == min_errors
349171440Srrs					    && mnet->last_active > min_errors_net->last_active) {
350171440Srrs						min_errors_net = mnet;
351171440Srrs						min_errors = mnet->error_count + 1;
352171440Srrs					}
353171440Srrs					continue;
354171440Srrs				} else {
355171440Srrs					if (min_errors == -1) {
356171440Srrs						min_errors = mnet->error_count;
357171440Srrs						min_errors_net = mnet;
358171440Srrs					} else if (mnet->error_count < min_errors) {
359171440Srrs						min_errors = mnet->error_count;
360171440Srrs						min_errors_net = mnet;
361171440Srrs					} else if (mnet->error_count == min_errors
362171440Srrs					    && mnet->last_active > min_errors_net->last_active) {
363171440Srrs						min_errors_net = mnet;
364171440Srrs						min_errors = mnet->error_count;
365171440Srrs					}
366171440Srrs					continue;
367171440Srrs				}
368171440Srrs			}
369171440Srrs			/*
370171440Srrs			 * JRS 5/14/07 - If the destination is reachable and
371171440Srrs			 * not in PF state, compare the cwnd of the
372171440Srrs			 * destination to the highest cwnd seen thus far.
373171440Srrs			 * Store the destination with the higher cwnd value.
374171440Srrs			 * If the cwnd values are equal, randomly choose one
375171440Srrs			 * of the two destinations.
376171440Srrs			 */
377171440Srrs			if (max_cwnd < mnet->cwnd) {
378171440Srrs				max_cwnd_net = mnet;
379171440Srrs				max_cwnd = mnet->cwnd;
380171440Srrs			} else if (max_cwnd == mnet->cwnd) {
381171440Srrs				uint32_t rndval;
382171440Srrs				uint8_t this_random;
383171440Srrs
384171440Srrs				if (stcb->asoc.hb_random_idx > 3) {
385171440Srrs					rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep);
386171440Srrs					memcpy(stcb->asoc.hb_random_values, &rndval, sizeof(stcb->asoc.hb_random_values));
387171440Srrs					this_random = stcb->asoc.hb_random_values[0];
388171440Srrs					stcb->asoc.hb_random_idx++;
389171440Srrs					stcb->asoc.hb_ect_randombit = 0;
390171440Srrs				} else {
391171440Srrs					this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
392171440Srrs					stcb->asoc.hb_random_idx++;
393171440Srrs					stcb->asoc.hb_ect_randombit = 0;
394171440Srrs				}
395171440Srrs				if (this_random % 2 == 1) {
396171440Srrs					max_cwnd_net = mnet;
397171440Srrs					max_cwnd = mnet->cwnd;
398171440Srrs					//Useless ?
399171440Srrs				}
400171440Srrs			}
401171440Srrs		}
402171440Srrs		/*
403171440Srrs		 * JRS 5/14/07 - After all destination have been considered
404171440Srrs		 * as alternates, check to see if there was some active
405171440Srrs		 * destination (not in PF state).  If not, check to see if
406171440Srrs		 * there was some PF destination with the minimum number of
407171440Srrs		 * errors.  If not, return the original destination.  If
408171440Srrs		 * there is a min_errors_net, remove the PF flag from that
409171440Srrs		 * destination, set the cwnd to one or two MTUs, and return
410171440Srrs		 * the destination as an alt. If there was some active
411171440Srrs		 * destination with a highest cwnd, return the destination
412171440Srrs		 * as an alt.
413171440Srrs		 */
414171440Srrs		if (max_cwnd_net == NULL) {
415171440Srrs			if (min_errors_net == NULL) {
416171440Srrs				return (net);
417171440Srrs			}
418171440Srrs			min_errors_net->dest_state &= ~SCTP_ADDR_PF;
419171440Srrs			min_errors_net->cwnd = min_errors_net->mtu * sctp_cmt_pf;
420171440Srrs			if (SCTP_OS_TIMER_PENDING(&min_errors_net->rxt_timer.timer)) {
421171440Srrs				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
422171440Srrs				    stcb, min_errors_net,
423171440Srrs				    SCTP_FROM_SCTP_TIMER + SCTP_LOC_2);
424171440Srrs			}
425171440Srrs			SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to active with %d errors.\n",
426171440Srrs			    min_errors_net, min_errors_net->error_count);
427171440Srrs			return (min_errors_net);
428171440Srrs		} else {
429171440Srrs			return (max_cwnd_net);
430171440Srrs		}
431171440Srrs	}
432171440Srrs	/*
433171440Srrs	 * JRS 5/14/07 - If mode is set to 1, use the CMT policy for
434171440Srrs	 * choosing an alternate net.
435171440Srrs	 */
436171440Srrs	else if (mode == 1) {
437171440Srrs		TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) {
438171440Srrs			if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) ||
439163953Srrs			    (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)
440163953Srrs			    ) {
441163953Srrs				/*
442163953Srrs				 * will skip ones that are not-reachable or
443163953Srrs				 * unconfirmed
444163953Srrs				 */
445163953Srrs				continue;
446163953Srrs			}
447171440Srrs			if (max_cwnd < mnet->cwnd) {
448171440Srrs				max_cwnd_net = mnet;
449171440Srrs				max_cwnd = mnet->cwnd;
450171440Srrs			} else if (max_cwnd == mnet->cwnd) {
451163953Srrs				uint32_t rndval;
452163953Srrs				uint8_t this_random;
453163953Srrs
454163953Srrs				if (stcb->asoc.hb_random_idx > 3) {
455163953Srrs					rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep);
456163953Srrs					memcpy(stcb->asoc.hb_random_values, &rndval,
457163953Srrs					    sizeof(stcb->asoc.hb_random_values));
458163953Srrs					this_random = stcb->asoc.hb_random_values[0];
459163953Srrs					stcb->asoc.hb_random_idx = 0;
460163953Srrs					stcb->asoc.hb_ect_randombit = 0;
461163953Srrs				} else {
462163953Srrs					this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
463163953Srrs					stcb->asoc.hb_random_idx++;
464163953Srrs					stcb->asoc.hb_ect_randombit = 0;
465163953Srrs				}
466163953Srrs				if (this_random % 2) {
467171440Srrs					max_cwnd_net = mnet;
468171440Srrs					max_cwnd = mnet->cwnd;
469163953Srrs				}
470163953Srrs			}
471163953Srrs		}
472171440Srrs		if (max_cwnd_net) {
473171440Srrs			return (max_cwnd_net);
474163953Srrs		}
475163953Srrs	}
476163953Srrs	mnet = net;
477163953Srrs	once = 0;
478163953Srrs
479163953Srrs	if (mnet == NULL) {
480163953Srrs		mnet = TAILQ_FIRST(&stcb->asoc.nets);
481163953Srrs	}
482163953Srrs	do {
483163953Srrs		alt = TAILQ_NEXT(mnet, sctp_next);
484163953Srrs		if (alt == NULL) {
485163953Srrs			once++;
486163953Srrs			if (once > 1) {
487163953Srrs				break;
488163953Srrs			}
489163953Srrs			alt = TAILQ_FIRST(&stcb->asoc.nets);
490163953Srrs		}
491163953Srrs		if (alt->ro.ro_rt == NULL) {
492167598Srrs			if (alt->ro._s_addr) {
493167598Srrs				sctp_free_ifa(alt->ro._s_addr);
494167598Srrs				alt->ro._s_addr = NULL;
495167598Srrs			}
496163953Srrs			alt->src_addr_selected = 0;
497163953Srrs		}
498163953Srrs		if (
499163953Srrs		    ((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
500163953Srrs		    (alt->ro.ro_rt != NULL) &&
501169655Srrs		/* sa_ignore NO_NULL_CHK */
502163953Srrs		    (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))
503163953Srrs		    ) {
504163953Srrs			/* Found a reachable address */
505163953Srrs			break;
506163953Srrs		}
507163953Srrs		mnet = alt;
508163953Srrs	} while (alt != NULL);
509163953Srrs
510163953Srrs	if (alt == NULL) {
511163953Srrs		/* Case where NO insv network exists (dormant state) */
512163953Srrs		/* we rotate destinations */
513163953Srrs		once = 0;
514163953Srrs		mnet = net;
515163953Srrs		do {
516163953Srrs			alt = TAILQ_NEXT(mnet, sctp_next);
517163953Srrs			if (alt == NULL) {
518163953Srrs				once++;
519163953Srrs				if (once > 1) {
520163953Srrs					break;
521163953Srrs				}
522163953Srrs				alt = TAILQ_FIRST(&stcb->asoc.nets);
523163953Srrs			}
524169655Srrs			/* sa_ignore NO_NULL_CHK */
525163953Srrs			if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
526163953Srrs			    (alt != net)) {
527163953Srrs				/* Found an alternate address */
528163953Srrs				break;
529163953Srrs			}
530163953Srrs			mnet = alt;
531163953Srrs		} while (alt != NULL);
532163953Srrs	}
533163953Srrs	if (alt == NULL) {
534163953Srrs		return (net);
535163953Srrs	}
536163953Srrs	return (alt);
537163953Srrs}
538163953Srrs
539171440Srrs
540171440Srrs
541163953Srrsstatic void
542163953Srrssctp_backoff_on_timeout(struct sctp_tcb *stcb,
543163953Srrs    struct sctp_nets *net,
544163953Srrs    int win_probe,
545163953Srrs    int num_marked)
546163953Srrs{
547170642Srrs	if (net->RTO == 0) {
548170642Srrs		net->RTO = stcb->asoc.minrto;
549170642Srrs	}
550163953Srrs	net->RTO <<= 1;
551163953Srrs	if (net->RTO > stcb->asoc.maxrto) {
552163953Srrs		net->RTO = stcb->asoc.maxrto;
553163953Srrs	}
554163953Srrs	if ((win_probe == 0) && num_marked) {
555163953Srrs		/* We don't apply penalty to window probe scenarios */
556171440Srrs		/* JRS - Use the congestion control given in the CC module */
557171440Srrs		stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout(stcb, net);
558163953Srrs	}
559163953Srrs}
560163953Srrs
561163953Srrsstatic int
562163953Srrssctp_mark_all_for_resend(struct sctp_tcb *stcb,
563163953Srrs    struct sctp_nets *net,
564163953Srrs    struct sctp_nets *alt,
565163953Srrs    int window_probe,
566163953Srrs    int *num_marked)
567163953Srrs{
568163953Srrs
569163953Srrs	/*
570163953Srrs	 * Mark all chunks (well not all) that were sent to *net for
571163953Srrs	 * retransmission. Move them to alt for there destination as well...
572163953Srrs	 * We only mark chunks that have been outstanding long enough to
573163953Srrs	 * have received feed-back.
574163953Srrs	 */
575163953Srrs	struct sctp_tmit_chunk *chk, *tp2, *could_be_sent = NULL;
576163953Srrs	struct sctp_nets *lnets;
577163953Srrs	struct timeval now, min_wait, tv;
578163953Srrs	int cur_rtt;
579168709Srrs	int audit_tf, num_mk, fir;
580163953Srrs	unsigned int cnt_mk;
581168709Srrs	uint32_t orig_flight, orig_tf;
582163953Srrs	uint32_t tsnlast, tsnfirst;
583163953Srrs
584171440Srrs
585163953Srrs	/* none in flight now */
586163953Srrs	audit_tf = 0;
587163953Srrs	fir = 0;
588163953Srrs	/*
589163953Srrs	 * figure out how long a data chunk must be pending before we can
590163953Srrs	 * mark it ..
591163953Srrs	 */
592169378Srrs	(void)SCTP_GETTIME_TIMEVAL(&now);
593163953Srrs	/* get cur rto in micro-seconds */
594163953Srrs	cur_rtt = (((net->lastsa >> 2) + net->lastsv) >> 1);
595163953Srrs	cur_rtt *= 1000;
596170744Srrs	if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
597170744Srrs		sctp_log_fr(cur_rtt,
598170744Srrs		    stcb->asoc.peers_rwnd,
599170744Srrs		    window_probe,
600170744Srrs		    SCTP_FR_T3_MARK_TIME);
601170744Srrs		sctp_log_fr(net->flight_size,
602170744Srrs		    SCTP_OS_TIMER_PENDING(&net->fr_timer.timer),
603170744Srrs		    SCTP_OS_TIMER_ACTIVE(&net->fr_timer.timer),
604170744Srrs		    SCTP_FR_CWND_REPORT);
605170744Srrs		sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT);
606170744Srrs	}
607163953Srrs	tv.tv_sec = cur_rtt / 1000000;
608163953Srrs	tv.tv_usec = cur_rtt % 1000000;
609163953Srrs	min_wait = now;
610163953Srrs	timevalsub(&min_wait, &tv);
611163953Srrs	if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
612163953Srrs		/*
613163953Srrs		 * if we hit here, we don't have enough seconds on the clock
614163953Srrs		 * to account for the RTO. We just let the lower seconds be
615163953Srrs		 * the bounds and don't worry about it. This may mean we
616163953Srrs		 * will mark a lot more than we should.
617163953Srrs		 */
618163953Srrs		min_wait.tv_sec = min_wait.tv_usec = 0;
619163953Srrs	}
620170744Srrs	if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
621170744Srrs		sctp_log_fr(cur_rtt, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME);
622170744Srrs		sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME);
623170744Srrs	}
624163953Srrs	/*
625163953Srrs	 * Our rwnd will be incorrect here since we are not adding back the
626163953Srrs	 * cnt * mbuf but we will fix that down below.
627163953Srrs	 */
628163953Srrs	orig_flight = net->flight_size;
629168709Srrs	orig_tf = stcb->asoc.total_flight;
630168709Srrs
631163953Srrs	net->fast_retran_ip = 0;
632163953Srrs	/* Now on to each chunk */
633163953Srrs	num_mk = cnt_mk = 0;
634163953Srrs	tsnfirst = tsnlast = 0;
635163953Srrs	chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
636163953Srrs	for (; chk != NULL; chk = tp2) {
637163953Srrs		tp2 = TAILQ_NEXT(chk, sctp_next);
638163953Srrs		if ((compare_with_wrap(stcb->asoc.last_acked_seq,
639163953Srrs		    chk->rec.data.TSN_seq,
640163953Srrs		    MAX_TSN)) ||
641163953Srrs		    (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
642163953Srrs			/* Strange case our list got out of order? */
643169420Srrs			SCTP_PRINTF("Our list is out of order?\n");
644163953Srrs			panic("Out of order list");
645163953Srrs		}
646163953Srrs		if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) {
647163953Srrs			/*
648163953Srrs			 * found one to mark: If it is less than
649163953Srrs			 * DATAGRAM_ACKED it MUST not be a skipped or marked
650163953Srrs			 * TSN but instead one that is either already set
651163953Srrs			 * for retransmission OR one that needs
652163953Srrs			 * retransmission.
653163953Srrs			 */
654163953Srrs
655163953Srrs			/* validate its been outstanding long enough */
656170744Srrs			if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
657170744Srrs				sctp_log_fr(chk->rec.data.TSN_seq,
658170744Srrs				    chk->sent_rcv_time.tv_sec,
659170744Srrs				    chk->sent_rcv_time.tv_usec,
660170744Srrs				    SCTP_FR_T3_MARK_TIME);
661170744Srrs			}
662163953Srrs			if ((chk->sent_rcv_time.tv_sec > min_wait.tv_sec) && (window_probe == 0)) {
663163953Srrs				/*
664163953Srrs				 * we have reached a chunk that was sent
665163953Srrs				 * some seconds past our min.. forget it we
666163953Srrs				 * will find no more to send.
667163953Srrs				 */
668170744Srrs				if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
669170744Srrs					sctp_log_fr(0,
670170744Srrs					    chk->sent_rcv_time.tv_sec,
671170744Srrs					    chk->sent_rcv_time.tv_usec,
672170744Srrs					    SCTP_FR_T3_STOPPED);
673170744Srrs				}
674163953Srrs				continue;
675163953Srrs			} else if ((chk->sent_rcv_time.tv_sec == min_wait.tv_sec) &&
676163953Srrs			    (window_probe == 0)) {
677163953Srrs				/*
678163953Srrs				 * we must look at the micro seconds to
679163953Srrs				 * know.
680163953Srrs				 */
681163953Srrs				if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) {
682163953Srrs					/*
683163953Srrs					 * ok it was sent after our boundary
684163953Srrs					 * time.
685163953Srrs					 */
686170744Srrs					if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
687170744Srrs						sctp_log_fr(0,
688170744Srrs						    chk->sent_rcv_time.tv_sec,
689170744Srrs						    chk->sent_rcv_time.tv_usec,
690170744Srrs						    SCTP_FR_T3_STOPPED);
691170744Srrs					}
692163953Srrs					continue;
693163953Srrs				}
694163953Srrs			}
695163953Srrs			if (PR_SCTP_TTL_ENABLED(chk->flags)) {
696163953Srrs				/* Is it expired? */
697163953Srrs				if ((now.tv_sec > chk->rec.data.timetodrop.tv_sec) ||
698163953Srrs				    ((chk->rec.data.timetodrop.tv_sec == now.tv_sec) &&
699163953Srrs				    (now.tv_usec > chk->rec.data.timetodrop.tv_usec))) {
700163953Srrs					/* Yes so drop it */
701163953Srrs					if (chk->data) {
702169420Srrs						(void)sctp_release_pr_sctp_chunk(stcb,
703163953Srrs						    chk,
704163953Srrs						    (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
705172090Srrs						    &stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED);
706163953Srrs					}
707163953Srrs				}
708163953Srrs				continue;
709163953Srrs			}
710163953Srrs			if (PR_SCTP_RTX_ENABLED(chk->flags)) {
711163953Srrs				/* Has it been retransmitted tv_sec times? */
712163953Srrs				if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) {
713163953Srrs					if (chk->data) {
714169420Srrs						(void)sctp_release_pr_sctp_chunk(stcb,
715163953Srrs						    chk,
716163953Srrs						    (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
717172090Srrs						    &stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED);
718163953Srrs					}
719163953Srrs				}
720163953Srrs				continue;
721163953Srrs			}
722168709Srrs			if (chk->sent < SCTP_DATAGRAM_RESEND) {
723163953Srrs				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
724163953Srrs				num_mk++;
725163953Srrs				if (fir == 0) {
726163953Srrs					fir = 1;
727163953Srrs					tsnfirst = chk->rec.data.TSN_seq;
728163953Srrs				}
729163953Srrs				tsnlast = chk->rec.data.TSN_seq;
730170744Srrs				if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
731170744Srrs					sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
732170744Srrs					    0, SCTP_FR_T3_MARKED);
733170744Srrs				}
734168709Srrs				if (chk->rec.data.chunk_was_revoked) {
735168709Srrs					/* deflate the cwnd */
736168709Srrs					chk->whoTo->cwnd -= chk->book_size;
737168709Srrs					chk->rec.data.chunk_was_revoked = 0;
738168709Srrs				}
739168709Srrs				net->marked_retrans++;
740168709Srrs				stcb->asoc.marked_retrans++;
741170744Srrs				if (sctp_logging_level & SCTP_FLIGHT_LOGGING_ENABLE) {
742170744Srrs					sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO,
743170744Srrs					    chk->whoTo->flight_size,
744170744Srrs					    chk->book_size,
745170744Srrs					    (uintptr_t) chk->whoTo,
746170744Srrs					    chk->rec.data.TSN_seq);
747170744Srrs				}
748168709Srrs				sctp_flight_size_decrease(chk);
749168709Srrs				sctp_total_flight_decrease(stcb, chk);
750168709Srrs				stcb->asoc.peers_rwnd += chk->send_size;
751168709Srrs				stcb->asoc.peers_rwnd += sctp_peer_chunk_oh;
752163953Srrs			}
753163953Srrs			chk->sent = SCTP_DATAGRAM_RESEND;
754163953Srrs			SCTP_STAT_INCR(sctps_markedretrans);
755165220Srrs
756163953Srrs			/* reset the TSN for striking and other FR stuff */
757163953Srrs			chk->rec.data.doing_fast_retransmit = 0;
758163953Srrs			/* Clear any time so NO RTT is being done */
759163953Srrs			chk->do_rtt = 0;
760163953Srrs			if (alt != net) {
761163953Srrs				sctp_free_remote_addr(chk->whoTo);
762163953Srrs				chk->no_fr_allowed = 1;
763163953Srrs				chk->whoTo = alt;
764163953Srrs				atomic_add_int(&alt->ref_count, 1);
765163953Srrs			} else {
766163953Srrs				chk->no_fr_allowed = 0;
767163953Srrs				if (TAILQ_EMPTY(&stcb->asoc.send_queue)) {
768163953Srrs					chk->rec.data.fast_retran_tsn = stcb->asoc.sending_seq;
769163953Srrs				} else {
770163953Srrs					chk->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq;
771163953Srrs				}
772163953Srrs			}
773170181Srrs			/*
774170181Srrs			 * CMT: Do not allow FRs on retransmitted TSNs.
775170181Srrs			 */
776163953Srrs			if (sctp_cmt_on_off == 1) {
777163953Srrs				chk->no_fr_allowed = 1;
778163953Srrs			}
779163953Srrs		} else if (chk->sent == SCTP_DATAGRAM_ACKED) {
780163953Srrs			/* remember highest acked one */
781163953Srrs			could_be_sent = chk;
782163953Srrs		}
783163953Srrs		if (chk->sent == SCTP_DATAGRAM_RESEND) {
784163953Srrs			cnt_mk++;
785163953Srrs		}
786163953Srrs	}
787168709Srrs	if ((orig_flight - net->flight_size) != (orig_tf - stcb->asoc.total_flight)) {
788168709Srrs		/* we did not subtract the same things? */
789168709Srrs		audit_tf = 1;
790168709Srrs	}
791170744Srrs	if (sctp_logging_level & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
792170744Srrs		sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
793170744Srrs	}
794163953Srrs#ifdef SCTP_DEBUG
795169420Srrs	if (num_mk) {
796169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n",
797169420Srrs		    tsnlast);
798169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%ld\n",
799169420Srrs		    num_mk, (u_long)stcb->asoc.peers_rwnd);
800169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n",
801169420Srrs		    tsnlast);
802169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%d\n",
803169420Srrs		    num_mk,
804169420Srrs		    (int)stcb->asoc.peers_rwnd);
805163953Srrs	}
806163953Srrs#endif
807163953Srrs	*num_marked = num_mk;
808163953Srrs	if ((stcb->asoc.sent_queue_retran_cnt == 0) && (could_be_sent)) {
809163953Srrs		/* fix it so we retransmit the highest acked anyway */
810163953Srrs		sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
811163953Srrs		cnt_mk++;
812163953Srrs		could_be_sent->sent = SCTP_DATAGRAM_RESEND;
813163953Srrs	}
814163953Srrs	if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) {
815165220Srrs#ifdef INVARIANTS
816171477Srrs		SCTP_PRINTF("Local Audit says there are %d for retran asoc cnt:%d we marked:%d this time\n",
817171477Srrs		    cnt_mk, stcb->asoc.sent_queue_retran_cnt, num_mk);
818163953Srrs#endif
819163953Srrs#ifndef SCTP_AUDITING_ENABLED
820163953Srrs		stcb->asoc.sent_queue_retran_cnt = cnt_mk;
821163953Srrs#endif
822163953Srrs	}
823163953Srrs	/* Now check for a ECN Echo that may be stranded */
824163953Srrs	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
825163953Srrs		if ((chk->whoTo == net) &&
826163953Srrs		    (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) {
827163953Srrs			sctp_free_remote_addr(chk->whoTo);
828163953Srrs			chk->whoTo = alt;
829163953Srrs			if (chk->sent != SCTP_DATAGRAM_RESEND) {
830163953Srrs				chk->sent = SCTP_DATAGRAM_RESEND;
831163953Srrs				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
832163953Srrs			}
833163953Srrs			atomic_add_int(&alt->ref_count, 1);
834163953Srrs		}
835163953Srrs	}
836163953Srrs	if (audit_tf) {
837169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER4,
838169420Srrs		    "Audit total flight due to negative value net:%p\n",
839169420Srrs		    net);
840163953Srrs		stcb->asoc.total_flight = 0;
841163953Srrs		stcb->asoc.total_flight_count = 0;
842163953Srrs		/* Clear all networks flight size */
843163953Srrs		TAILQ_FOREACH(lnets, &stcb->asoc.nets, sctp_next) {
844163953Srrs			lnets->flight_size = 0;
845169420Srrs			SCTPDBG(SCTP_DEBUG_TIMER4,
846169420Srrs			    "Net:%p c-f cwnd:%d ssthresh:%d\n",
847169420Srrs			    lnets, lnets->cwnd, lnets->ssthresh);
848163953Srrs		}
849163953Srrs		TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
850163953Srrs			if (chk->sent < SCTP_DATAGRAM_RESEND) {
851170744Srrs				if (sctp_logging_level & SCTP_FLIGHT_LOGGING_ENABLE) {
852170744Srrs					sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
853170744Srrs					    chk->whoTo->flight_size,
854170744Srrs					    chk->book_size,
855170744Srrs					    (uintptr_t) chk->whoTo,
856170744Srrs					    chk->rec.data.TSN_seq);
857170744Srrs				}
858168709Srrs				sctp_flight_size_increase(chk);
859168709Srrs				sctp_total_flight_increase(stcb, chk);
860163953Srrs			}
861163953Srrs		}
862163953Srrs	}
863163953Srrs	/*
864163953Srrs	 * Setup the ecn nonce re-sync point. We do this since
865163953Srrs	 * retranmissions are NOT setup for ECN. This means that do to
866163953Srrs	 * Karn's rule, we don't know the total of the peers ecn bits.
867163953Srrs	 */
868163953Srrs	chk = TAILQ_FIRST(&stcb->asoc.send_queue);
869163953Srrs	if (chk == NULL) {
870163953Srrs		stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
871163953Srrs	} else {
872163953Srrs		stcb->asoc.nonce_resync_tsn = chk->rec.data.TSN_seq;
873163953Srrs	}
874163953Srrs	stcb->asoc.nonce_wait_for_ecne = 0;
875163953Srrs	stcb->asoc.nonce_sum_check = 0;
876163953Srrs	/* We return 1 if we only have a window probe outstanding */
877163953Srrs	return (0);
878163953Srrs}
879163953Srrs
880163953Srrsstatic void
881163953Srrssctp_move_all_chunks_to_alt(struct sctp_tcb *stcb,
882163953Srrs    struct sctp_nets *net,
883163953Srrs    struct sctp_nets *alt)
884163953Srrs{
885163953Srrs	struct sctp_association *asoc;
886163953Srrs	struct sctp_stream_out *outs;
887163953Srrs	struct sctp_tmit_chunk *chk;
888163953Srrs	struct sctp_stream_queue_pending *sp;
889163953Srrs
890163953Srrs	if (net == alt)
891163953Srrs		/* nothing to do */
892163953Srrs		return;
893163953Srrs
894163953Srrs	asoc = &stcb->asoc;
895163953Srrs
896163953Srrs	/*
897163953Srrs	 * now through all the streams checking for chunks sent to our bad
898163953Srrs	 * network.
899163953Srrs	 */
900163953Srrs	TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
901163953Srrs		/* now clean up any chunks here */
902163953Srrs		TAILQ_FOREACH(sp, &outs->outqueue, next) {
903163953Srrs			if (sp->net == net) {
904163953Srrs				sctp_free_remote_addr(sp->net);
905163953Srrs				sp->net = alt;
906163953Srrs				atomic_add_int(&alt->ref_count, 1);
907163953Srrs			}
908163953Srrs		}
909163953Srrs	}
910163953Srrs	/* Now check the pending queue */
911163953Srrs	TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
912163953Srrs		if (chk->whoTo == net) {
913163953Srrs			sctp_free_remote_addr(chk->whoTo);
914163953Srrs			chk->whoTo = alt;
915163953Srrs			atomic_add_int(&alt->ref_count, 1);
916163953Srrs		}
917163953Srrs	}
918163953Srrs
919163953Srrs}
920163953Srrs
921163953Srrsint
922163953Srrssctp_t3rxt_timer(struct sctp_inpcb *inp,
923163953Srrs    struct sctp_tcb *stcb,
924163953Srrs    struct sctp_nets *net)
925163953Srrs{
926163953Srrs	struct sctp_nets *alt;
927163953Srrs	int win_probe, num_mk;
928163953Srrs
929170744Srrs	if (sctp_logging_level & SCTP_FR_LOGGING_ENABLE) {
930170744Srrs		sctp_log_fr(0, 0, 0, SCTP_FR_T3_TIMEOUT);
931170744Srrs	}
932170744Srrs	if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
933163953Srrs		struct sctp_nets *lnet;
934163953Srrs
935163953Srrs		TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
936163953Srrs			if (net == lnet) {
937163953Srrs				sctp_log_cwnd(stcb, lnet, 1, SCTP_CWND_LOG_FROM_T3);
938163953Srrs			} else {
939163953Srrs				sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_LOG_FROM_T3);
940163953Srrs			}
941163953Srrs		}
942163953Srrs	}
943163953Srrs	/* Find an alternate and mark those for retransmission */
944163953Srrs	if ((stcb->asoc.peers_rwnd == 0) &&
945163953Srrs	    (stcb->asoc.total_flight < net->mtu)) {
946163953Srrs		SCTP_STAT_INCR(sctps_timowindowprobe);
947163953Srrs		win_probe = 1;
948163953Srrs	} else {
949163953Srrs		win_probe = 0;
950163953Srrs	}
951168709Srrs
952171440Srrs	/*
953171440Srrs	 * JRS 5/14/07 - If CMT PF is on and the destination if not already
954171440Srrs	 * in PF state, set the destination to PF state and store the
955171440Srrs	 * current time as the time that the destination was last active. In
956171440Srrs	 * addition, find an alternate destination with PF-based
957171440Srrs	 * find_alt_net().
958171440Srrs	 */
959171477Srrs	if (sctp_cmt_on_off && sctp_cmt_pf) {
960171440Srrs		if ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF) {
961171440Srrs			net->dest_state |= SCTP_ADDR_PF;
962171477Srrs			net->last_active = sctp_get_tick_count();
963171440Srrs			SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from active to PF.\n",
964171440Srrs			    net);
965171440Srrs		}
966171440Srrs		alt = sctp_find_alternate_net(stcb, net, 2);
967171440Srrs	} else if (sctp_cmt_on_off) {
968168709Srrs		/*
969168709Srrs		 * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being
970168709Srrs		 * used, then pick dest with largest ssthresh for any
971168709Srrs		 * retransmission.
972168709Srrs		 */
973168709Srrs		alt = net;
974168709Srrs		alt = sctp_find_alternate_net(stcb, alt, 1);
975168709Srrs		/*
976168709Srrs		 * CUCv2: If a different dest is picked for the
977168709Srrs		 * retransmission, then new (rtx-)pseudo_cumack needs to be
978168709Srrs		 * tracked for orig dest. Let CUCv2 track new (rtx-)
979168709Srrs		 * pseudo-cumack always.
980168709Srrs		 */
981168709Srrs		net->find_pseudo_cumack = 1;
982168709Srrs		net->find_rtx_pseudo_cumack = 1;
983168709Srrs	} else {		/* CMT is OFF */
984168709Srrs		alt = sctp_find_alternate_net(stcb, net, 0);
985168709Srrs	}
986168709Srrs
987169420Srrs	(void)sctp_mark_all_for_resend(stcb, net, alt, win_probe, &num_mk);
988163953Srrs	/* FR Loss recovery just ended with the T3. */
989163953Srrs	stcb->asoc.fast_retran_loss_recovery = 0;
990163953Srrs
991163953Srrs	/* CMT FR loss recovery ended with the T3 */
992163953Srrs	net->fast_retran_loss_recovery = 0;
993163953Srrs
994163953Srrs	/*
995163953Srrs	 * setup the sat loss recovery that prevents satellite cwnd advance.
996163953Srrs	 */
997163953Srrs	stcb->asoc.sat_t3_loss_recovery = 1;
998163953Srrs	stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
999163953Srrs
1000163953Srrs	/* Backoff the timer and cwnd */
1001163953Srrs	sctp_backoff_on_timeout(stcb, net, win_probe, num_mk);
1002163953Srrs	if (win_probe == 0) {
1003163953Srrs		/* We don't do normal threshold management on window probes */
1004163953Srrs		if (sctp_threshold_management(inp, stcb, net,
1005163953Srrs		    stcb->asoc.max_send_times)) {
1006163953Srrs			/* Association was destroyed */
1007163953Srrs			return (1);
1008163953Srrs		} else {
1009163953Srrs			if (net != stcb->asoc.primary_destination) {
1010163953Srrs				/* send a immediate HB if our RTO is stale */
1011163953Srrs				struct timeval now;
1012163953Srrs				unsigned int ms_goneby;
1013163953Srrs
1014169378Srrs				(void)SCTP_GETTIME_TIMEVAL(&now);
1015163953Srrs				if (net->last_sent_time.tv_sec) {
1016163953Srrs					ms_goneby = (now.tv_sec - net->last_sent_time.tv_sec) * 1000;
1017163953Srrs				} else {
1018163953Srrs					ms_goneby = 0;
1019163953Srrs				}
1020163953Srrs				if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
1021163953Srrs					/*
1022163953Srrs					 * no recent feed back in an RTO or
1023163953Srrs					 * more, request a RTT update
1024163953Srrs					 */
1025171440Srrs					if (sctp_send_hb(stcb, 1, net) < 0)
1026171440Srrs						return 1;
1027163953Srrs				}
1028163953Srrs			}
1029163953Srrs		}
1030163953Srrs	} else {
1031163953Srrs		/*
1032163953Srrs		 * For a window probe we don't penalize the net's but only
1033163953Srrs		 * the association. This may fail it if SACKs are not coming
1034163953Srrs		 * back. If sack's are coming with rwnd locked at 0, we will
1035163953Srrs		 * continue to hold things waiting for rwnd to raise
1036163953Srrs		 */
1037163953Srrs		if (sctp_threshold_management(inp, stcb, NULL,
1038163953Srrs		    stcb->asoc.max_send_times)) {
1039163953Srrs			/* Association was destroyed */
1040163953Srrs			return (1);
1041163953Srrs		}
1042163953Srrs	}
1043163953Srrs	if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
1044163953Srrs		/* Move all pending over too */
1045163953Srrs		sctp_move_all_chunks_to_alt(stcb, net, alt);
1046169352Srrs
1047169352Srrs		/*
1048169352Srrs		 * Get the address that failed, to force a new src address
1049169352Srrs		 * selecton and a route allocation.
1050169352Srrs		 */
1051169352Srrs		if (net->ro._s_addr) {
1052169352Srrs			sctp_free_ifa(net->ro._s_addr);
1053169352Srrs			net->ro._s_addr = NULL;
1054169352Srrs		}
1055169352Srrs		net->src_addr_selected = 0;
1056169352Srrs
1057169352Srrs		/* Force a route allocation too */
1058169352Srrs		if (net->ro.ro_rt) {
1059169352Srrs			RTFREE(net->ro.ro_rt);
1060169352Srrs			net->ro.ro_rt = NULL;
1061169352Srrs		}
1062163953Srrs		/* Was it our primary? */
1063163953Srrs		if ((stcb->asoc.primary_destination == net) && (alt != net)) {
1064163953Srrs			/*
1065163953Srrs			 * Yes, note it as such and find an alternate note:
1066163953Srrs			 * this means HB code must use this to resent the
1067163953Srrs			 * primary if it goes active AND if someone does a
1068163953Srrs			 * change-primary then this flag must be cleared
1069163953Srrs			 * from any net structures.
1070163953Srrs			 */
1071163953Srrs			if (sctp_set_primary_addr(stcb,
1072163953Srrs			    (struct sockaddr *)NULL,
1073163953Srrs			    alt) == 0) {
1074163953Srrs				net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
1075163953Srrs			}
1076163953Srrs		}
1077171477Srrs	} else if (sctp_cmt_on_off && sctp_cmt_pf && (net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) {
1078171440Srrs		/*
1079171440Srrs		 * JRS 5/14/07 - If the destination hasn't failed completely
1080171440Srrs		 * but is in PF state, a PF-heartbeat needs to be sent
1081171440Srrs		 * manually.
1082171440Srrs		 */
1083171440Srrs		if (sctp_send_hb(stcb, 1, net) < 0)
1084171440Srrs			return 1;
1085163953Srrs	}
1086163953Srrs	/*
1087163953Srrs	 * Special case for cookie-echo'ed case, we don't do output but must
1088163953Srrs	 * await the COOKIE-ACK before retransmission
1089163953Srrs	 */
1090163953Srrs	if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
1091163953Srrs		/*
1092163953Srrs		 * Here we just reset the timer and start again since we
1093163953Srrs		 * have not established the asoc
1094163953Srrs		 */
1095163953Srrs		sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
1096163953Srrs		return (0);
1097163953Srrs	}
1098163953Srrs	if (stcb->asoc.peer_supports_prsctp) {
1099163953Srrs		struct sctp_tmit_chunk *lchk;
1100163953Srrs
1101163953Srrs		lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
1102163953Srrs		/* C3. See if we need to send a Fwd-TSN */
1103163953Srrs		if (compare_with_wrap(stcb->asoc.advanced_peer_ack_point,
1104163953Srrs		    stcb->asoc.last_acked_seq, MAX_TSN)) {
1105163953Srrs			/*
1106163953Srrs			 * ISSUE with ECN, see FWD-TSN processing for notes
1107163953Srrs			 * on issues that will occur when the ECN NONCE
1108163953Srrs			 * stuff is put into SCTP for cross checking.
1109163953Srrs			 */
1110163953Srrs			send_forward_tsn(stcb, &stcb->asoc);
1111163953Srrs			if (lchk) {
1112163953Srrs				/* Assure a timer is up */
1113163953Srrs				sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, lchk->whoTo);
1114163953Srrs			}
1115163953Srrs		}
1116163953Srrs	}
1117170744Srrs	if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1118170744Srrs		sctp_log_cwnd(stcb, net, net->cwnd, SCTP_CWND_LOG_FROM_RTX);
1119170744Srrs	}
1120163953Srrs	return (0);
1121163953Srrs}
1122163953Srrs
1123163953Srrsint
1124163953Srrssctp_t1init_timer(struct sctp_inpcb *inp,
1125163953Srrs    struct sctp_tcb *stcb,
1126163953Srrs    struct sctp_nets *net)
1127163953Srrs{
1128163953Srrs	/* bump the thresholds */
1129163953Srrs	if (stcb->asoc.delayed_connection) {
1130163953Srrs		/*
1131163953Srrs		 * special hook for delayed connection. The library did NOT
1132163953Srrs		 * complete the rest of its sends.
1133163953Srrs		 */
1134163953Srrs		stcb->asoc.delayed_connection = 0;
1135172090Srrs		sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED);
1136163953Srrs		return (0);
1137163953Srrs	}
1138163953Srrs	if (SCTP_GET_STATE((&stcb->asoc)) != SCTP_STATE_COOKIE_WAIT) {
1139163953Srrs		return (0);
1140163953Srrs	}
1141163953Srrs	if (sctp_threshold_management(inp, stcb, net,
1142163953Srrs	    stcb->asoc.max_init_times)) {
1143163953Srrs		/* Association was destroyed */
1144163953Srrs		return (1);
1145163953Srrs	}
1146163953Srrs	stcb->asoc.dropped_special_cnt = 0;
1147163953Srrs	sctp_backoff_on_timeout(stcb, stcb->asoc.primary_destination, 1, 0);
1148163953Srrs	if (stcb->asoc.initial_init_rto_max < net->RTO) {
1149163953Srrs		net->RTO = stcb->asoc.initial_init_rto_max;
1150163953Srrs	}
1151163953Srrs	if (stcb->asoc.numnets > 1) {
1152163953Srrs		/* If we have more than one addr use it */
1153163953Srrs		struct sctp_nets *alt;
1154163953Srrs
1155163953Srrs		alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination, 0);
1156163953Srrs		if ((alt != NULL) && (alt != stcb->asoc.primary_destination)) {
1157163953Srrs			sctp_move_all_chunks_to_alt(stcb, stcb->asoc.primary_destination, alt);
1158163953Srrs			stcb->asoc.primary_destination = alt;
1159163953Srrs		}
1160163953Srrs	}
1161163953Srrs	/* Send out a new init */
1162172090Srrs	sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED);
1163163953Srrs	return (0);
1164163953Srrs}
1165163953Srrs
1166163953Srrs/*
1167163953Srrs * For cookie and asconf we actually need to find and mark for resend, then
1168163953Srrs * increment the resend counter (after all the threshold management stuff of
1169163953Srrs * course).
1170163953Srrs */
1171163953Srrsint
1172163953Srrssctp_cookie_timer(struct sctp_inpcb *inp,
1173163953Srrs    struct sctp_tcb *stcb,
1174163953Srrs    struct sctp_nets *net)
1175163953Srrs{
1176163953Srrs	struct sctp_nets *alt;
1177163953Srrs	struct sctp_tmit_chunk *cookie;
1178163953Srrs
1179163953Srrs	/* first before all else we must find the cookie */
1180163953Srrs	TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, sctp_next) {
1181163953Srrs		if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
1182163953Srrs			break;
1183163953Srrs		}
1184163953Srrs	}
1185163953Srrs	if (cookie == NULL) {
1186163953Srrs		if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
1187163953Srrs			/* FOOBAR! */
1188163953Srrs			struct mbuf *oper;
1189163953Srrs
1190163953Srrs			oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
1191163953Srrs			    0, M_DONTWAIT, 1, MT_DATA);
1192163953Srrs			if (oper) {
1193163953Srrs				struct sctp_paramhdr *ph;
1194163953Srrs				uint32_t *ippp;
1195163953Srrs
1196165647Srrs				SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
1197163953Srrs				    sizeof(uint32_t);
1198163953Srrs				ph = mtod(oper, struct sctp_paramhdr *);
1199163953Srrs				ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
1200165647Srrs				ph->param_length = htons(SCTP_BUF_LEN(oper));
1201163953Srrs				ippp = (uint32_t *) (ph + 1);
1202171440Srrs				*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
1203163953Srrs			}
1204171440Srrs			inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4;
1205163953Srrs			sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR,
1206172090Srrs			    oper, SCTP_SO_NOT_LOCKED);
1207163953Srrs		} else {
1208165220Srrs#ifdef INVARIANTS
1209163953Srrs			panic("Cookie timer expires in wrong state?");
1210163953Srrs#else
1211169420Srrs			SCTP_PRINTF("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(&stcb->asoc));
1212163953Srrs			return (0);
1213163953Srrs#endif
1214163953Srrs		}
1215163953Srrs		return (0);
1216163953Srrs	}
1217163953Srrs	/* Ok we found the cookie, threshold management next */
1218163953Srrs	if (sctp_threshold_management(inp, stcb, cookie->whoTo,
1219163953Srrs	    stcb->asoc.max_init_times)) {
1220163953Srrs		/* Assoc is over */
1221163953Srrs		return (1);
1222163953Srrs	}
1223163953Srrs	/*
1224163953Srrs	 * cleared theshold management now lets backoff the address & select
1225163953Srrs	 * an alternate
1226163953Srrs	 */
1227163953Srrs	stcb->asoc.dropped_special_cnt = 0;
1228163953Srrs	sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0);
1229163953Srrs	alt = sctp_find_alternate_net(stcb, cookie->whoTo, 0);
1230163953Srrs	if (alt != cookie->whoTo) {
1231163953Srrs		sctp_free_remote_addr(cookie->whoTo);
1232163953Srrs		cookie->whoTo = alt;
1233163953Srrs		atomic_add_int(&alt->ref_count, 1);
1234163953Srrs	}
1235163953Srrs	/* Now mark the retran info */
1236163953Srrs	if (cookie->sent != SCTP_DATAGRAM_RESEND) {
1237163953Srrs		sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1238163953Srrs	}
1239163953Srrs	cookie->sent = SCTP_DATAGRAM_RESEND;
1240163953Srrs	/*
1241163953Srrs	 * Now call the output routine to kick out the cookie again, Note we
1242163953Srrs	 * don't mark any chunks for retran so that FR will need to kick in
1243163953Srrs	 * to move these (or a send timer).
1244163953Srrs	 */
1245163953Srrs	return (0);
1246163953Srrs}
1247163953Srrs
1248163953Srrsint
1249163953Srrssctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1250163953Srrs    struct sctp_nets *net)
1251163953Srrs{
1252163953Srrs	struct sctp_nets *alt;
1253163953Srrs	struct sctp_tmit_chunk *strrst = NULL, *chk = NULL;
1254163953Srrs
1255163953Srrs	if (stcb->asoc.stream_reset_outstanding == 0) {
1256163953Srrs		return (0);
1257163953Srrs	}
1258163953Srrs	/* find the existing STRRESET, we use the seq number we sent out on */
1259169420Srrs	(void)sctp_find_stream_reset(stcb, stcb->asoc.str_reset_seq_out, &strrst);
1260163953Srrs	if (strrst == NULL) {
1261163953Srrs		return (0);
1262163953Srrs	}
1263163953Srrs	/* do threshold management */
1264163953Srrs	if (sctp_threshold_management(inp, stcb, strrst->whoTo,
1265163953Srrs	    stcb->asoc.max_send_times)) {
1266163953Srrs		/* Assoc is over */
1267163953Srrs		return (1);
1268163953Srrs	}
1269163953Srrs	/*
1270163953Srrs	 * cleared theshold management now lets backoff the address & select
1271163953Srrs	 * an alternate
1272163953Srrs	 */
1273163953Srrs	sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0);
1274163953Srrs	alt = sctp_find_alternate_net(stcb, strrst->whoTo, 0);
1275163953Srrs	sctp_free_remote_addr(strrst->whoTo);
1276163953Srrs	strrst->whoTo = alt;
1277163953Srrs	atomic_add_int(&alt->ref_count, 1);
1278163953Srrs
1279163953Srrs	/* See if a ECN Echo is also stranded */
1280163953Srrs	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
1281163953Srrs		if ((chk->whoTo == net) &&
1282163953Srrs		    (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) {
1283163953Srrs			sctp_free_remote_addr(chk->whoTo);
1284163953Srrs			if (chk->sent != SCTP_DATAGRAM_RESEND) {
1285163953Srrs				chk->sent = SCTP_DATAGRAM_RESEND;
1286163953Srrs				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1287163953Srrs			}
1288163953Srrs			chk->whoTo = alt;
1289163953Srrs			atomic_add_int(&alt->ref_count, 1);
1290163953Srrs		}
1291163953Srrs	}
1292163953Srrs	if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
1293163953Srrs		/*
1294163953Srrs		 * If the address went un-reachable, we need to move to
1295163953Srrs		 * alternates for ALL chk's in queue
1296163953Srrs		 */
1297163953Srrs		sctp_move_all_chunks_to_alt(stcb, net, alt);
1298163953Srrs	}
1299163953Srrs	/* mark the retran info */
1300163953Srrs	if (strrst->sent != SCTP_DATAGRAM_RESEND)
1301163953Srrs		sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1302163953Srrs	strrst->sent = SCTP_DATAGRAM_RESEND;
1303163953Srrs
1304163953Srrs	/* restart the timer */
1305163953Srrs	sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, inp, stcb, strrst->whoTo);
1306163953Srrs	return (0);
1307163953Srrs}
1308163953Srrs
1309163953Srrsint
1310163953Srrssctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1311163953Srrs    struct sctp_nets *net)
1312163953Srrs{
1313163953Srrs	struct sctp_nets *alt;
1314163953Srrs	struct sctp_tmit_chunk *asconf, *chk;
1315163953Srrs
1316171572Srrs	/* is this a first send, or a retransmission? */
1317163953Srrs	if (stcb->asoc.asconf_sent == 0) {
1318163953Srrs		/* compose a new ASCONF chunk and send it */
1319163953Srrs		sctp_send_asconf(stcb, net);
1320163953Srrs	} else {
1321171572Srrs		/*
1322171572Srrs		 * Retransmission of the existing ASCONF is needed
1323171572Srrs		 */
1324163953Srrs
1325163953Srrs		/* find the existing ASCONF */
1326163953Srrs		TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
1327163953Srrs		    sctp_next) {
1328163953Srrs			if (asconf->rec.chunk_id.id == SCTP_ASCONF) {
1329163953Srrs				break;
1330163953Srrs			}
1331163953Srrs		}
1332163953Srrs		if (asconf == NULL) {
1333163953Srrs			return (0);
1334163953Srrs		}
1335163953Srrs		/* do threshold management */
1336163953Srrs		if (sctp_threshold_management(inp, stcb, asconf->whoTo,
1337163953Srrs		    stcb->asoc.max_send_times)) {
1338163953Srrs			/* Assoc is over */
1339163953Srrs			return (1);
1340163953Srrs		}
1341163953Srrs		if (asconf->snd_count > stcb->asoc.max_send_times) {
1342163953Srrs			/*
1343171572Srrs			 * Something is rotten: our peer is not responding
1344171572Srrs			 * to ASCONFs but apparently is to other chunks.
1345171572Srrs			 * i.e. it is not properly handling the chunk type
1346171572Srrs			 * upper bits. Mark this peer as ASCONF incapable
1347171572Srrs			 * and cleanup.
1348163953Srrs			 */
1349169420Srrs			SCTPDBG(SCTP_DEBUG_TIMER1, "asconf_timer: Peer has not responded to our repeated ASCONFs\n");
1350163953Srrs			sctp_asconf_cleanup(stcb, net);
1351163953Srrs			return (0);
1352163953Srrs		}
1353163953Srrs		/*
1354171572Srrs		 * cleared threshold management, so now backoff the net and
1355171572Srrs		 * select an alternate
1356163953Srrs		 */
1357163953Srrs		sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0);
1358163953Srrs		alt = sctp_find_alternate_net(stcb, asconf->whoTo, 0);
1359163953Srrs		sctp_free_remote_addr(asconf->whoTo);
1360163953Srrs		asconf->whoTo = alt;
1361163953Srrs		atomic_add_int(&alt->ref_count, 1);
1362163953Srrs
1363171572Srrs		/* See if an ECN Echo is also stranded */
1364163953Srrs		TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
1365163953Srrs			if ((chk->whoTo == net) &&
1366163953Srrs			    (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) {
1367163953Srrs				sctp_free_remote_addr(chk->whoTo);
1368163953Srrs				chk->whoTo = alt;
1369163953Srrs				if (chk->sent != SCTP_DATAGRAM_RESEND) {
1370163953Srrs					chk->sent = SCTP_DATAGRAM_RESEND;
1371163953Srrs					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1372163953Srrs				}
1373163953Srrs				atomic_add_int(&alt->ref_count, 1);
1374163953Srrs			}
1375163953Srrs		}
1376163953Srrs		if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
1377163953Srrs			/*
1378163953Srrs			 * If the address went un-reachable, we need to move
1379171572Srrs			 * to the alternate for ALL chunks in queue
1380163953Srrs			 */
1381163953Srrs			sctp_move_all_chunks_to_alt(stcb, net, alt);
1382163953Srrs		}
1383163953Srrs		/* mark the retran info */
1384163953Srrs		if (asconf->sent != SCTP_DATAGRAM_RESEND)
1385163953Srrs			sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1386163953Srrs		asconf->sent = SCTP_DATAGRAM_RESEND;
1387163953Srrs	}
1388163953Srrs	return (0);
1389163953Srrs}
1390163953Srrs
1391172091Srrs/* Mobility adaptation */
1392172156Srrsvoid
1393172091Srrssctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1394172091Srrs    struct sctp_nets *net)
1395172091Srrs{
1396172091Srrs	if (stcb->asoc.deleted_primary == NULL) {
1397172091Srrs		SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n");
1398172091Srrs		sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
1399172156Srrs		return;
1400172091Srrs	}
1401172091Srrs	SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: finished to keep deleted primary ");
1402172091Srrs	SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
1403172091Srrs	sctp_free_remote_addr(stcb->asoc.deleted_primary);
1404172091Srrs	stcb->asoc.deleted_primary = NULL;
1405172091Srrs	sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
1406172156Srrs	return;
1407172091Srrs}
1408172091Srrs
1409163953Srrs/*
1410163953Srrs * For the shutdown and shutdown-ack, we do not keep one around on the
1411163953Srrs * control queue. This means we must generate a new one and call the general
1412163953Srrs * chunk output routine, AFTER having done threshold management.
1413163953Srrs */
1414163953Srrsint
1415163953Srrssctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1416163953Srrs    struct sctp_nets *net)
1417163953Srrs{
1418163953Srrs	struct sctp_nets *alt;
1419163953Srrs
1420163953Srrs	/* first threshold managment */
1421163953Srrs	if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
1422163953Srrs		/* Assoc is over */
1423163953Srrs		return (1);
1424163953Srrs	}
1425163953Srrs	/* second select an alternative */
1426163953Srrs	alt = sctp_find_alternate_net(stcb, net, 0);
1427163953Srrs
1428163953Srrs	/* third generate a shutdown into the queue for out net */
1429163953Srrs	if (alt) {
1430163953Srrs		sctp_send_shutdown(stcb, alt);
1431163953Srrs	} else {
1432163953Srrs		/*
1433163953Srrs		 * if alt is NULL, there is no dest to send to??
1434163953Srrs		 */
1435163953Srrs		return (0);
1436163953Srrs	}
1437163953Srrs	/* fourth restart timer */
1438163953Srrs	sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt);
1439163953Srrs	return (0);
1440163953Srrs}
1441163953Srrs
1442163953Srrsint
1443163953Srrssctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1444163953Srrs    struct sctp_nets *net)
1445163953Srrs{
1446163953Srrs	struct sctp_nets *alt;
1447163953Srrs
1448163953Srrs	/* first threshold managment */
1449163953Srrs	if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
1450163953Srrs		/* Assoc is over */
1451163953Srrs		return (1);
1452163953Srrs	}
1453163953Srrs	/* second select an alternative */
1454163953Srrs	alt = sctp_find_alternate_net(stcb, net, 0);
1455163953Srrs
1456163953Srrs	/* third generate a shutdown into the queue for out net */
1457163953Srrs	sctp_send_shutdown_ack(stcb, alt);
1458163953Srrs
1459163953Srrs	/* fourth restart timer */
1460163953Srrs	sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt);
1461163953Srrs	return (0);
1462163953Srrs}
1463163953Srrs
1464163953Srrsstatic void
1465163953Srrssctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
1466163953Srrs    struct sctp_tcb *stcb)
1467163953Srrs{
1468163953Srrs	struct sctp_stream_out *outs;
1469163953Srrs	struct sctp_stream_queue_pending *sp;
1470163953Srrs	unsigned int chks_in_queue = 0;
1471163953Srrs	int being_filled = 0;
1472163953Srrs
1473163953Srrs	/*
1474163953Srrs	 * This function is ONLY called when the send/sent queues are empty.
1475163953Srrs	 */
1476163953Srrs	if ((stcb == NULL) || (inp == NULL))
1477163953Srrs		return;
1478163953Srrs
1479163953Srrs	if (stcb->asoc.sent_queue_retran_cnt) {
1480169420Srrs		SCTP_PRINTF("Hmm, sent_queue_retran_cnt is non-zero %d\n",
1481163953Srrs		    stcb->asoc.sent_queue_retran_cnt);
1482163953Srrs		stcb->asoc.sent_queue_retran_cnt = 0;
1483163953Srrs	}
1484163953Srrs	SCTP_TCB_SEND_LOCK(stcb);
1485163953Srrs	if (TAILQ_EMPTY(&stcb->asoc.out_wheel)) {
1486163953Srrs		int i, cnt = 0;
1487163953Srrs
1488163953Srrs		/* Check to see if a spoke fell off the wheel */
1489163953Srrs		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
1490163953Srrs			if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
1491163953Srrs				sctp_insert_on_wheel(stcb, &stcb->asoc, &stcb->asoc.strmout[i], 1);
1492163953Srrs				cnt++;
1493163953Srrs			}
1494163953Srrs		}
1495163953Srrs		if (cnt) {
1496163953Srrs			/* yep, we lost a spoke or two */
1497169420Srrs			SCTP_PRINTF("Found an additional %d streams NOT on outwheel, corrected\n", cnt);
1498163953Srrs		} else {
1499163953Srrs			/* no spokes lost, */
1500163953Srrs			stcb->asoc.total_output_queue_size = 0;
1501163953Srrs		}
1502163953Srrs		SCTP_TCB_SEND_UNLOCK(stcb);
1503163953Srrs		return;
1504163953Srrs	}
1505163953Srrs	SCTP_TCB_SEND_UNLOCK(stcb);
1506163953Srrs	/* Check to see if some data queued, if so report it */
1507163953Srrs	TAILQ_FOREACH(outs, &stcb->asoc.out_wheel, next_spoke) {
1508163953Srrs		if (!TAILQ_EMPTY(&outs->outqueue)) {
1509163953Srrs			TAILQ_FOREACH(sp, &outs->outqueue, next) {
1510163953Srrs				if (sp->msg_is_complete)
1511163953Srrs					being_filled++;
1512163953Srrs				chks_in_queue++;
1513163953Srrs			}
1514163953Srrs		}
1515163953Srrs	}
1516163953Srrs	if (chks_in_queue != stcb->asoc.stream_queue_cnt) {
1517169420Srrs		SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n",
1518163953Srrs		    stcb->asoc.stream_queue_cnt, chks_in_queue);
1519163953Srrs	}
1520163953Srrs	if (chks_in_queue) {
1521163953Srrs		/* call the output queue function */
1522172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1523163953Srrs		if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
1524163953Srrs		    (TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
1525163953Srrs			/*
1526163953Srrs			 * Probably should go in and make it go back through
1527163953Srrs			 * and add fragments allowed
1528163953Srrs			 */
1529163953Srrs			if (being_filled == 0) {
1530169420Srrs				SCTP_PRINTF("Still nothing moved %d chunks are stuck\n",
1531163953Srrs				    chks_in_queue);
1532163953Srrs			}
1533163953Srrs		}
1534163953Srrs	} else {
1535169420Srrs		SCTP_PRINTF("Found no chunks on any queue tot:%lu\n",
1536163953Srrs		    (u_long)stcb->asoc.total_output_queue_size);
1537163953Srrs		stcb->asoc.total_output_queue_size = 0;
1538163953Srrs	}
1539163953Srrs}
1540163953Srrs
1541163953Srrsint
1542163953Srrssctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1543163953Srrs    struct sctp_nets *net, int cnt_of_unconf)
1544163953Srrs{
1545171440Srrs	int ret;
1546171440Srrs
1547163953Srrs	if (net) {
1548163953Srrs		if (net->hb_responded == 0) {
1549167598Srrs			if (net->ro._s_addr) {
1550167598Srrs				/*
1551167598Srrs				 * Invalidate the src address if we did not
1552167598Srrs				 * get a response last time.
1553167598Srrs				 */
1554167598Srrs				sctp_free_ifa(net->ro._s_addr);
1555167598Srrs				net->ro._s_addr = NULL;
1556167598Srrs				net->src_addr_selected = 0;
1557167598Srrs			}
1558163953Srrs			sctp_backoff_on_timeout(stcb, net, 1, 0);
1559163953Srrs		}
1560163953Srrs		/* Zero PBA, if it needs it */
1561163953Srrs		if (net->partial_bytes_acked) {
1562163953Srrs			net->partial_bytes_acked = 0;
1563163953Srrs		}
1564163953Srrs	}
1565163953Srrs	if ((stcb->asoc.total_output_queue_size > 0) &&
1566163953Srrs	    (TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
1567163953Srrs	    (TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
1568163953Srrs		sctp_audit_stream_queues_for_size(inp, stcb);
1569163953Srrs	}
1570163953Srrs	/* Send a new HB, this will do threshold managment, pick a new dest */
1571163953Srrs	if (cnt_of_unconf == 0) {
1572163953Srrs		if (sctp_send_hb(stcb, 0, NULL) < 0) {
1573163953Srrs			return (1);
1574163953Srrs		}
1575163953Srrs	} else {
1576163953Srrs		/*
1577163953Srrs		 * this will send out extra hb's up to maxburst if there are
1578163953Srrs		 * any unconfirmed addresses.
1579163953Srrs		 */
1580170056Srrs		uint32_t cnt_sent = 0;
1581163953Srrs
1582163953Srrs		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1583163953Srrs			if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
1584163953Srrs			    (net->dest_state & SCTP_ADDR_REACHABLE)) {
1585163953Srrs				cnt_sent++;
1586167598Srrs				if (net->hb_responded == 0) {
1587167598Srrs					/* Did we respond last time? */
1588167598Srrs					if (net->ro._s_addr) {
1589167598Srrs						sctp_free_ifa(net->ro._s_addr);
1590167598Srrs						net->ro._s_addr = NULL;
1591167598Srrs						net->src_addr_selected = 0;
1592167598Srrs					}
1593167598Srrs				}
1594171440Srrs				ret = sctp_send_hb(stcb, 1, net);
1595171440Srrs				if (ret < 0)
1596171440Srrs					return 1;
1597171440Srrs				else if (ret == 0) {
1598163953Srrs					break;
1599163953Srrs				}
1600167598Srrs				if (cnt_sent >= sctp_hb_maxburst)
1601163953Srrs					break;
1602163953Srrs			}
1603163953Srrs		}
1604163953Srrs	}
1605163953Srrs	return (0);
1606163953Srrs}
1607163953Srrs
1608163953Srrsint
1609163953Srrssctp_is_hb_timer_running(struct sctp_tcb *stcb)
1610163953Srrs{
1611165647Srrs	if (SCTP_OS_TIMER_PENDING(&stcb->asoc.hb_timer.timer)) {
1612163953Srrs		/* its running */
1613163953Srrs		return (1);
1614163953Srrs	} else {
1615163953Srrs		/* nope */
1616163953Srrs		return (0);
1617163953Srrs	}
1618163953Srrs}
1619163953Srrs
1620163953Srrsint
1621163953Srrssctp_is_sack_timer_running(struct sctp_tcb *stcb)
1622163953Srrs{
1623165647Srrs	if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
1624163953Srrs		/* its running */
1625163953Srrs		return (1);
1626163953Srrs	} else {
1627163953Srrs		/* nope */
1628163953Srrs		return (0);
1629163953Srrs	}
1630163953Srrs}
1631163953Srrs
1632163953Srrs#define SCTP_NUMBER_OF_MTU_SIZES 18
1633163953Srrsstatic uint32_t mtu_sizes[] = {
1634163953Srrs	68,
1635163953Srrs	296,
1636163953Srrs	508,
1637163953Srrs	512,
1638163953Srrs	544,
1639163953Srrs	576,
1640163953Srrs	1006,
1641163953Srrs	1492,
1642163953Srrs	1500,
1643163953Srrs	1536,
1644163953Srrs	2002,
1645163953Srrs	2048,
1646163953Srrs	4352,
1647163953Srrs	4464,
1648163953Srrs	8166,
1649163953Srrs	17914,
1650163953Srrs	32000,
1651163953Srrs	65535
1652163953Srrs};
1653163953Srrs
1654163953Srrs
1655163953Srrsstatic uint32_t
1656163953Srrssctp_getnext_mtu(struct sctp_inpcb *inp, uint32_t cur_mtu)
1657163953Srrs{
1658163953Srrs	/* select another MTU that is just bigger than this one */
1659163953Srrs	int i;
1660163953Srrs
1661163953Srrs	for (i = 0; i < SCTP_NUMBER_OF_MTU_SIZES; i++) {
1662163953Srrs		if (cur_mtu < mtu_sizes[i]) {
1663163953Srrs			/* no max_mtu is bigger than this one */
1664163953Srrs			return (mtu_sizes[i]);
1665163953Srrs		}
1666163953Srrs	}
1667163953Srrs	/* here return the highest allowable */
1668163953Srrs	return (cur_mtu);
1669163953Srrs}
1670163953Srrs
1671163953Srrs
1672163953Srrsvoid
1673163953Srrssctp_pathmtu_timer(struct sctp_inpcb *inp,
1674163953Srrs    struct sctp_tcb *stcb,
1675163953Srrs    struct sctp_nets *net)
1676163953Srrs{
1677163953Srrs	uint32_t next_mtu;
1678163953Srrs
1679163953Srrs	/* restart the timer in any case */
1680163953Srrs	next_mtu = sctp_getnext_mtu(inp, net->mtu);
1681163953Srrs	if (next_mtu <= net->mtu) {
1682163953Srrs		/* nothing to do */
1683163953Srrs		return;
1684169352Srrs	} {
1685169352Srrs		uint32_t mtu;
1686169352Srrs
1687169352Srrs		if ((net->src_addr_selected == 0) ||
1688169352Srrs		    (net->ro._s_addr == NULL) ||
1689169352Srrs		    (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) {
1690169420Srrs			if ((net->ro._s_addr != NULL) && (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) {
1691169352Srrs				sctp_free_ifa(net->ro._s_addr);
1692169352Srrs				net->ro._s_addr = NULL;
1693169352Srrs				net->src_addr_selected = 0;
1694169420Srrs			} else if (net->ro._s_addr == NULL) {
1695169420Srrs				net->ro._s_addr = sctp_source_address_selection(inp,
1696169420Srrs				    stcb,
1697169420Srrs				    (sctp_route_t *) & net->ro,
1698169420Srrs				    net, 0, stcb->asoc.vrf_id);
1699169352Srrs			}
1700169352Srrs			if (net->ro._s_addr)
1701169352Srrs				net->src_addr_selected = 1;
1702169352Srrs		}
1703169352Srrs		if (net->ro._s_addr) {
1704169352Srrs			mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt);
1705169352Srrs			if (mtu > next_mtu) {
1706163953Srrs				net->mtu = next_mtu;
1707163953Srrs			}
1708163953Srrs		}
1709163953Srrs	}
1710163953Srrs	/* restart the timer */
1711163953Srrs	sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
1712163953Srrs}
1713163953Srrs
1714163953Srrsvoid
1715163953Srrssctp_autoclose_timer(struct sctp_inpcb *inp,
1716163953Srrs    struct sctp_tcb *stcb,
1717163953Srrs    struct sctp_nets *net)
1718163953Srrs{
1719163953Srrs	struct timeval tn, *tim_touse;
1720163953Srrs	struct sctp_association *asoc;
1721163953Srrs	int ticks_gone_by;
1722163953Srrs
1723169378Srrs	(void)SCTP_GETTIME_TIMEVAL(&tn);
1724163953Srrs	if (stcb->asoc.sctp_autoclose_ticks &&
1725163953Srrs	    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
1726163953Srrs		/* Auto close is on */
1727163953Srrs		asoc = &stcb->asoc;
1728163953Srrs		/* pick the time to use */
1729163953Srrs		if (asoc->time_last_rcvd.tv_sec >
1730163953Srrs		    asoc->time_last_sent.tv_sec) {
1731163953Srrs			tim_touse = &asoc->time_last_rcvd;
1732163953Srrs		} else {
1733163953Srrs			tim_touse = &asoc->time_last_sent;
1734163953Srrs		}
1735163953Srrs		/* Now has long enough transpired to autoclose? */
1736163953Srrs		ticks_gone_by = SEC_TO_TICKS(tn.tv_sec - tim_touse->tv_sec);
1737163953Srrs		if ((ticks_gone_by > 0) &&
1738163953Srrs		    (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) {
1739163953Srrs			/*
1740163953Srrs			 * autoclose time has hit, call the output routine,
1741163953Srrs			 * which should do nothing just to be SURE we don't
1742163953Srrs			 * have hanging data. We can then safely check the
1743163953Srrs			 * queues and know that we are clear to send
1744163953Srrs			 * shutdown
1745163953Srrs			 */
1746172090Srrs			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED);
1747163953Srrs			/* Are we clean? */
1748163953Srrs			if (TAILQ_EMPTY(&asoc->send_queue) &&
1749163953Srrs			    TAILQ_EMPTY(&asoc->sent_queue)) {
1750163953Srrs				/*
1751163953Srrs				 * there is nothing queued to send, so I'm
1752163953Srrs				 * done...
1753163953Srrs				 */
1754166675Srrs				if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1755163953Srrs					/* only send SHUTDOWN 1st time thru */
1756163953Srrs					sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
1757166675Srrs					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1758166675Srrs					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1759166675Srrs						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1760166675Srrs					}
1761171943Srrs					SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1762163953Srrs					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1763163953Srrs					    stcb->sctp_ep, stcb,
1764163953Srrs					    asoc->primary_destination);
1765163953Srrs					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1766163953Srrs					    stcb->sctp_ep, stcb,
1767163953Srrs					    asoc->primary_destination);
1768163953Srrs				}
1769163953Srrs			}
1770163953Srrs		} else {
1771163953Srrs			/*
1772163953Srrs			 * No auto close at this time, reset t-o to check
1773163953Srrs			 * later
1774163953Srrs			 */
1775163953Srrs			int tmp;
1776163953Srrs
1777163953Srrs			/* fool the timer startup to use the time left */
1778163953Srrs			tmp = asoc->sctp_autoclose_ticks;
1779163953Srrs			asoc->sctp_autoclose_ticks -= ticks_gone_by;
1780163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
1781163953Srrs			    net);
1782163953Srrs			/* restore the real tick value */
1783163953Srrs			asoc->sctp_autoclose_ticks = tmp;
1784163953Srrs		}
1785163953Srrs	}
1786163953Srrs}
1787163953Srrs
1788163953Srrsvoid
1789163953Srrssctp_iterator_timer(struct sctp_iterator *it)
1790163953Srrs{
1791163953Srrs	int iteration_count = 0;
1792167598Srrs	int inp_skip = 0;
1793163953Srrs
1794163953Srrs	/*
1795163953Srrs	 * only one iterator can run at a time. This is the only way we can
1796163953Srrs	 * cleanly pull ep's from underneath all the running interators when
1797163953Srrs	 * a ep is freed.
1798163953Srrs	 */
1799163953Srrs	SCTP_ITERATOR_LOCK();
1800163953Srrs	if (it->inp == NULL) {
1801163953Srrs		/* iterator is complete */
1802163953Srrsdone_with_iterator:
1803163953Srrs		SCTP_ITERATOR_UNLOCK();
1804163953Srrs		SCTP_INP_INFO_WLOCK();
1805167598Srrs		TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
1806163953Srrs		/* stopping the callout is not needed, in theory */
1807163953Srrs		SCTP_INP_INFO_WUNLOCK();
1808169378Srrs		(void)SCTP_OS_TIMER_STOP(&it->tmr.timer);
1809163953Srrs		if (it->function_atend != NULL) {
1810163953Srrs			(*it->function_atend) (it->pointer, it->val);
1811163953Srrs		}
1812170091Srrs		SCTP_FREE(it, SCTP_M_ITER);
1813163953Srrs		return;
1814163953Srrs	}
1815163953Srrsselect_a_new_ep:
1816163953Srrs	SCTP_INP_WLOCK(it->inp);
1817163953Srrs	while (((it->pcb_flags) &&
1818163953Srrs	    ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
1819163953Srrs	    ((it->pcb_features) &&
1820163953Srrs	    ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
1821163953Srrs		/* endpoint flags or features don't match, so keep looking */
1822163953Srrs		if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1823163953Srrs			SCTP_INP_WUNLOCK(it->inp);
1824163953Srrs			goto done_with_iterator;
1825163953Srrs		}
1826163953Srrs		SCTP_INP_WUNLOCK(it->inp);
1827163953Srrs		it->inp = LIST_NEXT(it->inp, sctp_list);
1828163953Srrs		if (it->inp == NULL) {
1829163953Srrs			goto done_with_iterator;
1830163953Srrs		}
1831163953Srrs		SCTP_INP_WLOCK(it->inp);
1832163953Srrs	}
1833163953Srrs	if ((it->inp->inp_starting_point_for_iterator != NULL) &&
1834163953Srrs	    (it->inp->inp_starting_point_for_iterator != it)) {
1835169420Srrs		SCTP_PRINTF("Iterator collision, waiting for one at %p\n",
1836163979Sru		    it->inp);
1837163953Srrs		SCTP_INP_WUNLOCK(it->inp);
1838163953Srrs		goto start_timer_return;
1839163953Srrs	}
1840163953Srrs	/* mark the current iterator on the endpoint */
1841163953Srrs	it->inp->inp_starting_point_for_iterator = it;
1842163953Srrs	SCTP_INP_WUNLOCK(it->inp);
1843163953Srrs	SCTP_INP_RLOCK(it->inp);
1844163953Srrs	/* now go through each assoc which is in the desired state */
1845167598Srrs	if (it->done_current_ep == 0) {
1846167598Srrs		if (it->function_inp != NULL)
1847167598Srrs			inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
1848167598Srrs		it->done_current_ep = 1;
1849167598Srrs	}
1850163953Srrs	if (it->stcb == NULL) {
1851163953Srrs		/* run the per instance function */
1852163953Srrs		it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
1853163953Srrs	}
1854163953Srrs	SCTP_INP_RUNLOCK(it->inp);
1855167598Srrs	if ((inp_skip) || it->stcb == NULL) {
1856167598Srrs		if (it->function_inp_end != NULL) {
1857167598Srrs			inp_skip = (*it->function_inp_end) (it->inp,
1858167598Srrs			    it->pointer,
1859167598Srrs			    it->val);
1860167598Srrs		}
1861167598Srrs		goto no_stcb;
1862167598Srrs	}
1863163953Srrs	if ((it->stcb) &&
1864163953Srrs	    (it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
1865163953Srrs		it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
1866163953Srrs	}
1867163953Srrs	while (it->stcb) {
1868163953Srrs		SCTP_TCB_LOCK(it->stcb);
1869163953Srrs		if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
1870163953Srrs			/* not in the right state... keep looking */
1871163953Srrs			SCTP_TCB_UNLOCK(it->stcb);
1872163953Srrs			goto next_assoc;
1873163953Srrs		}
1874163953Srrs		/* mark the current iterator on the assoc */
1875163953Srrs		it->stcb->asoc.stcb_starting_point_for_iterator = it;
1876163953Srrs		/* see if we have limited out the iterator loop */
1877163953Srrs		iteration_count++;
1878163953Srrs		if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
1879163953Srrs	start_timer_return:
1880163953Srrs			/* set a timer to continue this later */
1881170943Srrs			if (it->stcb)
1882170943Srrs				SCTP_TCB_UNLOCK(it->stcb);
1883163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR,
1884163953Srrs			    (struct sctp_inpcb *)it, NULL, NULL);
1885163953Srrs			SCTP_ITERATOR_UNLOCK();
1886163953Srrs			return;
1887163953Srrs		}
1888163953Srrs		/* run function on this one */
1889163953Srrs		(*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
1890163953Srrs
1891163953Srrs		/*
1892163953Srrs		 * we lie here, it really needs to have its own type but
1893163953Srrs		 * first I must verify that this won't effect things :-0
1894163953Srrs		 */
1895163953Srrs		if (it->no_chunk_output == 0)
1896172090Srrs			sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1897163953Srrs
1898163953Srrs		SCTP_TCB_UNLOCK(it->stcb);
1899163953Srrsnext_assoc:
1900163953Srrs		it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
1901167598Srrs		if (it->stcb == NULL) {
1902167598Srrs			if (it->function_inp_end != NULL) {
1903167598Srrs				inp_skip = (*it->function_inp_end) (it->inp,
1904167598Srrs				    it->pointer,
1905167598Srrs				    it->val);
1906167598Srrs			}
1907167598Srrs		}
1908163953Srrs	}
1909167598Srrsno_stcb:
1910163953Srrs	/* done with all assocs on this endpoint, move on to next endpoint */
1911167598Srrs	it->done_current_ep = 0;
1912163953Srrs	SCTP_INP_WLOCK(it->inp);
1913163953Srrs	it->inp->inp_starting_point_for_iterator = NULL;
1914163953Srrs	SCTP_INP_WUNLOCK(it->inp);
1915163953Srrs	if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1916163953Srrs		it->inp = NULL;
1917163953Srrs	} else {
1918163953Srrs		SCTP_INP_INFO_RLOCK();
1919163953Srrs		it->inp = LIST_NEXT(it->inp, sctp_list);
1920163953Srrs		SCTP_INP_INFO_RUNLOCK();
1921163953Srrs	}
1922163953Srrs	if (it->inp == NULL) {
1923163953Srrs		goto done_with_iterator;
1924163953Srrs	}
1925163953Srrs	goto select_a_new_ep;
1926163953Srrs}
1927