xref: /onnv-gate/usr/src/uts/common/inet/sctp/sctp_timer.c (revision 13009:29fc56bd19a6)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211735Skcpoon 
220Sstevel@tonic-gate /*
2312474SGeorge.Shepherd@Sun.COM  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/systm.h>
280Sstevel@tonic-gate #include <sys/stream.h>
290Sstevel@tonic-gate #include <sys/cmn_err.h>
300Sstevel@tonic-gate #include <sys/strsubr.h>
310Sstevel@tonic-gate #include <sys/strsun.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <netinet/in.h>
340Sstevel@tonic-gate #include <netinet/ip6.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <inet/common.h>
370Sstevel@tonic-gate #include <inet/ip.h>
380Sstevel@tonic-gate #include <inet/mib2.h>
390Sstevel@tonic-gate #include <inet/ipclassifier.h>
400Sstevel@tonic-gate #include "sctp_impl.h"
410Sstevel@tonic-gate #include "sctp_asconf.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /* Timer block states. */
440Sstevel@tonic-gate typedef enum {
450Sstevel@tonic-gate 	SCTP_TB_RUNNING = 1,
460Sstevel@tonic-gate 	SCTP_TB_IDLE,
470Sstevel@tonic-gate /* Could not stop/free before mblk got queued */
480Sstevel@tonic-gate 	SCTP_TB_RESCHED,	/* sctp_tb_time_left contains tick count */
490Sstevel@tonic-gate 	SCTP_TB_CANCELLED,
500Sstevel@tonic-gate 	SCTP_TB_TO_BE_FREED
510Sstevel@tonic-gate } timer_block_state;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate typedef struct sctp_tb_s {
540Sstevel@tonic-gate 	timer_block_state	sctp_tb_state;
550Sstevel@tonic-gate 	timeout_id_t		sctp_tb_tid;
560Sstevel@tonic-gate 	mblk_t			*sctp_tb_mp;
570Sstevel@tonic-gate 	clock_t			sctp_tb_time_left;
580Sstevel@tonic-gate } sctp_tb_t;
590Sstevel@tonic-gate 
6012869SKacheong.Poon@Sun.COM /*
6112869SKacheong.Poon@Sun.COM  * Early abort threshold when the system is under pressure, sctps_reclaim
6212869SKacheong.Poon@Sun.COM  * is on.
6312869SKacheong.Poon@Sun.COM  *
6412869SKacheong.Poon@Sun.COM  * sctp_pa_early_abort: number of strikes per association before abort
6512869SKacheong.Poon@Sun.COM  * sctp_pp_early_abort: number of strikes per peer address before abort
6612869SKacheong.Poon@Sun.COM  */
6712869SKacheong.Poon@Sun.COM uint32_t sctp_pa_early_abort = 5;
6812869SKacheong.Poon@Sun.COM uint32_t sctp_pp_early_abort = 3;
6912869SKacheong.Poon@Sun.COM 
700Sstevel@tonic-gate static void sctp_timer_fire(sctp_tb_t *);
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate  *		sctp_timer mechanism.
740Sstevel@tonic-gate  *
750Sstevel@tonic-gate  * Each timer is represented by a timer mblk. When the
760Sstevel@tonic-gate  * timer fires, and the sctp_t is busy, the timer mblk will be put on
770Sstevel@tonic-gate  * the associated sctp_t timer queue so that it can be executed when
780Sstevel@tonic-gate  * the thread holding the lock on the sctp_t is done with its job.
790Sstevel@tonic-gate  *
800Sstevel@tonic-gate  * Note that there is no lock to protect the timer mblk state.  The reason
810Sstevel@tonic-gate  * is that the timer state can only be changed by a thread holding the
820Sstevel@tonic-gate  * lock on the sctp_t.
830Sstevel@tonic-gate  *
840Sstevel@tonic-gate  * The interface consists of 4 entry points:
850Sstevel@tonic-gate  *	sctp_timer_alloc	- create a timer mblk
860Sstevel@tonic-gate  *	sctp_timer_free		- free a timer mblk
870Sstevel@tonic-gate  *	sctp_timer		- start, restart, stop the timer
880Sstevel@tonic-gate  *	sctp_timer_valid	- called by sctp_process_recvq to verify that
890Sstevel@tonic-gate  *				  the timer did indeed fire.
900Sstevel@tonic-gate  */
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate  * Start, restart, stop the timer.
950Sstevel@tonic-gate  * If "tim" is -1 the timer is stopped.
960Sstevel@tonic-gate  * Otherwise, the timer is stopped if it is already running, and
970Sstevel@tonic-gate  * set to fire tim clock ticks from now.
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate void
sctp_timer(sctp_t * sctp,mblk_t * mp,clock_t tim)1000Sstevel@tonic-gate sctp_timer(sctp_t *sctp, mblk_t *mp, clock_t tim)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
1030Sstevel@tonic-gate 	int state;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	ASSERT(sctp != NULL && mp != NULL);
1060Sstevel@tonic-gate 	ASSERT((mp->b_rptr - mp->b_datap->db_base) == sizeof (sctp_tb_t));
1070Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
1100Sstevel@tonic-gate 	if (tim >= 0) {
1110Sstevel@tonic-gate 		state = sctp_tb->sctp_tb_state;
1120Sstevel@tonic-gate 		sctp_tb->sctp_tb_time_left = tim;
1130Sstevel@tonic-gate 		if (state == SCTP_TB_RUNNING) {
1140Sstevel@tonic-gate 			if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
1150Sstevel@tonic-gate 				sctp_tb->sctp_tb_state = SCTP_TB_RESCHED;
1160Sstevel@tonic-gate 				/* sctp_timer_valid will start timer */
1170Sstevel@tonic-gate 				return;
1180Sstevel@tonic-gate 			}
1190Sstevel@tonic-gate 		} else if (state != SCTP_TB_IDLE) {
1200Sstevel@tonic-gate 			ASSERT(state != SCTP_TB_TO_BE_FREED);
1210Sstevel@tonic-gate 			if (state == SCTP_TB_CANCELLED) {
1220Sstevel@tonic-gate 				sctp_tb->sctp_tb_state = SCTP_TB_RESCHED;
1230Sstevel@tonic-gate 				/* sctp_timer_valid will start timer */
1240Sstevel@tonic-gate 				return;
1250Sstevel@tonic-gate 			}
1260Sstevel@tonic-gate 			if (state == SCTP_TB_RESCHED) {
1270Sstevel@tonic-gate 				/* sctp_timer_valid will start timer */
1280Sstevel@tonic-gate 				return;
1290Sstevel@tonic-gate 			}
1300Sstevel@tonic-gate 		} else {
1310Sstevel@tonic-gate 			SCTP_REFHOLD(sctp);
1320Sstevel@tonic-gate 		}
1330Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_RUNNING;
1340Sstevel@tonic-gate 		sctp_tb->sctp_tb_tid =
1350Sstevel@tonic-gate 		    timeout((pfv_t)sctp_timer_fire, sctp_tb, tim);
1360Sstevel@tonic-gate 		return;
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 	switch (tim) {
1390Sstevel@tonic-gate 	case -1:
1400Sstevel@tonic-gate 		sctp_timer_stop(mp);
1410Sstevel@tonic-gate 		break;
1420Sstevel@tonic-gate 	default:
1430Sstevel@tonic-gate 		ASSERT(0);
1440Sstevel@tonic-gate 		break;
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate  * sctp_timer_alloc is called by sctp_init to allocate and initialize a
1500Sstevel@tonic-gate  * sctp timer.
1510Sstevel@tonic-gate  *
1520Sstevel@tonic-gate  * Allocate an M_PCSIG timer message. The space between db_base and
1530Sstevel@tonic-gate  * b_rptr is used by the sctp_timer mechanism, and after b_rptr there is
1540Sstevel@tonic-gate  * space for sctpt_t.
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate mblk_t *
sctp_timer_alloc(sctp_t * sctp,pfv_t func,int sleep)1574691Skcpoon sctp_timer_alloc(sctp_t *sctp, pfv_t func, int sleep)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate 	mblk_t *mp;
1600Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
1610Sstevel@tonic-gate 	sctpt_t	*sctpt;
1623448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
1630Sstevel@tonic-gate 
1644691Skcpoon 	if (sleep == KM_SLEEP) {
1654691Skcpoon 		mp = allocb_wait(sizeof (sctp_t) + sizeof (sctp_tb_t), BPRI_HI,
1664691Skcpoon 		    STR_NOSIG, NULL);
1674691Skcpoon 	} else {
1684691Skcpoon 		mp = allocb(sizeof (sctp_t) + sizeof (sctp_tb_t), BPRI_HI);
1694691Skcpoon 	}
1704691Skcpoon 	if (mp != NULL) {
1710Sstevel@tonic-gate 		mp->b_datap->db_type = M_PCSIG;
1720Sstevel@tonic-gate 		sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
1730Sstevel@tonic-gate 		mp->b_rptr = (uchar_t *)&sctp_tb[1];
1740Sstevel@tonic-gate 		mp->b_wptr = mp->b_rptr + sizeof (sctpt_t);
1750Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
1760Sstevel@tonic-gate 		sctp_tb->sctp_tb_mp = mp;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 		sctpt = (sctpt_t *)mp->b_rptr;
1790Sstevel@tonic-gate 		sctpt->sctpt_sctp = sctp;
1800Sstevel@tonic-gate 		sctpt->sctpt_faddr = NULL;	/* set when starting timer */
1810Sstevel@tonic-gate 		sctpt->sctpt_pfv = func;
1820Sstevel@tonic-gate 		return (mp);
1830Sstevel@tonic-gate 	}
1843448Sdh155122 	SCTP_KSTAT(sctps, sctp_add_timer);
1850Sstevel@tonic-gate 	return (NULL);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate  * timeout() callback function.
1900Sstevel@tonic-gate  * Put the message on the process control block's queue.
1910Sstevel@tonic-gate  * If the timer is stopped or freed after
1920Sstevel@tonic-gate  * it has fired then sctp_timer() and sctp_timer_valid() will clean
1930Sstevel@tonic-gate  * things up.
1940Sstevel@tonic-gate  */
1950Sstevel@tonic-gate static void
sctp_timer_fire(sctp_tb_t * sctp_tb)1960Sstevel@tonic-gate sctp_timer_fire(sctp_tb_t *sctp_tb)
1970Sstevel@tonic-gate {
1980Sstevel@tonic-gate 	mblk_t *mp;
1990Sstevel@tonic-gate 	sctp_t *sctp;
2000Sstevel@tonic-gate 	sctpt_t *sctpt;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	mp = sctp_tb->sctp_tb_mp;
2030Sstevel@tonic-gate 	ASSERT(sctp_tb == (sctp_tb_t *)mp->b_datap->db_base);
2040Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	sctpt = (sctpt_t *)mp->b_rptr;
2070Sstevel@tonic-gate 	sctp = sctpt->sctpt_sctp;
2080Sstevel@tonic-gate 	ASSERT(sctp != NULL);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	mutex_enter(&sctp->sctp_lock);
2110Sstevel@tonic-gate 	if (sctp->sctp_running) {
2120Sstevel@tonic-gate 		/*
2130Sstevel@tonic-gate 		 * Put the timer mblk to the special sctp_timer_mp list.
2140Sstevel@tonic-gate 		 * This timer will be handled when the thread using this
2150Sstevel@tonic-gate 		 * SCTP is done with its job.
2160Sstevel@tonic-gate 		 */
2170Sstevel@tonic-gate 		if (sctp->sctp_timer_mp == NULL) {
2180Sstevel@tonic-gate 			SCTP_REFHOLD(sctp);
2190Sstevel@tonic-gate 			sctp->sctp_timer_mp = mp;
2200Sstevel@tonic-gate 		} else {
2210Sstevel@tonic-gate 			linkb(sctp->sctp_timer_mp, mp);
2220Sstevel@tonic-gate 		}
2230Sstevel@tonic-gate 		mp->b_cont = NULL;
2240Sstevel@tonic-gate 		mutex_exit(&sctp->sctp_lock);
2250Sstevel@tonic-gate 	} else {
2260Sstevel@tonic-gate 		sctp->sctp_running = B_TRUE;
2270Sstevel@tonic-gate 		mutex_exit(&sctp->sctp_lock);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 		sctp_timer_call(sctp, mp);
2300Sstevel@tonic-gate 		WAKE_SCTP(sctp);
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate 	SCTP_REFRELE(sctp);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate /*
2360Sstevel@tonic-gate  * Logically free a timer mblk (that might have a pending timeout().)
2370Sstevel@tonic-gate  * If the timer has fired and the mblk has been put on the queue then
2380Sstevel@tonic-gate  * sctp_timer_valid will free the mblk.
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate void
sctp_timer_free(mblk_t * mp)2410Sstevel@tonic-gate sctp_timer_free(mblk_t *mp)
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
2440Sstevel@tonic-gate 	int state;
2450Sstevel@tonic-gate 	sctpt_t *sctpt;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	ASSERT(mp != NULL);
2480Sstevel@tonic-gate 	ASSERT((mp->b_rptr - mp->b_datap->db_base) == sizeof (sctp_tb_t));
2490Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
2520Sstevel@tonic-gate 	state = sctp_tb->sctp_tb_state;
2530Sstevel@tonic-gate 
2541676Sjpk 	dprint(5, ("sctp_timer_free %p state %d\n", (void *)mp, state));
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	if (state == SCTP_TB_RUNNING) {
2570Sstevel@tonic-gate 		if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
2580Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_TO_BE_FREED;
2590Sstevel@tonic-gate 			/* sctp_timer_valid will free the mblk */
2600Sstevel@tonic-gate 			return;
2610Sstevel@tonic-gate 		}
2620Sstevel@tonic-gate 		sctpt = (sctpt_t *)mp->b_rptr;
2630Sstevel@tonic-gate 		SCTP_REFRELE(sctpt->sctpt_sctp);
2640Sstevel@tonic-gate 	} else if (state != SCTP_TB_IDLE) {
2650Sstevel@tonic-gate 		ASSERT(state != SCTP_TB_TO_BE_FREED);
2660Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_TO_BE_FREED;
2670Sstevel@tonic-gate 		/* sctp_timer_valid will free the mblk */
2680Sstevel@tonic-gate 		return;
2690Sstevel@tonic-gate 	}
2700Sstevel@tonic-gate 	freeb(mp);
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate /*
2740Sstevel@tonic-gate  * Called from sctp_timer(,,-1)
2750Sstevel@tonic-gate  */
2760Sstevel@tonic-gate void
sctp_timer_stop(mblk_t * mp)2770Sstevel@tonic-gate sctp_timer_stop(mblk_t *mp)
2780Sstevel@tonic-gate {
2790Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
2800Sstevel@tonic-gate 	int state;
2810Sstevel@tonic-gate 	sctpt_t *sctpt;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	ASSERT(mp != NULL);
2840Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
2870Sstevel@tonic-gate 	state = sctp_tb->sctp_tb_state;
2880Sstevel@tonic-gate 
2891676Sjpk 	dprint(5, ("sctp_timer_stop %p %d\n", (void *)mp, state));
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	if (state == SCTP_TB_RUNNING) {
2920Sstevel@tonic-gate 		if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
2930Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_CANCELLED;
2940Sstevel@tonic-gate 		} else {
2950Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
2960Sstevel@tonic-gate 			sctpt = (sctpt_t *)mp->b_rptr;
2970Sstevel@tonic-gate 			SCTP_REFRELE(sctpt->sctpt_sctp);
2980Sstevel@tonic-gate 		}
2990Sstevel@tonic-gate 	} else if (state == SCTP_TB_RESCHED) {
3000Sstevel@tonic-gate 		sctp_tb->sctp_tb_state = SCTP_TB_CANCELLED;
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate  * The user of the sctp_timer mechanism is required to call
3060Sstevel@tonic-gate  * sctp_timer_valid() for each M_PCSIG message processed in the
3070Sstevel@tonic-gate  * service procedures.
3080Sstevel@tonic-gate  * sctp_timer_valid will return "true" if the timer actually did fire.
3090Sstevel@tonic-gate  */
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate static boolean_t
sctp_timer_valid(mblk_t * mp)3120Sstevel@tonic-gate sctp_timer_valid(mblk_t *mp)
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate 	sctp_tb_t *sctp_tb;
3150Sstevel@tonic-gate 	int state;
3160Sstevel@tonic-gate 	sctpt_t *sctpt;
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	ASSERT(mp != NULL);
3190Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_type == M_PCSIG);
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 	sctp_tb = (sctp_tb_t *)DB_BASE(mp);
3220Sstevel@tonic-gate 	sctpt = (sctpt_t *)mp->b_rptr;
3230Sstevel@tonic-gate 	state = sctp_tb->sctp_tb_state;
3240Sstevel@tonic-gate 	if (state != SCTP_TB_RUNNING) {
3250Sstevel@tonic-gate 		ASSERT(state != SCTP_TB_IDLE);
3260Sstevel@tonic-gate 		if (state == SCTP_TB_TO_BE_FREED) {
3270Sstevel@tonic-gate 			/*
3280Sstevel@tonic-gate 			 * sctp_timer_free was called after the message
3290Sstevel@tonic-gate 			 * was putq'ed.
3300Sstevel@tonic-gate 			 */
3310Sstevel@tonic-gate 			freeb(mp);
3320Sstevel@tonic-gate 			return (B_FALSE);
3330Sstevel@tonic-gate 		}
3340Sstevel@tonic-gate 		if (state == SCTP_TB_CANCELLED) {
3350Sstevel@tonic-gate 			/* The timer was stopped after the mblk was putq'ed */
3360Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
3370Sstevel@tonic-gate 			return (B_FALSE);
3380Sstevel@tonic-gate 		}
3390Sstevel@tonic-gate 		if (state == SCTP_TB_RESCHED) {
3400Sstevel@tonic-gate 			/*
3410Sstevel@tonic-gate 			 * The timer was stopped and then restarted after
3420Sstevel@tonic-gate 			 * the mblk was putq'ed.
3430Sstevel@tonic-gate 			 * sctp_tb_time_left contains the number of ticks that
3440Sstevel@tonic-gate 			 * the timer was restarted with.
3450Sstevel@tonic-gate 			 * The sctp will not be disapper between the time
3460Sstevel@tonic-gate 			 * the sctpt_t is marked SCTP_TB_RESCHED and when
3470Sstevel@tonic-gate 			 * we get here as sctp_add_recvq() does a refhold.
3480Sstevel@tonic-gate 			 */
3490Sstevel@tonic-gate 			sctp_tb->sctp_tb_state = SCTP_TB_RUNNING;
3500Sstevel@tonic-gate 			sctp_tb->sctp_tb_tid = timeout((pfv_t)sctp_timer_fire,
3510Sstevel@tonic-gate 			    sctp_tb, sctp_tb->sctp_tb_time_left);
3520Sstevel@tonic-gate 			SCTP_REFHOLD(sctpt->sctpt_sctp);
3530Sstevel@tonic-gate 			return (B_FALSE);
3540Sstevel@tonic-gate 		}
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 	sctp_tb->sctp_tb_state = SCTP_TB_IDLE;
3570Sstevel@tonic-gate 	return (B_TRUE);
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate  * The SCTP timer call. Calls sctp_timer_valid() to verify whether
3620Sstevel@tonic-gate  * timer was cancelled or not.
3630Sstevel@tonic-gate  */
3640Sstevel@tonic-gate void
sctp_timer_call(sctp_t * sctp,mblk_t * mp)3650Sstevel@tonic-gate sctp_timer_call(sctp_t *sctp, mblk_t *mp)
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate 	sctpt_t *sctpt = (sctpt_t *)mp->b_rptr;
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	if (sctp_timer_valid(mp)) {
3700Sstevel@tonic-gate 		(*sctpt->sctpt_pfv)(sctp, sctpt->sctpt_faddr);
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate  * Delayed ack
3760Sstevel@tonic-gate  */
3770Sstevel@tonic-gate void
sctp_ack_timer(sctp_t * sctp)3780Sstevel@tonic-gate sctp_ack_timer(sctp_t *sctp)
3790Sstevel@tonic-gate {
3803448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
3813448Sdh155122 
3820Sstevel@tonic-gate 	sctp->sctp_ack_timer_running = 0;
3833448Sdh155122 	sctp->sctp_sack_toggle = sctps->sctps_deferred_acks_max;
38412869SKacheong.Poon@Sun.COM 	SCTPS_BUMP_MIB(sctps, sctpOutAckDelayed);
3854964Skcpoon 	(void) sctp_sack(sctp, NULL);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate /*
3890Sstevel@tonic-gate  * Peer address heartbeat timer handler
3900Sstevel@tonic-gate  */
3910Sstevel@tonic-gate void
sctp_heartbeat_timer(sctp_t * sctp)3920Sstevel@tonic-gate sctp_heartbeat_timer(sctp_t *sctp)
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate 	sctp_faddr_t	*fp;
3950Sstevel@tonic-gate 	int64_t		now;
3960Sstevel@tonic-gate 	int64_t		earliest_expiry;
3970Sstevel@tonic-gate 	int		cnt;
3983448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
39912869SKacheong.Poon@Sun.COM 	int		pp_max_retr;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) {
4020Sstevel@tonic-gate 		/*
40312869SKacheong.Poon@Sun.COM 		 * If there is a peer address with no strikes, don't give up
40412869SKacheong.Poon@Sun.COM 		 * yet unless we are under memory pressure.  If enough other
40512869SKacheong.Poon@Sun.COM 		 * peer  address are down, we could otherwise fail the
40612869SKacheong.Poon@Sun.COM 		 * association prematurely.  This is a byproduct of our
40712869SKacheong.Poon@Sun.COM 		 * aggressive probe approach when a heartbeat fails to
40812869SKacheong.Poon@Sun.COM 		 * connect. We may wish to revisit this...
4090Sstevel@tonic-gate 		 */
41012869SKacheong.Poon@Sun.COM 		if (sctps->sctps_reclaim || !sctp_is_a_faddr_clean(sctp)) {
4110Sstevel@tonic-gate 			/* time to give up */
41212869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpAborted);
41312869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpTimHeartBeatDrop);
4140Sstevel@tonic-gate 			sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
4150Sstevel@tonic-gate 			sctp_clean_death(sctp, sctp->sctp_client_errno ?
4160Sstevel@tonic-gate 			    sctp->sctp_client_errno : ETIMEDOUT);
4170Sstevel@tonic-gate 			return;
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/* Only send heartbeats in the established state */
4220Sstevel@tonic-gate 	if (sctp->sctp_state != SCTPS_ESTABLISHED) {
4230Sstevel@tonic-gate 		dprint(5, ("sctp_heartbeat_timer: not in ESTABLISHED\n"));
4240Sstevel@tonic-gate 		return;
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 
42711066Srafael.vanoni@sun.com 	now = ddi_get_lbolt64();
4280Sstevel@tonic-gate 	earliest_expiry = 0;
4293448Sdh155122 	cnt = sctps->sctps_maxburst;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	/*
4320Sstevel@tonic-gate 	 * Walk through all faddrs.  Since the timer should run infrequently
4330Sstevel@tonic-gate 	 * and the number of peer addresses should not be big, this should
4340Sstevel@tonic-gate 	 * be OK.
4350Sstevel@tonic-gate 	 */
436*13009SChandrasekar.Marimuthu@Sun.COM 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
43712869SKacheong.Poon@Sun.COM 		if (sctps->sctps_reclaim)
438*13009SChandrasekar.Marimuthu@Sun.COM 			pp_max_retr = MIN(sctp_pp_early_abort, fp->sf_max_retr);
43912869SKacheong.Poon@Sun.COM 		else
440*13009SChandrasekar.Marimuthu@Sun.COM 			pp_max_retr = fp->sf_max_retr;
44112869SKacheong.Poon@Sun.COM 
4420Sstevel@tonic-gate 		/*
4434818Skcpoon 		 * If the peer is unreachable because there is no available
44411042SErik.Nordmark@Sun.COM 		 * source address, call sctp_get_dest() to see if it is
4454818Skcpoon 		 * reachable now.  If it is OK, the state will become
4464818Skcpoon 		 * unconfirmed.  And the following code to handle unconfirmed
4474818Skcpoon 		 * address will be executed.  If it is still not OK,
4484818Skcpoon 		 * re-schedule.  If heartbeat is enabled, only try this
4494818Skcpoon 		 * up to the normal heartbeat max times.  But if heartbeat
4504818Skcpoon 		 * is disable, this retry may go on forever.
4510Sstevel@tonic-gate 		 */
452*13009SChandrasekar.Marimuthu@Sun.COM 		if (fp->sf_state == SCTP_FADDRS_UNREACH) {
45311042SErik.Nordmark@Sun.COM 			sctp_get_dest(sctp, fp);
454*13009SChandrasekar.Marimuthu@Sun.COM 			if (fp->sf_state == SCTP_FADDRS_UNREACH) {
455*13009SChandrasekar.Marimuthu@Sun.COM 				if (fp->sf_hb_enabled &&
456*13009SChandrasekar.Marimuthu@Sun.COM 				    ++fp->sf_strikes > pp_max_retr &&
4574818Skcpoon 				    sctp_faddr_dead(sctp, fp,
4584818Skcpoon 				    SCTP_FADDRS_DOWN) == -1) {
4594818Skcpoon 					/* Assoc is dead */
4604818Skcpoon 					return;
4614818Skcpoon 				}
462*13009SChandrasekar.Marimuthu@Sun.COM 				fp->sf_hb_expiry = now + SET_HB_INTVL(fp);
4634818Skcpoon 				goto set_expiry;
4644818Skcpoon 			} else {
4654818Skcpoon 				/* Send a heartbeat immediately. */
466*13009SChandrasekar.Marimuthu@Sun.COM 				fp->sf_hb_expiry = now;
4674818Skcpoon 			}
4684818Skcpoon 		}
4694818Skcpoon 		/*
4704818Skcpoon 		 * Don't send heartbeat to this address if it is not
4714818Skcpoon 		 * hb_enabled and the address has been confirmed.
4724818Skcpoon 		 */
473*13009SChandrasekar.Marimuthu@Sun.COM 		if (!fp->sf_hb_enabled && fp->sf_state !=
474*13009SChandrasekar.Marimuthu@Sun.COM 		    SCTP_FADDRS_UNCONFIRMED) {
4750Sstevel@tonic-gate 			continue;
4760Sstevel@tonic-gate 		}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 		/*
4790Sstevel@tonic-gate 		 * The heartbeat timer is expired.  If the address is dead,
4800Sstevel@tonic-gate 		 * we still send heartbeat to it in case it becomes alive
4814818Skcpoon 		 * again.  But we will only send once in a while, calculated
4824818Skcpoon 		 * by SET_HB_INTVL().
4830Sstevel@tonic-gate 		 *
4840Sstevel@tonic-gate 		 * If the address is alive and there is a hearbeat pending,
4850Sstevel@tonic-gate 		 * resend the heartbeat and start exponential backoff on the
4860Sstevel@tonic-gate 		 * heartbeat timeout value.  If there is no heartbeat pending,
4870Sstevel@tonic-gate 		 * just send out one.
4880Sstevel@tonic-gate 		 */
489*13009SChandrasekar.Marimuthu@Sun.COM 		if (now >= fp->sf_hb_expiry) {
490*13009SChandrasekar.Marimuthu@Sun.COM 			if (fp->sf_hb_pending) {
4910Sstevel@tonic-gate 				/*
4920Sstevel@tonic-gate 				 * If an address is not confirmed, no need
4930Sstevel@tonic-gate 				 * to bump the overall counter as it doesn't
4940Sstevel@tonic-gate 				 * matter as we will not use it to send data
4950Sstevel@tonic-gate 				 * and it should not affect the association.
4960Sstevel@tonic-gate 				 */
497*13009SChandrasekar.Marimuthu@Sun.COM 				switch (fp->sf_state) {
4980Sstevel@tonic-gate 				case SCTP_FADDRS_ALIVE:
4990Sstevel@tonic-gate 					sctp->sctp_strikes++;
5000Sstevel@tonic-gate 					/* FALLTHRU */
5010Sstevel@tonic-gate 				case SCTP_FADDRS_UNCONFIRMED:
5020Sstevel@tonic-gate 					/*
5030Sstevel@tonic-gate 					 * Retransmission implies that RTO
5040Sstevel@tonic-gate 					 * is probably not correct.
5050Sstevel@tonic-gate 					 */
506*13009SChandrasekar.Marimuthu@Sun.COM 					fp->sf_rtt_updates = 0;
507*13009SChandrasekar.Marimuthu@Sun.COM 					fp->sf_strikes++;
508*13009SChandrasekar.Marimuthu@Sun.COM 					if (fp->sf_strikes > pp_max_retr) {
5090Sstevel@tonic-gate 						if (sctp_faddr_dead(sctp, fp,
5100Sstevel@tonic-gate 						    SCTP_FADDRS_DOWN) == -1) {
5110Sstevel@tonic-gate 							/* Assoc is dead */
5120Sstevel@tonic-gate 							return;
5130Sstevel@tonic-gate 						}
5140Sstevel@tonic-gate 						/*
5150Sstevel@tonic-gate 						 * Addr is down; keep initial
5160Sstevel@tonic-gate 						 * RTO
5170Sstevel@tonic-gate 						 */
518*13009SChandrasekar.Marimuthu@Sun.COM 						fp->sf_rto =
5190Sstevel@tonic-gate 						    sctp->sctp_rto_initial;
5200Sstevel@tonic-gate 						goto dead_addr;
5210Sstevel@tonic-gate 					} else {
52212474SGeorge.Shepherd@Sun.COM 						SCTP_CALC_RXT(sctp, fp,
52312474SGeorge.Shepherd@Sun.COM 						    sctp->sctp_rto_max);
524*13009SChandrasekar.Marimuthu@Sun.COM 						fp->sf_hb_expiry = now +
525*13009SChandrasekar.Marimuthu@Sun.COM 						    fp->sf_rto;
5260Sstevel@tonic-gate 					}
5270Sstevel@tonic-gate 					break;
5280Sstevel@tonic-gate 				case SCTP_FADDRS_DOWN:
5290Sstevel@tonic-gate dead_addr:
530*13009SChandrasekar.Marimuthu@Sun.COM 					fp->sf_hb_expiry = now +
531*13009SChandrasekar.Marimuthu@Sun.COM 					    SET_HB_INTVL(fp);
5320Sstevel@tonic-gate 					break;
5330Sstevel@tonic-gate 				default:
5340Sstevel@tonic-gate 					continue;
5350Sstevel@tonic-gate 				}
5360Sstevel@tonic-gate 			} else {
5374818Skcpoon 				/*
5384818Skcpoon 				 * If there is unack'ed data, no need to
5394818Skcpoon 				 * send a heart beat.
5404818Skcpoon 				 */
541*13009SChandrasekar.Marimuthu@Sun.COM 				if (fp->sf_suna > 0) {
542*13009SChandrasekar.Marimuthu@Sun.COM 					fp->sf_hb_expiry = now +
543*13009SChandrasekar.Marimuthu@Sun.COM 					    SET_HB_INTVL(fp);
5444818Skcpoon 					goto set_expiry;
5454818Skcpoon 				} else {
546*13009SChandrasekar.Marimuthu@Sun.COM 					fp->sf_hb_expiry = now + fp->sf_rto;
5474818Skcpoon 				}
5480Sstevel@tonic-gate 			}
5490Sstevel@tonic-gate 			/*
5500Sstevel@tonic-gate 			 * Note that the total number of heartbeat we can send
5510Sstevel@tonic-gate 			 * out simultaneously is limited by sctp_maxburst.  If
5520Sstevel@tonic-gate 			 * the limit is exceeded, we need to wait for the next
5530Sstevel@tonic-gate 			 * timeout to send them.  This should only happen if
5540Sstevel@tonic-gate 			 * there is unconfirmed address.  Note that hb_pending
5550Sstevel@tonic-gate 			 * is set in sctp_send_heartbeat().  So if a heartbeat
5560Sstevel@tonic-gate 			 * is not sent, it will not affect the state of the
5570Sstevel@tonic-gate 			 * peer address.
5580Sstevel@tonic-gate 			 */
559*13009SChandrasekar.Marimuthu@Sun.COM 			if (fp->sf_state != SCTP_FADDRS_UNCONFIRMED ||
560*13009SChandrasekar.Marimuthu@Sun.COM 			    cnt-- > 0)
5610Sstevel@tonic-gate 				sctp_send_heartbeat(sctp, fp);
5620Sstevel@tonic-gate 		}
5634818Skcpoon set_expiry:
564*13009SChandrasekar.Marimuthu@Sun.COM 		if (fp->sf_hb_expiry < earliest_expiry || earliest_expiry == 0)
565*13009SChandrasekar.Marimuthu@Sun.COM 			earliest_expiry = fp->sf_hb_expiry;
5660Sstevel@tonic-gate 	}
5670Sstevel@tonic-gate 	if (sctp->sctp_autoclose != 0) {
5680Sstevel@tonic-gate 		int64_t expire;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 		expire = sctp->sctp_active + sctp->sctp_autoclose;
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 		if (expire <= now) {
5730Sstevel@tonic-gate 			dprint(3, ("sctp_heartbeat_timer: autoclosing\n"));
5740Sstevel@tonic-gate 			sctp_send_shutdown(sctp, 0);
5750Sstevel@tonic-gate 			return;
5760Sstevel@tonic-gate 		}
5770Sstevel@tonic-gate 		if (expire < earliest_expiry || earliest_expiry == 0)
5780Sstevel@tonic-gate 			earliest_expiry = expire;
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	earliest_expiry -= now;
5820Sstevel@tonic-gate 	if (earliest_expiry < 0)
5830Sstevel@tonic-gate 		earliest_expiry = 1;
5840Sstevel@tonic-gate 	sctp_timer(sctp, sctp->sctp_heartbeat_mp, earliest_expiry);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate void
sctp_rexmit_timer(sctp_t * sctp,sctp_faddr_t * fp)5880Sstevel@tonic-gate sctp_rexmit_timer(sctp_t *sctp, sctp_faddr_t *fp)
5890Sstevel@tonic-gate {
5900Sstevel@tonic-gate 	mblk_t 		*mp;
59112474SGeorge.Shepherd@Sun.COM 	uint32_t	rto_max = sctp->sctp_rto_max;
5923448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
59312869SKacheong.Poon@Sun.COM 	int		pp_max_retr, pa_max_retr;
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	ASSERT(fp != NULL);
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	dprint(3, ("sctp_timer: faddr=%x:%x:%x:%x\n",
598*13009SChandrasekar.Marimuthu@Sun.COM 	    SCTP_PRINTADDR(fp->sf_faddr)));
5990Sstevel@tonic-gate 
600*13009SChandrasekar.Marimuthu@Sun.COM 	fp->sf_timer_running = 0;
6010Sstevel@tonic-gate 
60212869SKacheong.Poon@Sun.COM 	if (!sctps->sctps_reclaim) {
603*13009SChandrasekar.Marimuthu@Sun.COM 		pp_max_retr = fp->sf_max_retr;
60412869SKacheong.Poon@Sun.COM 		pa_max_retr = sctp->sctp_pa_max_rxt;
60512869SKacheong.Poon@Sun.COM 	} else {
60612869SKacheong.Poon@Sun.COM 		/* App may have set a very aggressive retransmission limit. */
607*13009SChandrasekar.Marimuthu@Sun.COM 		pp_max_retr = MIN(sctp_pp_early_abort, fp->sf_max_retr);
60812869SKacheong.Poon@Sun.COM 		pa_max_retr = MIN(sctp_pa_early_abort, sctp->sctp_pa_max_rxt);
60912869SKacheong.Poon@Sun.COM 	}
61012869SKacheong.Poon@Sun.COM 
6110Sstevel@tonic-gate 	/* Check is we've reached the max for retries */
6120Sstevel@tonic-gate 	if (sctp->sctp_state < SCTPS_ESTABLISHED) {
613*13009SChandrasekar.Marimuthu@Sun.COM 		if (fp->sf_strikes >= sctp->sctp_max_init_rxt) {
6140Sstevel@tonic-gate 			/* time to give up */
61512869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpAborted);
61612869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpTimRetransDrop);
6170Sstevel@tonic-gate 			sctp_assoc_event(sctp, SCTP_CANT_STR_ASSOC, 0, NULL);
6180Sstevel@tonic-gate 			sctp_clean_death(sctp, sctp->sctp_client_errno ?
6190Sstevel@tonic-gate 			    sctp->sctp_client_errno : ETIMEDOUT);
6200Sstevel@tonic-gate 			return;
6210Sstevel@tonic-gate 		}
6220Sstevel@tonic-gate 	} else if (sctp->sctp_state >= SCTPS_ESTABLISHED) {
62312869SKacheong.Poon@Sun.COM 		if (sctp->sctp_strikes >= pa_max_retr) {
6240Sstevel@tonic-gate 			/* time to give up */
62512869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpAborted);
62612869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpTimRetransDrop);
6270Sstevel@tonic-gate 			sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
6280Sstevel@tonic-gate 			sctp_clean_death(sctp, sctp->sctp_client_errno ?
6290Sstevel@tonic-gate 			    sctp->sctp_client_errno : ETIMEDOUT);
6300Sstevel@tonic-gate 			return;
6310Sstevel@tonic-gate 		}
6320Sstevel@tonic-gate 	}
6330Sstevel@tonic-gate 
634*13009SChandrasekar.Marimuthu@Sun.COM 	if (fp->sf_strikes >= pp_max_retr) {
6350Sstevel@tonic-gate 		if (sctp_faddr_dead(sctp, fp, SCTP_FADDRS_DOWN) == -1) {
6360Sstevel@tonic-gate 			return;
6370Sstevel@tonic-gate 		}
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	switch (sctp->sctp_state) {
6414818Skcpoon 	case SCTPS_SHUTDOWN_RECEIVED:
6424818Skcpoon 		(void) sctp_shutdown_received(sctp, NULL, B_FALSE, B_TRUE,
6434818Skcpoon 		    NULL);
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 		/* FALLTHRU */
6464818Skcpoon 	case SCTPS_ESTABLISHED:
6470Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_PENDING:
6480Sstevel@tonic-gate 		if (sctp->sctp_xmit_head == NULL &&
6490Sstevel@tonic-gate 		    sctp->sctp_xmit_unsent == NULL) {
6500Sstevel@tonic-gate 			/* Nothing to retransmit */
6510Sstevel@tonic-gate 			if (sctp->sctp_state == SCTPS_SHUTDOWN_PENDING) {
6520Sstevel@tonic-gate 				sctp_send_shutdown(sctp, 1);
6530Sstevel@tonic-gate 			}
6540Sstevel@tonic-gate 			return;
6550Sstevel@tonic-gate 		}
6560Sstevel@tonic-gate 
65712869SKacheong.Poon@Sun.COM 		SCTPS_BUMP_MIB(sctps, sctpTimRetrans);
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 		sctp_rexmit(sctp, fp);
6600Sstevel@tonic-gate 		/*
6610Sstevel@tonic-gate 		 * sctp_rexmit() will increase the strikes and restart the
6620Sstevel@tonic-gate 		 * timer, so return here.
6630Sstevel@tonic-gate 		 */
6640Sstevel@tonic-gate 		return;
6650Sstevel@tonic-gate 	case SCTPS_COOKIE_WAIT:
6660Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T1expire);
6670Sstevel@tonic-gate rxmit_init:
6680Sstevel@tonic-gate 		/* retransmit init */
669432Svi117747 		/*
670432Svi117747 		 * We don't take the conn hash lock here since the source
671432Svi117747 		 * address list won't be modified (it would have been done
672432Svi117747 		 * the first time around).
673432Svi117747 		 */
67411042SErik.Nordmark@Sun.COM 		mp = sctp_init_mp(sctp, fp);
6750Sstevel@tonic-gate 		if (mp != NULL) {
67612869SKacheong.Poon@Sun.COM 			SCTPS_BUMP_MIB(sctps, sctpTimRetrans);
677*13009SChandrasekar.Marimuthu@Sun.COM 			(void) conn_ip_output(mp, fp->sf_ixa);
67811042SErik.Nordmark@Sun.COM 			BUMP_LOCAL(sctp->sctp_opkts);
6790Sstevel@tonic-gate 		}
68012474SGeorge.Shepherd@Sun.COM 		rto_max = sctp->sctp_rto_max_init;
6810Sstevel@tonic-gate 		break;
68211042SErik.Nordmark@Sun.COM 	case SCTPS_COOKIE_ECHOED:
6830Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T1expire);
6840Sstevel@tonic-gate 		if (sctp->sctp_cookie_mp == NULL) {
6850Sstevel@tonic-gate 			sctp->sctp_state = SCTPS_COOKIE_WAIT;
6860Sstevel@tonic-gate 			goto rxmit_init;
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 		mp = dupmsg(sctp->sctp_cookie_mp);
6890Sstevel@tonic-gate 		if (mp == NULL)
6900Sstevel@tonic-gate 			break;
691*13009SChandrasekar.Marimuthu@Sun.COM 		(void) conn_ip_output(mp, fp->sf_ixa);
69211042SErik.Nordmark@Sun.COM 		BUMP_LOCAL(sctp->sctp_opkts);
69312869SKacheong.Poon@Sun.COM 		SCTPS_BUMP_MIB(sctps, sctpTimRetrans);
69412474SGeorge.Shepherd@Sun.COM 		rto_max = sctp->sctp_rto_max_init;
6950Sstevel@tonic-gate 		break;
6960Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_SENT:
6970Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T2expire);
6980Sstevel@tonic-gate 		sctp_send_shutdown(sctp, 1);
69912869SKacheong.Poon@Sun.COM 		SCTPS_BUMP_MIB(sctps, sctpTimRetrans);
7000Sstevel@tonic-gate 		break;
7010Sstevel@tonic-gate 	case SCTPS_SHUTDOWN_ACK_SENT:
7020Sstevel@tonic-gate 		/* We shouldn't have any more outstanding data */
7030Sstevel@tonic-gate 		ASSERT(sctp->sctp_xmit_head == NULL);
7040Sstevel@tonic-gate 		ASSERT(sctp->sctp_xmit_unsent == NULL);
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 		BUMP_LOCAL(sctp->sctp_T2expire);
7071735Skcpoon 		(void) sctp_shutdown_received(sctp, NULL, B_FALSE, B_TRUE,
7081735Skcpoon 		    NULL);
70912869SKacheong.Poon@Sun.COM 		SCTPS_BUMP_MIB(sctps, sctpTimRetrans);
7100Sstevel@tonic-gate 		break;
7110Sstevel@tonic-gate 	default:
7120Sstevel@tonic-gate 		ASSERT(0);
7130Sstevel@tonic-gate 		break;
7140Sstevel@tonic-gate 	}
7150Sstevel@tonic-gate 
716*13009SChandrasekar.Marimuthu@Sun.COM 	fp->sf_strikes++;
7170Sstevel@tonic-gate 	sctp->sctp_strikes++;
71812474SGeorge.Shepherd@Sun.COM 	SCTP_CALC_RXT(sctp, fp, rto_max);
7190Sstevel@tonic-gate 
720*13009SChandrasekar.Marimuthu@Sun.COM 	SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->sf_rto);
7210Sstevel@tonic-gate }
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate /*
7240Sstevel@tonic-gate  * RTO calculation. timesent and now are both in ms.
7250Sstevel@tonic-gate  */
7260Sstevel@tonic-gate void
sctp_update_rtt(sctp_t * sctp,sctp_faddr_t * fp,clock_t delta)7270Sstevel@tonic-gate sctp_update_rtt(sctp_t *sctp, sctp_faddr_t *fp, clock_t delta)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate 	int rtt;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 	/* Calculate the RTT in ms */
7320Sstevel@tonic-gate 	rtt = (int)delta;
7330Sstevel@tonic-gate 	rtt = rtt > 0 ? rtt : 1;
7340Sstevel@tonic-gate 
7351676Sjpk 	dprint(5, ("sctp_update_rtt: fp = %p, rtt = %d\n", (void *)fp, rtt));
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	/* Is this the first RTT measurement? */
738*13009SChandrasekar.Marimuthu@Sun.COM 	if (fp->sf_srtt == -1) {
739*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_srtt = rtt;
740*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rttvar = rtt / 2;
741*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rto = 3 * rtt; /* == rtt + 4 * rttvar ( == rtt / 2) */
7420Sstevel@tonic-gate 	} else {
7430Sstevel@tonic-gate 		int abs;
7440Sstevel@tonic-gate 		/*
7450Sstevel@tonic-gate 		 * Versions of the RTO equations that use fixed-point math.
7460Sstevel@tonic-gate 		 * alpha and beta are NOT tunable in this implementation,
7470Sstevel@tonic-gate 		 * and so are hard-coded in. alpha = 1/8, beta = 1/4.
7480Sstevel@tonic-gate 		 */
749*13009SChandrasekar.Marimuthu@Sun.COM 		abs = fp->sf_srtt - rtt;
7500Sstevel@tonic-gate 		abs = abs >= 0 ? abs : -abs;
751*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rttvar = (3 * fp->sf_rttvar + abs) >> 2;
752*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rttvar = fp->sf_rttvar != 0 ? fp->sf_rttvar : 1;
7530Sstevel@tonic-gate 
754*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_srtt = (7 * fp->sf_srtt + rtt) >> 3;
755*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rto = fp->sf_srtt + 4 * fp->sf_rttvar;
7560Sstevel@tonic-gate 	}
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	dprint(5, ("sctp_update_rtt: srtt = %d, rttvar = %d, rto = %d\n",
759*13009SChandrasekar.Marimuthu@Sun.COM 	    fp->sf_srtt, fp->sf_rttvar, fp->sf_rto));
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 	/* Bound the RTO by configured min and max values */
762*13009SChandrasekar.Marimuthu@Sun.COM 	if (fp->sf_rto < sctp->sctp_rto_min) {
763*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rto = sctp->sctp_rto_min;
7640Sstevel@tonic-gate 	}
765*13009SChandrasekar.Marimuthu@Sun.COM 	if (fp->sf_rto > sctp->sctp_rto_max) {
766*13009SChandrasekar.Marimuthu@Sun.COM 		fp->sf_rto = sctp->sctp_rto_max;
7670Sstevel@tonic-gate 	}
7680Sstevel@tonic-gate 
76910212SGeorge.Shepherd@Sun.COM 	SCTP_MAX_RTO(sctp, fp);
770*13009SChandrasekar.Marimuthu@Sun.COM 	fp->sf_rtt_updates++;
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate void
sctp_free_faddr_timers(sctp_t * sctp)7740Sstevel@tonic-gate sctp_free_faddr_timers(sctp_t *sctp)
7750Sstevel@tonic-gate {
7760Sstevel@tonic-gate 	sctp_faddr_t *fp;
7770Sstevel@tonic-gate 
778*13009SChandrasekar.Marimuthu@Sun.COM 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
779*13009SChandrasekar.Marimuthu@Sun.COM 		if (fp->sf_timer_mp != NULL) {
780*13009SChandrasekar.Marimuthu@Sun.COM 			sctp_timer_free(fp->sf_timer_mp);
781*13009SChandrasekar.Marimuthu@Sun.COM 			fp->sf_timer_mp = NULL;
782*13009SChandrasekar.Marimuthu@Sun.COM 			fp->sf_timer_running = 0;
7830Sstevel@tonic-gate 		}
784*13009SChandrasekar.Marimuthu@Sun.COM 		if (fp->sf_rc_timer_mp != NULL) {
785*13009SChandrasekar.Marimuthu@Sun.COM 			sctp_timer_free(fp->sf_rc_timer_mp);
786*13009SChandrasekar.Marimuthu@Sun.COM 			fp->sf_rc_timer_mp = NULL;
787*13009SChandrasekar.Marimuthu@Sun.COM 			fp->sf_rc_timer_running = 0;
7880Sstevel@tonic-gate 		}
7890Sstevel@tonic-gate 	}
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate void
sctp_stop_faddr_timers(sctp_t * sctp)7930Sstevel@tonic-gate sctp_stop_faddr_timers(sctp_t *sctp)
7940Sstevel@tonic-gate {
7950Sstevel@tonic-gate 	sctp_faddr_t *fp;
7960Sstevel@tonic-gate 
797*13009SChandrasekar.Marimuthu@Sun.COM 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
7980Sstevel@tonic-gate 		SCTP_FADDR_TIMER_STOP(fp);
7990Sstevel@tonic-gate 		SCTP_FADDR_RC_TIMER_STOP(fp);
8000Sstevel@tonic-gate 	}
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate void
sctp_process_timer(sctp_t * sctp)8040Sstevel@tonic-gate sctp_process_timer(sctp_t *sctp)
8050Sstevel@tonic-gate {
8060Sstevel@tonic-gate 	mblk_t *mp;
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	ASSERT(sctp->sctp_running);
8090Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&sctp->sctp_lock));
8100Sstevel@tonic-gate 	while ((mp = sctp->sctp_timer_mp) != NULL) {
8110Sstevel@tonic-gate 		ASSERT(DB_TYPE(mp) == M_PCSIG);
8120Sstevel@tonic-gate 		/*
8130Sstevel@tonic-gate 		 * Since the timer mblk can be freed in sctp_timer_call(),
8140Sstevel@tonic-gate 		 * we need to grab the b_cont before that.
8150Sstevel@tonic-gate 		 */
8160Sstevel@tonic-gate 		sctp->sctp_timer_mp = mp->b_cont;
8170Sstevel@tonic-gate 		mp->b_cont = NULL;
8187444SGeorge.Shepherd@Sun.COM 		/*
8197444SGeorge.Shepherd@Sun.COM 		 * We have a reference on the sctp, the lock must be
8207444SGeorge.Shepherd@Sun.COM 		 * dropped to avoid deadlocks with functions potentially
8217444SGeorge.Shepherd@Sun.COM 		 * called in this context which in turn call untimeout().
8227444SGeorge.Shepherd@Sun.COM 		 */
8237444SGeorge.Shepherd@Sun.COM 		mutex_exit(&sctp->sctp_lock);
8240Sstevel@tonic-gate 		sctp_timer_call(sctp, mp);
8257444SGeorge.Shepherd@Sun.COM 		mutex_enter(&sctp->sctp_lock);
8260Sstevel@tonic-gate 	}
8270Sstevel@tonic-gate 	SCTP_REFRELE(sctp);
8280Sstevel@tonic-gate }
829