diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-11-09 11:41:36 -0500 |
---|---|---|
committer | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-11-09 11:41:36 -0500 |
commit | 123ed979eaa8de0dd2422862d247469eda0bd645 (patch) | |
tree | 745e6ff660cc401dd32e684f3651920e42150211 | |
parent | 027f6e1ad32de32f9fe1c61d0f744e329e8acfd9 (diff) |
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( | |||
328 | const union sctp_addr *paddr, | 328 | const union sctp_addr *paddr, |
329 | struct sctp_transport **transport) | 329 | struct sctp_transport **transport) |
330 | { | 330 | { |
331 | struct sctp_association *asoc = NULL; | ||
332 | struct sctp_transport *t = NULL; | ||
333 | struct sctp_hashbucket *head; | ||
334 | struct sctp_ep_common *epb; | ||
335 | int hash; | ||
331 | int rport; | 336 | int rport; |
332 | struct sctp_association *asoc; | ||
333 | struct list_head *pos; | ||
334 | 337 | ||
338 | *transport = NULL; | ||
335 | rport = ntohs(paddr->v4.sin_port); | 339 | rport = ntohs(paddr->v4.sin_port); |
336 | 340 | ||
337 | list_for_each(pos, &ep->asocs) { | 341 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); |
338 | asoc = list_entry(pos, struct sctp_association, asocs); | 342 | head = &sctp_assoc_hashtable[hash]; |
339 | if (rport == asoc->peer.port) { | 343 | read_lock(&head->lock); |
340 | *transport = sctp_assoc_lookup_paddr(asoc, paddr); | 344 | for (epb = head->chain; epb; epb = epb->next) { |
341 | 345 | asoc = sctp_assoc(epb); | |
342 | if (*transport) | 346 | if (asoc->ep != ep || rport != asoc->peer.port) |
343 | return asoc; | 347 | goto next; |
348 | |||
349 | t = sctp_assoc_lookup_paddr(asoc, paddr); | ||
350 | if (t) { | ||
351 | *transport = t; | ||
352 | break; | ||
344 | } | 353 | } |
354 | next: | ||
355 | asoc = NULL; | ||
345 | } | 356 | } |
346 | 357 | read_unlock(&head->lock); | |
347 | *transport = NULL; | 358 | return asoc; |
348 | return NULL; | ||
349 | } | 359 | } |
350 | 360 | ||
351 | /* Lookup association on an endpoint based on a peer address. BH-safe. */ | 361 | /* Lookup association on an endpoint based on a peer address. BH-safe. */ |