Skip to content

Commit 4f00878

Browse files
lxindavem330
authored andcommitted
sctp: apply rhashtable api to send/recv path
apply lookup apis to two functions, for __sctp_endpoint_lookup_assoc and __sctp_lookup_association, it's invoked in the protection of sock lock, it will be safe, but sctp_lookup_association need to call rcu_read_lock() and to detect the t->dead to protect it. Signed-off-by: Xin Long <[email protected]> Signed-off-by: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d6c0256 commit 4f00878

File tree

4 files changed

+29
-56
lines changed

4 files changed

+29
-56
lines changed

net/sctp/associola.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ void sctp_association_free(struct sctp_association *asoc)
383383
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
384384
transport = list_entry(pos, struct sctp_transport, transports);
385385
list_del_rcu(pos);
386+
sctp_unhash_transport(transport);
386387
sctp_transport_free(transport);
387388
}
388389

@@ -500,6 +501,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
500501

501502
/* Remove this peer from the list. */
502503
list_del_rcu(&peer->transports);
504+
/* Remove this peer from the transport hashtable */
505+
sctp_unhash_transport(peer);
503506

504507
/* Get the first transport of asoc. */
505508
pos = asoc->peer.transport_addr_list.next;
@@ -699,6 +702,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
699702
/* Attach the remote transport to our asoc. */
700703
list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
701704
asoc->peer.transport_count++;
705+
/* Add this peer into the transport hashtable */
706+
sctp_hash_transport(peer);
702707

703708
/* If we do not yet have a primary path, set one. */
704709
if (!asoc->peer.primary_path) {

net/sctp/endpointola.c

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -314,21 +314,16 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
314314
}
315315

316316
/* Find the association that goes with this chunk.
317-
* We do a linear search of the associations for this endpoint.
318-
* We return the matching transport address too.
317+
* We lookup the transport from hashtable at first, then get association
318+
* through t->assoc.
319319
*/
320320
static struct sctp_association *__sctp_endpoint_lookup_assoc(
321321
const struct sctp_endpoint *ep,
322322
const union sctp_addr *paddr,
323323
struct sctp_transport **transport)
324324
{
325325
struct sctp_association *asoc = NULL;
326-
struct sctp_association *tmp;
327-
struct sctp_transport *t = NULL;
328-
struct sctp_hashbucket *head;
329-
struct sctp_ep_common *epb;
330-
int hash;
331-
int rport;
326+
struct sctp_transport *t;
332327

333328
*transport = NULL;
334329

@@ -337,26 +332,12 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
337332
*/
338333
if (!ep->base.bind_addr.port)
339334
goto out;
335+
t = sctp_epaddr_lookup_transport(ep, paddr);
336+
if (!t || t->asoc->temp)
337+
goto out;
340338

341-
rport = ntohs(paddr->v4.sin_port);
342-
343-
hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
344-
rport);
345-
head = &sctp_assoc_hashtable[hash];
346-
read_lock(&head->lock);
347-
sctp_for_each_hentry(epb, &head->chain) {
348-
tmp = sctp_assoc(epb);
349-
if (tmp->ep != ep || rport != tmp->peer.port)
350-
continue;
351-
352-
t = sctp_assoc_lookup_paddr(tmp, paddr);
353-
if (t) {
354-
asoc = tmp;
355-
*transport = t;
356-
break;
357-
}
358-
}
359-
read_unlock(&head->lock);
339+
*transport = t;
340+
asoc = t->asoc;
360341
out:
361342
return asoc;
362343
}

net/sctp/input.c

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -981,38 +981,19 @@ static struct sctp_association *__sctp_lookup_association(
981981
const union sctp_addr *peer,
982982
struct sctp_transport **pt)
983983
{
984-
struct sctp_hashbucket *head;
985-
struct sctp_ep_common *epb;
986-
struct sctp_association *asoc;
987-
struct sctp_transport *transport;
988-
int hash;
984+
struct sctp_transport *t;
989985

990-
/* Optimize here for direct hit, only listening connections can
991-
* have wildcards anyways.
992-
*/
993-
hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
994-
ntohs(peer->v4.sin_port));
995-
head = &sctp_assoc_hashtable[hash];
996-
read_lock(&head->lock);
997-
sctp_for_each_hentry(epb, &head->chain) {
998-
asoc = sctp_assoc(epb);
999-
transport = sctp_assoc_is_match(asoc, net, local, peer);
1000-
if (transport)
1001-
goto hit;
1002-
}
986+
t = sctp_addrs_lookup_transport(net, local, peer);
987+
if (!t || t->dead || t->asoc->temp)
988+
return NULL;
1003989

1004-
read_unlock(&head->lock);
990+
sctp_association_hold(t->asoc);
991+
*pt = t;
1005992

1006-
return NULL;
1007-
1008-
hit:
1009-
*pt = transport;
1010-
sctp_association_hold(asoc);
1011-
read_unlock(&head->lock);
1012-
return asoc;
993+
return t->asoc;
1013994
}
1014995

1015-
/* Look up an association. BH-safe. */
996+
/* Look up an association. protected by RCU read lock */
1016997
static
1017998
struct sctp_association *sctp_lookup_association(struct net *net,
1018999
const union sctp_addr *laddr,
@@ -1021,9 +1002,9 @@ struct sctp_association *sctp_lookup_association(struct net *net,
10211002
{
10221003
struct sctp_association *asoc;
10231004

1024-
local_bh_disable();
1005+
rcu_read_lock();
10251006
asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
1026-
local_bh_enable();
1007+
rcu_read_unlock();
10271008

10281009
return asoc;
10291010
}

net/sctp/protocol.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,9 @@ static __init int sctp_init(void)
14671467
INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
14681468
}
14691469

1470+
if (sctp_transport_hashtable_init())
1471+
goto err_thash_alloc;
1472+
14701473
pr_info("Hash tables configured (established %d bind %d)\n",
14711474
sctp_assoc_hashsize, sctp_port_hashsize);
14721475

@@ -1521,6 +1524,8 @@ static __init int sctp_init(void)
15211524
get_order(sctp_port_hashsize *
15221525
sizeof(struct sctp_bind_hashbucket)));
15231526
err_bhash_alloc:
1527+
sctp_transport_hashtable_destroy();
1528+
err_thash_alloc:
15241529
kfree(sctp_ep_hashtable);
15251530
err_ehash_alloc:
15261531
free_pages((unsigned long)sctp_assoc_hashtable,
@@ -1567,6 +1572,7 @@ static __exit void sctp_exit(void)
15671572
free_pages((unsigned long)sctp_port_hashtable,
15681573
get_order(sctp_port_hashsize *
15691574
sizeof(struct sctp_bind_hashbucket)));
1575+
sctp_transport_hashtable_destroy();
15701576

15711577
percpu_counter_destroy(&sctp_sockets_allocated);
15721578

0 commit comments

Comments
 (0)