diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-11-09 17:41:36 +0100 |
---|---|---|
committer | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-11-09 17:41:36 +0100 |
commit | 123ed979eaa8de0dd2422862d247469eda0bd645 (patch) | |
tree | 745e6ff660cc401dd32e684f3651920e42150211 | |
parent | SCTP: Fix a potential race between timers and receive path. (diff) | |
download | linux-123ed979eaa8de0dd2422862d247469eda0bd645.tar.xz linux-123ed979eaa8de0dd2422862d247469eda0bd645.zip |
SCTP: Use hashed lookup when looking for an association.
A SCTP endpoint may have a lot of associations on them and walking
the list is fairly inefficient. Instead, use a hashed lookup,
and filter out the hash list based on the endopoing we already have.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
-rw-r--r-- | net/sctp/endpointola.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 2d2d81ef4a69..68f0556efcc6 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -328,24 +328,34 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( const union sctp_addr *paddr, struct sctp_transport **transport) { + struct sctp_association *asoc = NULL; + struct sctp_transport *t = NULL; + struct sctp_hashbucket *head; + struct sctp_ep_common *epb; + int hash; int rport; - struct sctp_association *asoc; - struct list_head *pos; + *transport = NULL; rport = ntohs(paddr->v4.sin_port); - list_for_each(pos, &ep->asocs) { - asoc = list_entry(pos, struct sctp_association, asocs); - if (rport == asoc->peer.port) { - *transport = sctp_assoc_lookup_paddr(asoc, paddr); - - if (*transport) - return asoc; + hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); + head = &sctp_assoc_hashtable[hash]; + read_lock(&head->lock); + for (epb = head->chain; epb; epb = epb->next) { + asoc = sctp_assoc(epb); + if (asoc->ep != ep || rport != asoc->peer.port) + goto next; + + t = sctp_assoc_lookup_paddr(asoc, paddr); + if (t) { + *transport = t; + break; } +next: + asoc = NULL; } - - *transport = NULL; - return NULL; + read_unlock(&head->lock); + return asoc; } /* Lookup association on an endpoint based on a peer address. BH-safe. */ |