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> 35a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 264838 2014-04-23 21:20:55Z tuexen $"); 368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h> 398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h> 408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h> 418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h> 428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h> 438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h> 448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h> 458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_input.h> 468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h> 478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h> 488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h> 498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTES: On the outbound side of things I need to check the sack timer to 538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * see if I should generate a sack into the chunk queue (if I have data to 548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send that is and will be sending it .. for bundling. 558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The callback in sctp_usrreq.c will get called when the socket is read from. 578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This will cause sctp_service_queues() to get called on the top entry in 588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the list. 598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc) 638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->my_rwnd = sctp_calc_rwnd(stcb, asoc); 658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Calculate what the rwnd would be */ 688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t 698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc) 708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 71b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen uint32_t calc = 0; 728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is really set wrong with respect to a 1-2-m socket. Since 758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sb_cc is the count that everyone as put up. When we re-write 768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_soreceive then we will fix this so that ONLY this 778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * associations data is taken into account. 788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket == NULL) 808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (calc); 818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sb_cc == 0 && 838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue == 0 && 848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams == 0) { 858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Full rwnd granted */ 868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), SCTP_MINIMAL_RWND); 878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (calc); 888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get actual space */ 908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen calc = (uint32_t) sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv); 918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * take out what has NOT been put on socket queue and we yet hold 948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for putting up. 958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen calc = sctp_sbspace_sub(calc, (uint32_t)(asoc->size_on_reasm_queue + 978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_on_reasm_queue * MSIZE)); 988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen calc = sctp_sbspace_sub(calc, (uint32_t)(asoc->size_on_all_streams + 998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_on_all_streams * MSIZE)); 1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (calc == 0) { 1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* out of space */ 1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (calc); 1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* what is the overhead of all these rwnd's */ 1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen calc = sctp_sbspace_sub(calc, stcb->asoc.my_rwnd_control_len); 1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If the window gets too small due to ctrl-stuff, reduce it 1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to 1, even it is 0. SWS engaged 1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (calc < stcb->asoc.my_rwnd_control_len) { 1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen calc = 1; 1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (calc); 1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Build out our readq entry based on the incoming packet. 1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_queued_to_read * 1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_build_readq_entry(struct sctp_tcb *stcb, 1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, 1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsn, uint32_t ppid, 1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t context, uint16_t stream_no, 1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t stream_seq, uint8_t flags, 1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *dm) 1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *read_queue_e = NULL; 1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_alloc_a_readq(stcb, read_queue_e); 1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (read_queue_e == NULL) { 1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto failed_build; 1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_stream = stream_no; 1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_ssn = stream_seq; 1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_flags = (flags << 8); 1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_ppid = ppid; 1400ac02f34d6041cd0018437596a5a9a94685e6919tuexen read_queue_e->sinfo_context = context; 1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_timetolive = 0; 1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_tsn = tsn; 1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_cumtsn = tsn; 1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_assoc_id = sctp_get_associd(stcb); 1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->whoFrom = net; 1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->length = 0; 1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&net->ref_count, 1); 1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->data = dm; 1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->spec_flags = 0; 1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->tail_mbuf = NULL; 1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->aux_data = NULL; 1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->stcb = stcb; 1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->port_from = stcb->rport; 1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->do_not_ref_stcb = 0; 1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->end_added = 0; 1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->some_taken = 0; 1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->pdapi_aborted = 0; 1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfailed_build: 1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (read_queue_e); 1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Build out our readq entry based on the incoming packet. 1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_queued_to_read * 1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_build_readq_entry_chk(struct sctp_tcb *stcb, 1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk) 1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *read_queue_e = NULL; 1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_alloc_a_readq(stcb, read_queue_e); 1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (read_queue_e == NULL) { 1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto failed_build; 1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_stream = chk->rec.data.stream_number; 1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_ssn = chk->rec.data.stream_seq; 1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_flags = (chk->rec.data.rcv_flags << 8); 1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_ppid = chk->rec.data.payloadtype; 1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_context = stcb->asoc.context; 1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_timetolive = 0; 1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_tsn = chk->rec.data.TSN_seq; 1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_cumtsn = chk->rec.data.TSN_seq; 1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->sinfo_assoc_id = sctp_get_associd(stcb); 1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->whoFrom = chk->whoTo; 1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->aux_data = NULL; 1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->length = 0; 1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&chk->whoTo->ref_count, 1); 1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->data = chk->data; 1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->tail_mbuf = NULL; 1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->stcb = stcb; 1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->port_from = stcb->rport; 1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->spec_flags = 0; 1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->do_not_ref_stcb = 0; 1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->end_added = 0; 1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->some_taken = 0; 1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen read_queue_e->pdapi_aborted = 0; 1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfailed_build: 1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (read_queue_e); 2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct mbuf * 2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) 2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_extrcvinfo *seinfo; 2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_sndrcvinfo *outinfo; 2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_rcvinfo *rcvinfo; 2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nxtinfo *nxtinfo; 21009c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows) 21109c18a940b9e5520f869d4f187988ab748484b25t WSACMSGHDR *cmh; 21209c18a940b9e5520f869d4f187988ab748484b25t#else 2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct cmsghdr *cmh; 21409c18a940b9e5520f869d4f187988ab748484b25t#endif 2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *ret; 2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int len; 2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int use_extended; 2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int provide_nxt; 2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) && 2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && 2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) { 2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* user does not want any ancillary data */ 2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len = 0; 2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) { 2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len += CMSG_SPACE(sizeof(struct sctp_rcvinfo)); 2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seinfo = (struct sctp_extrcvinfo *)sinfo; 2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) && 2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) { 2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen provide_nxt = 1; 2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len += CMSG_SPACE(sizeof(struct sctp_rcvinfo)); 2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen provide_nxt = 0; 2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) { 2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) { 2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen use_extended = 1; 2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len += CMSG_SPACE(sizeof(struct sctp_extrcvinfo)); 2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen use_extended = 0; 2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); 2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen use_extended = 0; 2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25168beeca578347438d9c434680197647ed551935ft ret = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); 2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ret == NULL) { 2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No space */ 2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ret); 2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(ret) = 0; 2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We need a CMSG header followed by the struct */ 25909c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows) 26009c18a940b9e5520f869d4f187988ab748484b25t cmh = mtod(ret, WSACMSGHDR *); 26109c18a940b9e5520f869d4f187988ab748484b25t#else 2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh = mtod(ret, struct cmsghdr *); 26309c18a940b9e5520f869d4f187988ab748484b25t#endif 2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) { 2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_level = IPPROTO_SCTP; 2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo)); 2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_type = SCTP_RCVINFO; 2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmh); 2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_sid = sinfo->sinfo_stream; 2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_ssn = sinfo->sinfo_ssn; 2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_flags = sinfo->sinfo_flags; 2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_ppid = sinfo->sinfo_ppid; 2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_tsn = sinfo->sinfo_tsn; 2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_cumtsn = sinfo->sinfo_cumtsn; 2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_context = sinfo->sinfo_context; 2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rcvinfo->rcv_assoc_id = sinfo->sinfo_assoc_id; 27709c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows) 27809c18a940b9e5520f869d4f187988ab748484b25t cmh = (WSACMSGHDR *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_rcvinfo))); 27909c18a940b9e5520f869d4f187988ab748484b25t#else 2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_rcvinfo))); 28109c18a940b9e5520f869d4f187988ab748484b25t#endif 2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_rcvinfo)); 2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (provide_nxt) { 2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_level = IPPROTO_SCTP; 2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo)); 2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_type = SCTP_NXTINFO; 2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh); 2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_sid = seinfo->sreinfo_next_stream; 2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_flags = 0; 2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) { 2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_flags |= SCTP_UNORDERED; 2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) { 2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_flags |= SCTP_NOTIFICATION; 2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) { 2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_flags |= SCTP_COMPLETE; 2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid; 3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_length = seinfo->sreinfo_next_length; 3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid; 30309c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows) 30409c18a940b9e5520f869d4f187988ab748484b25t cmh = (WSACMSGHDR *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo))); 30509c18a940b9e5520f869d4f187988ab748484b25t#else 3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo))); 30709c18a940b9e5520f869d4f187988ab748484b25t#endif 3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_nxtinfo)); 3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) { 3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_level = IPPROTO_SCTP; 3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh); 3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (use_extended) { 3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_extrcvinfo)); 3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_type = SCTP_EXTRCV; 3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(outinfo, sinfo, sizeof(struct sctp_extrcvinfo)); 3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_extrcvinfo)); 3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmh->cmsg_type = SCTP_SNDRCV; 3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *outinfo = *sinfo; 3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); 3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ret); 3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn) 3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t gap, i, cumackp1; 3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int fnd = 0; 3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cumackp1 = asoc->cumulative_tsn + 1; 3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(cumackp1, tsn)) { 3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this tsn is behind the cum ack and thus we don't 3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * need to worry about it being moved from one to the other. 3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); 3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 34747a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("gap:%x tsn:%x\n", gap, tsn); 3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_print_mapping_array(asoc); 3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Things are really messed up now!!"); 3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { 3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = tsn; 3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn == asoc->highest_tsn_inside_map) { 3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We must back down to see what the new highest is */ 3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = tsn - 1; SCTP_TSN_GE(i, asoc->mapping_array_base_tsn); i--) { 3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); 3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = i; 3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!fnd) { 3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1; 3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We are delivering currently from the reassembly queue. We must continue to 3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deliver until we either: 1) run out of space. 2) run out of sequential 3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * TSN's 3) hit the SCTP_DATA_LAST_FRAG flag. 3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) 3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t nxt_todel; 3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t stream_no; 3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int end = 0; 3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cntDel; 3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *control, *ctl, *nctl; 3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) 3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cntDel = stream_no = 0; 3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) || 3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* socket above is long gone or going.. */ 3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen abandon: 3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 0; 4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue -= chk->send_size; 4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_reasm_queue); 4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Lose the data pointer, since its in the socket 4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * buffer 4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now free the address and data */ 4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.TSN_seq != (asoc->tsn_last_delivered + 1)) { 4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't deliver more :< */ 4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stream_no = chk->rec.data.stream_number; 4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = asoc->strmin[stream_no].last_sequence_delivered + 1; 4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (nxt_todel != chk->rec.data.stream_seq && 4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) { 4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Not the next sequence to deliver in its stream OR 4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * unordered 4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) { 4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control = sctp_build_readq_entry_chk(stcb, chk); 4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control == NULL) { 4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* out of memory? */ 4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save it off for our future deliveries */ 4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi = control; 4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) 4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen end = 1; 4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen end = 0; 4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); 4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, 4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, control, &stcb->sctp_socket->so_rcv, end, 4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cntDel++; 4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) 4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen end = 1; 4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen end = 0; 4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); 4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_append_to_readq(stcb->sctp_ep, stcb, 4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi, 4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data, end, chk->rec.data.TSN_seq, 4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv)) { 4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * something is very wrong, either 4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * control_pdapi is NULL, or the tail_mbuf 4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is corrupt, or there is a EOM already on 4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the mbuf chain. 4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto abandon; 4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) { 4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("This should not happen control_pdapi NULL?"); 4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if we did not panic, it was a EOM */ 4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Bad chunking ??"); 4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) { 4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("This should not happen control_pdapi NULL?\n"); 4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Bad chunking ??\n"); 4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Dumping re-assembly queue this will probably hose the association\n"); 483000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 484000a5bac556b28e74e4e98c540f66b1743e9312dtuexen#endif 4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto abandon; 4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cntDel++; 4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pull it we did it */ 4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 0; 4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) { 4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[stream_no].last_sequence_delivered++; 4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0) { 4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs); 4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) { 5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * turn the flag back on since we just delivered 5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * yet another one. 5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 1; 5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_of_pdapi_last_delivered = chk->rec.data.TSN_seq; 5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_flags_delivered = chk->rec.data.rcv_flags; 5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_strm_seq_delivered = chk->rec.data.stream_seq; 5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_strm_no_delivered = chk->rec.data.stream_number; 5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = chk->rec.data.TSN_seq; 5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue -= chk->send_size; 5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_reasm_queue); 5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free up the chk */ 5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress == 0) { 5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now lets see if we can deliver the next one on 5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the stream 5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_in *strm; 5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm = &asoc->strmin[stream_no]; 5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = strm->last_sequence_delivered + 1; 5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &strm->inqueue, next, nctl) { 5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Deliver more if we can. */ 5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (nxt_todel == ctl->sinfo_ssn) { 5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&strm->inqueue, ctl, next); 5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams -= ctl->length; 5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm->last_sequence_delivered++; 5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); 5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl, 5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv, 1, 5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = strm->last_sequence_delivered + 1; 5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Queue the chunk either right into the socket buffer if it is the next one 5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to go OR put it in the correct place in the delivery queue. If we do 5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * append to the so_buf, keep doing so until we are out of order. One big 5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * question still remains, what to do when the socket buffer is FULL?? 5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, 5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *control, int *abort_flag) 5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX-ME maybe? What happens when the ssn wraps? If we are getting 5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all the data in one stream this could happen quite rapidly. One 5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * could use the TSN to keep track of things, but this scheme breaks 5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * down in the other type of stream useage that could occur. Send a 5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * single msg to stream 0, send 4Billion messages to stream 1, now 5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send a message to stream 0. You have a situation where the TSN 5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * has wrapped but not in the stream. Is this worth worrying about 5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * or should we just change our queue sort at the bottom to be by 5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * TSN. 5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Could it also be legal for a peer to send ssn 1 with TSN 2 and ssn 2 5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with TSN 1? If the peer is doing some sort of funky TSN/SSN 5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assignment this could happen... and I don't see how this would be 5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a violation. So for now I am undecided an will leave the sort by 5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SSN alone. Maybe a hybred approach is the answer 5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_in *strm; 5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *at; 5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int queue_needed; 5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t nxt_todel; 5828f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 5838f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 584000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen queue_needed = 1; 5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams += control->length; 5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->cnt_on_all_streams); 5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm = &asoc->strmin[control->sinfo_stream]; 5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = strm->last_sequence_delivered + 1; 5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD); 5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, 5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "queue to stream called for ssn:%u lastdel:%u nxt:%u\n", 5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) control->sinfo_stream, 5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) strm->last_sequence_delivered, 5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) nxt_todel); 5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) { 5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* The incoming sseq is behind where we last delivered? */ 6008f9e45fea288542b24a6bda01269c6fc184d991at SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n", 6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->sinfo_ssn, strm->last_sequence_delivered); 6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen protocol_error: 6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * throw it in the stream so it gets cleaned up in 6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association destruction 6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&strm->inqueue, control, next); 6088f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 6098f9e45fea288542b24a6bda01269c6fc184d991at strm->last_sequence_delivered, control->sinfo_tsn, 6108f9e45fea288542b24a6bda01269c6fc184d991at control->sinfo_stream, control->sinfo_ssn); 6118f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_1; 6138f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (nxt_todel == control->sinfo_ssn) { 6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can be delivered right away? */ 6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_IMMED_DEL); 6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* EY it wont be queued if it could be delivered directly*/ 6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen queue_needed = 0; 6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams -= control->length; 6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm->last_sequence_delivered++; 628000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, control->sinfo_tsn); 6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control, 6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv, 1, 6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) { 6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* all delivered */ 6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = strm->last_sequence_delivered + 1; 6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (nxt_todel == control->sinfo_ssn) { 6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&strm->inqueue, control, next); 6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams -= control->length; 6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm->last_sequence_delivered++; 6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We ignore the return of deliver_data here 6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we always can hold the chunk on the 6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * d-queue. And we have a finite number that 6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * can be delivered from the strq. 6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del(control, NULL, 6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STR_LOG_FROM_IMMED_DEL); 6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, control->sinfo_tsn); 6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control, 6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv, 1, 6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_READ_LOCK_NOT_HELD, 6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (queue_needed) { 6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok, we did not deliver this guy, find the correct place 6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to put it on the queue. 6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) { 6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto protocol_error; 6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&strm->inqueue)) { 6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Empty queue */ 6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INSERT_HD); 6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&strm->inqueue, control, next); 6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(at, &strm->inqueue, next) { 6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SSN_GT(at->sinfo_ssn, control->sinfo_ssn)) { 6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one in queue is bigger than the 6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new one, insert before this one 6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del(control, at, 6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STR_LOG_FROM_INSERT_MD); 6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_BEFORE(at, control, next); 6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (at->sinfo_ssn == control->sinfo_ssn) { 6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Gak, He sent me a duplicate str 6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * seq number 6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * foo bar, I guess I will just free 6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this new guy, should we abort 6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * too? FIX ME MAYBE? Or it COULD be 6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that the SSN's have wrapped. 7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Maybe I should compare to TSN 7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * somehow... sigh for now just blow 7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * away the chunk! 7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control->data) 7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(control->data); 7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->data = NULL; 7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams -= control->length; 7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control->whoFrom) { 7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(control->whoFrom); 7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->whoFrom = NULL; 7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_readq(stcb, control); 7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_NEXT(at, next) == NULL) { 7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We are at the end, insert 7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it after this one 7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del(control, at, 7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STR_LOG_FROM_INSERT_TL); 7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_AFTER(&strm->inqueue, 7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen at, control, next); 7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Returns two things: You get the total size of the deliverable parts of the 7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first fragmented message on the reassembly queue. And you get a 1 back if 7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all of the message is ready or a 0 back if the message is still incomplete 7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_all_msg_on_reasm(struct sctp_association *asoc, uint32_t *t_size) 7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsn; 7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *t_size = 0; 7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = TAILQ_FIRST(&asoc->reasmqueue); 7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk == NULL) { 7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing on the queue */ 7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0) { 7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Not a first on the queue */ 7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn = chk->rec.data.TSN_seq; 7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &asoc->reasmqueue, sctp_next) { 7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn != chk->rec.data.TSN_seq) { 7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *t_size += chk->send_size; 7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn++; 7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc) 7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t nxt_todel; 7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsize, pd_point; 7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen doit_again: 7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = TAILQ_FIRST(&asoc->reasmqueue); 7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk == NULL) { 7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Huh? */ 7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue = 0; 7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_on_reasm_queue = 0; 7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress == 0) { 7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = 7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered + 1; 7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) && 7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (nxt_todel == chk->rec.data.stream_seq || 7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED))) { 7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Yep the first one is here and its ok to deliver 7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * but should we? 7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 797cdc78af866f2b29865707afee7ea65e1706b4ff8t pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, 7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->partial_delivery_point); 7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pd_point = stcb->sctp_ep->partial_delivery_point; 8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) { 8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Yes, we setup to start reception, by 8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * backing down the TSN just in case we 8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * can't deliver. If we 8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 1; 8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = 8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.TSN_seq - 1; 8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_of_pdapi = 8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_number; 8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->ssn_of_pdapi = chk->rec.data.stream_seq; 8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pdapi_ppid = chk->rec.data.payloadtype; 8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragment_flags = chk->rec.data.rcv_flags; 8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_service_reassembly(stcb, asoc); 8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Service re-assembly will deliver stream data queued 8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * at the end of fragmented delivery.. but it wont know 8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to go back and call itself again... we do that here 8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with the got doit_again 8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_service_reassembly(stcb, asoc); 8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress == 0) { 8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* finished our Fragmented delivery, could be 8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * more waiting? 8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto doit_again; 8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Dump onto the re-assembly queue, in its proper place. After dumping on the 8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue, see if anthing can be delivered. If so pull it off (or as much as 8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we can. If we run out of space then we must dump what we can and set the 8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * appropriate flag to say we queued what we could. 8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, 8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, int *abort_flag) 8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 8458f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 8468f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 847b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen uint32_t cum_ackp1, prev_tsn, post_tsn; 8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *at, *prev, *next; 8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev = next = NULL; 8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ackp1 = asoc->tsn_last_delivered + 1; 8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->reasmqueue)) { 8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This is the first one on the queue */ 8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&asoc->reasmqueue, chk, sctp_next); 8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we do not check for delivery of anything when only one 8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * fragment is here 8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue = chk->send_size; 8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->cnt_on_reasm_queue); 8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.TSN_seq == cum_ackp1) { 8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress == 0 && 8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) != 8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_FIRST_FRAG) { 8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * An empty queue, no delivery inprogress, 8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we hit the next one and it does NOT have 8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a FIRST fragment mark. 8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not first, no fragmented delivery in progress\n"); 8718f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 8728f9e45fea288542b24a6bda01269c6fc184d991at "Expected B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 8738f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 8748f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 8758f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 8768f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_2; 8788f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->fragmented_delivery_inprogress && 8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) { 8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We are doing a partial delivery and the 8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NEXT chunk MUST be either the LAST or 8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * MIDDLE fragment NOT a FIRST 8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS a first and fragmented delivery in progress\n"); 8888f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 8898f9e45fea288542b24a6bda01269c6fc184d991at "Didn't expect B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 8908f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 8918f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 8928f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 8938f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_3; 8958f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->fragmented_delivery_inprogress) { 8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we are ok with a MIDDLE or LAST 9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * piece 9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.stream_number != 9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_of_pdapi) { 9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Got to be the right STR No */ 9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream number %d vs %d\n", 9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_number, 9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_of_pdapi); 9088f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 9098f9e45fea288542b24a6bda01269c6fc184d991at "Expected SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 9108f9e45fea288542b24a6bda01269c6fc184d991at asoc->str_of_pdapi, 9118f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 9128f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 9138f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 9148f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_4; 9168f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) != 9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_UNORDERED && 9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq != asoc->ssn_of_pdapi) { 9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Got to be the right STR Seq */ 9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n", 9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq, 9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->ssn_of_pdapi); 9258f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 9268f9e45fea288542b24a6bda01269c6fc184d991at "Expected SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 9278f9e45fea288542b24a6bda01269c6fc184d991at asoc->ssn_of_pdapi, 9288f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 9298f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 9308f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 9318f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_5; 9338f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Find its place */ 9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) { 9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(at->rec.data.TSN_seq, chk->rec.data.TSN_seq)) { 9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one in queue is bigger than the new one, insert 9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * before this one 9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* A check */ 9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue += chk->send_size; 9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->cnt_on_reasm_queue); 9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next = at; 9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_BEFORE(at, chk, sctp_next); 9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (at->rec.data.TSN_seq == chk->rec.data.TSN_seq) { 9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Gak, He sent me a duplicate str seq number */ 9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * foo bar, I guess I will just free this new guy, 9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should we abort too? FIX ME MAYBE? Or it COULD be 9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that the SSN's have wrapped. Maybe I should 9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * compare to TSN somehow... sigh for now just blow 9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * away the chunk! 9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev = at; 9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_NEXT(at, sctp_next) == NULL) { 9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We are at the end, insert it after this 9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one 9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check it first */ 9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue += chk->send_size; 9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->cnt_on_reasm_queue); 9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_AFTER(&asoc->reasmqueue, at, chk, sctp_next); 9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now the audits */ 9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (prev) { 9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev_tsn = chk->rec.data.TSN_seq - 1; 9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (prev_tsn == prev->rec.data.TSN_seq) { 9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok the one I am dropping onto the end is the 9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NEXT. A bit of valdiation here. 9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_FIRST_FRAG || 9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_MIDDLE_FRAG) { 9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Insert chk MUST be a MIDDLE or LAST 9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * fragment 9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_FIRST_FRAG) { 10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - It can be a midlle or last but not a first\n"); 10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it's a FIRST!\n"); 10038f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 10048f9e45fea288542b24a6bda01269c6fc184d991at "Can't handle B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 10058f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 10068f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 10078f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 10088f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_6; 10108f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.stream_number != 10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev->rec.data.stream_number) { 10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Huh, need the correct STR here, 10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * they must be the same. 10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 102020adfbc28f6151511c1cf170c99a64e98ff6c0eet SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sid:%d not the same as at:%d\n", 102133c1af7ee7b7958f1e60412f26cd07d199cc7531t chk->rec.data.stream_number, 102233c1af7ee7b7958f1e60412f26cd07d199cc7531t prev->rec.data.stream_number); 10238f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 10248f9e45fea288542b24a6bda01269c6fc184d991at "Expect SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 10258f9e45fea288542b24a6bda01269c6fc184d991at prev->rec.data.stream_number, 10268f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 10278f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 10288f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 10298f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7; 10318f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 103533c1af7ee7b7958f1e60412f26cd07d199cc7531t if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != 103633c1af7ee7b7958f1e60412f26cd07d199cc7531t (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { 103733c1af7ee7b7958f1e60412f26cd07d199cc7531t /* 103833c1af7ee7b7958f1e60412f26cd07d199cc7531t * Huh, need the same ordering here, 103933c1af7ee7b7958f1e60412f26cd07d199cc7531t * they must be the same. 104033c1af7ee7b7958f1e60412f26cd07d199cc7531t */ 104133c1af7ee7b7958f1e60412f26cd07d199cc7531t SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, U-bit not constant\n"); 104233c1af7ee7b7958f1e60412f26cd07d199cc7531t snprintf(msg, sizeof(msg), 104333c1af7ee7b7958f1e60412f26cd07d199cc7531t "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d", 104433c1af7ee7b7958f1e60412f26cd07d199cc7531t (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0, 104533c1af7ee7b7958f1e60412f26cd07d199cc7531t chk->rec.data.TSN_seq, 104633c1af7ee7b7958f1e60412f26cd07d199cc7531t (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); 104733c1af7ee7b7958f1e60412f26cd07d199cc7531t op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 104833c1af7ee7b7958f1e60412f26cd07d199cc7531t stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7; 104933c1af7ee7b7958f1e60412f26cd07d199cc7531t sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 105033c1af7ee7b7958f1e60412f26cd07d199cc7531t *abort_flag = 1; 105133c1af7ee7b7958f1e60412f26cd07d199cc7531t return; 105233c1af7ee7b7958f1e60412f26cd07d199cc7531t } 10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 && 10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq != 10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev->rec.data.stream_seq) { 10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Huh, need the correct STR here, 10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * they must be the same. 10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sseq:%d not the same as at:%d\n", 10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq, 10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev->rec.data.stream_seq); 10638f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 10648f9e45fea288542b24a6bda01269c6fc184d991at "Expect SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 10658f9e45fea288542b24a6bda01269c6fc184d991at prev->rec.data.stream_seq, 10668f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 10678f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 10688f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 10698f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_8; 10718f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 10728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_LAST_FRAG) { 10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Insert chk MUST be a FIRST */ 10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) != 10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_FIRST_FRAG) { 10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, evil plot, its not FIRST and it must be!\n"); 10818f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 10828f9e45fea288542b24a6bda01269c6fc184d991at "Expect B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 10838f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 10848f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 10858f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 10868f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_9; 10888f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (next) { 10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen post_tsn = chk->rec.data.TSN_seq + 1; 10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (post_tsn == next->rec.data.TSN_seq) { 10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok the one I am inserting ahead of is my NEXT 11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one. A bit of valdiation here. 11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (next->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) { 11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Insert chk MUST be a last fragment */ 11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) 11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen != SCTP_DATA_LAST_FRAG) { 11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is FIRST, we must be LAST\n"); 11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not a last!\n"); 11088f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 11098f9e45fea288542b24a6bda01269c6fc184d991at "Expect only E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 11108f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 11118f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 11128f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 11138f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_10; 11158f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((next->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_MIDDLE_FRAG || 11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (next->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_LAST_FRAG) { 11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Insert chk CAN be MIDDLE or FIRST NOT 11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LAST 11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) == 11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_LAST_FRAG) { 11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is a MIDDLE/LAST\n"); 11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, new prev chunk is a LAST\n"); 11318f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 11328f9e45fea288542b24a6bda01269c6fc184d991at "Didn't expect E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 11338f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 11348f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 11358f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 11368f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_11; 11388f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.stream_number != 11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next->rec.data.stream_number) { 11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Huh, need the correct STR here, 11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * they must be the same. 11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, ssn:%d not the same as at:%d\n", 11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_number, 11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next->rec.data.stream_number); 11518f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 11528f9e45fea288542b24a6bda01269c6fc184d991at "Required SID %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 11538f9e45fea288542b24a6bda01269c6fc184d991at next->rec.data.stream_number, 11548f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 11558f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 11568f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 11578f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12; 11598f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 116333c1af7ee7b7958f1e60412f26cd07d199cc7531t if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != 116433c1af7ee7b7958f1e60412f26cd07d199cc7531t (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { 116533c1af7ee7b7958f1e60412f26cd07d199cc7531t /* 116633c1af7ee7b7958f1e60412f26cd07d199cc7531t * Huh, need the same ordering here, 116733c1af7ee7b7958f1e60412f26cd07d199cc7531t * they must be the same. 116833c1af7ee7b7958f1e60412f26cd07d199cc7531t */ 116933c1af7ee7b7958f1e60412f26cd07d199cc7531t SCTPDBG(SCTP_DEBUG_INDATA1, "Next check - Gak, Evil plot, U-bit not constant\n"); 117033c1af7ee7b7958f1e60412f26cd07d199cc7531t snprintf(msg, sizeof(msg), 117133c1af7ee7b7958f1e60412f26cd07d199cc7531t "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d", 117233c1af7ee7b7958f1e60412f26cd07d199cc7531t (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0, 117333c1af7ee7b7958f1e60412f26cd07d199cc7531t chk->rec.data.TSN_seq, 117433c1af7ee7b7958f1e60412f26cd07d199cc7531t (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); 117533c1af7ee7b7958f1e60412f26cd07d199cc7531t op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 117633c1af7ee7b7958f1e60412f26cd07d199cc7531t stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12; 117733c1af7ee7b7958f1e60412f26cd07d199cc7531t sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 117833c1af7ee7b7958f1e60412f26cd07d199cc7531t *abort_flag = 1; 117933c1af7ee7b7958f1e60412f26cd07d199cc7531t return; 118033c1af7ee7b7958f1e60412f26cd07d199cc7531t } 11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 && 11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq != 11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next->rec.data.stream_seq) { 11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Huh, need the correct STR here, 11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * they must be the same. 11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, sseq:%d not the same as at:%d\n", 11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq, 11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next->rec.data.stream_seq); 11918f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 11928f9e45fea288542b24a6bda01269c6fc184d991at "Required SSN %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 11938f9e45fea288542b24a6bda01269c6fc184d991at next->rec.data.stream_seq, 11948f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.TSN_seq, 11958f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_number, 11968f9e45fea288542b24a6bda01269c6fc184d991at chk->rec.data.stream_seq); 11978f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_13; 11998f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Do we need to do some delivery? check */ 12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_deliver_reasm_check(stcb, asoc); 12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is an unfortunate routine. It checks to make sure a evil guy is not 12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stuffing us full of bad packet fragments. A broken peer could also do this 12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * but this is doubtful. It is to bad I must worry about evil crackers sigh 12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * :< more cycles. 12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_does_tsn_belong_to_reasm(struct sctp_association *asoc, 12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t TSN_seq) 12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *at; 12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsn_est; 12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) { 12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(TSN_seq, at->rec.data.TSN_seq)) { 12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is it one bigger? */ 12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn_est = at->rec.data.TSN_seq + 1; 12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn_est == TSN_seq) { 12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* yep. It better be a last then */ 12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((at->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) != 12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_LAST_FRAG) { 12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok this guy belongs next to a guy 12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that is NOT last, it should be a 12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * middle/last, not a complete 12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chunk. 12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This guy is ok since its a LAST 12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and the new chunk is a fully 12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * self- contained one. 12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (TSN_seq == at->rec.data.TSN_seq) { 12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Software error since I have a dup? */ 12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok, 'at' is larger than new chunk but does it 12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * need to be right before it. 12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn_est = TSN_seq + 1; 12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn_est == at->rec.data.TSN_seq) { 12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep, It better be a first */ 12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((at->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) != 12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DATA_FIRST_FRAG) { 12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, 12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf **m, int offset, struct sctp_data_chunk *ch, int chk_length, 12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, uint32_t *high_tsn, int *abort_flag, 12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *break_flag, int last_chunk) 12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Process a data chunk */ 12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* struct sctp_tmit_chunk *chk; */ 12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsn, gap; 12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *dmbuf; 12810ac02f34d6041cd0018437596a5a9a94685e6919tuexen int the_len; 12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int need_reasm_check = 0; 12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t strmno, strmseq; 12848f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 12858f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *control; 12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ordered; 12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t protocol_id; 12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t chunk_flags; 12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_list *liste; 12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = NULL; 12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn = ntohl(ch->dp.tsn); 12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunk_flags = ch->ch.chunk_flags; 12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_SACK_IMMEDIATELY) == SCTP_DATA_SACK_IMMEDIATELY) { 12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->send_sack = 1; 12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen protocol_id = ch->dp.protocol_id; 12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ordered = ((chunk_flags & SCTP_DATA_UNORDERED) == 0); 13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_TSN_ENTERS); 13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_CHK(stcb->sctp_ep, stcb, ch->ch.chunk_type, tsn); 13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* It is a duplicate */ 13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvdupdata); 13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) { 13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Record a dup for the next outbound sack */ 13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->dup_tsns[asoc->numduptsns] = tsn; 13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->numduptsns++; 13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->send_sack = 1; 13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Calculate the number of TSN's between the base and this TSN */ 13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); 13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (gap >= (SCTP_MAPPING_ARRAY << 3)) { 13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't hold the bit in the mapping at max array, toss it */ 13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (gap >= (uint32_t) (asoc->mapping_array_size << 3)) { 13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_expand_mapping_array(asoc, gap)) { 13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't expand, drop it */ 13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, *high_tsn)) { 13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *high_tsn = tsn; 13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* See if we have received this one already */ 13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap) || 13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, gap)) { 13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvdupdata); 13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) { 13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Record a dup for the next outbound sack */ 13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->dup_tsns[asoc->numduptsns] = tsn; 13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->numduptsns++; 13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->send_sack = 1; 13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Check to see about the GONE flag, duplicates would cause a sack 13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to be sent up above 13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 13528f9e45fea288542b24a6bda01269c6fc184d991at (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))) { 13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * wait a minute, this guy is gone, there is no longer a 13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * receiver. Send peer an ABORT! 13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13578f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 135847674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now before going further we see if there is room. If NOT then we 13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * MAY let one through only IF this TSN is the one we are waiting 13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for on a partial delivery API. 13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now do the tests */ 13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((asoc->cnt_on_all_streams + 13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_on_reasm_queue + 13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_msg_on_sb) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)) || 13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (((int)asoc->my_rwnd) <= 0)) { 13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * When we have NO room in the rwnd we check to make sure 13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the reader is doing its job... 13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket->so_rcv.sb_cc) { 13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* some to read, wake-up */ 13790612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 1381000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assoc was freed while we were unlocked */ 13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 13950612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now is it in the mapping array of what we have accepted? */ 14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_map) && 14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { 14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Nope not in the valid range dump it */ 14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_set_rwnd(stcb, asoc); 14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->cnt_on_all_streams + 14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_on_reasm_queue + 14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_msg_on_sb) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)) { 14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_datadropchklmt); 14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_datadroprwnd); 14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *break_flag = 1; 14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strmno = ntohs(ch->dp.stream_id); 14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (strmno >= asoc->streamincnt) { 14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *phdr; 14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *mb; 14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2), 142168beeca578347438d9c434680197647ed551935ft 0, M_NOWAIT, 1, MT_DATA); 14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mb != NULL) { 14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add some space up front so prepend will work well */ 14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr)); 14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = mtod(mb, struct sctp_paramhdr *); 14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Error causes are just param's and this one has 14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two back to back phdr, one with the error type 14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and size, the other with the streamid and a rsvd 14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2); 14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM); 14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr->param_length = 14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(sizeof(struct sctp_paramhdr) * 2); 14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr++; 14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We insert the stream in the type field */ 14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr->param_type = ch->dp.stream_id; 14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* And set the length to 0 for the rsvd field */ 14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr->param_length = 0; 14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_op_err(stcb, mb); 14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_badsid); 14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { 14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = tsn; 14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn == (asoc->cumulative_tsn + 1)) { 14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Update cum-ack */ 14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cumulative_tsn = tsn; 14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Before we continue lets validate that we are not being fooled by 14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an evil attacker. We can only have 4k chunks based on our TSN 14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * spread allowed by the mapping array 512 * 8 bits, so there is no 14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * way our stream sequence numbers could have wrapped. We of course 14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * only validate the FIRST fragment so the bit must be set. 14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strmseq = ntohs(ch->dp.stream_sequence); 14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS 14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->tsn_in_at >= SCTP_TSN_LOG_SIZE) { 14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_in_at = 0; 14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_in_wrapped = 1; 14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].tsn = tsn; 14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].strm = strmno; 14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].seq = strmseq; 14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].sz = chk_length; 14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].flgs = chunk_flags; 14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].stcb = (void *)stcb; 14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].in_pos = asoc->tsn_in_at; 14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->in_tsnlog[asoc->tsn_in_at].in_out = 1; 14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_in_at++; 14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_FIRST_FRAG) && 14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (TAILQ_EMPTY(&asoc->resetHead)) && 14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chunk_flags & SCTP_DATA_UNORDERED) == 0 && 14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SSN_GE(asoc->strmin[strmno].last_sequence_delivered, strmseq)) { 14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* The incoming sseq is behind where we last delivered? */ 14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "EVIL/Broken-Dup S-SEQ:%d delivered:%d from peer, Abort!\n", 14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strmseq, asoc->strmin[strmno].last_sequence_delivered); 14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14868f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 14878f9e45fea288542b24a6bda01269c6fc184d991at asoc->strmin[strmno].last_sequence_delivered, 14888f9e45fea288542b24a6bda01269c6fc184d991at tsn, strmno, strmseq); 14898f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_14; 14918f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /************************************ 14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * From here down we may find ch-> invalid 14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so its a good idea NOT to use it. 14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *************************************/ 14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen the_len = (chk_length - sizeof(struct sctp_data_chunk)); 15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (last_chunk == 0) { 15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen dmbuf = SCTP_M_COPYM(*m, 15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (offset + sizeof(struct sctp_data_chunk)), 150468beeca578347438d9c434680197647ed551935ft the_len, M_NOWAIT); 15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBUF_LOGGING 15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *mat; 1508b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen 1509b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (mat = dmbuf; mat; mat = SCTP_BUF_NEXT(mat)) { 15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_mb(mat, SCTP_MBUF_ICOPY); 15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We can steal the last chunk */ 15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int l_len; 15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen dmbuf = *m; 15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* lop off the top part */ 15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_adj(dmbuf, (offset + sizeof(struct sctp_data_chunk))); 15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_NEXT(dmbuf) == NULL) { 15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen l_len = SCTP_BUF_LEN(dmbuf); 15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* need to count up the size hopefully 15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does not hit this to often :-0 15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *lat; 1529b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen 15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen l_len = 0; 1531b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (lat = dmbuf; lat; lat = SCTP_BUF_NEXT(lat)) { 15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen l_len += SCTP_BUF_LEN(lat); 15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (l_len > the_len) { 15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Trim the end round bytes off too */ 15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_adj(dmbuf, -(l_len - the_len)); 15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (dmbuf == NULL) { 15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_nomem); 15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG && 15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress == 0 && 15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&asoc->resetHead) && 15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((ordered == 0) || 15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((uint16_t)(asoc->strmin[strmno].last_sequence_delivered + 1) == strmseq && 15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&asoc->strmin[strmno].inqueue)))) { 15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Candidate for express delivery */ 15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Its not fragmented, No PD-API is up, Nothing in the 15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delivery queue, Its un-ordered OR ordered and the next to 15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deliver AND nothing else is stuck on the stream queue, 15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * And there is room for it in the socket buffer. Lets just 15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stuff it up the buffer.... 15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* It would be nice to avoid this copy if we could :< */ 15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_alloc_a_readq(stcb, control); 15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, 15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen protocol_id, 15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strmno, strmseq, 15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunk_flags, 15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen dmbuf); 15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control == NULL) { 15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto failed_express_del; 15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { 15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = tsn; 15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control, &stcb->sctp_socket->so_rcv, 15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) { 15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* for ordered, bump what we delivered */ 15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[strmno].last_sequence_delivered++; 15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvexpress); 15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del_alt(stcb, tsn, strmseq, strmno, 15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STR_LOG_FROM_EXPRS_DEL); 15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control = NULL; 15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto finish_express_del; 15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfailed_express_del: 15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If we reach here this is a new chunk */ 15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = NULL; 15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control = NULL; 15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Express for fragmented delivery? */ 15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->fragmented_delivery_inprogress) && 15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.control_pdapi) && 15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->str_of_pdapi == strmno) && 15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->ssn_of_pdapi == strmseq) 15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control = stcb->asoc.control_pdapi; 16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) { 16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't be another first? */ 16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto failed_pdapi_express_del; 16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn == (control->sinfo_tsn + 1)) { 16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep, we can add it on */ 16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int end = 0; 1608b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen 16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chunk_flags & SCTP_DATA_LAST_FRAG) { 16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen end = 1; 16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_append_to_readq(stcb->sctp_ep, stcb, control, dmbuf, end, 16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn, 16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv)) { 16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Append fails end:%d\n", end); 16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto failed_pdapi_express_del; 16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { 16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = tsn; 16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvexpressm); 16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = tsn; 16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragment_flags = chunk_flags; 16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_of_pdapi_last_delivered = tsn; 16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_flags_delivered = chunk_flags; 16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_strm_seq_delivered = strmseq; 16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_strm_no_delivered = strmno; 16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (end) { 16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up the flags and such */ 16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 0; 16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) { 16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[strmno].last_sequence_delivered++; 16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi = NULL; 16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->reasmqueue) == 0) { 16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* There could be another message ready */ 16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen need_reasm_check = 1; 16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control = NULL; 16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto finish_express_del; 16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen failed_pdapi_express_del: 16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control = NULL; 16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { 16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = tsn; 16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); 16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_map)) { 16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = tsn; 16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) { 16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_alloc_a_chunk(stcb, chk); 16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk == NULL) { 16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No memory so we drop the chunk */ 16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_nomem); 16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (last_chunk == 0) { 16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we copied it, free the copy */ 16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(dmbuf); 16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.TSN_seq = tsn; 16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->no_fr_allowed = 0; 16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_seq = strmseq; 16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.stream_number = strmno; 16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.payloadtype = protocol_id; 16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.context = stcb->asoc.context; 16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.doing_fast_retransmit = 0; 16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.data.rcv_flags = chunk_flags; 16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->asoc = asoc; 16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->send_size = the_len; 16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = net; 16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&net->ref_count, 1); 16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = dmbuf; 16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_alloc_a_readq(stcb, control); 16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, 16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen protocol_id, 16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strmno, strmseq, 16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunk_flags, 16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen dmbuf); 16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control == NULL) { 16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No memory so we drop the chunk */ 16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_nomem); 16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (last_chunk == 0) { 16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we copied it, free the copy */ 16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(dmbuf); 16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->length = the_len; 17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Mark it as received */ 17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now queue it where it belongs */ 17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control != NULL) { 17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First a sanity check */ 17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress) { 17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok, we have a fragmented delivery in progress if 17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this chunk is next to deliver OR belongs in our 17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * view to the reassembly, the peer is evil or 17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * broken. 17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t estimate_tsn; 17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen estimate_tsn = asoc->tsn_last_delivered + 1; 17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->reasmqueue) && 17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (estimate_tsn == control->sinfo_tsn)) { 17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Evil/Broke peer */ 17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(control->data); 17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->data = NULL; 17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control->whoFrom) { 17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(control->whoFrom); 17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->whoFrom = NULL; 17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_readq(stcb, control); 17268f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "Reas. queue emtpy, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 17278f9e45fea288542b24a6bda01269c6fc184d991at tsn, strmno, strmseq); 17288f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_15; 17308f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 1732a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt if (last_chunk) { 1733a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt *m = NULL; 1734a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt } 17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) { 17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(control->data); 17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->data = NULL; 17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control->whoFrom) { 17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(control->whoFrom); 17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->whoFrom = NULL; 17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_readq(stcb, control); 17458f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 17468f9e45fea288542b24a6bda01269c6fc184d991at tsn, strmno, strmseq); 17478f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_16; 17498f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 1751a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt if (last_chunk) { 1752a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt *m = NULL; 1753a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt } 17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No PDAPI running */ 17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->reasmqueue)) { 17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Reassembly queue is NOT empty validate 17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that this tsn does not need to be in 17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reasembly queue. If it does then our peer 17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is broken or evil. 17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) { 17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(control->data); 17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->data = NULL; 17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (control->whoFrom) { 17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(control->whoFrom); 17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control->whoFrom = NULL; 17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_readq(stcb, control); 17748f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "No PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", 17758f9e45fea288542b24a6bda01269c6fc184d991at tsn, strmno, strmseq); 17768f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_17; 17788f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 1780a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt if (last_chunk) { 1781a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt *m = NULL; 1782a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt } 17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok, if we reach here we have passed the sanity checks */ 17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chunk_flags & SCTP_DATA_UNORDERED) { 17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue directly into socket buffer */ 17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, control->sinfo_tsn); 17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen control, 17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Special check for when streams are resetting. We 17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * could be more smart about this and check the 17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * actual stream to see if it is not being reset.. 17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that way we would not create a HOLB when amongst 18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * streams being reset and those not being reset. 18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We take complete messages that have a stream reset 18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * intervening (aka the TSN is after where our 18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cum-ack needs to be) off and put them on a 18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pending_reply_queue. The reassembly ones we do 18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not have to worry about since they are all sorted 18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and proceessed by TSN order. It is only the 18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * singletons I must worry about. 18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) && 18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GT(tsn, liste->tsn)) { 18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * yep its past where we need to reset... go 18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ahead and queue it. 18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->pending_reply_queue)) { 18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first one on */ 18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next); 18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctlOn, *nctlOn; 18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned char inserted = 0; 18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctlOn, &asoc->pending_reply_queue, next, nctlOn) { 18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(control->sinfo_tsn, ctlOn->sinfo_tsn)) { 18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_BEFORE(ctlOn, control, next); 18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inserted = 1; 18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inserted == 0) { 18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * must be put at end, use 18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * prevP (all setup from 18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * loop) to setup nextP. 18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next); 18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_data_to_stream(stcb, asoc, control, abort_flag); 18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*abort_flag) { 1845a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt if (last_chunk) { 1846a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt *m = NULL; 1847a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt } 18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Into the re-assembly queue */ 18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_data_for_reasm(stcb, asoc, chk, abort_flag); 18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*abort_flag) { 18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the assoc is now gone and chk was put onto the 18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reasm queue, which has all been freed. 18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1860a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt if (last_chunk) { 1861a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt *m = NULL; 1862a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt } 18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfinish_express_del: 1867000a5bac556b28e74e4e98c540f66b1743e9312dtuexen if (tsn == (asoc->cumulative_tsn + 1)) { 1868000a5bac556b28e74e4e98c540f66b1743e9312dtuexen /* Update cum-ack */ 1869000a5bac556b28e74e4e98c540f66b1743e9312dtuexen asoc->cumulative_tsn = tsn; 18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (last_chunk) { 18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *m = NULL; 18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ordered) { 18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER64(sctps_inorderchunks); 18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER64(sctps_inunorderchunks); 18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvdata); 18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Set it present please */ 18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_strm_del_alt(stcb, tsn, strmseq, strmno, SCTP_STR_LOG_FROM_MARK_TSN); 18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, 18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE); 18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check the special flag for stream resets */ 18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) && 18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GE(asoc->cumulative_tsn, liste->tsn)) { 18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we have finished working through the backlogged TSN's now 18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * time to reset streams. 1: call reset function. 2: free 18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pending_reply space 3: distribute any chunks in 18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pending_reply_queue. 18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *nctl; 18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1899c1f5477d96c0c5178c74caad234035e534c37bdct sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams); 19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->resetHead, liste, next_resp); 19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(liste, SCTP_M_STRESET); 19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen liste = TAILQ_FIRST(&asoc->resetHead); 19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->resetHead)) { 19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* All can be removed */ 19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) { 19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next); 19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag); 19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*abort_flag) { 1910b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) { 19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(ctl->sinfo_tsn, liste->tsn)) { 19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if ctl->sinfo_tsn is <= liste->tsn we can 19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process it which is the NOT of 19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ctl->sinfo_tsn > liste->tsn 19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next); 19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag); 19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*abort_flag) { 1926b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now service re-assembly to pick up anything that has been 19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * held on reassembly queue? 19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_deliver_reasm_check(stcb, asoc); 19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen need_reasm_check = 0; 19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (need_reasm_check) { 19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Another one waits ? */ 19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_deliver_reasm_check(stcb, asoc); 19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint8_t sctp_map_lookup_tab[256] = { 19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 5, 19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 6, 19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 5, 19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 7, 19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 5, 19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 6, 19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 5, 19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 4, 19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 3, 19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 1, 0, 2, 0, 1, 0, 8 19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}; 19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_slide_mapping_arrays(struct sctp_tcb *stcb) 19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now we also need to check the mapping array in a couple of ways. 19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1) Did we move the cum-ack point? 19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * When you first glance at this you might think 19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that all entries that make up the postion 19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * of the cum-ack would be in the nr-mapping array 19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * only.. i.e. things up to the cum-ack are always 19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deliverable. Thats true with one exception, when 19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * its a fragmented message we may not deliver the data 19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * until some threshold (or all of it) is in place. So 19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must OR the nr_mapping_array and mapping_array to 19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * get a true picture of the cum-ack. 19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int at; 20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t val; 20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int slide_from, slide_end, lgap, distance; 20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t old_cumack, old_base, old_highest, highest_tsn; 20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_cumack = asoc->cumulative_tsn; 20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_base = asoc->mapping_array_base_tsn; 20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_highest = asoc->highest_tsn_inside_map; 20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We could probably improve this a small bit by calculating the 20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * offset of the current cum-ack as the starting point. 20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen at = 0; 20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { 20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen val = asoc->nr_mapping_array[slide_from] | asoc->mapping_array[slide_from]; 20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (val == 0xff) { 20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen at += 8; 20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* there is a 0 bit */ 20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen at += sctp_map_lookup_tab[val]; 20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at-1); 20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->cumulative_tsn, asoc->highest_tsn_inside_map) && 20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GT(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map)) { 20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("huh, cumack 0x%x greater than high-tsn 0x%x in map", 20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cumulative_tsn, asoc->highest_tsn_inside_map); 20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("huh, cumack 0x%x greater than high-tsn 0x%x in map - should panic?\n", 20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cumulative_tsn, asoc->highest_tsn_inside_map); 20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_print_mapping_array(asoc); 20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(0, 6, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = asoc->cumulative_tsn; 20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn; 20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) { 20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = asoc->highest_tsn_inside_nr_map; 20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = asoc->highest_tsn_inside_map; 20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) { 20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* The complete array was completed by a single FR */ 20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* highest becomes the cum-ack */ 20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int clr; 20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int i; 20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear the array */ 20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen clr = ((at+7) >> 3); 20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (clr > asoc->mapping_array_size) { 20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen clr = asoc->mapping_array_size; 20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(asoc->mapping_array, 0, clr); 20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(asoc->nr_mapping_array, 0, clr); 20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < asoc->mapping_array_size; i++) { 20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->mapping_array[i]) || (asoc->nr_mapping_array[i])) { 206547a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("Error Mapping array's not clean at clear\n"); 20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_print_mapping_array(asoc); 20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1; 20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn; 20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (at >= 8) { 20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we can slide the mapping array down */ 20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* slide_from holds where we hit the first NON 0xff byte */ 20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now calculate the ceiling of the move using our highest 20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * TSN value 20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(lgap, highest_tsn, asoc->mapping_array_base_tsn); 20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen slide_end = (lgap >> 3); 20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (slide_end < slide_from) { 20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_print_mapping_array(asoc); 20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("impossible slide"); 20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 208747a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n", 208847a306d634abf33223ef347472c4b1cd441d139ftuexen lgap, slide_end, slide_from, at); 20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (slide_end > asoc->mapping_array_size) { 20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("would overrun buffer"); 20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 209647a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("Gak, would have overrun map end:%d slide_end:%d\n", 209747a306d634abf33223ef347472c4b1cd441d139ftuexen asoc->mapping_array_size, slide_end); 20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen slide_end = asoc->mapping_array_size; 20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen distance = (slide_end - slide_from) + 1; 21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(old_base, old_cumack, old_highest, 21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MAP_PREPARE_SLIDE); 21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map((uint32_t) slide_from, (uint32_t) slide_end, 21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) lgap, SCTP_MAP_SLIDE_FROM); 21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (distance + slide_from > asoc->mapping_array_size || 21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen distance < 0) { 21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we do NOT slide forward the array so that 21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * hopefully when more data comes in to fill it up 21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we will be able to slide it forward. Really I 21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * don't think this should happen :-0 21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map((uint32_t) distance, (uint32_t) slide_from, 21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) asoc->mapping_array_size, 21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MAP_SLIDE_NONE); 21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ii; 21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (ii = 0; ii < distance; ii++) { 21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array[ii] = asoc->mapping_array[slide_from + ii]; 21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->nr_mapping_array[ii] = asoc->nr_mapping_array[slide_from + ii]; 21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (ii = distance; ii < asoc->mapping_array_size; ii++) { 21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array[ii] = 0; 21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->nr_mapping_array[ii] = 0; 21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->highest_tsn_inside_map + 1 == asoc->mapping_array_base_tsn) { 21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map += (slide_from << 3); 21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->highest_tsn_inside_nr_map + 1 == asoc->mapping_array_base_tsn) { 21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map += (slide_from << 3); 21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array_base_tsn += (slide_from << 3); 21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(asoc->mapping_array_base_tsn, 21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cumulative_tsn, asoc->highest_tsn_inside_map, 21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MAP_SLIDE_RESULT); 21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 21510ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_sack_check(struct sctp_tcb *stcb, int was_a_gap) 21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t highest_tsn; 21550ac02f34d6041cd0018437596a5a9a94685e6919tuexen 21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) { 21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = asoc->highest_tsn_inside_nr_map; 21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = asoc->highest_tsn_inside_map; 21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now we need to see if we need to queue a sack or just start the 21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * timer (if allowed). 21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok special case, in SHUTDOWN-SENT case. here we 21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * maker sure SACK timer is off and instead send a 21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SHUTDOWN and a SACK 21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_RECV, 21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA+SCTP_LOC_18); 21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2177000a5bac556b28e74e4e98c540f66b1743e9312dtuexen sctp_send_shutdown(stcb, 21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination)); 21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int is_a_gap; 21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is there a gap now ? */ 21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen is_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algorithm: increase number of packets 21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * received since last ack 21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cmt_dac_pkts_rcvd++; 2191000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.send_sack == 1) || /* We need to send a SACK */ 21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((was_a_gap) && (is_a_gap == 0)) || /* was a gap, but no 21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * longer is one */ 21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.numduptsns) || /* we have dup's */ 21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (is_a_gap) || /* is still a gap */ 21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.delayed_ack == 0) || /* Delayed sack disabled */ 21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */ 21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2201b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if ((stcb->asoc.sctp_cmt_on_off > 0) && 22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) && 22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.send_sack == 0) && 22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.numduptsns == 0) && 22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.delayed_ack) && 22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) { 22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algorithm: With CMT, 22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delay acks even in the face of 22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reordering. Therefore, if acks 22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that do not have to be sent 22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * because of the above reasons, 22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will be delayed. That is, acks 22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that would have been sent due to 22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * gap reports will be delayed with 22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * DAC. Start the delayed ack timer. 22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_RECV, 22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, NULL); 22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok we must build a SACK since the 22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * timer is pending, we got our 22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first packet OR there are gaps or 22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * duplicates. 22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_RECV, 22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, NULL); 22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) 22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsize, pd_point; 22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t nxt_todel; 22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress) { 22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_service_reassembly(stcb, asoc); 22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can we proceed further, i.e. the PD-API is complete */ 22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress) { 22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no */ 22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now is there some other chunk I can deliver from the reassembly 22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue. 22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen doit_again: 22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = TAILQ_FIRST(&asoc->reasmqueue); 22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk == NULL) { 22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue = 0; 22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cnt_on_reasm_queue = 0; 22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nxt_todel = asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered + 1; 22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) && 22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((nxt_todel == chk->rec.data.stream_seq) || 22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED))) { 22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Yep the first one is here. We setup to start reception, 22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * by backing down the TSN just in case we can't deliver. 22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Before we start though either all of the message should 22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * be here or the socket buffer max or nothing on the 22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delivery queue and something can be delivered. 22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 2282cdc78af866f2b29865707afee7ea65e1706b4ff8t pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, 22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->partial_delivery_point); 22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pd_point = stcb->sctp_ep->partial_delivery_point; 22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) { 22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 1; 22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1; 22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_of_pdapi = chk->rec.data.stream_number; 22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->ssn_of_pdapi = chk->rec.data.stream_seq; 22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pdapi_ppid = chk->rec.data.payloadtype; 22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragment_flags = chk->rec.data.rcv_flags; 22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_service_reassembly(stcb, asoc); 22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress == 0) { 22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto doit_again; 22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, 2304e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 230551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctphdr *sh, struct sctp_inpcb *inp, 230651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t *high_tsn, 230751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 230851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 230951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 231051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id, uint16_t port) 23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_data_chunk *ch, chunk_buf; 23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_chunks = 0; /* number of control chunks processed */ 23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int stop_proc = 0; 23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int chk_length, break_flag, last_chunk; 23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_flag = 0, was_a_gap; 23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m; 23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t highest_tsn; 23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the rwnd */ 23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_set_rwnd(stcb, &stcb->asoc); 23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m = *mm; 23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) { 23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = asoc->highest_tsn_inside_nr_map; 23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = asoc->highest_tsn_inside_map; 23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * setup where we got the last DATA packet from for any SACK that 23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * may need to go out. Don't bump the net. This is done ONLY when a 23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chunk is assigned. 23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_data_chunk_from = net; 23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now before we proceed we must figure out if this is a wasted 23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cluster... i.e. it is a small packet sent in and yet the driver 23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * underneath allocated a full cluster for it. If so we must copy it 23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to a smaller mbuf and free up the cluster mbuf. This will help 23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with cluster starvation. Note for __Panda__ we don't do this 23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since it has clusters all the way down to 64 bytes. 23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_LEN(m) < (long)MLEN && SCTP_BUF_NEXT(m) == NULL) { 23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we only handle mbufs that are singletons.. not chains */ 235168beeca578347438d9c434680197647ed551935ft m = sctp_get_mbuf_for_msg(SCTP_BUF_LEN(m), 0, M_NOWAIT, 1, MT_DATA); 23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m) { 23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok lets see if we can copy the data up */ 23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen caddr_t *from, *to; 23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the pointers and copy */ 23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to = mtod(m, caddr_t *); 23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen from = mtod((*mm), caddr_t *); 23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(to, from, SCTP_BUF_LEN((*mm))); 23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy the length and free up the old */ 23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m) = SCTP_BUF_LEN((*mm)); 23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(*mm); 23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sucess, back copy */ 23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *mm = m; 23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are in trouble in the mbuf world .. yikes */ 23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m = *mm; 23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get pointer to the first chunk header */ 23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_data_chunk *)sctp_m_getptr(m, *offset, 23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_data_chunk), (uint8_t *) & chunk_buf); 23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process all DATA chunks... 23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *high_tsn = asoc->cumulative_tsn; 23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break_flag = 0; 23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->data_pkts_seen++; 23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (stop_proc == 0) { 23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate chunk length */ 23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk_length = ntohs(ch->ch.chunk_length); 23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (length - *offset < chk_length) { 23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* all done, mutulated chunk */ 23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stop_proc = 1; 2388b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen continue; 23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch->ch.chunk_type == SCTP_DATA) { 2391a06ca64c1ea60031147a135d015c66e4803beb1ct if ((size_t)chk_length < sizeof(struct sctp_data_chunk)) { 23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Need to send an abort since we had a 23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * invalid data chunk. 23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 23978f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23998f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "DATA chunk of length %d", 24008f9e45fea288542b24a6bda01269c6fc184d991at chk_length); 24018f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19; 2403e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, 2404e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 240551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 240651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 240751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 240851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (2); 24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2411a06ca64c1ea60031147a135d015c66e4803beb1ct if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) { 2412a06ca64c1ea60031147a135d015c66e4803beb1ct /* 2413a06ca64c1ea60031147a135d015c66e4803beb1ct * Need to send an abort since we had an 2414a06ca64c1ea60031147a135d015c66e4803beb1ct * empty data chunk. 2415a06ca64c1ea60031147a135d015c66e4803beb1ct */ 2416a06ca64c1ea60031147a135d015c66e4803beb1ct struct mbuf *op_err; 2417a06ca64c1ea60031147a135d015c66e4803beb1ct 2418a06ca64c1ea60031147a135d015c66e4803beb1ct op_err = sctp_generate_no_user_data_cause(ch->dp.tsn); 2419a06ca64c1ea60031147a135d015c66e4803beb1ct stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19; 2420a06ca64c1ea60031147a135d015c66e4803beb1ct sctp_abort_association(inp, stcb, m, iphlen, 2421a06ca64c1ea60031147a135d015c66e4803beb1ct src, dst, sh, op_err, 2422a06ca64c1ea60031147a135d015c66e4803beb1ct#if defined(__FreeBSD__) 2423a06ca64c1ea60031147a135d015c66e4803beb1ct use_mflowid, mflowid, 2424a06ca64c1ea60031147a135d015c66e4803beb1ct#endif 2425a06ca64c1ea60031147a135d015c66e4803beb1ct vrf_id, port); 2426a06ca64c1ea60031147a135d015c66e4803beb1ct return (2); 2427a06ca64c1ea60031147a135d015c66e4803beb1ct } 24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xB1, 0); 24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SIZE32(chk_length) == (length - *offset)) { 24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_chunk = 1; 24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_chunk = 0; 24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_process_a_data_chunk(stcb, asoc, mm, *offset, ch, 24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk_length, net, high_tsn, &abort_flag, &break_flag, 24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_chunk)) { 24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_chunks++; 24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_flag) 24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (2); 24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (break_flag) { 24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Set because of out of rwnd space and no 24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * drop rep space left. 24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stop_proc = 1; 2450b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen continue; 24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not a data chunk in the data region */ 24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ch->ch.chunk_type) { 24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_INITIATION: 24568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_INITIATION_ACK: 24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SELECTIVE_ACK: 2458b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen case SCTP_NR_SELECTIVE_ACK: 24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HEARTBEAT_REQUEST: 24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HEARTBEAT_ACK: 24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ABORT_ASSOCIATION: 24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN: 24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN_ACK: 24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_OPERATION_ERROR: 24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_COOKIE_ECHO: 24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_COOKIE_ACK: 24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ECN_ECHO: 24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ECN_CWR: 24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN_COMPLETE: 24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_AUTHENTICATION: 24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF_ACK: 24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_PACKET_DROPPED: 24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STREAM_RESET: 24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_FORWARD_CUM_TSN: 24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF: 24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now, what do we do with KNOWN chunks that 24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * are NOT in the right place? 24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For now, I do nothing but ignore them. We 24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * may later want to add sysctl stuff to 24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * switch out and do either an ABORT() or 24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * possibly process them. 24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) { 24868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24888f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, ""); 248951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen sctp_abort_association(inp, stcb, 249051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen m, iphlen, 2491e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, 249251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen sh, op_err, 249351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 249451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 249551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 249651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 24978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (2); 24988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 25008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unknown chunk type, use bit rules */ 25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch->ch.chunk_type & 0x40) { 25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Add a error report to the queue */ 25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *merr; 25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *phd; 25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 250768beeca578347438d9c434680197647ed551935ft merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA); 25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (merr) { 25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phd = mtod(merr, struct sctp_paramhdr *); 25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We cheat and use param 25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type since we did not 25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * bother to define a error 25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cause struct. They are 25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the same basic format 25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with different names. 25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phd->param_type = 25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(SCTP_CAUSE_UNRECOG_CHUNK); 25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phd->param_length = 25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(chk_length + sizeof(*phd)); 25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(merr) = sizeof(*phd); 252368beeca578347438d9c434680197647ed551935ft SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); 25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_NEXT(merr)) { 25254df11f5004bbb4c768851ee41149ba6982c60f29tuexen if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL)) { 25264df11f5004bbb4c768851ee41149ba6982c60f29tuexen sctp_m_freem(merr); 25274df11f5004bbb4c768851ee41149ba6982c60f29tuexen } else { 25284df11f5004bbb4c768851ee41149ba6982c60f29tuexen sctp_queue_op_err(stcb, merr); 25294df11f5004bbb4c768851ee41149ba6982c60f29tuexen } 25308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 25318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(merr); 25328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->ch.chunk_type & 0x80) == 0) { 25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* discard the rest of this packet */ 25378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stop_proc = 1; 25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* else skip this bad chunk and 25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * continue... */ 25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 2541b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } /* switch of chunk type */ 25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset += SCTP_SIZE32(chk_length); 25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((*offset >= length) || stop_proc) { 25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more data left in the mbuf chain */ 25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stop_proc = 1; 25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_data_chunk *)sctp_m_getptr(m, *offset, 25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_data_chunk), (uint8_t *) & chunk_buf); 25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stop_proc = 1; 2554b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen continue; 25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2556b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (break_flag) { 25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we need to report rwnd overrun drops. 25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 256138bf75f6cfcdbd22c0e22e82f236c2b7634591f1tuexen sctp_send_packet_dropped(stcb, net, *mm, length, iphlen, 0); 25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_chunks) { 25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Did we get data, if so update the time for auto-close and 25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * give peer credit for being alive. 25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvpktwithdata); 25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INDATA, 25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_last_rcvd); 25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now service all of the reassm queue if needed */ 25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(TAILQ_EMPTY(&asoc->reasmqueue))) 25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_service_queues(stcb, asoc); 25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assure that we ack right away */ 25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.send_sack = 1; 25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Start a sack timer or QUEUE a SACK for sending */ 25880ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_sack_check(stcb, was_a_gap); 25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1, uint32_t last_tsn, 25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t frag_strt, uint16_t frag_end, int nr_sacking, 25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *num_frs, 25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t *biggest_newly_acked_tsn, 25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t *this_sack_lowest_newack, 25980ac02f34d6041cd0018437596a5a9a94685e6919tuexen int *rto_ok) 25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1; 26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int theTSN; 26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int j, wake_him = 0, circled = 0; 26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Recover the tp1 we last saw */ 26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = *p_tp1; 26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1 == NULL) { 26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (j = frag_strt; j <= frag_end; j++) { 26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen theTSN = j + last_tsn; 26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (tp1) { 26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.doing_fast_retransmit) 26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*num_frs) += 1; 26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: CUCv2 algorithm. For each TSN being 26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * processed from the sent queue, track the 26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * next expected pseudo-cumack, or 26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * rtx_pseudo_cumack, if required. Separate 26208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cumack trackers for first transmissions, 26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and retransmissions. 26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && 26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (tp1->snd_count == 1)) { 26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq; 26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_pseudo_cumack = 0; 26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && 26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (tp1->snd_count > 1)) { 26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq; 26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_rtx_pseudo_cumack = 0; 26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.TSN_seq == theTSN) { 26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent != SCTP_DATAGRAM_UNSENT) { 26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * must be held until 26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cum-ack passes 26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If it is less than RESEND, it is 26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now no-longer in flight. 26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Higher values may already be set 26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * via previous Gap Ack Blocks... 26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * i.e. ACKED or RESEND. 26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, 26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *biggest_newly_acked_tsn)) { 26498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *biggest_newly_acked_tsn = tp1->rec.data.TSN_seq; 26508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: SFR algo (and HTNA) - set 26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * saw_newack to 1 for dest being 26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * newly acked. update 26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this_sack_highest_newack if 26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * appropriate. 26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.chunk_was_revoked == 0) 26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->saw_newack = 1; 26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, 26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->this_sack_highest_newack)) { 26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->this_sack_highest_newack = 26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq; 26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algo: also update 26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this_sack_lowest_newack 26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*this_sack_lowest_newack == 0) { 26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(*this_sack_lowest_newack, 26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_tsn, 26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_TSN_ACKED); 26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *this_sack_lowest_newack = tp1->rec.data.TSN_seq; 26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: CUCv2 algorithm. If (rtx-)pseudo-cumack for corresp 26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * dest is being acked, then we have a new (rtx-)pseudo-cumack. Set 26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new_(rtx_)pseudo_cumack to TRUE so that the cwnd for this dest can be 26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * updated. Also trigger search for the next expected (rtx-)pseudo-cumack. 26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Separate pseudo_cumack trackers for first transmissions and 26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * retransmissions. 26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) { 26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.chunk_was_revoked == 0) { 26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->new_pseudo_cumack = 1; 26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_pseudo_cumack = 1; 26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { 26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); 26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) { 26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.chunk_was_revoked == 0) { 27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->new_pseudo_cumack = 1; 27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_rtx_pseudo_cumack = 1; 27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(*biggest_newly_acked_tsn, 27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_tsn, 27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen frag_strt, 27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen frag_end, 27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_TSN_ACKED); 27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP, 27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(tp1); 27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { 27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo, 27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1); 27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, tp1); 27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack += tp1->send_size; 27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->snd_count < 2) { 27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * True non-retransmited chunk 27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack2 += tp1->send_size; 27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * update RTO too ? 27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->do_rtt) { 27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*rto_ok) { 27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->RTO = 27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_calculate_rto(stcb, 27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->asoc, 27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo, 27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &tp1->sent_rcv_time, 27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_align_safe_nocopy, 27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_DATA); 27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *rto_ok = 0; 27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo->rto_needed == 0) { 27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->rto_needed = 1; 27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->do_rtt = 0; 27518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent <= SCTP_DATAGRAM_RESEND) { 27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, 27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.this_sack_highest_gap)) { 27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.this_sack_highest_gap = 27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq; 27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND) { 27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(stcb->asoc.sent_queue_retran_cnt); 27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xB2, 27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.sent_queue_retran_cnt & 0x000000ff)); 27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * All chunks NOT UNSENT fall through here and are marked 27718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (leave PR-SCTP ones that are to skip alone though) 27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2773446be8e8a472f6e688885674d2430118fc4be5d7t if ((tp1->sent != SCTP_FORWARD_TSN_SKIP) && 277460db5740d3bcc26fd4ebc19b6b0652506994fd14t (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) { 27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent = SCTP_DATAGRAM_MARKED; 2776446be8e8a472f6e688885674d2430118fc4be5d7t } 27778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.chunk_was_revoked) { 27788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* deflate the cwnd */ 27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->cwnd -= tp1->book_size; 27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.chunk_was_revoked = 0; 27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* NR Sack code here */ 278360db5740d3bcc26fd4ebc19b6b0652506994fd14t if (nr_sacking && 278460db5740d3bcc26fd4ebc19b6b0652506994fd14t (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) { 278560db5740d3bcc26fd4ebc19b6b0652506994fd14t if (stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) { 278660db5740d3bcc26fd4ebc19b6b0652506994fd14t stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues--; 278760db5740d3bcc26fd4ebc19b6b0652506994fd14t#ifdef INVARIANTS 278860db5740d3bcc26fd4ebc19b6b0652506994fd14t } else { 278960db5740d3bcc26fd4ebc19b6b0652506994fd14t panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); 279060db5740d3bcc26fd4ebc19b6b0652506994fd14t#endif 279160db5740d3bcc26fd4ebc19b6b0652506994fd14t } 279260db5740d3bcc26fd4ebc19b6b0652506994fd14t tp1->sent = SCTP_DATAGRAM_NR_ACKED; 27938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->data) { 27948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 27958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 27968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(tp1->data); 27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->data = NULL; 27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wake_him++; 28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* if (tp1->TSN_seq == theTSN) */ 28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, theTSN)) { 28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 28068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_NEXT(tp1, sctp_next); 28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1 == NULL) && (circled == 0)) { 28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen circled++; 28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end while (tp1) */ 28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1 == NULL) { 28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen circled = 0; 28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* In case the fragments were not in order we must reset */ 28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end for (j = fragStart */ 28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *p_tp1 = tp1; 28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (wake_him); /* Return value only used for nr-sack */ 28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc, 28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t last_tsn, uint32_t *biggest_tsn_acked, 28278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t *biggest_newly_acked_tsn, uint32_t *this_sack_lowest_newack, 28280ac02f34d6041cd0018437596a5a9a94685e6919tuexen int num_seg, int num_nr_seg, int *rto_ok) 28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_gap_ack_block *frag, block; 28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1; 28328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 28338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_frs = 0; 28348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int chunk_freed; 28358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int non_revocable; 28368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t frag_strt, frag_end, prev_frag_end; 28378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&asoc->sent_queue); 28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev_frag_end = 0; 28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunk_freed = 0; 28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < (num_seg + num_nr_seg); i++) { 28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (i == num_seg) { 28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev_frag_end = 0; 28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&asoc->sent_queue); 28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset, 28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_gap_ack_block), (uint8_t *) &block); 28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset += sizeof(block); 28508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (frag == NULL) { 28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (chunk_freed); 28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen frag_strt = ntohs(frag->start); 28548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen frag_end = ntohs(frag->end); 28558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (frag_strt > frag_end) { 28578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This gap report is malformed, skip it. */ 28588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (frag_strt <= prev_frag_end) { 28618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This gap report is not in order, so restart. */ 28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&asoc->sent_queue); 28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT((last_tsn + frag_end), *biggest_tsn_acked)) { 28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *biggest_tsn_acked = last_tsn + frag_end; 28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (i < num_seg) { 28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen non_revocable = 0; 28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen non_revocable = 1; 28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, 28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen non_revocable, &num_frs, biggest_newly_acked_tsn, 28740ac02f34d6041cd0018437596a5a9a94685e6919tuexen this_sack_lowest_newack, rto_ok)) { 28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunk_freed = 1; 28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev_frag_end = frag_end; 28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_frs) 28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(*biggest_tsn_acked, 28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *biggest_newly_acked_tsn, 28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_tsn, SCTP_FR_LOG_BIGGEST_TSNS); 28848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (chunk_freed); 28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_for_revoked(struct sctp_tcb *stcb, 28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc, uint32_t cumack, 28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t biggest_tsn_acked) 28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1; 28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cumack)) { 28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ok this guy is either ACK or MARKED. If it is 28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ACKED it has been previously acked but not this 29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * time i.e. revoked. If it is MARKED it was ACK'ed 29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * again. 29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked)) { 29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_ACKED) { 29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it has been revoked */ 29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent = SCTP_DATAGRAM_SENT; 29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.chunk_was_revoked = 1; 29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We must add this stuff back in to 29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assure timers and such get started. 29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE, 29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 29198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_increase(tp1); 29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_increase(stcb, tp1); 29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We inflate the cwnd to compensate for our 29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * artificial inflation of the flight_size. 29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->cwnd += tp1->book_size; 29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(asoc->last_acked_seq, 29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cumack, 29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 29308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_TSN_REVOKED); 29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (tp1->sent == SCTP_DATAGRAM_MARKED) { 29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it has been re-acked in this SACK */ 29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent = SCTP_DATAGRAM_ACKED; 29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_UNSENT) 29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, 29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t biggest_tsn_acked, uint32_t biggest_tsn_newly_acked, uint32_t this_sack_lowest_newack, int accum_moved) 29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1; 29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int strike_flag = 0; 29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval now; 29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int tot_retrans = 0; 29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t sending_seq; 29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_dests_sacked = 0; 29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * select the sending_seq, this is either the next thing ready to be 29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sent but not transmitted, OR, the next seq we assign. 29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_FIRST(&stcb->asoc.send_queue); 29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1 == NULL) { 29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sending_seq = asoc->sending_seq; 29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sending_seq = tp1->rec.data.TSN_seq; 29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* CMT DAC algo: finding out if SACK is a mixed SACK */ 29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->sctp_cmt_on_off > 0) && 29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) { 29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->saw_newack) 29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_dests_sacked++; 29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peer_supports_prsctp) { 29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&now); 29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strike_flag = 0; 29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->no_fr_allowed) { 29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this one had a timeout or something */ 29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) 29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(biggest_tsn_newly_acked, 29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 29898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_CHECK_STRIKE); 29918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked) || 29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent == SCTP_DATAGRAM_UNSENT) { 29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* done */ 29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peer_supports_prsctp) { 29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((PR_SCTP_TTL_ENABLED(tp1->flags)) && tp1->sent < SCTP_DATAGRAM_ACKED) { 29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Is it expired? */ 30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__ 30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timercmp(&now, &tp1->rec.data.timetodrop, >)) { 30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) { 30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yes so drop it */ 30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->data != NULL) { 300747674b651417d493ff4e0318113fd7beeef119dbtuexen (void)sctp_release_pr_sctp_chunk(stcb, tp1, 1, 30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->this_sack_highest_gap)) { 30168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we are beyond the tsn in the sack */ 30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent >= SCTP_DATAGRAM_RESEND) { 30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* either a RESEND, ACKED, or MARKED */ 30218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* skip */ 30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_FORWARD_TSN_SKIP) { 30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Continue strikin FWD-TSN chunks */ 30248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.fwd_tsn_cnt++; 30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT : SFR algo (covers part of DAC and HTNA as well) 30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo && tp1->whoTo->saw_newack == 0) { 30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * No new acks were receieved for data sent to this 30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * dest. Therefore, according to the SFR algo for 30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT, no data sent to this dest can be marked for 30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FR using this SACK. 30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (tp1->whoTo && SCTP_TSN_GT(tp1->rec.data.TSN_seq, 30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->this_sack_highest_newack)) { 30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: New acks were receieved for data sent to 30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this dest. But no new acks were seen for data 30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sent after tp1. Therefore, according to the SFR 30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * algo for CMT, tp1 cannot be marked for FR using 30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this SACK. This step covers part of the DAC algo 30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and the HTNA algo as well. 30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we check to see if we were have already done a FR 30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and if so we see if the biggest TSN we saw in the sack is 30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * smaller than the recovery point. If so we don't strike 30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the tsn... otherwise we CAN strike the TSN. 30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * @@@ JRI: Check for CMT 30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if (accum_moved && asoc->fast_retran_loss_recovery && (sctp_cmt_on_off == 0)) { 30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (accum_moved && asoc->fast_retran_loss_recovery) { 30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Strike the TSN if in fast-recovery and cum-ack 30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * moved. 30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(biggest_tsn_newly_acked, 30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_STRIKE_CHUNK); 30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent++; 30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->sctp_cmt_on_off > 0) && 30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) { 30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algorithm: If SACK flag is set to 30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 0, then lowest_newack test will not pass 30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * because it would have been set to the 30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cumack earlier. If not already to be 30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * rtx'd, If not a mixed sack and if tp1 is 30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not between two sacked TSNs, then mark by 30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one more. 30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE that we are marking by one additional time since the SACK DAC flag indicates that 30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two packets have been received after this missing TSN. 30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && 30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) { 30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(16 + num_dests_sacked, 30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_STRIKE_CHUNK); 30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent++; 30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((tp1->rec.data.doing_fast_retransmit) && 31008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->sctp_cmt_on_off == 0)) { 31018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For those that have done a FR we must take 31038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * special consideration if we strike. I.e the 31048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * biggest_newly_acked must be higher than the 31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sending_seq at the time we did the FR. 31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ( 31088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_FR_TO_ALTERNATE 31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If FR's go to new networks, then we must only do 31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this for singly homed asoc's. However if the FR's 31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * go to the same network (Armando's work) then its 31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ok to FR multiple times. 31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->numnets < 2) 31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (1) 31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(biggest_tsn_newly_acked, 31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.fast_retran_tsn)) { 31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Strike the TSN, since this ack is 31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * beyond where things were when we 31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * did a FR. 31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 31298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(biggest_tsn_newly_acked, 31308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 31318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 31328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_STRIKE_CHUNK); 31338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 31358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent++; 31368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strike_flag = 1; 31388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->sctp_cmt_on_off > 0) && 31398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) { 31408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algorithm: If 31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SACK flag is set to 0, 31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * then lowest_newack test 31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will not pass because it 31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * would have been set to 31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the cumack earlier. If 31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not already to be rtx'd, 31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If not a mixed sack and 31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if tp1 is not between two 31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sacked TSNs, then mark by 31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one more. 31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE that we are marking by one additional time since the SACK DAC flag indicates that 31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two packets have been received after this missing TSN. 31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->sent < SCTP_DATAGRAM_RESEND) && 31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (num_dests_sacked == 1) && 31578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GT(this_sack_lowest_newack, 31588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq)) { 31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(32 + num_dests_sacked, 31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_STRIKE_CHUNK); 31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent++; 31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * JRI: TODO: remove code for HTNA algo. CMT's 31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SFR algo covers HTNA. 31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, 31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen biggest_tsn_newly_acked)) { 31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We don't strike these: This is the HTNA 31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * algorithm i.e. we don't strike If our TSN is 31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * larger than the Highest TSN Newly Acked. 31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ; 31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Strike the TSN */ 31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(biggest_tsn_newly_acked, 31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_STRIKE_CHUNK); 31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent++; 31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->sctp_cmt_on_off > 0) && 31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) { 31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algorithm: If SACK flag is set to 31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 0, then lowest_newack test will not pass 32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * because it would have been set to the 32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cumack earlier. If not already to be 32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * rtx'd, If not a mixed sack and if tp1 is 32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not between two sacked TSNs, then mark by 32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one more. 32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE that we are marking by one additional time since the SACK DAC flag indicates that 32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two packets have been received after this missing TSN. 32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && 32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) { 32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(48 + num_dests_sacked, 32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent, 32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FR_LOG_STRIKE_CHUNK); 32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent++; 32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND) { 32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *alt; 32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fix counts and things */ 32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND, 32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (tp1->whoTo ? (tp1->whoTo->flight_size) : 0), 32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo) { 32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack++; 32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(tp1); 32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { 32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo, 32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1); 32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3239000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) { 32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_rwnd(SCTP_INCREASE_PEER_RWND, 32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd, tp1->send_size, SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)); 32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add back to the rwnd */ 32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd += (tp1->send_size + SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)); 3246000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove from the total flight */ 32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, tp1); 32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.peer_supports_prsctp) && 32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (PR_SCTP_RTX_ENABLED(tp1->flags))) { 32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Has it been retransmitted tv_sec times? - we store the retran count there. */ 32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) { 32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yes, so drop it */ 32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->data != NULL) { 325647674b651417d493ff4e0318113fd7beeef119dbtuexen (void)sctp_release_pr_sctp_chunk(stcb, tp1, 1, 32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Make sure to flag we had a FR */ 32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack++; 32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3263000a5bac556b28e74e4e98c540f66b1743e9312dtuexen } 326447a306d634abf33223ef347472c4b1cd441d139ftuexen /* SCTP_PRINTF("OK, we are now ready to FR this guy\n"); */ 32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(tp1->rec.data.TSN_seq, tp1->snd_count, 32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, SCTP_FR_MARKED); 32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (strike_flag) { 32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This is a subsequent FR */ 32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_sendmultfastretrans); 32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->sctp_cmt_on_off > 0) { 32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: Using RTX_SSTHRESH policy for CMT. 32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If CMT is being used, then pick dest with 32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * largest ssthresh for any retransmission. 32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->no_fr_allowed = 1; 32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = tp1->whoTo; 32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->sctp_cmt_pf > 0) { 32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS 5/18/07 - If CMT PF is on, use the PF version of find_alt_net() */ 32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, alt, 2); 32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS 5/18/07 - If only CMT is on, use the CMT version of find_alt_net() */ 32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, alt, 1); 32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt == NULL) { 32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = tp1->whoTo; 32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CUCv2: If a different dest is picked for 32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the retransmission, then new 32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (rtx-)pseudo_cumack needs to be tracked 32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for orig dest. Let CUCv2 track new (rtx-) 32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pseudo-cumack always. 33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo) { 33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_pseudo_cumack = 1; 33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_rtx_pseudo_cumack = 1; 33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else {/* CMT is OFF */ 33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_FR_TO_ALTERNATE 33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can we find an alternate? */ 33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = sctp_find_alternate_net(stcb, tp1->whoTo, 0); 33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * default behavior is to NOT retransmit 33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FR's to an alternate. Armando Caro's 33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * paper details why. 33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen alt = tp1->whoTo; 33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.doing_fast_retransmit = 1; 33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tot_retrans++; 33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* mark the sending seq for possible subsequent FR's */ 33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 332547a306d634abf33223ef347472c4b1cd441d139ftuexen * SCTP_PRINTF("Marking TSN for FR new value %x\n", 33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (uint32_t)tpi->rec.data.TSN_seq); 33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->send_queue)) { 33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 33308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the queue of send is empty then its 33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the next sequence number that will be 33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assigned so we subtract one from this to 33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * get the one we last sent. 33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.fast_retran_tsn = sending_seq; 33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If there are chunks on the send queue 33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (unsent data that has made it from the 33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stream queues but not out the door, we 33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * take the first one (which will have the 33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lowest TSN) and subtract one to get the 33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one we last sent. 33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *ttt; 33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ttt = TAILQ_FIRST(&asoc->send_queue); 33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.fast_retran_tsn = 33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ttt->rec.data.TSN_seq; 33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->do_rtt) { 33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this guy had a RTO calculation pending on 33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it, cancel it 33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 3357b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if ((tp1->whoTo != NULL) && 3358b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen (tp1->whoTo->rto_needed == 0)) { 33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->rto_needed = 1; 33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->do_rtt = 0; 33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (alt != tp1->whoTo) { 33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* yes, there is an alternate. */ 33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(tp1->whoTo); 33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo = alt; 33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&alt->ref_count, 1); 33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tmit_chunk * 33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_try_advance_peer_ack_point(struct sctp_tcb *stcb, 33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc) 33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1, *tp2, *a_adv = NULL; 33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval now; 33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int now_filled = 0; 33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peer_supports_prsctp == 0) { 33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) { 33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent != SCTP_FORWARD_TSN_SKIP && 3387bd461585c67bdbabcad5414912c2528605350344t tp1->sent != SCTP_DATAGRAM_RESEND && 338860db5740d3bcc26fd4ebc19b6b0652506994fd14t tp1->sent != SCTP_DATAGRAM_NR_ACKED) { 33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no chance to advance, out of here */ 33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) { 3393446be8e8a472f6e688885674d2430118fc4be5d7t if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) || 339460db5740d3bcc26fd4ebc19b6b0652506994fd14t (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) { 33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FWD_TSN_CHECK, 33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point, 33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 0, 0); 33988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!PR_SCTP_ENABLED(tp1->flags)) { 34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We can't fwd-tsn past any that are reliable aka 34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * retransmitted until the asoc fails. 34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!now_filled) { 34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&now); 34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen now_filled = 1; 34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now we got a chunk which is marked for another 34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * retransmission to a PR-stream but has run out its chances 34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * already maybe OR has been marked to skip now. Can we skip 34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it if its a resend? 34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND && 34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (PR_SCTP_TTL_ENABLED(tp1->flags))) { 34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now is this one marked for resend and its time is 34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now up? 34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__ 34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timercmp(&now, &tp1->rec.data.timetodrop, >)) { 34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) { 34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yes so drop it */ 34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->data) { 34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_release_pr_sctp_chunk(stcb, tp1, 343147674b651417d493ff4e0318113fd7beeef119dbtuexen 1, SCTP_SO_NOT_LOCKED); 34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * No, we are done when hit one for resend 34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * whos time as not expired. 34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok now if this chunk is marked to drop it we can clean up 34438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the chunk, advance our peer ack point and we can check 34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the next chunk. 34458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 3446bd461585c67bdbabcad5414912c2528605350344t if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) || 344760db5740d3bcc26fd4ebc19b6b0652506994fd14t (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) { 34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* advance PeerAckPoint goes forward */ 34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->advanced_peer_ack_point)) { 34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq; 34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_adv = tp1; 34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (tp1->rec.data.TSN_seq == asoc->advanced_peer_ack_point) { 34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No update but we do save the chk */ 34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_adv = tp1; 34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If it is still in RESEND we can advance no 34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * further 34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (a_adv); 34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fs_audit(struct sctp_association *asoc) 34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 3471b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0; 34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int entry_flight, entry_cnt, ret; 3473b2fe8b34ee35fbfe6e9379ae37579f047f79b4f7t 34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen entry_flight = asoc->total_flight; 34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen entry_cnt = asoc->total_flight_count; 34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret = 0; 3477000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->pr_sctp_cnt >= asoc->sent_queue_cnt) 34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent < SCTP_DATAGRAM_RESEND) { 348347a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("Chk TSN:%u size:%d inflight cnt:%d\n", 348447a306d634abf33223ef347472c4b1cd441d139ftuexen chk->rec.data.TSN_seq, 348547a306d634abf33223ef347472c4b1cd441d139ftuexen chk->send_size, 348647a306d634abf33223ef347472c4b1cd441d139ftuexen chk->snd_count); 34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inflight++; 34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (chk->sent == SCTP_DATAGRAM_RESEND) { 34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen resend++; 34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (chk->sent < SCTP_DATAGRAM_ACKED) { 34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inbetween++; 34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (chk->sent > SCTP_DATAGRAM_ACKED) { 34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen above++; 34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen acked++; 34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inflight > 0) || (inbetween > 0)) { 35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Flight size-express incorrect? \n"); 35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 350347a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("asoc->total_flight:%d cnt:%d\n", 350447a306d634abf33223ef347472c4b1cd441d139ftuexen entry_flight, entry_cnt); 35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Flight size-express incorrect F:%d I:%d R:%d Ab:%d ACK:%d\n", 35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inflight, inbetween, resend, above, acked); 35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret = 1; 35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ret); 35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_window_probe_recovery(struct sctp_tcb *stcb, 35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc, 35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1) 35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->window_probe = 0; 35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->sent >= SCTP_DATAGRAM_ACKED) || (tp1->data == NULL)) { 35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSN's skipped we do NOT move back. */ 35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DWN_WP_FWD, 35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First setup this by shrinking flight */ 35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { 35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo, 35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1); 35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(tp1); 35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, tp1); 35378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now mark for resend */ 35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent = SCTP_DATAGRAM_RESEND; 35398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->sent_queue_retran_cnt); 3540000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP, 35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 35458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 35498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, 35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t rwnd, int *abort_now, int ecne_seen) 35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 35548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 35558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 35568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1, *tp2; 35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t old_rwnd; 35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int win_probe_recovery = 0; 35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int win_probe_recovered = 0; 35608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int j, done_once = 0; 3561b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int rto_ok = 1; 35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) { 35648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_SACK_LOG_EXPRESS, cumack, 35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd); 35668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 35688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS 35698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cumack; 35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cumack_log_at++; 35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cumack_log_at > SCTP_TSN_LOG_SIZE) { 35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cumack_log_at = 0; 35738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_rwnd = asoc->peers_rwnd; 35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->last_acked_seq, cumack)) { 35788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* old ack */ 35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 35808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->last_acked_seq == cumack) { 35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Window update sack */ 35828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = sctp_sbspace_sub(rwnd, 35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); 35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SWS sender side engages */ 35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = 0; 35878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd > old_rwnd) { 35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto again; 35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 35928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First setup for CC stuff */ 35958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 35968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(cumack, net->cwr_window_tsn)) { 35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Drag along the window_tsn for cwr's */ 35988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->cwr_window_tsn = cumack; 35998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->prev_cwnd = net->cwnd; 36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack = 0; 36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack2 = 0; 36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: Reset CUC and Fast recovery algo variables before 36068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SACK processing 36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 36088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->new_pseudo_cumack = 0; 36098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->will_exit_fast_recovery = 0; 36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) { 36118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack)(stcb, net); 36128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) { 36158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t send_s; 36168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->sent_queue)) { 36188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_LAST(&asoc->sent_queue, 36198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctpchunk_listhead); 36208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_s = tp1->rec.data.TSN_seq + 1; 36218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 36228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_s = asoc->sending_seq; 36238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(cumack, send_s)) { 36258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef INVARIANTS 36268f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 36278f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 36288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 36308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 36318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Impossible sack 1"); 36328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 363381616c6a3e184f46276632dd15aa489cd06d94dftuexen 36348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_now = 1; 36358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX */ 36368f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x", 36378f9e45fea288542b24a6bda01269c6fc184d991at cumack, send_s); 36388f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 36398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; 36408f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 36418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 36428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 36438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->this_sack_highest_gap = cumack; 36468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 36478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 36488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 36498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 36508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INDATA, 36518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 36528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 36548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(cumack, asoc->last_acked_seq)) { 36558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the new consecutive TSN first */ 36568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) { 36578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(cumack, tp1->rec.data.TSN_seq)) { 36588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_UNSENT) { 365947a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("Warning, an unsent is now acked?\n"); 36608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_ACKED) { 36628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 36638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If it is less than ACKED, it is 36648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now no-longer in flight. Higher 36658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * values may occur during marking 36668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 36678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 36688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 36698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA, 36708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 36718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 36728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 36738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 36748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(tp1); 36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { 36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo, 36788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1); 36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, tp1); 36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack += tp1->send_size; 36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->snd_count < 2) { 36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * True non-retransmited 36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chunk 36888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack2 += 36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->send_size; 36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update RTO too? */ 36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->do_rtt) { 36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (rto_ok) { 36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->RTO = 36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sa_ignore 36988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NO_NULL_CHK 36998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 37008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_calculate_rto(stcb, 37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc, tp1->whoTo, 37028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &tp1->sent_rcv_time, 37038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_align_safe_nocopy, 37048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_DATA); 37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rto_ok = 0; 37068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo->rto_needed == 0) { 37088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->rto_needed = 1; 37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->do_rtt = 0; 37118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 37148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: CUCv2 algorithm. From the 37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cumack'd TSNs, for each TSN being 37168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * acked for the first time, set the 37178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * following variables for the 37188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * corresp destination. 37198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new_pseudo_cumack will trigger a 37208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cwnd update. 37218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find_(rtx_)pseudo_cumack will 37228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * trigger search for the next 37238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * expected (rtx-)pseudo-cumack. 37248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 37258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->new_pseudo_cumack = 1; 37268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_pseudo_cumack = 1; 37278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_rtx_pseudo_cumack = 1; 37288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 37298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { 37308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 37318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); 37328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND) { 37358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->sent_queue_retran_cnt); 37368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.chunk_was_revoked) { 37388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* deflate the cwnd */ 37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->cwnd -= tp1->book_size; 37408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.chunk_was_revoked = 0; 37418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 374260db5740d3bcc26fd4ebc19b6b0652506994fd14t if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) { 3743446be8e8a472f6e688885674d2430118fc4be5d7t if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) { 3744446be8e8a472f6e688885674d2430118fc4be5d7t asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--; 3745446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS 3746446be8e8a472f6e688885674d2430118fc4be5d7t } else { 3747446be8e8a472f6e688885674d2430118fc4be5d7t panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); 3748446be8e8a472f6e688885674d2430118fc4be5d7t#endif 3749446be8e8a472f6e688885674d2430118fc4be5d7t } 3750446be8e8a472f6e688885674d2430118fc4be5d7t } 37518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); 37528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->data) { 37538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 37548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_bufspace(stcb, asoc, tp1, 1); 37558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(tp1->data); 37568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->data = NULL; 37578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 37598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(asoc->last_acked_seq, 37608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cumack, 37618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 37628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 37638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 37648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_FREE_SENT); 37658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt--; 37678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, tp1, SCTP_SO_NOT_LOCKED); 37688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 37698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 37708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 37738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37740612043f643c9b26245564c05defca64d472060etuexen#if defined(__Userspace__) 37750ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (stcb->sctp_ep->recv_callback) { 37760ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (stcb->sctp_socket) { 37770ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen uint32_t inqueue_bytes, sb_free_now; 37780ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen struct sctp_inpcb *inp; 37790ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen 37800ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen inp = stcb->sctp_ep; 3781fbf619a4618811e6651f5a78cbacc6530797fd7etuexen inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk)); 37820ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen sb_free_now = SCTP_SB_LIMIT_SND(stcb->sctp_socket) - (inqueue_bytes + stcb->asoc.sb_send_resv); 37830ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen 37840ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen /* check if the amount free in the send socket buffer crossed the threshold */ 37850ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (inp->send_callback && 37860ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen (((inp->send_sb_threshold > 0) && 37870ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen (sb_free_now >= inp->send_sb_threshold) && 37880ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen (stcb->asoc.chunks_on_out_queue <= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) || 37890ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen (inp->send_sb_threshold == 0))) { 37900ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen atomic_add_int(&stcb->asoc.refcnt, 1); 37910ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen SCTP_TCB_UNLOCK(stcb); 37920ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen inp->send_callback(stcb->sctp_socket, sb_free_now); 37930ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen SCTP_TCB_LOCK(stcb); 37940ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 37950ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen } 3796fbf619a4618811e6651f5a78cbacc6530797fd7etuexen } 37970ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen } else if (stcb->sctp_socket) { 3798fbf619a4618811e6651f5a78cbacc6530797fd7etuexen#else 37998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 38008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 38010ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#endif 38020612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 38038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 38048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SOCKBUF_LOCK(&stcb->sctp_socket->so_snd); 38078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) { 38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 38090ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_wakeup_log(stcb, 1, SCTP_WAKESND_FROM_SACK); 38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38110612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 38148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 38168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 38178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 38188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assoc was freed while we were unlocked */ 38208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 38218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 38228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket); 38250612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 38268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 38298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) { 38300ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_wakeup_log(stcb, 1, SCTP_NOWAKE_FROM_SACK); 38318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS - Use the congestion control given in the CC module */ 38358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->last_acked_seq != cumack) && (ecne_seen == 0)) { 38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->net_ack2 > 0) { 38388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Karn's rule applies to clearing error count, this 38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is optional. 38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 38428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->error_count = 0; 38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_REACHABLE)) { 38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* addr came good */ 38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_REACHABLE; 38468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 384747674b651417d493ff4e0318113fd7beeef119dbtuexen 0, (void *)net, SCTP_SO_NOT_LOCKED); 38488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == stcb->asoc.primary_destination) { 38508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.alternate) { 38518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* release the alternate, primary is good */ 38528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 38538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 38548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->dest_state & SCTP_ADDR_PF) { 38578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_PF; 38588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 38598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 38608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 38618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Done with this net */ 38628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack = 0; 38638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* restore any doubled timers */ 38658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 38668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO < stcb->asoc.minrto) { 38678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.minrto; 38688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO > stcb->asoc.maxrto) { 38708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.maxrto; 38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, 1, 0, 0); 38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_acked_seq = cumack; 38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->sent_queue)) { 38798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing left in-flight */ 38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 38818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flight_size = 0; 38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->partial_bytes_acked = 0; 38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight = 0; 38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight_count = 0; 38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* RWND update */ 38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = sctp_sbspace_sub(rwnd, 38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); 38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SWS sender side engages */ 38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = 0; 38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd > old_rwnd) { 38968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen win_probe_recovery = 1; 38978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now assure a timer where data is queued at */ 38998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenagain: 39008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen j = 0; 39018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 39028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int to_ticks; 39038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (win_probe_recovery && (net->window_probe)) { 39048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen win_probe_recovered = 1; 39058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 39068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Find first chunk that was used with window probe 39078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and clear the sent 39088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore FREED_MEMORY */ 39108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 39118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->window_probe) { 39128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* move back to data send queue */ 39130ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_window_probe_recovery(stcb, asoc, tp1); 39148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 39158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO == 0) { 39198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 39208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 39218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to_ticks = MSEC_TO_TICKS(net->RTO); 39228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->flight_size) { 39248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen j++; 39258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, 39268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timeout_handler, &net->rxt_timer); 39278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->window_probe) { 39288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->window_probe = 0; 39298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 39318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->window_probe) { 39328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* In window probes we must assure a timer is still running there */ 39338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->window_probe = 0; 39348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { 39358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, 39368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timeout_handler, &net->rxt_timer); 39378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { 39398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 39408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, 39418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); 39428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((j == 0) && 39468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!TAILQ_EMPTY(&asoc->sent_queue)) && 39478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->sent_queue_retran_cnt == 0) && 39488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (win_probe_recovered == 0) && 39498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (done_once == 0)) { 39508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* huh, this should not happen unless all packets 39518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * are PR-SCTP and marked to skip of course. 39528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_fs_audit(asoc)) { 39548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 39558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flight_size = 0; 39568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight = 0; 39588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight_count = 0; 39598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_retran_cnt = 0; 39608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 39618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 39628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_increase(tp1); 39638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_increase(stcb, tp1); 39648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (tp1->sent == SCTP_DATAGRAM_RESEND) { 39658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->sent_queue_retran_cnt); 39668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen done_once = 1; 39708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto again; 39718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**********************************/ 39738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now what about shutdown issues */ 39748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**********************************/ 39758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue)) { 39768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing left on sendqueue.. consider done */ 39778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up */ 39788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->stream_queue_cnt == 1) && 39798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) || 39808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED)) && 39818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->locked_on_sending) 39828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 39838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp; 39848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* I may be in a state where we got 39858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all across.. but cannot write more due 39868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to a shutdown... we abort since the 39878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * user did not indicate EOR in this case. The 39888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sp will be cleaned during free of the asoc. 39898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp = TAILQ_LAST(&((asoc->locked_on_sending)->outqueue), 39918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_streamhead); 39928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sp) && (sp->length == 0)) { 39938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Let cleanup code purge it */ 39948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->msg_is_complete) { 39958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_queue_cnt--; 39968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 39978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT; 39988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->locked_on_sending = NULL; 39998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_queue_cnt--; 40008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) && 40048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->stream_queue_cnt == 0)) { 40058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { 40068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Need to abort here */ 40078f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 40088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 40098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen abort_out_now: 40108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_now = 1; 40118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX */ 40128f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 40138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24; 40148f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 40158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 40168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netp; 40177988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 40188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 40198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 40208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 40218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); 40238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 40248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_timers_for_shutdown(stcb); 40258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->alternate) { 40268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp = asoc->alternate; 40278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 40288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp = asoc->primary_destination; 40298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown(stcb, netp); 40318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, 40328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, netp); 40338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 40348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, netp); 40358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) && 40378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->stream_queue_cnt == 0)) { 40388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netp; 40397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 40408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { 40418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto abort_out_now; 40428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 40448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 40458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 40468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_timers_for_shutdown(stcb); 40477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (asoc->alternate) { 40487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->alternate; 40497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } else { 40507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->primary_destination; 40517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } 40527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_send_shutdown_ack(stcb, netp); 40538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, 40548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, netp); 40558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*********************************************/ 40588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Here we perform PR-SCTP procedures */ 40598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* (section 4.2) */ 40608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*********************************************/ 40618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* C1. update advancedPeerAckPoint */ 40628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(cumack, asoc->advanced_peer_ack_point)) { 40638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point = cumack; 40648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* PR-Sctp issues need to be addressed too */ 40668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) { 40678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *lchk; 40688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t old_adv_peer_ack_point; 4069000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 40708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_adv_peer_ack_point = asoc->advanced_peer_ack_point; 40718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lchk = sctp_try_advance_peer_ack_point(stcb, asoc); 40728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* C3. See if we need to send a Fwd-TSN */ 40738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cumack)) { 40748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 40758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ISSUE with ECN, see FWD-TSN processing. 40768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 40778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) { 40788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_forward_tsn(stcb, asoc); 40798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (lchk) { 40808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* try to FR fwd-tsn's that get lost too */ 40818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk->rec.data.fwd_tsn_cnt >= 3) { 40828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_forward_tsn(stcb, asoc); 40838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk) { 40878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assure a timer is up */ 40888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, 40898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, lchk->whoTo); 40908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_RWND_LOGGING_ENABLE) { 40938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_SACK_RWND_UPDATE, 40948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rwnd, 40958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd, 40968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_flight, 40978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_output_queue_size); 40988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 41008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 41028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, 41030ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sctp_tcb *stcb, 41048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup, 41058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *abort_now, uint8_t flags, 41068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t cum_ack, uint32_t rwnd, int ecne_seen) 41078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 41088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 41098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1, *tp2; 41108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t last_tsn, biggest_tsn_acked, biggest_tsn_newly_acked, this_sack_lowest_newack; 41118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t wake_him = 0; 41128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t send_s = 0; 41138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen long j; 41148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int accum_moved = 0; 41158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int will_exit_fast_recovery = 0; 41168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t a_rwnd, old_rwnd; 41178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int win_probe_recovery = 0; 41188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int win_probe_recovered = 0; 41198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net = NULL; 41208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int done_once; 4121b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int rto_ok = 1; 41228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t reneged_all = 0; 41238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t cmt_dac_flag; 41248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 41258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we take any chance we can to service our queues since we cannot 41268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * get awoken when the socket is read from :< 41278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 41298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now perform the actual SACK handling: 1) Verify that it is not an 41308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * old sack, if so discard. 2) If there is nothing left in the send 41318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue (cum-ack is equal to last acked) then you have a duplicate 41328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * too, update any rwnd change and verify no timers are running. 41338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * then return. 3) Process any new consequtive data i.e. cum-ack 41348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * moved process these first and note that it moved. 4) Process any 41358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sack blocks. 5) Drop any acked from the queue. 6) Check for any 41368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * revoked blocks and mark. 7) Update the cwnd. 8) Nothing left, 41378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sync up flightsizes and things, stop all timers and also check 41388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for shutdown_pending state. If so then go ahead and send off the 41398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * shutdown. If in shutdown recv, send off the shutdown-ack and 41408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * start that timer, Ret. 9) Strike any non-acked things and do FR 41418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * procedure if needed being sure to set the FR flag. 10) Do pr-sctp 41428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * procedures. 11) Apply any FR penalties. 12) Assure we will SACK 41438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if in shutdown_recv state. 41448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 41468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* CMT DAC algo */ 41478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_sack_lowest_newack = 0; 41488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_slowpath_sack); 41498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_tsn = cum_ack; 41508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cmt_dac_flag = flags & SCTP_SACK_CMT_DAC; 41518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS 41528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cum_ack; 41538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cumack_log_at++; 41548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cumack_log_at > SCTP_TSN_LOG_SIZE) { 41558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cumack_log_at = 0; 41568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 41588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd = rwnd; 41598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) { 41618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_SACK_LOG_NORMAL, cum_ack, 41628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd); 41638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_rwnd = stcb->asoc.peers_rwnd; 41668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 41678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 41688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 41698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 41708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INDATA, 41718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 41728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 41748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 41758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 41768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(asoc->last_acked_seq, 41778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, 41788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 41798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_seg, 41808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_dup, 41818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_NEW_SACK); 41828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((num_dup) && (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE)) { 41848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t i; 41858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t *dupdata, dblock; 41868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < num_dup; i++) { 41888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen dupdata = (uint32_t *)sctp_m_getptr(m, offset_dup + i * sizeof(uint32_t), 41898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(uint32_t), (uint8_t *)&dblock); 41908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (dupdata == NULL) { 41918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 41928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_fr(*dupdata, 0, 0, SCTP_FR_DUPED); 41948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) { 41978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* reality check */ 41988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->sent_queue)) { 41998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = TAILQ_LAST(&asoc->sent_queue, 42008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctpchunk_listhead); 42018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_s = tp1->rec.data.TSN_seq + 1; 42028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 42038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = NULL; 42048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_s = asoc->sending_seq; 42058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(cum_ack, send_s)) { 42078f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 42088f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 42098f9e45fea288542b24a6bda01269c6fc184d991at 42108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 42118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no way, we have not even sent this TSN out yet. 42128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Peer is hopelessly messed up with us. 42138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 421447a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("NEW cum_ack:%x send_s:%x is smaller or equal\n", 421547a306d634abf33223ef347472c4b1cd441d139ftuexen cum_ack, send_s); 42168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1) { 421747a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("Got send_s from tsn:%x + 1 of tp1:%p\n", 4218ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t tp1->rec.data.TSN_seq, (void *)tp1); 42198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hopeless_peer: 42218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_now = 1; 42228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX */ 42238f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x", 42248f9e45fea288542b24a6bda01269c6fc184d991at cum_ack, send_s); 42258f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 42268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; 42278f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 42288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 42298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**********************/ 42328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 1) check the range */ 42338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**********************/ 42348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->last_acked_seq, last_tsn)) { 42358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* acking something behind */ 42368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 42378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update the Rwnd of the peer */ 42408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->sent_queue) && 42418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&asoc->send_queue) && 42428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->stream_queue_cnt == 0)) { 42438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing left on send/sent and strmq */ 42448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) { 42458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK, 42468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd, 0, 0, a_rwnd); 42478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = a_rwnd; 42498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->sent_queue_retran_cnt) { 42508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_retran_cnt = 0; 42518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 42538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SWS sender side engages */ 42548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = 0; 42558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop any timers */ 42578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 42588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 42598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26); 42608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->partial_bytes_acked = 0; 42618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flight_size = 0; 42628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight = 0; 42648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight_count = 0; 42658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 42668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 42688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We init netAckSz and netAckSz2 to 0. These are used to track 2 42698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * things. The total byte count acked is tracked in netAckSz AND 42708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * netAck2 is used to track the total bytes acked that are un- 42718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * amibguious and were never retransmitted. We track these on a per 42728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * destination address basis. 42738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 42748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 42758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(cum_ack, net->cwr_window_tsn)) { 42768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Drag along the window_tsn for cwr's */ 42778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->cwr_window_tsn = cum_ack; 42788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->prev_cwnd = net->cwnd; 42808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack = 0; 42818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack2 = 0; 42828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 42848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: Reset CUC and Fast recovery algo variables before 42858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SACK processing 42868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 42878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->new_pseudo_cumack = 0; 42888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->will_exit_fast_recovery = 0; 42898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) { 42908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack)(stcb, net); 42918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the new consecutive TSN first */ 42948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 42958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(last_tsn, tp1->rec.data.TSN_seq)) { 42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent != SCTP_DATAGRAM_UNSENT) { 42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen accum_moved = 1; 42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_ACKED) { 42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If it is less than ACKED, it is 43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now no-longer in flight. Higher 43028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * values may occur during marking 43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1->whoTo->dest_state & 43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_UNCONFIRMED) && 43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (tp1->snd_count < 2)) { 43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If there was no retran 43098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and the address is 43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * un-confirmed and we sent 43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * there and are now 43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sacked.. its confirmed, 43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * mark it so. 43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 43158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->dest_state &= 43168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ~SCTP_ADDR_UNCONFIRMED; 43178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 43198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 43208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA, 43218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(tp1); 43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, tp1); 43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { 43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo, 43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1); 43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack += tp1->send_size; 43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* CMT SFR and DAC algos */ 43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_sack_lowest_newack = tp1->rec.data.TSN_seq; 43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->saw_newack = 1; 43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->snd_count < 2) { 43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * True non-retransmited 43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chunk 43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->net_ack2 += 43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->send_size; 43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update RTO too? */ 43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->do_rtt) { 43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (rto_ok) { 43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->RTO = 43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_calculate_rto(stcb, 43528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc, tp1->whoTo, 43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &tp1->sent_rcv_time, 43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_align_safe_nocopy, 43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_DATA); 43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rto_ok = 0; 43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo->rto_needed == 0) { 43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->rto_needed = 1; 43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->do_rtt = 0; 43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: CUCv2 algorithm. From the 43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cumack'd TSNs, for each TSN being 43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * acked for the first time, set the 43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * following variables for the 43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * corresp destination. 43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new_pseudo_cumack will trigger a 43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cwnd update. 43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find_(rtx_)pseudo_cumack will 43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * trigger search for the next 43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * expected (rtx-)pseudo-cumack. 43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->new_pseudo_cumack = 1; 43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_pseudo_cumack = 1; 43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->find_rtx_pseudo_cumack = 1; 43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(asoc->last_acked_seq, 43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, 43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_TSN_ACKED); 43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { 43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); 43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND) { 43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->sent_queue_retran_cnt); 43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xB3, 43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->sent_queue_retran_cnt & 0x000000ff)); 43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.chunk_was_revoked) { 44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* deflate the cwnd */ 44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->cwnd -= tp1->book_size; 44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.chunk_was_revoked = 0; 44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 440560db5740d3bcc26fd4ebc19b6b0652506994fd14t if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) { 440660db5740d3bcc26fd4ebc19b6b0652506994fd14t tp1->sent = SCTP_DATAGRAM_ACKED; 440760db5740d3bcc26fd4ebc19b6b0652506994fd14t } 44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen biggest_tsn_newly_acked = biggest_tsn_acked = last_tsn; 44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* always set this up to cum-ack */ 44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->this_sack_highest_gap = last_tsn; 44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((num_seg > 0) || (num_nr_seg > 0)) { 44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: SFR algo (and HTNA) - this_sack_highest_newack has 44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to be greater than the cumack. Also reset saw_newack to 0 44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for all dests. 44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->saw_newack = 0; 44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->this_sack_highest_newack = last_tsn; 44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * thisSackHighestGap will increase while handling NEW 44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * segments this_sack_highest_newack will increase while 44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handling NEWLY ACKED chunks. this_sack_lowest_newack is 44338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * used for CMT DAC algo. saw_newack will also change. 44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_segments(m, &offset_seg, stcb, asoc, last_tsn, &biggest_tsn_acked, 44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &biggest_tsn_newly_acked, &this_sack_lowest_newack, 44370ac02f34d6041cd0018437596a5a9a94685e6919tuexen num_seg, num_nr_seg, &rto_ok)) { 44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wake_him++; 44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) { 44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * validate the biggest_tsn_acked in the gap acks if 44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * strict adherence is wanted. 44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(biggest_tsn_acked, send_s)) { 44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * peer is either confused or we are under 44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * attack. We must abort. 44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 445047a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("Hopeless peer! biggest_tsn_acked:%x largest seq:%x\n", 445147a306d634abf33223ef347472c4b1cd441d139ftuexen biggest_tsn_acked, send_s); 44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto hopeless_peer; 44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*******************************************/ 44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* cancel ALL T3-send timer if accum moved */ 44588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*******************************************/ 44598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->sctp_cmt_on_off > 0) { 44608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 44618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->new_pseudo_cumack) 44628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 44638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, 44648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INDATA + SCTP_LOC_27); 44658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (accum_moved) { 44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28); 44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /********************************************/ 44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* drop the acked chunks from the sentqueue */ 44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /********************************************/ 44788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_acked_seq = cum_ack; 44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) { 44818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cum_ack)) { 44828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 448460db5740d3bcc26fd4ebc19b6b0652506994fd14t if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) { 4485446be8e8a472f6e688885674d2430118fc4be5d7t if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) { 4486446be8e8a472f6e688885674d2430118fc4be5d7t asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--; 4487446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS 4488446be8e8a472f6e688885674d2430118fc4be5d7t } else { 4489446be8e8a472f6e688885674d2430118fc4be5d7t panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); 4490446be8e8a472f6e688885674d2430118fc4be5d7t#endif 4491446be8e8a472f6e688885674d2430118fc4be5d7t } 44928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); 449437a477684cd9fd2f02430cc2a9822c8c160973ect if (PR_SCTP_ENABLED(tp1->flags)) { 44958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->pr_sctp_cnt != 0) 44968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pr_sctp_cnt--; 44978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt--; 44998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->data) { 45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_bufspace(stcb, asoc, tp1, 1); 45028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(tp1->data); 45038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->data = NULL; 45048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) { 45058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_cnt_removeable--; 45068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { 45098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_sack(asoc->last_acked_seq, 45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, 45118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq, 45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 45148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LOG_FREE_SENT); 45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, tp1, SCTP_SO_NOT_LOCKED); 45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wake_him++; 45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->sent_queue) && (asoc->total_flight > 0)) { 45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 45218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Warning flight size is postive and should be 0"); 45228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Warning flight size incorrect should be 0 is %d\n", 45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight); 45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight = 0; 45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45290ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#if defined(__Userspace__) 45300ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (stcb->sctp_ep->recv_callback) { 45310ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (stcb->sctp_socket) { 45320ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen uint32_t inqueue_bytes, sb_free_now; 45330ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen struct sctp_inpcb *inp; 45340ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen 45350ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen inp = stcb->sctp_ep; 4536fbf619a4618811e6651f5a78cbacc6530797fd7etuexen inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk)); 4537283ff606e8e0d3d1880be501ae236653224cfa25tuexen sb_free_now = SCTP_SB_LIMIT_SND(stcb->sctp_socket) - (inqueue_bytes + stcb->asoc.sb_send_resv); 45380ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen 45390ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen /* check if the amount free in the send socket buffer crossed the threshold */ 45400ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (inp->send_callback && 45410ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen (((inp->send_sb_threshold > 0) && (sb_free_now >= inp->send_sb_threshold)) || 45420ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen (inp->send_sb_threshold == 0))) { 45430ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen atomic_add_int(&stcb->asoc.refcnt, 1); 45440ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen SCTP_TCB_UNLOCK(stcb); 45450ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen inp->send_callback(stcb->sctp_socket, sb_free_now); 45460ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen SCTP_TCB_LOCK(stcb); 45470ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 45480ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen } 4549fbf619a4618811e6651f5a78cbacc6530797fd7etuexen } 45500ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen } else if ((wake_him) && (stcb->sctp_socket)) { 4551fbf619a4618811e6651f5a78cbacc6530797fd7etuexen#else 45528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 45538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((wake_him) && (stcb->sctp_socket)) { 45540ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#endif 45550612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 45568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 45578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SOCKBUF_LOCK(&stcb->sctp_socket->so_snd); 45608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) { 45610ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_wakeup_log(stcb, wake_him, SCTP_WAKESND_FROM_SACK); 45628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45630612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 45648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 45668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 45688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 45698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 45708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assoc was freed while we were unlocked */ 45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket); 45770612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 45788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 45798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 45818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) { 45820ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_wakeup_log(stcb, wake_him, SCTP_NOWAKE_FROM_SACK); 45838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fast_retran_loss_recovery && accum_moved) { 45878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(asoc->last_acked_seq, asoc->fast_recovery_tsn)) { 45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Setup so we will exit RFC2582 fast recovery */ 45898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen will_exit_fast_recovery = 1; 45908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Check for revoked fragments: 45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if Previous sack - Had no frags then we can't have any revoked if 45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Previous sack - Had frag's then - If we now have frags aka 45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * num_seg > 0 call sctp_check_for_revoked() to tell if peer revoked 45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * some of them. else - The peer revoked all ACKED fragments, since 45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we had some before and now we have NONE. 46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_seg) { 46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked); 46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->saw_sack_with_frags = 1; 46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->saw_sack_with_frags) { 46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt_revoked = 0; 46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Peer revoked all dg's marked or acked */ 46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 46108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_ACKED) { 46118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent = SCTP_DATAGRAM_SENT; 46128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 46138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE, 46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 46158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)tp1->whoTo, 46178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_increase(tp1); 46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_increase(stcb, tp1); 46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.chunk_was_revoked = 1; 46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * To ensure that this increase in 46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flightsize, which is artificial, 46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does not throttle the sender, we 46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * also increase the cwnd 46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * artificially. 46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->cwnd += tp1->book_size; 46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_revoked++; 46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cnt_revoked) { 46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen reneged_all = 1; 46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->saw_sack_with_frags = 0; 46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_nr_seg > 0) 46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->saw_sack_with_nr_frags = 1; 46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->saw_sack_with_nr_frags = 0; 46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS - Use the congestion control given in the CC module */ 46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ecne_seen == 0) { 46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 46468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->net_ack2 > 0) { 46478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 46488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Karn's rule applies to clearing error count, this 46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is optional. 46508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->error_count = 0; 46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_REACHABLE)) { 46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* addr came good */ 46548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_REACHABLE; 46558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 465647674b651417d493ff4e0318113fd7beeef119dbtuexen 0, (void *)net, SCTP_SO_NOT_LOCKED); 46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == stcb->asoc.primary_destination) { 46608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.alternate) { 46618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* release the alternate, primary is good */ 46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->dest_state & SCTP_ADDR_PF) { 46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_PF; 46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Done with this net */ 46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack = 0; 46748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* restore any doubled timers */ 46768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 46778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO < stcb->asoc.minrto) { 46788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.minrto; 46798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->RTO > stcb->asoc.maxrto) { 46818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = stcb->asoc.maxrto; 46828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery); 46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->sent_queue)) { 46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing left in-flight */ 46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop all timers */ 46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30); 46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flight_size = 0; 46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->partial_bytes_acked = 0; 46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight = 0; 46988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight_count = 0; 46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 47018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**********************************/ 47028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now what about shutdown issues */ 47038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**********************************/ 47048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue)) { 47058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing left on sendqueue.. consider done */ 47068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) { 47078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK, 47088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd, 0, 0, a_rwnd); 47098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = a_rwnd; 47118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 47128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SWS sender side engages */ 47138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = 0; 47148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up */ 47168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->stream_queue_cnt == 1) && 47178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) || 47188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED)) && 47198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->locked_on_sending) 47208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 47218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp; 47228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* I may be in a state where we got 47238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all across.. but cannot write more due 47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to a shutdown... we abort since the 47258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * user did not indicate EOR in this case. 47268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp = TAILQ_LAST(&((asoc->locked_on_sending)->outqueue), 47288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_streamhead); 47298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sp) && (sp->length == 0)) { 47308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->locked_on_sending = NULL; 47318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->msg_is_complete) { 47328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_queue_cnt--; 47338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 47348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT; 47358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_queue_cnt--; 47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) && 47408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->stream_queue_cnt == 0)) { 47418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { 47428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Need to abort here */ 47438f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 47448f9e45fea288542b24a6bda01269c6fc184d991at 47458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen abort_out_now: 47468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_now = 1; 47478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX */ 47488f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 47498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31; 47508f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 47518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 47528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 47538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netp; 47547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 47558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 47568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 47578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 47588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); 47608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 47618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_timers_for_shutdown(stcb); 47627988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (asoc->alternate) { 47637988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->alternate; 47647988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } else { 47657988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->primary_destination; 47667988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } 47678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown(stcb, netp); 47688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, 47698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, netp); 47708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 47718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, netp); 47728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 47748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) && 47758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->stream_queue_cnt == 0)) { 47768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netp; 47777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 47788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { 47798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto abort_out_now; 47808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 47828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 47838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 47848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_timers_for_shutdown(stcb); 47857988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (asoc->alternate) { 47867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->alternate; 47877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } else { 47887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->primary_destination; 47897988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } 47907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_send_shutdown_ack(stcb, netp); 47918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, 47928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, netp); 47938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 47948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now here we are going to recycle net_ack for a different use... 47988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * HEADS UP. 47998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 48018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->net_ack = 0; 48028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 48058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT DAC algorithm: If SACK DAC flag was 0, then no extra marking 48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to be done. Setting this_sack_lowest_newack to the cum_ack will 48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * automatically ensure that. 48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->sctp_cmt_on_off > 0) && 48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_cmt_use_dac) && 48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (cmt_dac_flag == 0)) { 48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen this_sack_lowest_newack = cum_ack; 48138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((num_seg > 0) || (num_nr_seg > 0)) { 48158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_strike_gap_ack_chunks(stcb, asoc, biggest_tsn_acked, 48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen biggest_tsn_newly_acked, this_sack_lowest_newack, accum_moved); 48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS - Use the congestion control given in the CC module */ 48198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cc_functions.sctp_cwnd_update_after_fr(stcb, asoc); 48208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now are we exiting loss recovery ? */ 48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (will_exit_fast_recovery) { 48238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok, we must exit fast recovery */ 48248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fast_retran_loss_recovery = 0; 48258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->sat_t3_loss_recovery) && 48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GE(asoc->last_acked_seq, asoc->sat_t3_recovery_tsn)) { 48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* end satellite t3 loss recovery */ 48298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sat_t3_loss_recovery = 0; 48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT Fast recovery 48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->will_exit_fast_recovery) { 48368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok, we must exit fast recovery */ 48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->fast_retran_loss_recovery = 0; 48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Adjust and set the new rwnd value */ 48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) { 48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK, 48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd, asoc->total_flight, (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)), a_rwnd); 48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = sctp_sbspace_sub(a_rwnd, 48478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); 48488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 48498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SWS sender side engages */ 48508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = 0; 48518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peers_rwnd > old_rwnd) { 48538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen win_probe_recovery = 1; 48548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now we must setup so we have a timer up for anyone with 48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * outstanding data. 48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen done_once = 0; 48618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenagain: 48628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen j = 0; 48638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 48648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (win_probe_recovery && (net->window_probe)) { 48658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen win_probe_recovered = 1; 48668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 48678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Find first chunk that was used with 48688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * window probe and clear the event. Put 48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it back into the send queue as if has 48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not been sent. 48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 48738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->window_probe) { 48740ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_window_probe_recovery(stcb, asoc, tp1); 48758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 48768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->flight_size) { 48808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen j++; 48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { 48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, 48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, net); 48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->window_probe) { 48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->window_probe = 0; 48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->window_probe) { 48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* In window probes we must assure a timer is still running there */ 48918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { 48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, 48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, net); 48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { 48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, 48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); 49008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((j == 0) && 49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!TAILQ_EMPTY(&asoc->sent_queue)) && 49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->sent_queue_retran_cnt == 0) && 49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (win_probe_recovered == 0) && 49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (done_once == 0)) { 49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* huh, this should not happen unless all packets 49098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * are PR-SCTP and marked to skip of course. 49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_fs_audit(asoc)) { 49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flight_size = 0; 49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight = 0; 49168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->total_flight_count = 0; 49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sent_queue_retran_cnt = 0; 49188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_increase(tp1); 49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_increase(stcb, tp1); 49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (tp1->sent == SCTP_DATAGRAM_RESEND) { 49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(asoc->sent_queue_retran_cnt); 49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen done_once = 1; 49288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto again; 49298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*********************************************/ 49318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Here we perform PR-SCTP procedures */ 49328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* (section 4.2) */ 49338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*********************************************/ 49348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* C1. update advancedPeerAckPoint */ 49358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(cum_ack, asoc->advanced_peer_ack_point)) { 49368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point = cum_ack; 49378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* C2. try to further move advancedPeerAckPoint ahead */ 49398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) { 49408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *lchk; 49418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t old_adv_peer_ack_point; 4942000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 49438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_adv_peer_ack_point = asoc->advanced_peer_ack_point; 49448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lchk = sctp_try_advance_peer_ack_point(stcb, asoc); 49458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* C3. See if we need to send a Fwd-TSN */ 49468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cum_ack)) { 49478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 49488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ISSUE with ECN, see FWD-TSN processing. 49498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 49508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) { 49518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FWD_TSN_CHECK, 49528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0xee, cum_ack, asoc->advanced_peer_ack_point, 49538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_adv_peer_ack_point); 49548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) { 49568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_forward_tsn(stcb, asoc); 49578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (lchk) { 49588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* try to FR fwd-tsn's that get lost too */ 49598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk->rec.data.fwd_tsn_cnt >= 3) { 49608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_forward_tsn(stcb, asoc); 49618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk) { 49658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assure a timer is up */ 49668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, 49678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, lchk->whoTo); 49688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_RWND_LOGGING_ENABLE) { 49718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_SACK_RWND_UPDATE, 49728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd, 49738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd, 49748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_flight, 49758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_output_queue_size); 49768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 49788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 49800ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp, int *abort_flag) 49818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 49828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Copy cum-ack */ 49838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t cum_ack, a_rwnd; 49848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack = ntohl(cp->cumulative_tsn_ack); 49868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Arrange so a_rwnd does NOT change */ 49878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd = stcb->asoc.peers_rwnd + stcb->asoc.total_flight; 49888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now call the express sack handling */ 49908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_express_handle_sack(stcb, cum_ack, a_rwnd, abort_flag, 0); 49918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 49928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 49948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, 49958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_in *strmin) 49968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 49978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *nctl; 49988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 49998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t tt; 5000000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 50018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 50028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tt = strmin->last_sequence_delivered; 50038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 50048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * First deliver anything prior to and including the stream no that 50058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * came in 50068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) { 50088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SSN_GE(tt, ctl->sinfo_ssn)) { 50098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this is deliverable now */ 50108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&strmin->inqueue, ctl, next); 50118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* subtract pending on streams */ 50128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams -= ctl->length; 50138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 50148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* deliver it to at least the delivery-q */ 50158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 50168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); 50178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 50188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl, 50198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); 50208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 50228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more delivery now. */ 50238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 50278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now we must deliver things in queue the normal way if any are 50288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now ready. 50298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tt = strmin->last_sequence_delivered + 1; 50318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) { 50328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tt == ctl->sinfo_ssn) { 50338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this is deliverable now */ 50348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&strmin->inqueue, ctl, next); 50358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* subtract pending on streams */ 50368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams -= ctl->length; 50378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 50388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* deliver it to at least the delivery-q */ 50398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strmin->last_sequence_delivered = ctl->sinfo_ssn; 50408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 50418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); 50428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 50438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl, 50448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); 50458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tt = strmin->last_sequence_delivered + 1; 50488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 50498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 50538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 50558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb, 50568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc, 50578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t stream, uint16_t seq) 50588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 50598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 50608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For each one on here see if we need to toss it */ 50628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 50638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For now large messages held on the reasmqueue that are 50648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * complete will be tossed too. We could in theory do more 50658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * work to spin through and stop after dumping one msg aka 50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * seeing the start of a new msg at the head, and call the 50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delivery function... to see if it can be delivered... But 50688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for now we just dump everything on the queue. 50698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Do not toss it if on a different stream or 50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * marked for unordered delivery in which case 50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the stream sequence number has no meaning. 50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.stream_number != stream) || 50768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)) { 50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 50788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.stream_seq == seq) { 50808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* It needs to be tossed */ 50818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 50828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(chk->rec.data.TSN_seq, asoc->tsn_last_delivered)) { 50838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = chk->rec.data.TSN_seq; 50848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_of_pdapi = chk->rec.data.stream_number; 50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->ssn_of_pdapi = chk->rec.data.stream_seq; 50868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragment_flags = chk->rec.data.rcv_flags; 50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue -= chk->send_size; 50898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_reasm_queue); 50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Clear up any stream problem */ 50928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED && 50938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SSN_GT(chk->rec.data.stream_seq, asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered)) { 50948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 50958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We must dump forward this streams 50968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sequence number if the chunk is 50978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not unordered that is being 50988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * skipped. There is a chance that 50998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if the peer does not include the 51008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * last fragment in its FWD-TSN we 51018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * WILL have a problem here since 51028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * you would have a partial chunk in 51038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue that may not be 51048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deliverable. Also if a Partial 51058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delivery API as started the user 51068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * may get a partial chunk. The next 51078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * read returning a new chunk... 51088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * really ugly but I see no way 51098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * around it! Maybe a notify?? 51108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 51118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq; 51128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 51148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 51158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 51168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 51188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_SSN_GT(chk->rec.data.stream_seq, seq)) { 51198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If the stream_seq is > than the purging one, we are done */ 51208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 51248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 51278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_forward_tsn(struct sctp_tcb *stcb, 51288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_forward_tsn_chunk *fwd, 51298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *abort_flag, struct mbuf *m ,int offset) 51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* The pr-sctp fwd tsn */ 51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here we will perform all the data receiver side steps for 51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * processing FwdTSN, as required in by pr-sctp draft: 51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Assume we get FwdTSN(x): 51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1) update local cumTSN to x 2) try to further advance cumTSN to x + 51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * others we have 3) examine and update re-ordering queue on 51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pr-in-streams 4) clean up re-assembly queue 5) Send a sack to 51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * report where we are. 51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t new_cum_tsn, gap; 51450ac02f34d6041cd0018437596a5a9a94685e6919tuexen unsigned int i, fwd_sz, m_size; 51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t str_seq; 51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_in *strm; 51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *sv; 51508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) { 51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, 51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Bad size too small/big fwd-tsn\n"); 51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_size = (stcb->asoc.mapping_array_size << 3); 51588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*************************************************************/ 51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 1. Here we update local cumTSN and shift the bitmap array */ 51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*************************************************************/ 51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_cum_tsn = ntohl(fwd->new_cumulative_tsn); 51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(asoc->cumulative_tsn, new_cum_tsn)) { 51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Already got there ... */ 51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now we know the new TSN is more advanced, let's find the actual 51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * gap 51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn); 51728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cumulative_tsn = new_cum_tsn; 51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (gap >= m_size) { 51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) { 51758f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 51768f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 51778f9e45fea288542b24a6bda01269c6fc184d991at 51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * out of range (of single byte chunks in the rwnd I 51808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * give out). This must be an attacker. 51818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 51828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_flag = 1; 51838f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), 51848f9e45fea288542b24a6bda01269c6fc184d991at "New cum ack %8.8x too high, highest TSN %8.8x", 51858f9e45fea288542b24a6bda01269c6fc184d991at new_cum_tsn, asoc->highest_tsn_inside_map); 51868f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 51878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_33; 51888f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 51898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 51908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_fwdtsn_map_over); 5192000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 51938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 51948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array_base_tsn = new_cum_tsn + 1; 51958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = new_cum_tsn; 5196000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 51978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 51988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = new_cum_tsn; 5199000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 52008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 52018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 52028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 52058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i <= gap; i++) { 52068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, i) && 52078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, i)) { 52088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); 52098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(asoc->mapping_array_base_tsn + i, asoc->highest_tsn_inside_nr_map)) { 52108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = asoc->mapping_array_base_tsn + i; 52118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*************************************************************/ 52168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 2. Clear up re-assembly queue */ 52178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*************************************************************/ 52188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * First service it if pd-api is up, just in case we can progress it 52208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * forward 52218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->fragmented_delivery_inprogress) { 52238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_service_reassembly(stcb, asoc); 52248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For each one on here see if we need to toss it */ 52268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For now large messages held on the reasmqueue that are 52288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * complete will be tossed too. We could in theory do more 52298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * work to spin through and stop after dumping one msg aka 52308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * seeing the start of a new msg at the head, and call the 52318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delivery function... to see if it can be delivered... But 52328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for now we just dump everything on the queue. 52338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 52358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(new_cum_tsn, chk->rec.data.TSN_seq)) { 52368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* It needs to be tossed */ 52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 52388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(chk->rec.data.TSN_seq, asoc->tsn_last_delivered)) { 52398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = chk->rec.data.TSN_seq; 52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_of_pdapi = chk->rec.data.stream_number; 52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->ssn_of_pdapi = chk->rec.data.stream_seq; 52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragment_flags = chk->rec.data.rcv_flags; 52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue -= chk->send_size; 52458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_reasm_queue); 52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Clear up any stream problem */ 52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED && 52498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SSN_GT(chk->rec.data.stream_seq, asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered)) { 52508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We must dump forward this streams 52528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sequence number if the chunk is 52538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not unordered that is being 52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * skipped. There is a chance that 52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if the peer does not include the 52568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * last fragment in its FWD-TSN we 52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * WILL have a problem here since 52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * you would have a partial chunk in 52598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue that may not be 52608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deliverable. Also if a Partial 52618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delivery API as started the user 52628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * may get a partial chunk. The next 52638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * read returning a new chunk... 52648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * really ugly but I see no way 52658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * around it! Maybe a notify?? 52668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq; 52688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 52708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 52718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 52728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 52748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok we have gone beyond the end of the 52778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * fwd-tsn's mark. 52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 52808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*******************************************************/ 52838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 3. Update the PR-stream re-ordering queues and fix */ 52848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delivery issues as needed. */ 52858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*******************************************************/ 52868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fwd_sz -= sizeof(*fwd); 52878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m && fwd_sz) { 52888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* New method. */ 52898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int num_str; 52908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_strseq *stseq, strseqbuf; 52918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(*fwd); 52928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_LOCK(stcb->sctp_ep); 52948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_str = fwd_sz / sizeof(struct sctp_strseq); 52958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < num_str; i++) { 52968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t st; 52978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stseq = (struct sctp_strseq *)sctp_m_getptr(m, offset, 52988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_strseq), 52998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)&strseqbuf); 53008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(struct sctp_strseq); 53018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stseq == NULL) { 53028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Convert */ 53058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen st = ntohs(stseq->stream); 53068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stseq->stream = st; 53078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen st = ntohs(stseq->sequence); 53088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stseq->sequence = st; 53098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now process */ 53118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 53138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok we now look for the stream/seq on the read queue 53148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * where its not all delivered. If we find it we transmute the 53158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * read entry into a PDI_ABORTED. 53168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 53178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stseq->stream >= asoc->streamincnt) { 53188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* screwed up streams, stop! */ 53198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->str_of_pdapi == stseq->stream) && 53228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->ssn_of_pdapi == stseq->sequence)) { 53238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If this is the one we were partially delivering 53248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now then we no longer are. Note this will change 53258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with the reassembly re-write. 53268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 53278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->fragmented_delivery_inprogress = 0; 53288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flush_reassm_for_str_seq(stcb, asoc, stseq->stream, stseq->sequence); 53308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) { 53318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ctl->sinfo_stream == stseq->stream) && 53328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ctl->sinfo_ssn == stseq->sequence)) { 53338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen str_seq = (stseq->stream << 16) | stseq->sequence; 53348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl->end_added = 1; 53358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl->pdapi_aborted = 1; 53368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sv = stcb->asoc.control_pdapi; 53378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi = ctl; 53388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION, 53398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 53408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PARTIAL_DELIVERY_ABORTED, 53418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void *)&str_seq, 53428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 53438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi = sv; 53448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((ctl->sinfo_stream == stseq->stream) && 53468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SSN_GT(ctl->sinfo_ssn, stseq->sequence)) { 53478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are past our victim SSN */ 53488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm = &asoc->strmin[stseq->stream]; 53528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SSN_GT(stseq->sequence, strm->last_sequence_delivered)) { 53538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Update the sequence number */ 53548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strm->last_sequence_delivered = stseq->sequence; 53558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now kick the stream the new way */ 53578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 53588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_kick_prsctp_reorder_queue(stcb, strm); 53598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 53618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 53638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now slide thing forward. 53648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 53658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_slide_mapping_arrays(stcb); 53668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->reasmqueue)) { 53688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now lets kick out and check for more fragmented delivery */ 53698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 53708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_deliver_reasm_check(stcb, &stcb->asoc); 53718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 5373