1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
37*7c478bd9Sstevel@tonic-gate #include <netinet/ip6.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include <inet/common.h>
40*7c478bd9Sstevel@tonic-gate #include <inet/ip.h>
41*7c478bd9Sstevel@tonic-gate #include <inet/mib2.h>
42*7c478bd9Sstevel@tonic-gate #include <inet/ipclassifier.h>
43*7c478bd9Sstevel@tonic-gate #include "sctp_impl.h"
44*7c478bd9Sstevel@tonic-gate #include "sctp_asconf.h"
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /* Timer block states. */
47*7c478bd9Sstevel@tonic-gate typedef enum {
48*7c478bd9Sstevel@tonic-gate 	SCTP_TB_RUNNING = 1,
49*7c478bd9Sstevel@tonic-gate 	SCTP_TB_IDLE,
50*7c478bd9Sstevel@tonic-gate /* Could not stop/free before mblk got queued */
51*7c478bd9Sstevel@tonic-gate 	SCTP_TB_RESCHED,	/* sctp_tb_time_left contains tick count */
52*7c478bd9Sstevel@tonic-gate 	SCTP_TB_CANCELLED,
53*7c478bd9Sstevel@tonic-gate 	SCTP_TB_TO_BE_FREED
54*7c478bd9Sstevel@tonic-gate } timer_block_state;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate typedef struct sctp_tb_s {
57*7c478bd9Sstevel@tonic-gate 	timer_block_state	sctp_tb_state;
58*7c478bd9Sstevel@tonic-gate 	timeout_id_t		sctp_tb_tid;
59*7c478bd9Sstevel@tonic-gate 	mblk_t			*sctp_tb_mp;
60*7c478bd9Sstevel@tonic-gate 	clock_t			sctp_tb_time_left;
61*7c478bd9Sstevel@tonic-gate } sctp_tb_t;
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static void sctp_timer_fire(sctp_tb_t *);
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate /*
66*7c478bd9Sstevel@tonic-gate  *		sctp_timer mechanism.
67*7c478bd9Sstevel@tonic-gate  *
68*7c478bd9Sstevel@tonic-gate  * Each timer is represented by a timer mblk. When the
69*7c478bd9Sstevel@tonic-gate  * timer fires, and the sctp_t is busy, the timer mblk will be put on
70*7c478bd9Sstevel@tonic-gate  * the associated sctp_t timer queue so that it can be executed when
71*7c478bd9Sstevel@tonic-gate  * the thread holding the lock on the sctp_t is done with its job.
72*7c478bd9Sstevel@tonic-gate  *
73*7c478bd9Sstevel@tonic-gate  * Note that there is no lock to protect the timer mblk state.  The reason
74*7c478bd9Sstevel@tonic-gate  * is that the timer state can only be changed by a thread holding the
75*7c478bd9Sstevel@tonic-gate  * lock on the sctp_t.
76*7c478bd9Sstevel@tonic-gate  *
77*7c478bd9Sstevel@tonic-gate  * The interface consists of 4 entry points:
78*7c478bd9Sstevel@tonic-gate  *	sctp_timer_alloc	- create a timer mblk
79*7c478bd9Sstevel@tonic-gate  *	sctp_timer_free		- free a timer mblk
80*7c478bd9Sstevel@tonic-gate  *	sctp_timer		- start, restart, stop the timer
81*7c478bd9Sstevel@tonic-gate  *	sctp_timer_valid	- called by sctp_process_recvq to verify that
82*7c478bd9Sstevel@tonic-gate  *				  the timer did indeed fire.
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate  * Start, restart, stop the timer.
88*7c478bd9Sstevel@tonic-gate  * If "tim" is -1 the timer is stopped.
89*7c478bd9Sstevel@tonic-gate  * Otherwise, the timer is stopped if it is already running, and
90*7c478bd9Sstevel@tonic-gate  * set to fire tim clock ticks from now.
91*7c478bd9Sstevel@tonic-gate  */
92*7c478bd9Sstevel@tonic-gate void
93*7c478bd9Sstevel@tonic-gate sctp_timer(sctp_t *sctp, mblk_t *mp, clock_t tim)
94*7c478bd9Sstevel@tonic-gate {
95*7c478bd9Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
96*7c478bd9Sstevel@tonic-gate 	int state;
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate 	ASSERT(sctp != NULL && mp != NULL);
99*7c478bd9Sstevel@tonic-gate 	ASSERT((mp->b_rptr - mp->b_datap->db_base) == sizeof (sctp_tb_t));
100*7c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
103*7c478bd9Sstevel@tonic-gate 	if (tim >= 0) {
104*7c478bd9Sstevel@tonic-gate 		state = sctp_tb->sctp_tb_state;
105*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_time_left = tim;
106*7c478bd9Sstevel@tonic-gate 		if (state == SCTP_TB_RUNNING) {
107*7c478bd9Sstevel@tonic-gate 			if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
108*7c478bd9Sstevel@tonic-gate 				sctp_tb->sctp_tb_state = SCTP_TB_RESCHED;
109*7c478bd9Sstevel@tonic-gate 				/* sctp_timer_valid will start timer */
110*7c478bd9Sstevel@tonic-gate 				return;
111*7c478bd9Sstevel@tonic-gate 			}
112*7c478bd9Sstevel@tonic-gate 		} else if (state != SCTP_TB_IDLE) {
113*7c478bd9Sstevel@tonic-gate 			ASSERT(state != SCTP_TB_TO_BE_FREED);
114*7c478bd9Sstevel@tonic-gate 			if (state == SCTP_TB_CANCELLED) {
115*7c478bd9Sstevel@tonic-gate 				sctp_tb->sctp_tb_state = SCTP_TB_RESCHED;
116*7c478bd9Sstevel@tonic-gate 				/* sctp_timer_valid will start timer */
117*7c478bd9Sstevel@tonic-gate 				return;
118*7c478bd9Sstevel@tonic-gate 			}
119*7c478bd9Sstevel@tonic-gate 			if (state == SCTP_TB_RESCHED) {
120*7c478bd9Sstevel@tonic-gate 				/* sctp_timer_valid will start timer */
121*7c478bd9Sstevel@tonic-gate 				return;
122*7c478bd9Sstevel@tonic-gate 			}
123*7c478bd9Sstevel@tonic-gate 		} else {
124*7c478bd9Sstevel@tonic-gate 			SCTP_REFHOLD(sctp);
125*7c478bd9Sstevel@tonic-gate 		}
126*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_RUNNING;
127*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_tid =
128*7c478bd9Sstevel@tonic-gate 		    timeout((pfv_t)sctp_timer_fire, sctp_tb, tim);
129*7c478bd9Sstevel@tonic-gate 		return;
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate 	switch (tim) {
132*7c478bd9Sstevel@tonic-gate 	case -1:
133*7c478bd9Sstevel@tonic-gate 		sctp_timer_stop(mp);
134*7c478bd9Sstevel@tonic-gate 		break;
135*7c478bd9Sstevel@tonic-gate 	default:
136*7c478bd9Sstevel@tonic-gate 		ASSERT(0);
137*7c478bd9Sstevel@tonic-gate 		break;
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate }
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate /*
142*7c478bd9Sstevel@tonic-gate  * sctp_timer_alloc is called by sctp_init to allocate and initialize a
143*7c478bd9Sstevel@tonic-gate  * sctp timer.
144*7c478bd9Sstevel@tonic-gate  *
145*7c478bd9Sstevel@tonic-gate  * Allocate an M_PCSIG timer message. The space between db_base and
146*7c478bd9Sstevel@tonic-gate  * b_rptr is used by the sctp_timer mechanism, and after b_rptr there is
147*7c478bd9Sstevel@tonic-gate  * space for sctpt_t.
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate mblk_t *
150*7c478bd9Sstevel@tonic-gate sctp_timer_alloc(sctp_t *sctp, pfv_t func)
151*7c478bd9Sstevel@tonic-gate {
152*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
153*7c478bd9Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
154*7c478bd9Sstevel@tonic-gate 	sctpt_t	*sctpt;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	if ((mp = allocb(sizeof (sctp_t) + sizeof (sctp_tb_t), BPRI_HI))) {
157*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_PCSIG;
158*7c478bd9Sstevel@tonic-gate 		sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
159*7c478bd9Sstevel@tonic-gate 		mp->b_rptr = (uchar_t *)&sctp_tb[1];
160*7c478bd9Sstevel@tonic-gate 		mp->b_wptr = mp->b_rptr + sizeof (sctpt_t);
161*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
162*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_mp = mp;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 		sctpt = (sctpt_t *)mp->b_rptr;
165*7c478bd9Sstevel@tonic-gate 		sctpt->sctpt_sctp = sctp;
166*7c478bd9Sstevel@tonic-gate 		sctpt->sctpt_faddr = NULL;	/* set when starting timer */
167*7c478bd9Sstevel@tonic-gate 		sctpt->sctpt_pfv = func;
168*7c478bd9Sstevel@tonic-gate 		return (mp);
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 	return (NULL);
171*7c478bd9Sstevel@tonic-gate }
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate /*
174*7c478bd9Sstevel@tonic-gate  * timeout() callback function.
175*7c478bd9Sstevel@tonic-gate  * Put the message on the process control block's queue.
176*7c478bd9Sstevel@tonic-gate  * If the timer is stopped or freed after
177*7c478bd9Sstevel@tonic-gate  * it has fired then sctp_timer() and sctp_timer_valid() will clean
178*7c478bd9Sstevel@tonic-gate  * things up.
179*7c478bd9Sstevel@tonic-gate  */
180*7c478bd9Sstevel@tonic-gate static void
181*7c478bd9Sstevel@tonic-gate sctp_timer_fire(sctp_tb_t *sctp_tb)
182*7c478bd9Sstevel@tonic-gate {
183*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
184*7c478bd9Sstevel@tonic-gate 	sctp_t *sctp;
185*7c478bd9Sstevel@tonic-gate 	sctpt_t *sctpt;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	mp = sctp_tb->sctp_tb_mp;
188*7c478bd9Sstevel@tonic-gate 	ASSERT(sctp_tb == (sctp_tb_t *)mp->b_datap->db_base);
189*7c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	sctpt = (sctpt_t *)mp->b_rptr;
192*7c478bd9Sstevel@tonic-gate 	sctp = sctpt->sctpt_sctp;
193*7c478bd9Sstevel@tonic-gate 	ASSERT(sctp != NULL);
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	mutex_enter(&sctp->sctp_lock);
196*7c478bd9Sstevel@tonic-gate 	if (sctp->sctp_running) {
197*7c478bd9Sstevel@tonic-gate 		/*
198*7c478bd9Sstevel@tonic-gate 		 * Put the timer mblk to the special sctp_timer_mp list.
199*7c478bd9Sstevel@tonic-gate 		 * This timer will be handled when the thread using this
200*7c478bd9Sstevel@tonic-gate 		 * SCTP is done with its job.
201*7c478bd9Sstevel@tonic-gate 		 */
202*7c478bd9Sstevel@tonic-gate 		if (sctp->sctp_timer_mp == NULL) {
203*7c478bd9Sstevel@tonic-gate 			SCTP_REFHOLD(sctp);
204*7c478bd9Sstevel@tonic-gate 			sctp->sctp_timer_mp = mp;
205*7c478bd9Sstevel@tonic-gate 		} else {
206*7c478bd9Sstevel@tonic-gate 			linkb(sctp->sctp_timer_mp, mp);
207*7c478bd9Sstevel@tonic-gate 		}
208*7c478bd9Sstevel@tonic-gate 		mp->b_cont = NULL;
209*7c478bd9Sstevel@tonic-gate 		mutex_exit(&sctp->sctp_lock);
210*7c478bd9Sstevel@tonic-gate 	} else {
211*7c478bd9Sstevel@tonic-gate 		sctp->sctp_running = B_TRUE;
212*7c478bd9Sstevel@tonic-gate 		mutex_exit(&sctp->sctp_lock);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 		sctp_timer_call(sctp, mp);
215*7c478bd9Sstevel@tonic-gate 		WAKE_SCTP(sctp);
216*7c478bd9Sstevel@tonic-gate 		sctp_process_sendq(sctp);
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate 	SCTP_REFRELE(sctp);
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate /*
222*7c478bd9Sstevel@tonic-gate  * Logically free a timer mblk (that might have a pending timeout().)
223*7c478bd9Sstevel@tonic-gate  * If the timer has fired and the mblk has been put on the queue then
224*7c478bd9Sstevel@tonic-gate  * sctp_timer_valid will free the mblk.
225*7c478bd9Sstevel@tonic-gate  */
226*7c478bd9Sstevel@tonic-gate void
227*7c478bd9Sstevel@tonic-gate sctp_timer_free(mblk_t *mp)
228*7c478bd9Sstevel@tonic-gate {
229*7c478bd9Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
230*7c478bd9Sstevel@tonic-gate 	int state;
231*7c478bd9Sstevel@tonic-gate 	sctpt_t *sctpt;
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL);
234*7c478bd9Sstevel@tonic-gate 	ASSERT((mp->b_rptr - mp->b_datap->db_base) == sizeof (sctp_tb_t));
235*7c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
238*7c478bd9Sstevel@tonic-gate 	state = sctp_tb->sctp_tb_state;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	dprint(5, ("sctp_timer_free %p state %d\n", mp, state));
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	if (state == SCTP_TB_RUNNING) {
243*7c478bd9Sstevel@tonic-gate 		if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
244*7c478bd9Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_TO_BE_FREED;
245*7c478bd9Sstevel@tonic-gate 			/* sctp_timer_valid will free the mblk */
246*7c478bd9Sstevel@tonic-gate 			return;
247*7c478bd9Sstevel@tonic-gate 		}
248*7c478bd9Sstevel@tonic-gate 		sctpt = (sctpt_t *)mp->b_rptr;
249*7c478bd9Sstevel@tonic-gate 		SCTP_REFRELE(sctpt->sctpt_sctp);
250*7c478bd9Sstevel@tonic-gate 	} else if (state != SCTP_TB_IDLE) {
251*7c478bd9Sstevel@tonic-gate 		ASSERT(state != SCTP_TB_TO_BE_FREED);
252*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_TO_BE_FREED;
253*7c478bd9Sstevel@tonic-gate 		/* sctp_timer_valid will free the mblk */
254*7c478bd9Sstevel@tonic-gate 		return;
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 	freeb(mp);
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /*
260*7c478bd9Sstevel@tonic-gate  * Called from sctp_timer(,,-1)
261*7c478bd9Sstevel@tonic-gate  */
262*7c478bd9Sstevel@tonic-gate void
263*7c478bd9Sstevel@tonic-gate sctp_timer_stop(mblk_t *mp)
264*7c478bd9Sstevel@tonic-gate {
265*7c478bd9Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
266*7c478bd9Sstevel@tonic-gate 	int state;
267*7c478bd9Sstevel@tonic-gate 	sctpt_t *sctpt;
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL);
270*7c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
273*7c478bd9Sstevel@tonic-gate 	state = sctp_tb->sctp_tb_state;
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	dprint(5, ("sctp_timer_stop %p %d\n", mp, state));
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	if (state == SCTP_TB_RUNNING) {
278*7c478bd9Sstevel@tonic-gate 		if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
279*7c478bd9Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_CANCELLED;
280*7c478bd9Sstevel@tonic-gate 		} else {
281*7c478bd9Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
282*7c478bd9Sstevel@tonic-gate 			sctpt = (sctpt_t *)mp->b_rptr;
283*7c478bd9Sstevel@tonic-gate 			SCTP_REFRELE(sctpt->sctpt_sctp);
284*7c478bd9Sstevel@tonic-gate 		}
285*7c478bd9Sstevel@tonic-gate 	} else if (state == SCTP_TB_RESCHED) {
286*7c478bd9Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_CANCELLED;
287*7c478bd9Sstevel@tonic-gate 	}
288*7c478bd9Sstevel@tonic-gate }
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate /*
291*7c478bd9Sstevel@tonic-gate  * The user of the sctp_timer mechanism is required to call
292*7c478bd9Sstevel@tonic-gate  * sctp_timer_valid() for each M_PCSIG message processed in the
293*7c478bd9Sstevel@tonic-gate  * service procedures.
294*7c478bd9Sstevel@tonic-gate  * sctp_timer_valid will return "true" if the timer actually did fire.
295*7c478bd9Sstevel@tonic-gate  */
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate static boolean_t
298*7c478bd9Sstevel@tonic-gate sctp_timer_valid(mblk_t *mp)
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
301*7c478bd9Sstevel@tonic-gate 	int state;
302*7c478bd9Sstevel@tonic-gate 	sctpt_t *sctpt;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL);
305*7c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)DB_BASE(mp);
308*7c478bd9Sstevel@tonic-gate 	sctpt = (sctpt_t *)mp->b_rptr;
309*7c478bd9Sstevel@tonic-gate 	state = sctp_tb->sctp_tb_state;
310*7c478bd9Sstevel@tonic-gate 	if (state != SCTP_TB_RUNNING) {
311*7c478bd9Sstevel@tonic-gate 		ASSERT(state != SCTP_TB_IDLE);
312*7c478bd9Sstevel@tonic-gate 		if (state == SCTP_TB_TO_BE_FREED) {
313*7c478bd9Sstevel@tonic-gate 			/*
314*7c478bd9Sstevel@tonic-gate 			 * sctp_timer_free was called after the message
315*7c478bd9Sstevel@tonic-gate 			 * was putq'ed.
316*7c478bd9Sstevel@tonic-gate 			 */
317*7c478bd9Sstevel@tonic-gate 			freeb(mp);
318*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);
319*7c478bd9Sstevel@tonic-gate 		}
320*7c478bd9Sstevel@tonic-gate 		if (state == SCTP_TB_CANCELLED) {
321*7c478bd9Sstevel@tonic-gate 			/* The timer was stopped after the mblk was putq'ed */
322*7c478bd9Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
323*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 		if (state == SCTP_TB_RESCHED) {
326*7c478bd9Sstevel@tonic-gate 			/*
327*7c478bd9Sstevel@tonic-gate 			 * The timer was stopped and then restarted after
328*7c478bd9Sstevel@tonic-gate 			 * the mblk was putq'ed.
329*7c478bd9Sstevel@tonic-gate 			 * sctp_tb_time_left contains the number of ticks that
330*7c478bd9Sstevel@tonic-gate 			 * the timer was restarted with.
331*7c478bd9Sstevel@tonic-gate 			 * The sctp will not be disapper between the time
332*7c478bd9Sstevel@tonic-gate 			 * the sctpt_t is marked SCTP_TB_RESCHED and when
333*7c478bd9Sstevel@tonic-gate 			 * we get here as sctp_add_recvq() does a refhold.
334*7c478bd9Sstevel@tonic-gate 			 */
335*7c478bd9Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_RUNNING;
336*7c478bd9Sstevel@tonic-gate 			sctp_tb->sctp_tb_tid = timeout((pfv_t)sctp_timer_fire,
337*7c478bd9Sstevel@tonic-gate 			    sctp_tb, sctp_tb->sctp_tb_time_left);
338*7c478bd9Sstevel@tonic-gate 			SCTP_REFHOLD(sctpt->sctpt_sctp);
339*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);
340*7c478bd9Sstevel@tonic-gate 		}
341*7c478bd9Sstevel@tonic-gate 	}
342*7c478bd9Sstevel@tonic-gate 	sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
343*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate /*
347*7c478bd9Sstevel@tonic-gate  * The SCTP timer call. Calls sctp_timer_valid() to verify whether
348*7c478bd9Sstevel@tonic-gate  * timer was cancelled or not.
349*7c478bd9Sstevel@tonic-gate  */
350*7c478bd9Sstevel@tonic-gate void
351*7c478bd9Sstevel@tonic-gate sctp_timer_call(sctp_t *sctp, mblk_t *mp)
352*7c478bd9Sstevel@tonic-gate {
353*7c478bd9Sstevel@tonic-gate 	sctpt_t *sctpt = (sctpt_t *)mp->b_rptr;
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	if (sctp_timer_valid(mp)) {
356*7c478bd9Sstevel@tonic-gate 		(*sctpt->sctpt_pfv)(sctp, sctpt->sctpt_faddr);
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate /*
361*7c478bd9Sstevel@tonic-gate  * Delayed ack
362*7c478bd9Sstevel@tonic-gate  */
363*7c478bd9Sstevel@tonic-gate void
364*7c478bd9Sstevel@tonic-gate sctp_ack_timer(sctp_t *sctp)
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 	sctp->sctp_ack_timer_running = 0;
367*7c478bd9Sstevel@tonic-gate 	sctp->sctp_sack_toggle = 2;
368*7c478bd9Sstevel@tonic-gate 	BUMP_MIB(&sctp_mib, sctpOutAckDelayed);
369*7c478bd9Sstevel@tonic-gate 	sctp_sack(sctp, NULL);
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate /*
373*7c478bd9Sstevel@tonic-gate  * Peer address heartbeat timer handler
374*7c478bd9Sstevel@tonic-gate  */
375*7c478bd9Sstevel@tonic-gate void
376*7c478bd9Sstevel@tonic-gate sctp_heartbeat_timer(sctp_t *sctp)
377*7c478bd9Sstevel@tonic-gate {
378*7c478bd9Sstevel@tonic-gate 	sctp_faddr_t	*fp;
379*7c478bd9Sstevel@tonic-gate 	int64_t		now;
380*7c478bd9Sstevel@tonic-gate 	int64_t		earliest_expiry;
381*7c478bd9Sstevel@tonic-gate 	int		cnt;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) {
384*7c478bd9Sstevel@tonic-gate 		/*
385*7c478bd9Sstevel@tonic-gate 		 * If there is a peer address with no strikes,
386*7c478bd9Sstevel@tonic-gate 		 * don't give up yet. If enough other peer
387*7c478bd9Sstevel@tonic-gate 		 * address are down, we could otherwise fail
388*7c478bd9Sstevel@tonic-gate 		 * the association prematurely.  This is a
389*7c478bd9Sstevel@tonic-gate 		 * byproduct of our aggressive probe approach
390*7c478bd9Sstevel@tonic-gate 		 * when a heartbeat fails to connect. We may
391*7c478bd9Sstevel@tonic-gate 		 * wish to revisit this...
392*7c478bd9Sstevel@tonic-gate 		 */
393*7c478bd9Sstevel@tonic-gate 		if (!sctp_is_a_faddr_clean(sctp)) {
394*7c478bd9Sstevel@tonic-gate 			/* time to give up */
395*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpAborted);
396*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpTimHeartBeatDrop);
397*7c478bd9Sstevel@tonic-gate 			sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
398*7c478bd9Sstevel@tonic-gate 			sctp_clean_death(sctp, sctp->sctp_client_errno ?
399*7c478bd9Sstevel@tonic-gate 			    sctp->sctp_client_errno : ETIMEDOUT);
400*7c478bd9Sstevel@tonic-gate 			return;
401*7c478bd9Sstevel@tonic-gate 		}
402*7c478bd9Sstevel@tonic-gate 	}
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 	/* Only send heartbeats in the established state */
405*7c478bd9Sstevel@tonic-gate 	if (sctp->sctp_state != SCTPS_ESTABLISHED) {
406*7c478bd9Sstevel@tonic-gate 		dprint(5, ("sctp_heartbeat_timer: not in ESTABLISHED\n"));
407*7c478bd9Sstevel@tonic-gate 		return;
408*7c478bd9Sstevel@tonic-gate 	}
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	now = lbolt64;
411*7c478bd9Sstevel@tonic-gate 	earliest_expiry = 0;
412*7c478bd9Sstevel@tonic-gate 	cnt = sctp_maxburst;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 	/*
415*7c478bd9Sstevel@tonic-gate 	 * Walk through all faddrs.  Since the timer should run infrequently
416*7c478bd9Sstevel@tonic-gate 	 * and the number of peer addresses should not be big, this should
417*7c478bd9Sstevel@tonic-gate 	 * be OK.
418*7c478bd9Sstevel@tonic-gate 	 */
419*7c478bd9Sstevel@tonic-gate 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) {
420*7c478bd9Sstevel@tonic-gate 		/*
421*7c478bd9Sstevel@tonic-gate 		 * Don't send heartbeat to this address if
422*7c478bd9Sstevel@tonic-gate 		 * 1. it is not reachable OR
423*7c478bd9Sstevel@tonic-gate 		 * 2. hb_interval == 0 and the address has been confirmed.
424*7c478bd9Sstevel@tonic-gate 		 */
425*7c478bd9Sstevel@tonic-gate 		if (fp->state == SCTP_FADDRS_UNREACH ||
426*7c478bd9Sstevel@tonic-gate 		    (fp->hb_interval == 0 &&
427*7c478bd9Sstevel@tonic-gate 		    fp->state != SCTP_FADDRS_UNCONFIRMED)) {
428*7c478bd9Sstevel@tonic-gate 			continue;
429*7c478bd9Sstevel@tonic-gate 		}
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 		/*
432*7c478bd9Sstevel@tonic-gate 		 * The heartbeat timer is expired.  If the address is dead,
433*7c478bd9Sstevel@tonic-gate 		 * we still send heartbeat to it in case it becomes alive
434*7c478bd9Sstevel@tonic-gate 		 * again.  But we will only send once every hb_interval.
435*7c478bd9Sstevel@tonic-gate 		 *
436*7c478bd9Sstevel@tonic-gate 		 * If the address is alive and there is a hearbeat pending,
437*7c478bd9Sstevel@tonic-gate 		 * resend the heartbeat and start exponential backoff on the
438*7c478bd9Sstevel@tonic-gate 		 * heartbeat timeout value.  If there is no heartbeat pending,
439*7c478bd9Sstevel@tonic-gate 		 * just send out one.
440*7c478bd9Sstevel@tonic-gate 		 */
441*7c478bd9Sstevel@tonic-gate 		if (now >= fp->hb_expiry) {
442*7c478bd9Sstevel@tonic-gate 			if (fp->hb_pending) {
443*7c478bd9Sstevel@tonic-gate 				/*
444*7c478bd9Sstevel@tonic-gate 				 * If an address is not confirmed, no need
445*7c478bd9Sstevel@tonic-gate 				 * to bump the overall counter as it doesn't
446*7c478bd9Sstevel@tonic-gate 				 * matter as we will not use it to send data
447*7c478bd9Sstevel@tonic-gate 				 * and it should not affect the association.
448*7c478bd9Sstevel@tonic-gate 				 */
449*7c478bd9Sstevel@tonic-gate 				switch (fp->state) {
450*7c478bd9Sstevel@tonic-gate 				case SCTP_FADDRS_ALIVE:
451*7c478bd9Sstevel@tonic-gate 					sctp->sctp_strikes++;
452*7c478bd9Sstevel@tonic-gate 					/* FALLTHRU */
453*7c478bd9Sstevel@tonic-gate 				case SCTP_FADDRS_UNCONFIRMED:
454*7c478bd9Sstevel@tonic-gate 					/*
455*7c478bd9Sstevel@tonic-gate 					 * Retransmission implies that RTO
456*7c478bd9Sstevel@tonic-gate 					 * is probably not correct.
457*7c478bd9Sstevel@tonic-gate 					 */
458*7c478bd9Sstevel@tonic-gate 					fp->rtt_updates = 0;
459*7c478bd9Sstevel@tonic-gate 					fp->strikes++;
460*7c478bd9Sstevel@tonic-gate 					if (fp->strikes > fp->max_retr) {
461*7c478bd9Sstevel@tonic-gate 						if (sctp_faddr_dead(sctp, fp,
462*7c478bd9Sstevel@tonic-gate 						    SCTP_FADDRS_DOWN) == -1) {
463*7c478bd9Sstevel@tonic-gate 							/* Assoc is dead */
464*7c478bd9Sstevel@tonic-gate 							return;
465*7c478bd9Sstevel@tonic-gate 						}
466*7c478bd9Sstevel@tonic-gate 						/*
467*7c478bd9Sstevel@tonic-gate 						 * Addr is down; keep initial
468*7c478bd9Sstevel@tonic-gate 						 * RTO
469*7c478bd9Sstevel@tonic-gate 						 */
470*7c478bd9Sstevel@tonic-gate 						fp->rto =
471*7c478bd9Sstevel@tonic-gate 						    sctp->sctp_rto_initial;
472*7c478bd9Sstevel@tonic-gate 						goto dead_addr;
473*7c478bd9Sstevel@tonic-gate 					} else {
474*7c478bd9Sstevel@tonic-gate 						SCTP_CALC_RXT(fp,
475*7c478bd9Sstevel@tonic-gate 						    sctp->sctp_rto_max);
476*7c478bd9Sstevel@tonic-gate 						fp->hb_expiry = now + fp->rto;
477*7c478bd9Sstevel@tonic-gate 					}
478*7c478bd9Sstevel@tonic-gate 					break;
479*7c478bd9Sstevel@tonic-gate 				case SCTP_FADDRS_DOWN:
480*7c478bd9Sstevel@tonic-gate dead_addr:
481*7c478bd9Sstevel@tonic-gate 					fp->hb_expiry = now + SET_HB_INTVL(fp);
482*7c478bd9Sstevel@tonic-gate 					break;
483*7c478bd9Sstevel@tonic-gate 				default:
484*7c478bd9Sstevel@tonic-gate 					continue;
485*7c478bd9Sstevel@tonic-gate 				}
486*7c478bd9Sstevel@tonic-gate 			} else {
487*7c478bd9Sstevel@tonic-gate 				fp->hb_expiry = now + fp->rto;
488*7c478bd9Sstevel@tonic-gate 			}
489*7c478bd9Sstevel@tonic-gate 			/*
490*7c478bd9Sstevel@tonic-gate 			 * Note that the total number of heartbeat we can send
491*7c478bd9Sstevel@tonic-gate 			 * out simultaneously is limited by sctp_maxburst.  If
492*7c478bd9Sstevel@tonic-gate 			 * the limit is exceeded, we need to wait for the next
493*7c478bd9Sstevel@tonic-gate 			 * timeout to send them.  This should only happen if
494*7c478bd9Sstevel@tonic-gate 			 * there is unconfirmed address.  Note that hb_pending
495*7c478bd9Sstevel@tonic-gate 			 * is set in sctp_send_heartbeat().  So if a heartbeat
496*7c478bd9Sstevel@tonic-gate 			 * is not sent, it will not affect the state of the
497*7c478bd9Sstevel@tonic-gate 			 * peer address.
498*7c478bd9Sstevel@tonic-gate 			 */
499*7c478bd9Sstevel@tonic-gate 			if (fp->state != SCTP_FADDRS_UNCONFIRMED || cnt-- > 0)
500*7c478bd9Sstevel@tonic-gate 				sctp_send_heartbeat(sctp, fp);
501*7c478bd9Sstevel@tonic-gate 		}
502*7c478bd9Sstevel@tonic-gate 		if (fp->hb_expiry < earliest_expiry || earliest_expiry == 0)
503*7c478bd9Sstevel@tonic-gate 			earliest_expiry = fp->hb_expiry;
504*7c478bd9Sstevel@tonic-gate 	}
505*7c478bd9Sstevel@tonic-gate 	if (sctp->sctp_autoclose != 0) {
506*7c478bd9Sstevel@tonic-gate 		int64_t expire;
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 		expire = sctp->sctp_active + sctp->sctp_autoclose;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 		if (expire <= now) {
511*7c478bd9Sstevel@tonic-gate 			dprint(3, ("sctp_heartbeat_timer: autoclosing\n"));
512*7c478bd9Sstevel@tonic-gate 			sctp_send_shutdown(sctp, 0);
513*7c478bd9Sstevel@tonic-gate 			return;
514*7c478bd9Sstevel@tonic-gate 		}
515*7c478bd9Sstevel@tonic-gate 		if (expire < earliest_expiry || earliest_expiry == 0)
516*7c478bd9Sstevel@tonic-gate 			earliest_expiry = expire;
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	earliest_expiry -= now;
520*7c478bd9Sstevel@tonic-gate 	if (earliest_expiry < 0)
521*7c478bd9Sstevel@tonic-gate 		earliest_expiry = 1;
522*7c478bd9Sstevel@tonic-gate 	sctp_timer(sctp, sctp->sctp_heartbeat_mp, earliest_expiry);
523*7c478bd9Sstevel@tonic-gate }
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate void
526*7c478bd9Sstevel@tonic-gate sctp_rexmit_timer(sctp_t *sctp, sctp_faddr_t *fp)
527*7c478bd9Sstevel@tonic-gate {
528*7c478bd9Sstevel@tonic-gate 	mblk_t 		*mp;
529*7c478bd9Sstevel@tonic-gate 	uint32_t	rto_max = sctp->sctp_rto_max;
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	ASSERT(fp != NULL);
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	dprint(3, ("sctp_timer: faddr=%x:%x:%x:%x\n",
534*7c478bd9Sstevel@tonic-gate 	    SCTP_PRINTADDR(fp->faddr)));
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 	fp->timer_running = 0;
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 	/* Check is we've reached the max for retries */
539*7c478bd9Sstevel@tonic-gate 	if (sctp->sctp_state < SCTPS_ESTABLISHED) {
540*7c478bd9Sstevel@tonic-gate 		if (fp->strikes >= sctp->sctp_max_init_rxt) {
541*7c478bd9Sstevel@tonic-gate 			/* time to give up */
542*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpAborted);
543*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpTimRetransDrop);
544*7c478bd9Sstevel@tonic-gate 			sctp_assoc_event(sctp, SCTP_CANT_STR_ASSOC, 0, NULL);
545*7c478bd9Sstevel@tonic-gate 			sctp_clean_death(sctp, sctp->sctp_client_errno ?
546*7c478bd9Sstevel@tonic-gate 			    sctp->sctp_client_errno : ETIMEDOUT);
547*7c478bd9Sstevel@tonic-gate 			return;
548*7c478bd9Sstevel@tonic-gate 		}
549*7c478bd9Sstevel@tonic-gate 	} else if (sctp->sctp_state >= SCTPS_ESTABLISHED) {
550*7c478bd9Sstevel@tonic-gate 		if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) {
551*7c478bd9Sstevel@tonic-gate 			/* time to give up */
552*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpAborted);
553*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpTimRetransDrop);
554*7c478bd9Sstevel@tonic-gate 			sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
555*7c478bd9Sstevel@tonic-gate 			sctp_clean_death(sctp, sctp->sctp_client_errno ?
556*7c478bd9Sstevel@tonic-gate 			    sctp->sctp_client_errno : ETIMEDOUT);
557*7c478bd9Sstevel@tonic-gate 			return;
558*7c478bd9Sstevel@tonic-gate 		}
559*7c478bd9Sstevel@tonic-gate 	}
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 	if (fp->strikes >= fp->max_retr) {
562*7c478bd9Sstevel@tonic-gate 		if (sctp_faddr_dead(sctp, fp, SCTP_FADDRS_DOWN) == -1) {
563*7c478bd9Sstevel@tonic-gate 			return;
564*7c478bd9Sstevel@tonic-gate 		}
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	switch (sctp->sctp_state) {
568*7c478bd9Sstevel@tonic-gate 	case SCTPS_ESTABLISHED:
569*7c478bd9Sstevel@tonic-gate 		/*
570*7c478bd9Sstevel@tonic-gate 		 * Reset the heartbeat expiry time.  We don't need a heartbeat
571*7c478bd9Sstevel@tonic-gate 		 * timer running if we are retransmitting.  Otherwise, the drop
572*7c478bd9Sstevel@tonic-gate 		 * of heartbeat may just make this peer address to be marked
573*7c478bd9Sstevel@tonic-gate 		 * dead faster as fp->strikes is also increased for heartbeat.
574*7c478bd9Sstevel@tonic-gate 		 */
575*7c478bd9Sstevel@tonic-gate 		fp->hb_expiry = lbolt64 + SET_HB_INTVL(fp);
576*7c478bd9Sstevel@tonic-gate 		fp->hb_pending = B_FALSE;
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
579*7c478bd9Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_PENDING:
580*7c478bd9Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_RECEIVED:
581*7c478bd9Sstevel@tonic-gate 		if (sctp->sctp_state == SCTPS_SHUTDOWN_RECEIVED) {
582*7c478bd9Sstevel@tonic-gate 			(void) sctp_shutdown_received(sctp, NULL, 0, 1);
583*7c478bd9Sstevel@tonic-gate 		}
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 		if (sctp->sctp_xmit_head == NULL &&
586*7c478bd9Sstevel@tonic-gate 		    sctp->sctp_xmit_unsent == NULL) {
587*7c478bd9Sstevel@tonic-gate 			/* Nothing to retransmit */
588*7c478bd9Sstevel@tonic-gate 			if (sctp->sctp_state == SCTPS_SHUTDOWN_PENDING) {
589*7c478bd9Sstevel@tonic-gate 				sctp_send_shutdown(sctp, 1);
590*7c478bd9Sstevel@tonic-gate 			}
591*7c478bd9Sstevel@tonic-gate 			return;
592*7c478bd9Sstevel@tonic-gate 		}
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 		BUMP_MIB(&sctp_mib, sctpTimRetrans);
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 		sctp_rexmit(sctp, fp);
597*7c478bd9Sstevel@tonic-gate 		/*
598*7c478bd9Sstevel@tonic-gate 		 * sctp_rexmit() will increase the strikes and restart the
599*7c478bd9Sstevel@tonic-gate 		 * timer, so return here.
600*7c478bd9Sstevel@tonic-gate 		 */
601*7c478bd9Sstevel@tonic-gate 		return;
602*7c478bd9Sstevel@tonic-gate 	case SCTPS_COOKIE_WAIT:
603*7c478bd9Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T1expire);
604*7c478bd9Sstevel@tonic-gate rxmit_init:
605*7c478bd9Sstevel@tonic-gate 		/* retransmit init */
606*7c478bd9Sstevel@tonic-gate 		mp = sctp_init_mp(sctp);
607*7c478bd9Sstevel@tonic-gate 		if (mp != NULL) {
608*7c478bd9Sstevel@tonic-gate 			BUMP_MIB(&sctp_mib, sctpTimRetrans);
609*7c478bd9Sstevel@tonic-gate 			sctp_add_sendq(sctp, mp);
610*7c478bd9Sstevel@tonic-gate 		}
611*7c478bd9Sstevel@tonic-gate 		rto_max = sctp->sctp_init_rto_max;
612*7c478bd9Sstevel@tonic-gate 		break;
613*7c478bd9Sstevel@tonic-gate 	case SCTPS_COOKIE_ECHOED: {
614*7c478bd9Sstevel@tonic-gate 		ipha_t *iph;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T1expire);
617*7c478bd9Sstevel@tonic-gate 		if (sctp->sctp_cookie_mp == NULL) {
618*7c478bd9Sstevel@tonic-gate 			sctp->sctp_state = SCTPS_COOKIE_WAIT;
619*7c478bd9Sstevel@tonic-gate 			goto rxmit_init;
620*7c478bd9Sstevel@tonic-gate 		}
621*7c478bd9Sstevel@tonic-gate 		mp = dupmsg(sctp->sctp_cookie_mp);
622*7c478bd9Sstevel@tonic-gate 		if (mp == NULL)
623*7c478bd9Sstevel@tonic-gate 			break;
624*7c478bd9Sstevel@tonic-gate 		iph = (ipha_t *)mp->b_rptr;
625*7c478bd9Sstevel@tonic-gate 		/* Reset the IP ident. */
626*7c478bd9Sstevel@tonic-gate 		if (IPH_HDR_VERSION(iph) == IPV4_VERSION)
627*7c478bd9Sstevel@tonic-gate 			iph->ipha_ident = 0;
628*7c478bd9Sstevel@tonic-gate 		sctp_add_sendq(sctp, mp);
629*7c478bd9Sstevel@tonic-gate 		BUMP_MIB(&sctp_mib, sctpTimRetrans);
630*7c478bd9Sstevel@tonic-gate 		rto_max = sctp->sctp_init_rto_max;
631*7c478bd9Sstevel@tonic-gate 		break;
632*7c478bd9Sstevel@tonic-gate 	}
633*7c478bd9Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_SENT:
634*7c478bd9Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T2expire);
635*7c478bd9Sstevel@tonic-gate 		sctp_send_shutdown(sctp, 1);
636*7c478bd9Sstevel@tonic-gate 		BUMP_MIB(&sctp_mib, sctpTimRetrans);
637*7c478bd9Sstevel@tonic-gate 		break;
638*7c478bd9Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_ACK_SENT:
639*7c478bd9Sstevel@tonic-gate 		/* We shouldn't have any more outstanding data */
640*7c478bd9Sstevel@tonic-gate 		ASSERT(sctp->sctp_xmit_head == NULL);
641*7c478bd9Sstevel@tonic-gate 		ASSERT(sctp->sctp_xmit_unsent == NULL);
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T2expire);
644*7c478bd9Sstevel@tonic-gate 		(void) sctp_shutdown_received(sctp, NULL, 0, 1);
645*7c478bd9Sstevel@tonic-gate 		BUMP_MIB(&sctp_mib, sctpTimRetrans);
646*7c478bd9Sstevel@tonic-gate 		break;
647*7c478bd9Sstevel@tonic-gate 	default:
648*7c478bd9Sstevel@tonic-gate 		ASSERT(0);
649*7c478bd9Sstevel@tonic-gate 		break;
650*7c478bd9Sstevel@tonic-gate 	}
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	fp->strikes++;
653*7c478bd9Sstevel@tonic-gate 	sctp->sctp_strikes++;
654*7c478bd9Sstevel@tonic-gate 	SCTP_CALC_RXT(fp, rto_max);
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto);
657*7c478bd9Sstevel@tonic-gate }
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate /*
660*7c478bd9Sstevel@tonic-gate  * RTO calculation. timesent and now are both in ms.
661*7c478bd9Sstevel@tonic-gate  */
662*7c478bd9Sstevel@tonic-gate void
663*7c478bd9Sstevel@tonic-gate sctp_update_rtt(sctp_t *sctp, sctp_faddr_t *fp, clock_t delta)
664*7c478bd9Sstevel@tonic-gate {
665*7c478bd9Sstevel@tonic-gate 	int rtt;
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	/* Calculate the RTT in ms */
668*7c478bd9Sstevel@tonic-gate 	rtt = (int)delta;
669*7c478bd9Sstevel@tonic-gate 	rtt = rtt > 0 ? rtt : 1;
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	dprint(5, ("sctp_update_rtt: fp = %p, rtt = %d\n", fp, rtt));
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	/* Is this the first RTT measurement? */
674*7c478bd9Sstevel@tonic-gate 	if (fp->srtt == -1) {
675*7c478bd9Sstevel@tonic-gate 		fp->srtt = rtt;
676*7c478bd9Sstevel@tonic-gate 		fp->rttvar = rtt / 2;
677*7c478bd9Sstevel@tonic-gate 		fp->rto = 3 * rtt; /* == rtt + 4 * rttvar ( == rtt / 2) */
678*7c478bd9Sstevel@tonic-gate 	} else {
679*7c478bd9Sstevel@tonic-gate 		int abs;
680*7c478bd9Sstevel@tonic-gate 		/*
681*7c478bd9Sstevel@tonic-gate 		 * Versions of the RTO equations that use fixed-point math.
682*7c478bd9Sstevel@tonic-gate 		 * alpha and beta are NOT tunable in this implementation,
683*7c478bd9Sstevel@tonic-gate 		 * and so are hard-coded in. alpha = 1/8, beta = 1/4.
684*7c478bd9Sstevel@tonic-gate 		 */
685*7c478bd9Sstevel@tonic-gate 		abs = fp->srtt - rtt;
686*7c478bd9Sstevel@tonic-gate 		abs = abs >= 0 ? abs : -abs;
687*7c478bd9Sstevel@tonic-gate 		fp->rttvar = (3 * fp->rttvar + abs) >> 2;
688*7c478bd9Sstevel@tonic-gate 		fp->rttvar = fp->rttvar != 0 ? fp->rttvar : 1;
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate 		fp->srtt = (7 * fp->srtt + rtt) >> 3;
691*7c478bd9Sstevel@tonic-gate 		fp->rto = fp->srtt + 4 * fp->rttvar;
692*7c478bd9Sstevel@tonic-gate 	}
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	dprint(5, ("sctp_update_rtt: srtt = %d, rttvar = %d, rto = %d\n",
695*7c478bd9Sstevel@tonic-gate 	    fp->srtt, fp->rttvar, fp->rto));
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 	/* Bound the RTO by configured min and max values */
698*7c478bd9Sstevel@tonic-gate 	if (fp->rto < sctp->sctp_rto_min) {
699*7c478bd9Sstevel@tonic-gate 		fp->rto = sctp->sctp_rto_min;
700*7c478bd9Sstevel@tonic-gate 	}
701*7c478bd9Sstevel@tonic-gate 	if (fp->rto > sctp->sctp_rto_max) {
702*7c478bd9Sstevel@tonic-gate 		fp->rto = sctp->sctp_rto_max;
703*7c478bd9Sstevel@tonic-gate 	}
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	fp->rtt_updates++;
706*7c478bd9Sstevel@tonic-gate }
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate void
709*7c478bd9Sstevel@tonic-gate sctp_free_faddr_timers(sctp_t *sctp)
710*7c478bd9Sstevel@tonic-gate {
711*7c478bd9Sstevel@tonic-gate 	sctp_faddr_t *fp;
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) {
714*7c478bd9Sstevel@tonic-gate 		if (fp->timer_mp != NULL) {
715*7c478bd9Sstevel@tonic-gate 			sctp_timer_free(fp->timer_mp);
716*7c478bd9Sstevel@tonic-gate 			fp->timer_mp = NULL;
717*7c478bd9Sstevel@tonic-gate 			fp->timer_running = 0;
718*7c478bd9Sstevel@tonic-gate 		}
719*7c478bd9Sstevel@tonic-gate 		if (fp->rc_timer_mp != NULL) {
720*7c478bd9Sstevel@tonic-gate 			sctp_timer_free(fp->rc_timer_mp);
721*7c478bd9Sstevel@tonic-gate 			fp->rc_timer_mp = NULL;
722*7c478bd9Sstevel@tonic-gate 			fp->rc_timer_running = 0;
723*7c478bd9Sstevel@tonic-gate 		}
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate }
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate void
728*7c478bd9Sstevel@tonic-gate sctp_stop_faddr_timers(sctp_t *sctp)
729*7c478bd9Sstevel@tonic-gate {
730*7c478bd9Sstevel@tonic-gate 	sctp_faddr_t *fp;
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) {
733*7c478bd9Sstevel@tonic-gate 		SCTP_FADDR_TIMER_STOP(fp);
734*7c478bd9Sstevel@tonic-gate 		SCTP_FADDR_RC_TIMER_STOP(fp);
735*7c478bd9Sstevel@tonic-gate 	}
736*7c478bd9Sstevel@tonic-gate }
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate void
739*7c478bd9Sstevel@tonic-gate sctp_process_timer(sctp_t *sctp)
740*7c478bd9Sstevel@tonic-gate {
741*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	ASSERT(sctp->sctp_running);
744*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&sctp->sctp_lock));
745*7c478bd9Sstevel@tonic-gate 	while ((mp = sctp->sctp_timer_mp) != NULL) {
746*7c478bd9Sstevel@tonic-gate 		ASSERT(DB_TYPE(mp) == M_PCSIG);
747*7c478bd9Sstevel@tonic-gate 		/*
748*7c478bd9Sstevel@tonic-gate 		 * Since the timer mblk can be freed in sctp_timer_call(),
749*7c478bd9Sstevel@tonic-gate 		 * we need to grab the b_cont before that.
750*7c478bd9Sstevel@tonic-gate 		 */
751*7c478bd9Sstevel@tonic-gate 		sctp->sctp_timer_mp = mp->b_cont;
752*7c478bd9Sstevel@tonic-gate 		mp->b_cont = NULL;
753*7c478bd9Sstevel@tonic-gate 		sctp_timer_call(sctp, mp);
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 	SCTP_REFRELE(sctp);
756*7c478bd9Sstevel@tonic-gate }
757