18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * net/dccp/ackvec.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * An implementation of Ack Vectors for the DCCP protocol 68c2ecf20Sopenharmony_ci * Copyright (c) 2007 University of Aberdeen, Scotland, UK 78c2ecf20Sopenharmony_ci * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include "dccp.h" 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/export.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic struct kmem_cache *dccp_ackvec_slab; 158c2ecf20Sopenharmony_cistatic struct kmem_cache *dccp_ackvec_record_slab; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci struct dccp_ackvec *av = kmem_cache_zalloc(dccp_ackvec_slab, priority); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (av != NULL) { 228c2ecf20Sopenharmony_ci av->av_buf_head = av->av_buf_tail = DCCPAV_MAX_ACKVEC_LEN - 1; 238c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&av->av_records); 248c2ecf20Sopenharmony_ci } 258c2ecf20Sopenharmony_ci return av; 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void dccp_ackvec_purge_records(struct dccp_ackvec *av) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct dccp_ackvec_record *cur, *next; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci list_for_each_entry_safe(cur, next, &av->av_records, avr_node) 338c2ecf20Sopenharmony_ci kmem_cache_free(dccp_ackvec_record_slab, cur); 348c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&av->av_records); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_civoid dccp_ackvec_free(struct dccp_ackvec *av) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci if (likely(av != NULL)) { 408c2ecf20Sopenharmony_ci dccp_ackvec_purge_records(av); 418c2ecf20Sopenharmony_ci kmem_cache_free(dccp_ackvec_slab, av); 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/** 468c2ecf20Sopenharmony_ci * dccp_ackvec_update_records - Record information about sent Ack Vectors 478c2ecf20Sopenharmony_ci * @av: Ack Vector records to update 488c2ecf20Sopenharmony_ci * @seqno: Sequence number of the packet carrying the Ack Vector just sent 498c2ecf20Sopenharmony_ci * @nonce_sum: The sum of all buffer nonces contained in the Ack Vector 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ciint dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seqno, u8 nonce_sum) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct dccp_ackvec_record *avr; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci avr = kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC); 568c2ecf20Sopenharmony_ci if (avr == NULL) 578c2ecf20Sopenharmony_ci return -ENOBUFS; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci avr->avr_ack_seqno = seqno; 608c2ecf20Sopenharmony_ci avr->avr_ack_ptr = av->av_buf_head; 618c2ecf20Sopenharmony_ci avr->avr_ack_ackno = av->av_buf_ackno; 628c2ecf20Sopenharmony_ci avr->avr_ack_nonce = nonce_sum; 638c2ecf20Sopenharmony_ci avr->avr_ack_runlen = dccp_ackvec_runlen(av->av_buf + av->av_buf_head); 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * When the buffer overflows, we keep no more than one record. This is 668c2ecf20Sopenharmony_ci * the simplest way of disambiguating sender-Acks dating from before the 678c2ecf20Sopenharmony_ci * overflow from sender-Acks which refer to after the overflow; a simple 688c2ecf20Sopenharmony_ci * solution is preferable here since we are handling an exception. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci if (av->av_overflow) 718c2ecf20Sopenharmony_ci dccp_ackvec_purge_records(av); 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * Since GSS is incremented for each packet, the list is automatically 748c2ecf20Sopenharmony_ci * arranged in descending order of @ack_seqno. 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci list_add(&avr->avr_node, &av->av_records); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci dccp_pr_debug("Added Vector, ack_seqno=%llu, ack_ackno=%llu (rl=%u)\n", 798c2ecf20Sopenharmony_ci (unsigned long long)avr->avr_ack_seqno, 808c2ecf20Sopenharmony_ci (unsigned long long)avr->avr_ack_ackno, 818c2ecf20Sopenharmony_ci avr->avr_ack_runlen); 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic struct dccp_ackvec_record *dccp_ackvec_lookup(struct list_head *av_list, 868c2ecf20Sopenharmony_ci const u64 ackno) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct dccp_ackvec_record *avr; 898c2ecf20Sopenharmony_ci /* 908c2ecf20Sopenharmony_ci * Exploit that records are inserted in descending order of sequence 918c2ecf20Sopenharmony_ci * number, start with the oldest record first. If @ackno is `before' 928c2ecf20Sopenharmony_ci * the earliest ack_ackno, the packet is too old to be considered. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci list_for_each_entry_reverse(avr, av_list, avr_node) { 958c2ecf20Sopenharmony_ci if (avr->avr_ack_seqno == ackno) 968c2ecf20Sopenharmony_ci return avr; 978c2ecf20Sopenharmony_ci if (before48(ackno, avr->avr_ack_seqno)) 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci return NULL; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* 1048c2ecf20Sopenharmony_ci * Buffer index and length computation using modulo-buffersize arithmetic. 1058c2ecf20Sopenharmony_ci * Note that, as pointers move from right to left, head is `before' tail. 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_cistatic inline u16 __ackvec_idx_add(const u16 a, const u16 b) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci return (a + b) % DCCPAV_MAX_ACKVEC_LEN; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic inline u16 __ackvec_idx_sub(const u16 a, const u16 b) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci return __ackvec_idx_add(a, DCCPAV_MAX_ACKVEC_LEN - b); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ciu16 dccp_ackvec_buflen(const struct dccp_ackvec *av) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci if (unlikely(av->av_overflow)) 1208c2ecf20Sopenharmony_ci return DCCPAV_MAX_ACKVEC_LEN; 1218c2ecf20Sopenharmony_ci return __ackvec_idx_sub(av->av_buf_tail, av->av_buf_head); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/** 1258c2ecf20Sopenharmony_ci * dccp_ackvec_update_old - Update previous state as per RFC 4340, 11.4.1 1268c2ecf20Sopenharmony_ci * @av: non-empty buffer to update 1278c2ecf20Sopenharmony_ci * @distance: negative or zero distance of @seqno from buf_ackno downward 1288c2ecf20Sopenharmony_ci * @seqno: the (old) sequence number whose record is to be updated 1298c2ecf20Sopenharmony_ci * @state: state in which packet carrying @seqno was received 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_cistatic void dccp_ackvec_update_old(struct dccp_ackvec *av, s64 distance, 1328c2ecf20Sopenharmony_ci u64 seqno, enum dccp_ackvec_states state) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci u16 ptr = av->av_buf_head; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci BUG_ON(distance > 0); 1378c2ecf20Sopenharmony_ci if (unlikely(dccp_ackvec_is_empty(av))) 1388c2ecf20Sopenharmony_ci return; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci do { 1418c2ecf20Sopenharmony_ci u8 runlen = dccp_ackvec_runlen(av->av_buf + ptr); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (distance + runlen >= 0) { 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * Only update the state if packet has not been received 1468c2ecf20Sopenharmony_ci * yet. This is OK as per the second table in RFC 4340, 1478c2ecf20Sopenharmony_ci * 11.4.1; i.e. here we are using the following table: 1488c2ecf20Sopenharmony_ci * RECEIVED 1498c2ecf20Sopenharmony_ci * 0 1 3 1508c2ecf20Sopenharmony_ci * S +---+---+---+ 1518c2ecf20Sopenharmony_ci * T 0 | 0 | 0 | 0 | 1528c2ecf20Sopenharmony_ci * O +---+---+---+ 1538c2ecf20Sopenharmony_ci * R 1 | 1 | 1 | 1 | 1548c2ecf20Sopenharmony_ci * E +---+---+---+ 1558c2ecf20Sopenharmony_ci * D 3 | 0 | 1 | 3 | 1568c2ecf20Sopenharmony_ci * +---+---+---+ 1578c2ecf20Sopenharmony_ci * The "Not Received" state was set by reserve_seats(). 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci if (av->av_buf[ptr] == DCCPAV_NOT_RECEIVED) 1608c2ecf20Sopenharmony_ci av->av_buf[ptr] = state; 1618c2ecf20Sopenharmony_ci else 1628c2ecf20Sopenharmony_ci dccp_pr_debug("Not changing %llu state to %u\n", 1638c2ecf20Sopenharmony_ci (unsigned long long)seqno, state); 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci distance += runlen + 1; 1688c2ecf20Sopenharmony_ci ptr = __ackvec_idx_add(ptr, 1); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci } while (ptr != av->av_buf_tail); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* Mark @num entries after buf_head as "Not yet received". */ 1748c2ecf20Sopenharmony_cistatic void dccp_ackvec_reserve_seats(struct dccp_ackvec *av, u16 num) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci u16 start = __ackvec_idx_add(av->av_buf_head, 1), 1778c2ecf20Sopenharmony_ci len = DCCPAV_MAX_ACKVEC_LEN - start; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* check for buffer wrap-around */ 1808c2ecf20Sopenharmony_ci if (num > len) { 1818c2ecf20Sopenharmony_ci memset(av->av_buf + start, DCCPAV_NOT_RECEIVED, len); 1828c2ecf20Sopenharmony_ci start = 0; 1838c2ecf20Sopenharmony_ci num -= len; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci if (num) 1868c2ecf20Sopenharmony_ci memset(av->av_buf + start, DCCPAV_NOT_RECEIVED, num); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci/** 1908c2ecf20Sopenharmony_ci * dccp_ackvec_add_new - Record one or more new entries in Ack Vector buffer 1918c2ecf20Sopenharmony_ci * @av: container of buffer to update (can be empty or non-empty) 1928c2ecf20Sopenharmony_ci * @num_packets: number of packets to register (must be >= 1) 1938c2ecf20Sopenharmony_ci * @seqno: sequence number of the first packet in @num_packets 1948c2ecf20Sopenharmony_ci * @state: state in which packet carrying @seqno was received 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_cistatic void dccp_ackvec_add_new(struct dccp_ackvec *av, u32 num_packets, 1978c2ecf20Sopenharmony_ci u64 seqno, enum dccp_ackvec_states state) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci u32 num_cells = num_packets; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (num_packets > DCCPAV_BURST_THRESH) { 2028c2ecf20Sopenharmony_ci u32 lost_packets = num_packets - 1; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci DCCP_WARN("Warning: large burst loss (%u)\n", lost_packets); 2058c2ecf20Sopenharmony_ci /* 2068c2ecf20Sopenharmony_ci * We received 1 packet and have a loss of size "num_packets-1" 2078c2ecf20Sopenharmony_ci * which we squeeze into num_cells-1 rather than reserving an 2088c2ecf20Sopenharmony_ci * entire byte for each lost packet. 2098c2ecf20Sopenharmony_ci * The reason is that the vector grows in O(burst_length); when 2108c2ecf20Sopenharmony_ci * it grows too large there will no room left for the payload. 2118c2ecf20Sopenharmony_ci * This is a trade-off: if a few packets out of the burst show 2128c2ecf20Sopenharmony_ci * up later, their state will not be changed; it is simply too 2138c2ecf20Sopenharmony_ci * costly to reshuffle/reallocate/copy the buffer each time. 2148c2ecf20Sopenharmony_ci * Should such problems persist, we will need to switch to a 2158c2ecf20Sopenharmony_ci * different underlying data structure. 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci for (num_packets = num_cells = 1; lost_packets; ++num_cells) { 2188c2ecf20Sopenharmony_ci u8 len = min_t(u32, lost_packets, DCCPAV_MAX_RUNLEN); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci av->av_buf_head = __ackvec_idx_sub(av->av_buf_head, 1); 2218c2ecf20Sopenharmony_ci av->av_buf[av->av_buf_head] = DCCPAV_NOT_RECEIVED | len; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci lost_packets -= len; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (num_cells + dccp_ackvec_buflen(av) >= DCCPAV_MAX_ACKVEC_LEN) { 2288c2ecf20Sopenharmony_ci DCCP_CRIT("Ack Vector buffer overflow: dropping old entries"); 2298c2ecf20Sopenharmony_ci av->av_overflow = true; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci av->av_buf_head = __ackvec_idx_sub(av->av_buf_head, num_packets); 2338c2ecf20Sopenharmony_ci if (av->av_overflow) 2348c2ecf20Sopenharmony_ci av->av_buf_tail = av->av_buf_head; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci av->av_buf[av->av_buf_head] = state; 2378c2ecf20Sopenharmony_ci av->av_buf_ackno = seqno; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (num_packets > 1) 2408c2ecf20Sopenharmony_ci dccp_ackvec_reserve_seats(av, num_packets - 1); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci/** 2448c2ecf20Sopenharmony_ci * dccp_ackvec_input - Register incoming packet in the buffer 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_civoid dccp_ackvec_input(struct dccp_ackvec *av, struct sk_buff *skb) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci u64 seqno = DCCP_SKB_CB(skb)->dccpd_seq; 2498c2ecf20Sopenharmony_ci enum dccp_ackvec_states state = DCCPAV_RECEIVED; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (dccp_ackvec_is_empty(av)) { 2528c2ecf20Sopenharmony_ci dccp_ackvec_add_new(av, 1, seqno, state); 2538c2ecf20Sopenharmony_ci av->av_tail_ackno = seqno; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci } else { 2568c2ecf20Sopenharmony_ci s64 num_packets = dccp_delta_seqno(av->av_buf_ackno, seqno); 2578c2ecf20Sopenharmony_ci u8 *current_head = av->av_buf + av->av_buf_head; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci if (num_packets == 1 && 2608c2ecf20Sopenharmony_ci dccp_ackvec_state(current_head) == state && 2618c2ecf20Sopenharmony_ci dccp_ackvec_runlen(current_head) < DCCPAV_MAX_RUNLEN) { 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci *current_head += 1; 2648c2ecf20Sopenharmony_ci av->av_buf_ackno = seqno; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci } else if (num_packets > 0) { 2678c2ecf20Sopenharmony_ci dccp_ackvec_add_new(av, num_packets, seqno, state); 2688c2ecf20Sopenharmony_ci } else { 2698c2ecf20Sopenharmony_ci dccp_ackvec_update_old(av, num_packets, seqno, state); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/** 2758c2ecf20Sopenharmony_ci * dccp_ackvec_clear_state - Perform house-keeping / garbage-collection 2768c2ecf20Sopenharmony_ci * This routine is called when the peer acknowledges the receipt of Ack Vectors 2778c2ecf20Sopenharmony_ci * up to and including @ackno. While based on section A.3 of RFC 4340, here 2788c2ecf20Sopenharmony_ci * are additional precautions to prevent corrupted buffer state. In particular, 2798c2ecf20Sopenharmony_ci * we use tail_ackno to identify outdated records; it always marks the earliest 2808c2ecf20Sopenharmony_ci * packet of group (2) in 11.4.2. 2818c2ecf20Sopenharmony_ci */ 2828c2ecf20Sopenharmony_civoid dccp_ackvec_clear_state(struct dccp_ackvec *av, const u64 ackno) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct dccp_ackvec_record *avr, *next; 2858c2ecf20Sopenharmony_ci u8 runlen_now, eff_runlen; 2868c2ecf20Sopenharmony_ci s64 delta; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci avr = dccp_ackvec_lookup(&av->av_records, ackno); 2898c2ecf20Sopenharmony_ci if (avr == NULL) 2908c2ecf20Sopenharmony_ci return; 2918c2ecf20Sopenharmony_ci /* 2928c2ecf20Sopenharmony_ci * Deal with outdated acknowledgments: this arises when e.g. there are 2938c2ecf20Sopenharmony_ci * several old records and the acks from the peer come in slowly. In 2948c2ecf20Sopenharmony_ci * that case we may still have records that pre-date tail_ackno. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci delta = dccp_delta_seqno(av->av_tail_ackno, avr->avr_ack_ackno); 2978c2ecf20Sopenharmony_ci if (delta < 0) 2988c2ecf20Sopenharmony_ci goto free_records; 2998c2ecf20Sopenharmony_ci /* 3008c2ecf20Sopenharmony_ci * Deal with overlapping Ack Vectors: don't subtract more than the 3018c2ecf20Sopenharmony_ci * number of packets between tail_ackno and ack_ackno. 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_ci eff_runlen = delta < avr->avr_ack_runlen ? delta : avr->avr_ack_runlen; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci runlen_now = dccp_ackvec_runlen(av->av_buf + avr->avr_ack_ptr); 3068c2ecf20Sopenharmony_ci /* 3078c2ecf20Sopenharmony_ci * The run length of Ack Vector cells does not decrease over time. If 3088c2ecf20Sopenharmony_ci * the run length is the same as at the time the Ack Vector was sent, we 3098c2ecf20Sopenharmony_ci * free the ack_ptr cell. That cell can however not be freed if the run 3108c2ecf20Sopenharmony_ci * length has increased: in this case we need to move the tail pointer 3118c2ecf20Sopenharmony_ci * backwards (towards higher indices), to its next-oldest neighbour. 3128c2ecf20Sopenharmony_ci */ 3138c2ecf20Sopenharmony_ci if (runlen_now > eff_runlen) { 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci av->av_buf[avr->avr_ack_ptr] -= eff_runlen + 1; 3168c2ecf20Sopenharmony_ci av->av_buf_tail = __ackvec_idx_add(avr->avr_ack_ptr, 1); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* This move may not have cleared the overflow flag. */ 3198c2ecf20Sopenharmony_ci if (av->av_overflow) 3208c2ecf20Sopenharmony_ci av->av_overflow = (av->av_buf_head == av->av_buf_tail); 3218c2ecf20Sopenharmony_ci } else { 3228c2ecf20Sopenharmony_ci av->av_buf_tail = avr->avr_ack_ptr; 3238c2ecf20Sopenharmony_ci /* 3248c2ecf20Sopenharmony_ci * We have made sure that avr points to a valid cell within the 3258c2ecf20Sopenharmony_ci * buffer. This cell is either older than head, or equals head 3268c2ecf20Sopenharmony_ci * (empty buffer): in both cases we no longer have any overflow. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ci av->av_overflow = 0; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* 3328c2ecf20Sopenharmony_ci * The peer has acknowledged up to and including ack_ackno. Hence the 3338c2ecf20Sopenharmony_ci * first packet in group (2) of 11.4.2 is the successor of ack_ackno. 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ci av->av_tail_ackno = ADD48(avr->avr_ack_ackno, 1); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cifree_records: 3388c2ecf20Sopenharmony_ci list_for_each_entry_safe_from(avr, next, &av->av_records, avr_node) { 3398c2ecf20Sopenharmony_ci list_del(&avr->avr_node); 3408c2ecf20Sopenharmony_ci kmem_cache_free(dccp_ackvec_record_slab, avr); 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/* 3458c2ecf20Sopenharmony_ci * Routines to keep track of Ack Vectors received in an skb 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ciint dccp_ackvec_parsed_add(struct list_head *head, u8 *vec, u8 len, u8 nonce) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci struct dccp_ackvec_parsed *new = kmalloc(sizeof(*new), GFP_ATOMIC); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci if (new == NULL) 3528c2ecf20Sopenharmony_ci return -ENOBUFS; 3538c2ecf20Sopenharmony_ci new->vec = vec; 3548c2ecf20Sopenharmony_ci new->len = len; 3558c2ecf20Sopenharmony_ci new->nonce = nonce; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci list_add_tail(&new->node, head); 3588c2ecf20Sopenharmony_ci return 0; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dccp_ackvec_parsed_add); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_civoid dccp_ackvec_parsed_cleanup(struct list_head *parsed_chunks) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci struct dccp_ackvec_parsed *cur, *next; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci list_for_each_entry_safe(cur, next, parsed_chunks, node) 3678c2ecf20Sopenharmony_ci kfree(cur); 3688c2ecf20Sopenharmony_ci INIT_LIST_HEAD(parsed_chunks); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dccp_ackvec_parsed_cleanup); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ciint __init dccp_ackvec_init(void) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci dccp_ackvec_slab = kmem_cache_create("dccp_ackvec", 3758c2ecf20Sopenharmony_ci sizeof(struct dccp_ackvec), 0, 3768c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL); 3778c2ecf20Sopenharmony_ci if (dccp_ackvec_slab == NULL) 3788c2ecf20Sopenharmony_ci goto out_err; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci dccp_ackvec_record_slab = kmem_cache_create("dccp_ackvec_record", 3818c2ecf20Sopenharmony_ci sizeof(struct dccp_ackvec_record), 3828c2ecf20Sopenharmony_ci 0, SLAB_HWCACHE_ALIGN, NULL); 3838c2ecf20Sopenharmony_ci if (dccp_ackvec_record_slab == NULL) 3848c2ecf20Sopenharmony_ci goto out_destroy_slab; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci return 0; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ciout_destroy_slab: 3898c2ecf20Sopenharmony_ci kmem_cache_destroy(dccp_ackvec_slab); 3908c2ecf20Sopenharmony_ci dccp_ackvec_slab = NULL; 3918c2ecf20Sopenharmony_ciout_err: 3928c2ecf20Sopenharmony_ci DCCP_CRIT("Unable to create Ack Vector slab cache"); 3938c2ecf20Sopenharmony_ci return -ENOBUFS; 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_civoid dccp_ackvec_exit(void) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci kmem_cache_destroy(dccp_ackvec_slab); 3998c2ecf20Sopenharmony_ci dccp_ackvec_slab = NULL; 4008c2ecf20Sopenharmony_ci kmem_cache_destroy(dccp_ackvec_record_slab); 4018c2ecf20Sopenharmony_ci dccp_ackvec_record_slab = NULL; 4028c2ecf20Sopenharmony_ci} 403