18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without 78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met: 88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice, 100ac02f34d6041cd0018437596a5a9a94685e6919tuexen * this list of conditions and the following disclaimer. 118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright 138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * notice, this list of conditions and the following disclaimer in 140ac02f34d6041cd0018437596a5a9a94685e6919tuexen * the documentation and/or other materials provided with the distribution. 158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its 178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * contributors may be used to endorse or promote products derived 188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * from this software without specific prior written permission. 198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE. 318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__ 348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h> 35a8657c4fc04fb9cc82100f648810d51ec6ab155at__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 269448 2014-08-02 21:36:40Z tuexen $"); 368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define _IP_VHL 398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h> 408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h> 418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace_os_FreeBSD) 438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet6/sctp6_var.h> 448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h> 478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h> 488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h> 498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h> 508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h> 518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h> 528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h> 538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h> 548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_input.h> 558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp.h> 568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h> 5748830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 580612043f643c9b26245564c05defca64d472060etuexen#if !defined(__Userspace_os_Windows) 598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/udp.h> 6081616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif 616c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 6 658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_audit_retranmission_queue(struct sctp_association *asoc) 698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER4, "Audit invoked on send queue cnt:%d onqueue:%d\n", 738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_retran_cnt, 748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt); 758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_retran_cnt = 0; 768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt = 0; 778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent == SCTP_DATAGRAM_RESEND) { 798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->sent_queue_retran_cnt); 808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt++; 828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) { 848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent == SCTP_DATAGRAM_RESEND) { 858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->sent_queue_retran_cnt); 868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &asoc->asconf_send_queue, sctp_next) { 898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent == SCTP_DATAGRAM_RESEND) { 908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->sent_queue_retran_cnt); 918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER4, "Audit completes retran:%d onqueue:%d\n", 948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_retran_cnt, 958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt); 968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, uint16_t threshold) 1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net) { 1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->error_count++; 1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER4, "Error count for %p now %d thresh:%d\n", 105ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)net, net->error_count, 1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->failure_threshold); 1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->error_count > net->failure_threshold) { 1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We had a threshold failure */ 1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->dest_state & SCTP_ADDR_REACHABLE) { 1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_REACHABLE; 1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_PF; 1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, 11447674b651417d493ff4e0318113fd7beeef119dbtuexen stcb, 0, 1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void *)net, SCTP_SO_NOT_LOCKED); 1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((net->pf_threshold < net->failure_threshold) && 1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->error_count > net->pf_threshold)) { 1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_PF)) { 1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_PF; 1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->last_active = sctp_get_tick_count(); 1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); 1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) 1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net) { 1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) { 1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_INCR, 1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.overall_error_count+1), 1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_TIMER, 1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count++; 1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_INCR, 1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.overall_error_count+1), 1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_TIMER, 1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count++; 1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER4, "Overall error count for %p now %d thresh:%u state:%x\n", 153ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)&stcb->asoc, stcb->asoc.overall_error_count, 1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t)threshold, 1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((net == NULL) ? (uint32_t) 0 : (uint32_t) net->dest_state)); 1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We specifically do not do >= to give the assoc one more change 1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * before we fail it. 1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.overall_error_count > threshold) { 1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Abort notification sends a ULP notify */ 1628f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1648f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 1658f9e45fea288542b24a6bda01269c6fc184d991at "Association error couter exceeded"); 1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_1; 1678f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); 1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 173000a5bac556b28e74e4e98c540f66b1743e9312dtuexen/* 1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_find_alternate_net() returns a non-NULL pointer as long 1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the argument net is non-NULL. 1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_nets * 1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_alternate_net(struct sctp_tcb *stcb, 1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, 1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int mode) 1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Find and return an alternate network if possible */ 1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt, *mnet, *min_errors_net = NULL , *max_cwnd_net = NULL; 1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int once; 1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS 5/14/07 - Initialize min_errors to an impossible value. */ 1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int min_errors = -1; 1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t max_cwnd = 0; 1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.numnets == 1) { 1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No others but net */ 1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (TAILQ_FIRST(&stcb->asoc.nets)); 1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * JRS 5/14/07 - If mode is set to 2, use the CMT PF find alternate net algorithm. 1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This algorithm chooses the active destination (not in PF state) with the largest 1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cwnd value. If all destinations are in PF state, unreachable, or unconfirmed, choose 1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the desination that is in PF state with the lowest error count. In case of a tie, 1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * choose the destination that was most recently active. 1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mode == 2) { 2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { 2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS 5/14/07 - If the destination is unreachable or unconfirmed, skip it. */ 2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || 2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { 2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * JRS 5/14/07 - If the destination is reachable but in PF state, compare 2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the error count of the destination to the minimum error count seen thus far. 2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Store the destination with the lower error count. If the error counts are 2118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * equal, store the destination that was most recently active. 2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mnet->dest_state & SCTP_ADDR_PF) { 2148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * JRS 5/14/07 - If the destination under consideration is the current 2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * destination, work as if the error count is one higher. The 2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * actual error count will not be incremented until later in the 2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * t3 handler. 2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mnet == net) { 221e2828360ea9cf8951730d46f5c14626c9425cb30t if (min_errors == -1) { 2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors = mnet->error_count + 1; 2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors_net = mnet; 2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (mnet->error_count + 1 < min_errors) { 2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors = mnet->error_count + 1; 2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors_net = mnet; 2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (mnet->error_count + 1 == min_errors 2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen && mnet->last_active > min_errors_net->last_active) { 2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors_net = mnet; 2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors = mnet->error_count + 1; 2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 234e2828360ea9cf8951730d46f5c14626c9425cb30t if (min_errors == -1) { 2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors = mnet->error_count; 2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors_net = mnet; 2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (mnet->error_count < min_errors) { 2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors = mnet->error_count; 2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors_net = mnet; 2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (mnet->error_count == min_errors 2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen && mnet->last_active > min_errors_net->last_active) { 2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors_net = mnet; 2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_errors = mnet->error_count; 2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * JRS 5/14/07 - If the destination is reachable and not in PF state, compare the 2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cwnd of the destination to the highest cwnd seen thus far. Store the 2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * destination with the higher cwnd value. If the cwnd values are equal, 2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * randomly choose one of the two destinations. 2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (max_cwnd < mnet->cwnd) { 2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd_net = mnet; 2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd = mnet->cwnd; 2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (max_cwnd == mnet->cwnd) { 2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t rndval; 2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t this_random; 2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.hb_random_idx > 3) { 2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep); 2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(stcb->asoc.hb_random_values, &rndval, sizeof(stcb->asoc.hb_random_values)); 2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_random = stcb->asoc.hb_random_values[0]; 2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_random_idx++; 2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_ect_randombit = 0; 2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_random_idx++; 2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_ect_randombit = 0; 2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (this_random % 2 == 1) { 2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd_net = mnet; 2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd = mnet->cwnd; /* Useless? */ 2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (max_cwnd_net == NULL) { 2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (min_errors_net == NULL) { 2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (net); 2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (min_errors_net); 2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (max_cwnd_net); 2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* JRS 5/14/07 - If mode is set to 1, use the CMT policy for choosing an alternate net. */ 2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else if (mode == 1) { 2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { 2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || 2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { 2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will skip ones that are not-reachable or 2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * unconfirmed 2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (max_cwnd < mnet->cwnd) { 2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd_net = mnet; 2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd = mnet->cwnd; 3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (max_cwnd == mnet->cwnd) { 3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t rndval; 3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t this_random; 3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.hb_random_idx > 3) { 3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep); 3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(stcb->asoc.hb_random_values, &rndval, 3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(stcb->asoc.hb_random_values)); 3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_random = stcb->asoc.hb_random_values[0]; 3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_random_idx = 0; 3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_ect_randombit = 0; 3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx]; 3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_random_idx++; 3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.hb_ect_randombit = 0; 3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (this_random % 2) { 3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd_net = mnet; 3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen max_cwnd = mnet->cwnd; 3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (max_cwnd_net) { 3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (max_cwnd_net); 3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mnet = net; 3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen once = 0; 3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mnet == NULL) { 3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mnet = TAILQ_FIRST(&stcb->asoc.nets); 3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mnet == NULL) { 3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen do { 3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = TAILQ_NEXT(mnet, sctp_next); 3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt == NULL) 338e2828360ea9cf8951730d46f5c14626c9425cb30t { 3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen once++; 3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (once > 1) { 3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = TAILQ_FIRST(&stcb->asoc.nets); 3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt == NULL) { 3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt->ro.ro_rt == NULL) { 3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt->ro._s_addr) { 3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(alt->ro._s_addr); 3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt->ro._s_addr = NULL; 3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt->src_addr_selected = 0; 3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) && 3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (alt->ro.ro_rt != NULL) && 3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) { 3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Found a reachable address */ 3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mnet = alt; 3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } while (alt != NULL); 3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt == NULL) { 3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Case where NO insv network exists (dormant state) */ 3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we rotate destinations */ 3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen once = 0; 3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mnet = net; 3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen do { 3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mnet == NULL) { 3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (TAILQ_FIRST(&stcb->asoc.nets)); 3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = TAILQ_NEXT(mnet, sctp_next); 3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt == NULL) { 3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen once++; 3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (once > 1) { 3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = TAILQ_FIRST(&stcb->asoc.nets); 3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) && 3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (alt != net)) { 3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Found an alternate address */ 3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mnet = alt; 3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } while (alt != NULL); 3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt == NULL) { 3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (net); 3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (alt); 3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_backoff_on_timeout(struct sctp_tcb *stcb, 3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, 4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int win_probe, 4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_marked, int num_abandoned) 4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO == 0) { 4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.minrto; 4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO <<= 1; 4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO > stcb->asoc.maxrto) { 4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.maxrto; 4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((win_probe == 0) && (num_marked || num_abandoned)) { 4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We don't apply penalty to window probe scenarios */ 4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS - Use the congestion control given in the CC module */ 4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout(stcb, net); 4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef INVARIANTS 4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_recover_sent_list(struct sctp_tcb *stcb) 4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.TSN_seq)) { 4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n", 428ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)chk, chk->rec.data.TSN_seq, asoc->last_acked_seq); 42960db5740d3bcc26fd4ebc19b6b0652506994fd14t if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 430446be8e8a472f6e688885674d2430118fc4be5d7t if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 431446be8e8a472f6e688885674d2430118fc4be5d7t asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 432446be8e8a472f6e688885674d2430118fc4be5d7t } 433446be8e8a472f6e688885674d2430118fc4be5d7t } 4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 43537a477684cd9fd2f02430cc2a9822c8c160973ect if (PR_SCTP_ENABLED(chk->flags)) { 4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->pr_sctp_cnt != 0) 4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pr_sctp_cnt--; 4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_bufspace(stcb, asoc, chk, 1); 4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 444a8657c4fc04fb9cc82100f648810d51ec6ab155at if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(chk->flags)) { 4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt_removeable--; 4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt--; 4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("after recover order is as follows\n"); 4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 454ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTP_PRINTF("chk:%p TSN:%x\n", (void *)chk, chk->rec.data.TSN_seq); 4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mark_all_for_resend(struct sctp_tcb *stcb, 4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, 4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt, 4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int window_probe, 4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *num_marked, 4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *num_abandoned) 4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Mark all chunks (well not all) that were sent to *net for 4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * retransmission. Move them to alt for there destination as well... 4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We only mark chunks that have been outstanding long enough to 4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have received feed-back. 4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *lnets; 4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval now, min_wait, tv; 4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cur_rto; 4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt_abandoned; 4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int audit_tf, num_mk, fir; 4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int cnt_mk; 4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t orig_flight, orig_tf; 4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsnlast, tsnfirst; 483b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int recovery_cnt = 0; 4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* none in flight now */ 4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen audit_tf = 0; 4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fir = 0; 4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * figure out how long a data chunk must be pending before we can 4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * mark it .. 4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&now); 4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get cur rto in micro-seconds */ 4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cur_rto *= 1000; 4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(cur_rto, 4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd, 5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen window_probe, 5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_T3_MARK_TIME); 5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(net->flight_size, 0, 0, SCTP_FR_CWND_REPORT); 5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT); 5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tv.tv_sec = cur_rto / 1000000; 5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tv.tv_usec = cur_rto % 1000000; 5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__ 5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen timersub(&now, &tv, &min_wait); 5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_wait = now; 5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen timevalsub(&min_wait, &tv); 5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) { 5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if we hit here, we don't have enough seconds on the clock 5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to account for the RTO. We just let the lower seconds be 5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the bounds and don't worry about it. This may mean we 5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will mark a lot more than we should. 5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min_wait.tv_sec = min_wait.tv_usec = 0; 5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME); 5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME); 5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Our rwnd will be incorrect here since we are not adding back the 5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cnt * mbuf but we will fix that down below. 5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen orig_flight = net->flight_size; 5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen orig_tf = stcb->asoc.total_flight; 5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->fast_retran_ip = 0; 5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now on to each chunk */ 5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_abandoned = 0; 5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_mk = cnt_mk = 0; 5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsnfirst = tsnlast = 0; 5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef INVARIANTS 5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen start_again: 5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) { 5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) { 5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Strange case our list got out of order? */ 544ac15c9a0691d5760c1c3b9b70f6daaaa067b7274t SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x\n", 5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq); 5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen recovery_cnt++; 5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("last acked >= chk on sent-Q"); 5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt); 5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_recover_sent_list(stcb); 5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (recovery_cnt < 10) { 5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto start_again; 5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Recovery fails %d times??\n", recovery_cnt); 5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) { 5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * found one to mark: If it is less than 5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * DATAGRAM_ACKED it MUST not be a skipped or marked 5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * TSN but instead one that is either already set 5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for retransmission OR one that needs 5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * retransmission. 5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate its been outstanding long enough */ 5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(chk->rec.data.TSN_seq, 5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent_rcv_time.tv_sec, 5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent_rcv_time.tv_usec, 5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_T3_MARK_TIME); 5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->sent_rcv_time.tv_sec > min_wait.tv_sec) && (window_probe == 0)) { 5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we have reached a chunk that was sent 5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * some seconds past our min.. forget it we 5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will find no more to send. 5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(0, 5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent_rcv_time.tv_sec, 5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent_rcv_time.tv_usec, 5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_T3_STOPPED); 5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((chk->sent_rcv_time.tv_sec == min_wait.tv_sec) && 5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (window_probe == 0)) { 5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must look at the micro seconds to 5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * know. 5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) { 5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ok it was sent after our boundary 5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * time. 5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 602a8657c4fc04fb9cc82100f648810d51ec6ab155at if (stcb->asoc.prsctp_supported && PR_SCTP_TTL_ENABLED(chk->flags)) { 6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Is it expired? */ 6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__ 6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timercmp(&now, &chk->rec.data.timetodrop, >)) { 6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timevalcmp(&now, &chk->rec.data.timetodrop, >)) { 6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yes so drop it */ 6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_release_pr_sctp_chunk(stcb, 6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk, 61347674b651417d493ff4e0318113fd7beeef119dbtuexen 1, 6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_abandoned++; 6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 620a8657c4fc04fb9cc82100f648810d51ec6ab155at if (stcb->asoc.prsctp_supported && PR_SCTP_RTX_ENABLED(chk->flags)) { 6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Has it been retransmitted tv_sec times? */ 6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) { 6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_release_pr_sctp_chunk(stcb, 6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk, 62647674b651417d493ff4e0318113fd7beeef119dbtuexen 1, 6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_abandoned++; 6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent < SCTP_DATAGRAM_RESEND) { 6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_mk++; 6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (fir == 0) { 6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fir = 1; 6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsnfirst = chk->rec.data.TSN_seq; 6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsnlast = chk->rec.data.TSN_seq; 6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count, 6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, SCTP_FR_T3_MARKED); 6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.chunk_was_revoked) { 6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* deflate the cwnd */ 6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo->cwnd -= chk->book_size; 6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.chunk_was_revoked = 0; 6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->marked_retrans++; 6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.marked_retrans++; 6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO, 6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo->flight_size, 6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->book_size, 6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)chk->whoTo, 6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.TSN_seq); 6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(chk); 6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, chk); 6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd += chk->send_size; 6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh); 6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_markedretrans); 6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* reset the TSN for striking and other FR stuff */ 6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.doing_fast_retransmit = 0; 6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Clear any time so NO RTT is being done */ 6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->do_rtt) { 6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->whoTo->rto_needed == 0) { 6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo->rto_needed = 1; 6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->do_rtt = 0; 6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt != net) { 6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->no_fr_allowed = 1; 6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = alt; 6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->no_fr_allowed = 0; 6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* CMT: Do not allow FRs on retransmitted TSNs. 6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_cmt_on_off > 0) { 6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->no_fr_allowed = 1; 6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef THIS_SHOULD_NOT_BE_DONE 6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (chk->sent == SCTP_DATAGRAM_ACKED) { 6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remember highest acked one */ 6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen could_be_sent = chk; 7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent == SCTP_DATAGRAM_RESEND) { 7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_mk++; 7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((orig_flight - net->flight_size) != (orig_tf - stcb->asoc.total_flight)) { 7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we did not subtract the same things? */ 7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen audit_tf = 1; 7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT); 7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_mk) { 7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n", 7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsnlast); 7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%ld\n", 7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_mk, (u_long)stcb->asoc.peers_rwnd); 7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER1, "LAST TSN marked was %x\n", 7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsnlast); 7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER1, "Num marked for retransmission was %d peer-rwd:%d\n", 7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_mk, 7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (int)stcb->asoc.peers_rwnd); 7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *num_marked = num_mk; 7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *num_abandoned = cnt_abandoned; 7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now check for a ECN Echo that may be stranded And 7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * include the cnt_mk'd to have all resends in the 7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * control queue. 7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent == SCTP_DATAGRAM_RESEND) { 7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_mk++; 7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->whoTo == net) && 7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = alt; 7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent != SCTP_DATAGRAM_RESEND) { 7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_mk++; 7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef THIS_SHOULD_NOT_BE_DONE 7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.sent_queue_retran_cnt == 0) && (could_be_sent)) { 7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fix it so we retransmit the highest acked anyway */ 7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_mk++; 7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen could_be_sent->sent = SCTP_DATAGRAM_RESEND; 7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 756000a5bac556b28e74e4e98c540f66b1743e9312dtuexen#endif 7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) { 7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Local Audit says there are %d for retran asoc cnt:%d we marked:%d this time\n", 7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_mk, stcb->asoc.sent_queue_retran_cnt, num_mk); 7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef SCTP_AUDITING_ENABLED 7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sent_queue_retran_cnt = cnt_mk; 7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (audit_tf) { 7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER4, 7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Audit total flight due to negative value net:%p\n", 769ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)net); 7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_flight = 0; 7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_flight_count = 0; 7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Clear all networks flight size */ 7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(lnets, &stcb->asoc.nets, sctp_next) { 7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lnets->flight_size = 0; 7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER4, 7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Net:%p c-f cwnd:%d ssthresh:%d\n", 777ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)lnets, lnets->cwnd, lnets->ssthresh); 7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent < SCTP_DATAGRAM_RESEND) { 7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_UP, 7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo->flight_size, 7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->book_size, 7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)chk->whoTo, 7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.TSN_seq); 7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_increase(chk); 7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_increase(stcb, chk); 7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We return 1 if we only have a window probe outstanding */ 7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_t3rxt_timer(struct sctp_inpcb *inp, 8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, 8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int win_probe, num_mk, num_abandoned; 8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(0, 0, 0, SCTP_FR_T3_TIMEOUT); 8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { 8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *lnet; 8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == lnet) { 8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, lnet, 1, SCTP_CWND_LOG_FROM_T3); 8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_LOG_FROM_T3); 8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Find an alternate and mark those for retransmission */ 8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.peers_rwnd == 0) && 8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.total_flight < net->mtu)) { 8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_timowindowprobe); 8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen win_probe = 1; 8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen win_probe = 0; 8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (win_probe == 0) { 8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We don't do normal threshold management on window probes */ 8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, net, 8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.max_send_times)) { 8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Association was destroyed */ 8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net != stcb->asoc.primary_destination) { 8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* send a immediate HB if our RTO is stale */ 8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval now; 8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int ms_goneby; 8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&now); 8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->last_sent_time.tv_sec) { 8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ms_goneby = (now.tv_sec - net->last_sent_time.tv_sec) * 1000; 8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ms_goneby = 0; 8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net->dest_state & SCTP_ADDR_PF) == 0) { 8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ms_goneby > net->RTO) || (net->RTO == 0)) { 8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no recent feed back in an RTO or 8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * more, request a RTT update 8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For a window probe we don't penalize the net's but only 8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the association. This may fail it if SACKs are not coming 8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * back. If sack's are coming with rwnd locked at 0, we will 8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * continue to hold things waiting for rwnd to raise 8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, NULL, 8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.max_send_times)) { 8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Association was destroyed */ 8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_cmt_on_off > 0) { 8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->pf_threshold < net->failure_threshold) { 8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, net, 2); 8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: Using RTX_SSTHRESH policy for CMT. 8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If CMT is being used, then pick dest with 8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * largest ssthresh for any retransmission. 8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, net, 1); 8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CUCv2: If a different dest is picked for 8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the retransmission, then new 8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (rtx-)pseudo_cumack needs to be tracked 8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for orig dest. Let CUCv2 track new (rtx-) 8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pseudo-cumack always. 8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->find_pseudo_cumack = 1; 8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->find_rtx_pseudo_cumack = 1; 8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, net, 0); 8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_mk = 0; 8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_abandoned = 0; 898000a5bac556b28e74e4e98c540f66b1743e9312dtuexen (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe, 8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &num_mk, &num_abandoned); 9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* FR Loss recovery just ended with the T3. */ 9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.fast_retran_loss_recovery = 0; 9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* CMT FR loss recovery ended with the T3 */ 9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->fast_retran_loss_recovery = 0; 905000a5bac556b28e74e4e98c540f66b1743e9312dtuexen if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) && 9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->flight_size == 0)) { 9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins)(stcb, net); 9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * setup the sat loss recovery that prevents satellite cwnd advance. 9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sat_t3_loss_recovery = 1; 9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq; 9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Backoff the timer and cwnd */ 9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned); 9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((!(net->dest_state & SCTP_ADDR_REACHABLE)) || 9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->dest_state & SCTP_ADDR_PF)) { 9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Move all pending over too */ 9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_chunks_from_net(stcb, net); 9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get the address that failed, to 9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * force a new src address selecton and 9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a route allocation. 9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._s_addr) { 9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 929e2828360ea9cf8951730d46f5c14626c9425cb30t net->ro._s_addr = NULL; 9308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 931e2828360ea9cf8951730d46f5c14626c9425cb30t net->src_addr_selected = 0; 9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Force a route allocation too */ 9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro.ro_rt) { 9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(net->ro.ro_rt); 9368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt = NULL; 9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Was it our primary? */ 9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.primary_destination == net) && (alt != net)) { 9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Yes, note it as such and find an alternate note: 9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this means HB code must use this to resent the 9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * primary if it goes active AND if someone does a 9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * change-primary then this flag must be cleared 9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * from any net structures. 9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.alternate) { 9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = alt; 9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.alternate->ref_count, 1); 9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Special case for cookie-echo'ed case, we don't do output but must 9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * await the COOKIE-ACK before retransmission 9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we just reset the timer and start again since we 9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have not established the asoc 9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); 9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 967a8657c4fc04fb9cc82100f648810d51ec6ab155at if (stcb->asoc.prsctp_supported) { 9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *lchk; 9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc); 9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* C3. See if we need to send a Fwd-TSN */ 9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(stcb->asoc.advanced_peer_ack_point, stcb->asoc.last_acked_seq)) { 9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_forward_tsn(stcb, &stcb->asoc); 9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk) { 9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assure a timer is up */ 9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, lchk->whoTo); 9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { 9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, net, net->cwnd, SCTP_CWND_LOG_FROM_RTX); 9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_t1init_timer(struct sctp_inpcb *inp, 9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, 9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* bump the thresholds */ 9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.delayed_connection) { 9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * special hook for delayed connection. The library did NOT 9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * complete the rest of its sends. 9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.delayed_connection = 0; 9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE((&stcb->asoc)) != SCTP_STATE_COOKIE_WAIT) { 10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, net, 10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.max_init_times)) { 10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Association was destroyed */ 10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.dropped_special_cnt = 0; 10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, stcb->asoc.primary_destination, 1, 0, 0); 10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.initial_init_rto_max < net->RTO) { 10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.initial_init_rto_max; 10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.numnets > 1) { 10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If we have more than one addr use it */ 10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination, 0); 10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt != stcb->asoc.primary_destination) { 10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_chunks_from_net(stcb, stcb->asoc.primary_destination); 10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = alt; 10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Send out a new init */ 10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED); 10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 10288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For cookie and asconf we actually need to find and mark for resend, then 10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * increment the resend counter (after all the threshold management stuff of 10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * course). 10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cookie_timer(struct sctp_inpcb *inp, 10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, 10370ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sctp_nets *net SCTP_UNUSED) 10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *cookie; 10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first before all else we must find the cookie */ 10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, sctp_next) { 10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie == NULL) { 10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* FOOBAR! */ 10518f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10538f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 10548f9e45fea288542b24a6bda01269c6fc184d991at "Cookie timer expired, but no cookie"); 10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_4; 10568f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); 10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Cookie timer expires in wrong state?"); 10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(&stcb->asoc)); 10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 10638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok we found the cookie, threshold management next */ 10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, cookie->whoTo, 10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.max_init_times)) { 10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assoc is over */ 10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 10728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 10748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleared theshold management now lets backoff the address & select 10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an alternate 10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.dropped_special_cnt = 0; 10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0, 0); 10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, cookie->whoTo, 0); 10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt != cookie->whoTo) { 10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(cookie->whoTo); 10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->whoTo = alt; 10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now mark the retran info */ 10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie->sent != SCTP_DATAGRAM_RESEND) { 10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->sent = SCTP_DATAGRAM_RESEND; 10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now call the output routine to kick out the cookie again, Note we 10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * don't mark any chunks for retran so that FR will need to kick in 10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to move these (or a send timer). 10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *strrst = NULL, *chk = NULL; 11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.stream_reset_outstanding == 0) { 11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the existing STRRESET, we use the seq number we sent out on */ 11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_find_stream_reset(stcb, stcb->asoc.str_reset_seq_out, &strrst); 11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (strrst == NULL) { 11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* do threshold management */ 11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, strrst->whoTo, 11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.max_send_times)) { 11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assoc is over */ 11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleared theshold management now lets backoff the address & select 11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an alternate 11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0, 0); 11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, strrst->whoTo, 0); 11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(strrst->whoTo); 11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strrst->whoTo = alt; 11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* See if a ECN Echo is also stranded */ 11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->whoTo == net) && 11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent != SCTP_DATAGRAM_RESEND) { 11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = alt; 11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_REACHABLE)) { 11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the address went un-reachable, we need to move to 11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * alternates for ALL chk's in queue 11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_chunks_from_net(stcb, net); 11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* mark the retran info */ 11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (strrst->sent != SCTP_DATAGRAM_RESEND) 11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strrst->sent = SCTP_DATAGRAM_RESEND; 11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* restart the timer */ 11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, inp, stcb, strrst->whoTo); 11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *asconf, *chk; 11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is this a first send, or a retransmission? */ 11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) { 11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* compose a new ASCONF chunk and send it */ 11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Retransmission of the existing ASCONF is needed 11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the existing ASCONF */ 11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf = TAILQ_FIRST(&stcb->asoc.asconf_send_queue); 11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf == NULL) { 11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* do threshold management */ 11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, asconf->whoTo, 11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.max_send_times)) { 11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assoc is over */ 11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf->snd_count > stcb->asoc.max_send_times) { 11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Something is rotten: our peer is not responding to 11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONFs but apparently is to other chunks. i.e. it 11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is not properly handling the chunk type upper bits. 11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Mark this peer as ASCONF incapable and cleanup. 11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_TIMER1, "asconf_timer: Peer has not responded to our repeated ASCONFs\n"); 11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_cleanup(stcb, net); 11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 11968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleared threshold management, so now backoff the net and 11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * select an alternate 12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0, 0); 12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, asconf->whoTo, 0); 12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf->whoTo != alt) { 12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(asconf->whoTo); 12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf->whoTo = alt; 12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* See if an ECN Echo is also stranded */ 12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->whoTo == net) && 12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.chunk_id.id == SCTP_ECN_ECHO)) { 12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = alt; 12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent != SCTP_DATAGRAM_RESEND) { 12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.asconf_send_queue, sctp_next) { 12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->whoTo != alt) { 12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = alt; 12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf->sent != SCTP_DATAGRAM_RESEND && chk->sent != SCTP_DATAGRAM_UNSENT) 12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_REACHABLE)) { 12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the address went un-reachable, we need to move 12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to the alternate for ALL chunks in queue 12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_chunks_from_net(stcb, net); 12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* mark the retran info */ 12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf->sent != SCTP_DATAGRAM_RESEND) 12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf->sent = SCTP_DATAGRAM_RESEND; 12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* send another ASCONF if any and we can do */ 12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, alt, SCTP_ADDR_NOT_LOCKED); 12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Mobility adaptation */ 12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 12530ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sctp_nets *net SCTP_UNUSED) 12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.deleted_primary == NULL) { 12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n"); 12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: finished to keep deleted primary "); 12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.deleted_primary); 12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary = NULL; 12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For the shutdown and shutdown-ack, we do not keep one around on the 12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * control queue. This means we must generate a new one and call the general 12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chunk output routine, AFTER having done threshold management. 12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * It is assumed that net is non-NULL. 12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first threshold managment */ 12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assoc is over */ 12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* second select an alternative */ 12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, net, 0); 12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* third generate a shutdown into the queue for out net */ 12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown(stcb, alt); 12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fourth restart timer */ 12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt); 12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first threshold managment */ 13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assoc is over */ 13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* second select an alternative */ 13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, net, 0); 13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* third generate a shutdown into the queue for out net */ 13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown_ack(stcb, alt); 13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fourth restart timer */ 13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt); 13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, 13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb) 13238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp; 13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int i, chks_in_queue = 0; 13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int being_filled = 0; 13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This function is ONLY called when the send/sent queues are empty. 13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) || (inp == NULL)) 13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sent_queue_retran_cnt) { 13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Hmm, sent_queue_retran_cnt is non-zero %d\n", 13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sent_queue_retran_cnt); 13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sent_queue_retran_cnt = 0; 13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { 13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No stream scheduler information, initialize scheduler */ 13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 0); 13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { 13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* yep, we lost a stream or two */ 13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Found additional streams NOT managed by scheduler, corrected\n"); 13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no streams lost */ 13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_output_queue_size = 0; 13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Check to see if some data queued, if so report it */ 13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { 13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(sp, &stcb->asoc.strmout[i].outqueue, next) { 13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->msg_is_complete) 13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen being_filled++; 13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chks_in_queue++; 13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chks_in_queue != stcb->asoc.stream_queue_cnt) { 13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n", 13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.stream_queue_cnt, chks_in_queue); 13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chks_in_queue) { 13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* call the output queue function */ 13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) && 13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Probably should go in and make it go back through 13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and add fragments allowed 13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (being_filled == 0) { 13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Still nothing moved %d chunks are stuck\n", 13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chks_in_queue); 13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Found no chunks on any queue tot:%lu\n", 13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (u_long)stcb->asoc.total_output_queue_size); 13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_output_queue_size = 0; 13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t net_was_pf; 13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1390b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (net->dest_state & SCTP_ADDR_PF) { 1391b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net_was_pf = 1; 1392b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } else { 1393b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net_was_pf = 0; 1394b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 1395b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (net->hb_responded == 0) { 1396b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (net->ro._s_addr) { 1397b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen /* Invalidate the src address if we did not get 1398b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen * a response last time. 1399b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen */ 1400b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen sctp_free_ifa(net->ro._s_addr); 1401b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net->ro._s_addr = NULL; 1402b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net->src_addr_selected = 0; 14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1404b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen sctp_backoff_on_timeout(stcb, net, 1, 0, 0); 1405b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) { 1406b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen /* Assoc is over */ 1407b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (1); 14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1410b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen /* Zero PBA, if it needs it */ 1411b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (net->partial_bytes_acked) { 1412b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net->partial_bytes_acked = 0; 1413b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.total_output_queue_size > 0) && 14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (TAILQ_EMPTY(&stcb->asoc.send_queue)) && 14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_stream_queues_for_size(inp, stcb); 14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_NOHB) && 14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !((net_was_pf == 0) && (net->dest_state & SCTP_ADDR_PF))) { 14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* when move to PF during threshold mangement, a HB has been 14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen queued in that routine */ 142345f112c39d02f84188c816dcf86ad9e3c7532376tuexen uint32_t ms_gone_by; 142445f112c39d02f84188c816dcf86ad9e3c7532376tuexen 142545f112c39d02f84188c816dcf86ad9e3c7532376tuexen if ((net->last_sent_time.tv_sec > 0) || 142645f112c39d02f84188c816dcf86ad9e3c7532376tuexen (net->last_sent_time.tv_usec > 0)) { 142745f112c39d02f84188c816dcf86ad9e3c7532376tuexen#ifdef __FreeBSD__ 142845f112c39d02f84188c816dcf86ad9e3c7532376tuexen struct timeval diff; 1429000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 143045f112c39d02f84188c816dcf86ad9e3c7532376tuexen SCTP_GETTIME_TIMEVAL(&diff); 143145f112c39d02f84188c816dcf86ad9e3c7532376tuexen timevalsub(&diff, &net->last_sent_time); 143245f112c39d02f84188c816dcf86ad9e3c7532376tuexen#else 143345f112c39d02f84188c816dcf86ad9e3c7532376tuexen struct timeval diff, now; 143445f112c39d02f84188c816dcf86ad9e3c7532376tuexen 143545f112c39d02f84188c816dcf86ad9e3c7532376tuexen SCTP_GETTIME_TIMEVAL(&now); 143645f112c39d02f84188c816dcf86ad9e3c7532376tuexen timersub(&now, &net->last_sent_time, &diff); 143745f112c39d02f84188c816dcf86ad9e3c7532376tuexen#endif 143845f112c39d02f84188c816dcf86ad9e3c7532376tuexen ms_gone_by = (uint32_t)(diff.tv_sec * 1000) + 143945f112c39d02f84188c816dcf86ad9e3c7532376tuexen (uint32_t)(diff.tv_usec / 1000); 144045f112c39d02f84188c816dcf86ad9e3c7532376tuexen } else { 144145f112c39d02f84188c816dcf86ad9e3c7532376tuexen ms_gone_by = 0xffffffff; 144245f112c39d02f84188c816dcf86ad9e3c7532376tuexen } 1443ca66412c3b42453d5614aca62e15e7f371b42075tuexen if ((ms_gone_by >= net->heart_beat_delay) || 1444ca66412c3b42453d5614aca62e15e7f371b42075tuexen (net->dest_state & SCTP_ADDR_PF)) { 144545f112c39d02f84188c816dcf86ad9e3c7532376tuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 144645f112c39d02f84188c816dcf86ad9e3c7532376tuexen } 14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pathmtu_timer(struct sctp_inpcb *inp, 14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, 14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t next_mtu, mtu; 14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14580ac02f34d6041cd0018437596a5a9a94685e6919tuexen next_mtu = sctp_get_next_mtu(net->mtu); 14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((next_mtu > net->mtu) && (net->port == 0)) { 14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net->src_addr_selected == 0) || 14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->ro._s_addr == NULL) || 14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net->ro._s_addr != NULL) && (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) { 14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = NULL; 14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 0; 14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (net->ro._s_addr == NULL) { 14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE) 14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._l_addr.sa.sa_family == AF_INET6) { 14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* KAME hack: embed scopeid */ 1473c2ae94ce88da509bd10c652de26407ac5b2ee97ctuexen#if defined(__APPLE__) 14741ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) 14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)in6_embedscope(&sin6->sin6_addr, sin6, NULL, NULL); 14761ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else 14771ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen (void)in6_embedscope(&sin6->sin6_addr, sin6, NULL, NULL, NULL); 14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(SCTP_KAME) 14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); 14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 1482e2828360ea9cf8951730d46f5c14626c9425cb30t (void)in6_embedscope(&sin6->sin6_addr, sin6); 14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = sctp_source_address_selection(inp, 14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_route_t *)&net->ro, 14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net, 0, stcb->asoc.vrf_id); 14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET6) && defined(SCTP_EMBEDDED_V6_SCOPE) 14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._l_addr.sa.sa_family == AF_INET6) { 14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME 14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sa6_recoverscope(sin6); 14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)in6_recoverscope(sin6, &sin6->sin6_addr, NULL); 14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */ 14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* INET6 */ 15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._s_addr) 15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 1; 15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._s_addr) { 15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt); 150748830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->port) { 15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mtu -= sizeof(struct udphdr); 15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15116c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mtu > next_mtu) { 15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->mtu = next_mtu; 15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* restart the timer */ 15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); 15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_autoclose_timer(struct sctp_inpcb *inp, 15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, 15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval tn, *tim_touse; 15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ticks_gone_by; 15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&tn); 15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_autoclose_ticks && 15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Auto close is on */ 15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pick the time to use */ 15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->time_last_rcvd.tv_sec > 15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->time_last_sent.tv_sec) { 15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tim_touse = &asoc->time_last_rcvd; 15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tim_touse = &asoc->time_last_sent; 15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now has long enough transpired to autoclose? */ 15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ticks_gone_by = SEC_TO_TICKS(tn.tv_sec - tim_touse->tv_sec); 15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ticks_gone_by > 0) && 15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) { 15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * autoclose time has hit, call the output routine, 15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * which should do nothing just to be SURE we don't 15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have hanging data. We can then safely check the 15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queues and know that we are clear to send 15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * shutdown 15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Are we clean? */ 15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->send_queue) && 15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&asoc->sent_queue)) { 15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * there is nothing queued to send, so I'm 15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * done... 15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* only send SHUTDOWN 1st time thru */ 15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netp; 15647988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); 15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 15717988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_stop_timers_for_shutdown(stcb); 15727988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.alternate) { 15737988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = stcb->asoc.alternate; 15747988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } else { 15757988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = stcb->asoc.primary_destination; 15767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } 15777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_send_shutdown(stcb, netp); 15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, 15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, 15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp); 15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, 15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp); 15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * No auto close at this time, reset t-o to check 15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * later 15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int tmp; 15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fool the timer startup to use the time left */ 15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tmp = asoc->sctp_autoclose_ticks; 15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sctp_autoclose_ticks -= ticks_gone_by; 15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net); 15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* restore the real tick value */ 15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sctp_autoclose_ticks = tmp; 16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1604