aboutsummaryrefslogtreecommitdiffstats
path: root/net/rxrpc
diff options
context:
space:
mode:
authorTim Smith <tim@electronghost.co.uk>2014-03-03 18:04:45 -0500
committerDavid Howells <dhowells@redhat.com>2014-03-04 05:36:53 -0500
commit7727640cc3c4d03b6a3cb5bf26d48c72e31403ca (patch)
tree1297fc34c3003a300faa45d57ecd4db15730a5d8 /net/rxrpc
parente8388eb10371745627d1e538e018cb10ded86aa7 (diff)
af_rxrpc: Keep rxrpc_call pointers in a hashtable
Keep track of rxrpc_call structures in a hashtable so they can be found directly from the network parameters which define the call. This allows incoming packets to be routed directly to a call without walking through hierarchy of peer -> transport -> connection -> call and all the spinlocks that that entailed. Signed-off-by: Tim Smith <tim@electronghost.co.uk> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc')
-rw-r--r--net/rxrpc/ar-call.c193
-rw-r--r--net/rxrpc/ar-input.c177
-rw-r--r--net/rxrpc/ar-internal.h13
3 files changed, 277 insertions, 106 deletions
diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c
index 6e4d58c9b042..a9e05db0f5d5 100644
--- a/net/rxrpc/ar-call.c
+++ b/net/rxrpc/ar-call.c
@@ -12,6 +12,8 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/circ_buf.h> 14#include <linux/circ_buf.h>
15#include <linux/hashtable.h>
16#include <linux/spinlock_types.h>
15#include <net/sock.h> 17#include <net/sock.h>
16#include <net/af_rxrpc.h> 18#include <net/af_rxrpc.h>
17#include "ar-internal.h" 19#include "ar-internal.h"
@@ -55,6 +57,145 @@ static void rxrpc_dead_call_expired(unsigned long _call);
55static void rxrpc_ack_time_expired(unsigned long _call); 57static void rxrpc_ack_time_expired(unsigned long _call);
56static void rxrpc_resend_time_expired(unsigned long _call); 58static void rxrpc_resend_time_expired(unsigned long _call);
57 59
60static DEFINE_SPINLOCK(rxrpc_call_hash_lock);
61static DEFINE_HASHTABLE(rxrpc_call_hash, 10);
62
63/*
64 * Hash function for rxrpc_call_hash
65 */
66static unsigned long rxrpc_call_hashfunc(
67 u8 clientflag,
68 __be32 cid,
69 __be32 call_id,
70 __be32 epoch,
71 __be16 service_id,
72 sa_family_t proto,
73 void *localptr,
74 unsigned int addr_size,
75 const u8 *peer_addr)
76{
77 const u16 *p;
78 unsigned int i;
79 unsigned long key;
80 u32 hcid = ntohl(cid);
81
82 _enter("");
83
84 key = (unsigned long)localptr;
85 /* We just want to add up the __be32 values, so forcing the
86 * cast should be okay.
87 */
88 key += (__force u32)epoch;
89 key += (__force u16)service_id;
90 key += (__force u32)call_id;
91 key += (hcid & RXRPC_CIDMASK) >> RXRPC_CIDSHIFT;
92 key += hcid & RXRPC_CHANNELMASK;
93 key += clientflag;
94 key += proto;
95 /* Step through the peer address in 16-bit portions for speed */
96 for (i = 0, p = (const u16 *)peer_addr; i < addr_size >> 1; i++, p++)
97 key += *p;
98 _leave(" key = 0x%lx", key);
99 return key;
100}
101
102/*
103 * Add a call to the hashtable
104 */
105static void rxrpc_call_hash_add(struct rxrpc_call *call)
106{
107 unsigned long key;
108 unsigned int addr_size = 0;
109
110 _enter("");
111 switch (call->proto) {
112 case AF_INET:
113 addr_size = sizeof(call->peer_ip.ipv4_addr);
114 break;
115 case AF_INET6:
116 addr_size = sizeof(call->peer_ip.ipv6_addr);
117 break;
118 default:
119 break;
120 }
121 key = rxrpc_call_hashfunc(call->in_clientflag, call->cid,
122 call->call_id, call->epoch,
123 call->service_id, call->proto,
124 call->conn->trans->local, addr_size,
125 call->peer_ip.ipv6_addr);
126 /* Store the full key in the call */
127 call->hash_key = key;
128 spin_lock(&rxrpc_call_hash_lock);
129 hash_add_rcu(rxrpc_call_hash, &call->hash_node, key);
130 spin_unlock(&rxrpc_call_hash_lock);
131 _leave("");
132}
133
134/*
135 * Remove a call from the hashtable
136 */
137static void rxrpc_call_hash_del(struct rxrpc_call *call)
138{
139 _enter("");
140 spin_lock(&rxrpc_call_hash_lock);
141 hash_del_rcu(&call->hash_node);
142 spin_unlock(&rxrpc_call_hash_lock);
143 _leave("");
144}
145
146/*
147 * Find a call in the hashtable and return it, or NULL if it
148 * isn't there.
149 */
150struct rxrpc_call *rxrpc_find_call_hash(
151 u8 clientflag,
152 __be32 cid,
153 __be32 call_id,
154 __be32 epoch,
155 __be16 service_id,
156 void *localptr,
157 sa_family_t proto,
158 const u8 *peer_addr)
159{
160 unsigned long key;
161 unsigned int addr_size = 0;
162 struct rxrpc_call *call = NULL;
163 struct rxrpc_call *ret = NULL;
164
165 _enter("");
166 switch (proto) {
167 case AF_INET:
168 addr_size = sizeof(call->peer_ip.ipv4_addr);
169 break;
170 case AF_INET6:
171 addr_size = sizeof(call->peer_ip.ipv6_addr);
172 break;
173 default:
174 break;
175 }
176
177 key = rxrpc_call_hashfunc(clientflag, cid, call_id, epoch,
178 service_id, proto, localptr, addr_size,
179 peer_addr);
180 hash_for_each_possible_rcu(rxrpc_call_hash, call, hash_node, key) {
181 if (call->hash_key == key &&
182 call->call_id == call_id &&
183 call->cid == cid &&
184 call->in_clientflag == clientflag &&
185 call->service_id == service_id &&
186 call->proto == proto &&
187 call->local == localptr &&
188 memcmp(call->peer_ip.ipv6_addr, peer_addr,
189 addr_size) == 0 &&
190 call->epoch == epoch) {
191 ret = call;
192 break;
193 }
194 }
195 _leave(" = %p", ret);
196 return ret;
197}
198
58/* 199/*
59 * allocate a new call 200 * allocate a new call
60 */ 201 */
@@ -136,6 +277,26 @@ static struct rxrpc_call *rxrpc_alloc_client_call(
136 return ERR_PTR(ret); 277 return ERR_PTR(ret);
137 } 278 }
138 279
280 /* Record copies of information for hashtable lookup */
281 call->proto = rx->proto;
282 call->local = trans->local;
283 switch (call->proto) {
284 case AF_INET:
285 call->peer_ip.ipv4_addr =
286 trans->peer->srx.transport.sin.sin_addr.s_addr;
287 break;
288 case AF_INET6:
289 memcpy(call->peer_ip.ipv6_addr,
290 trans->peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8,
291 sizeof(call->peer_ip.ipv6_addr));
292 break;
293 }
294 call->epoch = call->conn->epoch;
295 call->service_id = call->conn->service_id;
296 call->in_clientflag = call->conn->in_clientflag;
297 /* Add the new call to the hashtable */
298 rxrpc_call_hash_add(call);
299
139 spin_lock(&call->conn->trans->peer->lock); 300 spin_lock(&call->conn->trans->peer->lock);
140 list_add(&call->error_link, &call->conn->trans->peer->error_targets); 301 list_add(&call->error_link, &call->conn->trans->peer->error_targets);
141 spin_unlock(&call->conn->trans->peer->lock); 302 spin_unlock(&call->conn->trans->peer->lock);
@@ -328,9 +489,12 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
328 parent = *p; 489 parent = *p;
329 call = rb_entry(parent, struct rxrpc_call, conn_node); 490 call = rb_entry(parent, struct rxrpc_call, conn_node);
330 491
331 if (call_id < call->call_id) 492 /* The tree is sorted in order of the __be32 value without
493 * turning it into host order.
494 */
495 if ((__force u32)call_id < (__force u32)call->call_id)
332 p = &(*p)->rb_left; 496 p = &(*p)->rb_left;
333 else if (call_id > call->call_id) 497 else if ((__force u32)call_id > (__force u32)call->call_id)
334 p = &(*p)->rb_right; 498 p = &(*p)->rb_right;
335 else 499 else
336 goto old_call; 500 goto old_call;
@@ -355,6 +519,28 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
355 list_add_tail(&call->link, &rxrpc_calls); 519 list_add_tail(&call->link, &rxrpc_calls);
356 write_unlock_bh(&rxrpc_call_lock); 520 write_unlock_bh(&rxrpc_call_lock);
357 521
522 /* Record copies of information for hashtable lookup */
523 call->proto = rx->proto;
524 call->local = conn->trans->local;
525 switch (call->proto) {
526 case AF_INET:
527 call->peer_ip.ipv4_addr =
528 conn->trans->peer->srx.transport.sin.sin_addr.s_addr;
529 break;
530 case AF_INET6:
531 memcpy(call->peer_ip.ipv6_addr,
532 conn->trans->peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8,
533 sizeof(call->peer_ip.ipv6_addr));
534 break;
535 default:
536 break;
537 }
538 call->epoch = conn->epoch;
539 call->service_id = conn->service_id;
540 call->in_clientflag = conn->in_clientflag;
541 /* Add the new call to the hashtable */
542 rxrpc_call_hash_add(call);
543
358 _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); 544 _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id);
359 545
360 call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; 546 call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime;
@@ -673,6 +859,9 @@ static void rxrpc_cleanup_call(struct rxrpc_call *call)
673 rxrpc_put_connection(call->conn); 859 rxrpc_put_connection(call->conn);
674 } 860 }
675 861
862 /* Remove the call from the hash */
863 rxrpc_call_hash_del(call);
864
676 if (call->acks_window) { 865 if (call->acks_window) {
677 _debug("kill Tx window %d", 866 _debug("kill Tx window %d",
678 CIRC_CNT(call->acks_head, call->acks_tail, 867 CIRC_CNT(call->acks_head, call->acks_tail,
diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c
index e449c675c36a..73742647c135 100644
--- a/net/rxrpc/ar-input.c
+++ b/net/rxrpc/ar-input.c
@@ -523,36 +523,38 @@ protocol_error:
523 * post an incoming packet to the appropriate call/socket to deal with 523 * post an incoming packet to the appropriate call/socket to deal with
524 * - must get rid of the sk_buff, either by freeing it or by queuing it 524 * - must get rid of the sk_buff, either by freeing it or by queuing it
525 */ 525 */
526static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn, 526static void rxrpc_post_packet_to_call(struct rxrpc_call *call,
527 struct sk_buff *skb) 527 struct sk_buff *skb)
528{ 528{
529 struct rxrpc_skb_priv *sp; 529 struct rxrpc_skb_priv *sp;
530 struct rxrpc_call *call;
531 struct rb_node *p;
532 __be32 call_id;
533 530
534 _enter("%p,%p", conn, skb); 531 _enter("%p,%p", call, skb);
535
536 read_lock_bh(&conn->lock);
537 532
538 sp = rxrpc_skb(skb); 533 sp = rxrpc_skb(skb);
539 534
540 /* look at extant calls by channel number first */
541 call = conn->channels[ntohl(sp->hdr.cid) & RXRPC_CHANNELMASK];
542 if (!call || call->call_id != sp->hdr.callNumber)
543 goto call_not_extant;
544
545 _debug("extant call [%d]", call->state); 535 _debug("extant call [%d]", call->state);
546 ASSERTCMP(call->conn, ==, conn);
547 536
548 read_lock(&call->state_lock); 537 read_lock(&call->state_lock);
549 switch (call->state) { 538 switch (call->state) {
550 case RXRPC_CALL_LOCALLY_ABORTED: 539 case RXRPC_CALL_LOCALLY_ABORTED:
551 if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events)) 540 if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events)) {
552 rxrpc_queue_call(call); 541 rxrpc_queue_call(call);
542 goto free_unlock;
543 }
553 case RXRPC_CALL_REMOTELY_ABORTED: 544 case RXRPC_CALL_REMOTELY_ABORTED:
554 case RXRPC_CALL_NETWORK_ERROR: 545 case RXRPC_CALL_NETWORK_ERROR:
555 case RXRPC_CALL_DEAD: 546 case RXRPC_CALL_DEAD:
547 goto dead_call;
548 case RXRPC_CALL_COMPLETE:
549 case RXRPC_CALL_CLIENT_FINAL_ACK:
550 /* complete server call */
551 if (call->conn->in_clientflag)
552 goto dead_call;
553 /* resend last packet of a completed call */
554 _debug("final ack again");
555 rxrpc_get_call(call);
556 set_bit(RXRPC_CALL_ACK_FINAL, &call->events);
557 rxrpc_queue_call(call);
556 goto free_unlock; 558 goto free_unlock;
557 default: 559 default:
558 break; 560 break;
@@ -560,7 +562,6 @@ static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn,
560 562
561 read_unlock(&call->state_lock); 563 read_unlock(&call->state_lock);
562 rxrpc_get_call(call); 564 rxrpc_get_call(call);
563 read_unlock_bh(&conn->lock);
564 565
565 if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && 566 if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
566 sp->hdr.flags & RXRPC_JUMBO_PACKET) 567 sp->hdr.flags & RXRPC_JUMBO_PACKET)
@@ -571,80 +572,16 @@ static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn,
571 rxrpc_put_call(call); 572 rxrpc_put_call(call);
572 goto done; 573 goto done;
573 574
574call_not_extant:
575 /* search the completed calls in case what we're dealing with is
576 * there */
577 _debug("call not extant");
578
579 call_id = sp->hdr.callNumber;
580 p = conn->calls.rb_node;
581 while (p) {
582 call = rb_entry(p, struct rxrpc_call, conn_node);
583
584 if (call_id < call->call_id)
585 p = p->rb_left;
586 else if (call_id > call->call_id)
587 p = p->rb_right;
588 else
589 goto found_completed_call;
590 }
591
592dead_call: 575dead_call:
593 /* it's a either a really old call that we no longer remember or its a
594 * new incoming call */
595 read_unlock_bh(&conn->lock);
596
597 if (sp->hdr.flags & RXRPC_CLIENT_INITIATED &&
598 sp->hdr.seq == cpu_to_be32(1)) {
599 _debug("incoming call");
600 skb_queue_tail(&conn->trans->local->accept_queue, skb);
601 rxrpc_queue_work(&conn->trans->local->acceptor);
602 goto done;
603 }
604
605 _debug("dead call");
606 if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) { 576 if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) {
607 skb->priority = RX_CALL_DEAD; 577 skb->priority = RX_CALL_DEAD;
608 rxrpc_reject_packet(conn->trans->local, skb); 578 rxrpc_reject_packet(call->conn->trans->local, skb);
609 } 579 goto unlock;
610 goto done;
611
612 /* resend last packet of a completed call
613 * - client calls may have been aborted or ACK'd
614 * - server calls may have been aborted
615 */
616found_completed_call:
617 _debug("completed call");
618
619 if (atomic_read(&call->usage) == 0)
620 goto dead_call;
621
622 /* synchronise any state changes */
623 read_lock(&call->state_lock);
624 ASSERTIFCMP(call->state != RXRPC_CALL_CLIENT_FINAL_ACK,
625 call->state, >=, RXRPC_CALL_COMPLETE);
626
627 if (call->state == RXRPC_CALL_LOCALLY_ABORTED ||
628 call->state == RXRPC_CALL_REMOTELY_ABORTED ||
629 call->state == RXRPC_CALL_DEAD) {
630 read_unlock(&call->state_lock);
631 goto dead_call;
632 } 580 }
633
634 if (call->conn->in_clientflag) {
635 read_unlock(&call->state_lock);
636 goto dead_call; /* complete server call */
637 }
638
639 _debug("final ack again");
640 rxrpc_get_call(call);
641 set_bit(RXRPC_CALL_ACK_FINAL, &call->events);
642 rxrpc_queue_call(call);
643
644free_unlock: 581free_unlock:
645 read_unlock(&call->state_lock);
646 read_unlock_bh(&conn->lock);
647 rxrpc_free_skb(skb); 582 rxrpc_free_skb(skb);
583unlock:
584 read_unlock(&call->state_lock);
648done: 585done:
649 _leave(""); 586 _leave("");
650} 587}
@@ -663,17 +600,42 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
663 rxrpc_queue_conn(conn); 600 rxrpc_queue_conn(conn);
664} 601}
665 602
603static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
604 struct sk_buff *skb,
605 struct rxrpc_skb_priv *sp)
606{
607 struct rxrpc_peer *peer;
608 struct rxrpc_transport *trans;
609 struct rxrpc_connection *conn;
610
611 peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr,
612 udp_hdr(skb)->source);
613 if (IS_ERR(peer))
614 goto cant_find_conn;
615
616 trans = rxrpc_find_transport(local, peer);
617 rxrpc_put_peer(peer);
618 if (!trans)
619 goto cant_find_conn;
620
621 conn = rxrpc_find_connection(trans, &sp->hdr);
622 rxrpc_put_transport(trans);
623 if (!conn)
624 goto cant_find_conn;
625
626 return conn;
627cant_find_conn:
628 return NULL;
629}
630
666/* 631/*
667 * handle data received on the local endpoint 632 * handle data received on the local endpoint
668 * - may be called in interrupt context 633 * - may be called in interrupt context
669 */ 634 */
670void rxrpc_data_ready(struct sock *sk, int count) 635void rxrpc_data_ready(struct sock *sk, int count)
671{ 636{
672 struct rxrpc_connection *conn;
673 struct rxrpc_transport *trans;
674 struct rxrpc_skb_priv *sp; 637 struct rxrpc_skb_priv *sp;
675 struct rxrpc_local *local; 638 struct rxrpc_local *local;
676 struct rxrpc_peer *peer;
677 struct sk_buff *skb; 639 struct sk_buff *skb;
678 int ret; 640 int ret;
679 641
@@ -748,27 +710,34 @@ void rxrpc_data_ready(struct sock *sk, int count)
748 (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) 710 (sp->hdr.callNumber == 0 || sp->hdr.seq == 0))
749 goto bad_message; 711 goto bad_message;
750 712
751 peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr, udp_hdr(skb)->source); 713 if (sp->hdr.callNumber == 0) {
752 if (IS_ERR(peer)) 714 /* This is a connection-level packet. These should be
753 goto cant_route_call; 715 * fairly rare, so the extra overhead of looking them up the
754 716 * old-fashioned way doesn't really hurt */
755 trans = rxrpc_find_transport(local, peer); 717 struct rxrpc_connection *conn;
756 rxrpc_put_peer(peer);
757 if (!trans)
758 goto cant_route_call;
759
760 conn = rxrpc_find_connection(trans, &sp->hdr);
761 rxrpc_put_transport(trans);
762 if (!conn)
763 goto cant_route_call;
764 718
765 _debug("CONN %p {%d}", conn, conn->debug_id); 719 conn = rxrpc_conn_from_local(local, skb, sp);
720 if (!conn)
721 goto cant_route_call;
766 722
767 if (sp->hdr.callNumber == 0) 723 _debug("CONN %p {%d}", conn, conn->debug_id);
768 rxrpc_post_packet_to_conn(conn, skb); 724 rxrpc_post_packet_to_conn(conn, skb);
769 else 725 rxrpc_put_connection(conn);
770 rxrpc_post_packet_to_call(conn, skb); 726 } else {
771 rxrpc_put_connection(conn); 727 struct rxrpc_call *call;
728 u8 in_clientflag = 0;
729
730 if (sp->hdr.flags & RXRPC_CLIENT_INITIATED)
731 in_clientflag = RXRPC_CLIENT_INITIATED;
732 call = rxrpc_find_call_hash(in_clientflag, sp->hdr.cid,
733 sp->hdr.callNumber, sp->hdr.epoch,
734 sp->hdr.serviceId, local, AF_INET,
735 (u8 *)&ip_hdr(skb)->saddr);
736 if (call)
737 rxrpc_post_packet_to_call(call, skb);
738 else
739 goto cant_route_call;
740 }
772 rxrpc_put_local(local); 741 rxrpc_put_local(local);
773 return; 742 return;
774 743
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 1ecd070e9149..c831d44b0841 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -396,9 +396,20 @@ struct rxrpc_call {
396#define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG) 396#define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG)
397 unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1]; 397 unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1];
398 398
399 struct hlist_node hash_node;
400 unsigned long hash_key; /* Full hash key */
401 u8 in_clientflag; /* Copy of conn->in_clientflag for hashing */
402 struct rxrpc_local *local; /* Local endpoint. Used for hashing. */
403 sa_family_t proto; /* Frame protocol */
399 /* the following should all be in net order */ 404 /* the following should all be in net order */
400 __be32 cid; /* connection ID + channel index */ 405 __be32 cid; /* connection ID + channel index */
401 __be32 call_id; /* call ID on connection */ 406 __be32 call_id; /* call ID on connection */
407 __be32 epoch; /* epoch of this connection */
408 __be16 service_id; /* service ID */
409 union { /* Peer IP address for hashing */
410 __be32 ipv4_addr;
411 __u8 ipv6_addr[16]; /* Anticipates eventual IPv6 support */
412 } peer_ip;
402}; 413};
403 414
404/* 415/*
@@ -453,6 +464,8 @@ extern struct kmem_cache *rxrpc_call_jar;
453extern struct list_head rxrpc_calls; 464extern struct list_head rxrpc_calls;
454extern rwlock_t rxrpc_call_lock; 465extern rwlock_t rxrpc_call_lock;
455 466
467struct rxrpc_call *rxrpc_find_call_hash(u8, __be32, __be32, __be32,
468 __be16, void *, sa_family_t, const u8 *);
456struct rxrpc_call *rxrpc_get_client_call(struct rxrpc_sock *, 469struct rxrpc_call *rxrpc_get_client_call(struct rxrpc_sock *,
457 struct rxrpc_transport *, 470 struct rxrpc_transport *,
458 struct rxrpc_conn_bundle *, 471 struct rxrpc_conn_bundle *,