You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.1 KiB
125 lines
3.1 KiB
/* 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); |
|
}
|
|
|