sctp_timer.c revision 172156
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 172156 2007-09-13 10:36:43Z 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) { 146172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED); 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, 222172090Srrs (void *)net, SCTP_SO_NOT_LOCKED); 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; 283172090Srrs sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper, SCTP_SO_NOT_LOCKED); 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), 705172090Srrs &stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED); 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), 717172090Srrs &stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED); 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; 1135172090Srrs sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 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 */ 1162172090Srrs sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 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, 1206172090Srrs oper, SCTP_SO_NOT_LOCKED); 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 1391172091Srrs/* Mobility adaptation */ 1392172156Srrsvoid 1393172091Srrssctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1394172091Srrs struct sctp_nets *net) 1395172091Srrs{ 1396172091Srrs if (stcb->asoc.deleted_primary == NULL) { 1397172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n"); 1398172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 1399172156Srrs return; 1400172091Srrs } 1401172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: finished to keep deleted primary "); 1402172091Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 1403172091Srrs sctp_free_remote_addr(stcb->asoc.deleted_primary); 1404172091Srrs stcb->asoc.deleted_primary = NULL; 1405172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 1406172156Srrs return; 1407172091Srrs} 1408172091Srrs 1409163953Srrs/* 1410163953Srrs * For the shutdown and shutdown-ack, we do not keep one around on the 1411163953Srrs * control queue. This means we must generate a new one and call the general 1412163953Srrs * chunk output routine, AFTER having done threshold management. 1413163953Srrs */ 1414163953Srrsint 1415163953Srrssctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1416163953Srrs struct sctp_nets *net) 1417163953Srrs{ 1418163953Srrs struct sctp_nets *alt; 1419163953Srrs 1420163953Srrs /* first threshold managment */ 1421163953Srrs if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1422163953Srrs /* Assoc is over */ 1423163953Srrs return (1); 1424163953Srrs } 1425163953Srrs /* second select an alternative */ 1426163953Srrs alt = sctp_find_alternate_net(stcb, net, 0); 1427163953Srrs 1428163953Srrs /* third generate a shutdown into the queue for out net */ 1429163953Srrs if (alt) { 1430163953Srrs sctp_send_shutdown(stcb, alt); 1431163953Srrs } else { 1432163953Srrs /* 1433163953Srrs * if alt is NULL, there is no dest to send to?? 1434163953Srrs */ 1435163953Srrs return (0); 1436163953Srrs } 1437163953Srrs /* fourth restart timer */ 1438163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt); 1439163953Srrs return (0); 1440163953Srrs} 1441163953Srrs 1442163953Srrsint 1443163953Srrssctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1444163953Srrs struct sctp_nets *net) 1445163953Srrs{ 1446163953Srrs struct sctp_nets *alt; 1447163953Srrs 1448163953Srrs /* first threshold managment */ 1449163953Srrs if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1450163953Srrs /* Assoc is over */ 1451163953Srrs return (1); 1452163953Srrs } 1453163953Srrs /* second select an alternative */ 1454163953Srrs alt = sctp_find_alternate_net(stcb, net, 0); 1455163953Srrs 1456163953Srrs /* third generate a shutdown into the queue for out net */ 1457163953Srrs sctp_send_shutdown_ack(stcb, alt); 1458163953Srrs 1459163953Srrs /* fourth restart timer */ 1460163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt); 1461163953Srrs return (0); 1462163953Srrs} 1463163953Srrs 1464163953Srrsstatic void 1465163953Srrssctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, 1466163953Srrs struct sctp_tcb *stcb) 1467163953Srrs{ 1468163953Srrs struct sctp_stream_out *outs; 1469163953Srrs struct sctp_stream_queue_pending *sp; 1470163953Srrs unsigned int chks_in_queue = 0; 1471163953Srrs int being_filled = 0; 1472163953Srrs 1473163953Srrs /* 1474163953Srrs * This function is ONLY called when the send/sent queues are empty. 1475163953Srrs */ 1476163953Srrs if ((stcb == NULL) || (inp == NULL)) 1477163953Srrs return; 1478163953Srrs 1479163953Srrs if (stcb->asoc.sent_queue_retran_cnt) { 1480169420Srrs SCTP_PRINTF("Hmm, sent_queue_retran_cnt is non-zero %d\n", 1481163953Srrs stcb->asoc.sent_queue_retran_cnt); 1482163953Srrs stcb->asoc.sent_queue_retran_cnt = 0; 1483163953Srrs } 1484163953Srrs SCTP_TCB_SEND_LOCK(stcb); 1485163953Srrs if (TAILQ_EMPTY(&stcb->asoc.out_wheel)) { 1486163953Srrs int i, cnt = 0; 1487163953Srrs 1488163953Srrs /* Check to see if a spoke fell off the wheel */ 1489163953Srrs for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1490163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { 1491163953Srrs sctp_insert_on_wheel(stcb, &stcb->asoc, &stcb->asoc.strmout[i], 1); 1492163953Srrs cnt++; 1493163953Srrs } 1494163953Srrs } 1495163953Srrs if (cnt) { 1496163953Srrs /* yep, we lost a spoke or two */ 1497169420Srrs SCTP_PRINTF("Found an additional %d streams NOT on outwheel, corrected\n", cnt); 1498163953Srrs } else { 1499163953Srrs /* no spokes lost, */ 1500163953Srrs stcb->asoc.total_output_queue_size = 0; 1501163953Srrs } 1502163953Srrs SCTP_TCB_SEND_UNLOCK(stcb); 1503163953Srrs return; 1504163953Srrs } 1505163953Srrs SCTP_TCB_SEND_UNLOCK(stcb); 1506163953Srrs /* Check to see if some data queued, if so report it */ 1507163953Srrs TAILQ_FOREACH(outs, &stcb->asoc.out_wheel, next_spoke) { 1508163953Srrs if (!TAILQ_EMPTY(&outs->outqueue)) { 1509163953Srrs TAILQ_FOREACH(sp, &outs->outqueue, next) { 1510163953Srrs if (sp->msg_is_complete) 1511163953Srrs being_filled++; 1512163953Srrs chks_in_queue++; 1513163953Srrs } 1514163953Srrs } 1515163953Srrs } 1516163953Srrs if (chks_in_queue != stcb->asoc.stream_queue_cnt) { 1517169420Srrs SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n", 1518163953Srrs stcb->asoc.stream_queue_cnt, chks_in_queue); 1519163953Srrs } 1520163953Srrs if (chks_in_queue) { 1521163953Srrs /* call the output queue function */ 1522172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1523163953Srrs if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) && 1524163953Srrs (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1525163953Srrs /* 1526163953Srrs * Probably should go in and make it go back through 1527163953Srrs * and add fragments allowed 1528163953Srrs */ 1529163953Srrs if (being_filled == 0) { 1530169420Srrs SCTP_PRINTF("Still nothing moved %d chunks are stuck\n", 1531163953Srrs chks_in_queue); 1532163953Srrs } 1533163953Srrs } 1534163953Srrs } else { 1535169420Srrs SCTP_PRINTF("Found no chunks on any queue tot:%lu\n", 1536163953Srrs (u_long)stcb->asoc.total_output_queue_size); 1537163953Srrs stcb->asoc.total_output_queue_size = 0; 1538163953Srrs } 1539163953Srrs} 1540163953Srrs 1541163953Srrsint 1542163953Srrssctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1543163953Srrs struct sctp_nets *net, int cnt_of_unconf) 1544163953Srrs{ 1545171440Srrs int ret; 1546171440Srrs 1547163953Srrs if (net) { 1548163953Srrs if (net->hb_responded == 0) { 1549167598Srrs if (net->ro._s_addr) { 1550167598Srrs /* 1551167598Srrs * Invalidate the src address if we did not 1552167598Srrs * get a response last time. 1553167598Srrs */ 1554167598Srrs sctp_free_ifa(net->ro._s_addr); 1555167598Srrs net->ro._s_addr = NULL; 1556167598Srrs net->src_addr_selected = 0; 1557167598Srrs } 1558163953Srrs sctp_backoff_on_timeout(stcb, net, 1, 0); 1559163953Srrs } 1560163953Srrs /* Zero PBA, if it needs it */ 1561163953Srrs if (net->partial_bytes_acked) { 1562163953Srrs net->partial_bytes_acked = 0; 1563163953Srrs } 1564163953Srrs } 1565163953Srrs if ((stcb->asoc.total_output_queue_size > 0) && 1566163953Srrs (TAILQ_EMPTY(&stcb->asoc.send_queue)) && 1567163953Srrs (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1568163953Srrs sctp_audit_stream_queues_for_size(inp, stcb); 1569163953Srrs } 1570163953Srrs /* Send a new HB, this will do threshold managment, pick a new dest */ 1571163953Srrs if (cnt_of_unconf == 0) { 1572163953Srrs if (sctp_send_hb(stcb, 0, NULL) < 0) { 1573163953Srrs return (1); 1574163953Srrs } 1575163953Srrs } else { 1576163953Srrs /* 1577163953Srrs * this will send out extra hb's up to maxburst if there are 1578163953Srrs * any unconfirmed addresses. 1579163953Srrs */ 1580170056Srrs uint32_t cnt_sent = 0; 1581163953Srrs 1582163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1583163953Srrs if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 1584163953Srrs (net->dest_state & SCTP_ADDR_REACHABLE)) { 1585163953Srrs cnt_sent++; 1586167598Srrs if (net->hb_responded == 0) { 1587167598Srrs /* Did we respond last time? */ 1588167598Srrs if (net->ro._s_addr) { 1589167598Srrs sctp_free_ifa(net->ro._s_addr); 1590167598Srrs net->ro._s_addr = NULL; 1591167598Srrs net->src_addr_selected = 0; 1592167598Srrs } 1593167598Srrs } 1594171440Srrs ret = sctp_send_hb(stcb, 1, net); 1595171440Srrs if (ret < 0) 1596171440Srrs return 1; 1597171440Srrs else if (ret == 0) { 1598163953Srrs break; 1599163953Srrs } 1600167598Srrs if (cnt_sent >= sctp_hb_maxburst) 1601163953Srrs break; 1602163953Srrs } 1603163953Srrs } 1604163953Srrs } 1605163953Srrs return (0); 1606163953Srrs} 1607163953Srrs 1608163953Srrsint 1609163953Srrssctp_is_hb_timer_running(struct sctp_tcb *stcb) 1610163953Srrs{ 1611165647Srrs if (SCTP_OS_TIMER_PENDING(&stcb->asoc.hb_timer.timer)) { 1612163953Srrs /* its running */ 1613163953Srrs return (1); 1614163953Srrs } else { 1615163953Srrs /* nope */ 1616163953Srrs return (0); 1617163953Srrs } 1618163953Srrs} 1619163953Srrs 1620163953Srrsint 1621163953Srrssctp_is_sack_timer_running(struct sctp_tcb *stcb) 1622163953Srrs{ 1623165647Srrs if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 1624163953Srrs /* its running */ 1625163953Srrs return (1); 1626163953Srrs } else { 1627163953Srrs /* nope */ 1628163953Srrs return (0); 1629163953Srrs } 1630163953Srrs} 1631163953Srrs 1632163953Srrs#define SCTP_NUMBER_OF_MTU_SIZES 18 1633163953Srrsstatic uint32_t mtu_sizes[] = { 1634163953Srrs 68, 1635163953Srrs 296, 1636163953Srrs 508, 1637163953Srrs 512, 1638163953Srrs 544, 1639163953Srrs 576, 1640163953Srrs 1006, 1641163953Srrs 1492, 1642163953Srrs 1500, 1643163953Srrs 1536, 1644163953Srrs 2002, 1645163953Srrs 2048, 1646163953Srrs 4352, 1647163953Srrs 4464, 1648163953Srrs 8166, 1649163953Srrs 17914, 1650163953Srrs 32000, 1651163953Srrs 65535 1652163953Srrs}; 1653163953Srrs 1654163953Srrs 1655163953Srrsstatic uint32_t 1656163953Srrssctp_getnext_mtu(struct sctp_inpcb *inp, uint32_t cur_mtu) 1657163953Srrs{ 1658163953Srrs /* select another MTU that is just bigger than this one */ 1659163953Srrs int i; 1660163953Srrs 1661163953Srrs for (i = 0; i < SCTP_NUMBER_OF_MTU_SIZES; i++) { 1662163953Srrs if (cur_mtu < mtu_sizes[i]) { 1663163953Srrs /* no max_mtu is bigger than this one */ 1664163953Srrs return (mtu_sizes[i]); 1665163953Srrs } 1666163953Srrs } 1667163953Srrs /* here return the highest allowable */ 1668163953Srrs return (cur_mtu); 1669163953Srrs} 1670163953Srrs 1671163953Srrs 1672163953Srrsvoid 1673163953Srrssctp_pathmtu_timer(struct sctp_inpcb *inp, 1674163953Srrs struct sctp_tcb *stcb, 1675163953Srrs struct sctp_nets *net) 1676163953Srrs{ 1677163953Srrs uint32_t next_mtu; 1678163953Srrs 1679163953Srrs /* restart the timer in any case */ 1680163953Srrs next_mtu = sctp_getnext_mtu(inp, net->mtu); 1681163953Srrs if (next_mtu <= net->mtu) { 1682163953Srrs /* nothing to do */ 1683163953Srrs return; 1684169352Srrs } { 1685169352Srrs uint32_t mtu; 1686169352Srrs 1687169352Srrs if ((net->src_addr_selected == 0) || 1688169352Srrs (net->ro._s_addr == NULL) || 1689169352Srrs (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 1690169420Srrs if ((net->ro._s_addr != NULL) && (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 1691169352Srrs sctp_free_ifa(net->ro._s_addr); 1692169352Srrs net->ro._s_addr = NULL; 1693169352Srrs net->src_addr_selected = 0; 1694169420Srrs } else if (net->ro._s_addr == NULL) { 1695169420Srrs net->ro._s_addr = sctp_source_address_selection(inp, 1696169420Srrs stcb, 1697169420Srrs (sctp_route_t *) & net->ro, 1698169420Srrs net, 0, stcb->asoc.vrf_id); 1699169352Srrs } 1700169352Srrs if (net->ro._s_addr) 1701169352Srrs net->src_addr_selected = 1; 1702169352Srrs } 1703169352Srrs if (net->ro._s_addr) { 1704169352Srrs mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt); 1705169352Srrs if (mtu > next_mtu) { 1706163953Srrs net->mtu = next_mtu; 1707163953Srrs } 1708163953Srrs } 1709163953Srrs } 1710163953Srrs /* restart the timer */ 1711163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); 1712163953Srrs} 1713163953Srrs 1714163953Srrsvoid 1715163953Srrssctp_autoclose_timer(struct sctp_inpcb *inp, 1716163953Srrs struct sctp_tcb *stcb, 1717163953Srrs struct sctp_nets *net) 1718163953Srrs{ 1719163953Srrs struct timeval tn, *tim_touse; 1720163953Srrs struct sctp_association *asoc; 1721163953Srrs int ticks_gone_by; 1722163953Srrs 1723169378Srrs (void)SCTP_GETTIME_TIMEVAL(&tn); 1724163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1725163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1726163953Srrs /* Auto close is on */ 1727163953Srrs asoc = &stcb->asoc; 1728163953Srrs /* pick the time to use */ 1729163953Srrs if (asoc->time_last_rcvd.tv_sec > 1730163953Srrs asoc->time_last_sent.tv_sec) { 1731163953Srrs tim_touse = &asoc->time_last_rcvd; 1732163953Srrs } else { 1733163953Srrs tim_touse = &asoc->time_last_sent; 1734163953Srrs } 1735163953Srrs /* Now has long enough transpired to autoclose? */ 1736163953Srrs ticks_gone_by = SEC_TO_TICKS(tn.tv_sec - tim_touse->tv_sec); 1737163953Srrs if ((ticks_gone_by > 0) && 1738163953Srrs (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) { 1739163953Srrs /* 1740163953Srrs * autoclose time has hit, call the output routine, 1741163953Srrs * which should do nothing just to be SURE we don't 1742163953Srrs * have hanging data. We can then safely check the 1743163953Srrs * queues and know that we are clear to send 1744163953Srrs * shutdown 1745163953Srrs */ 1746172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 1747163953Srrs /* Are we clean? */ 1748163953Srrs if (TAILQ_EMPTY(&asoc->send_queue) && 1749163953Srrs TAILQ_EMPTY(&asoc->sent_queue)) { 1750163953Srrs /* 1751163953Srrs * there is nothing queued to send, so I'm 1752163953Srrs * done... 1753163953Srrs */ 1754166675Srrs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1755163953Srrs /* only send SHUTDOWN 1st time thru */ 1756163953Srrs sctp_send_shutdown(stcb, stcb->asoc.primary_destination); 1757166675Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 1758166675Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1759166675Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1760166675Srrs } 1761171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); 1762163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, 1763163953Srrs stcb->sctp_ep, stcb, 1764163953Srrs asoc->primary_destination); 1765163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1766163953Srrs stcb->sctp_ep, stcb, 1767163953Srrs asoc->primary_destination); 1768163953Srrs } 1769163953Srrs } 1770163953Srrs } else { 1771163953Srrs /* 1772163953Srrs * No auto close at this time, reset t-o to check 1773163953Srrs * later 1774163953Srrs */ 1775163953Srrs int tmp; 1776163953Srrs 1777163953Srrs /* fool the timer startup to use the time left */ 1778163953Srrs tmp = asoc->sctp_autoclose_ticks; 1779163953Srrs asoc->sctp_autoclose_ticks -= ticks_gone_by; 1780163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1781163953Srrs net); 1782163953Srrs /* restore the real tick value */ 1783163953Srrs asoc->sctp_autoclose_ticks = tmp; 1784163953Srrs } 1785163953Srrs } 1786163953Srrs} 1787163953Srrs 1788163953Srrsvoid 1789163953Srrssctp_iterator_timer(struct sctp_iterator *it) 1790163953Srrs{ 1791163953Srrs int iteration_count = 0; 1792167598Srrs int inp_skip = 0; 1793163953Srrs 1794163953Srrs /* 1795163953Srrs * only one iterator can run at a time. This is the only way we can 1796163953Srrs * cleanly pull ep's from underneath all the running interators when 1797163953Srrs * a ep is freed. 1798163953Srrs */ 1799163953Srrs SCTP_ITERATOR_LOCK(); 1800163953Srrs if (it->inp == NULL) { 1801163953Srrs /* iterator is complete */ 1802163953Srrsdone_with_iterator: 1803163953Srrs SCTP_ITERATOR_UNLOCK(); 1804163953Srrs SCTP_INP_INFO_WLOCK(); 1805167598Srrs TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr); 1806163953Srrs /* stopping the callout is not needed, in theory */ 1807163953Srrs SCTP_INP_INFO_WUNLOCK(); 1808169378Srrs (void)SCTP_OS_TIMER_STOP(&it->tmr.timer); 1809163953Srrs if (it->function_atend != NULL) { 1810163953Srrs (*it->function_atend) (it->pointer, it->val); 1811163953Srrs } 1812170091Srrs SCTP_FREE(it, SCTP_M_ITER); 1813163953Srrs return; 1814163953Srrs } 1815163953Srrsselect_a_new_ep: 1816163953Srrs SCTP_INP_WLOCK(it->inp); 1817163953Srrs while (((it->pcb_flags) && 1818163953Srrs ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || 1819163953Srrs ((it->pcb_features) && 1820163953Srrs ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { 1821163953Srrs /* endpoint flags or features don't match, so keep looking */ 1822163953Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1823163953Srrs SCTP_INP_WUNLOCK(it->inp); 1824163953Srrs goto done_with_iterator; 1825163953Srrs } 1826163953Srrs SCTP_INP_WUNLOCK(it->inp); 1827163953Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 1828163953Srrs if (it->inp == NULL) { 1829163953Srrs goto done_with_iterator; 1830163953Srrs } 1831163953Srrs SCTP_INP_WLOCK(it->inp); 1832163953Srrs } 1833163953Srrs if ((it->inp->inp_starting_point_for_iterator != NULL) && 1834163953Srrs (it->inp->inp_starting_point_for_iterator != it)) { 1835169420Srrs SCTP_PRINTF("Iterator collision, waiting for one at %p\n", 1836163979Sru it->inp); 1837163953Srrs SCTP_INP_WUNLOCK(it->inp); 1838163953Srrs goto start_timer_return; 1839163953Srrs } 1840163953Srrs /* mark the current iterator on the endpoint */ 1841163953Srrs it->inp->inp_starting_point_for_iterator = it; 1842163953Srrs SCTP_INP_WUNLOCK(it->inp); 1843163953Srrs SCTP_INP_RLOCK(it->inp); 1844163953Srrs /* now go through each assoc which is in the desired state */ 1845167598Srrs if (it->done_current_ep == 0) { 1846167598Srrs if (it->function_inp != NULL) 1847167598Srrs inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val); 1848167598Srrs it->done_current_ep = 1; 1849167598Srrs } 1850163953Srrs if (it->stcb == NULL) { 1851163953Srrs /* run the per instance function */ 1852163953Srrs it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list); 1853163953Srrs } 1854163953Srrs SCTP_INP_RUNLOCK(it->inp); 1855167598Srrs if ((inp_skip) || it->stcb == NULL) { 1856167598Srrs if (it->function_inp_end != NULL) { 1857167598Srrs inp_skip = (*it->function_inp_end) (it->inp, 1858167598Srrs it->pointer, 1859167598Srrs it->val); 1860167598Srrs } 1861167598Srrs goto no_stcb; 1862167598Srrs } 1863163953Srrs if ((it->stcb) && 1864163953Srrs (it->stcb->asoc.stcb_starting_point_for_iterator == it)) { 1865163953Srrs it->stcb->asoc.stcb_starting_point_for_iterator = NULL; 1866163953Srrs } 1867163953Srrs while (it->stcb) { 1868163953Srrs SCTP_TCB_LOCK(it->stcb); 1869163953Srrs if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) { 1870163953Srrs /* not in the right state... keep looking */ 1871163953Srrs SCTP_TCB_UNLOCK(it->stcb); 1872163953Srrs goto next_assoc; 1873163953Srrs } 1874163953Srrs /* mark the current iterator on the assoc */ 1875163953Srrs it->stcb->asoc.stcb_starting_point_for_iterator = it; 1876163953Srrs /* see if we have limited out the iterator loop */ 1877163953Srrs iteration_count++; 1878163953Srrs if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) { 1879163953Srrs start_timer_return: 1880163953Srrs /* set a timer to continue this later */ 1881170943Srrs if (it->stcb) 1882170943Srrs SCTP_TCB_UNLOCK(it->stcb); 1883163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, 1884163953Srrs (struct sctp_inpcb *)it, NULL, NULL); 1885163953Srrs SCTP_ITERATOR_UNLOCK(); 1886163953Srrs return; 1887163953Srrs } 1888163953Srrs /* run function on this one */ 1889163953Srrs (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val); 1890163953Srrs 1891163953Srrs /* 1892163953Srrs * we lie here, it really needs to have its own type but 1893163953Srrs * first I must verify that this won't effect things :-0 1894163953Srrs */ 1895163953Srrs if (it->no_chunk_output == 0) 1896172090Srrs sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1897163953Srrs 1898163953Srrs SCTP_TCB_UNLOCK(it->stcb); 1899163953Srrsnext_assoc: 1900163953Srrs it->stcb = LIST_NEXT(it->stcb, sctp_tcblist); 1901167598Srrs if (it->stcb == NULL) { 1902167598Srrs if (it->function_inp_end != NULL) { 1903167598Srrs inp_skip = (*it->function_inp_end) (it->inp, 1904167598Srrs it->pointer, 1905167598Srrs it->val); 1906167598Srrs } 1907167598Srrs } 1908163953Srrs } 1909167598Srrsno_stcb: 1910163953Srrs /* done with all assocs on this endpoint, move on to next endpoint */ 1911167598Srrs it->done_current_ep = 0; 1912163953Srrs SCTP_INP_WLOCK(it->inp); 1913163953Srrs it->inp->inp_starting_point_for_iterator = NULL; 1914163953Srrs SCTP_INP_WUNLOCK(it->inp); 1915163953Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1916163953Srrs it->inp = NULL; 1917163953Srrs } else { 1918163953Srrs SCTP_INP_INFO_RLOCK(); 1919163953Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 1920163953Srrs SCTP_INP_INFO_RUNLOCK(); 1921163953Srrs } 1922163953Srrs if (it->inp == NULL) { 1923163953Srrs goto done_with_iterator; 1924163953Srrs } 1925163953Srrs goto select_a_new_ep; 1926163953Srrs} 1927