PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/net/sctp/tsnmap.c

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