aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-06-30 07:02:53 -0400
committerDavid Howells <dhowells@redhat.com>2016-07-06 05:51:14 -0400
commit1291e9d1084506c5cba6313ce809d7516bb5868a (patch)
treebe33d884464e6072ee278801327de9fe76c9b089
parente8d70ce177eeb4fbd1c218c60118d2c19c2496a6 (diff)
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>
-rw-r--r--net/rxrpc/ar-internal.h3
-rw-r--r--net/rxrpc/conn_object.c73
-rw-r--r--net/rxrpc/input.c30
-rw-r--r--net/rxrpc/utils.c27
4 files changed, 59 insertions, 74 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 6fdee761dd0b..0fe63baf1286 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -564,7 +564,6 @@ void rxrpc_extract_conn_params(struct rxrpc_conn_proto *,
564 struct rxrpc_local *, struct sk_buff *); 564 struct rxrpc_local *, struct sk_buff *);
565struct rxrpc_connection *rxrpc_alloc_connection(gfp_t); 565struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
566struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *, 566struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *,
567 struct rxrpc_peer *,
568 struct sk_buff *); 567 struct sk_buff *);
569void __rxrpc_disconnect_call(struct rxrpc_call *); 568void __rxrpc_disconnect_call(struct rxrpc_call *);
570void rxrpc_disconnect_call(struct rxrpc_call *); 569void rxrpc_disconnect_call(struct rxrpc_call *);
@@ -768,8 +767,6 @@ static inline void rxrpc_sysctl_exit(void) {}
768/* 767/*
769 * utils.c 768 * utils.c
770 */ 769 */
771void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *,
772 struct sockaddr_rxrpc *);
773int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *); 770int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
774 771
775/* 772/*
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 89bc6480b4e2..130713869a16 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -68,52 +68,91 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
68 * packet 68 * packet
69 */ 69 */
70struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local, 70struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local,
71 struct rxrpc_peer *peer,
72 struct sk_buff *skb) 71 struct sk_buff *skb)
73{ 72{
74 struct rxrpc_connection *conn; 73 struct rxrpc_connection *conn;
74 struct rxrpc_conn_proto k;
75 struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 75 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
76 struct sockaddr_rxrpc srx;
77 struct rxrpc_peer *peer;
76 struct rb_node *p; 78 struct rb_node *p;
77 u32 epoch, cid;
78 79
79 _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags); 80 _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags);
80 81
81 read_lock_bh(&peer->conn_lock); 82 if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)
83 goto not_found;
82 84
83 cid = sp->hdr.cid & RXRPC_CIDMASK; 85 /* We may have to handle mixing IPv4 and IPv6 */
84 epoch = sp->hdr.epoch; 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;
85 95
86 if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) { 96 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
87 p = peer->service_conns.rb_node; 107 p = peer->service_conns.rb_node;
88 while (p) { 108 while (p) {
89 conn = rb_entry(p, struct rxrpc_connection, service_node); 109 conn = rb_entry(p, struct rxrpc_connection, service_node);
90 110
91 _debug("maybe %x", conn->proto.cid); 111 _debug("maybe %x", conn->proto.cid);
92 112
93 if (epoch < conn->proto.epoch) 113 if (k.epoch < conn->proto.epoch)
94 p = p->rb_left; 114 p = p->rb_left;
95 else if (epoch > conn->proto.epoch) 115 else if (k.epoch > conn->proto.epoch)
96 p = p->rb_right; 116 p = p->rb_right;
97 else if (cid < conn->proto.cid) 117 else if (k.cid < conn->proto.cid)
98 p = p->rb_left; 118 p = p->rb_left;
99 else if (cid > conn->proto.cid) 119 else if (k.cid > conn->proto.cid)
100 p = p->rb_right; 120 p = p->rb_right;
101 else 121 else
102 goto found; 122 goto found_service_conn;
103 } 123 }
124 read_unlock_bh(&peer->conn_lock);
104 } else { 125 } else {
105 conn = idr_find(&rxrpc_client_conn_ids, cid >> RXRPC_CIDSHIFT); 126 conn = idr_find(&rxrpc_client_conn_ids,
106 if (conn && 127 k.cid >> RXRPC_CIDSHIFT);
107 conn->proto.epoch == epoch && 128 if (!conn ||
108 conn->params.peer == peer) 129 conn->proto.epoch != k.epoch ||
109 goto found; 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;
110 } 149 }
111 150
112 read_unlock_bh(&peer->conn_lock); 151not_found:
113 _leave(" = NULL"); 152 _leave(" = NULL");
114 return NULL; 153 return NULL;
115 154
116found: 155found_service_conn:
117 conn = rxrpc_get_connection_maybe(conn); 156 conn = rxrpc_get_connection_maybe(conn);
118 read_unlock_bh(&peer->conn_lock); 157 read_unlock_bh(&peer->conn_lock);
119 _leave(" = %p", conn); 158 _leave(" = %p", conn);
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index b993f2dc5a09..c2436476f793 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -626,32 +626,6 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb)
626 return 0; 626 return 0;
627} 627}
628 628
629static 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
649cant_find_peer:
650 rcu_read_unlock();
651cant_find_conn:
652 return NULL;
653}
654
655/* 629/*
656 * handle data received on the local endpoint 630 * handle data received on the local endpoint
657 * - may be called in interrupt context 631 * - may be called in interrupt context
@@ -731,7 +705,9 @@ void rxrpc_data_ready(struct sock *sk)
731 * old-fashioned way doesn't really hurt */ 705 * old-fashioned way doesn't really hurt */
732 struct rxrpc_connection *conn; 706 struct rxrpc_connection *conn;
733 707
734 conn = rxrpc_conn_from_local(local, skb); 708 rcu_read_lock();
709 conn = rxrpc_find_connection(local, skb);
710 rcu_read_unlock();
735 if (!conn) 711 if (!conn)
736 goto cant_route_call; 712 goto cant_route_call;
737 713
diff --git a/net/rxrpc/utils.c b/net/rxrpc/utils.c
index d3db02ecc37f..b88914d53ca5 100644
--- a/net/rxrpc/utils.c
+++ b/net/rxrpc/utils.c
@@ -15,33 +15,6 @@
15#include "ar-internal.h" 15#include "ar-internal.h"
16 16
17/* 17/*
18 * Set up an RxRPC address from a socket buffer.
19 */
20void 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
44/*
45 * Fill out a peer address from a socket buffer containing a packet. 18 * Fill out a peer address from a socket buffer containing a packet.
46 */ 19 */
47int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb) 20int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb)