rxrpc: Move data_ready peer lookup into rxrpc_find_connection()
Move the peer lookup done in input.c by data_ready into rxrpc_find_connection(). Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
e8d70ce177
commit
1291e9d108
|
@ -564,7 +564,6 @@ void rxrpc_extract_conn_params(struct rxrpc_conn_proto *,
|
||||||
struct rxrpc_local *, struct sk_buff *);
|
struct rxrpc_local *, struct sk_buff *);
|
||||||
struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
|
struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
|
||||||
struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *,
|
struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *,
|
||||||
struct rxrpc_peer *,
|
|
||||||
struct sk_buff *);
|
struct sk_buff *);
|
||||||
void __rxrpc_disconnect_call(struct rxrpc_call *);
|
void __rxrpc_disconnect_call(struct rxrpc_call *);
|
||||||
void rxrpc_disconnect_call(struct rxrpc_call *);
|
void rxrpc_disconnect_call(struct rxrpc_call *);
|
||||||
|
@ -768,8 +767,6 @@ static inline void rxrpc_sysctl_exit(void) {}
|
||||||
/*
|
/*
|
||||||
* utils.c
|
* utils.c
|
||||||
*/
|
*/
|
||||||
void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *,
|
|
||||||
struct sockaddr_rxrpc *);
|
|
||||||
int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
|
int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -68,52 +68,91 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
|
||||||
* packet
|
* packet
|
||||||
*/
|
*/
|
||||||
struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local,
|
struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local,
|
||||||
struct rxrpc_peer *peer,
|
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct rxrpc_connection *conn;
|
struct rxrpc_connection *conn;
|
||||||
|
struct rxrpc_conn_proto k;
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
|
struct sockaddr_rxrpc srx;
|
||||||
|
struct rxrpc_peer *peer;
|
||||||
struct rb_node *p;
|
struct rb_node *p;
|
||||||
u32 epoch, cid;
|
|
||||||
|
|
||||||
_enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags);
|
_enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags);
|
||||||
|
|
||||||
read_lock_bh(&peer->conn_lock);
|
if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
cid = sp->hdr.cid & RXRPC_CIDMASK;
|
/* We may have to handle mixing IPv4 and IPv6 */
|
||||||
epoch = sp->hdr.epoch;
|
if (srx.transport.family != local->srx.transport.family) {
|
||||||
|
pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n",
|
||||||
|
srx.transport.family,
|
||||||
|
local->srx.transport.family);
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
k.epoch = sp->hdr.epoch;
|
||||||
|
k.cid = sp->hdr.cid & RXRPC_CIDMASK;
|
||||||
|
|
||||||
if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) {
|
if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) {
|
||||||
|
/* We need to look up service connections by the full protocol
|
||||||
|
* parameter set. We look up the peer first as an intermediate
|
||||||
|
* step and then the connection from the peer's tree.
|
||||||
|
*/
|
||||||
|
peer = rxrpc_lookup_peer_rcu(local, &srx);
|
||||||
|
if (!peer)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
read_lock_bh(&peer->conn_lock);
|
||||||
|
|
||||||
p = peer->service_conns.rb_node;
|
p = peer->service_conns.rb_node;
|
||||||
while (p) {
|
while (p) {
|
||||||
conn = rb_entry(p, struct rxrpc_connection, service_node);
|
conn = rb_entry(p, struct rxrpc_connection, service_node);
|
||||||
|
|
||||||
_debug("maybe %x", conn->proto.cid);
|
_debug("maybe %x", conn->proto.cid);
|
||||||
|
|
||||||
if (epoch < conn->proto.epoch)
|
if (k.epoch < conn->proto.epoch)
|
||||||
p = p->rb_left;
|
p = p->rb_left;
|
||||||
else if (epoch > conn->proto.epoch)
|
else if (k.epoch > conn->proto.epoch)
|
||||||
p = p->rb_right;
|
p = p->rb_right;
|
||||||
else if (cid < conn->proto.cid)
|
else if (k.cid < conn->proto.cid)
|
||||||
p = p->rb_left;
|
p = p->rb_left;
|
||||||
else if (cid > conn->proto.cid)
|
else if (k.cid > conn->proto.cid)
|
||||||
p = p->rb_right;
|
p = p->rb_right;
|
||||||
else
|
else
|
||||||
goto found;
|
goto found_service_conn;
|
||||||
}
|
}
|
||||||
|
read_unlock_bh(&peer->conn_lock);
|
||||||
} else {
|
} else {
|
||||||
conn = idr_find(&rxrpc_client_conn_ids, cid >> RXRPC_CIDSHIFT);
|
conn = idr_find(&rxrpc_client_conn_ids,
|
||||||
if (conn &&
|
k.cid >> RXRPC_CIDSHIFT);
|
||||||
conn->proto.epoch == epoch &&
|
if (!conn ||
|
||||||
conn->params.peer == peer)
|
conn->proto.epoch != k.epoch ||
|
||||||
goto found;
|
conn->params.local != local)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
peer = conn->params.peer;
|
||||||
|
switch (srx.transport.family) {
|
||||||
|
case AF_INET:
|
||||||
|
if (peer->srx.transport.sin.sin_port !=
|
||||||
|
srx.transport.sin.sin_port ||
|
||||||
|
peer->srx.transport.sin.sin_addr.s_addr !=
|
||||||
|
srx.transport.sin.sin_addr.s_addr)
|
||||||
|
goto not_found;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = rxrpc_get_connection_maybe(conn);
|
||||||
|
_leave(" = %p", conn);
|
||||||
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_unlock_bh(&peer->conn_lock);
|
not_found:
|
||||||
_leave(" = NULL");
|
_leave(" = NULL");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
found:
|
found_service_conn:
|
||||||
conn = rxrpc_get_connection_maybe(conn);
|
conn = rxrpc_get_connection_maybe(conn);
|
||||||
read_unlock_bh(&peer->conn_lock);
|
read_unlock_bh(&peer->conn_lock);
|
||||||
_leave(" = %p", conn);
|
_leave(" = %p", conn);
|
||||||
|
|
|
@ -626,32 +626,6 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
|
|
||||||
struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
struct rxrpc_peer *peer;
|
|
||||||
struct rxrpc_connection *conn;
|
|
||||||
struct sockaddr_rxrpc srx;
|
|
||||||
|
|
||||||
rxrpc_get_addr_from_skb(local, skb, &srx);
|
|
||||||
rcu_read_lock();
|
|
||||||
peer = rxrpc_lookup_peer_rcu(local, &srx);
|
|
||||||
if (!peer)
|
|
||||||
goto cant_find_peer;
|
|
||||||
|
|
||||||
conn = rxrpc_find_connection(local, peer, skb);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (!conn)
|
|
||||||
goto cant_find_conn;
|
|
||||||
|
|
||||||
return conn;
|
|
||||||
|
|
||||||
cant_find_peer:
|
|
||||||
rcu_read_unlock();
|
|
||||||
cant_find_conn:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* handle data received on the local endpoint
|
* handle data received on the local endpoint
|
||||||
* - may be called in interrupt context
|
* - may be called in interrupt context
|
||||||
|
@ -731,7 +705,9 @@ void rxrpc_data_ready(struct sock *sk)
|
||||||
* old-fashioned way doesn't really hurt */
|
* old-fashioned way doesn't really hurt */
|
||||||
struct rxrpc_connection *conn;
|
struct rxrpc_connection *conn;
|
||||||
|
|
||||||
conn = rxrpc_conn_from_local(local, skb);
|
rcu_read_lock();
|
||||||
|
conn = rxrpc_find_connection(local, skb);
|
||||||
|
rcu_read_unlock();
|
||||||
if (!conn)
|
if (!conn)
|
||||||
goto cant_route_call;
|
goto cant_route_call;
|
||||||
|
|
||||||
|
|
|
@ -14,33 +14,6 @@
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
#include "ar-internal.h"
|
#include "ar-internal.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Set up an RxRPC address from a socket buffer.
|
|
||||||
*/
|
|
||||||
void rxrpc_get_addr_from_skb(struct rxrpc_local *local,
|
|
||||||
const struct sk_buff *skb,
|
|
||||||
struct sockaddr_rxrpc *srx)
|
|
||||||
{
|
|
||||||
memset(srx, 0, sizeof(*srx));
|
|
||||||
srx->transport_type = local->srx.transport_type;
|
|
||||||
srx->transport.family = local->srx.transport.family;
|
|
||||||
|
|
||||||
/* Can we see an ipv4 UDP packet on an ipv6 UDP socket? and vice
|
|
||||||
* versa?
|
|
||||||
*/
|
|
||||||
switch (srx->transport.family) {
|
|
||||||
case AF_INET:
|
|
||||||
srx->transport.sin.sin_port = udp_hdr(skb)->source;
|
|
||||||
srx->transport_len = sizeof(struct sockaddr_in);
|
|
||||||
memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr,
|
|
||||||
sizeof(struct in_addr));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill out a peer address from a socket buffer containing a packet.
|
* Fill out a peer address from a socket buffer containing a packet.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue