Skip to content

Commit 1291e9d

Browse files
committed
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 <[email protected]>
1 parent e8d70ce commit 1291e9d

File tree

4 files changed

+59
-74
lines changed

4 files changed

+59
-74
lines changed

net/rxrpc/ar-internal.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,6 @@ void rxrpc_extract_conn_params(struct rxrpc_conn_proto *,
564564
struct rxrpc_local *, struct sk_buff *);
565565
struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
566566
struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *,
567-
struct rxrpc_peer *,
568567
struct sk_buff *);
569568
void __rxrpc_disconnect_call(struct rxrpc_call *);
570569
void rxrpc_disconnect_call(struct rxrpc_call *);
@@ -768,8 +767,6 @@ static inline void rxrpc_sysctl_exit(void) {}
768767
/*
769768
* utils.c
770769
*/
771-
void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *,
772-
struct sockaddr_rxrpc *);
773770
int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
774771

775772
/*

net/rxrpc/conn_object.c

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,52 +68,91 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
6868
* packet
6969
*/
7070
struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local,
71-
struct rxrpc_peer *peer,
7271
struct sk_buff *skb)
7372
{
7473
struct rxrpc_connection *conn;
74+
struct rxrpc_conn_proto k;
7575
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
76+
struct sockaddr_rxrpc srx;
77+
struct rxrpc_peer *peer;
7678
struct rb_node *p;
77-
u32 epoch, cid;
7879

7980
_enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags);
8081

81-
read_lock_bh(&peer->conn_lock);
82+
if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)
83+
goto not_found;
8284

83-
cid = sp->hdr.cid & RXRPC_CIDMASK;
84-
epoch = sp->hdr.epoch;
85+
/* We may have to handle mixing IPv4 and IPv6 */
86+
if (srx.transport.family != local->srx.transport.family) {
87+
pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n",
88+
srx.transport.family,
89+
local->srx.transport.family);
90+
goto not_found;
91+
}
92+
93+
k.epoch = sp->hdr.epoch;
94+
k.cid = sp->hdr.cid & RXRPC_CIDMASK;
8595

8696
if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) {
97+
/* We need to look up service connections by the full protocol
98+
* parameter set. We look up the peer first as an intermediate
99+
* step and then the connection from the peer's tree.
100+
*/
101+
peer = rxrpc_lookup_peer_rcu(local, &srx);
102+
if (!peer)
103+
goto not_found;
104+
105+
read_lock_bh(&peer->conn_lock);
106+
87107
p = peer->service_conns.rb_node;
88108
while (p) {
89109
conn = rb_entry(p, struct rxrpc_connection, service_node);
90110

91111
_debug("maybe %x", conn->proto.cid);
92112

93-
if (epoch < conn->proto.epoch)
113+
if (k.epoch < conn->proto.epoch)
94114
p = p->rb_left;
95-
else if (epoch > conn->proto.epoch)
115+
else if (k.epoch > conn->proto.epoch)
96116
p = p->rb_right;
97-
else if (cid < conn->proto.cid)
117+
else if (k.cid < conn->proto.cid)
98118
p = p->rb_left;
99-
else if (cid > conn->proto.cid)
119+
else if (k.cid > conn->proto.cid)
100120
p = p->rb_right;
101121
else
102-
goto found;
122+
goto found_service_conn;
103123
}
124+
read_unlock_bh(&peer->conn_lock);
104125
} else {
105-
conn = idr_find(&rxrpc_client_conn_ids, cid >> RXRPC_CIDSHIFT);
106-
if (conn &&
107-
conn->proto.epoch == epoch &&
108-
conn->params.peer == peer)
109-
goto found;
126+
conn = idr_find(&rxrpc_client_conn_ids,
127+
k.cid >> RXRPC_CIDSHIFT);
128+
if (!conn ||
129+
conn->proto.epoch != k.epoch ||
130+
conn->params.local != local)
131+
goto not_found;
132+
133+
peer = conn->params.peer;
134+
switch (srx.transport.family) {
135+
case AF_INET:
136+
if (peer->srx.transport.sin.sin_port !=
137+
srx.transport.sin.sin_port ||
138+
peer->srx.transport.sin.sin_addr.s_addr !=
139+
srx.transport.sin.sin_addr.s_addr)
140+
goto not_found;
141+
break;
142+
default:
143+
BUG();
144+
}
145+
146+
conn = rxrpc_get_connection_maybe(conn);
147+
_leave(" = %p", conn);
148+
return conn;
110149
}
111150

112-
read_unlock_bh(&peer->conn_lock);
151+
not_found:
113152
_leave(" = NULL");
114153
return NULL;
115154

116-
found:
155+
found_service_conn:
117156
conn = rxrpc_get_connection_maybe(conn);
118157
read_unlock_bh(&peer->conn_lock);
119158
_leave(" = %p", conn);

net/rxrpc/input.c

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -626,32 +626,6 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb)
626626
return 0;
627627
}
628628

629-
static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
630-
struct sk_buff *skb)
631-
{
632-
struct rxrpc_peer *peer;
633-
struct rxrpc_connection *conn;
634-
struct sockaddr_rxrpc srx;
635-
636-
rxrpc_get_addr_from_skb(local, skb, &srx);
637-
rcu_read_lock();
638-
peer = rxrpc_lookup_peer_rcu(local, &srx);
639-
if (!peer)
640-
goto cant_find_peer;
641-
642-
conn = rxrpc_find_connection(local, peer, skb);
643-
rcu_read_unlock();
644-
if (!conn)
645-
goto cant_find_conn;
646-
647-
return conn;
648-
649-
cant_find_peer:
650-
rcu_read_unlock();
651-
cant_find_conn:
652-
return NULL;
653-
}
654-
655629
/*
656630
* handle data received on the local endpoint
657631
* - may be called in interrupt context
@@ -731,7 +705,9 @@ void rxrpc_data_ready(struct sock *sk)
731705
* old-fashioned way doesn't really hurt */
732706
struct rxrpc_connection *conn;
733707

734-
conn = rxrpc_conn_from_local(local, skb);
708+
rcu_read_lock();
709+
conn = rxrpc_find_connection(local, skb);
710+
rcu_read_unlock();
735711
if (!conn)
736712
goto cant_route_call;
737713

net/rxrpc/utils.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,6 @@
1414
#include <linux/udp.h>
1515
#include "ar-internal.h"
1616

17-
/*
18-
* Set up an RxRPC address from a socket buffer.
19-
*/
20-
void rxrpc_get_addr_from_skb(struct rxrpc_local *local,
21-
const struct sk_buff *skb,
22-
struct sockaddr_rxrpc *srx)
23-
{
24-
memset(srx, 0, sizeof(*srx));
25-
srx->transport_type = local->srx.transport_type;
26-
srx->transport.family = local->srx.transport.family;
27-
28-
/* Can we see an ipv4 UDP packet on an ipv6 UDP socket? and vice
29-
* versa?
30-
*/
31-
switch (srx->transport.family) {
32-
case AF_INET:
33-
srx->transport.sin.sin_port = udp_hdr(skb)->source;
34-
srx->transport_len = sizeof(struct sockaddr_in);
35-
memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr,
36-
sizeof(struct in_addr));
37-
break;
38-
39-
default:
40-
BUG();
41-
}
42-
}
43-
4417
/*
4518
* Fill out a peer address from a socket buffer containing a packet.
4619
*/

0 commit comments

Comments
 (0)