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