sctp_timer.c revision 221627
1163953Srrs/*- 2169382Srrs * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3218319Srrs * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved. 4218319Srrs * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved. 5163953Srrs * 6163953Srrs * Redistribution and use in source and binary forms, with or without 7163953Srrs * modification, are permitted provided that the following conditions are met: 8163953Srrs * 9163953Srrs * a) Redistributions of source code must retain the above copyright notice, 10163953Srrs * this list of conditions and the following disclaimer. 11163953Srrs * 12163953Srrs * b) Redistributions in binary form must reproduce the above copyright 13163953Srrs * notice, this list of conditions and the following disclaimer in 14163953Srrs * the documentation and/or other materials provided with the distribution. 15163953Srrs * 16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its 17163953Srrs * contributors may be used to endorse or promote products derived 18163953Srrs * from this software without specific prior written permission. 19163953Srrs * 20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE. 31163953Srrs */ 32163953Srrs 33163953Srrs/* $KAME: sctp_timer.c,v 1.29 2005/03/06 16:04:18 itojun Exp $ */ 34163953Srrs 35163953Srrs#include <sys/cdefs.h> 36163953Srrs__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 221627 2011-05-08 09:11:59Z tuexen $"); 37163953Srrs 38163953Srrs#define _IP_VHL 39166086Srrs#include <netinet/sctp_os.h> 40163953Srrs#include <netinet/sctp_pcb.h> 41163953Srrs#ifdef INET6 42163953Srrs#endif 43163953Srrs#include <netinet/sctp_var.h> 44167598Srrs#include <netinet/sctp_sysctl.h> 45163953Srrs#include <netinet/sctp_timer.h> 46163953Srrs#include <netinet/sctputil.h> 47163953Srrs#include <netinet/sctp_output.h> 48163953Srrs#include <netinet/sctp_header.h> 49163953Srrs#include <netinet/sctp_indata.h> 50163953Srrs#include <netinet/sctp_asconf.h> 51163953Srrs#include <netinet/sctp_input.h> 52163953Srrs#include <netinet/sctp.h> 53163953Srrs#include <netinet/sctp_uio.h> 54185694Srrs#include <netinet/udp.h> 55163953Srrs 56163953Srrs 57163953Srrsvoid 58163953Srrssctp_early_fr_timer(struct sctp_inpcb *inp, 59163953Srrs struct sctp_tcb *stcb, 60163953Srrs struct sctp_nets *net) 61163953Srrs{ 62216822Stuexen struct sctp_tmit_chunk *chk, *pchk; 63163953Srrs struct timeval now, min_wait, tv; 64219014Stuexen unsigned int cur_rto, cnt = 0, cnt_resend = 0; 65163953Srrs 66163953Srrs /* an early FR is occuring. */ 67169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 68163953Srrs /* get cur rto in micro-seconds */ 69163953Srrs if (net->lastsa == 0) { 70163953Srrs /* Hmm no rtt estimate yet? */ 71219014Stuexen cur_rto = stcb->asoc.initial_rto >> 2; 72163953Srrs } else { 73163953Srrs 74219014Stuexen cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 75163953Srrs } 76219014Stuexen if (cur_rto < SCTP_BASE_SYSCTL(sctp_early_fr_msec)) { 77219014Stuexen cur_rto = SCTP_BASE_SYSCTL(sctp_early_fr_msec); 78163953Srrs } 79219014Stuexen cur_rto *= 1000; 80219014Stuexen tv.tv_sec = cur_rto / 1000000; 81219014Stuexen tv.tv_usec = cur_rto % 1000000; 82163953Srrs min_wait = now; 83163953Srrs timevalsub(&min_wait, &tv); 84163953Srrs if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) { 85163953Srrs /* 86163953Srrs * if we hit here, we don't have enough seconds on the clock 87163953Srrs * to account for the RTO. We just let the lower seconds be 88163953Srrs * the bounds and don't worry about it. This may mean we 89163953Srrs * will mark a lot more than we should. 90163953Srrs */ 91163953Srrs min_wait.tv_sec = min_wait.tv_usec = 0; 92163953Srrs } 93216822Stuexen TAILQ_FOREACH_REVERSE_SAFE(chk, &stcb->asoc.sent_queue, sctpchunk_listhead, sctp_next, pchk) { 94163953Srrs if (chk->whoTo != net) { 95163953Srrs continue; 96163953Srrs } 97163953Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) 98163953Srrs cnt_resend++; 99163953Srrs else if ((chk->sent > SCTP_DATAGRAM_UNSENT) && 100163953Srrs (chk->sent < SCTP_DATAGRAM_RESEND)) { 101163953Srrs /* pending, may need retran */ 102163953Srrs if (chk->sent_rcv_time.tv_sec > min_wait.tv_sec) { 103163953Srrs /* 104163953Srrs * we have reached a chunk that was sent 105163953Srrs * some seconds past our min.. forget it we 106163953Srrs * will find no more to send. 107163953Srrs */ 108163953Srrs continue; 109163953Srrs } else if (chk->sent_rcv_time.tv_sec == min_wait.tv_sec) { 110163953Srrs /* 111163953Srrs * we must look at the micro seconds to 112163953Srrs * know. 113163953Srrs */ 114163953Srrs if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) { 115163953Srrs /* 116163953Srrs * ok it was sent after our boundary 117163953Srrs * time. 118163953Srrs */ 119163953Srrs continue; 120163953Srrs } 121163953Srrs } 122179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_EARLYFR_LOGGING_ENABLE) { 123170744Srrs sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count, 124170744Srrs 4, SCTP_FR_MARKED_EARLY); 125170744Srrs } 126163953Srrs SCTP_STAT_INCR(sctps_earlyfrmrkretrans); 127163953Srrs chk->sent = SCTP_DATAGRAM_RESEND; 128163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 129163953Srrs /* double book size since we are doing an early FR */ 130163953Srrs chk->book_size_scale++; 131163953Srrs cnt += chk->send_size; 132163953Srrs if ((cnt + net->flight_size) > net->cwnd) { 133163953Srrs /* Mark all we could possibly resend */ 134163953Srrs break; 135163953Srrs } 136163953Srrs } 137163953Srrs } 138163953Srrs if (cnt) { 139163953Srrs /* 140171440Srrs * JRS - Use the congestion control given in the congestion 141171440Srrs * control module 142163953Srrs */ 143171440Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer(inp, stcb, net); 144163953Srrs } else if (cnt_resend) { 145172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED); 146163953Srrs } 147163953Srrs /* Restart it? */ 148163953Srrs if (net->flight_size < net->cwnd) { 149163953Srrs SCTP_STAT_INCR(sctps_earlyfrstrtmr); 150163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net); 151163953Srrs } 152163953Srrs} 153163953Srrs 154163953Srrsvoid 155163953Srrssctp_audit_retranmission_queue(struct sctp_association *asoc) 156163953Srrs{ 157163953Srrs struct sctp_tmit_chunk *chk; 158163953Srrs 159169420Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Audit invoked on send queue cnt:%d onqueue:%d\n", 160169420Srrs asoc->sent_queue_retran_cnt, 161169420Srrs asoc->sent_queue_cnt); 162163953Srrs asoc->sent_queue_retran_cnt = 0; 163163953Srrs asoc->sent_queue_cnt = 0; 164163953Srrs TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 165163953Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 166163953Srrs sctp_ucount_incr(asoc->sent_queue_retran_cnt); 167163953Srrs } 168163953Srrs asoc->sent_queue_cnt++; 169163953Srrs } 170163953Srrs TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) { 171163953Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 172163953Srrs sctp_ucount_incr(asoc->sent_queue_retran_cnt); 173163953Srrs } 174163953Srrs } 175179157Srrs TAILQ_FOREACH(chk, &asoc->asconf_send_queue, sctp_next) { 176179157Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 177179157Srrs sctp_ucount_incr(asoc->sent_queue_retran_cnt); 178179157Srrs } 179179157Srrs } 180169420Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Audit completes retran:%d onqueue:%d\n", 181169420Srrs asoc->sent_queue_retran_cnt, 182169420Srrs asoc->sent_queue_cnt); 183163953Srrs} 184163953Srrs 185163953Srrsint 186163953Srrssctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 187163953Srrs struct sctp_nets *net, uint16_t threshold) 188163953Srrs{ 189163953Srrs if (net) { 190163953Srrs net->error_count++; 191169420Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Error count for %p now %d thresh:%d\n", 192169420Srrs net, net->error_count, 193169420Srrs net->failure_threshold); 194163953Srrs if (net->error_count > net->failure_threshold) { 195163953Srrs /* We had a threshold failure */ 196163953Srrs if (net->dest_state & SCTP_ADDR_REACHABLE) { 197163953Srrs net->dest_state &= ~SCTP_ADDR_REACHABLE; 198163953Srrs net->dest_state |= SCTP_ADDR_NOT_REACHABLE; 199167598Srrs net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 200163953Srrs if (net == stcb->asoc.primary_destination) { 201163953Srrs net->dest_state |= SCTP_ADDR_WAS_PRIMARY; 202163953Srrs } 203171440Srrs /* 204171440Srrs * JRS 5/14/07 - If a destination is 205171440Srrs * unreachable, the PF bit is turned off. 206171440Srrs * This allows an unambiguous use of the PF 207171440Srrs * bit for destinations that are reachable 208171440Srrs * but potentially failed. If the 209171440Srrs * destination is set to the unreachable 210171440Srrs * state, also set the destination to the PF 211171440Srrs * state. 212171440Srrs */ 213171440Srrs /* 214171440Srrs * Add debug message here if destination is 215171440Srrs * not in PF state. 216171440Srrs */ 217171440Srrs /* Stop any running T3 timers here? */ 218216669Stuexen if ((stcb->asoc.sctp_cmt_on_off > 0) && 219211944Stuexen (stcb->asoc.sctp_cmt_pf > 0)) { 220171440Srrs net->dest_state &= ~SCTP_ADDR_PF; 221171440Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n", 222171440Srrs net); 223171440Srrs } 224163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, 225163953Srrs stcb, 226163953Srrs SCTP_FAILED_THRESHOLD, 227172090Srrs (void *)net, SCTP_SO_NOT_LOCKED); 228163953Srrs } 229163953Srrs } 230163953Srrs /*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE 231163953Srrs *********ROUTING CODE 232163953Srrs */ 233163953Srrs /*********HOLD THIS COMMENT FOR END OF PATCH OF ALTERNATE 234163953Srrs *********ROUTING CODE 235163953Srrs */ 236163953Srrs } 237163953Srrs if (stcb == NULL) 238163953Srrs return (0); 239163953Srrs 240163953Srrs if (net) { 241163953Srrs if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) { 242179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 243171943Srrs sctp_misc_ints(SCTP_THRESHOLD_INCR, 244171943Srrs stcb->asoc.overall_error_count, 245171943Srrs (stcb->asoc.overall_error_count + 1), 246171943Srrs SCTP_FROM_SCTP_TIMER, 247171943Srrs __LINE__); 248171943Srrs } 249163953Srrs stcb->asoc.overall_error_count++; 250163953Srrs } 251163953Srrs } else { 252179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 253171943Srrs sctp_misc_ints(SCTP_THRESHOLD_INCR, 254171943Srrs stcb->asoc.overall_error_count, 255171943Srrs (stcb->asoc.overall_error_count + 1), 256171943Srrs SCTP_FROM_SCTP_TIMER, 257171943Srrs __LINE__); 258171943Srrs } 259163953Srrs stcb->asoc.overall_error_count++; 260163953Srrs } 261169420Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Overall error count for %p now %d thresh:%u state:%x\n", 262169420Srrs &stcb->asoc, stcb->asoc.overall_error_count, 263169420Srrs (uint32_t) threshold, 264169420Srrs ((net == NULL) ? (uint32_t) 0 : (uint32_t) net->dest_state)); 265163953Srrs /* 266163953Srrs * We specifically do not do >= to give the assoc one more change 267163953Srrs * before we fail it. 268163953Srrs */ 269163953Srrs if (stcb->asoc.overall_error_count > threshold) { 270163953Srrs /* Abort notification sends a ULP notify */ 271163953Srrs struct mbuf *oper; 272163953Srrs 273163953Srrs oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), 274163953Srrs 0, M_DONTWAIT, 1, MT_DATA); 275163953Srrs if (oper) { 276163953Srrs struct sctp_paramhdr *ph; 277163953Srrs uint32_t *ippp; 278163953Srrs 279165647Srrs SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + 280163953Srrs sizeof(uint32_t); 281163953Srrs ph = mtod(oper, struct sctp_paramhdr *); 282163953Srrs ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); 283165647Srrs ph->param_length = htons(SCTP_BUF_LEN(oper)); 284163953Srrs ippp = (uint32_t *) (ph + 1); 285165220Srrs *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1); 286163953Srrs } 287165220Srrs inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1; 288172090Srrs sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper, SCTP_SO_NOT_LOCKED); 289163953Srrs return (1); 290163953Srrs } 291163953Srrs return (0); 292163953Srrs} 293163953Srrs 294214928Stuexen/* 295214928Stuexen * sctp_find_alternate_net() returns a non-NULL pointer as long 296214928Stuexen * the argument net is non-NULL. 297214928Stuexen */ 298163953Srrsstruct sctp_nets * 299163953Srrssctp_find_alternate_net(struct sctp_tcb *stcb, 300163953Srrs struct sctp_nets *net, 301171440Srrs int mode) 302163953Srrs{ 303163953Srrs /* Find and return an alternate network if possible */ 304171440Srrs struct sctp_nets *alt, *mnet, *min_errors_net = NULL, *max_cwnd_net = NULL; 305163953Srrs int once; 306163953Srrs 307171440Srrs /* JRS 5/14/07 - Initialize min_errors to an impossible value. */ 308171440Srrs int min_errors = -1; 309171440Srrs uint32_t max_cwnd = 0; 310171440Srrs 311163953Srrs if (stcb->asoc.numnets == 1) { 312163953Srrs /* No others but net */ 313163953Srrs return (TAILQ_FIRST(&stcb->asoc.nets)); 314163953Srrs } 315171440Srrs /* 316171440Srrs * JRS 5/14/07 - If mode is set to 2, use the CMT PF find alternate 317171440Srrs * net algorithm. This algorithm chooses the active destination (not 318171440Srrs * in PF state) with the largest cwnd value. If all destinations are 319171440Srrs * in PF state, unreachable, or unconfirmed, choose the desination 320171440Srrs * that is in PF state with the lowest error count. In case of a 321171440Srrs * tie, choose the destination that was most recently active. 322171440Srrs */ 323171440Srrs if (mode == 2) { 324163953Srrs TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { 325171440Srrs /* 326171440Srrs * JRS 5/14/07 - If the destination is unreachable 327171440Srrs * or unconfirmed, skip it. 328171440Srrs */ 329163953Srrs if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || 330171440Srrs (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { 331171440Srrs continue; 332171440Srrs } 333171440Srrs /* 334171440Srrs * JRS 5/14/07 - If the destination is reachable 335171440Srrs * but in PF state, compare the error count of the 336171440Srrs * destination to the minimum error count seen thus 337171440Srrs * far. Store the destination with the lower error 338171440Srrs * count. If the error counts are equal, store the 339171440Srrs * destination that was most recently active. 340171440Srrs */ 341171440Srrs if (mnet->dest_state & SCTP_ADDR_PF) { 342171440Srrs /* 343171440Srrs * JRS 5/14/07 - If the destination under 344171440Srrs * consideration is the current destination, 345171440Srrs * work as if the error count is one higher. 346171440Srrs * The actual error count will not be 347171440Srrs * incremented until later in the t3 348171440Srrs * handler. 349171440Srrs */ 350171440Srrs if (mnet == net) { 351171440Srrs if (min_errors == -1) { 352171440Srrs min_errors = mnet->error_count + 1; 353171440Srrs min_errors_net = mnet; 354171440Srrs } else if (mnet->error_count + 1 < min_errors) { 355171440Srrs min_errors = mnet->error_count + 1; 356171440Srrs min_errors_net = mnet; 357171440Srrs } else if (mnet->error_count + 1 == min_errors 358171440Srrs && mnet->last_active > min_errors_net->last_active) { 359171440Srrs min_errors_net = mnet; 360171440Srrs min_errors = mnet->error_count + 1; 361171440Srrs } 362171440Srrs continue; 363171440Srrs } else { 364171440Srrs if (min_errors == -1) { 365171440Srrs min_errors = mnet->error_count; 366171440Srrs min_errors_net = mnet; 367171440Srrs } else if (mnet->error_count < min_errors) { 368171440Srrs min_errors = mnet->error_count; 369171440Srrs min_errors_net = mnet; 370171440Srrs } else if (mnet->error_count == min_errors 371171440Srrs && mnet->last_active > min_errors_net->last_active) { 372171440Srrs min_errors_net = mnet; 373171440Srrs min_errors = mnet->error_count; 374171440Srrs } 375171440Srrs continue; 376171440Srrs } 377171440Srrs } 378171440Srrs /* 379171440Srrs * JRS 5/14/07 - If the destination is reachable and 380171440Srrs * not in PF state, compare the cwnd of the 381171440Srrs * destination to the highest cwnd seen thus far. 382171440Srrs * Store the destination with the higher cwnd value. 383171440Srrs * If the cwnd values are equal, randomly choose one 384171440Srrs * of the two destinations. 385171440Srrs */ 386171440Srrs if (max_cwnd < mnet->cwnd) { 387171440Srrs max_cwnd_net = mnet; 388171440Srrs max_cwnd = mnet->cwnd; 389171440Srrs } else if (max_cwnd == mnet->cwnd) { 390171440Srrs uint32_t rndval; 391171440Srrs uint8_t this_random; 392171440Srrs 393171440Srrs if (stcb->asoc.hb_random_idx > 3) { 394171440Srrs rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep); 395171440Srrs memcpy(stcb->asoc.hb_random_values, &rndval, sizeof(stcb->asoc.hb_random_values)); 396171440Srrs this_random = stcb->asoc.hb_random_values[0]; 397171440Srrs stcb->asoc.hb_random_idx++; 398171440Srrs stcb->asoc.hb_ect_randombit = 0; 399171440Srrs } else { 400171440Srrs this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 401171440Srrs stcb->asoc.hb_random_idx++; 402171440Srrs stcb->asoc.hb_ect_randombit = 0; 403171440Srrs } 404171440Srrs if (this_random % 2 == 1) { 405171440Srrs max_cwnd_net = mnet; 406180387Srrs max_cwnd = mnet->cwnd; /* Useless? */ 407171440Srrs } 408171440Srrs } 409171440Srrs } 410171440Srrs /* 411171440Srrs * JRS 5/14/07 - After all destination have been considered 412171440Srrs * as alternates, check to see if there was some active 413171440Srrs * destination (not in PF state). If not, check to see if 414171440Srrs * there was some PF destination with the minimum number of 415171440Srrs * errors. If not, return the original destination. If 416171440Srrs * there is a min_errors_net, remove the PF flag from that 417171440Srrs * destination, set the cwnd to one or two MTUs, and return 418171440Srrs * the destination as an alt. If there was some active 419171440Srrs * destination with a highest cwnd, return the destination 420171440Srrs * as an alt. 421171440Srrs */ 422171440Srrs if (max_cwnd_net == NULL) { 423171440Srrs if (min_errors_net == NULL) { 424171440Srrs return (net); 425171440Srrs } 426171440Srrs min_errors_net->dest_state &= ~SCTP_ADDR_PF; 427211944Stuexen min_errors_net->cwnd = min_errors_net->mtu * stcb->asoc.sctp_cmt_pf; 428171440Srrs if (SCTP_OS_TIMER_PENDING(&min_errors_net->rxt_timer.timer)) { 429171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 430171440Srrs stcb, min_errors_net, 431171440Srrs SCTP_FROM_SCTP_TIMER + SCTP_LOC_2); 432171440Srrs } 433171440Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to active with %d errors.\n", 434171440Srrs min_errors_net, min_errors_net->error_count); 435171440Srrs return (min_errors_net); 436171440Srrs } else { 437171440Srrs return (max_cwnd_net); 438171440Srrs } 439171440Srrs } 440171440Srrs /* 441171440Srrs * JRS 5/14/07 - If mode is set to 1, use the CMT policy for 442171440Srrs * choosing an alternate net. 443171440Srrs */ 444171440Srrs else if (mode == 1) { 445171440Srrs TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { 446171440Srrs if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || 447214928Stuexen (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { 448163953Srrs /* 449163953Srrs * will skip ones that are not-reachable or 450163953Srrs * unconfirmed 451163953Srrs */ 452163953Srrs continue; 453163953Srrs } 454171440Srrs if (max_cwnd < mnet->cwnd) { 455171440Srrs max_cwnd_net = mnet; 456171440Srrs max_cwnd = mnet->cwnd; 457171440Srrs } else if (max_cwnd == mnet->cwnd) { 458163953Srrs uint32_t rndval; 459163953Srrs uint8_t this_random; 460163953Srrs 461163953Srrs if (stcb->asoc.hb_random_idx > 3) { 462163953Srrs rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep); 463163953Srrs memcpy(stcb->asoc.hb_random_values, &rndval, 464163953Srrs sizeof(stcb->asoc.hb_random_values)); 465163953Srrs this_random = stcb->asoc.hb_random_values[0]; 466163953Srrs stcb->asoc.hb_random_idx = 0; 467163953Srrs stcb->asoc.hb_ect_randombit = 0; 468163953Srrs } else { 469163953Srrs this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 470163953Srrs stcb->asoc.hb_random_idx++; 471163953Srrs stcb->asoc.hb_ect_randombit = 0; 472163953Srrs } 473163953Srrs if (this_random % 2) { 474171440Srrs max_cwnd_net = mnet; 475171440Srrs max_cwnd = mnet->cwnd; 476163953Srrs } 477163953Srrs } 478163953Srrs } 479171440Srrs if (max_cwnd_net) { 480171440Srrs return (max_cwnd_net); 481163953Srrs } 482163953Srrs } 483163953Srrs mnet = net; 484163953Srrs once = 0; 485163953Srrs 486163953Srrs if (mnet == NULL) { 487163953Srrs mnet = TAILQ_FIRST(&stcb->asoc.nets); 488212225Srrs if (mnet == NULL) { 489212225Srrs return (NULL); 490212225Srrs } 491163953Srrs } 492163953Srrs do { 493163953Srrs alt = TAILQ_NEXT(mnet, sctp_next); 494163953Srrs if (alt == NULL) { 495163953Srrs once++; 496163953Srrs if (once > 1) { 497163953Srrs break; 498163953Srrs } 499163953Srrs alt = TAILQ_FIRST(&stcb->asoc.nets); 500212225Srrs if (alt == NULL) { 501212225Srrs return (NULL); 502212225Srrs } 503163953Srrs } 504163953Srrs if (alt->ro.ro_rt == NULL) { 505167598Srrs if (alt->ro._s_addr) { 506167598Srrs sctp_free_ifa(alt->ro._s_addr); 507167598Srrs alt->ro._s_addr = NULL; 508167598Srrs } 509163953Srrs alt->src_addr_selected = 0; 510163953Srrs } 511214928Stuexen /* sa_ignore NO_NULL_CHK */ 512214928Stuexen if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) && 513163953Srrs (alt->ro.ro_rt != NULL) && 514214928Stuexen (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) { 515163953Srrs /* Found a reachable address */ 516163953Srrs break; 517163953Srrs } 518163953Srrs mnet = alt; 519163953Srrs } while (alt != NULL); 520163953Srrs 521163953Srrs if (alt == NULL) { 522163953Srrs /* Case where NO insv network exists (dormant state) */ 523163953Srrs /* we rotate destinations */ 524163953Srrs once = 0; 525163953Srrs mnet = net; 526163953Srrs do { 527212225Srrs if (mnet == NULL) { 528212225Srrs return (TAILQ_FIRST(&stcb->asoc.nets)); 529212225Srrs } 530163953Srrs alt = TAILQ_NEXT(mnet, sctp_next); 531163953Srrs if (alt == NULL) { 532163953Srrs once++; 533163953Srrs if (once > 1) { 534163953Srrs break; 535163953Srrs } 536163953Srrs alt = TAILQ_FIRST(&stcb->asoc.nets); 537163953Srrs } 538169655Srrs /* sa_ignore NO_NULL_CHK */ 539163953Srrs if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) && 540163953Srrs (alt != net)) { 541163953Srrs /* Found an alternate address */ 542163953Srrs break; 543163953Srrs } 544163953Srrs mnet = alt; 545163953Srrs } while (alt != NULL); 546163953Srrs } 547163953Srrs if (alt == NULL) { 548163953Srrs return (net); 549163953Srrs } 550163953Srrs return (alt); 551163953Srrs} 552163953Srrs 553163953Srrsstatic void 554163953Srrssctp_backoff_on_timeout(struct sctp_tcb *stcb, 555163953Srrs struct sctp_nets *net, 556163953Srrs int win_probe, 557210599Srrs int num_marked, int num_abandoned) 558163953Srrs{ 559170642Srrs if (net->RTO == 0) { 560170642Srrs net->RTO = stcb->asoc.minrto; 561170642Srrs } 562163953Srrs net->RTO <<= 1; 563163953Srrs if (net->RTO > stcb->asoc.maxrto) { 564163953Srrs net->RTO = stcb->asoc.maxrto; 565163953Srrs } 566210599Srrs if ((win_probe == 0) && (num_marked || num_abandoned)) { 567163953Srrs /* We don't apply penalty to window probe scenarios */ 568171440Srrs /* JRS - Use the congestion control given in the CC module */ 569171440Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout(stcb, net); 570163953Srrs } 571163953Srrs} 572163953Srrs 573184333Srrs#ifndef INVARIANTS 574184333Srrsstatic void 575182367Srrssctp_recover_sent_list(struct sctp_tcb *stcb) 576182367Srrs{ 577216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 578182367Srrs struct sctp_association *asoc; 579182367Srrs 580182367Srrs asoc = &stcb->asoc; 581216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 582216825Stuexen if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.TSN_seq)) { 583182367Srrs SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n", 584216822Stuexen chk, chk->rec.data.TSN_seq, asoc->last_acked_seq); 585182367Srrs TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 586182367Srrs if (chk->pr_sctp_on) { 587182367Srrs if (asoc->pr_sctp_cnt != 0) 588182367Srrs asoc->pr_sctp_cnt--; 589182367Srrs } 590182367Srrs if (chk->data) { 591182367Srrs /* sa_ignore NO_NULL_CHK */ 592182367Srrs sctp_free_bufspace(stcb, asoc, chk, 1); 593182367Srrs sctp_m_freem(chk->data); 594216822Stuexen chk->data = NULL; 595196260Stuexen if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) { 596182367Srrs asoc->sent_queue_cnt_removeable--; 597182367Srrs } 598182367Srrs } 599182367Srrs asoc->sent_queue_cnt--; 600221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 601182367Srrs } 602182367Srrs } 603182367Srrs SCTP_PRINTF("after recover order is as follows\n"); 604216822Stuexen TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 605182367Srrs SCTP_PRINTF("chk:%p TSN:%x\n", chk, chk->rec.data.TSN_seq); 606182367Srrs } 607182367Srrs} 608182367Srrs 609184333Srrs#endif 610184333Srrs 611163953Srrsstatic int 612163953Srrssctp_mark_all_for_resend(struct sctp_tcb *stcb, 613163953Srrs struct sctp_nets *net, 614163953Srrs struct sctp_nets *alt, 615163953Srrs int window_probe, 616210599Srrs int *num_marked, 617210599Srrs int *num_abandoned) 618163953Srrs{ 619163953Srrs 620163953Srrs /* 621163953Srrs * Mark all chunks (well not all) that were sent to *net for 622163953Srrs * retransmission. Move them to alt for there destination as well... 623163953Srrs * We only mark chunks that have been outstanding long enough to 624163953Srrs * have received feed-back. 625163953Srrs */ 626216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 627163953Srrs struct sctp_nets *lnets; 628163953Srrs struct timeval now, min_wait, tv; 629219014Stuexen int cur_rto; 630210599Srrs int cnt_abandoned; 631168709Srrs int audit_tf, num_mk, fir; 632163953Srrs unsigned int cnt_mk; 633168709Srrs uint32_t orig_flight, orig_tf; 634163953Srrs uint32_t tsnlast, tsnfirst; 635182367Srrs int recovery_cnt = 0; 636163953Srrs 637171440Srrs 638163953Srrs /* none in flight now */ 639163953Srrs audit_tf = 0; 640163953Srrs fir = 0; 641163953Srrs /* 642163953Srrs * figure out how long a data chunk must be pending before we can 643163953Srrs * mark it .. 644163953Srrs */ 645169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 646163953Srrs /* get cur rto in micro-seconds */ 647219014Stuexen cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 648219014Stuexen cur_rto *= 1000; 649179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 650219014Stuexen sctp_log_fr(cur_rto, 651170744Srrs stcb->asoc.peers_rwnd, 652170744Srrs window_probe, 653170744Srrs SCTP_FR_T3_MARK_TIME); 654170744Srrs sctp_log_fr(net->flight_size, 655170744Srrs SCTP_OS_TIMER_PENDING(&net->fr_timer.timer), 656170744Srrs SCTP_OS_TIMER_ACTIVE(&net->fr_timer.timer), 657170744Srrs SCTP_FR_CWND_REPORT); 658170744Srrs sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT); 659170744Srrs } 660219014Stuexen tv.tv_sec = cur_rto / 1000000; 661219014Stuexen tv.tv_usec = cur_rto % 1000000; 662163953Srrs min_wait = now; 663163953Srrs timevalsub(&min_wait, &tv); 664163953Srrs if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) { 665163953Srrs /* 666163953Srrs * if we hit here, we don't have enough seconds on the clock 667163953Srrs * to account for the RTO. We just let the lower seconds be 668163953Srrs * the bounds and don't worry about it. This may mean we 669163953Srrs * will mark a lot more than we should. 670163953Srrs */ 671163953Srrs min_wait.tv_sec = min_wait.tv_usec = 0; 672163953Srrs } 673179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 674219014Stuexen sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME); 675170744Srrs sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME); 676170744Srrs } 677163953Srrs /* 678163953Srrs * Our rwnd will be incorrect here since we are not adding back the 679163953Srrs * cnt * mbuf but we will fix that down below. 680163953Srrs */ 681163953Srrs orig_flight = net->flight_size; 682168709Srrs orig_tf = stcb->asoc.total_flight; 683168709Srrs 684163953Srrs net->fast_retran_ip = 0; 685163953Srrs /* Now on to each chunk */ 686210599Srrs cnt_abandoned = 0; 687163953Srrs num_mk = cnt_mk = 0; 688163953Srrs tsnfirst = tsnlast = 0; 689184333Srrs#ifndef INVARIANTS 690182367Srrsstart_again: 691184333Srrs#endif 692216822Stuexen TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) { 693216825Stuexen if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) { 694163953Srrs /* Strange case our list got out of order? */ 695182367Srrs SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x", 696182367Srrs (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq); 697182367Srrs recovery_cnt++; 698182367Srrs#ifdef INVARIANTS 699182367Srrs panic("last acked >= chk on sent-Q"); 700182367Srrs#else 701182367Srrs SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt); 702182367Srrs sctp_recover_sent_list(stcb); 703182367Srrs if (recovery_cnt < 10) { 704182367Srrs goto start_again; 705182367Srrs } else { 706182367Srrs SCTP_PRINTF("Recovery fails %d times??\n", recovery_cnt); 707182367Srrs } 708182367Srrs#endif 709163953Srrs } 710163953Srrs if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) { 711163953Srrs /* 712163953Srrs * found one to mark: If it is less than 713163953Srrs * DATAGRAM_ACKED it MUST not be a skipped or marked 714163953Srrs * TSN but instead one that is either already set 715163953Srrs * for retransmission OR one that needs 716163953Srrs * retransmission. 717163953Srrs */ 718163953Srrs 719163953Srrs /* validate its been outstanding long enough */ 720179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 721170744Srrs sctp_log_fr(chk->rec.data.TSN_seq, 722170744Srrs chk->sent_rcv_time.tv_sec, 723170744Srrs chk->sent_rcv_time.tv_usec, 724170744Srrs SCTP_FR_T3_MARK_TIME); 725170744Srrs } 726163953Srrs if ((chk->sent_rcv_time.tv_sec > min_wait.tv_sec) && (window_probe == 0)) { 727163953Srrs /* 728163953Srrs * we have reached a chunk that was sent 729163953Srrs * some seconds past our min.. forget it we 730163953Srrs * will find no more to send. 731163953Srrs */ 732179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 733170744Srrs sctp_log_fr(0, 734170744Srrs chk->sent_rcv_time.tv_sec, 735170744Srrs chk->sent_rcv_time.tv_usec, 736170744Srrs SCTP_FR_T3_STOPPED); 737170744Srrs } 738163953Srrs continue; 739163953Srrs } else if ((chk->sent_rcv_time.tv_sec == min_wait.tv_sec) && 740163953Srrs (window_probe == 0)) { 741163953Srrs /* 742163953Srrs * we must look at the micro seconds to 743163953Srrs * know. 744163953Srrs */ 745163953Srrs if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) { 746163953Srrs /* 747163953Srrs * ok it was sent after our boundary 748163953Srrs * time. 749163953Srrs */ 750179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 751170744Srrs sctp_log_fr(0, 752170744Srrs chk->sent_rcv_time.tv_sec, 753170744Srrs chk->sent_rcv_time.tv_usec, 754170744Srrs SCTP_FR_T3_STOPPED); 755170744Srrs } 756163953Srrs continue; 757163953Srrs } 758163953Srrs } 759196260Stuexen if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) { 760163953Srrs /* Is it expired? */ 761212801Stuexen if (timevalcmp(&now, &chk->rec.data.timetodrop, >)) { 762163953Srrs /* Yes so drop it */ 763163953Srrs if (chk->data) { 764169420Srrs (void)sctp_release_pr_sctp_chunk(stcb, 765163953Srrs chk, 766163953Srrs (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT), 767189790Srrs SCTP_SO_NOT_LOCKED); 768210599Srrs cnt_abandoned++; 769163953Srrs } 770185694Srrs continue; 771163953Srrs } 772163953Srrs } 773196260Stuexen if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) { 774163953Srrs /* Has it been retransmitted tv_sec times? */ 775163953Srrs if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) { 776163953Srrs if (chk->data) { 777169420Srrs (void)sctp_release_pr_sctp_chunk(stcb, 778163953Srrs chk, 779163953Srrs (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT), 780189790Srrs SCTP_SO_NOT_LOCKED); 781210599Srrs cnt_abandoned++; 782163953Srrs } 783185694Srrs continue; 784163953Srrs } 785163953Srrs } 786168709Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 787163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 788163953Srrs num_mk++; 789163953Srrs if (fir == 0) { 790163953Srrs fir = 1; 791163953Srrs tsnfirst = chk->rec.data.TSN_seq; 792163953Srrs } 793163953Srrs tsnlast = chk->rec.data.TSN_seq; 794179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 795170744Srrs sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count, 796170744Srrs 0, SCTP_FR_T3_MARKED); 797170744Srrs } 798168709Srrs if (chk->rec.data.chunk_was_revoked) { 799168709Srrs /* deflate the cwnd */ 800168709Srrs chk->whoTo->cwnd -= chk->book_size; 801168709Srrs chk->rec.data.chunk_was_revoked = 0; 802168709Srrs } 803168709Srrs net->marked_retrans++; 804168709Srrs stcb->asoc.marked_retrans++; 805179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 806170744Srrs sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO, 807170744Srrs chk->whoTo->flight_size, 808170744Srrs chk->book_size, 809170744Srrs (uintptr_t) chk->whoTo, 810170744Srrs chk->rec.data.TSN_seq); 811170744Srrs } 812168709Srrs sctp_flight_size_decrease(chk); 813168709Srrs sctp_total_flight_decrease(stcb, chk); 814168709Srrs stcb->asoc.peers_rwnd += chk->send_size; 815179783Srrs stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh); 816163953Srrs } 817163953Srrs chk->sent = SCTP_DATAGRAM_RESEND; 818163953Srrs SCTP_STAT_INCR(sctps_markedretrans); 819165220Srrs 820163953Srrs /* reset the TSN for striking and other FR stuff */ 821163953Srrs chk->rec.data.doing_fast_retransmit = 0; 822163953Srrs /* Clear any time so NO RTT is being done */ 823219397Srrs 824219397Srrs if (chk->do_rtt) { 825219397Srrs if (chk->whoTo->rto_needed == 0) { 826219397Srrs chk->whoTo->rto_needed = 1; 827219397Srrs } 828219397Srrs } 829163953Srrs chk->do_rtt = 0; 830163953Srrs if (alt != net) { 831163953Srrs sctp_free_remote_addr(chk->whoTo); 832163953Srrs chk->no_fr_allowed = 1; 833163953Srrs chk->whoTo = alt; 834163953Srrs atomic_add_int(&alt->ref_count, 1); 835163953Srrs } else { 836163953Srrs chk->no_fr_allowed = 0; 837163953Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 838163953Srrs chk->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 839163953Srrs } else { 840163953Srrs chk->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 841163953Srrs } 842163953Srrs } 843170181Srrs /* 844170181Srrs * CMT: Do not allow FRs on retransmitted TSNs. 845170181Srrs */ 846216669Stuexen if (stcb->asoc.sctp_cmt_on_off > 0) { 847163953Srrs chk->no_fr_allowed = 1; 848163953Srrs } 849210599Srrs#ifdef THIS_SHOULD_NOT_BE_DONE 850163953Srrs } else if (chk->sent == SCTP_DATAGRAM_ACKED) { 851163953Srrs /* remember highest acked one */ 852163953Srrs could_be_sent = chk; 853210599Srrs#endif 854163953Srrs } 855163953Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 856163953Srrs cnt_mk++; 857163953Srrs } 858163953Srrs } 859168709Srrs if ((orig_flight - net->flight_size) != (orig_tf - stcb->asoc.total_flight)) { 860168709Srrs /* we did not subtract the same things? */ 861168709Srrs audit_tf = 1; 862168709Srrs } 863179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) { 864170744Srrs sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT); 865170744Srrs } 866163953Srrs#ifdef SCTP_DEBUG 867169420Srrs if (num_mk) { 868169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n", 869169420Srrs tsnlast); 870169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%ld\n", 871169420Srrs num_mk, (u_long)stcb->asoc.peers_rwnd); 872169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n", 873169420Srrs tsnlast); 874169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%d\n", 875169420Srrs num_mk, 876169420Srrs (int)stcb->asoc.peers_rwnd); 877163953Srrs } 878163953Srrs#endif 879163953Srrs *num_marked = num_mk; 880210599Srrs *num_abandoned = cnt_abandoned; 881210493Srrs /* 882210493Srrs * Now check for a ECN Echo that may be stranded And include the 883210493Srrs * cnt_mk'd to have all resends in the control queue. 884210493Srrs */ 885210493Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 886210493Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 887210493Srrs cnt_mk++; 888210493Srrs } 889210493Srrs if ((chk->whoTo == net) && 890210493Srrs (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 891210493Srrs sctp_free_remote_addr(chk->whoTo); 892210493Srrs chk->whoTo = alt; 893210493Srrs if (chk->sent != SCTP_DATAGRAM_RESEND) { 894210493Srrs chk->sent = SCTP_DATAGRAM_RESEND; 895210493Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 896210493Srrs cnt_mk++; 897210493Srrs } 898210493Srrs atomic_add_int(&alt->ref_count, 1); 899210493Srrs } 900210493Srrs } 901210599Srrs#ifdef THIS_SHOULD_NOT_BE_DONE 902163953Srrs if ((stcb->asoc.sent_queue_retran_cnt == 0) && (could_be_sent)) { 903163953Srrs /* fix it so we retransmit the highest acked anyway */ 904163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 905163953Srrs cnt_mk++; 906163953Srrs could_be_sent->sent = SCTP_DATAGRAM_RESEND; 907163953Srrs } 908210599Srrs#endif 909163953Srrs if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) { 910165220Srrs#ifdef INVARIANTS 911171477Srrs SCTP_PRINTF("Local Audit says there are %d for retran asoc cnt:%d we marked:%d this time\n", 912171477Srrs cnt_mk, stcb->asoc.sent_queue_retran_cnt, num_mk); 913163953Srrs#endif 914163953Srrs#ifndef SCTP_AUDITING_ENABLED 915163953Srrs stcb->asoc.sent_queue_retran_cnt = cnt_mk; 916163953Srrs#endif 917163953Srrs } 918163953Srrs if (audit_tf) { 919169420Srrs SCTPDBG(SCTP_DEBUG_TIMER4, 920169420Srrs "Audit total flight due to negative value net:%p\n", 921169420Srrs net); 922163953Srrs stcb->asoc.total_flight = 0; 923163953Srrs stcb->asoc.total_flight_count = 0; 924163953Srrs /* Clear all networks flight size */ 925163953Srrs TAILQ_FOREACH(lnets, &stcb->asoc.nets, sctp_next) { 926163953Srrs lnets->flight_size = 0; 927169420Srrs SCTPDBG(SCTP_DEBUG_TIMER4, 928169420Srrs "Net:%p c-f cwnd:%d ssthresh:%d\n", 929169420Srrs lnets, lnets->cwnd, lnets->ssthresh); 930163953Srrs } 931163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 932163953Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 933179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 934170744Srrs sctp_misc_ints(SCTP_FLIGHT_LOG_UP, 935170744Srrs chk->whoTo->flight_size, 936170744Srrs chk->book_size, 937170744Srrs (uintptr_t) chk->whoTo, 938170744Srrs chk->rec.data.TSN_seq); 939170744Srrs } 940168709Srrs sctp_flight_size_increase(chk); 941168709Srrs sctp_total_flight_increase(stcb, chk); 942163953Srrs } 943163953Srrs } 944163953Srrs } 945163953Srrs /* We return 1 if we only have a window probe outstanding */ 946163953Srrs return (0); 947163953Srrs} 948163953Srrs 949163953Srrs 950163953Srrsint 951163953Srrssctp_t3rxt_timer(struct sctp_inpcb *inp, 952163953Srrs struct sctp_tcb *stcb, 953163953Srrs struct sctp_nets *net) 954163953Srrs{ 955163953Srrs struct sctp_nets *alt; 956210599Srrs int win_probe, num_mk, num_abandoned; 957163953Srrs 958179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 959170744Srrs sctp_log_fr(0, 0, 0, SCTP_FR_T3_TIMEOUT); 960170744Srrs } 961179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { 962163953Srrs struct sctp_nets *lnet; 963163953Srrs 964163953Srrs TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 965163953Srrs if (net == lnet) { 966163953Srrs sctp_log_cwnd(stcb, lnet, 1, SCTP_CWND_LOG_FROM_T3); 967163953Srrs } else { 968163953Srrs sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_LOG_FROM_T3); 969163953Srrs } 970163953Srrs } 971163953Srrs } 972163953Srrs /* Find an alternate and mark those for retransmission */ 973163953Srrs if ((stcb->asoc.peers_rwnd == 0) && 974163953Srrs (stcb->asoc.total_flight < net->mtu)) { 975163953Srrs SCTP_STAT_INCR(sctps_timowindowprobe); 976163953Srrs win_probe = 1; 977163953Srrs } else { 978163953Srrs win_probe = 0; 979163953Srrs } 980168709Srrs 981171440Srrs /* 982171440Srrs * JRS 5/14/07 - If CMT PF is on and the destination if not already 983171440Srrs * in PF state, set the destination to PF state and store the 984171440Srrs * current time as the time that the destination was last active. In 985171440Srrs * addition, find an alternate destination with PF-based 986171440Srrs * find_alt_net(). 987171440Srrs */ 988216669Stuexen if ((stcb->asoc.sctp_cmt_on_off > 0) && 989211944Stuexen (stcb->asoc.sctp_cmt_pf > 0)) { 990171440Srrs if ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF) { 991171440Srrs net->dest_state |= SCTP_ADDR_PF; 992171477Srrs net->last_active = sctp_get_tick_count(); 993171440Srrs SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from active to PF.\n", 994171440Srrs net); 995171440Srrs } 996171440Srrs alt = sctp_find_alternate_net(stcb, net, 2); 997216669Stuexen } else if (stcb->asoc.sctp_cmt_on_off > 0) { 998168709Srrs /* 999168709Srrs * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being 1000168709Srrs * used, then pick dest with largest ssthresh for any 1001168709Srrs * retransmission. 1002168709Srrs */ 1003214928Stuexen alt = sctp_find_alternate_net(stcb, net, 1); 1004168709Srrs /* 1005168709Srrs * CUCv2: If a different dest is picked for the 1006168709Srrs * retransmission, then new (rtx-)pseudo_cumack needs to be 1007168709Srrs * tracked for orig dest. Let CUCv2 track new (rtx-) 1008168709Srrs * pseudo-cumack always. 1009168709Srrs */ 1010168709Srrs net->find_pseudo_cumack = 1; 1011168709Srrs net->find_rtx_pseudo_cumack = 1; 1012168709Srrs } else { /* CMT is OFF */ 1013168709Srrs alt = sctp_find_alternate_net(stcb, net, 0); 1014168709Srrs } 1015210599Srrs num_mk = 0; 1016210599Srrs num_abandoned = 0; 1017210599Srrs (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe, 1018210599Srrs &num_mk, &num_abandoned); 1019163953Srrs /* FR Loss recovery just ended with the T3. */ 1020163953Srrs stcb->asoc.fast_retran_loss_recovery = 0; 1021163953Srrs 1022163953Srrs /* CMT FR loss recovery ended with the T3 */ 1023163953Srrs net->fast_retran_loss_recovery = 0; 1024219057Srrs if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) && 1025219057Srrs (net->flight_size == 0)) { 1026219057Srrs (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net); 1027219057Srrs } 1028163953Srrs /* 1029163953Srrs * setup the sat loss recovery that prevents satellite cwnd advance. 1030163953Srrs */ 1031163953Srrs stcb->asoc.sat_t3_loss_recovery = 1; 1032163953Srrs stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq; 1033163953Srrs 1034163953Srrs /* Backoff the timer and cwnd */ 1035210599Srrs sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned); 1036163953Srrs if (win_probe == 0) { 1037163953Srrs /* We don't do normal threshold management on window probes */ 1038163953Srrs if (sctp_threshold_management(inp, stcb, net, 1039163953Srrs stcb->asoc.max_send_times)) { 1040163953Srrs /* Association was destroyed */ 1041163953Srrs return (1); 1042163953Srrs } else { 1043163953Srrs if (net != stcb->asoc.primary_destination) { 1044163953Srrs /* send a immediate HB if our RTO is stale */ 1045163953Srrs struct timeval now; 1046163953Srrs unsigned int ms_goneby; 1047163953Srrs 1048169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 1049163953Srrs if (net->last_sent_time.tv_sec) { 1050163953Srrs ms_goneby = (now.tv_sec - net->last_sent_time.tv_sec) * 1000; 1051163953Srrs } else { 1052163953Srrs ms_goneby = 0; 1053163953Srrs } 1054163953Srrs if ((ms_goneby > net->RTO) || (net->RTO == 0)) { 1055163953Srrs /* 1056163953Srrs * no recent feed back in an RTO or 1057163953Srrs * more, request a RTT update 1058163953Srrs */ 1059221627Stuexen if (sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED) < 0) 1060185694Srrs /* 1061185694Srrs * Less than 0 means we lost 1062185694Srrs * the assoc 1063185694Srrs */ 1064185694Srrs return (1); 1065163953Srrs } 1066163953Srrs } 1067163953Srrs } 1068163953Srrs } else { 1069163953Srrs /* 1070163953Srrs * For a window probe we don't penalize the net's but only 1071163953Srrs * the association. This may fail it if SACKs are not coming 1072163953Srrs * back. If sack's are coming with rwnd locked at 0, we will 1073163953Srrs * continue to hold things waiting for rwnd to raise 1074163953Srrs */ 1075163953Srrs if (sctp_threshold_management(inp, stcb, NULL, 1076163953Srrs stcb->asoc.max_send_times)) { 1077163953Srrs /* Association was destroyed */ 1078163953Srrs return (1); 1079163953Srrs } 1080163953Srrs } 1081163953Srrs if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) { 1082163953Srrs /* Move all pending over too */ 1083212712Stuexen sctp_move_chunks_from_net(stcb, net); 1084169352Srrs 1085169352Srrs /* 1086169352Srrs * Get the address that failed, to force a new src address 1087169352Srrs * selecton and a route allocation. 1088169352Srrs */ 1089169352Srrs if (net->ro._s_addr) { 1090169352Srrs sctp_free_ifa(net->ro._s_addr); 1091169352Srrs net->ro._s_addr = NULL; 1092169352Srrs } 1093169352Srrs net->src_addr_selected = 0; 1094169352Srrs 1095169352Srrs /* Force a route allocation too */ 1096169352Srrs if (net->ro.ro_rt) { 1097169352Srrs RTFREE(net->ro.ro_rt); 1098169352Srrs net->ro.ro_rt = NULL; 1099169352Srrs } 1100163953Srrs /* Was it our primary? */ 1101163953Srrs if ((stcb->asoc.primary_destination == net) && (alt != net)) { 1102163953Srrs /* 1103163953Srrs * Yes, note it as such and find an alternate note: 1104163953Srrs * this means HB code must use this to resent the 1105163953Srrs * primary if it goes active AND if someone does a 1106163953Srrs * change-primary then this flag must be cleared 1107163953Srrs * from any net structures. 1108163953Srrs */ 1109163953Srrs if (sctp_set_primary_addr(stcb, 1110163953Srrs (struct sockaddr *)NULL, 1111163953Srrs alt) == 0) { 1112163953Srrs net->dest_state |= SCTP_ADDR_WAS_PRIMARY; 1113163953Srrs } 1114163953Srrs } 1115216669Stuexen } else if ((stcb->asoc.sctp_cmt_on_off > 0) && 1116211944Stuexen (stcb->asoc.sctp_cmt_pf > 0) && 1117211944Stuexen ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) { 1118171440Srrs /* 1119171440Srrs * JRS 5/14/07 - If the destination hasn't failed completely 1120171440Srrs * but is in PF state, a PF-heartbeat needs to be sent 1121171440Srrs * manually. 1122171440Srrs */ 1123221627Stuexen if (sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED) < 0) 1124185694Srrs /* Return less than 0 means we lost the association */ 1125185694Srrs return (1); 1126163953Srrs } 1127163953Srrs /* 1128163953Srrs * Special case for cookie-echo'ed case, we don't do output but must 1129163953Srrs * await the COOKIE-ACK before retransmission 1130163953Srrs */ 1131163953Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 1132163953Srrs /* 1133163953Srrs * Here we just reset the timer and start again since we 1134163953Srrs * have not established the asoc 1135163953Srrs */ 1136163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); 1137163953Srrs return (0); 1138163953Srrs } 1139163953Srrs if (stcb->asoc.peer_supports_prsctp) { 1140163953Srrs struct sctp_tmit_chunk *lchk; 1141163953Srrs 1142163953Srrs lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc); 1143163953Srrs /* C3. See if we need to send a Fwd-TSN */ 1144216825Stuexen if (SCTP_TSN_GT(stcb->asoc.advanced_peer_ack_point, stcb->asoc.last_acked_seq)) { 1145163953Srrs send_forward_tsn(stcb, &stcb->asoc); 1146163953Srrs if (lchk) { 1147163953Srrs /* Assure a timer is up */ 1148163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, lchk->whoTo); 1149163953Srrs } 1150163953Srrs } 1151163953Srrs } 1152179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { 1153170744Srrs sctp_log_cwnd(stcb, net, net->cwnd, SCTP_CWND_LOG_FROM_RTX); 1154170744Srrs } 1155163953Srrs return (0); 1156163953Srrs} 1157163953Srrs 1158163953Srrsint 1159163953Srrssctp_t1init_timer(struct sctp_inpcb *inp, 1160163953Srrs struct sctp_tcb *stcb, 1161163953Srrs struct sctp_nets *net) 1162163953Srrs{ 1163163953Srrs /* bump the thresholds */ 1164163953Srrs if (stcb->asoc.delayed_connection) { 1165163953Srrs /* 1166163953Srrs * special hook for delayed connection. The library did NOT 1167163953Srrs * complete the rest of its sends. 1168163953Srrs */ 1169163953Srrs stcb->asoc.delayed_connection = 0; 1170172090Srrs sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 1171163953Srrs return (0); 1172163953Srrs } 1173163953Srrs if (SCTP_GET_STATE((&stcb->asoc)) != SCTP_STATE_COOKIE_WAIT) { 1174163953Srrs return (0); 1175163953Srrs } 1176163953Srrs if (sctp_threshold_management(inp, stcb, net, 1177163953Srrs stcb->asoc.max_init_times)) { 1178163953Srrs /* Association was destroyed */ 1179163953Srrs return (1); 1180163953Srrs } 1181163953Srrs stcb->asoc.dropped_special_cnt = 0; 1182210599Srrs sctp_backoff_on_timeout(stcb, stcb->asoc.primary_destination, 1, 0, 0); 1183163953Srrs if (stcb->asoc.initial_init_rto_max < net->RTO) { 1184163953Srrs net->RTO = stcb->asoc.initial_init_rto_max; 1185163953Srrs } 1186163953Srrs if (stcb->asoc.numnets > 1) { 1187163953Srrs /* If we have more than one addr use it */ 1188163953Srrs struct sctp_nets *alt; 1189163953Srrs 1190163953Srrs alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination, 0); 1191214928Stuexen if (alt != stcb->asoc.primary_destination) { 1192212712Stuexen sctp_move_chunks_from_net(stcb, stcb->asoc.primary_destination); 1193163953Srrs stcb->asoc.primary_destination = alt; 1194163953Srrs } 1195163953Srrs } 1196163953Srrs /* Send out a new init */ 1197172090Srrs sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 1198163953Srrs return (0); 1199163953Srrs} 1200163953Srrs 1201163953Srrs/* 1202163953Srrs * For cookie and asconf we actually need to find and mark for resend, then 1203163953Srrs * increment the resend counter (after all the threshold management stuff of 1204163953Srrs * course). 1205163953Srrs */ 1206163953Srrsint 1207163953Srrssctp_cookie_timer(struct sctp_inpcb *inp, 1208163953Srrs struct sctp_tcb *stcb, 1209163953Srrs struct sctp_nets *net) 1210163953Srrs{ 1211163953Srrs struct sctp_nets *alt; 1212163953Srrs struct sctp_tmit_chunk *cookie; 1213163953Srrs 1214163953Srrs /* first before all else we must find the cookie */ 1215163953Srrs TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, sctp_next) { 1216163953Srrs if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 1217163953Srrs break; 1218163953Srrs } 1219163953Srrs } 1220163953Srrs if (cookie == NULL) { 1221163953Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 1222163953Srrs /* FOOBAR! */ 1223163953Srrs struct mbuf *oper; 1224163953Srrs 1225163953Srrs oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), 1226163953Srrs 0, M_DONTWAIT, 1, MT_DATA); 1227163953Srrs if (oper) { 1228163953Srrs struct sctp_paramhdr *ph; 1229163953Srrs uint32_t *ippp; 1230163953Srrs 1231165647Srrs SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + 1232163953Srrs sizeof(uint32_t); 1233163953Srrs ph = mtod(oper, struct sctp_paramhdr *); 1234163953Srrs ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); 1235165647Srrs ph->param_length = htons(SCTP_BUF_LEN(oper)); 1236163953Srrs ippp = (uint32_t *) (ph + 1); 1237171440Srrs *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); 1238163953Srrs } 1239171440Srrs inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4; 1240163953Srrs sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR, 1241172090Srrs oper, SCTP_SO_NOT_LOCKED); 1242163953Srrs } else { 1243165220Srrs#ifdef INVARIANTS 1244163953Srrs panic("Cookie timer expires in wrong state?"); 1245163953Srrs#else 1246169420Srrs SCTP_PRINTF("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(&stcb->asoc)); 1247163953Srrs return (0); 1248163953Srrs#endif 1249163953Srrs } 1250163953Srrs return (0); 1251163953Srrs } 1252163953Srrs /* Ok we found the cookie, threshold management next */ 1253163953Srrs if (sctp_threshold_management(inp, stcb, cookie->whoTo, 1254163953Srrs stcb->asoc.max_init_times)) { 1255163953Srrs /* Assoc is over */ 1256163953Srrs return (1); 1257163953Srrs } 1258163953Srrs /* 1259163953Srrs * cleared theshold management now lets backoff the address & select 1260163953Srrs * an alternate 1261163953Srrs */ 1262163953Srrs stcb->asoc.dropped_special_cnt = 0; 1263210599Srrs sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0, 0); 1264163953Srrs alt = sctp_find_alternate_net(stcb, cookie->whoTo, 0); 1265163953Srrs if (alt != cookie->whoTo) { 1266163953Srrs sctp_free_remote_addr(cookie->whoTo); 1267163953Srrs cookie->whoTo = alt; 1268163953Srrs atomic_add_int(&alt->ref_count, 1); 1269163953Srrs } 1270163953Srrs /* Now mark the retran info */ 1271163953Srrs if (cookie->sent != SCTP_DATAGRAM_RESEND) { 1272163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1273163953Srrs } 1274163953Srrs cookie->sent = SCTP_DATAGRAM_RESEND; 1275163953Srrs /* 1276163953Srrs * Now call the output routine to kick out the cookie again, Note we 1277163953Srrs * don't mark any chunks for retran so that FR will need to kick in 1278163953Srrs * to move these (or a send timer). 1279163953Srrs */ 1280163953Srrs return (0); 1281163953Srrs} 1282163953Srrs 1283163953Srrsint 1284163953Srrssctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1285163953Srrs struct sctp_nets *net) 1286163953Srrs{ 1287163953Srrs struct sctp_nets *alt; 1288163953Srrs struct sctp_tmit_chunk *strrst = NULL, *chk = NULL; 1289163953Srrs 1290163953Srrs if (stcb->asoc.stream_reset_outstanding == 0) { 1291163953Srrs return (0); 1292163953Srrs } 1293163953Srrs /* find the existing STRRESET, we use the seq number we sent out on */ 1294169420Srrs (void)sctp_find_stream_reset(stcb, stcb->asoc.str_reset_seq_out, &strrst); 1295163953Srrs if (strrst == NULL) { 1296163953Srrs return (0); 1297163953Srrs } 1298163953Srrs /* do threshold management */ 1299163953Srrs if (sctp_threshold_management(inp, stcb, strrst->whoTo, 1300163953Srrs stcb->asoc.max_send_times)) { 1301163953Srrs /* Assoc is over */ 1302163953Srrs return (1); 1303163953Srrs } 1304163953Srrs /* 1305163953Srrs * cleared theshold management now lets backoff the address & select 1306163953Srrs * an alternate 1307163953Srrs */ 1308210599Srrs sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0, 0); 1309163953Srrs alt = sctp_find_alternate_net(stcb, strrst->whoTo, 0); 1310163953Srrs sctp_free_remote_addr(strrst->whoTo); 1311163953Srrs strrst->whoTo = alt; 1312163953Srrs atomic_add_int(&alt->ref_count, 1); 1313163953Srrs 1314163953Srrs /* See if a ECN Echo is also stranded */ 1315163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 1316163953Srrs if ((chk->whoTo == net) && 1317163953Srrs (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 1318163953Srrs sctp_free_remote_addr(chk->whoTo); 1319163953Srrs if (chk->sent != SCTP_DATAGRAM_RESEND) { 1320163953Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1321163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1322163953Srrs } 1323163953Srrs chk->whoTo = alt; 1324163953Srrs atomic_add_int(&alt->ref_count, 1); 1325163953Srrs } 1326163953Srrs } 1327163953Srrs if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) { 1328163953Srrs /* 1329163953Srrs * If the address went un-reachable, we need to move to 1330163953Srrs * alternates for ALL chk's in queue 1331163953Srrs */ 1332212712Stuexen sctp_move_chunks_from_net(stcb, net); 1333163953Srrs } 1334163953Srrs /* mark the retran info */ 1335163953Srrs if (strrst->sent != SCTP_DATAGRAM_RESEND) 1336163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1337163953Srrs strrst->sent = SCTP_DATAGRAM_RESEND; 1338163953Srrs 1339163953Srrs /* restart the timer */ 1340163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, inp, stcb, strrst->whoTo); 1341163953Srrs return (0); 1342163953Srrs} 1343163953Srrs 1344163953Srrsint 1345163953Srrssctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1346163953Srrs struct sctp_nets *net) 1347163953Srrs{ 1348163953Srrs struct sctp_nets *alt; 1349216822Stuexen struct sctp_tmit_chunk *asconf, *chk; 1350163953Srrs 1351171572Srrs /* is this a first send, or a retransmission? */ 1352179157Srrs if (TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) { 1353163953Srrs /* compose a new ASCONF chunk and send it */ 1354172190Srrs sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 1355163953Srrs } else { 1356171572Srrs /* 1357171572Srrs * Retransmission of the existing ASCONF is needed 1358171572Srrs */ 1359163953Srrs 1360163953Srrs /* find the existing ASCONF */ 1361179157Srrs asconf = TAILQ_FIRST(&stcb->asoc.asconf_send_queue); 1362163953Srrs if (asconf == NULL) { 1363163953Srrs return (0); 1364163953Srrs } 1365163953Srrs /* do threshold management */ 1366163953Srrs if (sctp_threshold_management(inp, stcb, asconf->whoTo, 1367163953Srrs stcb->asoc.max_send_times)) { 1368163953Srrs /* Assoc is over */ 1369163953Srrs return (1); 1370163953Srrs } 1371163953Srrs if (asconf->snd_count > stcb->asoc.max_send_times) { 1372163953Srrs /* 1373171572Srrs * Something is rotten: our peer is not responding 1374171572Srrs * to ASCONFs but apparently is to other chunks. 1375171572Srrs * i.e. it is not properly handling the chunk type 1376171572Srrs * upper bits. Mark this peer as ASCONF incapable 1377171572Srrs * and cleanup. 1378163953Srrs */ 1379169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "asconf_timer: Peer has not responded to our repeated ASCONFs\n"); 1380163953Srrs sctp_asconf_cleanup(stcb, net); 1381163953Srrs return (0); 1382163953Srrs } 1383163953Srrs /* 1384171572Srrs * cleared threshold management, so now backoff the net and 1385171572Srrs * select an alternate 1386163953Srrs */ 1387210599Srrs sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0, 0); 1388163953Srrs alt = sctp_find_alternate_net(stcb, asconf->whoTo, 0); 1389179157Srrs if (asconf->whoTo != alt) { 1390179157Srrs sctp_free_remote_addr(asconf->whoTo); 1391179157Srrs asconf->whoTo = alt; 1392179157Srrs atomic_add_int(&alt->ref_count, 1); 1393179157Srrs } 1394171572Srrs /* See if an ECN Echo is also stranded */ 1395163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 1396163953Srrs if ((chk->whoTo == net) && 1397163953Srrs (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 1398163953Srrs sctp_free_remote_addr(chk->whoTo); 1399163953Srrs chk->whoTo = alt; 1400163953Srrs if (chk->sent != SCTP_DATAGRAM_RESEND) { 1401163953Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1402163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1403163953Srrs } 1404163953Srrs atomic_add_int(&alt->ref_count, 1); 1405163953Srrs } 1406163953Srrs } 1407216822Stuexen TAILQ_FOREACH(chk, &stcb->asoc.asconf_send_queue, sctp_next) { 1408179157Srrs if (chk->whoTo != alt) { 1409179157Srrs sctp_free_remote_addr(chk->whoTo); 1410179157Srrs chk->whoTo = alt; 1411179157Srrs atomic_add_int(&alt->ref_count, 1); 1412179157Srrs } 1413179157Srrs if (asconf->sent != SCTP_DATAGRAM_RESEND && chk->sent != SCTP_DATAGRAM_UNSENT) 1414179157Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1415179157Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1416179157Srrs } 1417163953Srrs if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) { 1418163953Srrs /* 1419163953Srrs * If the address went un-reachable, we need to move 1420171572Srrs * to the alternate for ALL chunks in queue 1421163953Srrs */ 1422212712Stuexen sctp_move_chunks_from_net(stcb, net); 1423163953Srrs } 1424163953Srrs /* mark the retran info */ 1425163953Srrs if (asconf->sent != SCTP_DATAGRAM_RESEND) 1426163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1427163953Srrs asconf->sent = SCTP_DATAGRAM_RESEND; 1428179157Srrs 1429179157Srrs /* send another ASCONF if any and we can do */ 1430179157Srrs sctp_send_asconf(stcb, alt, SCTP_ADDR_NOT_LOCKED); 1431163953Srrs } 1432163953Srrs return (0); 1433163953Srrs} 1434163953Srrs 1435172091Srrs/* Mobility adaptation */ 1436172156Srrsvoid 1437172091Srrssctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1438172091Srrs struct sctp_nets *net) 1439172091Srrs{ 1440172091Srrs if (stcb->asoc.deleted_primary == NULL) { 1441172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n"); 1442172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 1443172156Srrs return; 1444172091Srrs } 1445172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: finished to keep deleted primary "); 1446172091Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 1447172091Srrs sctp_free_remote_addr(stcb->asoc.deleted_primary); 1448172091Srrs stcb->asoc.deleted_primary = NULL; 1449172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 1450172156Srrs return; 1451172091Srrs} 1452172091Srrs 1453163953Srrs/* 1454163953Srrs * For the shutdown and shutdown-ack, we do not keep one around on the 1455163953Srrs * control queue. This means we must generate a new one and call the general 1456163953Srrs * chunk output routine, AFTER having done threshold management. 1457214928Stuexen * It is assumed that net is non-NULL. 1458163953Srrs */ 1459163953Srrsint 1460163953Srrssctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1461163953Srrs struct sctp_nets *net) 1462163953Srrs{ 1463163953Srrs struct sctp_nets *alt; 1464163953Srrs 1465163953Srrs /* first threshold managment */ 1466163953Srrs if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1467163953Srrs /* Assoc is over */ 1468163953Srrs return (1); 1469163953Srrs } 1470214928Stuexen sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 1471163953Srrs /* second select an alternative */ 1472163953Srrs alt = sctp_find_alternate_net(stcb, net, 0); 1473163953Srrs 1474163953Srrs /* third generate a shutdown into the queue for out net */ 1475214928Stuexen sctp_send_shutdown(stcb, alt); 1476214928Stuexen 1477163953Srrs /* fourth restart timer */ 1478163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt); 1479163953Srrs return (0); 1480163953Srrs} 1481163953Srrs 1482163953Srrsint 1483163953Srrssctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1484163953Srrs struct sctp_nets *net) 1485163953Srrs{ 1486163953Srrs struct sctp_nets *alt; 1487163953Srrs 1488163953Srrs /* first threshold managment */ 1489163953Srrs if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1490163953Srrs /* Assoc is over */ 1491163953Srrs return (1); 1492163953Srrs } 1493214928Stuexen sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 1494163953Srrs /* second select an alternative */ 1495163953Srrs alt = sctp_find_alternate_net(stcb, net, 0); 1496163953Srrs 1497163953Srrs /* third generate a shutdown into the queue for out net */ 1498163953Srrs sctp_send_shutdown_ack(stcb, alt); 1499163953Srrs 1500163953Srrs /* fourth restart timer */ 1501163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt); 1502163953Srrs return (0); 1503163953Srrs} 1504163953Srrs 1505163953Srrsstatic void 1506163953Srrssctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, 1507163953Srrs struct sctp_tcb *stcb) 1508163953Srrs{ 1509163953Srrs struct sctp_stream_queue_pending *sp; 1510217760Stuexen unsigned int i, chks_in_queue = 0; 1511163953Srrs int being_filled = 0; 1512163953Srrs 1513163953Srrs /* 1514163953Srrs * This function is ONLY called when the send/sent queues are empty. 1515163953Srrs */ 1516163953Srrs if ((stcb == NULL) || (inp == NULL)) 1517163953Srrs return; 1518163953Srrs 1519163953Srrs if (stcb->asoc.sent_queue_retran_cnt) { 1520169420Srrs SCTP_PRINTF("Hmm, sent_queue_retran_cnt is non-zero %d\n", 1521163953Srrs stcb->asoc.sent_queue_retran_cnt); 1522163953Srrs stcb->asoc.sent_queue_retran_cnt = 0; 1523163953Srrs } 1524217760Stuexen if (stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { 1525218241Stuexen /* No stream scheduler information, initialize scheduler */ 1526218241Stuexen stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 0); 1527218241Stuexen if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { 1528218241Stuexen /* yep, we lost a stream or two */ 1529218241Stuexen SCTP_PRINTF("Found additional streams NOT managed by scheduler, corrected\n"); 1530163953Srrs } else { 1531218241Stuexen /* no streams lost */ 1532163953Srrs stcb->asoc.total_output_queue_size = 0; 1533163953Srrs } 1534163953Srrs } 1535163953Srrs /* Check to see if some data queued, if so report it */ 1536217760Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1537217760Stuexen if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { 1538217760Stuexen TAILQ_FOREACH(sp, &stcb->asoc.strmout[i].outqueue, next) { 1539163953Srrs if (sp->msg_is_complete) 1540163953Srrs being_filled++; 1541163953Srrs chks_in_queue++; 1542163953Srrs } 1543163953Srrs } 1544163953Srrs } 1545163953Srrs if (chks_in_queue != stcb->asoc.stream_queue_cnt) { 1546169420Srrs SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n", 1547163953Srrs stcb->asoc.stream_queue_cnt, chks_in_queue); 1548163953Srrs } 1549163953Srrs if (chks_in_queue) { 1550163953Srrs /* call the output queue function */ 1551172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1552163953Srrs if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) && 1553163953Srrs (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1554163953Srrs /* 1555163953Srrs * Probably should go in and make it go back through 1556163953Srrs * and add fragments allowed 1557163953Srrs */ 1558163953Srrs if (being_filled == 0) { 1559169420Srrs SCTP_PRINTF("Still nothing moved %d chunks are stuck\n", 1560163953Srrs chks_in_queue); 1561163953Srrs } 1562163953Srrs } 1563163953Srrs } else { 1564169420Srrs SCTP_PRINTF("Found no chunks on any queue tot:%lu\n", 1565163953Srrs (u_long)stcb->asoc.total_output_queue_size); 1566163953Srrs stcb->asoc.total_output_queue_size = 0; 1567163953Srrs } 1568163953Srrs} 1569163953Srrs 1570163953Srrsint 1571163953Srrssctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1572163953Srrs struct sctp_nets *net, int cnt_of_unconf) 1573163953Srrs{ 1574171440Srrs int ret; 1575171440Srrs 1576163953Srrs if (net) { 1577163953Srrs if (net->hb_responded == 0) { 1578167598Srrs if (net->ro._s_addr) { 1579167598Srrs /* 1580167598Srrs * Invalidate the src address if we did not 1581167598Srrs * get a response last time. 1582167598Srrs */ 1583167598Srrs sctp_free_ifa(net->ro._s_addr); 1584167598Srrs net->ro._s_addr = NULL; 1585167598Srrs net->src_addr_selected = 0; 1586167598Srrs } 1587210599Srrs sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 1588163953Srrs } 1589163953Srrs /* Zero PBA, if it needs it */ 1590163953Srrs if (net->partial_bytes_acked) { 1591163953Srrs net->partial_bytes_acked = 0; 1592163953Srrs } 1593163953Srrs } 1594163953Srrs if ((stcb->asoc.total_output_queue_size > 0) && 1595163953Srrs (TAILQ_EMPTY(&stcb->asoc.send_queue)) && 1596163953Srrs (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1597163953Srrs sctp_audit_stream_queues_for_size(inp, stcb); 1598163953Srrs } 1599163953Srrs /* Send a new HB, this will do threshold managment, pick a new dest */ 1600163953Srrs if (cnt_of_unconf == 0) { 1601221627Stuexen if (sctp_send_hb(stcb, 0, NULL, SCTP_SO_NOT_LOCKED) < 0) { 1602163953Srrs return (1); 1603163953Srrs } 1604163953Srrs } else { 1605163953Srrs /* 1606163953Srrs * this will send out extra hb's up to maxburst if there are 1607163953Srrs * any unconfirmed addresses. 1608163953Srrs */ 1609170056Srrs uint32_t cnt_sent = 0; 1610163953Srrs 1611163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1612163953Srrs if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 1613163953Srrs (net->dest_state & SCTP_ADDR_REACHABLE)) { 1614163953Srrs cnt_sent++; 1615167598Srrs if (net->hb_responded == 0) { 1616167598Srrs /* Did we respond last time? */ 1617167598Srrs if (net->ro._s_addr) { 1618167598Srrs sctp_free_ifa(net->ro._s_addr); 1619167598Srrs net->ro._s_addr = NULL; 1620167598Srrs net->src_addr_selected = 0; 1621167598Srrs } 1622167598Srrs } 1623221627Stuexen ret = sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED); 1624171440Srrs if (ret < 0) 1625171440Srrs return 1; 1626171440Srrs else if (ret == 0) { 1627163953Srrs break; 1628163953Srrs } 1629218186Srrs if (SCTP_BASE_SYSCTL(sctp_hb_maxburst) && 1630218186Srrs (cnt_sent >= SCTP_BASE_SYSCTL(sctp_hb_maxburst))) 1631163953Srrs break; 1632163953Srrs } 1633163953Srrs } 1634163953Srrs } 1635163953Srrs return (0); 1636163953Srrs} 1637163953Srrs 1638163953Srrsvoid 1639163953Srrssctp_pathmtu_timer(struct sctp_inpcb *inp, 1640163953Srrs struct sctp_tcb *stcb, 1641163953Srrs struct sctp_nets *net) 1642163953Srrs{ 1643179157Srrs uint32_t next_mtu, mtu; 1644163953Srrs 1645214939Stuexen next_mtu = sctp_get_next_mtu(inp, net->mtu); 1646169352Srrs 1647179157Srrs if ((next_mtu > net->mtu) && (net->port == 0)) { 1648169352Srrs if ((net->src_addr_selected == 0) || 1649169352Srrs (net->ro._s_addr == NULL) || 1650169352Srrs (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 1651169420Srrs if ((net->ro._s_addr != NULL) && (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 1652169352Srrs sctp_free_ifa(net->ro._s_addr); 1653169352Srrs net->ro._s_addr = NULL; 1654169352Srrs net->src_addr_selected = 0; 1655169420Srrs } else if (net->ro._s_addr == NULL) { 1656179157Srrs#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE) 1657179157Srrs if (net->ro._l_addr.sa.sa_family == AF_INET6) { 1658179157Srrs struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1659179157Srrs 1660179157Srrs /* KAME hack: embed scopeid */ 1661197288Srrs (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); 1662179157Srrs } 1663179157Srrs#endif 1664179157Srrs 1665169420Srrs net->ro._s_addr = sctp_source_address_selection(inp, 1666169420Srrs stcb, 1667169420Srrs (sctp_route_t *) & net->ro, 1668169420Srrs net, 0, stcb->asoc.vrf_id); 1669179157Srrs#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE) 1670179157Srrs if (net->ro._l_addr.sa.sa_family == AF_INET6) { 1671179157Srrs struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1672179157Srrs 1673179157Srrs (void)sa6_recoverscope(sin6); 1674179157Srrs } 1675179157Srrs#endif /* INET6 */ 1676169352Srrs } 1677169352Srrs if (net->ro._s_addr) 1678169352Srrs net->src_addr_selected = 1; 1679169352Srrs } 1680169352Srrs if (net->ro._s_addr) { 1681169352Srrs mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt); 1682185694Srrs if (net->port) { 1683185694Srrs mtu -= sizeof(struct udphdr); 1684185694Srrs } 1685169352Srrs if (mtu > next_mtu) { 1686163953Srrs net->mtu = next_mtu; 1687163953Srrs } 1688163953Srrs } 1689163953Srrs } 1690163953Srrs /* restart the timer */ 1691163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); 1692163953Srrs} 1693163953Srrs 1694163953Srrsvoid 1695163953Srrssctp_autoclose_timer(struct sctp_inpcb *inp, 1696163953Srrs struct sctp_tcb *stcb, 1697163953Srrs struct sctp_nets *net) 1698163953Srrs{ 1699163953Srrs struct timeval tn, *tim_touse; 1700163953Srrs struct sctp_association *asoc; 1701163953Srrs int ticks_gone_by; 1702163953Srrs 1703169378Srrs (void)SCTP_GETTIME_TIMEVAL(&tn); 1704163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1705163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1706163953Srrs /* Auto close is on */ 1707163953Srrs asoc = &stcb->asoc; 1708163953Srrs /* pick the time to use */ 1709163953Srrs if (asoc->time_last_rcvd.tv_sec > 1710163953Srrs asoc->time_last_sent.tv_sec) { 1711163953Srrs tim_touse = &asoc->time_last_rcvd; 1712163953Srrs } else { 1713163953Srrs tim_touse = &asoc->time_last_sent; 1714163953Srrs } 1715163953Srrs /* Now has long enough transpired to autoclose? */ 1716163953Srrs ticks_gone_by = SEC_TO_TICKS(tn.tv_sec - tim_touse->tv_sec); 1717163953Srrs if ((ticks_gone_by > 0) && 1718163953Srrs (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) { 1719163953Srrs /* 1720163953Srrs * autoclose time has hit, call the output routine, 1721163953Srrs * which should do nothing just to be SURE we don't 1722163953Srrs * have hanging data. We can then safely check the 1723163953Srrs * queues and know that we are clear to send 1724163953Srrs * shutdown 1725163953Srrs */ 1726172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 1727163953Srrs /* Are we clean? */ 1728163953Srrs if (TAILQ_EMPTY(&asoc->send_queue) && 1729163953Srrs TAILQ_EMPTY(&asoc->sent_queue)) { 1730163953Srrs /* 1731163953Srrs * there is nothing queued to send, so I'm 1732163953Srrs * done... 1733163953Srrs */ 1734166675Srrs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1735163953Srrs /* only send SHUTDOWN 1st time thru */ 1736163953Srrs sctp_send_shutdown(stcb, stcb->asoc.primary_destination); 1737166675Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 1738166675Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1739166675Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1740166675Srrs } 1741171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); 1742172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 1743163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, 1744163953Srrs stcb->sctp_ep, stcb, 1745163953Srrs asoc->primary_destination); 1746163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1747163953Srrs stcb->sctp_ep, stcb, 1748163953Srrs asoc->primary_destination); 1749163953Srrs } 1750163953Srrs } 1751163953Srrs } else { 1752163953Srrs /* 1753163953Srrs * No auto close at this time, reset t-o to check 1754163953Srrs * later 1755163953Srrs */ 1756163953Srrs int tmp; 1757163953Srrs 1758163953Srrs /* fool the timer startup to use the time left */ 1759163953Srrs tmp = asoc->sctp_autoclose_ticks; 1760163953Srrs asoc->sctp_autoclose_ticks -= ticks_gone_by; 1761163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1762163953Srrs net); 1763163953Srrs /* restore the real tick value */ 1764163953Srrs asoc->sctp_autoclose_ticks = tmp; 1765163953Srrs } 1766163953Srrs } 1767163953Srrs} 1768