Commit eda8254f authored by Jon Grimm's avatar Jon Grimm

Merge

parents 3e446c25 6708c876
......@@ -92,24 +92,24 @@ struct sctp_ssnmap;
/* Structures useful for managing bind/connect. */
typedef struct sctp_bind_bucket {
struct sctp_bind_bucket {
unsigned short port;
unsigned short fastreuse;
struct sctp_bind_bucket *next;
struct sctp_bind_bucket **pprev;
struct sock *sk;
} sctp_bind_bucket_t;
};
typedef struct sctp_bind_hashbucket {
struct sctp_bind_hashbucket {
spinlock_t lock;
struct sctp_bind_bucket *chain;
} sctp_bind_hashbucket_t;
};
/* Used for hashing all associations. */
typedef struct sctp_hashbucket {
struct sctp_hashbucket {
rwlock_t lock;
struct sctp_ep_common *chain;
} sctp_hashbucket_t __attribute__((__aligned__(8)));
} __attribute__((__aligned__(8)));
/* The SCTP protocol structure. */
......@@ -167,17 +167,17 @@ struct sctp_protocol {
/* This is the hash of all endpoints. */
int ep_hashsize;
sctp_hashbucket_t *ep_hashbucket;
struct sctp_hashbucket *ep_hashbucket;
/* This is the hash of all associations. */
int assoc_hashsize;
sctp_hashbucket_t *assoc_hashbucket;
struct sctp_hashbucket *assoc_hashbucket;
/* This is the sctp port control hash. */
int port_hashsize;
int port_rover;
spinlock_t port_alloc_lock; /* Protects port_rover. */
sctp_bind_hashbucket_t *port_hashtable;
struct sctp_bind_hashbucket *port_hashtable;
/* This is the global local address list.
* We actively maintain this complete list of interfaces on
......
......@@ -522,7 +522,7 @@ void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
sctp_hashbucket_t *head;
struct sctp_hashbucket *head;
epb = &ep->base;
......@@ -550,7 +550,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
/* Remove endpoint from the hash table. */
void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{
sctp_hashbucket_t *head;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
epb = &ep->base;
......@@ -582,7 +582,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
/* Look up an endpoint. */
struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
{
sctp_hashbucket_t *head;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
int hash;
......@@ -619,7 +619,7 @@ void __sctp_hash_established(struct sctp_association *asoc)
{
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
sctp_hashbucket_t *head;
struct sctp_hashbucket *head;
epb = &asoc->base;
......@@ -649,7 +649,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
/* Remove association from the hash table. */
void __sctp_unhash_established(struct sctp_association *asoc)
{
sctp_hashbucket_t *head;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
epb = &asoc->base;
......@@ -677,7 +677,7 @@ struct sctp_association *__sctp_lookup_association(
const union sctp_addr *peer,
struct sctp_transport **pt)
{
sctp_hashbucket_t *head;
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_association *asoc;
struct sctp_transport *transport;
......
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
......@@ -74,6 +74,9 @@ static struct sctp_pf *sctp_pf_inet_specific;
static struct sctp_af *sctp_af_v4_specific;
static struct sctp_af *sctp_af_v6_specific;
kmem_cache_t *sctp_chunk_cachep;
kmem_cache_t *sctp_bucket_cachep;
extern struct net_proto_family inet_family_ops;
extern int sctp_snmp_proc_init(void);
......@@ -106,10 +109,12 @@ __init int sctp_proc_init(void)
return rc;
}
/* Clean up the proc fs entry for the SCTP protocol. */
/* Clean up the proc fs entry for the SCTP protocol.
* Note: Do not make this __exit as it is used in the init error
* path.
*/
void sctp_proc_exit(void)
{
sctp_snmp_proc_exit();
if (proc_net_sctp) {
......@@ -928,6 +933,22 @@ __init int sctp_init(void)
inet_register_protosw(&sctp_seqpacket_protosw);
inet_register_protosw(&sctp_stream_protosw);
/* Allocate a cache pools. */
sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
sizeof(struct sctp_bind_bucket),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
if (!sctp_bucket_cachep)
goto err_bucket_cachep;
sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
sizeof(struct sctp_chunk),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
if (!sctp_chunk_cachep)
goto err_chunk_cachep;
/* Allocate and initialise sctp mibs. */
status = init_sctp_mibs();
if (status)
......@@ -984,8 +1005,8 @@ __init int sctp_init(void)
/* Allocate and initialize the association hash table. */
sctp_proto.assoc_hashsize = 4096;
sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
sctp_proto.assoc_hashbucket = (struct sctp_hashbucket *)
kmalloc(4096 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_proto.assoc_hashbucket) {
printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
status = -ENOMEM;
......@@ -998,8 +1019,8 @@ __init int sctp_init(void)
/* Allocate and initialize the endpoint hash table. */
sctp_proto.ep_hashsize = 64;
sctp_proto.ep_hashbucket = (sctp_hashbucket_t *)
kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
sctp_proto.ep_hashbucket = (struct sctp_hashbucket *)
kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_proto.ep_hashbucket) {
printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
status = -ENOMEM;
......@@ -1013,8 +1034,8 @@ __init int sctp_init(void)
/* Allocate and initialize the SCTP port hash table. */
sctp_proto.port_hashsize = 4096;
sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL);
sctp_proto.port_hashtable = (struct sctp_bind_hashbucket *)
kmalloc(4096 * sizeof(struct sctp_bind_hashbucket),GFP_KERNEL);
if (!sctp_proto.port_hashtable) {
printk(KERN_ERR "SCTP: Failed bind hash alloc.");
status = -ENOMEM;
......@@ -1071,6 +1092,10 @@ __init int sctp_init(void)
sctp_proc_exit();
cleanup_sctp_mibs();
err_init_mibs:
kmem_cache_destroy(sctp_chunk_cachep);
err_chunk_cachep:
kmem_cache_destroy(sctp_bucket_cachep);
err_bucket_cachep:
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
inet_unregister_protosw(&sctp_seqpacket_protosw);
inet_unregister_protosw(&sctp_stream_protosw);
......@@ -1101,6 +1126,9 @@ __exit void sctp_exit(void)
kfree(sctp_proto.ep_hashbucket);
kfree(sctp_proto.port_hashtable);
kmem_cache_destroy(sctp_chunk_cachep);
kmem_cache_destroy(sctp_bucket_cachep);
sctp_dbg_objcnt_exit();
sctp_proc_exit();
cleanup_sctp_mibs();
......
......@@ -68,6 +68,8 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
extern kmem_cache_t *sctp_chunk_cachep;
/* What was the inbound interface for this chunk? */
int sctp_chunk_iif(const struct sctp_chunk *chunk)
{
......@@ -976,7 +978,9 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
const struct sctp_association *asoc,
struct sock *sk)
{
struct sctp_chunk *retval = t_new(struct sctp_chunk, GFP_ATOMIC);
struct sctp_chunk *retval;
retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC);
if (!retval)
goto nodata;
......@@ -1075,13 +1079,12 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
}
retval->chunk_hdr = chunk_hdr;
retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(sctp_chunkhdr_t);
retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);
/* Set the skb to the belonging sock for accounting. */
skb->sk = sk;
return retval;
nodata:
return NULL;
}
......@@ -1090,12 +1093,11 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
/* Release the memory occupied by a chunk. */
static void sctp_chunk_destroy(struct sctp_chunk *chunk)
{
/* Free the chunk skb data and the SCTP_chunk stub itself. */
dev_kfree_skb(chunk->skb);
kfree(chunk);
SCTP_DBG_OBJCNT_DEC(chunk);
kmem_cache_free(sctp_chunk_cachep, chunk);
}
/* Possibly, free the chunk. */
......
......@@ -2739,6 +2739,9 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
/* Pull the SACK chunk from the data buffer */
sackh = sctp_sm_pull_sack(chunk);
/* Was this a bogus SACK? */
if (!sackh)
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
chunk->subh.sack_hdr = sackh;
ctsn = ntohl(sackh->cum_tsn_ack);
......@@ -4405,22 +4408,27 @@ sctp_disposition_t sctp_sf_timer_ignore(const struct sctp_endpoint *ep,
********************************************************************/
/* Pull the SACK chunk based on the SACK header. */
sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *chunk)
struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
{
sctp_sackhdr_t *sack;
struct sctp_sackhdr *sack;
unsigned int len;
__u16 num_blocks;
__u16 num_dup_tsns;
/* FIXME: Protect ourselves from reading too far into
/* Protect ourselves from reading too far into
* the skb from a bogus sender.
*/
sack = (sctp_sackhdr_t *) chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_sackhdr_t));
sack = (struct sctp_sackhdr *) chunk->skb->data;
num_blocks = ntohs(sack->num_gap_ack_blocks);
num_dup_tsns = ntohs(sack->num_dup_tsns);
len = sizeof(struct sctp_sackhdr);
len = (num_blocks + num_dup_tsns) * sizeof(__u32);
if (len > chunk->skb->len)
return NULL;
skb_pull(chunk->skb, len);
skb_pull(chunk->skb, (num_blocks + num_dup_tsns) * sizeof(__u32));
return sack;
}
......
......@@ -99,6 +99,8 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
struct sctp_association *, sctp_socket_type_t);
static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
extern kmem_cache_t *sctp_bucket_cachep;
/* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored.
*/
......@@ -2721,7 +2723,7 @@ static void sctp_unhash(struct sock *sk)
*
* The port hash table (contained in the 'global' SCTP protocol storage
* returned by struct sctp_protocol *sctp_get_protocol()). The hash
* table is an array of 4096 lists (sctp_bind_hashbucket_t). Each
* table is an array of 4096 lists (sctp_bind_hashbucket). Each
* list (the list number is the port number hashed out, so as you
* would expect from a hash function, all the ports in a given list have
* such a number that hashes out to the same list number; you were
......@@ -2729,12 +2731,13 @@ static void sctp_unhash(struct sock *sk)
* link to the socket (struct sock) that uses it, the port number and
* a fastreuse flag (FIXME: NPI ipg).
*/
static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head,
unsigned short snum);
static struct sctp_bind_bucket *sctp_bucket_create(
struct sctp_bind_hashbucket *head, unsigned short snum);
static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{
sctp_bind_hashbucket_t *head; /* hash list */
sctp_bind_bucket_t *pp; /* hash list port iterator */
struct sctp_bind_hashbucket *head; /* hash list */
struct sctp_bind_bucket *pp; /* hash list port iterator */
struct sctp_protocol *sctp = sctp_get_protocol();
unsigned short snum;
int ret;
......@@ -3105,12 +3108,12 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
* 2nd Level Abstractions
********************************************************************/
static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsigned short snum)
static struct sctp_bind_bucket *sctp_bucket_create(
struct sctp_bind_hashbucket *head, unsigned short snum)
{
sctp_bind_bucket_t *pp;
struct sctp_bind_bucket *pp;
SCTP_DEBUG_PRINTK( "sctp_bucket_create() begins, snum=%d\n", snum);
pp = kmalloc(sizeof(sctp_bind_bucket_t), GFP_ATOMIC);
pp = kmem_cache_alloc(sctp_bucket_cachep, SLAB_ATOMIC);
if (pp) {
pp->port = snum;
pp->fastreuse = 0;
......@@ -3120,31 +3123,36 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
head->chain = pp;
pp->pprev = &head->chain;
}
SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp);
return pp;
}
/* Caller must hold hashbucket lock for this tb with local BH disabled */
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
if (pp->sk) {
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
kmem_cache_free(sctp_bucket_cachep, pp);
}
}
/* FIXME: Comments! */
static __inline__ void __sctp_put_port(struct sock *sk)
{
struct sctp_protocol *sctp_proto = sctp_get_protocol();
sctp_bind_hashbucket_t *head =
struct sctp_bind_hashbucket *head =
&sctp_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
sctp_bind_bucket_t *pp;
struct sctp_bind_bucket *pp;
sctp_spin_lock(&head->lock);
pp = (sctp_bind_bucket_t *) sk->prev;
pp = (struct sctp_bind_bucket *) sk->prev;
if (sk->bind_next)
sk->bind_next->bind_pprev = sk->bind_pprev;
*(sk->bind_pprev) = sk->bind_next;
sk->prev = NULL;
inet_sk(sk)->num = 0;
if (pp->sk) {
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
kfree(pp);
}
sctp_bucket_destroy(pp);
sctp_spin_unlock(&head->lock);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment