diff options
Diffstat (limited to 'net/sctp/tsnmap.c')
| -rw-r--r-- | net/sctp/tsnmap.c | 52 | 
1 files changed, 23 insertions, 29 deletions
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index 747d5412c46..7635f9f2311 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -21,25 +21,18 @@   * See the GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with GNU CC; see the file COPYING.  If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * along with GNU CC; see the file COPYING.  If not, see + * <http://www.gnu.org/licenses/>.   *   * Please send any bug reports or fixes you make to the   * email address(es): - *    lksctp developers <lksctp-developers@lists.sourceforge.net> - * - * Or submit a bug report through the following website: - *    http://www.sf.net/projects/lksctp + *    lksctp developers <linux-sctp@vger.kernel.org>   *   * Written or modified by:   *    La Monte H.P. Yarroll <piggy@acm.org>   *    Jon Grimm             <jgrimm@us.ibm.com>   *    Karl Knutson          <karl@athena.chicago.il.us>   *    Sridhar Samudrala     <sri@us.ibm.com> - * - * Any bugs reported given to us we will try to fix... any fixes shared will - * be incorporated into the next SCTP release.   */  #include <linux/slab.h> @@ -51,7 +44,7 @@  static void sctp_tsnmap_update(struct sctp_tsnmap *map);  static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off,  				     __u16 len, __u16 *start, __u16 *end); -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap); +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size);  /* Initialize a block of memory as a tsnmap.  */  struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, @@ -114,7 +107,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)  /* Mark this TSN as seen.  */ -int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) +int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, +		     struct sctp_transport *trans)  {  	u16 gap; @@ -123,7 +117,7 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)  	gap = tsn - map->base_tsn; -	if (gap >= map->len && !sctp_tsnmap_grow(map, gap)) +	if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1))  		return -ENOMEM;  	if (!sctp_tsnmap_has_gap(map) && gap == 0) { @@ -133,6 +127,9 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)  		 */  		map->max_tsn_seen++;  		map->cumulative_tsn_ack_point++; +		if (trans) +			trans->sack_generation = +				trans->asoc->peer.sack_generation;  		map->base_tsn++;  	} else {  		/* Either we already have a gap, or about to record a gap, so @@ -157,8 +154,8 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)  /* Initialize a Gap Ack Block iterator from memory being provided.  */ -SCTP_STATIC void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map, -				       struct sctp_tsnmap_iter *iter) +static void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map, +				  struct sctp_tsnmap_iter *iter)  {  	/* Only start looking one past the Cumulative TSN Ack Point.  */  	iter->start = map->cumulative_tsn_ack_point + 1; @@ -167,9 +164,9 @@ SCTP_STATIC void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,  /* Get the next Gap Ack Blocks. Returns 0 if there was not another block   * to get.   */ -SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, -					 struct sctp_tsnmap_iter *iter, -					 __u16 *start, __u16 *end) +static int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, +				    struct sctp_tsnmap_iter *iter, +				    __u16 *start, __u16 *end)  {  	int ended = 0;  	__u16 start_ = 0, end_ = 0, offset; @@ -268,7 +265,7 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)  	__u32 max_tsn = map->max_tsn_seen;  	__u32 base_tsn = map->base_tsn;  	__u16 pending_data; -	u32 gap, i; +	u32 gap;  	pending_data = max_tsn - cum_tsn;  	gap = max_tsn - base_tsn; @@ -276,11 +273,7 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)  	if (gap == 0 || gap >= map->len)  		goto out; -	for (i = 0; i < gap+1; i++) { -		if (test_bit(i, map->tsn_map)) -			pending_data--; -	} - +	pending_data -= bitmap_weight(map->tsn_map, gap + 1);  out:  	return pending_data;  } @@ -344,7 +337,7 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,  	/* Refresh the gap ack information. */  	if (sctp_tsnmap_has_gap(map)) { -		__u16 start, end; +		__u16 start = 0, end = 0;  		sctp_tsnmap_iter_init(map, &iter);  		while (sctp_tsnmap_next_gap_ack(map, &iter,  						&start, @@ -360,23 +353,24 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,  	return ngaps;  } -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap) +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size)  {  	unsigned long *new;  	unsigned long inc;  	u16  len; -	if (gap >= SCTP_TSN_MAP_SIZE) +	if (size > SCTP_TSN_MAP_SIZE)  		return 0; -	inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; +	inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT;  	len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE);  	new = kzalloc(len>>3, GFP_ATOMIC);  	if (!new)  		return 0; -	bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn); +	bitmap_copy(new, map->tsn_map, +		map->max_tsn_seen - map->cumulative_tsn_ack_point);  	kfree(map->tsn_map);  	map->tsn_map = new;  	map->len = len;  | 
