sctp_timer.c revision 319407
140939Sdes/*- 2226537Sdes * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3253680Sdes * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 440939Sdes * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 540939Sdes * 640939Sdes * Redistribution and use in source and binary forms, with or without 740939Sdes * modification, are permitted provided that the following conditions are met: 840939Sdes * 940939Sdes * a) Redistributions of source code must retain the above copyright notice, 1040939Sdes * this list of conditions and the following disclaimer. 1140939Sdes * 1240939Sdes * b) Redistributions in binary form must reproduce the above copyright 1340939Sdes * notice, this list of conditions and the following disclaimer in 1440939Sdes * the documentation and/or other materials provided with the distribution. 1540939Sdes * 1640939Sdes * c) Neither the name of Cisco Systems, Inc. nor the names of its 1740939Sdes * contributors may be used to endorse or promote products derived 1840939Sdes * from this software without specific prior written permission. 1940939Sdes * 2040939Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2140939Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2240939Sdes * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2340939Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2440939Sdes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2540939Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2640939Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2740939Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2840939Sdes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2940939Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3084203Sdillon * THE POSSIBILITY OF SUCH DAMAGE. 3184203Sdillon */ 3284203Sdillon 3341862Sdes#include <sys/cdefs.h> 3440939Sdes__FBSDID("$FreeBSD: stable/11/sys/netinet/sctp_timer.c 319407 2017-06-01 09:18:03Z tuexen $"); 3555557Sdes 3662981Sdes#define _IP_VHL 37174752Sdes#include <netinet/sctp_os.h> 3840939Sdes#include <netinet/sctp_pcb.h> 3940939Sdes#ifdef INET6 40174752Sdes#endif 4140939Sdes#include <netinet/sctp_var.h> 42210568Sdes#include <netinet/sctp_sysctl.h> 4340939Sdes#include <netinet/sctp_timer.h> 44109695Sdes#include <netinet/sctputil.h> 4560924Sdes#include <netinet/sctp_output.h> 4641862Sdes#include <netinet/sctp_header.h> 4741862Sdes#include <netinet/sctp_indata.h> 4840939Sdes#include <netinet/sctp_asconf.h> 4940939Sdes#include <netinet/sctp_input.h> 5040939Sdes#include <netinet/sctp.h> 51253680Sdes#include <netinet/sctp_uio.h> 52253680Sdes#if defined(INET) || defined(INET6) 53253680Sdes#include <netinet/udp.h> 54253680Sdes#endif 5540939Sdes 5640939Sdes 5740939Sdesvoid 5840975Sdessctp_audit_retranmission_queue(struct sctp_association *asoc) 5940939Sdes{ 6040939Sdes struct sctp_tmit_chunk *chk; 6140939Sdes 6240939Sdes SCTPDBG(SCTP_DEBUG_TIMER4, "Audit invoked on send queue cnt:%d onqueue:%d\n", 6340939Sdes asoc->sent_queue_retran_cnt, 64174588Sdes asoc->sent_queue_cnt); 65121423Sume asoc->sent_queue_retran_cnt = 0; 6690267Sdes asoc->sent_queue_cnt = 0; 67121423Sume TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 6890267Sdes if (chk->sent == SCTP_DATAGRAM_RESEND) { 6990267Sdes sctp_ucount_incr(asoc->sent_queue_retran_cnt); 7090267Sdes } 7190267Sdes asoc->sent_queue_cnt++; 7240939Sdes } 7340939Sdes TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) { 7462981Sdes if (chk->sent == SCTP_DATAGRAM_RESEND) { 7575891Sarchie sctp_ucount_incr(asoc->sent_queue_retran_cnt); 7640939Sdes } 7762981Sdes } 7840939Sdes TAILQ_FOREACH(chk, &asoc->asconf_send_queue, sctp_next) { 7940939Sdes if (chk->sent == SCTP_DATAGRAM_RESEND) { 8040939Sdes sctp_ucount_incr(asoc->sent_queue_retran_cnt); 8140939Sdes } 8240939Sdes } 8360924Sdes SCTPDBG(SCTP_DEBUG_TIMER4, "Audit completes retran:%d onqueue:%d\n", 84174588Sdes asoc->sent_queue_retran_cnt, 8540939Sdes asoc->sent_queue_cnt); 8690267Sdes} 8790267Sdes 8890267Sdesstatic int 8940939Sdessctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 9040939Sdes struct sctp_nets *net, uint16_t threshold) 9140939Sdes{ 9240939Sdes if (net) { 9340939Sdes net->error_count++; 9440939Sdes SCTPDBG(SCTP_DEBUG_TIMER4, "Error count for %p now %d thresh:%d\n", 95174588Sdes (void *)net, net->error_count, 9640939Sdes net->failure_threshold); 97174588Sdes if (net->error_count > net->failure_threshold) { 9890267Sdes /* We had a threshold failure */ 9990267Sdes if (net->dest_state & SCTP_ADDR_REACHABLE) { 10040939Sdes net->dest_state &= ~SCTP_ADDR_REACHABLE; 10140939Sdes net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 10240939Sdes net->dest_state &= ~SCTP_ADDR_PF; 10340939Sdes sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, 10440939Sdes stcb, 0, 10540939Sdes (void *)net, SCTP_SO_NOT_LOCKED); 106174588Sdes } 10740939Sdes } else if ((net->pf_threshold < net->failure_threshold) && 10890267Sdes (net->error_count > net->pf_threshold)) { 10990267Sdes if (!(net->dest_state & SCTP_ADDR_PF)) { 11090267Sdes net->dest_state |= SCTP_ADDR_PF; 11190267Sdes net->last_active = sctp_get_tick_count(); 11290267Sdes sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 11390267Sdes sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, 11490267Sdes inp, stcb, net, 11590267Sdes SCTP_FROM_SCTP_TIMER + SCTP_LOC_1); 11690267Sdes sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 11790267Sdes } 11890267Sdes } 11990267Sdes } 12090267Sdes if (stcb == NULL) 12190267Sdes return (0); 12290267Sdes 12390267Sdes if (net) { 12490267Sdes if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) { 12590267Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 12690267Sdes sctp_misc_ints(SCTP_THRESHOLD_INCR, 12790267Sdes stcb->asoc.overall_error_count, 12890267Sdes (stcb->asoc.overall_error_count + 1), 12990267Sdes SCTP_FROM_SCTP_TIMER, 13090267Sdes __LINE__); 13190267Sdes } 13290267Sdes stcb->asoc.overall_error_count++; 13390267Sdes } 13490267Sdes } else { 13590267Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 13690267Sdes sctp_misc_ints(SCTP_THRESHOLD_INCR, 13790267Sdes stcb->asoc.overall_error_count, 13890267Sdes (stcb->asoc.overall_error_count + 1), 13990267Sdes SCTP_FROM_SCTP_TIMER, 14090267Sdes __LINE__); 14190267Sdes } 14290267Sdes stcb->asoc.overall_error_count++; 14390267Sdes } 14490267Sdes SCTPDBG(SCTP_DEBUG_TIMER4, "Overall error count for %p now %d thresh:%u state:%x\n", 14590267Sdes (void *)&stcb->asoc, stcb->asoc.overall_error_count, 14690267Sdes (uint32_t)threshold, 14790267Sdes ((net == NULL) ? (uint32_t)0 : (uint32_t)net->dest_state)); 14890267Sdes /* 14990267Sdes * We specifically do not do >= to give the assoc one more change 15090267Sdes * before we fail it. 15190267Sdes */ 15290267Sdes if (stcb->asoc.overall_error_count > threshold) { 15390267Sdes /* Abort notification sends a ULP notify */ 15490267Sdes struct mbuf *op_err; 15590267Sdes 15690267Sdes op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 15790267Sdes "Association error counter exceeded"); 15890267Sdes inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2; 15940939Sdes sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); 16040939Sdes return (1); 16140939Sdes } 16241862Sdes return (0); 16341862Sdes} 16441862Sdes 16560924Sdes/* 166174588Sdes * sctp_find_alternate_net() returns a non-NULL pointer as long 16741862Sdes * the argument net is non-NULL. 16890267Sdes */ 16990267Sdesstruct sctp_nets * 17090267Sdessctp_find_alternate_net(struct sctp_tcb *stcb, 17190267Sdes struct sctp_nets *net, 17290267Sdes int mode) 17390267Sdes{ 17441862Sdes /* Find and return an alternate network if possible */ 17541862Sdes struct sctp_nets *alt, *mnet, *min_errors_net = NULL, *max_cwnd_net = NULL; 17641862Sdes int once; 17740939Sdes 17840939Sdes /* JRS 5/14/07 - Initialize min_errors to an impossible value. */ 17940939Sdes int min_errors = -1; 18068551Sdes uint32_t max_cwnd = 0; 18168551Sdes 18268551Sdes if (stcb->asoc.numnets == 1) { 183174588Sdes /* No others but net */ 18468551Sdes return (TAILQ_FIRST(&stcb->asoc.nets)); 18590267Sdes } 18668551Sdes /* 18790267Sdes * JRS 5/14/07 - If mode is set to 2, use the CMT PF find alternate 18890267Sdes * net algorithm. This algorithm chooses the active destination (not 18990267Sdes * in PF state) with the largest cwnd value. If all destinations are 19090267Sdes * in PF state, unreachable, or unconfirmed, choose the desination 19190267Sdes * that is in PF state with the lowest error count. In case of a 19290267Sdes * tie, choose the destination that was most recently active. 19390267Sdes */ 19468551Sdes if (mode == 2) { 19568551Sdes TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { 19668551Sdes /* 19768551Sdes * JRS 5/14/07 - If the destination is unreachable 19868551Sdes * or unconfirmed, skip it. 19968551Sdes */ 200174588Sdes if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || 20168551Sdes (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { 20290267Sdes continue; 20390267Sdes } 20490267Sdes /* 20590267Sdes * JRS 5/14/07 - If the destination is reachable 20690267Sdes * but in PF state, compare the error count of the 20768551Sdes * destination to the minimum error count seen thus 20868551Sdes * far. Store the destination with the lower error 20998117Sdes * count. If the error counts are equal, store the 21068551Sdes * destination that was most recently active. 21197866Sdes */ 21297866Sdes if (mnet->dest_state & SCTP_ADDR_PF) { 21397866Sdes /* 214174588Sdes * JRS 5/14/07 - If the destination under 21597866Sdes * consideration is the current destination, 21697866Sdes * work as if the error count is one higher. 217236193Sjilles * The actual error count will not be 21897866Sdes * incremented until later in the t3 21997866Sdes * handler. 220109967Sdes */ 22197866Sdes if (mnet == net) { 222221830Sdes if (min_errors == -1) { 223236193Sjilles min_errors = mnet->error_count + 1; 22497866Sdes min_errors_net = mnet; 22598117Sdes } else if (mnet->error_count + 1 < min_errors) { 22697866Sdes min_errors = mnet->error_count + 1; 22797866Sdes min_errors_net = mnet; 22897866Sdes } else if (mnet->error_count + 1 == min_errors 22997866Sdes && mnet->last_active > min_errors_net->last_active) { 23097866Sdes min_errors_net = mnet; 23198117Sdes min_errors = mnet->error_count + 1; 23298117Sdes } 23398117Sdes continue; 234174588Sdes } else { 23598117Sdes if (min_errors == -1) { 23698117Sdes min_errors = mnet->error_count; 23798117Sdes min_errors_net = mnet; 23898117Sdes } else if (mnet->error_count < min_errors) { 23998117Sdes min_errors = mnet->error_count; 24098117Sdes min_errors_net = mnet; 24198117Sdes } else if (mnet->error_count == min_errors 24298117Sdes && mnet->last_active > min_errors_net->last_active) { 243111816Sdes min_errors_net = mnet; 244111816Sdes min_errors = mnet->error_count; 245111816Sdes } 246174588Sdes continue; 247111816Sdes } 248111816Sdes } 249111816Sdes /* 250111816Sdes * JRS 5/14/07 - If the destination is reachable and 251111816Sdes * not in PF state, compare the cwnd of the 252111816Sdes * destination to the highest cwnd seen thus far. 253111816Sdes * Store the destination with the higher cwnd value. 254111816Sdes * If the cwnd values are equal, randomly choose one 255111816Sdes * of the two destinations. 256111816Sdes */ 257111816Sdes if (max_cwnd < mnet->cwnd) { 258111816Sdes max_cwnd_net = mnet; 259111816Sdes max_cwnd = mnet->cwnd; 260111816Sdes } else if (max_cwnd == mnet->cwnd) { 261111816Sdes uint32_t rndval; 262111816Sdes uint8_t this_random; 263111816Sdes 264111816Sdes if (stcb->asoc.hb_random_idx > 3) { 26540939Sdes rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep); 26640939Sdes memcpy(stcb->asoc.hb_random_values, &rndval, sizeof(stcb->asoc.hb_random_values)); 26797856Sdes this_random = stcb->asoc.hb_random_values[0]; 268174588Sdes stcb->asoc.hb_random_idx++; 26940939Sdes stcb->asoc.hb_ect_randombit = 0; 27097856Sdes } else { 27190267Sdes this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 272111816Sdes stcb->asoc.hb_random_idx++; 27390267Sdes stcb->asoc.hb_ect_randombit = 0; 27490267Sdes } 27540939Sdes if (this_random % 2 == 1) { 27690267Sdes max_cwnd_net = mnet; 27741862Sdes max_cwnd = mnet->cwnd; /* Useless? */ 27890267Sdes } 279174588Sdes } 28040939Sdes } 28190267Sdes if (max_cwnd_net == NULL) { 28290267Sdes if (min_errors_net == NULL) { 28390267Sdes return (net); 28490267Sdes } 28590267Sdes return (min_errors_net); 28690267Sdes } else { 28790267Sdes return (max_cwnd_net); 288174588Sdes } 28997856Sdes } /* JRS 5/14/07 - If mode is set to 1, use the 29090267Sdes * CMT policy for choosing an alternate net. */ 291111816Sdes else if (mode == 1) { 29290267Sdes TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { 29390267Sdes if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || 294174588Sdes (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { 29590267Sdes /* 29690267Sdes * will skip ones that are not-reachable or 297111816Sdes * unconfirmed 29890267Sdes */ 29962981Sdes continue; 30090267Sdes } 301111816Sdes if (max_cwnd < mnet->cwnd) { 302174588Sdes max_cwnd_net = mnet; 303174588Sdes max_cwnd = mnet->cwnd; 304111816Sdes } else if (max_cwnd == mnet->cwnd) { 305111816Sdes uint32_t rndval; 306111816Sdes uint8_t this_random; 307210568Sdes 308210568Sdes if (stcb->asoc.hb_random_idx > 3) { 30990267Sdes rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep); 31090267Sdes memcpy(stcb->asoc.hb_random_values, &rndval, 31190267Sdes sizeof(stcb->asoc.hb_random_values)); 31290267Sdes this_random = stcb->asoc.hb_random_values[0]; 31390267Sdes stcb->asoc.hb_random_idx = 0; 314174588Sdes stcb->asoc.hb_ect_randombit = 0; 31597856Sdes } else { 31690267Sdes this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 31740939Sdes stcb->asoc.hb_random_idx++; 318174588Sdes stcb->asoc.hb_ect_randombit = 0; 319174588Sdes } 32097856Sdes if (this_random % 2) { 321103459Sfenner max_cwnd_net = mnet; 32297856Sdes max_cwnd = mnet->cwnd; 32340939Sdes } 32441989Sdes } 325253680Sdes } 326253680Sdes if (max_cwnd_net) { 327253680Sdes return (max_cwnd_net); 328253680Sdes } 329253680Sdes } 330253680Sdes mnet = net; 331253680Sdes once = 0; 332253680Sdes 333253680Sdes if (mnet == NULL) { 334253680Sdes mnet = TAILQ_FIRST(&stcb->asoc.nets); 335253680Sdes if (mnet == NULL) { 336253680Sdes return (NULL); 337253680Sdes } 33841989Sdes } 33955557Sdes for (;;) { 340253680Sdes alt = TAILQ_NEXT(mnet, sctp_next); 341253680Sdes if (alt == NULL) { 342253680Sdes once++; 343253680Sdes if (once > 1) { 344253680Sdes break; 345253680Sdes } 346253680Sdes alt = TAILQ_FIRST(&stcb->asoc.nets); 347253680Sdes if (alt == NULL) { 348253680Sdes return (NULL); 349253680Sdes } 350253680Sdes } 351253680Sdes if (alt->ro.ro_rt == NULL) { 352253680Sdes if (alt->ro._s_addr) { 353253680Sdes sctp_free_ifa(alt->ro._s_addr); 354253680Sdes alt->ro._s_addr = NULL; 355253680Sdes } 356253680Sdes alt->src_addr_selected = 0; 357253680Sdes } 358253680Sdes if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) && 359253680Sdes (alt->ro.ro_rt != NULL) && 360253680Sdes (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) { 361253680Sdes /* Found a reachable address */ 362253680Sdes break; 363253680Sdes } 364253680Sdes mnet = alt; 365253680Sdes } 366253680Sdes 367253680Sdes if (alt == NULL) { 368253680Sdes /* Case where NO insv network exists (dormant state) */ 369253680Sdes /* we rotate destinations */ 370253680Sdes once = 0; 371253680Sdes mnet = net; 372253680Sdes for (;;) { 373253680Sdes if (mnet == NULL) { 374253680Sdes return (TAILQ_FIRST(&stcb->asoc.nets)); 375253680Sdes } 376253680Sdes alt = TAILQ_NEXT(mnet, sctp_next); 377253680Sdes if (alt == NULL) { 378253680Sdes once++; 379253680Sdes if (once > 1) { 380253680Sdes break; 381253680Sdes } 382253680Sdes alt = TAILQ_FIRST(&stcb->asoc.nets); 383253680Sdes if (alt == NULL) { 384253680Sdes break; 385253680Sdes } 386253680Sdes } 387253680Sdes if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) && 388253680Sdes (alt != net)) { 389253680Sdes /* Found an alternate address */ 390253680Sdes break; 391253680Sdes } 392253680Sdes mnet = alt; 393253680Sdes } 394253680Sdes } 395253680Sdes if (alt == NULL) { 396253680Sdes return (net); 397253680Sdes } 398253680Sdes return (alt); 399253680Sdes} 400253680Sdes 401253680Sdesstatic void 402253680Sdessctp_backoff_on_timeout(struct sctp_tcb *stcb, 403253680Sdes struct sctp_nets *net, 404253680Sdes int win_probe, 405253680Sdes int num_marked, int num_abandoned) 406253680Sdes{ 407253680Sdes if (net->RTO == 0) { 408253680Sdes if (net->RTO_measured) { 409253680Sdes net->RTO = stcb->asoc.minrto; 410253680Sdes } else { 411253680Sdes net->RTO = stcb->asoc.initial_rto; 412253680Sdes } 413253680Sdes } 414253680Sdes net->RTO <<= 1; 415253680Sdes if (net->RTO > stcb->asoc.maxrto) { 416253680Sdes net->RTO = stcb->asoc.maxrto; 417253680Sdes } 418253680Sdes if ((win_probe == 0) && (num_marked || num_abandoned)) { 419253680Sdes /* We don't apply penalty to window probe scenarios */ 420253680Sdes /* JRS - Use the congestion control given in the CC module */ 421253680Sdes stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout(stcb, net); 422253680Sdes } 423253680Sdes} 424253680Sdes 425253680Sdes#ifndef INVARIANTS 426253680Sdesstatic void 427253680Sdessctp_recover_sent_list(struct sctp_tcb *stcb) 428253680Sdes{ 429253680Sdes struct sctp_tmit_chunk *chk, *nchk; 430253680Sdes struct sctp_association *asoc; 431253680Sdes 432253680Sdes asoc = &stcb->asoc; 433253680Sdes TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 434253680Sdes if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.tsn)) { 435253680Sdes SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n", 436253680Sdes (void *)chk, chk->rec.data.tsn, asoc->last_acked_seq); 437253680Sdes if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 438253680Sdes if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { 439253680Sdes asoc->strmout[chk->rec.data.sid].chunks_on_queues--; 440253680Sdes } 441253680Sdes } 442253680Sdes if ((asoc->strmout[chk->rec.data.sid].chunks_on_queues == 0) && 443253680Sdes (asoc->strmout[chk->rec.data.sid].state == SCTP_STREAM_RESET_PENDING) && 444253680Sdes TAILQ_EMPTY(&asoc->strmout[chk->rec.data.sid].outqueue)) { 445253680Sdes asoc->trigger_reset = 1; 446253680Sdes } 447253680Sdes TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 448253680Sdes if (PR_SCTP_ENABLED(chk->flags)) { 449253680Sdes if (asoc->pr_sctp_cnt != 0) 450253680Sdes asoc->pr_sctp_cnt--; 451253680Sdes } 452253680Sdes if (chk->data) { 453253680Sdes /* sa_ignore NO_NULL_CHK */ 454253680Sdes sctp_free_bufspace(stcb, asoc, chk, 1); 455253680Sdes sctp_m_freem(chk->data); 456253680Sdes chk->data = NULL; 457253680Sdes if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(chk->flags)) { 458253680Sdes asoc->sent_queue_cnt_removeable--; 459253680Sdes } 460253680Sdes } 461253680Sdes asoc->sent_queue_cnt--; 462253680Sdes sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 463253680Sdes } 464253680Sdes } 465253680Sdes SCTP_PRINTF("after recover order is as follows\n"); 466253680Sdes TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 467253680Sdes SCTP_PRINTF("chk:%p TSN:%x\n", (void *)chk, chk->rec.data.tsn); 468253680Sdes } 469253680Sdes} 470253680Sdes#endif 471253680Sdes 472253680Sdesstatic int 473253680Sdessctp_mark_all_for_resend(struct sctp_tcb *stcb, 474253680Sdes struct sctp_nets *net, 475253680Sdes struct sctp_nets *alt, 476253680Sdes int window_probe, 477253680Sdes int *num_marked, 478253680Sdes int *num_abandoned) 479253680Sdes{ 480253680Sdes 481253680Sdes /* 482253680Sdes * Mark all chunks (well not all) that were sent to *net for 483253680Sdes * retransmission. Move them to alt for there destination as well... 484253680Sdes * We only mark chunks that have been outstanding long enough to 485253680Sdes * have received feed-back. 486253680Sdes */ 487253680Sdes struct sctp_tmit_chunk *chk, *nchk; 488253680Sdes struct sctp_nets *lnets; 489253680Sdes struct timeval now, min_wait, tv; 490253680Sdes int cur_rto; 491253680Sdes int cnt_abandoned; 492253680Sdes int audit_tf, num_mk, fir; 493253680Sdes unsigned int cnt_mk; 494253680Sdes uint32_t orig_flight, orig_tf; 495253680Sdes uint32_t tsnlast, tsnfirst; 496253680Sdes int recovery_cnt = 0; 497253680Sdes 498253680Sdes 499253680Sdes /* none in flight now */ 500253680Sdes audit_tf = 0; 501253680Sdes fir = 0; 502253680Sdes /* 503253680Sdes * figure out how long a data chunk must be pending before we can 504253680Sdes * mark it .. 505253680Sdes */ 506253680Sdes (void)SCTP_GETTIME_TIMEVAL(&now); 507253680Sdes /* get cur rto in micro-seconds */ 508253680Sdes cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 509253680Sdes cur_rto *= 1000; 510253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 511253680Sdes sctp_log_fr(cur_rto, 512253680Sdes stcb->asoc.peers_rwnd, 513253680Sdes window_probe, 514253680Sdes SCTP_FR_T3_MARK_TIME); 515253680Sdes sctp_log_fr(net->flight_size, 0, 0, SCTP_FR_CWND_REPORT); 516253680Sdes sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT); 517253680Sdes } 518253680Sdes tv.tv_sec = cur_rto / 1000000; 519253680Sdes tv.tv_usec = cur_rto % 1000000; 520253680Sdes min_wait = now; 521253680Sdes timevalsub(&min_wait, &tv); 522253680Sdes if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) { 523253680Sdes /* 524253680Sdes * if we hit here, we don't have enough seconds on the clock 525253680Sdes * to account for the RTO. We just let the lower seconds be 526253680Sdes * the bounds and don't worry about it. This may mean we 527253680Sdes * will mark a lot more than we should. 528253680Sdes */ 529253680Sdes min_wait.tv_sec = min_wait.tv_usec = 0; 530253680Sdes } 531253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 532253680Sdes sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME); 533253680Sdes sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME); 534253680Sdes } 535253680Sdes /* 536253680Sdes * Our rwnd will be incorrect here since we are not adding back the 537253680Sdes * cnt * mbuf but we will fix that down below. 538253680Sdes */ 539253680Sdes orig_flight = net->flight_size; 540253680Sdes orig_tf = stcb->asoc.total_flight; 541253680Sdes 542253680Sdes net->fast_retran_ip = 0; 543253680Sdes /* Now on to each chunk */ 544253680Sdes cnt_abandoned = 0; 545253680Sdes num_mk = cnt_mk = 0; 546253680Sdes tsnfirst = tsnlast = 0; 547253680Sdes#ifndef INVARIANTS 548253680Sdesstart_again: 549253680Sdes#endif 550253680Sdes TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) { 551253680Sdes if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.tsn)) { 552253680Sdes /* Strange case our list got out of order? */ 553253680Sdes SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x\n", 554253680Sdes (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.tsn); 555253680Sdes recovery_cnt++; 556253680Sdes#ifdef INVARIANTS 557253680Sdes panic("last acked >= chk on sent-Q"); 558253680Sdes#else 559253680Sdes SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt); 560253680Sdes sctp_recover_sent_list(stcb); 561253680Sdes if (recovery_cnt < 10) { 562253680Sdes goto start_again; 563253680Sdes } else { 564253680Sdes SCTP_PRINTF("Recovery fails %d times??\n", recovery_cnt); 565253680Sdes } 566253680Sdes#endif 567253680Sdes } 568253680Sdes if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) { 569253680Sdes /* 570253680Sdes * found one to mark: If it is less than 571253680Sdes * DATAGRAM_ACKED it MUST not be a skipped or marked 572253680Sdes * TSN but instead one that is either already set 573253680Sdes * for retransmission OR one that needs 574253680Sdes * retransmission. 575253680Sdes */ 576253680Sdes 577253680Sdes /* validate its been outstanding long enough */ 578253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 579253680Sdes sctp_log_fr(chk->rec.data.tsn, 580253680Sdes chk->sent_rcv_time.tv_sec, 581253680Sdes chk->sent_rcv_time.tv_usec, 582253680Sdes SCTP_FR_T3_MARK_TIME); 583253680Sdes } 584253680Sdes if ((chk->sent_rcv_time.tv_sec > min_wait.tv_sec) && (window_probe == 0)) { 585253680Sdes /* 586253680Sdes * we have reached a chunk that was sent 587253680Sdes * some seconds past our min.. forget it we 588253680Sdes * will find no more to send. 589253680Sdes */ 590253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 591253680Sdes sctp_log_fr(0, 592253680Sdes chk->sent_rcv_time.tv_sec, 593253680Sdes chk->sent_rcv_time.tv_usec, 594253680Sdes SCTP_FR_T3_STOPPED); 595253680Sdes } 596253680Sdes continue; 597253680Sdes } else if ((chk->sent_rcv_time.tv_sec == min_wait.tv_sec) && 598253680Sdes (window_probe == 0)) { 599253680Sdes /* 600253680Sdes * we must look at the micro seconds to 601253680Sdes * know. 602253680Sdes */ 603253680Sdes if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) { 604253680Sdes /* 605253680Sdes * ok it was sent after our boundary 606253680Sdes * time. 607253680Sdes */ 608253680Sdes continue; 609253680Sdes } 610253680Sdes } 611253680Sdes if (stcb->asoc.prsctp_supported && PR_SCTP_TTL_ENABLED(chk->flags)) { 612253680Sdes /* Is it expired? */ 613253680Sdes if (timevalcmp(&now, &chk->rec.data.timetodrop, >)) { 614253680Sdes /* Yes so drop it */ 615253680Sdes if (chk->data) { 616253680Sdes (void)sctp_release_pr_sctp_chunk(stcb, 617253680Sdes chk, 618253680Sdes 1, 619253680Sdes SCTP_SO_NOT_LOCKED); 620253680Sdes cnt_abandoned++; 621253680Sdes } 622253680Sdes continue; 623253680Sdes } 624253680Sdes } 625253680Sdes if (stcb->asoc.prsctp_supported && PR_SCTP_RTX_ENABLED(chk->flags)) { 626253680Sdes /* Has it been retransmitted tv_sec times? */ 627253680Sdes if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) { 628253680Sdes if (chk->data) { 629253680Sdes (void)sctp_release_pr_sctp_chunk(stcb, 630253680Sdes chk, 631253680Sdes 1, 632253680Sdes SCTP_SO_NOT_LOCKED); 633253680Sdes cnt_abandoned++; 634253680Sdes } 635253680Sdes continue; 636253680Sdes } 637253680Sdes } 638253680Sdes if (chk->sent < SCTP_DATAGRAM_RESEND) { 639253680Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 640253680Sdes num_mk++; 641253680Sdes if (fir == 0) { 642253680Sdes fir = 1; 643253680Sdes tsnfirst = chk->rec.data.tsn; 644253680Sdes } 645253680Sdes tsnlast = chk->rec.data.tsn; 646253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 647253680Sdes sctp_log_fr(chk->rec.data.tsn, chk->snd_count, 648253680Sdes 0, SCTP_FR_T3_MARKED); 649253680Sdes } 650253680Sdes if (chk->rec.data.chunk_was_revoked) { 651253680Sdes /* deflate the cwnd */ 652253680Sdes chk->whoTo->cwnd -= chk->book_size; 653253680Sdes chk->rec.data.chunk_was_revoked = 0; 654253680Sdes } 655253680Sdes net->marked_retrans++; 656253680Sdes stcb->asoc.marked_retrans++; 657253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 658253680Sdes sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO, 659253680Sdes chk->whoTo->flight_size, 660253680Sdes chk->book_size, 661253680Sdes (uint32_t)(uintptr_t)chk->whoTo, 662253680Sdes chk->rec.data.tsn); 663253680Sdes } 664253680Sdes sctp_flight_size_decrease(chk); 665253680Sdes sctp_total_flight_decrease(stcb, chk); 666253680Sdes stcb->asoc.peers_rwnd += chk->send_size; 667253680Sdes stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh); 668253680Sdes } 669253680Sdes chk->sent = SCTP_DATAGRAM_RESEND; 670253680Sdes chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 671253680Sdes SCTP_STAT_INCR(sctps_markedretrans); 672253680Sdes 673253680Sdes /* reset the TSN for striking and other FR stuff */ 674253680Sdes chk->rec.data.doing_fast_retransmit = 0; 675253680Sdes /* Clear any time so NO RTT is being done */ 676253680Sdes 677253680Sdes if (chk->do_rtt) { 678253680Sdes if (chk->whoTo->rto_needed == 0) { 679253680Sdes chk->whoTo->rto_needed = 1; 680253680Sdes } 681253680Sdes } 682253680Sdes chk->do_rtt = 0; 683253680Sdes if (alt != net) { 684253680Sdes sctp_free_remote_addr(chk->whoTo); 685253680Sdes chk->no_fr_allowed = 1; 686253680Sdes chk->whoTo = alt; 687253680Sdes atomic_add_int(&alt->ref_count, 1); 688253680Sdes } else { 689253680Sdes chk->no_fr_allowed = 0; 690253680Sdes if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 691253680Sdes chk->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 692253680Sdes } else { 693253680Sdes chk->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.tsn; 694253680Sdes } 695253680Sdes } 696253680Sdes /* 697253680Sdes * CMT: Do not allow FRs on retransmitted TSNs. 698253680Sdes */ 699253680Sdes if (stcb->asoc.sctp_cmt_on_off > 0) { 700253680Sdes chk->no_fr_allowed = 1; 701253680Sdes } 702253680Sdes#ifdef THIS_SHOULD_NOT_BE_DONE 703253680Sdes } else if (chk->sent == SCTP_DATAGRAM_ACKED) { 704253680Sdes /* remember highest acked one */ 705253680Sdes could_be_sent = chk; 706253680Sdes#endif 707253680Sdes } 708253680Sdes if (chk->sent == SCTP_DATAGRAM_RESEND) { 709253680Sdes cnt_mk++; 710253680Sdes } 711253680Sdes } 712253680Sdes if ((orig_flight - net->flight_size) != (orig_tf - stcb->asoc.total_flight)) { 713253680Sdes /* we did not subtract the same things? */ 714253680Sdes audit_tf = 1; 715253680Sdes } 716253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 717253680Sdes sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT); 718253680Sdes } 719253680Sdes#ifdef SCTP_DEBUG 720253680Sdes if (num_mk) { 721253680Sdes SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n", 722253680Sdes tsnlast); 723253680Sdes SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%u\n", 724253680Sdes num_mk, 725253680Sdes stcb->asoc.peers_rwnd); 726253680Sdes } 727253680Sdes#endif 728253680Sdes *num_marked = num_mk; 729253680Sdes *num_abandoned = cnt_abandoned; 730253680Sdes /* 731253680Sdes * Now check for a ECN Echo that may be stranded And include the 732253680Sdes * cnt_mk'd to have all resends in the control queue. 733253680Sdes */ 734253680Sdes TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 735253680Sdes if (chk->sent == SCTP_DATAGRAM_RESEND) { 736253680Sdes cnt_mk++; 737253680Sdes } 738253680Sdes if ((chk->whoTo == net) && 739253680Sdes (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 740253680Sdes sctp_free_remote_addr(chk->whoTo); 741253680Sdes chk->whoTo = alt; 742253680Sdes if (chk->sent != SCTP_DATAGRAM_RESEND) { 743253680Sdes chk->sent = SCTP_DATAGRAM_RESEND; 744253680Sdes chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 745253680Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 746253680Sdes cnt_mk++; 747253680Sdes } 748253680Sdes atomic_add_int(&alt->ref_count, 1); 749253680Sdes } 750253680Sdes } 751253680Sdes#ifdef THIS_SHOULD_NOT_BE_DONE 752253680Sdes if ((stcb->asoc.sent_queue_retran_cnt == 0) && (could_be_sent)) { 753253680Sdes /* fix it so we retransmit the highest acked anyway */ 754253680Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 755253680Sdes cnt_mk++; 756253680Sdes could_be_sent->sent = SCTP_DATAGRAM_RESEND; 757253680Sdes } 758253680Sdes#endif 759253680Sdes if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) { 760253680Sdes#ifdef INVARIANTS 761253680Sdes SCTP_PRINTF("Local Audit says there are %d for retran asoc cnt:%d we marked:%d this time\n", 762253680Sdes cnt_mk, stcb->asoc.sent_queue_retran_cnt, num_mk); 763253680Sdes#endif 764253680Sdes#ifndef SCTP_AUDITING_ENABLED 765253680Sdes stcb->asoc.sent_queue_retran_cnt = cnt_mk; 766253680Sdes#endif 767253680Sdes } 768253680Sdes if (audit_tf) { 769253680Sdes SCTPDBG(SCTP_DEBUG_TIMER4, 770253680Sdes "Audit total flight due to negative value net:%p\n", 771253680Sdes (void *)net); 772253680Sdes stcb->asoc.total_flight = 0; 773253680Sdes stcb->asoc.total_flight_count = 0; 774253680Sdes /* Clear all networks flight size */ 775253680Sdes TAILQ_FOREACH(lnets, &stcb->asoc.nets, sctp_next) { 776253680Sdes lnets->flight_size = 0; 777253680Sdes SCTPDBG(SCTP_DEBUG_TIMER4, 778253680Sdes "Net:%p c-f cwnd:%d ssthresh:%d\n", 779253680Sdes (void *)lnets, lnets->cwnd, lnets->ssthresh); 780253680Sdes } 781253680Sdes TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 782253680Sdes if (chk->sent < SCTP_DATAGRAM_RESEND) { 783253680Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 784253680Sdes sctp_misc_ints(SCTP_FLIGHT_LOG_UP, 785253680Sdes chk->whoTo->flight_size, 786253680Sdes chk->book_size, 787253680Sdes (uint32_t)(uintptr_t)chk->whoTo, 788253680Sdes chk->rec.data.tsn); 789253680Sdes } 790253680Sdes sctp_flight_size_increase(chk); 791253680Sdes sctp_total_flight_increase(stcb, chk); 792253680Sdes } 793253680Sdes } 794253680Sdes } 795253680Sdes /* We return 1 if we only have a window probe outstanding */ 796253680Sdes return (0); 797253680Sdes} 79897868Sdes 79997868Sdes 80097868Sdesint 801253680Sdessctp_t3rxt_timer(struct sctp_inpcb *inp, 80297868Sdes struct sctp_tcb *stcb, 803214256Semaste struct sctp_nets *net) 804210568Sdes{ 805253680Sdes struct sctp_nets *alt; 806253680Sdes int win_probe, num_mk, num_abandoned; 80797868Sdes 80897868Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 80997868Sdes sctp_log_fr(0, 0, 0, SCTP_FR_T3_TIMEOUT); 81097868Sdes } 81197868Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { 81297868Sdes struct sctp_nets *lnet; 81397868Sdes 81497868Sdes TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 81597868Sdes if (net == lnet) { 81697868Sdes sctp_log_cwnd(stcb, lnet, 1, SCTP_CWND_LOG_FROM_T3); 81797868Sdes } else { 818108579Sdes sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_LOG_FROM_T3); 81997868Sdes } 820253680Sdes } 821253680Sdes } 822253680Sdes /* Find an alternate and mark those for retransmission */ 823253680Sdes if ((stcb->asoc.peers_rwnd == 0) && 824253680Sdes (stcb->asoc.total_flight < net->mtu)) { 825253680Sdes SCTP_STAT_INCR(sctps_timowindowprobe); 82697868Sdes win_probe = 1; 827253680Sdes } else { 82897868Sdes win_probe = 0; 82997868Sdes } 83097868Sdes 83197868Sdes if (win_probe == 0) { 832258756Sbdrewery /* We don't do normal threshold management on window probes */ 833258756Sbdrewery if (sctp_threshold_management(inp, stcb, net, 834258756Sbdrewery stcb->asoc.max_send_times)) { 835258756Sbdrewery /* Association was destroyed */ 836258756Sbdrewery return (1); 837258756Sbdrewery } else { 838258756Sbdrewery if (net != stcb->asoc.primary_destination) { 839258756Sbdrewery /* send a immediate HB if our RTO is stale */ 840258756Sbdrewery struct timeval now; 841258756Sbdrewery unsigned int ms_goneby; 842210568Sdes 843210568Sdes (void)SCTP_GETTIME_TIMEVAL(&now); 844210568Sdes if (net->last_sent_time.tv_sec) { 845210568Sdes ms_goneby = (now.tv_sec - net->last_sent_time.tv_sec) * 1000; 846210568Sdes } else { 847210568Sdes ms_goneby = 0; 848210568Sdes } 84997868Sdes if ((net->dest_state & SCTP_ADDR_PF) == 0) { 850253680Sdes if ((ms_goneby > net->RTO) || (net->RTO == 0)) { 85197868Sdes /* 852253680Sdes * no recent feed back in an 853253680Sdes * RTO or more, request a 854253680Sdes * RTT update 855253680Sdes */ 856253680Sdes sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 857253680Sdes } 858253680Sdes } 859253680Sdes } 860253680Sdes } 861253680Sdes } else { 862253680Sdes /* 863253680Sdes * For a window probe we don't penalize the net's but only 864253680Sdes * the association. This may fail it if SACKs are not coming 865253680Sdes * back. If sack's are coming with rwnd locked at 0, we will 866253680Sdes * continue to hold things waiting for rwnd to raise 867253680Sdes */ 86897868Sdes if (sctp_threshold_management(inp, stcb, NULL, 869253680Sdes stcb->asoc.max_send_times)) { 87097868Sdes /* Association was destroyed */ 87197868Sdes return (1); 87297868Sdes } 873253680Sdes } 874253680Sdes if (stcb->asoc.sctp_cmt_on_off > 0) { 87597868Sdes if (net->pf_threshold < net->failure_threshold) { 87697868Sdes alt = sctp_find_alternate_net(stcb, net, 2); 877253680Sdes } else { 878253680Sdes /* 87997868Sdes * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is 88097868Sdes * being used, then pick dest with largest ssthresh 88197868Sdes * for any retransmission. 88297891Sdes */ 88397891Sdes alt = sctp_find_alternate_net(stcb, net, 1); 88497891Sdes /* 88597891Sdes * CUCv2: If a different dest is picked for the 88697891Sdes * retransmission, then new (rtx-)pseudo_cumack 88797891Sdes * needs to be tracked for orig dest. Let CUCv2 88897868Sdes * track new (rtx-) pseudo-cumack always. 88997868Sdes */ 890210568Sdes net->find_pseudo_cumack = 1; 891210568Sdes net->find_rtx_pseudo_cumack = 1; 892210568Sdes } 89398117Sdes } else { 894210568Sdes alt = sctp_find_alternate_net(stcb, net, 0); 895210568Sdes } 896210568Sdes 897210568Sdes num_mk = 0; 898210568Sdes num_abandoned = 0; 899210568Sdes (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe, 900210568Sdes &num_mk, &num_abandoned); 901210568Sdes /* FR Loss recovery just ended with the T3. */ 902210568Sdes stcb->asoc.fast_retran_loss_recovery = 0; 903210568Sdes 904210568Sdes /* CMT FR loss recovery ended with the T3 */ 905210568Sdes net->fast_retran_loss_recovery = 0; 906210568Sdes if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) && 907210568Sdes (net->flight_size == 0)) { 908210568Sdes (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net); 909210568Sdes } 910210568Sdes /* 911210568Sdes * setup the sat loss recovery that prevents satellite cwnd advance. 912210568Sdes */ 913210568Sdes stcb->asoc.sat_t3_loss_recovery = 1; 914210568Sdes stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq; 915210568Sdes 916230307Sdes /* Backoff the timer and cwnd */ 917230307Sdes sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned); 918230307Sdes if ((!(net->dest_state & SCTP_ADDR_REACHABLE)) || 919230307Sdes (net->dest_state & SCTP_ADDR_PF)) { 920230307Sdes /* Move all pending over too */ 921230307Sdes sctp_move_chunks_from_net(stcb, net); 922230307Sdes 923230307Sdes /* 924230307Sdes * Get the address that failed, to force a new src address 925230307Sdes * selecton and a route allocation. 926230307Sdes */ 927230307Sdes if (net->ro._s_addr) { 928230307Sdes sctp_free_ifa(net->ro._s_addr); 929230307Sdes net->ro._s_addr = NULL; 930230307Sdes } 931230307Sdes net->src_addr_selected = 0; 932230307Sdes 933230307Sdes /* Force a route allocation too */ 934230307Sdes if (net->ro.ro_rt) { 935230307Sdes RTFREE(net->ro.ro_rt); 936230307Sdes net->ro.ro_rt = NULL; 937230307Sdes } 938230307Sdes /* Was it our primary? */ 939230307Sdes if ((stcb->asoc.primary_destination == net) && (alt != net)) { 940230307Sdes /* 941230307Sdes * Yes, note it as such and find an alternate note: 942230307Sdes * this means HB code must use this to resent the 943210568Sdes * primary if it goes active AND if someone does a 944210568Sdes * change-primary then this flag must be cleared 945210568Sdes * from any net structures. 946210568Sdes */ 947210568Sdes if (stcb->asoc.alternate) { 948210568Sdes sctp_free_remote_addr(stcb->asoc.alternate); 949210568Sdes } 950210568Sdes stcb->asoc.alternate = alt; 951210568Sdes atomic_add_int(&stcb->asoc.alternate->ref_count, 1); 952210568Sdes } 953210568Sdes } 954210568Sdes /* 955210568Sdes * Special case for cookie-echo'ed case, we don't do output but must 956210568Sdes * await the COOKIE-ACK before retransmission 957210568Sdes */ 95897868Sdes if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 95997866Sdes /* 96055557Sdes * Here we just reset the timer and start again since we 96197866Sdes * have not established the asoc 962174588Sdes */ 96355557Sdes sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); 964177447Sdes return (0); 96590267Sdes } 96697866Sdes if (stcb->asoc.prsctp_supported) { 967230307Sdes struct sctp_tmit_chunk *lchk; 96890267Sdes 969234837Sdes lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc); 97090267Sdes /* C3. See if we need to send a Fwd-TSN */ 97190267Sdes if (SCTP_TSN_GT(stcb->asoc.advanced_peer_ack_point, stcb->asoc.last_acked_seq)) { 97255557Sdes send_forward_tsn(stcb, &stcb->asoc); 97390267Sdes if (lchk) { 97497866Sdes /* Assure a timer is up */ 975230307Sdes sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, lchk->whoTo); 976230307Sdes } 977230307Sdes } 978230307Sdes } 979230307Sdes if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { 980230307Sdes sctp_log_cwnd(stcb, net, net->cwnd, SCTP_CWND_LOG_FROM_RTX); 981230307Sdes } 982230307Sdes return (0); 983230307Sdes} 984230307Sdes 985230307Sdesint 986230307Sdessctp_t1init_timer(struct sctp_inpcb *inp, 987230307Sdes struct sctp_tcb *stcb, 988230307Sdes struct sctp_nets *net) 989230307Sdes{ 990230478Sdes /* bump the thresholds */ 991230307Sdes if (stcb->asoc.delayed_connection) { 992230307Sdes /* 99397866Sdes * special hook for delayed connection. The library did NOT 994210568Sdes * complete the rest of its sends. 995210568Sdes */ 996210568Sdes stcb->asoc.delayed_connection = 0; 997210568Sdes sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 998210568Sdes return (0); 999210568Sdes } 1000210568Sdes if (SCTP_GET_STATE((&stcb->asoc)) != SCTP_STATE_COOKIE_WAIT) { 1001210568Sdes return (0); 1002210568Sdes } 1003210568Sdes if (sctp_threshold_management(inp, stcb, net, 1004210568Sdes stcb->asoc.max_init_times)) { 1005210568Sdes /* Association was destroyed */ 1006210568Sdes return (1); 1007210568Sdes } 1008210568Sdes stcb->asoc.dropped_special_cnt = 0; 1009210568Sdes sctp_backoff_on_timeout(stcb, stcb->asoc.primary_destination, 1, 0, 0); 1010210568Sdes if (stcb->asoc.initial_init_rto_max < net->RTO) { 1011210568Sdes net->RTO = stcb->asoc.initial_init_rto_max; 1012210568Sdes } 1013210568Sdes if (stcb->asoc.numnets > 1) { 1014210568Sdes /* If we have more than one addr use it */ 1015210568Sdes struct sctp_nets *alt; 1016210568Sdes 1017210568Sdes alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination, 0); 1018210568Sdes if (alt != stcb->asoc.primary_destination) { 1019210568Sdes sctp_move_chunks_from_net(stcb, stcb->asoc.primary_destination); 1020210568Sdes stcb->asoc.primary_destination = alt; 1021210568Sdes } 1022210568Sdes } 1023210568Sdes /* Send out a new init */ 1024210568Sdes sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 1025210568Sdes return (0); 1026210568Sdes} 1027210568Sdes 1028230307Sdes/* 1029230307Sdes * For cookie and asconf we actually need to find and mark for resend, then 1030210568Sdes * increment the resend counter (after all the threshold management stuff of 1031210568Sdes * course). 1032210568Sdes */ 1033234837Sdesint 1034234837Sdessctp_cookie_timer(struct sctp_inpcb *inp, 103597856Sdes struct sctp_tcb *stcb, 1036234837Sdes struct sctp_nets *net SCTP_UNUSED) 1037234837Sdes{ 1038234837Sdes struct sctp_nets *alt; 1039234837Sdes struct sctp_tmit_chunk *cookie; 1040234837Sdes 1041234837Sdes /* first before all else we must find the cookie */ 1042234837Sdes TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, sctp_next) { 1043234837Sdes if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 104490267Sdes break; 104597866Sdes } 1046234837Sdes } 1047234837Sdes if (cookie == NULL) { 1048230307Sdes if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 1049230307Sdes /* FOOBAR! */ 1050230307Sdes struct mbuf *op_err; 1051230307Sdes 1052230307Sdes op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 1053230307Sdes "Cookie timer expired, but no cookie"); 1054174588Sdes inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3; 105590267Sdes sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); 105690267Sdes } else { 105790267Sdes#ifdef INVARIANTS 105897866Sdes panic("Cookie timer expires in wrong state?"); 105997866Sdes#else 106097866Sdes SCTP_PRINTF("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(&stcb->asoc)); 106197866Sdes return (0); 106298117Sdes#endif 106397866Sdes } 106497866Sdes return (0); 106597866Sdes } 106697866Sdes /* Ok we found the cookie, threshold management next */ 106797866Sdes if (sctp_threshold_management(inp, stcb, cookie->whoTo, 106897866Sdes stcb->asoc.max_init_times)) { 1069174588Sdes /* Assoc is over */ 107097866Sdes return (1); 107197866Sdes } 107297866Sdes /* 1073106186Sdes * Cleared threshold management, now lets backoff the address and 107497866Sdes * select an alternate 107597866Sdes */ 107697866Sdes stcb->asoc.dropped_special_cnt = 0; 107797866Sdes sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0, 0); 107897866Sdes alt = sctp_find_alternate_net(stcb, cookie->whoTo, 0); 107997866Sdes if (alt != cookie->whoTo) { 108097866Sdes sctp_free_remote_addr(cookie->whoTo); 108197866Sdes cookie->whoTo = alt; 108297866Sdes atomic_add_int(&alt->ref_count, 1); 108397866Sdes } 108497866Sdes /* Now mark the retran info */ 108597866Sdes if (cookie->sent != SCTP_DATAGRAM_RESEND) { 108697866Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 108797866Sdes } 1088174588Sdes cookie->sent = SCTP_DATAGRAM_RESEND; 1089106186Sdes cookie->flags |= CHUNK_FLAGS_FRAGMENT_OK; 109097866Sdes /* 1091106186Sdes * Now call the output routine to kick out the cookie again, Note we 1092106137Sobrien * don't mark any chunks for retran so that FR will need to kick in 109397856Sdes * to move these (or a send timer). 109497856Sdes */ 109597856Sdes return (0); 109697856Sdes} 109797856Sdes 109890267Sdesint 109990267Sdessctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 110090267Sdes struct sctp_nets *net) 110197856Sdes{ 110297856Sdes struct sctp_nets *alt; 110390267Sdes struct sctp_tmit_chunk *strrst = NULL, *chk = NULL; 110490267Sdes 110590267Sdes if (stcb->asoc.stream_reset_outstanding == 0) { 110697856Sdes return (0); 110797856Sdes } 110890267Sdes /* find the existing STRRESET, we use the seq number we sent out on */ 110955557Sdes (void)sctp_find_stream_reset(stcb, stcb->asoc.str_reset_seq_out, &strrst); 111055557Sdes if (strrst == NULL) { 111155557Sdes return (0); 111262981Sdes } 111397866Sdes /* do threshold management */ 111462981Sdes if (sctp_threshold_management(inp, stcb, strrst->whoTo, 111597866Sdes stcb->asoc.max_send_times)) { 1116174588Sdes /* Assoc is over */ 111797866Sdes return (1); 1118106175Simp } 1119106175Simp /* 1120106175Simp * Cleared threshold management, now lets backoff the address and 1121106175Simp * select an alternate 1122174588Sdes */ 1123106175Simp sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0, 0); 1124106175Simp alt = sctp_find_alternate_net(stcb, strrst->whoTo, 0); 1125106175Simp sctp_free_remote_addr(strrst->whoTo); 1126106175Simp strrst->whoTo = alt; 1127106175Simp atomic_add_int(&alt->ref_count, 1); 1128106175Simp 1129106175Simp /* See if a ECN Echo is also stranded */ 1130174588Sdes TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 1131106175Simp if ((chk->whoTo == net) && 1132177447Sdes (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 113397866Sdes sctp_free_remote_addr(chk->whoTo); 113497866Sdes if (chk->sent != SCTP_DATAGRAM_RESEND) { 113597866Sdes chk->sent = SCTP_DATAGRAM_RESEND; 113697866Sdes chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 113797866Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 113897866Sdes } 113997866Sdes chk->whoTo = alt; 114097866Sdes atomic_add_int(&alt->ref_count, 1); 114197866Sdes } 114297866Sdes } 1143106175Simp if (!(net->dest_state & SCTP_ADDR_REACHABLE)) { 1144106175Simp /* 114597866Sdes * If the address went un-reachable, we need to move to 114697866Sdes * alternates for ALL chk's in queue 114797866Sdes */ 1148177447Sdes sctp_move_chunks_from_net(stcb, net); 1149177447Sdes } 1150177447Sdes /* mark the retran info */ 1151177447Sdes if (strrst->sent != SCTP_DATAGRAM_RESEND) 1152177447Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 115397866Sdes strrst->sent = SCTP_DATAGRAM_RESEND; 1154177447Sdes strrst->flags |= CHUNK_FLAGS_FRAGMENT_OK; 115597866Sdes 1156174588Sdes /* restart the timer */ 115797866Sdes sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, inp, stcb, strrst->whoTo); 115897866Sdes return (0); 115997866Sdes} 1160177447Sdes 116197866Sdesint 116297866Sdessctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 116397866Sdes struct sctp_nets *net) 116497866Sdes{ 116597866Sdes struct sctp_nets *alt; 116697866Sdes struct sctp_tmit_chunk *asconf, *chk; 116797866Sdes 116897891Sdes /* is this a first send, or a retransmission? */ 116997866Sdes if (TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) { 1170106175Simp /* compose a new ASCONF chunk and send it */ 1171106175Simp sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 117297866Sdes } else { 117397891Sdes /* 1174106175Simp * Retransmission of the existing ASCONF is needed 1175106175Simp */ 117697866Sdes 1177210568Sdes /* find the existing ASCONF */ 1178106175Simp asconf = TAILQ_FIRST(&stcb->asoc.asconf_send_queue); 1179174588Sdes if (asconf == NULL) { 118097866Sdes return (0); 1181106175Simp } 118297866Sdes /* do threshold management */ 118397866Sdes if (sctp_threshold_management(inp, stcb, asconf->whoTo, 118497866Sdes stcb->asoc.max_send_times)) { 118597866Sdes /* Assoc is over */ 118697866Sdes return (1); 118797866Sdes } 1188106175Simp if (asconf->snd_count > stcb->asoc.max_send_times) { 1189106175Simp /* 1190106175Simp * Something is rotten: our peer is not responding 1191106175Simp * to ASCONFs but apparently is to other chunks. 1192106175Simp * i.e. it is not properly handling the chunk type 1193106175Simp * upper bits. Mark this peer as ASCONF incapable 1194106175Simp * and cleanup. 1195106175Simp */ 1196106175Simp SCTPDBG(SCTP_DEBUG_TIMER1, "asconf_timer: Peer has not responded to our repeated ASCONFs\n"); 119797866Sdes sctp_asconf_cleanup(stcb, net); 119897866Sdes return (0); 119997866Sdes } 120097866Sdes /* 120198117Sdes * cleared threshold management, so now backoff the net and 120297866Sdes * select an alternate 120397866Sdes */ 120497866Sdes sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0, 0); 120562981Sdes alt = sctp_find_alternate_net(stcb, asconf->whoTo, 0); 1206174588Sdes if (asconf->whoTo != alt) { 120762981Sdes sctp_free_remote_addr(asconf->whoTo); 1208106175Simp asconf->whoTo = alt; 1209106205Sdes atomic_add_int(&alt->ref_count, 1); 121098748Sdes } 121198748Sdes /* See if an ECN Echo is also stranded */ 1212106175Simp TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 1213106175Simp if ((chk->whoTo == net) && 1214106175Simp (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 1215109967Sdes sctp_free_remote_addr(chk->whoTo); 1216106205Sdes chk->whoTo = alt; 1217174588Sdes if (chk->sent != SCTP_DATAGRAM_RESEND) { 1218106205Sdes chk->sent = SCTP_DATAGRAM_RESEND; 1219174588Sdes chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 1220106205Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 122190267Sdes } 122290267Sdes atomic_add_int(&alt->ref_count, 1); 122362981Sdes } 122462981Sdes } 122562981Sdes TAILQ_FOREACH(chk, &stcb->asoc.asconf_send_queue, sctp_next) { 122697856Sdes if (chk->whoTo != alt) { 122797856Sdes sctp_free_remote_addr(chk->whoTo); 122897856Sdes chk->whoTo = alt; 122997856Sdes atomic_add_int(&alt->ref_count, 1); 1230174588Sdes } 123197856Sdes if (asconf->sent != SCTP_DATAGRAM_RESEND && chk->sent != SCTP_DATAGRAM_UNSENT) 123297856Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 123397856Sdes chk->sent = SCTP_DATAGRAM_RESEND; 123498117Sdes chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 123598117Sdes } 1236253680Sdes if (!(net->dest_state & SCTP_ADDR_REACHABLE)) { 1237253680Sdes /* 1238253680Sdes * If the address went un-reachable, we need to move 1239253680Sdes * to the alternate for ALL chunks in queue 1240253680Sdes */ 1241253680Sdes sctp_move_chunks_from_net(stcb, net); 1242253680Sdes } 1243253680Sdes /* mark the retran info */ 1244253680Sdes if (asconf->sent != SCTP_DATAGRAM_RESEND) 1245253680Sdes sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1246253680Sdes asconf->sent = SCTP_DATAGRAM_RESEND; 1247253680Sdes asconf->flags |= CHUNK_FLAGS_FRAGMENT_OK; 1248253680Sdes 1249253680Sdes /* send another ASCONF if any and we can do */ 1250253680Sdes sctp_send_asconf(stcb, alt, SCTP_ADDR_NOT_LOCKED); 1251253680Sdes } 125297856Sdes return (0); 1253230307Sdes} 1254141970Sdes 125597856Sdes/* Mobility adaptation */ 125697856Sdesvoid 125797856Sdessctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 125897856Sdes struct sctp_nets *net SCTP_UNUSED) 125997856Sdes{ 126041989Sdes if (stcb->asoc.deleted_primary == NULL) { 126141989Sdes SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n"); 126241989Sdes sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 1263174588Sdes return; 126490267Sdes } 126541989Sdes SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: finished to keep deleted primary "); 126690267Sdes SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 126741989Sdes sctp_free_remote_addr(stcb->asoc.deleted_primary); 126890267Sdes stcb->asoc.deleted_primary = NULL; 126990268Sdes sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 127090267Sdes return; 127141989Sdes} 127241989Sdes 127390267Sdes/* 1274109967Sdes * For the shutdown and shutdown-ack, we do not keep one around on the 127590267Sdes * control queue. This means we must generate a new one and call the general 127690267Sdes * chunk output routine, AFTER having done threshold management. 1277174588Sdes * It is assumed that net is non-NULL. 127890267Sdes */ 127990267Sdesint 128090268Sdessctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 128190267Sdes struct sctp_nets *net) 128290267Sdes{ 128341989Sdes struct sctp_nets *alt; 128490267Sdes 128590267Sdes /* first threshold management */ 1286176105Sdes if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 128741989Sdes /* Assoc is over */ 128890267Sdes return (1); 128990267Sdes } 129090267Sdes sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 129190267Sdes /* second select an alternative */ 129241989Sdes alt = sctp_find_alternate_net(stcb, net, 0); 1293109695Sdes 1294109695Sdes /* third generate a shutdown into the queue for out net */ 1295109695Sdes sctp_send_shutdown(stcb, alt); 1296109695Sdes 1297109695Sdes /* fourth restart timer */ 1298174588Sdes sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt); 1299109695Sdes return (0); 1300109695Sdes} 1301109695Sdes 1302178234Scpercivaint 1303109695Sdessctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1304109695Sdes struct sctp_nets *net) 1305109695Sdes{ 1306109695Sdes struct sctp_nets *alt; 1307109695Sdes 1308109695Sdes /* first threshold management */ 1309109695Sdes if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1310109695Sdes /* Assoc is over */ 1311174588Sdes return (1); 1312109695Sdes } 1313109695Sdes sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 1314109695Sdes /* second select an alternative */ 1315109695Sdes alt = sctp_find_alternate_net(stcb, net, 0); 1316109695Sdes 1317109695Sdes /* third generate a shutdown into the queue for out net */ 1318109695Sdes sctp_send_shutdown_ack(stcb, alt); 1319109967Sdes 1320174588Sdes /* fourth restart timer */ 1321109695Sdes sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt); 1322109695Sdes return (0); 1323109695Sdes} 1324109695Sdes 1325109695Sdesstatic void 1326109695Sdessctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, 1327109695Sdes struct sctp_tcb *stcb) 1328109695Sdes{ 1329109695Sdes struct sctp_stream_queue_pending *sp; 1330109695Sdes unsigned int i, chks_in_queue = 0; 1331109695Sdes int being_filled = 0; 1332109967Sdes 1333109695Sdes /* 1334109695Sdes * This function is ONLY called when the send/sent queues are empty. 1335109695Sdes */ 1336109695Sdes if ((stcb == NULL) || (inp == NULL)) 1337109695Sdes return; 1338174588Sdes 1339109695Sdes if (stcb->asoc.sent_queue_retran_cnt) { 1340174588Sdes SCTP_PRINTF("Hmm, sent_queue_retran_cnt is non-zero %d\n", 1341109695Sdes stcb->asoc.sent_queue_retran_cnt); 1342109695Sdes stcb->asoc.sent_queue_retran_cnt = 0; 1343109695Sdes } 1344174588Sdes if (stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { 1345109695Sdes /* No stream scheduler information, initialize scheduler */ 1346174588Sdes stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 0); 1347109695Sdes if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { 1348109695Sdes /* yep, we lost a stream or two */ 1349109695Sdes SCTP_PRINTF("Found additional streams NOT managed by scheduler, corrected\n"); 1350109695Sdes } else { 1351109695Sdes /* no streams lost */ 1352174588Sdes stcb->asoc.total_output_queue_size = 0; 1353109695Sdes } 1354174588Sdes } 1355109695Sdes /* Check to see if some data queued, if so report it */ 1356109967Sdes for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1357109960Sjwd if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { 1358174588Sdes TAILQ_FOREACH(sp, &stcb->asoc.strmout[i].outqueue, next) { 1359109695Sdes if (sp->msg_is_complete) 1360109695Sdes being_filled++; 1361109695Sdes chks_in_queue++; 1362174588Sdes } 1363109695Sdes } 1364109967Sdes } 1365109960Sjwd if (chks_in_queue != stcb->asoc.stream_queue_cnt) { 1366174588Sdes SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n", 1367109695Sdes stcb->asoc.stream_queue_cnt, chks_in_queue); 1368109695Sdes } 1369109695Sdes if (chks_in_queue) { 1370174588Sdes /* call the output queue function */ 1371109695Sdes sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1372109695Sdes if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) && 1373109695Sdes (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1374109695Sdes /* 1375109695Sdes * Probably should go in and make it go back through 1376109695Sdes * and add fragments allowed 1377109695Sdes */ 1378109695Sdes if (being_filled == 0) { 1379109695Sdes SCTP_PRINTF("Still nothing moved %d chunks are stuck\n", 1380109695Sdes chks_in_queue); 1381109695Sdes } 1382109695Sdes } 1383174752Sdes } else { 1384174752Sdes SCTP_PRINTF("Found no chunks on any queue tot:%lu\n", 1385174752Sdes (u_long)stcb->asoc.total_output_queue_size); 1386174752Sdes stcb->asoc.total_output_queue_size = 0; 1387174752Sdes } 1388174752Sdes} 1389174752Sdes 1390174752Sdesint 1391174752Sdessctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1392174752Sdes struct sctp_nets *net) 1393174752Sdes{ 1394174752Sdes uint8_t net_was_pf; 1395174752Sdes 1396174752Sdes if (net->dest_state & SCTP_ADDR_PF) { 1397174752Sdes net_was_pf = 1; 1398174752Sdes } else { 1399174752Sdes net_was_pf = 0; 1400174752Sdes } 1401174752Sdes if (net->hb_responded == 0) { 1402174752Sdes if (net->ro._s_addr) { 1403174752Sdes /* 1404174752Sdes * Invalidate the src address if we did not get a 1405174752Sdes * response last time. 1406174752Sdes */ 1407174752Sdes sctp_free_ifa(net->ro._s_addr); 1408174752Sdes net->ro._s_addr = NULL; 1409174752Sdes net->src_addr_selected = 0; 1410174761Sdes } 1411174752Sdes sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 1412174752Sdes if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1413174752Sdes /* Assoc is over */ 1414174752Sdes return (1); 1415174761Sdes } 1416174752Sdes } 1417174752Sdes /* Zero PBA, if it needs it */ 1418174752Sdes if (net->partial_bytes_acked) { 1419198339Sfabient net->partial_bytes_acked = 0; 1420174752Sdes } 1421174752Sdes if ((stcb->asoc.total_output_queue_size > 0) && 1422174752Sdes (TAILQ_EMPTY(&stcb->asoc.send_queue)) && 1423174752Sdes (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1424174752Sdes sctp_audit_stream_queues_for_size(inp, stcb); 1425174752Sdes } 1426174752Sdes if (!(net->dest_state & SCTP_ADDR_NOHB) && 1427174752Sdes !((net_was_pf == 0) && (net->dest_state & SCTP_ADDR_PF))) { 1428174752Sdes /* 1429174752Sdes * when move to PF during threshold mangement, a HB has been 1430174752Sdes * queued in that routine 1431 */ 1432 uint32_t ms_gone_by; 1433 1434 if ((net->last_sent_time.tv_sec > 0) || 1435 (net->last_sent_time.tv_usec > 0)) { 1436 struct timeval diff; 1437 1438 SCTP_GETTIME_TIMEVAL(&diff); 1439 timevalsub(&diff, &net->last_sent_time); 1440 ms_gone_by = (uint32_t)(diff.tv_sec * 1000) + 1441 (uint32_t)(diff.tv_usec / 1000); 1442 } else { 1443 ms_gone_by = 0xffffffff; 1444 } 1445 if ((ms_gone_by >= net->heart_beat_delay) || 1446 (net->dest_state & SCTP_ADDR_PF)) { 1447 sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 1448 } 1449 } 1450 return (0); 1451} 1452 1453void 1454sctp_pathmtu_timer(struct sctp_inpcb *inp, 1455 struct sctp_tcb *stcb, 1456 struct sctp_nets *net) 1457{ 1458 uint32_t next_mtu, mtu; 1459 1460 next_mtu = sctp_get_next_mtu(net->mtu); 1461 1462 if ((next_mtu > net->mtu) && (net->port == 0)) { 1463 if ((net->src_addr_selected == 0) || 1464 (net->ro._s_addr == NULL) || 1465 (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 1466 if ((net->ro._s_addr != NULL) && (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 1467 sctp_free_ifa(net->ro._s_addr); 1468 net->ro._s_addr = NULL; 1469 net->src_addr_selected = 0; 1470 } else if (net->ro._s_addr == NULL) { 1471#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE) 1472 if (net->ro._l_addr.sa.sa_family == AF_INET6) { 1473 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1474 1475 /* KAME hack: embed scopeid */ 1476 (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); 1477 } 1478#endif 1479 1480 net->ro._s_addr = sctp_source_address_selection(inp, 1481 stcb, 1482 (sctp_route_t *)&net->ro, 1483 net, 0, stcb->asoc.vrf_id); 1484#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE) 1485 if (net->ro._l_addr.sa.sa_family == AF_INET6) { 1486 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1487 1488 (void)sa6_recoverscope(sin6); 1489 } 1490#endif /* INET6 */ 1491 } 1492 if (net->ro._s_addr) 1493 net->src_addr_selected = 1; 1494 } 1495 if (net->ro._s_addr) { 1496 mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt); 1497#if defined(INET) || defined(INET6) 1498 if (net->port) { 1499 mtu -= sizeof(struct udphdr); 1500 } 1501#endif 1502 if (mtu > next_mtu) { 1503 net->mtu = next_mtu; 1504 } else { 1505 net->mtu = mtu; 1506 } 1507 } 1508 } 1509 /* restart the timer */ 1510 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); 1511} 1512 1513void 1514sctp_autoclose_timer(struct sctp_inpcb *inp, 1515 struct sctp_tcb *stcb, 1516 struct sctp_nets *net) 1517{ 1518 struct timeval tn, *tim_touse; 1519 struct sctp_association *asoc; 1520 int ticks_gone_by; 1521 1522 (void)SCTP_GETTIME_TIMEVAL(&tn); 1523 if (stcb->asoc.sctp_autoclose_ticks && 1524 sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1525 /* Auto close is on */ 1526 asoc = &stcb->asoc; 1527 /* pick the time to use */ 1528 if (asoc->time_last_rcvd.tv_sec > 1529 asoc->time_last_sent.tv_sec) { 1530 tim_touse = &asoc->time_last_rcvd; 1531 } else { 1532 tim_touse = &asoc->time_last_sent; 1533 } 1534 /* Now has long enough transpired to autoclose? */ 1535 ticks_gone_by = SEC_TO_TICKS(tn.tv_sec - tim_touse->tv_sec); 1536 if ((ticks_gone_by > 0) && 1537 (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) { 1538 /* 1539 * autoclose time has hit, call the output routine, 1540 * which should do nothing just to be SURE we don't 1541 * have hanging data. We can then safely check the 1542 * queues and know that we are clear to send 1543 * shutdown 1544 */ 1545 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 1546 /* Are we clean? */ 1547 if (TAILQ_EMPTY(&asoc->send_queue) && 1548 TAILQ_EMPTY(&asoc->sent_queue)) { 1549 /* 1550 * there is nothing queued to send, so I'm 1551 * done... 1552 */ 1553 if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1554 /* only send SHUTDOWN 1st time thru */ 1555 struct sctp_nets *netp; 1556 1557 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 1558 (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1559 SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1560 } 1561 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); 1562 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 1563 sctp_stop_timers_for_shutdown(stcb); 1564 if (stcb->asoc.alternate) { 1565 netp = stcb->asoc.alternate; 1566 } else { 1567 netp = stcb->asoc.primary_destination; 1568 } 1569 sctp_send_shutdown(stcb, netp); 1570 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, 1571 stcb->sctp_ep, stcb, 1572 netp); 1573 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1574 stcb->sctp_ep, stcb, 1575 netp); 1576 } 1577 } 1578 } else { 1579 /* 1580 * No auto close at this time, reset t-o to check 1581 * later 1582 */ 1583 int tmp; 1584 1585 /* fool the timer startup to use the time left */ 1586 tmp = asoc->sctp_autoclose_ticks; 1587 asoc->sctp_autoclose_ticks -= ticks_gone_by; 1588 sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1589 net); 1590 /* restore the real tick value */ 1591 asoc->sctp_autoclose_ticks = tmp; 1592 } 1593 } 1594} 1595