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