18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* SCTP kernel implementation 38c2ecf20Sopenharmony_ci * (C) Copyright IBM Corp. 2001, 2004 48c2ecf20Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 58c2ecf20Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 68c2ecf20Sopenharmony_ci * Copyright (c) 2001-2003 Intel Corp. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This file is part of the SCTP kernel implementation 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * These functions implement the sctp_outq class. The outqueue handles 118c2ecf20Sopenharmony_ci * bundling and queueing of outgoing SCTP chunks. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Please send any bug reports or fixes you make to the 148c2ecf20Sopenharmony_ci * email address(es): 158c2ecf20Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Written or modified by: 188c2ecf20Sopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 198c2ecf20Sopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 208c2ecf20Sopenharmony_ci * Perry Melange <pmelange@null.cc.uic.edu> 218c2ecf20Sopenharmony_ci * Xingang Guo <xingang.guo@intel.com> 228c2ecf20Sopenharmony_ci * Hui Huang <hui.huang@nokia.com> 238c2ecf20Sopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 248c2ecf20Sopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/types.h> 308c2ecf20Sopenharmony_ci#include <linux/list.h> /* For struct list_head */ 318c2ecf20Sopenharmony_ci#include <linux/socket.h> 328c2ecf20Sopenharmony_ci#include <linux/ip.h> 338c2ecf20Sopenharmony_ci#include <linux/slab.h> 348c2ecf20Sopenharmony_ci#include <net/sock.h> /* For skb_set_owner_w */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <net/sctp/sctp.h> 378c2ecf20Sopenharmony_ci#include <net/sctp/sm.h> 388c2ecf20Sopenharmony_ci#include <net/sctp/stream_sched.h> 398c2ecf20Sopenharmony_ci#include <trace/events/sctp.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* Declare internal functions here. */ 428c2ecf20Sopenharmony_cistatic int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn); 438c2ecf20Sopenharmony_cistatic void sctp_check_transmitted(struct sctp_outq *q, 448c2ecf20Sopenharmony_ci struct list_head *transmitted_queue, 458c2ecf20Sopenharmony_ci struct sctp_transport *transport, 468c2ecf20Sopenharmony_ci union sctp_addr *saddr, 478c2ecf20Sopenharmony_ci struct sctp_sackhdr *sack, 488c2ecf20Sopenharmony_ci __u32 *highest_new_tsn); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic void sctp_mark_missing(struct sctp_outq *q, 518c2ecf20Sopenharmony_ci struct list_head *transmitted_queue, 528c2ecf20Sopenharmony_ci struct sctp_transport *transport, 538c2ecf20Sopenharmony_ci __u32 highest_new_tsn, 548c2ecf20Sopenharmony_ci int count_of_newacks); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* Add data to the front of the queue. */ 598c2ecf20Sopenharmony_cistatic inline void sctp_outq_head_data(struct sctp_outq *q, 608c2ecf20Sopenharmony_ci struct sctp_chunk *ch) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct sctp_stream_out_ext *oute; 638c2ecf20Sopenharmony_ci __u16 stream; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci list_add(&ch->list, &q->out_chunk_list); 668c2ecf20Sopenharmony_ci q->out_qlen += ch->skb->len; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci stream = sctp_chunk_stream_no(ch); 698c2ecf20Sopenharmony_ci oute = SCTP_SO(&q->asoc->stream, stream)->ext; 708c2ecf20Sopenharmony_ci list_add(&ch->stream_list, &oute->outq); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* Take data from the front of the queue. */ 748c2ecf20Sopenharmony_cistatic inline struct sctp_chunk *sctp_outq_dequeue_data(struct sctp_outq *q) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci return q->sched->dequeue(q); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Add data chunk to the end of the queue. */ 808c2ecf20Sopenharmony_cistatic inline void sctp_outq_tail_data(struct sctp_outq *q, 818c2ecf20Sopenharmony_ci struct sctp_chunk *ch) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct sctp_stream_out_ext *oute; 848c2ecf20Sopenharmony_ci __u16 stream; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci list_add_tail(&ch->list, &q->out_chunk_list); 878c2ecf20Sopenharmony_ci q->out_qlen += ch->skb->len; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci stream = sctp_chunk_stream_no(ch); 908c2ecf20Sopenharmony_ci oute = SCTP_SO(&q->asoc->stream, stream)->ext; 918c2ecf20Sopenharmony_ci list_add_tail(&ch->stream_list, &oute->outq); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* 958c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 968c2ecf20Sopenharmony_ci * D) If count_of_newacks is greater than or equal to 2 978c2ecf20Sopenharmony_ci * and t was not sent to the current primary then the 988c2ecf20Sopenharmony_ci * sender MUST NOT increment missing report count for t. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_cistatic inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary, 1018c2ecf20Sopenharmony_ci struct sctp_transport *transport, 1028c2ecf20Sopenharmony_ci int count_of_newacks) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci if (count_of_newacks >= 2 && transport != primary) 1058c2ecf20Sopenharmony_ci return 1; 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* 1108c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 1118c2ecf20Sopenharmony_ci * F) If count_of_newacks is less than 2, let d be the 1128c2ecf20Sopenharmony_ci * destination to which t was sent. If cacc_saw_newack 1138c2ecf20Sopenharmony_ci * is 0 for destination d, then the sender MUST NOT 1148c2ecf20Sopenharmony_ci * increment missing report count for t. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_cistatic inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport, 1178c2ecf20Sopenharmony_ci int count_of_newacks) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci if (count_of_newacks < 2 && 1208c2ecf20Sopenharmony_ci (transport && !transport->cacc.cacc_saw_newack)) 1218c2ecf20Sopenharmony_ci return 1; 1228c2ecf20Sopenharmony_ci return 0; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* 1268c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 1278c2ecf20Sopenharmony_ci * 3.1) If CYCLING_CHANGEOVER is 0, the sender SHOULD 1288c2ecf20Sopenharmony_ci * execute steps C, D, F. 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci * C has been implemented in sctp_outq_sack 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic inline int sctp_cacc_skip_3_1(struct sctp_transport *primary, 1338c2ecf20Sopenharmony_ci struct sctp_transport *transport, 1348c2ecf20Sopenharmony_ci int count_of_newacks) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci if (!primary->cacc.cycling_changeover) { 1378c2ecf20Sopenharmony_ci if (sctp_cacc_skip_3_1_d(primary, transport, count_of_newacks)) 1388c2ecf20Sopenharmony_ci return 1; 1398c2ecf20Sopenharmony_ci if (sctp_cacc_skip_3_1_f(transport, count_of_newacks)) 1408c2ecf20Sopenharmony_ci return 1; 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci return 0; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* 1478c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 1488c2ecf20Sopenharmony_ci * 3.2) Else if CYCLING_CHANGEOVER is 1, and t is less 1498c2ecf20Sopenharmony_ci * than next_tsn_at_change of the current primary, then 1508c2ecf20Sopenharmony_ci * the sender MUST NOT increment missing report count 1518c2ecf20Sopenharmony_ci * for t. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_cistatic inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci if (primary->cacc.cycling_changeover && 1568c2ecf20Sopenharmony_ci TSN_lt(tsn, primary->cacc.next_tsn_at_change)) 1578c2ecf20Sopenharmony_ci return 1; 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci/* 1628c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 1638c2ecf20Sopenharmony_ci * 3) If the missing report count for TSN t is to be 1648c2ecf20Sopenharmony_ci * incremented according to [RFC2960] and 1658c2ecf20Sopenharmony_ci * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, 1668c2ecf20Sopenharmony_ci * then the sender MUST further execute steps 3.1 and 1678c2ecf20Sopenharmony_ci * 3.2 to determine if the missing report count for 1688c2ecf20Sopenharmony_ci * TSN t SHOULD NOT be incremented. 1698c2ecf20Sopenharmony_ci * 1708c2ecf20Sopenharmony_ci * 3.3) If 3.1 and 3.2 do not dictate that the missing 1718c2ecf20Sopenharmony_ci * report count for t should not be incremented, then 1728c2ecf20Sopenharmony_ci * the sender SHOULD increment missing report count for 1738c2ecf20Sopenharmony_ci * t (according to [RFC2960] and [SCTP_STEWART_2002]). 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_cistatic inline int sctp_cacc_skip(struct sctp_transport *primary, 1768c2ecf20Sopenharmony_ci struct sctp_transport *transport, 1778c2ecf20Sopenharmony_ci int count_of_newacks, 1788c2ecf20Sopenharmony_ci __u32 tsn) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci if (primary->cacc.changeover_active && 1818c2ecf20Sopenharmony_ci (sctp_cacc_skip_3_1(primary, transport, count_of_newacks) || 1828c2ecf20Sopenharmony_ci sctp_cacc_skip_3_2(primary, tsn))) 1838c2ecf20Sopenharmony_ci return 1; 1848c2ecf20Sopenharmony_ci return 0; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci/* Initialize an existing sctp_outq. This does the boring stuff. 1888c2ecf20Sopenharmony_ci * You still need to define handlers if you really want to DO 1898c2ecf20Sopenharmony_ci * something with this structure... 1908c2ecf20Sopenharmony_ci */ 1918c2ecf20Sopenharmony_civoid sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci memset(q, 0, sizeof(struct sctp_outq)); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci q->asoc = asoc; 1968c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&q->out_chunk_list); 1978c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&q->control_chunk_list); 1988c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&q->retransmit); 1998c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&q->sacked); 2008c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&q->abandoned); 2018c2ecf20Sopenharmony_ci sctp_sched_set_sched(asoc, sctp_sk(asoc->base.sk)->default_ss); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci/* Free the outqueue structure and any related pending chunks. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_cistatic void __sctp_outq_teardown(struct sctp_outq *q) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct sctp_transport *transport; 2098c2ecf20Sopenharmony_ci struct list_head *lchunk, *temp; 2108c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, *tmp; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci /* Throw away unacknowledged chunks. */ 2138c2ecf20Sopenharmony_ci list_for_each_entry(transport, &q->asoc->peer.transport_addr_list, 2148c2ecf20Sopenharmony_ci transports) { 2158c2ecf20Sopenharmony_ci while ((lchunk = sctp_list_dequeue(&transport->transmitted)) != NULL) { 2168c2ecf20Sopenharmony_ci chunk = list_entry(lchunk, struct sctp_chunk, 2178c2ecf20Sopenharmony_ci transmitted_list); 2188c2ecf20Sopenharmony_ci /* Mark as part of a failed message. */ 2198c2ecf20Sopenharmony_ci sctp_chunk_fail(chunk, q->error); 2208c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* Throw away chunks that have been gap ACKed. */ 2258c2ecf20Sopenharmony_ci list_for_each_safe(lchunk, temp, &q->sacked) { 2268c2ecf20Sopenharmony_ci list_del_init(lchunk); 2278c2ecf20Sopenharmony_ci chunk = list_entry(lchunk, struct sctp_chunk, 2288c2ecf20Sopenharmony_ci transmitted_list); 2298c2ecf20Sopenharmony_ci sctp_chunk_fail(chunk, q->error); 2308c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* Throw away any chunks in the retransmit queue. */ 2348c2ecf20Sopenharmony_ci list_for_each_safe(lchunk, temp, &q->retransmit) { 2358c2ecf20Sopenharmony_ci list_del_init(lchunk); 2368c2ecf20Sopenharmony_ci chunk = list_entry(lchunk, struct sctp_chunk, 2378c2ecf20Sopenharmony_ci transmitted_list); 2388c2ecf20Sopenharmony_ci sctp_chunk_fail(chunk, q->error); 2398c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* Throw away any chunks that are in the abandoned queue. */ 2438c2ecf20Sopenharmony_ci list_for_each_safe(lchunk, temp, &q->abandoned) { 2448c2ecf20Sopenharmony_ci list_del_init(lchunk); 2458c2ecf20Sopenharmony_ci chunk = list_entry(lchunk, struct sctp_chunk, 2468c2ecf20Sopenharmony_ci transmitted_list); 2478c2ecf20Sopenharmony_ci sctp_chunk_fail(chunk, q->error); 2488c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* Throw away any leftover data chunks. */ 2528c2ecf20Sopenharmony_ci while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { 2538c2ecf20Sopenharmony_ci sctp_sched_dequeue_done(q, chunk); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* Mark as send failure. */ 2568c2ecf20Sopenharmony_ci sctp_chunk_fail(chunk, q->error); 2578c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* Throw away any leftover control chunks. */ 2618c2ecf20Sopenharmony_ci list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { 2628c2ecf20Sopenharmony_ci list_del_init(&chunk->list); 2638c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_civoid sctp_outq_teardown(struct sctp_outq *q) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci __sctp_outq_teardown(q); 2708c2ecf20Sopenharmony_ci sctp_outq_init(q->asoc, q); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* Free the outqueue structure and any related pending chunks. */ 2748c2ecf20Sopenharmony_civoid sctp_outq_free(struct sctp_outq *q) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci /* Throw away leftover chunks. */ 2778c2ecf20Sopenharmony_ci __sctp_outq_teardown(q); 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci/* Put a new chunk in an sctp_outq. */ 2818c2ecf20Sopenharmony_civoid sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk, gfp_t gfp) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct net *net = q->asoc->base.net; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci pr_debug("%s: outq:%p, chunk:%p[%s]\n", __func__, q, chunk, 2868c2ecf20Sopenharmony_ci chunk && chunk->chunk_hdr ? 2878c2ecf20Sopenharmony_ci sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : 2888c2ecf20Sopenharmony_ci "illegal chunk"); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* If it is data, queue it up, otherwise, send it 2918c2ecf20Sopenharmony_ci * immediately. 2928c2ecf20Sopenharmony_ci */ 2938c2ecf20Sopenharmony_ci if (sctp_chunk_is_data(chunk)) { 2948c2ecf20Sopenharmony_ci pr_debug("%s: outqueueing: outq:%p, chunk:%p[%s])\n", 2958c2ecf20Sopenharmony_ci __func__, q, chunk, chunk && chunk->chunk_hdr ? 2968c2ecf20Sopenharmony_ci sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : 2978c2ecf20Sopenharmony_ci "illegal chunk"); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci sctp_outq_tail_data(q, chunk); 3008c2ecf20Sopenharmony_ci if (chunk->asoc->peer.prsctp_capable && 3018c2ecf20Sopenharmony_ci SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) 3028c2ecf20Sopenharmony_ci chunk->asoc->sent_cnt_removable++; 3038c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) 3048c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS); 3058c2ecf20Sopenharmony_ci else 3068c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS); 3078c2ecf20Sopenharmony_ci } else { 3088c2ecf20Sopenharmony_ci list_add_tail(&chunk->list, &q->control_chunk_list); 3098c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (!q->cork) 3138c2ecf20Sopenharmony_ci sctp_outq_flush(q, 0, gfp); 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci/* Insert a chunk into the sorted list based on the TSNs. The retransmit list 3178c2ecf20Sopenharmony_ci * and the abandoned list are in ascending order. 3188c2ecf20Sopenharmony_ci */ 3198c2ecf20Sopenharmony_cistatic void sctp_insert_list(struct list_head *head, struct list_head *new) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci struct list_head *pos; 3228c2ecf20Sopenharmony_ci struct sctp_chunk *nchunk, *lchunk; 3238c2ecf20Sopenharmony_ci __u32 ntsn, ltsn; 3248c2ecf20Sopenharmony_ci int done = 0; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci nchunk = list_entry(new, struct sctp_chunk, transmitted_list); 3278c2ecf20Sopenharmony_ci ntsn = ntohl(nchunk->subh.data_hdr->tsn); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci list_for_each(pos, head) { 3308c2ecf20Sopenharmony_ci lchunk = list_entry(pos, struct sctp_chunk, transmitted_list); 3318c2ecf20Sopenharmony_ci ltsn = ntohl(lchunk->subh.data_hdr->tsn); 3328c2ecf20Sopenharmony_ci if (TSN_lt(ntsn, ltsn)) { 3338c2ecf20Sopenharmony_ci list_add(new, pos->prev); 3348c2ecf20Sopenharmony_ci done = 1; 3358c2ecf20Sopenharmony_ci break; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci if (!done) 3398c2ecf20Sopenharmony_ci list_add_tail(new, head); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic int sctp_prsctp_prune_sent(struct sctp_association *asoc, 3438c2ecf20Sopenharmony_ci struct sctp_sndrcvinfo *sinfo, 3448c2ecf20Sopenharmony_ci struct list_head *queue, int msg_len) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci struct sctp_chunk *chk, *temp; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci list_for_each_entry_safe(chk, temp, queue, transmitted_list) { 3498c2ecf20Sopenharmony_ci struct sctp_stream_out *streamout; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci if (!chk->msg->abandoned && 3528c2ecf20Sopenharmony_ci (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || 3538c2ecf20Sopenharmony_ci chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)) 3548c2ecf20Sopenharmony_ci continue; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci chk->msg->abandoned = 1; 3578c2ecf20Sopenharmony_ci list_del_init(&chk->transmitted_list); 3588c2ecf20Sopenharmony_ci sctp_insert_list(&asoc->outqueue.abandoned, 3598c2ecf20Sopenharmony_ci &chk->transmitted_list); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci streamout = SCTP_SO(&asoc->stream, chk->sinfo.sinfo_stream); 3628c2ecf20Sopenharmony_ci asoc->sent_cnt_removable--; 3638c2ecf20Sopenharmony_ci asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; 3648c2ecf20Sopenharmony_ci streamout->ext->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (queue != &asoc->outqueue.retransmit && 3678c2ecf20Sopenharmony_ci !chk->tsn_gap_acked) { 3688c2ecf20Sopenharmony_ci if (chk->transport) 3698c2ecf20Sopenharmony_ci chk->transport->flight_size -= 3708c2ecf20Sopenharmony_ci sctp_data_size(chk); 3718c2ecf20Sopenharmony_ci asoc->outqueue.outstanding_bytes -= sctp_data_size(chk); 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci msg_len -= chk->skb->truesize + sizeof(struct sctp_chunk); 3758c2ecf20Sopenharmony_ci if (msg_len <= 0) 3768c2ecf20Sopenharmony_ci break; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci return msg_len; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic int sctp_prsctp_prune_unsent(struct sctp_association *asoc, 3838c2ecf20Sopenharmony_ci struct sctp_sndrcvinfo *sinfo, int msg_len) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci struct sctp_outq *q = &asoc->outqueue; 3868c2ecf20Sopenharmony_ci struct sctp_chunk *chk, *temp; 3878c2ecf20Sopenharmony_ci struct sctp_stream_out *sout; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci q->sched->unsched_all(&asoc->stream); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) { 3928c2ecf20Sopenharmony_ci if (!chk->msg->abandoned && 3938c2ecf20Sopenharmony_ci (!(chk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG) || 3948c2ecf20Sopenharmony_ci !SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || 3958c2ecf20Sopenharmony_ci chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)) 3968c2ecf20Sopenharmony_ci continue; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci chk->msg->abandoned = 1; 3998c2ecf20Sopenharmony_ci sctp_sched_dequeue_common(q, chk); 4008c2ecf20Sopenharmony_ci asoc->sent_cnt_removable--; 4018c2ecf20Sopenharmony_ci asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci sout = SCTP_SO(&asoc->stream, chk->sinfo.sinfo_stream); 4048c2ecf20Sopenharmony_ci sout->ext->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci /* clear out_curr if all frag chunks are pruned */ 4078c2ecf20Sopenharmony_ci if (asoc->stream.out_curr == sout && 4088c2ecf20Sopenharmony_ci list_is_last(&chk->frag_list, &chk->msg->chunks)) 4098c2ecf20Sopenharmony_ci asoc->stream.out_curr = NULL; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci msg_len -= chk->skb->truesize + sizeof(struct sctp_chunk); 4128c2ecf20Sopenharmony_ci sctp_chunk_free(chk); 4138c2ecf20Sopenharmony_ci if (msg_len <= 0) 4148c2ecf20Sopenharmony_ci break; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci q->sched->sched_all(&asoc->stream); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return msg_len; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/* Abandon the chunks according their priorities */ 4238c2ecf20Sopenharmony_civoid sctp_prsctp_prune(struct sctp_association *asoc, 4248c2ecf20Sopenharmony_ci struct sctp_sndrcvinfo *sinfo, int msg_len) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci struct sctp_transport *transport; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (!asoc->peer.prsctp_capable || !asoc->sent_cnt_removable) 4298c2ecf20Sopenharmony_ci return; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci msg_len = sctp_prsctp_prune_sent(asoc, sinfo, 4328c2ecf20Sopenharmony_ci &asoc->outqueue.retransmit, 4338c2ecf20Sopenharmony_ci msg_len); 4348c2ecf20Sopenharmony_ci if (msg_len <= 0) 4358c2ecf20Sopenharmony_ci return; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci list_for_each_entry(transport, &asoc->peer.transport_addr_list, 4388c2ecf20Sopenharmony_ci transports) { 4398c2ecf20Sopenharmony_ci msg_len = sctp_prsctp_prune_sent(asoc, sinfo, 4408c2ecf20Sopenharmony_ci &transport->transmitted, 4418c2ecf20Sopenharmony_ci msg_len); 4428c2ecf20Sopenharmony_ci if (msg_len <= 0) 4438c2ecf20Sopenharmony_ci return; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci sctp_prsctp_prune_unsent(asoc, sinfo, msg_len); 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci/* Mark all the eligible packets on a transport for retransmission. */ 4508c2ecf20Sopenharmony_civoid sctp_retransmit_mark(struct sctp_outq *q, 4518c2ecf20Sopenharmony_ci struct sctp_transport *transport, 4528c2ecf20Sopenharmony_ci __u8 reason) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct list_head *lchunk, *ltemp; 4558c2ecf20Sopenharmony_ci struct sctp_chunk *chunk; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* Walk through the specified transmitted queue. */ 4588c2ecf20Sopenharmony_ci list_for_each_safe(lchunk, ltemp, &transport->transmitted) { 4598c2ecf20Sopenharmony_ci chunk = list_entry(lchunk, struct sctp_chunk, 4608c2ecf20Sopenharmony_ci transmitted_list); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* If the chunk is abandoned, move it to abandoned list. */ 4638c2ecf20Sopenharmony_ci if (sctp_chunk_abandoned(chunk)) { 4648c2ecf20Sopenharmony_ci list_del_init(lchunk); 4658c2ecf20Sopenharmony_ci sctp_insert_list(&q->abandoned, lchunk); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* If this chunk has not been previousely acked, 4688c2ecf20Sopenharmony_ci * stop considering it 'outstanding'. Our peer 4698c2ecf20Sopenharmony_ci * will most likely never see it since it will 4708c2ecf20Sopenharmony_ci * not be retransmitted 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci if (!chunk->tsn_gap_acked) { 4738c2ecf20Sopenharmony_ci if (chunk->transport) 4748c2ecf20Sopenharmony_ci chunk->transport->flight_size -= 4758c2ecf20Sopenharmony_ci sctp_data_size(chunk); 4768c2ecf20Sopenharmony_ci q->outstanding_bytes -= sctp_data_size(chunk); 4778c2ecf20Sopenharmony_ci q->asoc->peer.rwnd += sctp_data_size(chunk); 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci continue; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* If we are doing retransmission due to a timeout or pmtu 4838c2ecf20Sopenharmony_ci * discovery, only the chunks that are not yet acked should 4848c2ecf20Sopenharmony_ci * be added to the retransmit queue. 4858c2ecf20Sopenharmony_ci */ 4868c2ecf20Sopenharmony_ci if ((reason == SCTP_RTXR_FAST_RTX && 4878c2ecf20Sopenharmony_ci (chunk->fast_retransmit == SCTP_NEED_FRTX)) || 4888c2ecf20Sopenharmony_ci (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { 4898c2ecf20Sopenharmony_ci /* RFC 2960 6.2.1 Processing a Received SACK 4908c2ecf20Sopenharmony_ci * 4918c2ecf20Sopenharmony_ci * C) Any time a DATA chunk is marked for 4928c2ecf20Sopenharmony_ci * retransmission (via either T3-rtx timer expiration 4938c2ecf20Sopenharmony_ci * (Section 6.3.3) or via fast retransmit 4948c2ecf20Sopenharmony_ci * (Section 7.2.4)), add the data size of those 4958c2ecf20Sopenharmony_ci * chunks to the rwnd. 4968c2ecf20Sopenharmony_ci */ 4978c2ecf20Sopenharmony_ci q->asoc->peer.rwnd += sctp_data_size(chunk); 4988c2ecf20Sopenharmony_ci q->outstanding_bytes -= sctp_data_size(chunk); 4998c2ecf20Sopenharmony_ci if (chunk->transport) 5008c2ecf20Sopenharmony_ci transport->flight_size -= sctp_data_size(chunk); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci /* sctpimpguide-05 Section 2.8.2 5038c2ecf20Sopenharmony_ci * M5) If a T3-rtx timer expires, the 5048c2ecf20Sopenharmony_ci * 'TSN.Missing.Report' of all affected TSNs is set 5058c2ecf20Sopenharmony_ci * to 0. 5068c2ecf20Sopenharmony_ci */ 5078c2ecf20Sopenharmony_ci chunk->tsn_missing_report = 0; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* If a chunk that is being used for RTT measurement 5108c2ecf20Sopenharmony_ci * has to be retransmitted, we cannot use this chunk 5118c2ecf20Sopenharmony_ci * anymore for RTT measurements. Reset rto_pending so 5128c2ecf20Sopenharmony_ci * that a new RTT measurement is started when a new 5138c2ecf20Sopenharmony_ci * data chunk is sent. 5148c2ecf20Sopenharmony_ci */ 5158c2ecf20Sopenharmony_ci if (chunk->rtt_in_progress) { 5168c2ecf20Sopenharmony_ci chunk->rtt_in_progress = 0; 5178c2ecf20Sopenharmony_ci transport->rto_pending = 0; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* Move the chunk to the retransmit queue. The chunks 5218c2ecf20Sopenharmony_ci * on the retransmit queue are always kept in order. 5228c2ecf20Sopenharmony_ci */ 5238c2ecf20Sopenharmony_ci list_del_init(lchunk); 5248c2ecf20Sopenharmony_ci sctp_insert_list(&q->retransmit, lchunk); 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci pr_debug("%s: transport:%p, reason:%d, cwnd:%d, ssthresh:%d, " 5298c2ecf20Sopenharmony_ci "flight_size:%d, pba:%d\n", __func__, transport, reason, 5308c2ecf20Sopenharmony_ci transport->cwnd, transport->ssthresh, transport->flight_size, 5318c2ecf20Sopenharmony_ci transport->partial_bytes_acked); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci/* Mark all the eligible packets on a transport for retransmission and force 5358c2ecf20Sopenharmony_ci * one packet out. 5368c2ecf20Sopenharmony_ci */ 5378c2ecf20Sopenharmony_civoid sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, 5388c2ecf20Sopenharmony_ci enum sctp_retransmit_reason reason) 5398c2ecf20Sopenharmony_ci{ 5408c2ecf20Sopenharmony_ci struct net *net = q->asoc->base.net; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci switch (reason) { 5438c2ecf20Sopenharmony_ci case SCTP_RTXR_T3_RTX: 5448c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS); 5458c2ecf20Sopenharmony_ci sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); 5468c2ecf20Sopenharmony_ci /* Update the retran path if the T3-rtx timer has expired for 5478c2ecf20Sopenharmony_ci * the current retran path. 5488c2ecf20Sopenharmony_ci */ 5498c2ecf20Sopenharmony_ci if (transport == transport->asoc->peer.retran_path) 5508c2ecf20Sopenharmony_ci sctp_assoc_update_retran_path(transport->asoc); 5518c2ecf20Sopenharmony_ci transport->asoc->rtx_data_chunks += 5528c2ecf20Sopenharmony_ci transport->asoc->unack_data; 5538c2ecf20Sopenharmony_ci break; 5548c2ecf20Sopenharmony_ci case SCTP_RTXR_FAST_RTX: 5558c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_FAST_RETRANSMITS); 5568c2ecf20Sopenharmony_ci sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); 5578c2ecf20Sopenharmony_ci q->fast_rtx = 1; 5588c2ecf20Sopenharmony_ci break; 5598c2ecf20Sopenharmony_ci case SCTP_RTXR_PMTUD: 5608c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_PMTUD_RETRANSMITS); 5618c2ecf20Sopenharmony_ci break; 5628c2ecf20Sopenharmony_ci case SCTP_RTXR_T1_RTX: 5638c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T1_RETRANSMITS); 5648c2ecf20Sopenharmony_ci transport->asoc->init_retries++; 5658c2ecf20Sopenharmony_ci break; 5668c2ecf20Sopenharmony_ci default: 5678c2ecf20Sopenharmony_ci BUG(); 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci sctp_retransmit_mark(q, transport, reason); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination, 5738c2ecf20Sopenharmony_ci * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by 5748c2ecf20Sopenharmony_ci * following the procedures outlined in C1 - C5. 5758c2ecf20Sopenharmony_ci */ 5768c2ecf20Sopenharmony_ci if (reason == SCTP_RTXR_T3_RTX) 5778c2ecf20Sopenharmony_ci q->asoc->stream.si->generate_ftsn(q, q->asoc->ctsn_ack_point); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci /* Flush the queues only on timeout, since fast_rtx is only 5808c2ecf20Sopenharmony_ci * triggered during sack processing and the queue 5818c2ecf20Sopenharmony_ci * will be flushed at the end. 5828c2ecf20Sopenharmony_ci */ 5838c2ecf20Sopenharmony_ci if (reason != SCTP_RTXR_FAST_RTX) 5848c2ecf20Sopenharmony_ci sctp_outq_flush(q, /* rtx_timeout */ 1, GFP_ATOMIC); 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci/* 5888c2ecf20Sopenharmony_ci * Transmit DATA chunks on the retransmit queue. Upon return from 5898c2ecf20Sopenharmony_ci * __sctp_outq_flush_rtx() the packet 'pkt' may contain chunks which 5908c2ecf20Sopenharmony_ci * need to be transmitted by the caller. 5918c2ecf20Sopenharmony_ci * We assume that pkt->transport has already been set. 5928c2ecf20Sopenharmony_ci * 5938c2ecf20Sopenharmony_ci * The return value is a normal kernel error return value. 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_cistatic int __sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, 5968c2ecf20Sopenharmony_ci int rtx_timeout, int *start_timer, gfp_t gfp) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci struct sctp_transport *transport = pkt->transport; 5998c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, *chunk1; 6008c2ecf20Sopenharmony_ci struct list_head *lqueue; 6018c2ecf20Sopenharmony_ci enum sctp_xmit status; 6028c2ecf20Sopenharmony_ci int error = 0; 6038c2ecf20Sopenharmony_ci int timer = 0; 6048c2ecf20Sopenharmony_ci int done = 0; 6058c2ecf20Sopenharmony_ci int fast_rtx; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci lqueue = &q->retransmit; 6088c2ecf20Sopenharmony_ci fast_rtx = q->fast_rtx; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci /* This loop handles time-out retransmissions, fast retransmissions, 6118c2ecf20Sopenharmony_ci * and retransmissions due to opening of whindow. 6128c2ecf20Sopenharmony_ci * 6138c2ecf20Sopenharmony_ci * RFC 2960 6.3.3 Handle T3-rtx Expiration 6148c2ecf20Sopenharmony_ci * 6158c2ecf20Sopenharmony_ci * E3) Determine how many of the earliest (i.e., lowest TSN) 6168c2ecf20Sopenharmony_ci * outstanding DATA chunks for the address for which the 6178c2ecf20Sopenharmony_ci * T3-rtx has expired will fit into a single packet, subject 6188c2ecf20Sopenharmony_ci * to the MTU constraint for the path corresponding to the 6198c2ecf20Sopenharmony_ci * destination transport address to which the retransmission 6208c2ecf20Sopenharmony_ci * is being sent (this may be different from the address for 6218c2ecf20Sopenharmony_ci * which the timer expires [see Section 6.4]). Call this value 6228c2ecf20Sopenharmony_ci * K. Bundle and retransmit those K DATA chunks in a single 6238c2ecf20Sopenharmony_ci * packet to the destination endpoint. 6248c2ecf20Sopenharmony_ci * 6258c2ecf20Sopenharmony_ci * [Just to be painfully clear, if we are retransmitting 6268c2ecf20Sopenharmony_ci * because a timeout just happened, we should send only ONE 6278c2ecf20Sopenharmony_ci * packet of retransmitted data.] 6288c2ecf20Sopenharmony_ci * 6298c2ecf20Sopenharmony_ci * For fast retransmissions we also send only ONE packet. However, 6308c2ecf20Sopenharmony_ci * if we are just flushing the queue due to open window, we'll 6318c2ecf20Sopenharmony_ci * try to send as much as possible. 6328c2ecf20Sopenharmony_ci */ 6338c2ecf20Sopenharmony_ci list_for_each_entry_safe(chunk, chunk1, lqueue, transmitted_list) { 6348c2ecf20Sopenharmony_ci /* If the chunk is abandoned, move it to abandoned list. */ 6358c2ecf20Sopenharmony_ci if (sctp_chunk_abandoned(chunk)) { 6368c2ecf20Sopenharmony_ci list_del_init(&chunk->transmitted_list); 6378c2ecf20Sopenharmony_ci sctp_insert_list(&q->abandoned, 6388c2ecf20Sopenharmony_ci &chunk->transmitted_list); 6398c2ecf20Sopenharmony_ci continue; 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* Make sure that Gap Acked TSNs are not retransmitted. A 6438c2ecf20Sopenharmony_ci * simple approach is just to move such TSNs out of the 6448c2ecf20Sopenharmony_ci * way and into a 'transmitted' queue and skip to the 6458c2ecf20Sopenharmony_ci * next chunk. 6468c2ecf20Sopenharmony_ci */ 6478c2ecf20Sopenharmony_ci if (chunk->tsn_gap_acked) { 6488c2ecf20Sopenharmony_ci list_move_tail(&chunk->transmitted_list, 6498c2ecf20Sopenharmony_ci &transport->transmitted); 6508c2ecf20Sopenharmony_ci continue; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci /* If we are doing fast retransmit, ignore non-fast_rtransmit 6548c2ecf20Sopenharmony_ci * chunks 6558c2ecf20Sopenharmony_ci */ 6568c2ecf20Sopenharmony_ci if (fast_rtx && !chunk->fast_retransmit) 6578c2ecf20Sopenharmony_ci continue; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ciredo: 6608c2ecf20Sopenharmony_ci /* Attempt to append this chunk to the packet. */ 6618c2ecf20Sopenharmony_ci status = sctp_packet_append_chunk(pkt, chunk); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci switch (status) { 6648c2ecf20Sopenharmony_ci case SCTP_XMIT_PMTU_FULL: 6658c2ecf20Sopenharmony_ci if (!pkt->has_data && !pkt->has_cookie_echo) { 6668c2ecf20Sopenharmony_ci /* If this packet did not contain DATA then 6678c2ecf20Sopenharmony_ci * retransmission did not happen, so do it 6688c2ecf20Sopenharmony_ci * again. We'll ignore the error here since 6698c2ecf20Sopenharmony_ci * control chunks are already freed so there 6708c2ecf20Sopenharmony_ci * is nothing we can do. 6718c2ecf20Sopenharmony_ci */ 6728c2ecf20Sopenharmony_ci sctp_packet_transmit(pkt, gfp); 6738c2ecf20Sopenharmony_ci goto redo; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* Send this packet. */ 6778c2ecf20Sopenharmony_ci error = sctp_packet_transmit(pkt, gfp); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci /* If we are retransmitting, we should only 6808c2ecf20Sopenharmony_ci * send a single packet. 6818c2ecf20Sopenharmony_ci * Otherwise, try appending this chunk again. 6828c2ecf20Sopenharmony_ci */ 6838c2ecf20Sopenharmony_ci if (rtx_timeout || fast_rtx) 6848c2ecf20Sopenharmony_ci done = 1; 6858c2ecf20Sopenharmony_ci else 6868c2ecf20Sopenharmony_ci goto redo; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci /* Bundle next chunk in the next round. */ 6898c2ecf20Sopenharmony_ci break; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci case SCTP_XMIT_RWND_FULL: 6928c2ecf20Sopenharmony_ci /* Send this packet. */ 6938c2ecf20Sopenharmony_ci error = sctp_packet_transmit(pkt, gfp); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci /* Stop sending DATA as there is no more room 6968c2ecf20Sopenharmony_ci * at the receiver. 6978c2ecf20Sopenharmony_ci */ 6988c2ecf20Sopenharmony_ci done = 1; 6998c2ecf20Sopenharmony_ci break; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci case SCTP_XMIT_DELAY: 7028c2ecf20Sopenharmony_ci /* Send this packet. */ 7038c2ecf20Sopenharmony_ci error = sctp_packet_transmit(pkt, gfp); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci /* Stop sending DATA because of nagle delay. */ 7068c2ecf20Sopenharmony_ci done = 1; 7078c2ecf20Sopenharmony_ci break; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci default: 7108c2ecf20Sopenharmony_ci /* The append was successful, so add this chunk to 7118c2ecf20Sopenharmony_ci * the transmitted list. 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_ci list_move_tail(&chunk->transmitted_list, 7148c2ecf20Sopenharmony_ci &transport->transmitted); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci /* Mark the chunk as ineligible for fast retransmit 7178c2ecf20Sopenharmony_ci * after it is retransmitted. 7188c2ecf20Sopenharmony_ci */ 7198c2ecf20Sopenharmony_ci if (chunk->fast_retransmit == SCTP_NEED_FRTX) 7208c2ecf20Sopenharmony_ci chunk->fast_retransmit = SCTP_DONT_FRTX; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci q->asoc->stats.rtxchunks++; 7238c2ecf20Sopenharmony_ci break; 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* Set the timer if there were no errors */ 7278c2ecf20Sopenharmony_ci if (!error && !timer) 7288c2ecf20Sopenharmony_ci timer = 1; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if (done) 7318c2ecf20Sopenharmony_ci break; 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* If we are here due to a retransmit timeout or a fast 7358c2ecf20Sopenharmony_ci * retransmit and if there are any chunks left in the retransmit 7368c2ecf20Sopenharmony_ci * queue that could not fit in the PMTU sized packet, they need 7378c2ecf20Sopenharmony_ci * to be marked as ineligible for a subsequent fast retransmit. 7388c2ecf20Sopenharmony_ci */ 7398c2ecf20Sopenharmony_ci if (rtx_timeout || fast_rtx) { 7408c2ecf20Sopenharmony_ci list_for_each_entry(chunk1, lqueue, transmitted_list) { 7418c2ecf20Sopenharmony_ci if (chunk1->fast_retransmit == SCTP_NEED_FRTX) 7428c2ecf20Sopenharmony_ci chunk1->fast_retransmit = SCTP_DONT_FRTX; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci *start_timer = timer; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci /* Clear fast retransmit hint */ 7498c2ecf20Sopenharmony_ci if (fast_rtx) 7508c2ecf20Sopenharmony_ci q->fast_rtx = 0; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci return error; 7538c2ecf20Sopenharmony_ci} 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci/* Cork the outqueue so queued chunks are really queued. */ 7568c2ecf20Sopenharmony_civoid sctp_outq_uncork(struct sctp_outq *q, gfp_t gfp) 7578c2ecf20Sopenharmony_ci{ 7588c2ecf20Sopenharmony_ci if (q->cork) 7598c2ecf20Sopenharmony_ci q->cork = 0; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci sctp_outq_flush(q, 0, gfp); 7628c2ecf20Sopenharmony_ci} 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_cistatic int sctp_packet_singleton(struct sctp_transport *transport, 7658c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, gfp_t gfp) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci const struct sctp_association *asoc = transport->asoc; 7688c2ecf20Sopenharmony_ci const __u16 sport = asoc->base.bind_addr.port; 7698c2ecf20Sopenharmony_ci const __u16 dport = asoc->peer.port; 7708c2ecf20Sopenharmony_ci const __u32 vtag = asoc->peer.i.init_tag; 7718c2ecf20Sopenharmony_ci struct sctp_packet singleton; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci sctp_packet_init(&singleton, transport, sport, dport); 7748c2ecf20Sopenharmony_ci sctp_packet_config(&singleton, vtag, 0); 7758c2ecf20Sopenharmony_ci sctp_packet_append_chunk(&singleton, chunk); 7768c2ecf20Sopenharmony_ci return sctp_packet_transmit(&singleton, gfp); 7778c2ecf20Sopenharmony_ci} 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci/* Struct to hold the context during sctp outq flush */ 7808c2ecf20Sopenharmony_cistruct sctp_flush_ctx { 7818c2ecf20Sopenharmony_ci struct sctp_outq *q; 7828c2ecf20Sopenharmony_ci /* Current transport being used. It's NOT the same as curr active one */ 7838c2ecf20Sopenharmony_ci struct sctp_transport *transport; 7848c2ecf20Sopenharmony_ci /* These transports have chunks to send. */ 7858c2ecf20Sopenharmony_ci struct list_head transport_list; 7868c2ecf20Sopenharmony_ci struct sctp_association *asoc; 7878c2ecf20Sopenharmony_ci /* Packet on the current transport above */ 7888c2ecf20Sopenharmony_ci struct sctp_packet *packet; 7898c2ecf20Sopenharmony_ci gfp_t gfp; 7908c2ecf20Sopenharmony_ci}; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci/* transport: current transport */ 7938c2ecf20Sopenharmony_cistatic void sctp_outq_select_transport(struct sctp_flush_ctx *ctx, 7948c2ecf20Sopenharmony_ci struct sctp_chunk *chunk) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci struct sctp_transport *new_transport = chunk->transport; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci if (!new_transport) { 7998c2ecf20Sopenharmony_ci if (!sctp_chunk_is_data(chunk)) { 8008c2ecf20Sopenharmony_ci /* If we have a prior transport pointer, see if 8018c2ecf20Sopenharmony_ci * the destination address of the chunk 8028c2ecf20Sopenharmony_ci * matches the destination address of the 8038c2ecf20Sopenharmony_ci * current transport. If not a match, then 8048c2ecf20Sopenharmony_ci * try to look up the transport with a given 8058c2ecf20Sopenharmony_ci * destination address. We do this because 8068c2ecf20Sopenharmony_ci * after processing ASCONFs, we may have new 8078c2ecf20Sopenharmony_ci * transports created. 8088c2ecf20Sopenharmony_ci */ 8098c2ecf20Sopenharmony_ci if (ctx->transport && sctp_cmp_addr_exact(&chunk->dest, 8108c2ecf20Sopenharmony_ci &ctx->transport->ipaddr)) 8118c2ecf20Sopenharmony_ci new_transport = ctx->transport; 8128c2ecf20Sopenharmony_ci else 8138c2ecf20Sopenharmony_ci new_transport = sctp_assoc_lookup_paddr(ctx->asoc, 8148c2ecf20Sopenharmony_ci &chunk->dest); 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci /* if we still don't have a new transport, then 8188c2ecf20Sopenharmony_ci * use the current active path. 8198c2ecf20Sopenharmony_ci */ 8208c2ecf20Sopenharmony_ci if (!new_transport) 8218c2ecf20Sopenharmony_ci new_transport = ctx->asoc->peer.active_path; 8228c2ecf20Sopenharmony_ci } else { 8238c2ecf20Sopenharmony_ci __u8 type; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci switch (new_transport->state) { 8268c2ecf20Sopenharmony_ci case SCTP_INACTIVE: 8278c2ecf20Sopenharmony_ci case SCTP_UNCONFIRMED: 8288c2ecf20Sopenharmony_ci case SCTP_PF: 8298c2ecf20Sopenharmony_ci /* If the chunk is Heartbeat or Heartbeat Ack, 8308c2ecf20Sopenharmony_ci * send it to chunk->transport, even if it's 8318c2ecf20Sopenharmony_ci * inactive. 8328c2ecf20Sopenharmony_ci * 8338c2ecf20Sopenharmony_ci * 3.3.6 Heartbeat Acknowledgement: 8348c2ecf20Sopenharmony_ci * ... 8358c2ecf20Sopenharmony_ci * A HEARTBEAT ACK is always sent to the source IP 8368c2ecf20Sopenharmony_ci * address of the IP datagram containing the 8378c2ecf20Sopenharmony_ci * HEARTBEAT chunk to which this ack is responding. 8388c2ecf20Sopenharmony_ci * ... 8398c2ecf20Sopenharmony_ci * 8408c2ecf20Sopenharmony_ci * ASCONF_ACKs also must be sent to the source. 8418c2ecf20Sopenharmony_ci */ 8428c2ecf20Sopenharmony_ci type = chunk->chunk_hdr->type; 8438c2ecf20Sopenharmony_ci if (type != SCTP_CID_HEARTBEAT && 8448c2ecf20Sopenharmony_ci type != SCTP_CID_HEARTBEAT_ACK && 8458c2ecf20Sopenharmony_ci type != SCTP_CID_ASCONF_ACK) 8468c2ecf20Sopenharmony_ci new_transport = ctx->asoc->peer.active_path; 8478c2ecf20Sopenharmony_ci break; 8488c2ecf20Sopenharmony_ci default: 8498c2ecf20Sopenharmony_ci break; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci /* Are we switching transports? Take care of transport locks. */ 8548c2ecf20Sopenharmony_ci if (new_transport != ctx->transport) { 8558c2ecf20Sopenharmony_ci ctx->transport = new_transport; 8568c2ecf20Sopenharmony_ci ctx->packet = &ctx->transport->packet; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci if (list_empty(&ctx->transport->send_ready)) 8598c2ecf20Sopenharmony_ci list_add_tail(&ctx->transport->send_ready, 8608c2ecf20Sopenharmony_ci &ctx->transport_list); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci sctp_packet_config(ctx->packet, 8638c2ecf20Sopenharmony_ci ctx->asoc->peer.i.init_tag, 8648c2ecf20Sopenharmony_ci ctx->asoc->peer.ecn_capable); 8658c2ecf20Sopenharmony_ci /* We've switched transports, so apply the 8668c2ecf20Sopenharmony_ci * Burst limit to the new transport. 8678c2ecf20Sopenharmony_ci */ 8688c2ecf20Sopenharmony_ci sctp_transport_burst_limited(ctx->transport); 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci} 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_cistatic void sctp_outq_flush_ctrl(struct sctp_flush_ctx *ctx) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, *tmp; 8758c2ecf20Sopenharmony_ci enum sctp_xmit status; 8768c2ecf20Sopenharmony_ci int one_packet, error; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci list_for_each_entry_safe(chunk, tmp, &ctx->q->control_chunk_list, list) { 8798c2ecf20Sopenharmony_ci one_packet = 0; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* RFC 5061, 5.3 8828c2ecf20Sopenharmony_ci * F1) This means that until such time as the ASCONF 8838c2ecf20Sopenharmony_ci * containing the add is acknowledged, the sender MUST 8848c2ecf20Sopenharmony_ci * NOT use the new IP address as a source for ANY SCTP 8858c2ecf20Sopenharmony_ci * packet except on carrying an ASCONF Chunk. 8868c2ecf20Sopenharmony_ci */ 8878c2ecf20Sopenharmony_ci if (ctx->asoc->src_out_of_asoc_ok && 8888c2ecf20Sopenharmony_ci chunk->chunk_hdr->type != SCTP_CID_ASCONF) 8898c2ecf20Sopenharmony_ci continue; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci list_del_init(&chunk->list); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci /* Pick the right transport to use. Should always be true for 8948c2ecf20Sopenharmony_ci * the first chunk as we don't have a transport by then. 8958c2ecf20Sopenharmony_ci */ 8968c2ecf20Sopenharmony_ci sctp_outq_select_transport(ctx, chunk); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci switch (chunk->chunk_hdr->type) { 8998c2ecf20Sopenharmony_ci /* 6.10 Bundling 9008c2ecf20Sopenharmony_ci * ... 9018c2ecf20Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or SHUTDOWN 9028c2ecf20Sopenharmony_ci * COMPLETE with any other chunks. [Send them immediately.] 9038c2ecf20Sopenharmony_ci */ 9048c2ecf20Sopenharmony_ci case SCTP_CID_INIT: 9058c2ecf20Sopenharmony_ci case SCTP_CID_INIT_ACK: 9068c2ecf20Sopenharmony_ci case SCTP_CID_SHUTDOWN_COMPLETE: 9078c2ecf20Sopenharmony_ci error = sctp_packet_singleton(ctx->transport, chunk, 9088c2ecf20Sopenharmony_ci ctx->gfp); 9098c2ecf20Sopenharmony_ci if (error < 0) { 9108c2ecf20Sopenharmony_ci ctx->asoc->base.sk->sk_err = -error; 9118c2ecf20Sopenharmony_ci return; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci break; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci case SCTP_CID_ABORT: 9168c2ecf20Sopenharmony_ci if (sctp_test_T_bit(chunk)) 9178c2ecf20Sopenharmony_ci ctx->packet->vtag = ctx->asoc->c.my_vtag; 9188c2ecf20Sopenharmony_ci fallthrough; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci /* The following chunks are "response" chunks, i.e. 9218c2ecf20Sopenharmony_ci * they are generated in response to something we 9228c2ecf20Sopenharmony_ci * received. If we are sending these, then we can 9238c2ecf20Sopenharmony_ci * send only 1 packet containing these chunks. 9248c2ecf20Sopenharmony_ci */ 9258c2ecf20Sopenharmony_ci case SCTP_CID_HEARTBEAT_ACK: 9268c2ecf20Sopenharmony_ci case SCTP_CID_SHUTDOWN_ACK: 9278c2ecf20Sopenharmony_ci case SCTP_CID_COOKIE_ACK: 9288c2ecf20Sopenharmony_ci case SCTP_CID_COOKIE_ECHO: 9298c2ecf20Sopenharmony_ci case SCTP_CID_ERROR: 9308c2ecf20Sopenharmony_ci case SCTP_CID_ECN_CWR: 9318c2ecf20Sopenharmony_ci case SCTP_CID_ASCONF_ACK: 9328c2ecf20Sopenharmony_ci one_packet = 1; 9338c2ecf20Sopenharmony_ci fallthrough; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci case SCTP_CID_SACK: 9368c2ecf20Sopenharmony_ci case SCTP_CID_HEARTBEAT: 9378c2ecf20Sopenharmony_ci case SCTP_CID_SHUTDOWN: 9388c2ecf20Sopenharmony_ci case SCTP_CID_ECN_ECNE: 9398c2ecf20Sopenharmony_ci case SCTP_CID_ASCONF: 9408c2ecf20Sopenharmony_ci case SCTP_CID_FWD_TSN: 9418c2ecf20Sopenharmony_ci case SCTP_CID_I_FWD_TSN: 9428c2ecf20Sopenharmony_ci case SCTP_CID_RECONF: 9438c2ecf20Sopenharmony_ci status = sctp_packet_transmit_chunk(ctx->packet, chunk, 9448c2ecf20Sopenharmony_ci one_packet, ctx->gfp); 9458c2ecf20Sopenharmony_ci if (status != SCTP_XMIT_OK) { 9468c2ecf20Sopenharmony_ci /* put the chunk back */ 9478c2ecf20Sopenharmony_ci list_add(&chunk->list, &ctx->q->control_chunk_list); 9488c2ecf20Sopenharmony_ci break; 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci ctx->asoc->stats.octrlchunks++; 9528c2ecf20Sopenharmony_ci /* PR-SCTP C5) If a FORWARD TSN is sent, the 9538c2ecf20Sopenharmony_ci * sender MUST assure that at least one T3-rtx 9548c2ecf20Sopenharmony_ci * timer is running. 9558c2ecf20Sopenharmony_ci */ 9568c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN || 9578c2ecf20Sopenharmony_ci chunk->chunk_hdr->type == SCTP_CID_I_FWD_TSN) { 9588c2ecf20Sopenharmony_ci sctp_transport_reset_t3_rtx(ctx->transport); 9598c2ecf20Sopenharmony_ci ctx->transport->last_time_sent = jiffies; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (chunk == ctx->asoc->strreset_chunk) 9638c2ecf20Sopenharmony_ci sctp_transport_reset_reconf_timer(ctx->transport); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci break; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci default: 9688c2ecf20Sopenharmony_ci /* We built a chunk with an illegal type! */ 9698c2ecf20Sopenharmony_ci BUG(); 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci/* Returns false if new data shouldn't be sent */ 9758c2ecf20Sopenharmony_cistatic bool sctp_outq_flush_rtx(struct sctp_flush_ctx *ctx, 9768c2ecf20Sopenharmony_ci int rtx_timeout) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci int error, start_timer = 0; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (ctx->asoc->peer.retran_path->state == SCTP_UNCONFIRMED) 9818c2ecf20Sopenharmony_ci return false; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci if (ctx->transport != ctx->asoc->peer.retran_path) { 9848c2ecf20Sopenharmony_ci /* Switch transports & prepare the packet. */ 9858c2ecf20Sopenharmony_ci ctx->transport = ctx->asoc->peer.retran_path; 9868c2ecf20Sopenharmony_ci ctx->packet = &ctx->transport->packet; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci if (list_empty(&ctx->transport->send_ready)) 9898c2ecf20Sopenharmony_ci list_add_tail(&ctx->transport->send_ready, 9908c2ecf20Sopenharmony_ci &ctx->transport_list); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci sctp_packet_config(ctx->packet, ctx->asoc->peer.i.init_tag, 9938c2ecf20Sopenharmony_ci ctx->asoc->peer.ecn_capable); 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci error = __sctp_outq_flush_rtx(ctx->q, ctx->packet, rtx_timeout, 9978c2ecf20Sopenharmony_ci &start_timer, ctx->gfp); 9988c2ecf20Sopenharmony_ci if (error < 0) 9998c2ecf20Sopenharmony_ci ctx->asoc->base.sk->sk_err = -error; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci if (start_timer) { 10028c2ecf20Sopenharmony_ci sctp_transport_reset_t3_rtx(ctx->transport); 10038c2ecf20Sopenharmony_ci ctx->transport->last_time_sent = jiffies; 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci /* This can happen on COOKIE-ECHO resend. Only 10078c2ecf20Sopenharmony_ci * one chunk can get bundled with a COOKIE-ECHO. 10088c2ecf20Sopenharmony_ci */ 10098c2ecf20Sopenharmony_ci if (ctx->packet->has_cookie_echo) 10108c2ecf20Sopenharmony_ci return false; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci /* Don't send new data if there is still data 10138c2ecf20Sopenharmony_ci * waiting to retransmit. 10148c2ecf20Sopenharmony_ci */ 10158c2ecf20Sopenharmony_ci if (!list_empty(&ctx->q->retransmit)) 10168c2ecf20Sopenharmony_ci return false; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci return true; 10198c2ecf20Sopenharmony_ci} 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_cistatic void sctp_outq_flush_data(struct sctp_flush_ctx *ctx, 10228c2ecf20Sopenharmony_ci int rtx_timeout) 10238c2ecf20Sopenharmony_ci{ 10248c2ecf20Sopenharmony_ci struct sctp_chunk *chunk; 10258c2ecf20Sopenharmony_ci enum sctp_xmit status; 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* Is it OK to send data chunks? */ 10288c2ecf20Sopenharmony_ci switch (ctx->asoc->state) { 10298c2ecf20Sopenharmony_ci case SCTP_STATE_COOKIE_ECHOED: 10308c2ecf20Sopenharmony_ci /* Only allow bundling when this packet has a COOKIE-ECHO 10318c2ecf20Sopenharmony_ci * chunk. 10328c2ecf20Sopenharmony_ci */ 10338c2ecf20Sopenharmony_ci if (!ctx->packet || !ctx->packet->has_cookie_echo) 10348c2ecf20Sopenharmony_ci return; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci fallthrough; 10378c2ecf20Sopenharmony_ci case SCTP_STATE_ESTABLISHED: 10388c2ecf20Sopenharmony_ci case SCTP_STATE_SHUTDOWN_PENDING: 10398c2ecf20Sopenharmony_ci case SCTP_STATE_SHUTDOWN_RECEIVED: 10408c2ecf20Sopenharmony_ci break; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci default: 10438c2ecf20Sopenharmony_ci /* Do nothing. */ 10448c2ecf20Sopenharmony_ci return; 10458c2ecf20Sopenharmony_ci } 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* RFC 2960 6.1 Transmission of DATA Chunks 10488c2ecf20Sopenharmony_ci * 10498c2ecf20Sopenharmony_ci * C) When the time comes for the sender to transmit, 10508c2ecf20Sopenharmony_ci * before sending new DATA chunks, the sender MUST 10518c2ecf20Sopenharmony_ci * first transmit any outstanding DATA chunks which 10528c2ecf20Sopenharmony_ci * are marked for retransmission (limited by the 10538c2ecf20Sopenharmony_ci * current cwnd). 10548c2ecf20Sopenharmony_ci */ 10558c2ecf20Sopenharmony_ci if (!list_empty(&ctx->q->retransmit) && 10568c2ecf20Sopenharmony_ci !sctp_outq_flush_rtx(ctx, rtx_timeout)) 10578c2ecf20Sopenharmony_ci return; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci /* Apply Max.Burst limitation to the current transport in 10608c2ecf20Sopenharmony_ci * case it will be used for new data. We are going to 10618c2ecf20Sopenharmony_ci * rest it before we return, but we want to apply the limit 10628c2ecf20Sopenharmony_ci * to the currently queued data. 10638c2ecf20Sopenharmony_ci */ 10648c2ecf20Sopenharmony_ci if (ctx->transport) 10658c2ecf20Sopenharmony_ci sctp_transport_burst_limited(ctx->transport); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* Finally, transmit new packets. */ 10688c2ecf20Sopenharmony_ci while ((chunk = sctp_outq_dequeue_data(ctx->q)) != NULL) { 10698c2ecf20Sopenharmony_ci __u32 sid = ntohs(chunk->subh.data_hdr->stream); 10708c2ecf20Sopenharmony_ci __u8 stream_state = SCTP_SO(&ctx->asoc->stream, sid)->state; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci /* Has this chunk expired? */ 10738c2ecf20Sopenharmony_ci if (sctp_chunk_abandoned(chunk)) { 10748c2ecf20Sopenharmony_ci sctp_sched_dequeue_done(ctx->q, chunk); 10758c2ecf20Sopenharmony_ci sctp_chunk_fail(chunk, 0); 10768c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 10778c2ecf20Sopenharmony_ci continue; 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if (stream_state == SCTP_STREAM_CLOSED) { 10818c2ecf20Sopenharmony_ci sctp_outq_head_data(ctx->q, chunk); 10828c2ecf20Sopenharmony_ci break; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci sctp_outq_select_transport(ctx, chunk); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci pr_debug("%s: outq:%p, chunk:%p[%s], tx-tsn:0x%x skb->head:%p skb->users:%d\n", 10888c2ecf20Sopenharmony_ci __func__, ctx->q, chunk, chunk && chunk->chunk_hdr ? 10898c2ecf20Sopenharmony_ci sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : 10908c2ecf20Sopenharmony_ci "illegal chunk", ntohl(chunk->subh.data_hdr->tsn), 10918c2ecf20Sopenharmony_ci chunk->skb ? chunk->skb->head : NULL, chunk->skb ? 10928c2ecf20Sopenharmony_ci refcount_read(&chunk->skb->users) : -1); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci /* Add the chunk to the packet. */ 10958c2ecf20Sopenharmony_ci status = sctp_packet_transmit_chunk(ctx->packet, chunk, 0, 10968c2ecf20Sopenharmony_ci ctx->gfp); 10978c2ecf20Sopenharmony_ci if (status != SCTP_XMIT_OK) { 10988c2ecf20Sopenharmony_ci /* We could not append this chunk, so put 10998c2ecf20Sopenharmony_ci * the chunk back on the output queue. 11008c2ecf20Sopenharmony_ci */ 11018c2ecf20Sopenharmony_ci pr_debug("%s: could not transmit tsn:0x%x, status:%d\n", 11028c2ecf20Sopenharmony_ci __func__, ntohl(chunk->subh.data_hdr->tsn), 11038c2ecf20Sopenharmony_ci status); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci sctp_outq_head_data(ctx->q, chunk); 11068c2ecf20Sopenharmony_ci break; 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci /* The sender is in the SHUTDOWN-PENDING state, 11108c2ecf20Sopenharmony_ci * The sender MAY set the I-bit in the DATA 11118c2ecf20Sopenharmony_ci * chunk header. 11128c2ecf20Sopenharmony_ci */ 11138c2ecf20Sopenharmony_ci if (ctx->asoc->state == SCTP_STATE_SHUTDOWN_PENDING) 11148c2ecf20Sopenharmony_ci chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM; 11158c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) 11168c2ecf20Sopenharmony_ci ctx->asoc->stats.ouodchunks++; 11178c2ecf20Sopenharmony_ci else 11188c2ecf20Sopenharmony_ci ctx->asoc->stats.oodchunks++; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* Only now it's safe to consider this 11218c2ecf20Sopenharmony_ci * chunk as sent, sched-wise. 11228c2ecf20Sopenharmony_ci */ 11238c2ecf20Sopenharmony_ci sctp_sched_dequeue_done(ctx->q, chunk); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci list_add_tail(&chunk->transmitted_list, 11268c2ecf20Sopenharmony_ci &ctx->transport->transmitted); 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci sctp_transport_reset_t3_rtx(ctx->transport); 11298c2ecf20Sopenharmony_ci ctx->transport->last_time_sent = jiffies; 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci /* Only let one DATA chunk get bundled with a 11328c2ecf20Sopenharmony_ci * COOKIE-ECHO chunk. 11338c2ecf20Sopenharmony_ci */ 11348c2ecf20Sopenharmony_ci if (ctx->packet->has_cookie_echo) 11358c2ecf20Sopenharmony_ci break; 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci} 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cistatic void sctp_outq_flush_transports(struct sctp_flush_ctx *ctx) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci struct list_head *ltransport; 11428c2ecf20Sopenharmony_ci struct sctp_packet *packet; 11438c2ecf20Sopenharmony_ci struct sctp_transport *t; 11448c2ecf20Sopenharmony_ci int error = 0; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci while ((ltransport = sctp_list_dequeue(&ctx->transport_list)) != NULL) { 11478c2ecf20Sopenharmony_ci t = list_entry(ltransport, struct sctp_transport, send_ready); 11488c2ecf20Sopenharmony_ci packet = &t->packet; 11498c2ecf20Sopenharmony_ci if (!sctp_packet_empty(packet)) { 11508c2ecf20Sopenharmony_ci error = sctp_packet_transmit(packet, ctx->gfp); 11518c2ecf20Sopenharmony_ci if (error < 0) 11528c2ecf20Sopenharmony_ci ctx->q->asoc->base.sk->sk_err = -error; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci /* Clear the burst limited state, if any */ 11568c2ecf20Sopenharmony_ci sctp_transport_burst_reset(t); 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci} 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci/* Try to flush an outqueue. 11618c2ecf20Sopenharmony_ci * 11628c2ecf20Sopenharmony_ci * Description: Send everything in q which we legally can, subject to 11638c2ecf20Sopenharmony_ci * congestion limitations. 11648c2ecf20Sopenharmony_ci * * Note: This function can be called from multiple contexts so appropriate 11658c2ecf20Sopenharmony_ci * locking concerns must be made. Today we use the sock lock to protect 11668c2ecf20Sopenharmony_ci * this function. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci struct sctp_flush_ctx ctx = { 11728c2ecf20Sopenharmony_ci .q = q, 11738c2ecf20Sopenharmony_ci .transport = NULL, 11748c2ecf20Sopenharmony_ci .transport_list = LIST_HEAD_INIT(ctx.transport_list), 11758c2ecf20Sopenharmony_ci .asoc = q->asoc, 11768c2ecf20Sopenharmony_ci .packet = NULL, 11778c2ecf20Sopenharmony_ci .gfp = gfp, 11788c2ecf20Sopenharmony_ci }; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci /* 6.10 Bundling 11818c2ecf20Sopenharmony_ci * ... 11828c2ecf20Sopenharmony_ci * When bundling control chunks with DATA chunks, an 11838c2ecf20Sopenharmony_ci * endpoint MUST place control chunks first in the outbound 11848c2ecf20Sopenharmony_ci * SCTP packet. The transmitter MUST transmit DATA chunks 11858c2ecf20Sopenharmony_ci * within a SCTP packet in increasing order of TSN. 11868c2ecf20Sopenharmony_ci * ... 11878c2ecf20Sopenharmony_ci */ 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci sctp_outq_flush_ctrl(&ctx); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci if (q->asoc->src_out_of_asoc_ok) 11928c2ecf20Sopenharmony_ci goto sctp_flush_out; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci sctp_outq_flush_data(&ctx, rtx_timeout); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_cisctp_flush_out: 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci sctp_outq_flush_transports(&ctx); 11998c2ecf20Sopenharmony_ci} 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci/* Update unack_data based on the incoming SACK chunk */ 12028c2ecf20Sopenharmony_cistatic void sctp_sack_update_unack_data(struct sctp_association *assoc, 12038c2ecf20Sopenharmony_ci struct sctp_sackhdr *sack) 12048c2ecf20Sopenharmony_ci{ 12058c2ecf20Sopenharmony_ci union sctp_sack_variable *frags; 12068c2ecf20Sopenharmony_ci __u16 unack_data; 12078c2ecf20Sopenharmony_ci int i; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci unack_data = assoc->next_tsn - assoc->ctsn_ack_point - 1; 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci frags = sack->variable; 12128c2ecf20Sopenharmony_ci for (i = 0; i < ntohs(sack->num_gap_ack_blocks); i++) { 12138c2ecf20Sopenharmony_ci unack_data -= ((ntohs(frags[i].gab.end) - 12148c2ecf20Sopenharmony_ci ntohs(frags[i].gab.start) + 1)); 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci assoc->unack_data = unack_data; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci/* This is where we REALLY process a SACK. 12218c2ecf20Sopenharmony_ci * 12228c2ecf20Sopenharmony_ci * Process the SACK against the outqueue. Mostly, this just frees 12238c2ecf20Sopenharmony_ci * things off the transmitted queue. 12248c2ecf20Sopenharmony_ci */ 12258c2ecf20Sopenharmony_ciint sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) 12268c2ecf20Sopenharmony_ci{ 12278c2ecf20Sopenharmony_ci struct sctp_association *asoc = q->asoc; 12288c2ecf20Sopenharmony_ci struct sctp_sackhdr *sack = chunk->subh.sack_hdr; 12298c2ecf20Sopenharmony_ci struct sctp_transport *transport; 12308c2ecf20Sopenharmony_ci struct sctp_chunk *tchunk = NULL; 12318c2ecf20Sopenharmony_ci struct list_head *lchunk, *transport_list, *temp; 12328c2ecf20Sopenharmony_ci union sctp_sack_variable *frags = sack->variable; 12338c2ecf20Sopenharmony_ci __u32 sack_ctsn, ctsn, tsn; 12348c2ecf20Sopenharmony_ci __u32 highest_tsn, highest_new_tsn; 12358c2ecf20Sopenharmony_ci __u32 sack_a_rwnd; 12368c2ecf20Sopenharmony_ci unsigned int outstanding; 12378c2ecf20Sopenharmony_ci struct sctp_transport *primary = asoc->peer.primary_path; 12388c2ecf20Sopenharmony_ci int count_of_newacks = 0; 12398c2ecf20Sopenharmony_ci int gap_ack_blocks; 12408c2ecf20Sopenharmony_ci u8 accum_moved = 0; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* Grab the association's destination address list. */ 12438c2ecf20Sopenharmony_ci transport_list = &asoc->peer.transport_addr_list; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci /* SCTP path tracepoint for congestion control debugging. */ 12468c2ecf20Sopenharmony_ci if (trace_sctp_probe_path_enabled()) { 12478c2ecf20Sopenharmony_ci list_for_each_entry(transport, transport_list, transports) 12488c2ecf20Sopenharmony_ci trace_sctp_probe_path(transport, asoc); 12498c2ecf20Sopenharmony_ci } 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci sack_ctsn = ntohl(sack->cum_tsn_ack); 12528c2ecf20Sopenharmony_ci gap_ack_blocks = ntohs(sack->num_gap_ack_blocks); 12538c2ecf20Sopenharmony_ci asoc->stats.gapcnt += gap_ack_blocks; 12548c2ecf20Sopenharmony_ci /* 12558c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 12568c2ecf20Sopenharmony_ci * On receipt of a SACK the sender SHOULD execute the 12578c2ecf20Sopenharmony_ci * following statements. 12588c2ecf20Sopenharmony_ci * 12598c2ecf20Sopenharmony_ci * 1) If the cumulative ack in the SACK passes next tsn_at_change 12608c2ecf20Sopenharmony_ci * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be 12618c2ecf20Sopenharmony_ci * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for 12628c2ecf20Sopenharmony_ci * all destinations. 12638c2ecf20Sopenharmony_ci * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE 12648c2ecf20Sopenharmony_ci * is set the receiver of the SACK MUST take the following actions: 12658c2ecf20Sopenharmony_ci * 12668c2ecf20Sopenharmony_ci * A) Initialize the cacc_saw_newack to 0 for all destination 12678c2ecf20Sopenharmony_ci * addresses. 12688c2ecf20Sopenharmony_ci * 12698c2ecf20Sopenharmony_ci * Only bother if changeover_active is set. Otherwise, this is 12708c2ecf20Sopenharmony_ci * totally suboptimal to do on every SACK. 12718c2ecf20Sopenharmony_ci */ 12728c2ecf20Sopenharmony_ci if (primary->cacc.changeover_active) { 12738c2ecf20Sopenharmony_ci u8 clear_cycling = 0; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { 12768c2ecf20Sopenharmony_ci primary->cacc.changeover_active = 0; 12778c2ecf20Sopenharmony_ci clear_cycling = 1; 12788c2ecf20Sopenharmony_ci } 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci if (clear_cycling || gap_ack_blocks) { 12818c2ecf20Sopenharmony_ci list_for_each_entry(transport, transport_list, 12828c2ecf20Sopenharmony_ci transports) { 12838c2ecf20Sopenharmony_ci if (clear_cycling) 12848c2ecf20Sopenharmony_ci transport->cacc.cycling_changeover = 0; 12858c2ecf20Sopenharmony_ci if (gap_ack_blocks) 12868c2ecf20Sopenharmony_ci transport->cacc.cacc_saw_newack = 0; 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci /* Get the highest TSN in the sack. */ 12928c2ecf20Sopenharmony_ci highest_tsn = sack_ctsn; 12938c2ecf20Sopenharmony_ci if (gap_ack_blocks) 12948c2ecf20Sopenharmony_ci highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci if (TSN_lt(asoc->highest_sacked, highest_tsn)) 12978c2ecf20Sopenharmony_ci asoc->highest_sacked = highest_tsn; 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci highest_new_tsn = sack_ctsn; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci /* Run through the retransmit queue. Credit bytes received 13028c2ecf20Sopenharmony_ci * and free those chunks that we can. 13038c2ecf20Sopenharmony_ci */ 13048c2ecf20Sopenharmony_ci sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci /* Run through the transmitted queue. 13078c2ecf20Sopenharmony_ci * Credit bytes received and free those chunks which we can. 13088c2ecf20Sopenharmony_ci * 13098c2ecf20Sopenharmony_ci * This is a MASSIVE candidate for optimization. 13108c2ecf20Sopenharmony_ci */ 13118c2ecf20Sopenharmony_ci list_for_each_entry(transport, transport_list, transports) { 13128c2ecf20Sopenharmony_ci sctp_check_transmitted(q, &transport->transmitted, 13138c2ecf20Sopenharmony_ci transport, &chunk->source, sack, 13148c2ecf20Sopenharmony_ci &highest_new_tsn); 13158c2ecf20Sopenharmony_ci /* 13168c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 13178c2ecf20Sopenharmony_ci * C) Let count_of_newacks be the number of 13188c2ecf20Sopenharmony_ci * destinations for which cacc_saw_newack is set. 13198c2ecf20Sopenharmony_ci */ 13208c2ecf20Sopenharmony_ci if (transport->cacc.cacc_saw_newack) 13218c2ecf20Sopenharmony_ci count_of_newacks++; 13228c2ecf20Sopenharmony_ci } 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci /* Move the Cumulative TSN Ack Point if appropriate. */ 13258c2ecf20Sopenharmony_ci if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn)) { 13268c2ecf20Sopenharmony_ci asoc->ctsn_ack_point = sack_ctsn; 13278c2ecf20Sopenharmony_ci accum_moved = 1; 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci if (gap_ack_blocks) { 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci if (asoc->fast_recovery && accum_moved) 13338c2ecf20Sopenharmony_ci highest_new_tsn = highest_tsn; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci list_for_each_entry(transport, transport_list, transports) 13368c2ecf20Sopenharmony_ci sctp_mark_missing(q, &transport->transmitted, transport, 13378c2ecf20Sopenharmony_ci highest_new_tsn, count_of_newacks); 13388c2ecf20Sopenharmony_ci } 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci /* Update unack_data field in the assoc. */ 13418c2ecf20Sopenharmony_ci sctp_sack_update_unack_data(asoc, sack); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci ctsn = asoc->ctsn_ack_point; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci /* Throw away stuff rotting on the sack queue. */ 13468c2ecf20Sopenharmony_ci list_for_each_safe(lchunk, temp, &q->sacked) { 13478c2ecf20Sopenharmony_ci tchunk = list_entry(lchunk, struct sctp_chunk, 13488c2ecf20Sopenharmony_ci transmitted_list); 13498c2ecf20Sopenharmony_ci tsn = ntohl(tchunk->subh.data_hdr->tsn); 13508c2ecf20Sopenharmony_ci if (TSN_lte(tsn, ctsn)) { 13518c2ecf20Sopenharmony_ci list_del_init(&tchunk->transmitted_list); 13528c2ecf20Sopenharmony_ci if (asoc->peer.prsctp_capable && 13538c2ecf20Sopenharmony_ci SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) 13548c2ecf20Sopenharmony_ci asoc->sent_cnt_removable--; 13558c2ecf20Sopenharmony_ci sctp_chunk_free(tchunk); 13568c2ecf20Sopenharmony_ci } 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci /* ii) Set rwnd equal to the newly received a_rwnd minus the 13608c2ecf20Sopenharmony_ci * number of bytes still outstanding after processing the 13618c2ecf20Sopenharmony_ci * Cumulative TSN Ack and the Gap Ack Blocks. 13628c2ecf20Sopenharmony_ci */ 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci sack_a_rwnd = ntohl(sack->a_rwnd); 13658c2ecf20Sopenharmony_ci asoc->peer.zero_window_announced = !sack_a_rwnd; 13668c2ecf20Sopenharmony_ci outstanding = q->outstanding_bytes; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci if (outstanding < sack_a_rwnd) 13698c2ecf20Sopenharmony_ci sack_a_rwnd -= outstanding; 13708c2ecf20Sopenharmony_ci else 13718c2ecf20Sopenharmony_ci sack_a_rwnd = 0; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci asoc->peer.rwnd = sack_a_rwnd; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci asoc->stream.si->generate_ftsn(q, sack_ctsn); 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci pr_debug("%s: sack cumulative tsn ack:0x%x\n", __func__, sack_ctsn); 13788c2ecf20Sopenharmony_ci pr_debug("%s: cumulative tsn ack of assoc:%p is 0x%x, " 13798c2ecf20Sopenharmony_ci "advertised peer ack point:0x%x\n", __func__, asoc, ctsn, 13808c2ecf20Sopenharmony_ci asoc->adv_peer_ack_point); 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci return sctp_outq_is_empty(q); 13838c2ecf20Sopenharmony_ci} 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci/* Is the outqueue empty? 13868c2ecf20Sopenharmony_ci * The queue is empty when we have not pending data, no in-flight data 13878c2ecf20Sopenharmony_ci * and nothing pending retransmissions. 13888c2ecf20Sopenharmony_ci */ 13898c2ecf20Sopenharmony_ciint sctp_outq_is_empty(const struct sctp_outq *q) 13908c2ecf20Sopenharmony_ci{ 13918c2ecf20Sopenharmony_ci return q->out_qlen == 0 && q->outstanding_bytes == 0 && 13928c2ecf20Sopenharmony_ci list_empty(&q->retransmit); 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci/******************************************************************** 13968c2ecf20Sopenharmony_ci * 2nd Level Abstractions 13978c2ecf20Sopenharmony_ci ********************************************************************/ 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci/* Go through a transport's transmitted list or the association's retransmit 14008c2ecf20Sopenharmony_ci * list and move chunks that are acked by the Cumulative TSN Ack to q->sacked. 14018c2ecf20Sopenharmony_ci * The retransmit list will not have an associated transport. 14028c2ecf20Sopenharmony_ci * 14038c2ecf20Sopenharmony_ci * I added coherent debug information output. --xguo 14048c2ecf20Sopenharmony_ci * 14058c2ecf20Sopenharmony_ci * Instead of printing 'sacked' or 'kept' for each TSN on the 14068c2ecf20Sopenharmony_ci * transmitted_queue, we print a range: SACKED: TSN1-TSN2, TSN3, TSN4-TSN5. 14078c2ecf20Sopenharmony_ci * KEPT TSN6-TSN7, etc. 14088c2ecf20Sopenharmony_ci */ 14098c2ecf20Sopenharmony_cistatic void sctp_check_transmitted(struct sctp_outq *q, 14108c2ecf20Sopenharmony_ci struct list_head *transmitted_queue, 14118c2ecf20Sopenharmony_ci struct sctp_transport *transport, 14128c2ecf20Sopenharmony_ci union sctp_addr *saddr, 14138c2ecf20Sopenharmony_ci struct sctp_sackhdr *sack, 14148c2ecf20Sopenharmony_ci __u32 *highest_new_tsn_in_sack) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci struct list_head *lchunk; 14178c2ecf20Sopenharmony_ci struct sctp_chunk *tchunk; 14188c2ecf20Sopenharmony_ci struct list_head tlist; 14198c2ecf20Sopenharmony_ci __u32 tsn; 14208c2ecf20Sopenharmony_ci __u32 sack_ctsn; 14218c2ecf20Sopenharmony_ci __u32 rtt; 14228c2ecf20Sopenharmony_ci __u8 restart_timer = 0; 14238c2ecf20Sopenharmony_ci int bytes_acked = 0; 14248c2ecf20Sopenharmony_ci int migrate_bytes = 0; 14258c2ecf20Sopenharmony_ci bool forward_progress = false; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci sack_ctsn = ntohl(sack->cum_tsn_ack); 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&tlist); 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci /* The while loop will skip empty transmitted queues. */ 14328c2ecf20Sopenharmony_ci while (NULL != (lchunk = sctp_list_dequeue(transmitted_queue))) { 14338c2ecf20Sopenharmony_ci tchunk = list_entry(lchunk, struct sctp_chunk, 14348c2ecf20Sopenharmony_ci transmitted_list); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci if (sctp_chunk_abandoned(tchunk)) { 14378c2ecf20Sopenharmony_ci /* Move the chunk to abandoned list. */ 14388c2ecf20Sopenharmony_ci sctp_insert_list(&q->abandoned, lchunk); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci /* If this chunk has not been acked, stop 14418c2ecf20Sopenharmony_ci * considering it as 'outstanding'. 14428c2ecf20Sopenharmony_ci */ 14438c2ecf20Sopenharmony_ci if (transmitted_queue != &q->retransmit && 14448c2ecf20Sopenharmony_ci !tchunk->tsn_gap_acked) { 14458c2ecf20Sopenharmony_ci if (tchunk->transport) 14468c2ecf20Sopenharmony_ci tchunk->transport->flight_size -= 14478c2ecf20Sopenharmony_ci sctp_data_size(tchunk); 14488c2ecf20Sopenharmony_ci q->outstanding_bytes -= sctp_data_size(tchunk); 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci continue; 14518c2ecf20Sopenharmony_ci } 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci tsn = ntohl(tchunk->subh.data_hdr->tsn); 14548c2ecf20Sopenharmony_ci if (sctp_acked(sack, tsn)) { 14558c2ecf20Sopenharmony_ci /* If this queue is the retransmit queue, the 14568c2ecf20Sopenharmony_ci * retransmit timer has already reclaimed 14578c2ecf20Sopenharmony_ci * the outstanding bytes for this chunk, so only 14588c2ecf20Sopenharmony_ci * count bytes associated with a transport. 14598c2ecf20Sopenharmony_ci */ 14608c2ecf20Sopenharmony_ci if (transport && !tchunk->tsn_gap_acked) { 14618c2ecf20Sopenharmony_ci /* If this chunk is being used for RTT 14628c2ecf20Sopenharmony_ci * measurement, calculate the RTT and update 14638c2ecf20Sopenharmony_ci * the RTO using this value. 14648c2ecf20Sopenharmony_ci * 14658c2ecf20Sopenharmony_ci * 6.3.1 C5) Karn's algorithm: RTT measurements 14668c2ecf20Sopenharmony_ci * MUST NOT be made using packets that were 14678c2ecf20Sopenharmony_ci * retransmitted (and thus for which it is 14688c2ecf20Sopenharmony_ci * ambiguous whether the reply was for the 14698c2ecf20Sopenharmony_ci * first instance of the packet or a later 14708c2ecf20Sopenharmony_ci * instance). 14718c2ecf20Sopenharmony_ci */ 14728c2ecf20Sopenharmony_ci if (!sctp_chunk_retransmitted(tchunk) && 14738c2ecf20Sopenharmony_ci tchunk->rtt_in_progress) { 14748c2ecf20Sopenharmony_ci tchunk->rtt_in_progress = 0; 14758c2ecf20Sopenharmony_ci rtt = jiffies - tchunk->sent_at; 14768c2ecf20Sopenharmony_ci sctp_transport_update_rto(transport, 14778c2ecf20Sopenharmony_ci rtt); 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci if (TSN_lte(tsn, sack_ctsn)) { 14818c2ecf20Sopenharmony_ci /* 14828c2ecf20Sopenharmony_ci * SFR-CACC algorithm: 14838c2ecf20Sopenharmony_ci * 2) If the SACK contains gap acks 14848c2ecf20Sopenharmony_ci * and the flag CHANGEOVER_ACTIVE is 14858c2ecf20Sopenharmony_ci * set the receiver of the SACK MUST 14868c2ecf20Sopenharmony_ci * take the following action: 14878c2ecf20Sopenharmony_ci * 14888c2ecf20Sopenharmony_ci * B) For each TSN t being acked that 14898c2ecf20Sopenharmony_ci * has not been acked in any SACK so 14908c2ecf20Sopenharmony_ci * far, set cacc_saw_newack to 1 for 14918c2ecf20Sopenharmony_ci * the destination that the TSN was 14928c2ecf20Sopenharmony_ci * sent to. 14938c2ecf20Sopenharmony_ci */ 14948c2ecf20Sopenharmony_ci if (sack->num_gap_ack_blocks && 14958c2ecf20Sopenharmony_ci q->asoc->peer.primary_path->cacc. 14968c2ecf20Sopenharmony_ci changeover_active) 14978c2ecf20Sopenharmony_ci transport->cacc.cacc_saw_newack 14988c2ecf20Sopenharmony_ci = 1; 14998c2ecf20Sopenharmony_ci } 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* If the chunk hasn't been marked as ACKED, 15038c2ecf20Sopenharmony_ci * mark it and account bytes_acked if the 15048c2ecf20Sopenharmony_ci * chunk had a valid transport (it will not 15058c2ecf20Sopenharmony_ci * have a transport if ASCONF had deleted it 15068c2ecf20Sopenharmony_ci * while DATA was outstanding). 15078c2ecf20Sopenharmony_ci */ 15088c2ecf20Sopenharmony_ci if (!tchunk->tsn_gap_acked) { 15098c2ecf20Sopenharmony_ci tchunk->tsn_gap_acked = 1; 15108c2ecf20Sopenharmony_ci if (TSN_lt(*highest_new_tsn_in_sack, tsn)) 15118c2ecf20Sopenharmony_ci *highest_new_tsn_in_sack = tsn; 15128c2ecf20Sopenharmony_ci bytes_acked += sctp_data_size(tchunk); 15138c2ecf20Sopenharmony_ci if (!tchunk->transport) 15148c2ecf20Sopenharmony_ci migrate_bytes += sctp_data_size(tchunk); 15158c2ecf20Sopenharmony_ci forward_progress = true; 15168c2ecf20Sopenharmony_ci } 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (TSN_lte(tsn, sack_ctsn)) { 15198c2ecf20Sopenharmony_ci /* RFC 2960 6.3.2 Retransmission Timer Rules 15208c2ecf20Sopenharmony_ci * 15218c2ecf20Sopenharmony_ci * R3) Whenever a SACK is received 15228c2ecf20Sopenharmony_ci * that acknowledges the DATA chunk 15238c2ecf20Sopenharmony_ci * with the earliest outstanding TSN 15248c2ecf20Sopenharmony_ci * for that address, restart T3-rtx 15258c2ecf20Sopenharmony_ci * timer for that address with its 15268c2ecf20Sopenharmony_ci * current RTO. 15278c2ecf20Sopenharmony_ci */ 15288c2ecf20Sopenharmony_ci restart_timer = 1; 15298c2ecf20Sopenharmony_ci forward_progress = true; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci list_add_tail(&tchunk->transmitted_list, 15328c2ecf20Sopenharmony_ci &q->sacked); 15338c2ecf20Sopenharmony_ci } else { 15348c2ecf20Sopenharmony_ci /* RFC2960 7.2.4, sctpimpguide-05 2.8.2 15358c2ecf20Sopenharmony_ci * M2) Each time a SACK arrives reporting 15368c2ecf20Sopenharmony_ci * 'Stray DATA chunk(s)' record the highest TSN 15378c2ecf20Sopenharmony_ci * reported as newly acknowledged, call this 15388c2ecf20Sopenharmony_ci * value 'HighestTSNinSack'. A newly 15398c2ecf20Sopenharmony_ci * acknowledged DATA chunk is one not 15408c2ecf20Sopenharmony_ci * previously acknowledged in a SACK. 15418c2ecf20Sopenharmony_ci * 15428c2ecf20Sopenharmony_ci * When the SCTP sender of data receives a SACK 15438c2ecf20Sopenharmony_ci * chunk that acknowledges, for the first time, 15448c2ecf20Sopenharmony_ci * the receipt of a DATA chunk, all the still 15458c2ecf20Sopenharmony_ci * unacknowledged DATA chunks whose TSN is 15468c2ecf20Sopenharmony_ci * older than that newly acknowledged DATA 15478c2ecf20Sopenharmony_ci * chunk, are qualified as 'Stray DATA chunks'. 15488c2ecf20Sopenharmony_ci */ 15498c2ecf20Sopenharmony_ci list_add_tail(lchunk, &tlist); 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci } else { 15528c2ecf20Sopenharmony_ci if (tchunk->tsn_gap_acked) { 15538c2ecf20Sopenharmony_ci pr_debug("%s: receiver reneged on data TSN:0x%x\n", 15548c2ecf20Sopenharmony_ci __func__, tsn); 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci tchunk->tsn_gap_acked = 0; 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci if (tchunk->transport) 15598c2ecf20Sopenharmony_ci bytes_acked -= sctp_data_size(tchunk); 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci /* RFC 2960 6.3.2 Retransmission Timer Rules 15628c2ecf20Sopenharmony_ci * 15638c2ecf20Sopenharmony_ci * R4) Whenever a SACK is received missing a 15648c2ecf20Sopenharmony_ci * TSN that was previously acknowledged via a 15658c2ecf20Sopenharmony_ci * Gap Ack Block, start T3-rtx for the 15668c2ecf20Sopenharmony_ci * destination address to which the DATA 15678c2ecf20Sopenharmony_ci * chunk was originally 15688c2ecf20Sopenharmony_ci * transmitted if it is not already running. 15698c2ecf20Sopenharmony_ci */ 15708c2ecf20Sopenharmony_ci restart_timer = 1; 15718c2ecf20Sopenharmony_ci } 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci list_add_tail(lchunk, &tlist); 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (transport) { 15788c2ecf20Sopenharmony_ci if (bytes_acked) { 15798c2ecf20Sopenharmony_ci struct sctp_association *asoc = transport->asoc; 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci /* We may have counted DATA that was migrated 15828c2ecf20Sopenharmony_ci * to this transport due to DEL-IP operation. 15838c2ecf20Sopenharmony_ci * Subtract those bytes, since the were never 15848c2ecf20Sopenharmony_ci * send on this transport and shouldn't be 15858c2ecf20Sopenharmony_ci * credited to this transport. 15868c2ecf20Sopenharmony_ci */ 15878c2ecf20Sopenharmony_ci bytes_acked -= migrate_bytes; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci /* 8.2. When an outstanding TSN is acknowledged, 15908c2ecf20Sopenharmony_ci * the endpoint shall clear the error counter of 15918c2ecf20Sopenharmony_ci * the destination transport address to which the 15928c2ecf20Sopenharmony_ci * DATA chunk was last sent. 15938c2ecf20Sopenharmony_ci * The association's overall error counter is 15948c2ecf20Sopenharmony_ci * also cleared. 15958c2ecf20Sopenharmony_ci */ 15968c2ecf20Sopenharmony_ci transport->error_count = 0; 15978c2ecf20Sopenharmony_ci transport->asoc->overall_error_count = 0; 15988c2ecf20Sopenharmony_ci forward_progress = true; 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci /* 16018c2ecf20Sopenharmony_ci * While in SHUTDOWN PENDING, we may have started 16028c2ecf20Sopenharmony_ci * the T5 shutdown guard timer after reaching the 16038c2ecf20Sopenharmony_ci * retransmission limit. Stop that timer as soon 16048c2ecf20Sopenharmony_ci * as the receiver acknowledged any data. 16058c2ecf20Sopenharmony_ci */ 16068c2ecf20Sopenharmony_ci if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING && 16078c2ecf20Sopenharmony_ci del_timer(&asoc->timers 16088c2ecf20Sopenharmony_ci [SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD])) 16098c2ecf20Sopenharmony_ci sctp_association_put(asoc); 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci /* Mark the destination transport address as 16128c2ecf20Sopenharmony_ci * active if it is not so marked. 16138c2ecf20Sopenharmony_ci */ 16148c2ecf20Sopenharmony_ci if ((transport->state == SCTP_INACTIVE || 16158c2ecf20Sopenharmony_ci transport->state == SCTP_UNCONFIRMED) && 16168c2ecf20Sopenharmony_ci sctp_cmp_addr_exact(&transport->ipaddr, saddr)) { 16178c2ecf20Sopenharmony_ci sctp_assoc_control_transport( 16188c2ecf20Sopenharmony_ci transport->asoc, 16198c2ecf20Sopenharmony_ci transport, 16208c2ecf20Sopenharmony_ci SCTP_TRANSPORT_UP, 16218c2ecf20Sopenharmony_ci SCTP_RECEIVED_SACK); 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci sctp_transport_raise_cwnd(transport, sack_ctsn, 16258c2ecf20Sopenharmony_ci bytes_acked); 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci transport->flight_size -= bytes_acked; 16288c2ecf20Sopenharmony_ci if (transport->flight_size == 0) 16298c2ecf20Sopenharmony_ci transport->partial_bytes_acked = 0; 16308c2ecf20Sopenharmony_ci q->outstanding_bytes -= bytes_acked + migrate_bytes; 16318c2ecf20Sopenharmony_ci } else { 16328c2ecf20Sopenharmony_ci /* RFC 2960 6.1, sctpimpguide-06 2.15.2 16338c2ecf20Sopenharmony_ci * When a sender is doing zero window probing, it 16348c2ecf20Sopenharmony_ci * should not timeout the association if it continues 16358c2ecf20Sopenharmony_ci * to receive new packets from the receiver. The 16368c2ecf20Sopenharmony_ci * reason is that the receiver MAY keep its window 16378c2ecf20Sopenharmony_ci * closed for an indefinite time. 16388c2ecf20Sopenharmony_ci * A sender is doing zero window probing when the 16398c2ecf20Sopenharmony_ci * receiver's advertised window is zero, and there is 16408c2ecf20Sopenharmony_ci * only one data chunk in flight to the receiver. 16418c2ecf20Sopenharmony_ci * 16428c2ecf20Sopenharmony_ci * Allow the association to timeout while in SHUTDOWN 16438c2ecf20Sopenharmony_ci * PENDING or SHUTDOWN RECEIVED in case the receiver 16448c2ecf20Sopenharmony_ci * stays in zero window mode forever. 16458c2ecf20Sopenharmony_ci */ 16468c2ecf20Sopenharmony_ci if (!q->asoc->peer.rwnd && 16478c2ecf20Sopenharmony_ci !list_empty(&tlist) && 16488c2ecf20Sopenharmony_ci (sack_ctsn+2 == q->asoc->next_tsn) && 16498c2ecf20Sopenharmony_ci q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) { 16508c2ecf20Sopenharmony_ci pr_debug("%s: sack received for zero window " 16518c2ecf20Sopenharmony_ci "probe:%u\n", __func__, sack_ctsn); 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci q->asoc->overall_error_count = 0; 16548c2ecf20Sopenharmony_ci transport->error_count = 0; 16558c2ecf20Sopenharmony_ci } 16568c2ecf20Sopenharmony_ci } 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci /* RFC 2960 6.3.2 Retransmission Timer Rules 16598c2ecf20Sopenharmony_ci * 16608c2ecf20Sopenharmony_ci * R2) Whenever all outstanding data sent to an address have 16618c2ecf20Sopenharmony_ci * been acknowledged, turn off the T3-rtx timer of that 16628c2ecf20Sopenharmony_ci * address. 16638c2ecf20Sopenharmony_ci */ 16648c2ecf20Sopenharmony_ci if (!transport->flight_size) { 16658c2ecf20Sopenharmony_ci if (del_timer(&transport->T3_rtx_timer)) 16668c2ecf20Sopenharmony_ci sctp_transport_put(transport); 16678c2ecf20Sopenharmony_ci } else if (restart_timer) { 16688c2ecf20Sopenharmony_ci if (!mod_timer(&transport->T3_rtx_timer, 16698c2ecf20Sopenharmony_ci jiffies + transport->rto)) 16708c2ecf20Sopenharmony_ci sctp_transport_hold(transport); 16718c2ecf20Sopenharmony_ci } 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci if (forward_progress) { 16748c2ecf20Sopenharmony_ci if (transport->dst) 16758c2ecf20Sopenharmony_ci sctp_transport_dst_confirm(transport); 16768c2ecf20Sopenharmony_ci } 16778c2ecf20Sopenharmony_ci } 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci list_splice(&tlist, transmitted_queue); 16808c2ecf20Sopenharmony_ci} 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci/* Mark chunks as missing and consequently may get retransmitted. */ 16838c2ecf20Sopenharmony_cistatic void sctp_mark_missing(struct sctp_outq *q, 16848c2ecf20Sopenharmony_ci struct list_head *transmitted_queue, 16858c2ecf20Sopenharmony_ci struct sctp_transport *transport, 16868c2ecf20Sopenharmony_ci __u32 highest_new_tsn_in_sack, 16878c2ecf20Sopenharmony_ci int count_of_newacks) 16888c2ecf20Sopenharmony_ci{ 16898c2ecf20Sopenharmony_ci struct sctp_chunk *chunk; 16908c2ecf20Sopenharmony_ci __u32 tsn; 16918c2ecf20Sopenharmony_ci char do_fast_retransmit = 0; 16928c2ecf20Sopenharmony_ci struct sctp_association *asoc = q->asoc; 16938c2ecf20Sopenharmony_ci struct sctp_transport *primary = asoc->peer.primary_path; 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci list_for_each_entry(chunk, transmitted_queue, transmitted_list) { 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci tsn = ntohl(chunk->subh.data_hdr->tsn); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci /* RFC 2960 7.2.4, sctpimpguide-05 2.8.2 M3) Examine all 17008c2ecf20Sopenharmony_ci * 'Unacknowledged TSN's', if the TSN number of an 17018c2ecf20Sopenharmony_ci * 'Unacknowledged TSN' is smaller than the 'HighestTSNinSack' 17028c2ecf20Sopenharmony_ci * value, increment the 'TSN.Missing.Report' count on that 17038c2ecf20Sopenharmony_ci * chunk if it has NOT been fast retransmitted or marked for 17048c2ecf20Sopenharmony_ci * fast retransmit already. 17058c2ecf20Sopenharmony_ci */ 17068c2ecf20Sopenharmony_ci if (chunk->fast_retransmit == SCTP_CAN_FRTX && 17078c2ecf20Sopenharmony_ci !chunk->tsn_gap_acked && 17088c2ecf20Sopenharmony_ci TSN_lt(tsn, highest_new_tsn_in_sack)) { 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci /* SFR-CACC may require us to skip marking 17118c2ecf20Sopenharmony_ci * this chunk as missing. 17128c2ecf20Sopenharmony_ci */ 17138c2ecf20Sopenharmony_ci if (!transport || !sctp_cacc_skip(primary, 17148c2ecf20Sopenharmony_ci chunk->transport, 17158c2ecf20Sopenharmony_ci count_of_newacks, tsn)) { 17168c2ecf20Sopenharmony_ci chunk->tsn_missing_report++; 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci pr_debug("%s: tsn:0x%x missing counter:%d\n", 17198c2ecf20Sopenharmony_ci __func__, tsn, chunk->tsn_missing_report); 17208c2ecf20Sopenharmony_ci } 17218c2ecf20Sopenharmony_ci } 17228c2ecf20Sopenharmony_ci /* 17238c2ecf20Sopenharmony_ci * M4) If any DATA chunk is found to have a 17248c2ecf20Sopenharmony_ci * 'TSN.Missing.Report' 17258c2ecf20Sopenharmony_ci * value larger than or equal to 3, mark that chunk for 17268c2ecf20Sopenharmony_ci * retransmission and start the fast retransmit procedure. 17278c2ecf20Sopenharmony_ci */ 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci if (chunk->tsn_missing_report >= 3) { 17308c2ecf20Sopenharmony_ci chunk->fast_retransmit = SCTP_NEED_FRTX; 17318c2ecf20Sopenharmony_ci do_fast_retransmit = 1; 17328c2ecf20Sopenharmony_ci } 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci if (transport) { 17368c2ecf20Sopenharmony_ci if (do_fast_retransmit) 17378c2ecf20Sopenharmony_ci sctp_retransmit(q, transport, SCTP_RTXR_FAST_RTX); 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci pr_debug("%s: transport:%p, cwnd:%d, ssthresh:%d, " 17408c2ecf20Sopenharmony_ci "flight_size:%d, pba:%d\n", __func__, transport, 17418c2ecf20Sopenharmony_ci transport->cwnd, transport->ssthresh, 17428c2ecf20Sopenharmony_ci transport->flight_size, transport->partial_bytes_acked); 17438c2ecf20Sopenharmony_ci } 17448c2ecf20Sopenharmony_ci} 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci/* Is the given TSN acked by this packet? */ 17478c2ecf20Sopenharmony_cistatic int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn) 17488c2ecf20Sopenharmony_ci{ 17498c2ecf20Sopenharmony_ci __u32 ctsn = ntohl(sack->cum_tsn_ack); 17508c2ecf20Sopenharmony_ci union sctp_sack_variable *frags; 17518c2ecf20Sopenharmony_ci __u16 tsn_offset, blocks; 17528c2ecf20Sopenharmony_ci int i; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci if (TSN_lte(tsn, ctsn)) 17558c2ecf20Sopenharmony_ci goto pass; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci /* 3.3.4 Selective Acknowledgment (SACK) (3): 17588c2ecf20Sopenharmony_ci * 17598c2ecf20Sopenharmony_ci * Gap Ack Blocks: 17608c2ecf20Sopenharmony_ci * These fields contain the Gap Ack Blocks. They are repeated 17618c2ecf20Sopenharmony_ci * for each Gap Ack Block up to the number of Gap Ack Blocks 17628c2ecf20Sopenharmony_ci * defined in the Number of Gap Ack Blocks field. All DATA 17638c2ecf20Sopenharmony_ci * chunks with TSNs greater than or equal to (Cumulative TSN 17648c2ecf20Sopenharmony_ci * Ack + Gap Ack Block Start) and less than or equal to 17658c2ecf20Sopenharmony_ci * (Cumulative TSN Ack + Gap Ack Block End) of each Gap Ack 17668c2ecf20Sopenharmony_ci * Block are assumed to have been received correctly. 17678c2ecf20Sopenharmony_ci */ 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci frags = sack->variable; 17708c2ecf20Sopenharmony_ci blocks = ntohs(sack->num_gap_ack_blocks); 17718c2ecf20Sopenharmony_ci tsn_offset = tsn - ctsn; 17728c2ecf20Sopenharmony_ci for (i = 0; i < blocks; ++i) { 17738c2ecf20Sopenharmony_ci if (tsn_offset >= ntohs(frags[i].gab.start) && 17748c2ecf20Sopenharmony_ci tsn_offset <= ntohs(frags[i].gab.end)) 17758c2ecf20Sopenharmony_ci goto pass; 17768c2ecf20Sopenharmony_ci } 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci return 0; 17798c2ecf20Sopenharmony_cipass: 17808c2ecf20Sopenharmony_ci return 1; 17818c2ecf20Sopenharmony_ci} 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_cistatic inline int sctp_get_skip_pos(struct sctp_fwdtsn_skip *skiplist, 17848c2ecf20Sopenharmony_ci int nskips, __be16 stream) 17858c2ecf20Sopenharmony_ci{ 17868c2ecf20Sopenharmony_ci int i; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci for (i = 0; i < nskips; i++) { 17898c2ecf20Sopenharmony_ci if (skiplist[i].stream == stream) 17908c2ecf20Sopenharmony_ci return i; 17918c2ecf20Sopenharmony_ci } 17928c2ecf20Sopenharmony_ci return i; 17938c2ecf20Sopenharmony_ci} 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci/* Create and add a fwdtsn chunk to the outq's control queue if needed. */ 17968c2ecf20Sopenharmony_civoid sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) 17978c2ecf20Sopenharmony_ci{ 17988c2ecf20Sopenharmony_ci struct sctp_association *asoc = q->asoc; 17998c2ecf20Sopenharmony_ci struct sctp_chunk *ftsn_chunk = NULL; 18008c2ecf20Sopenharmony_ci struct sctp_fwdtsn_skip ftsn_skip_arr[10]; 18018c2ecf20Sopenharmony_ci int nskips = 0; 18028c2ecf20Sopenharmony_ci int skip_pos = 0; 18038c2ecf20Sopenharmony_ci __u32 tsn; 18048c2ecf20Sopenharmony_ci struct sctp_chunk *chunk; 18058c2ecf20Sopenharmony_ci struct list_head *lchunk, *temp; 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci if (!asoc->peer.prsctp_capable) 18088c2ecf20Sopenharmony_ci return; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci /* PR-SCTP C1) Let SackCumAck be the Cumulative TSN ACK carried in the 18118c2ecf20Sopenharmony_ci * received SACK. 18128c2ecf20Sopenharmony_ci * 18138c2ecf20Sopenharmony_ci * If (Advanced.Peer.Ack.Point < SackCumAck), then update 18148c2ecf20Sopenharmony_ci * Advanced.Peer.Ack.Point to be equal to SackCumAck. 18158c2ecf20Sopenharmony_ci */ 18168c2ecf20Sopenharmony_ci if (TSN_lt(asoc->adv_peer_ack_point, ctsn)) 18178c2ecf20Sopenharmony_ci asoc->adv_peer_ack_point = ctsn; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci /* PR-SCTP C2) Try to further advance the "Advanced.Peer.Ack.Point" 18208c2ecf20Sopenharmony_ci * locally, that is, to move "Advanced.Peer.Ack.Point" up as long as 18218c2ecf20Sopenharmony_ci * the chunk next in the out-queue space is marked as "abandoned" as 18228c2ecf20Sopenharmony_ci * shown in the following example: 18238c2ecf20Sopenharmony_ci * 18248c2ecf20Sopenharmony_ci * Assuming that a SACK arrived with the Cumulative TSN ACK 102 18258c2ecf20Sopenharmony_ci * and the Advanced.Peer.Ack.Point is updated to this value: 18268c2ecf20Sopenharmony_ci * 18278c2ecf20Sopenharmony_ci * out-queue at the end of ==> out-queue after Adv.Ack.Point 18288c2ecf20Sopenharmony_ci * normal SACK processing local advancement 18298c2ecf20Sopenharmony_ci * ... ... 18308c2ecf20Sopenharmony_ci * Adv.Ack.Pt-> 102 acked 102 acked 18318c2ecf20Sopenharmony_ci * 103 abandoned 103 abandoned 18328c2ecf20Sopenharmony_ci * 104 abandoned Adv.Ack.P-> 104 abandoned 18338c2ecf20Sopenharmony_ci * 105 105 18348c2ecf20Sopenharmony_ci * 106 acked 106 acked 18358c2ecf20Sopenharmony_ci * ... ... 18368c2ecf20Sopenharmony_ci * 18378c2ecf20Sopenharmony_ci * In this example, the data sender successfully advanced the 18388c2ecf20Sopenharmony_ci * "Advanced.Peer.Ack.Point" from 102 to 104 locally. 18398c2ecf20Sopenharmony_ci */ 18408c2ecf20Sopenharmony_ci list_for_each_safe(lchunk, temp, &q->abandoned) { 18418c2ecf20Sopenharmony_ci chunk = list_entry(lchunk, struct sctp_chunk, 18428c2ecf20Sopenharmony_ci transmitted_list); 18438c2ecf20Sopenharmony_ci tsn = ntohl(chunk->subh.data_hdr->tsn); 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci /* Remove any chunks in the abandoned queue that are acked by 18468c2ecf20Sopenharmony_ci * the ctsn. 18478c2ecf20Sopenharmony_ci */ 18488c2ecf20Sopenharmony_ci if (TSN_lte(tsn, ctsn)) { 18498c2ecf20Sopenharmony_ci list_del_init(lchunk); 18508c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 18518c2ecf20Sopenharmony_ci } else { 18528c2ecf20Sopenharmony_ci if (TSN_lte(tsn, asoc->adv_peer_ack_point+1)) { 18538c2ecf20Sopenharmony_ci asoc->adv_peer_ack_point = tsn; 18548c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->flags & 18558c2ecf20Sopenharmony_ci SCTP_DATA_UNORDERED) 18568c2ecf20Sopenharmony_ci continue; 18578c2ecf20Sopenharmony_ci skip_pos = sctp_get_skip_pos(&ftsn_skip_arr[0], 18588c2ecf20Sopenharmony_ci nskips, 18598c2ecf20Sopenharmony_ci chunk->subh.data_hdr->stream); 18608c2ecf20Sopenharmony_ci ftsn_skip_arr[skip_pos].stream = 18618c2ecf20Sopenharmony_ci chunk->subh.data_hdr->stream; 18628c2ecf20Sopenharmony_ci ftsn_skip_arr[skip_pos].ssn = 18638c2ecf20Sopenharmony_ci chunk->subh.data_hdr->ssn; 18648c2ecf20Sopenharmony_ci if (skip_pos == nskips) 18658c2ecf20Sopenharmony_ci nskips++; 18668c2ecf20Sopenharmony_ci if (nskips == 10) 18678c2ecf20Sopenharmony_ci break; 18688c2ecf20Sopenharmony_ci } else 18698c2ecf20Sopenharmony_ci break; 18708c2ecf20Sopenharmony_ci } 18718c2ecf20Sopenharmony_ci } 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci /* PR-SCTP C3) If, after step C1 and C2, the "Advanced.Peer.Ack.Point" 18748c2ecf20Sopenharmony_ci * is greater than the Cumulative TSN ACK carried in the received 18758c2ecf20Sopenharmony_ci * SACK, the data sender MUST send the data receiver a FORWARD TSN 18768c2ecf20Sopenharmony_ci * chunk containing the latest value of the 18778c2ecf20Sopenharmony_ci * "Advanced.Peer.Ack.Point". 18788c2ecf20Sopenharmony_ci * 18798c2ecf20Sopenharmony_ci * C4) For each "abandoned" TSN the sender of the FORWARD TSN SHOULD 18808c2ecf20Sopenharmony_ci * list each stream and sequence number in the forwarded TSN. This 18818c2ecf20Sopenharmony_ci * information will enable the receiver to easily find any 18828c2ecf20Sopenharmony_ci * stranded TSN's waiting on stream reorder queues. Each stream 18838c2ecf20Sopenharmony_ci * SHOULD only be reported once; this means that if multiple 18848c2ecf20Sopenharmony_ci * abandoned messages occur in the same stream then only the 18858c2ecf20Sopenharmony_ci * highest abandoned stream sequence number is reported. If the 18868c2ecf20Sopenharmony_ci * total size of the FORWARD TSN does NOT fit in a single MTU then 18878c2ecf20Sopenharmony_ci * the sender of the FORWARD TSN SHOULD lower the 18888c2ecf20Sopenharmony_ci * Advanced.Peer.Ack.Point to the last TSN that will fit in a 18898c2ecf20Sopenharmony_ci * single MTU. 18908c2ecf20Sopenharmony_ci */ 18918c2ecf20Sopenharmony_ci if (asoc->adv_peer_ack_point > ctsn) 18928c2ecf20Sopenharmony_ci ftsn_chunk = sctp_make_fwdtsn(asoc, asoc->adv_peer_ack_point, 18938c2ecf20Sopenharmony_ci nskips, &ftsn_skip_arr[0]); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci if (ftsn_chunk) { 18968c2ecf20Sopenharmony_ci list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); 18978c2ecf20Sopenharmony_ci SCTP_INC_STATS(asoc->base.net, SCTP_MIB_OUTCTRLCHUNKS); 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci} 1900