mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 <lucien.xin@gmail.com> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									d6c0256a60
								
							
						
					
					
						commit
						4f00878126
					
				
					 4 changed files with 29 additions and 56 deletions
				
			
		| 
						 | 
				
			
			@ -383,6 +383,7 @@ void sctp_association_free(struct sctp_association *asoc)
 | 
			
		|||
	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
 | 
			
		||||
		transport = list_entry(pos, struct sctp_transport, transports);
 | 
			
		||||
		list_del_rcu(pos);
 | 
			
		||||
		sctp_unhash_transport(transport);
 | 
			
		||||
		sctp_transport_free(transport);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -500,6 +501,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
 | 
			
		|||
 | 
			
		||||
	/* Remove this peer from the list. */
 | 
			
		||||
	list_del_rcu(&peer->transports);
 | 
			
		||||
	/* Remove this peer from the transport hashtable */
 | 
			
		||||
	sctp_unhash_transport(peer);
 | 
			
		||||
 | 
			
		||||
	/* Get the first transport of asoc. */
 | 
			
		||||
	pos = asoc->peer.transport_addr_list.next;
 | 
			
		||||
| 
						 | 
				
			
			@ -699,6 +702,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 | 
			
		|||
	/* Attach the remote transport to our asoc.  */
 | 
			
		||||
	list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
 | 
			
		||||
	asoc->peer.transport_count++;
 | 
			
		||||
	/* Add this peer into the transport hashtable */
 | 
			
		||||
	sctp_hash_transport(peer);
 | 
			
		||||
 | 
			
		||||
	/* If we do not yet have a primary path, set one.  */
 | 
			
		||||
	if (!asoc->peer.primary_path) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -314,8 +314,8 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* Find the association that goes with this chunk.
 | 
			
		||||
 * We do a linear search of the associations for this endpoint.
 | 
			
		||||
 * We return the matching transport address too.
 | 
			
		||||
 * We lookup the transport from hashtable at first, then get association
 | 
			
		||||
 * through t->assoc.
 | 
			
		||||
 */
 | 
			
		||||
