diff options
author | David Howells <dhowells@redhat.com> | 2016-06-30 07:02:53 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-07-06 05:51:14 -0400 |
commit | 1291e9d1084506c5cba6313ce809d7516bb5868a (patch) | |
tree | be33d884464e6072ee278801327de9fe76c9b089 | |
parent | e8d70ce177eeb4fbd1c218c60118d2c19c2496a6 (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.h | 3 | ||||
-rw-r--r-- | net/rxrpc/conn_object.c | 73 | ||||
-rw-r--r-- | net/rxrpc/input.c | 30 | ||||
-rw-r--r-- | net/rxrpc/utils.c | 27 |
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 *); |
565 | struct rxrpc_connection *rxrpc_alloc_connection(gfp_t); | 565 | struct rxrpc_connection *rxrpc_alloc_connection(gfp_t); |
566 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *, | 566 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *, |
567 | struct rxrpc_peer *, | ||
568 | struct sk_buff *); | 567 | struct sk_buff *); |
569 | void __rxrpc_disconnect_call(struct rxrpc_call *); | 568 | void __rxrpc_disconnect_call(struct rxrpc_call *); |
570 | void rxrpc_disconnect_call(struct rxrpc_call *); | 569 | void 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 | */ |
771 | void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *, | ||
772 | struct sockaddr_rxrpc *); | ||
773 | int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *); | 770 | int 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 | */ |
70 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local, | 70 | struct 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); | 151 | not_found: |
113 | _leave(" = NULL"); | 152 | _leave(" = NULL"); |
114 | return NULL; | 153 | return NULL; |
115 | 154 | ||
116 | found: | 155 | found_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 | ||
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 | |||
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 | */ | ||
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 | |||
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 | */ |
47 | int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb) | 20 | int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb) |