cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tsnmap.c (9010B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* SCTP kernel implementation
      3 * (C) Copyright IBM Corp. 2001, 2004
      4 * Copyright (c) 1999-2000 Cisco, Inc.
      5 * Copyright (c) 1999-2001 Motorola, Inc.
      6 * Copyright (c) 2001 Intel Corp.
      7 *
      8 * This file is part of the SCTP kernel implementation
      9 *
     10 * These functions manipulate sctp tsn mapping array.
     11 *
     12 * Please send any bug reports or fixes you make to the
     13 * email address(es):
     14 *    lksctp developers <linux-sctp@vger.kernel.org>
     15 *
     16 * Written or modified by:
     17 *    La Monte H.P. Yarroll <piggy@acm.org>
     18 *    Jon Grimm             <jgrimm@us.ibm.com>
     19 *    Karl Knutson          <karl@athena.chicago.il.us>
     20 *    Sridhar Samudrala     <sri@us.ibm.com>
     21 */
     22
     23#include <linux/slab.h>
     24#include <linux/types.h>
     25#include <linux/bitmap.h>
     26#include <net/sctp/sctp.h>
     27#include <net/sctp/sm.h>
     28
     29static void sctp_tsnmap_update(struct sctp_tsnmap *map);
     30static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off,
     31				     __u16 len, __u16 *start, __u16 *end);
     32static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size);
     33
     34/* Initialize a block of memory as a tsnmap.  */
     35struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len,
     36				     __u32 initial_tsn, gfp_t gfp)
     37{
     38	if (!map->tsn_map) {
     39		map->tsn_map = kzalloc(len>>3, gfp);
     40		if (map->tsn_map == NULL)
     41			return NULL;
     42
     43		map->len = len;
     44	} else {
     45		bitmap_zero(map->tsn_map, map->len);
     46	}
     47
     48	/* Keep track of TSNs represented by tsn_map.  */
     49	map->base_tsn = initial_tsn;
     50	map->cumulative_tsn_ack_point = initial_tsn - 1;
     51	map->max_tsn_seen = map->cumulative_tsn_ack_point;
     52	map->num_dup_tsns = 0;
     53
     54	return map;
     55}
     56
     57void sctp_tsnmap_free(struct sctp_tsnmap *map)
     58{
     59	map->len = 0;
     60	kfree(map->tsn_map);
     61}
     62
     63/* Test the tracking state of this TSN.
     64 * Returns:
     65 *   0 if the TSN has not yet been seen
     66 *  >0 if the TSN has been seen (duplicate)
     67 *  <0 if the TSN is invalid (too large to track)
     68 */
     69int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
     70{
     71	u32 gap;
     72
     73	/* Check to see if this is an old TSN */
     74	if (TSN_lte(tsn, map->cumulative_tsn_ack_point))
     75		return 1;
     76
     77	/* Verify that we can hold this TSN and that it will not
     78	 * overflow our map
     79	 */
     80	if (!TSN_lt(tsn, map->base_tsn + SCTP_TSN_MAP_SIZE))
     81		return -1;
     82
     83	/* Calculate the index into the mapping arrays.  */
     84	gap = tsn - map->base_tsn;
     85
     86	/* Check to see if TSN has already been recorded.  */
     87	if (gap < map->len && test_bit(gap, map->tsn_map))
     88		return 1;
     89	else
     90		return 0;
     91}
     92
     93
     94/* Mark this TSN as seen.  */
     95int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,
     96		     struct sctp_transport *trans)
     97{
     98	u16 gap;
     99
    100	if (TSN_lt(tsn, map->base_tsn))
    101		return 0;
    102
    103	gap = tsn - map->base_tsn;
    104
    105	if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1))
    106		return -ENOMEM;
    107
    108	if (!sctp_tsnmap_has_gap(map) && gap == 0) {
    109		/* In this case the map has no gaps and the tsn we are
    110		 * recording is the next expected tsn.  We don't touch
    111		 * the map but simply bump the values.
    112		 */
    113		map->max_tsn_seen++;
    114		map->cumulative_tsn_ack_point++;
    115		if (trans)
    116			trans->sack_generation =
    117				trans->asoc->peer.sack_generation;
    118		map->base_tsn++;
    119	} else {
    120		/* Either we already have a gap, or about to record a gap, so
    121		 * have work to do.
    122		 *
    123		 * Bump the max.
    124		 */
    125		if (TSN_lt(map->max_tsn_seen, tsn))
    126			map->max_tsn_seen = tsn;
    127
    128		/* Mark the TSN as received.  */
    129		set_bit(gap, map->tsn_map);
    130
    131		/* Go fixup any internal TSN mapping variables including
    132		 * cumulative_tsn_ack_point.
    133		 */
    134		sctp_tsnmap_update(map);
    135	}
    136
    137	return 0;
    138}
    139
    140
    141/* Initialize a Gap Ack Block iterator from memory being provided.  */
    142static void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
    143				  struct sctp_tsnmap_iter *iter)
    144{
    145	/* Only start looking one past the Cumulative TSN Ack Point.  */
    146	iter->start = map->cumulative_tsn_ack_point + 1;
    147}
    148
    149/* Get the next Gap Ack Blocks. Returns 0 if there was not another block
    150 * to get.
    151 */
    152static int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
    153				    struct sctp_tsnmap_iter *iter,
    154				    __u16 *start, __u16 *end)
    155{
    156	int ended = 0;
    157	__u16 start_ = 0, end_ = 0, offset;
    158
    159	/* If there are no more gap acks possible, get out fast.  */
    160	if (TSN_lte(map->max_tsn_seen, iter->start))
    161		return 0;
    162
    163	offset = iter->start - map->base_tsn;
    164	sctp_tsnmap_find_gap_ack(map->tsn_map, offset, map->len,
    165				 &start_, &end_);
    166
    167	/* The Gap Ack Block happens to end at the end of the map. */
    168	if (start_ && !end_)
    169		end_ = map->len - 1;
    170
    171	/* If we found a Gap Ack Block, return the start and end and
    172	 * bump the iterator forward.
    173	 */
    174	if (end_) {
    175		/* Fix up the start and end based on the
    176		 * Cumulative TSN Ack which is always 1 behind base.
    177		 */
    178		*start = start_ + 1;
    179		*end = end_ + 1;
    180
    181		/* Move the iterator forward.  */
    182		iter->start = map->cumulative_tsn_ack_point + *end + 1;
    183		ended = 1;
    184	}
    185
    186	return ended;
    187}
    188
    189/* Mark this and any lower TSN as seen.  */
    190void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn)
    191{
    192	u32 gap;
    193
    194	if (TSN_lt(tsn, map->base_tsn))
    195		return;
    196	if (!TSN_lt(tsn, map->base_tsn + SCTP_TSN_MAP_SIZE))
    197		return;
    198
    199	/* Bump the max.  */
    200	if (TSN_lt(map->max_tsn_seen, tsn))
    201		map->max_tsn_seen = tsn;
    202
    203	gap = tsn - map->base_tsn + 1;
    204
    205	map->base_tsn += gap;
    206	map->cumulative_tsn_ack_point += gap;
    207	if (gap >= map->len) {
    208		/* If our gap is larger then the map size, just
    209		 * zero out the map.
    210		 */
    211		bitmap_zero(map->tsn_map, map->len);
    212	} else {
    213		/* If the gap is smaller than the map size,
    214		 * shift the map by 'gap' bits and update further.
    215		 */
    216		bitmap_shift_right(map->tsn_map, map->tsn_map, gap, map->len);
    217		sctp_tsnmap_update(map);
    218	}
    219}
    220
    221/********************************************************************
    222 * 2nd Level Abstractions
    223 ********************************************************************/
    224
    225/* This private helper function updates the tsnmap buffers and
    226 * the Cumulative TSN Ack Point.
    227 */
    228static void sctp_tsnmap_update(struct sctp_tsnmap *map)
    229{
    230	u16 len;
    231	unsigned long zero_bit;
    232
    233
    234	len = map->max_tsn_seen - map->cumulative_tsn_ack_point;
    235	zero_bit = find_first_zero_bit(map->tsn_map, len);
    236	if (!zero_bit)
    237		return;		/* The first 0-bit is bit 0.  nothing to do */
    238
    239	map->base_tsn += zero_bit;
    240	map->cumulative_tsn_ack_point += zero_bit;
    241
    242	bitmap_shift_right(map->tsn_map, map->tsn_map, zero_bit, map->len);
    243}
    244
    245/* How many data chunks  are we missing from our peer?
    246 */
    247__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
    248{
    249	__u32 cum_tsn = map->cumulative_tsn_ack_point;
    250	__u32 max_tsn = map->max_tsn_seen;
    251	__u32 base_tsn = map->base_tsn;
    252	__u16 pending_data;
    253	u32 gap;
    254
    255	pending_data = max_tsn - cum_tsn;
    256	gap = max_tsn - base_tsn;
    257
    258	if (gap == 0 || gap >= map->len)
    259		goto out;
    260
    261	pending_data -= bitmap_weight(map->tsn_map, gap + 1);
    262out:
    263	return pending_data;
    264}
    265
    266/* This is a private helper for finding Gap Ack Blocks.  It searches a
    267 * single array for the start and end of a Gap Ack Block.
    268 *
    269 * The flags "started" and "ended" tell is if we found the beginning
    270 * or (respectively) the end of a Gap Ack Block.
    271 */
    272static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off,
    273				     __u16 len, __u16 *start, __u16 *end)
    274{
    275	int i = off;
    276
    277	/* Look through the entire array, but break out
    278	 * early if we have found the end of the Gap Ack Block.
    279	 */
    280
    281	/* Also, stop looking past the maximum TSN seen. */
    282
    283	/* Look for the start. */
    284	i = find_next_bit(map, len, off);
    285	if (i < len)
    286		*start = i;
    287
    288	/* Look for the end.  */
    289	if (*start) {
    290		/* We have found the start, let's find the
    291		 * end.  If we find the end, break out.
    292		 */
    293		i = find_next_zero_bit(map, len, i);
    294		if (i < len)
    295			*end = i - 1;
    296	}
    297}
    298
    299/* Renege that we have seen a TSN.  */
    300void sctp_tsnmap_renege(struct sctp_tsnmap *map, __u32 tsn)
    301{
    302	u32 gap;
    303
    304	if (TSN_lt(tsn, map->base_tsn))
    305		return;
    306	/* Assert: TSN is in range.  */
    307	if (!TSN_lt(tsn, map->base_tsn + map->len))
    308		return;
    309
    310	gap = tsn - map->base_tsn;
    311
    312	/* Pretend we never saw the TSN.  */
    313	clear_bit(gap, map->tsn_map);
    314}
    315
    316/* How many gap ack blocks do we have recorded? */
    317__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,
    318			   struct sctp_gap_ack_block *gabs)
    319{
    320	struct sctp_tsnmap_iter iter;
    321	int ngaps = 0;
    322
    323	/* Refresh the gap ack information. */
    324	if (sctp_tsnmap_has_gap(map)) {
    325		__u16 start = 0, end = 0;
    326		sctp_tsnmap_iter_init(map, &iter);
    327		while (sctp_tsnmap_next_gap_ack(map, &iter,
    328						&start,
    329						&end)) {
    330
    331			gabs[ngaps].start = htons(start);
    332			gabs[ngaps].end = htons(end);
    333			ngaps++;
    334			if (ngaps >= SCTP_MAX_GABS)
    335				break;
    336		}
    337	}
    338	return ngaps;
    339}
    340
    341static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size)
    342{
    343	unsigned long *new;
    344	unsigned long inc;
    345	u16  len;
    346
    347	if (size > SCTP_TSN_MAP_SIZE)
    348		return 0;
    349
    350	inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT;
    351	len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE);
    352
    353	new = kzalloc(len>>3, GFP_ATOMIC);
    354	if (!new)
    355		return 0;
    356
    357	bitmap_copy(new, map->tsn_map,
    358		map->max_tsn_seen - map->cumulative_tsn_ack_point);
    359	kfree(map->tsn_map);
    360	map->tsn_map = new;
    361	map->len = len;
    362
    363	return 1;
    364}