static struct sctp_association *__sctp_endpoint_lookup_assoc(
 | 
			
		||||
	const struct sctp_endpoint *ep,
 | 
			
		||||
| 
						 | 
				
			
			@ -323,12 +323,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
 | 
			
		|||
	struct sctp_transport **transport)
 | 
			
		||||
{
 | 
			
		||||
	struct sctp_association *asoc = NULL;
 | 
			
		||||
	struct sctp_association *tmp;
 | 
			
		||||
	struct sctp_transport *t = NULL;
 | 
			
		||||
	struct sctp_hashbucket *head;
 | 
			
		||||
	struct sctp_ep_common *epb;
 | 
			
		||||
	int hash;
 | 
			
		||||
	int rport;
 | 
			
		||||
	struct sctp_transport *t;
 | 
			
		||||
 | 
			
		||||
	*transport = NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -337,26 +332,12 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
 | 
			
		|||
	 */
 | 
			
		||||
	if (!ep->base.bind_addr.port)
 | 
			
		||||
		goto out;
 | 
			
		||||
	t = sctp_epaddr_lookup_transport(ep, paddr);
 | 
			
		||||
	if (!t || t->asoc->temp)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	rport = ntohs(paddr->v4.sin_port);
 | 
			
		||||
 | 
			
		||||
	hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
 | 
			
		||||
				 rport);
 | 
			
		||||
	head = &sctp_assoc_hashtable[hash];
 | 
			
		||||
	read_lock(&head->lock);
 | 
			
		||||
	sctp_for_each_hentry(epb, &head->chain) {
 | 
			
		||||
		tmp = sctp_assoc(epb);
 | 
			
		||||
		if (tmp->ep != ep || rport != tmp->peer.port)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		t = sctp_assoc_lookup_paddr(tmp, paddr);
 | 
			
		||||
		if (t) {
 | 
			
		||||
			asoc = tmp;
 | 
			
		||||
			*transport = t;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	read_unlock(&head->lock);
 | 
			
		||||
	*transport = t;
 | 
			
		||||
	asoc = t->asoc;
 | 
			
		||||
out:
 | 
			
		||||
	return asoc;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -981,38 +981,19 @@ static struct sctp_association *__sctp_lookup_association(
 | 
			
		|||
					const union sctp_addr *peer,
 | 
			
		||||
					struct sctp_transport **pt)
 | 
			
		||||
{
 | 
			
		||||
	struct sctp_hashbucket *head;
 | 
			
		||||
	struct sctp_ep_common *epb;
 | 
			
		||||
	struct sctp_association *asoc;
 | 
			
		||||
	struct sctp_transport *transport;
 | 
			
		||||
	int hash;
 | 
			
		||||
	struct sctp_transport *t;
 | 
			
		||||
 | 
			
		||||
	/* Optimize here for direct hit, only listening connections can
 | 
			
		||||
	 * have wildcards anyways.
 | 
			
		||||
	 */
 | 
			
		||||
	hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
 | 
			
		||||
				 ntohs(peer->v4.sin_port));
 | 
			
		||||
	head = &sctp_assoc_hashtable[hash];
 | 
			
		||||
	read_lock(&head->lock);
 | 
			
		||||
	sctp_for_each_hentry(epb, &head->chain) {
 | 
			
		||||
		asoc = sctp_assoc(epb);
 | 
			
		||||
		transport = sctp_assoc_is_match(asoc, net, local, peer);
 | 
			
		||||
		if (transport)
 | 
			
		||||
			goto hit;
 | 
			
		||||
	}
 | 
			
		||||
	t = sctp_addrs_lookup_transport(net, local, peer);
 | 
			
		||||
	if (!t || t->dead || t->asoc->temp)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	read_unlock(&head->lock);
 | 
			
		||||
	sctp_association_hold(t->asoc);
 | 
			
		||||
	*pt = t;
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
 | 
			
		||||
hit:
 | 
			
		||||
	*pt = transport;
 | 
			
		||||
	sctp_association_hold(asoc);
 | 
			
		||||
	read_unlock(&head->lock);
 | 
			
		||||
	return asoc;
 | 
			
		||||
	return t->asoc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Look up an association. BH-safe. */
 | 
			
		||||
/* Look up an association. protected by RCU read lock */
 | 
			
		||||
static
 | 
			
		||||
struct sctp_association *sctp_lookup_association(struct net *net,
 | 
			
		||||
						 const union sctp_addr *laddr,
 | 
			
		||||
| 
						 | 
				
			
			@ -1021,9 +1002,9 @@ struct sctp_association *sctp_lookup_association(struct net *net,
 | 
			
		|||
{
 | 
			
		||||
	struct sctp_association *asoc;
 | 
			
		||||
 | 
			
		||||
	local_bh_disable();
 | 
			
		||||
	rcu_read_lock();
 | 
			
		||||
	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
 | 
			
		||||
	local_bh_enable();
 | 
			
		||||
	rcu_read_unlock();
 | 
			
		||||
 | 
			
		||||
	return asoc;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1467,6 +1467,9 @@ static __init int sctp_init(void)
 | 
			
		|||
		INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sctp_transport_hashtable_init())
 | 
			
		||||
		goto err_thash_alloc;
 | 
			
		||||
 | 
			
		||||
	pr_info("Hash tables configured (established %d bind %d)\n",
 | 
			
		||||
		sctp_assoc_hashsize, sctp_port_hashsize);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1521,6 +1524,8 @@ static __init int sctp_init(void)
 | 
			
		|||
		   get_order(sctp_port_hashsize *
 | 
			
		||||
			     sizeof(struct sctp_bind_hashbucket)));
 | 
			
		||||
err_bhash_alloc:
 | 
			
		||||
	sctp_transport_hashtable_destroy();
 | 
			
		||||
err_thash_alloc:
 | 
			
		||||
	kfree(sctp_ep_hashtable);
 | 
			
		||||
err_ehash_alloc:
 | 
			
		||||
	free_pages((unsigned long)sctp_assoc_hashtable,
 | 
			
		||||
| 
						 | 
				
			
			@ -1567,6 +1572,7 @@ static __exit void sctp_exit(void)
 | 
			
		|||
	free_pages((unsigned long)sctp_port_hashtable,
 | 
			
		||||
		   get_order(sctp_port_hashsize *
 | 
			
		||||
			     sizeof(struct sctp_bind_hashbucket)));
 | 
			
		||||
	sctp_transport_hashtable_destroy();
 | 
			
		||||
 | 
			
		||||
	percpu_counter_destroy(&sctp_sockets_allocated);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue