Commit eda8254f authored by Jon Grimm's avatar Jon Grimm

Merge

parents 3e446c25 6708c876
...@@ -92,24 +92,24 @@ struct sctp_ssnmap; ...@@ -92,24 +92,24 @@ struct sctp_ssnmap;
/* Structures useful for managing bind/connect. */ /* Structures useful for managing bind/connect. */
typedef struct sctp_bind_bucket { struct sctp_bind_bucket {
unsigned short port; unsigned short port;
unsigned short fastreuse; unsigned short fastreuse;
struct sctp_bind_bucket *next; struct sctp_bind_bucket *next;
struct sctp_bind_bucket **pprev; struct sctp_bind_bucket **pprev;
struct sock *sk; struct sock *sk;
} sctp_bind_bucket_t; };
typedef struct sctp_bind_hashbucket { struct sctp_bind_hashbucket {
spinlock_t lock; spinlock_t lock;
struct sctp_bind_bucket *chain; struct sctp_bind_bucket *chain;
} sctp_bind_hashbucket_t; };
/* Used for hashing all associations. */ /* Used for hashing all associations. */
typedef struct sctp_hashbucket { struct sctp_hashbucket {
rwlock_t lock; rwlock_t lock;
struct sctp_ep_common *chain; struct sctp_ep_common *chain;
} sctp_hashbucket_t __attribute__((__aligned__(8))); } __attribute__((__aligned__(8)));
/* The SCTP protocol structure. */ /* The SCTP protocol structure. */
...@@ -167,17 +167,17 @@ struct sctp_protocol { ...@@ -167,17 +167,17 @@ struct sctp_protocol {
/* This is the hash of all endpoints. */ /* This is the hash of all endpoints. */
int ep_hashsize; int ep_hashsize;
sctp_hashbucket_t *ep_hashbucket; struct sctp_hashbucket *ep_hashbucket;
/* This is the hash of all associations. */ /* This is the hash of all associations. */
int assoc_hashsize; int assoc_hashsize;
sctp_hashbucket_t *assoc_hashbucket; struct sctp_hashbucket *assoc_hashbucket;
/* This is the sctp port control hash. */ /* This is the sctp port control hash. */
int port_hashsize; int port_hashsize;
int port_rover; int port_rover;
spinlock_t port_alloc_lock; /* Protects 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. /* This is the global local address list.
* We actively maintain this complete list of interfaces on * We actively maintain this complete list of interfaces on
...@@ -239,7 +239,7 @@ struct sctp_af { ...@@ -239,7 +239,7 @@ struct sctp_af {
int (*is_any) (const union sctp_addr *); int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *); int (*available) (const union sctp_addr *);
int (*skb_iif) (const struct sk_buff *sk); int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk); int (*is_ce) (const struct sk_buff *sk);
__u16 net_header_len; __u16 net_header_len;
int sockaddr_len; int sockaddr_len;
sa_family_t sa_family; sa_family_t sa_family;
...@@ -461,7 +461,7 @@ struct sctp_datamsg { ...@@ -461,7 +461,7 @@ struct sctp_datamsg {
/* Reference counting. */ /* Reference counting. */
atomic_t refcnt; atomic_t refcnt;
/* When is this message no longer interesting to the peer? */ /* When is this message no longer interesting to the peer? */
unsigned long expires_at; unsigned long expires_at;
/* Did the messenge fail to send? */ /* Did the messenge fail to send? */
int send_error; int send_error;
char send_failed; char send_failed;
......
...@@ -522,7 +522,7 @@ void __sctp_hash_endpoint(struct sctp_endpoint *ep) ...@@ -522,7 +522,7 @@ void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{ {
struct sctp_ep_common **epp; struct sctp_ep_common **epp;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
epb = &ep->base; epb = &ep->base;
...@@ -550,7 +550,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep) ...@@ -550,7 +550,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
/* Remove endpoint from the hash table. */ /* Remove endpoint from the hash table. */
void __sctp_unhash_endpoint(struct sctp_endpoint *ep) void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
epb = &ep->base; epb = &ep->base;
...@@ -582,7 +582,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep) ...@@ -582,7 +582,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
/* Look up an endpoint. */ /* Look up an endpoint. */
struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr) 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_ep_common *epb;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
int hash; int hash;
...@@ -619,7 +619,7 @@ void __sctp_hash_established(struct sctp_association *asoc) ...@@ -619,7 +619,7 @@ void __sctp_hash_established(struct sctp_association *asoc)
{ {
struct sctp_ep_common **epp; struct sctp_ep_common **epp;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
epb = &asoc->base; epb = &asoc->base;
...@@ -649,7 +649,7 @@ void sctp_unhash_established(struct sctp_association *asoc) ...@@ -649,7 +649,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
/* Remove association from the hash table. */ /* Remove association from the hash table. */
void __sctp_unhash_established(struct sctp_association *asoc) void __sctp_unhash_established(struct sctp_association *asoc)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
epb = &asoc->base; epb = &asoc->base;
...@@ -677,7 +677,7 @@ struct sctp_association *__sctp_lookup_association( ...@@ -677,7 +677,7 @@ struct sctp_association *__sctp_lookup_association(
const union sctp_addr *peer, const union sctp_addr *peer,
struct sctp_transport **pt) struct sctp_transport **pt)
{ {
sctp_hashbucket_t *head; struct sctp_hashbucket *head;
struct sctp_ep_common *epb; struct sctp_ep_common *epb;
struct sctp_association *asoc; struct sctp_association *asoc;
struct sctp_transport *transport; struct sctp_transport *transport;
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, 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 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
...@@ -74,6 +74,9 @@ static struct sctp_pf *sctp_pf_inet_specific; ...@@ -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_v4_specific;
static struct sctp_af *sctp_af_v6_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 struct net_proto_family inet_family_ops;
extern int sctp_snmp_proc_init(void); extern int sctp_snmp_proc_init(void);
...@@ -106,10 +109,12 @@ __init int sctp_proc_init(void) ...@@ -106,10 +109,12 @@ __init int sctp_proc_init(void)
return rc; 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) void sctp_proc_exit(void)
{ {
sctp_snmp_proc_exit(); sctp_snmp_proc_exit();
if (proc_net_sctp) { if (proc_net_sctp) {
...@@ -928,6 +933,22 @@ __init int sctp_init(void) ...@@ -928,6 +933,22 @@ __init int sctp_init(void)
inet_register_protosw(&sctp_seqpacket_protosw); inet_register_protosw(&sctp_seqpacket_protosw);
inet_register_protosw(&sctp_stream_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. */ /* Allocate and initialise sctp mibs. */
status = init_sctp_mibs(); status = init_sctp_mibs();
if (status) if (status)
...@@ -984,8 +1005,8 @@ __init int sctp_init(void) ...@@ -984,8 +1005,8 @@ __init int sctp_init(void)
/* Allocate and initialize the association hash table. */ /* Allocate and initialize the association hash table. */
sctp_proto.assoc_hashsize = 4096; sctp_proto.assoc_hashsize = 4096;
sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *) sctp_proto.assoc_hashbucket = (struct sctp_hashbucket *)
kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_proto.assoc_hashbucket) { if (!sctp_proto.assoc_hashbucket) {
printk(KERN_ERR "SCTP: Failed association hash alloc.\n"); printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
status = -ENOMEM; status = -ENOMEM;
...@@ -998,8 +1019,8 @@ __init int sctp_init(void) ...@@ -998,8 +1019,8 @@ __init int sctp_init(void)
/* Allocate and initialize the endpoint hash table. */ /* Allocate and initialize the endpoint hash table. */
sctp_proto.ep_hashsize = 64; sctp_proto.ep_hashsize = 64;
sctp_proto.ep_hashbucket = (sctp_hashbucket_t *) sctp_proto.ep_hashbucket = (struct sctp_hashbucket *)
kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_proto.ep_hashbucket) { if (!sctp_proto.ep_hashbucket) {
printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
status = -ENOMEM; status = -ENOMEM;
...@@ -1013,8 +1034,8 @@ __init int sctp_init(void) ...@@ -1013,8 +1034,8 @@ __init int sctp_init(void)
/* Allocate and initialize the SCTP port hash table. */ /* Allocate and initialize the SCTP port hash table. */
sctp_proto.port_hashsize = 4096; sctp_proto.port_hashsize = 4096;
sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *) sctp_proto.port_hashtable = (struct sctp_bind_hashbucket *)
kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(struct sctp_bind_hashbucket),GFP_KERNEL);
if (!sctp_proto.port_hashtable) { if (!sctp_proto.port_hashtable) {
printk(KERN_ERR "SCTP: Failed bind hash alloc."); printk(KERN_ERR "SCTP: Failed bind hash alloc.");
status = -ENOMEM; status = -ENOMEM;
...@@ -1071,6 +1092,10 @@ __init int sctp_init(void) ...@@ -1071,6 +1092,10 @@ __init int sctp_init(void)
sctp_proc_exit(); sctp_proc_exit();
cleanup_sctp_mibs(); cleanup_sctp_mibs();
err_init_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_del_protocol(&sctp_protocol, IPPROTO_SCTP);
inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_seqpacket_protosw);
inet_unregister_protosw(&sctp_stream_protosw); inet_unregister_protosw(&sctp_stream_protosw);
...@@ -1101,6 +1126,9 @@ __exit void sctp_exit(void) ...@@ -1101,6 +1126,9 @@ __exit void sctp_exit(void)
kfree(sctp_proto.ep_hashbucket); kfree(sctp_proto.ep_hashbucket);
kfree(sctp_proto.port_hashtable); kfree(sctp_proto.port_hashtable);
kmem_cache_destroy(sctp_chunk_cachep);
kmem_cache_destroy(sctp_bucket_cachep);
sctp_dbg_objcnt_exit(); sctp_dbg_objcnt_exit();
sctp_proc_exit(); sctp_proc_exit();
cleanup_sctp_mibs(); cleanup_sctp_mibs();
......
...@@ -68,6 +68,8 @@ ...@@ -68,6 +68,8 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
extern kmem_cache_t *sctp_chunk_cachep;
/* What was the inbound interface for this chunk? */ /* What was the inbound interface for this chunk? */
int sctp_chunk_iif(const struct sctp_chunk *chunk) int sctp_chunk_iif(const struct sctp_chunk *chunk)
{ {
...@@ -874,7 +876,7 @@ struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, ...@@ -874,7 +876,7 @@ struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
const void *payload, const size_t paylen) const void *payload, const size_t paylen)
{ {
struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT,
0, paylen); 0, paylen);
if (!retval) if (!retval)
goto nodata; goto nodata;
...@@ -976,7 +978,9 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, ...@@ -976,7 +978,9 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
const struct sctp_association *asoc, const struct sctp_association *asoc,
struct sock *sk) 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) if (!retval)
goto nodata; goto nodata;
...@@ -1048,7 +1052,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk) ...@@ -1048,7 +1052,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
* arguments, reserving enough space for a 'paylen' byte payload. * arguments, reserving enough space for a 'paylen' byte payload.
*/ */
struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
__u8 type, __u8 flags, int paylen) __u8 type, __u8 flags, int paylen)
{ {
struct sctp_chunk *retval; struct sctp_chunk *retval;
sctp_chunkhdr_t *chunk_hdr; sctp_chunkhdr_t *chunk_hdr;
...@@ -1075,13 +1079,12 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, ...@@ -1075,13 +1079,12 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
} }
retval->chunk_hdr = chunk_hdr; 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. */ /* Set the skb to the belonging sock for accounting. */
skb->sk = sk; skb->sk = sk;
return retval; return retval;
nodata: nodata:
return NULL; return NULL;
} }
...@@ -1090,12 +1093,11 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, ...@@ -1090,12 +1093,11 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
/* Release the memory occupied by a chunk. */ /* Release the memory occupied by a chunk. */
static void sctp_chunk_destroy(struct sctp_chunk *chunk) static void sctp_chunk_destroy(struct sctp_chunk *chunk)
{ {
/* Free the chunk skb data and the SCTP_chunk stub itself. */ /* Free the chunk skb data and the SCTP_chunk stub itself. */
dev_kfree_skb(chunk->skb); dev_kfree_skb(chunk->skb);
kfree(chunk);
SCTP_DBG_OBJCNT_DEC(chunk); SCTP_DBG_OBJCNT_DEC(chunk);
kmem_cache_free(sctp_chunk_cachep, chunk);
} }
/* Possibly, free the chunk. */ /* Possibly, free the chunk. */
......
...@@ -2333,7 +2333,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, ...@@ -2333,7 +2333,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
/* Do real work as sideffect. */ /* Do real work as sideffect. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
SCTP_U32(tsn)); SCTP_U32(tsn));
} }
} }
...@@ -2374,7 +2374,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, ...@@ -2374,7 +2374,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
* PMTU. In cases, such as loopback, this might be a rather * PMTU. In cases, such as loopback, this might be a rather
* large spill over. * large spill over.
*/ */
if (!asoc->rwnd || asoc->rwnd_over || if (!asoc->rwnd || asoc->rwnd_over ||
(datalen > asoc->rwnd + asoc->frag_point)) { (datalen > asoc->rwnd + asoc->frag_point)) {
/* If this is the next TSN, consider reneging to make /* If this is the next TSN, consider reneging to make
...@@ -2593,7 +2593,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep, ...@@ -2593,7 +2593,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
/* Do real work as sideffect. */ /* Do real work as sideffect. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
SCTP_U32(tsn)); SCTP_U32(tsn));
} }
} }
...@@ -2739,6 +2739,9 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, ...@@ -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 */ /* Pull the SACK chunk from the data buffer */
sackh = sctp_sm_pull_sack(chunk); 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; chunk->subh.sack_hdr = sackh;
ctsn = ntohl(sackh->cum_tsn_ack); ctsn = ntohl(sackh->cum_tsn_ack);
...@@ -4405,22 +4408,27 @@ sctp_disposition_t sctp_sf_timer_ignore(const struct sctp_endpoint *ep, ...@@ -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. */ /* 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_blocks;
__u16 num_dup_tsns; __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. * the skb from a bogus sender.
*/ */
sack = (sctp_sackhdr_t *) chunk->skb->data; sack = (struct sctp_sackhdr *) chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_sackhdr_t));
num_blocks = ntohs(sack->num_gap_ack_blocks); num_blocks = ntohs(sack->num_gap_ack_blocks);
num_dup_tsns = ntohs(sack->num_dup_tsns); 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; return sack;
} }
......
...@@ -99,6 +99,8 @@ static void sctp_sock_migrate(struct sock *, struct sock *, ...@@ -99,6 +99,8 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
struct sctp_association *, sctp_socket_type_t); struct sctp_association *, sctp_socket_type_t);
static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; 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 /* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored. * socket, the ID field is always ignored.
*/ */
...@@ -2721,7 +2723,7 @@ static void sctp_unhash(struct sock *sk) ...@@ -2721,7 +2723,7 @@ static void sctp_unhash(struct sock *sk)
* *
* The port hash table (contained in the 'global' SCTP protocol storage * The port hash table (contained in the 'global' SCTP protocol storage
* returned by struct sctp_protocol *sctp_get_protocol()). The hash * 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 * 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 * 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 * such a number that hashes out to the same list number; you were
...@@ -2729,12 +2731,13 @@ static void sctp_unhash(struct sock *sk) ...@@ -2729,12 +2731,13 @@ static void sctp_unhash(struct sock *sk)
* link to the socket (struct sock) that uses it, the port number and * link to the socket (struct sock) that uses it, the port number and
* a fastreuse flag (FIXME: NPI ipg). * a fastreuse flag (FIXME: NPI ipg).
*/ */
static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, static struct sctp_bind_bucket *sctp_bucket_create(
unsigned short snum); struct sctp_bind_hashbucket *head, unsigned short snum);
static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{ {
sctp_bind_hashbucket_t *head; /* hash list */ struct sctp_bind_hashbucket *head; /* hash list */
sctp_bind_bucket_t *pp; /* hash list port iterator */ struct sctp_bind_bucket *pp; /* hash list port iterator */
struct sctp_protocol *sctp = sctp_get_protocol(); struct sctp_protocol *sctp = sctp_get_protocol();
unsigned short snum; unsigned short snum;
int ret; int ret;
...@@ -3105,12 +3108,12 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) ...@@ -3105,12 +3108,12 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
* 2nd Level Abstractions * 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 = kmem_cache_alloc(sctp_bucket_cachep, SLAB_ATOMIC);
pp = kmalloc(sizeof(sctp_bind_bucket_t), GFP_ATOMIC);
if (pp) { if (pp) {
pp->port = snum; pp->port = snum;
pp->fastreuse = 0; pp->fastreuse = 0;
...@@ -3120,31 +3123,36 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi ...@@ -3120,31 +3123,36 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
head->chain = pp; head->chain = pp;
pp->pprev = &head->chain; pp->pprev = &head->chain;
} }
SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp);
return 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! */ /* FIXME: Comments! */
static __inline__ void __sctp_put_port(struct sock *sk) static __inline__ void __sctp_put_port(struct sock *sk)
{ {
struct sctp_protocol *sctp_proto = sctp_get_protocol(); 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_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
sctp_bind_bucket_t *pp; struct sctp_bind_bucket *pp;
sctp_spin_lock(&head->lock); sctp_spin_lock(&head->lock);
pp = (sctp_bind_bucket_t *) sk->prev; pp = (struct sctp_bind_bucket *) sk->prev;
if (sk->bind_next) if (sk->bind_next)
sk->bind_next->bind_pprev = sk->bind_pprev; sk->bind_next->bind_pprev = sk->bind_pprev;
*(sk->bind_pprev) = sk->bind_next; *(sk->bind_pprev) = sk->bind_next;
sk->prev = NULL; sk->prev = NULL;
inet_sk(sk)->num = 0; inet_sk(sk)->num = 0;
if (pp->sk) { sctp_bucket_destroy(pp);
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
kfree(pp);
}
sctp_spin_unlock(&head->lock); 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