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