/* SCTP kernel implementation
 * Copyright (c) 2003 International Business Machines, Corp.
 *
 * This file is part of the SCTP kernel implementation
 *
 * These functions manipulate sctp SSN tracker.
 *
 * This SCTP implementation is free software;
 * you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This SCTP implementation is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *                 ************************
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * 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, see
 * <http://www.gnu.org/licenses/>.
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
 *    lksctp developers <linux-sctp@vger.kernel.org>
 *
 * Written or modified by:
 *    Jon Grimm             <jgrimm@us.ibm.com>
 */

#include <linux/types.h>
#include <linux/slab.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>

static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
					    __u16 out);

/* Storage size needed for map includes 2 headers and then the
 * specific needs of in or out streams.
 */
static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)
{
	return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16);
}


/* Create a new sctp_ssnmap.
 * Allocate room to store at least 'len' contiguous TSNs.
 */
struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
				    gfp_t gfp)
{
	struct sctp_ssnmap *retval;
	int size;

	size = sctp_ssnmap_size(in, out);
	if (size <= KMALLOC_MAX_SIZE)
		retval = kmalloc(size, gfp);
	else
		retval = (struct sctp_ssnmap *)
			  __get_free_pages(gfp, get_order(size));
	if (!retval)
		goto fail;

	if (!sctp_ssnmap_init(retval, in, out))
		goto fail_map;

	SCTP_DBG_OBJCNT_INC(ssnmap);

	return retval;

fail_map:
	if (size <= KMALLOC_MAX_SIZE)
		kfree(retval);
	else
		free_pages((unsigned long)retval, get_order(size));
fail:
	return NULL;
}


/* Initialize a block of memory as a ssnmap.  */
static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
					    __u16 out)
{
	memset(map, 0x00, sctp_ssnmap_size(in, out));

	/* Start 'in' stream just after the map header. */
	map->in.ssn = (__u16 *)&map[1];
	map->in.len = in;

	/* Start 'out' stream just after 'in'. */
	map->out.ssn = &map->in.ssn[in];
	map->out.len = out;

	return map;
}

/* Clear out the ssnmap streams.  */
void sctp_ssnmap_clear(struct sctp_ssnmap *map)
{
	size_t size;

	size = (map->in.len + map->out.len) * sizeof(__u16);
	memset(map->in.ssn, 0x00, size);
}

/* Dispose of a ssnmap.  */
void sctp_ssnmap_free(struct sctp_ssnmap *map)
{
	int size;

	if (unlikely(!map))
		return;

	size = sctp_ssnmap_size(map->in.len, map->out.len);
	if (size <= KMALLOC_MAX_SIZE)
		kfree(map);
	else
		free_pages((unsigned long)map, get_order(size));

	SCTP_DBG_OBJCNT_DEC(ssnmap);
}
