root/net/sctp/tsnmap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sctp_tsnmap_init
  2. sctp_tsnmap_free
  3. sctp_tsnmap_check
  4. sctp_tsnmap_mark
  5. sctp_tsnmap_iter_init
  6. sctp_tsnmap_next_gap_ack
  7. sctp_tsnmap_skip
  8. sctp_tsnmap_update
  9. sctp_tsnmap_pending
  10. sctp_tsnmap_find_gap_ack
  11. sctp_tsnmap_renege
  12. sctp_tsnmap_num_gabs
  13. sctp_tsnmap_grow

   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 
  29 static void sctp_tsnmap_update(struct sctp_tsnmap *map);
  30 static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off,
  31                                      __u16 len, __u16 *start, __u16 *end);
  32 static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size);
  33 
  34 /* Initialize a block of memory as a tsnmap.  */
  35 struct 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 
  57 void 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  */
  69 int 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          * overlfow 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.  */
  95 int 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.  */
 142 static 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  */
 152 static 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.  */
 190 void 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  */
 228 static 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);
 262 out:
 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  */
 272 static 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.  */
 300 void 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 
 341 static 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 }

/* [<][>][^][v][top][bottom][index][help] */