|
@@ -25,8 +25,6 @@
|
|
|
#include <net/net_namespace.h>
|
|
|
#include "ar-internal.h"
|
|
|
|
|
|
-unsigned long rxrpc_ack_timeout = 1;
|
|
|
-
|
|
|
const char *rxrpc_pkts[] = {
|
|
|
"?00",
|
|
|
"DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG",
|
|
@@ -349,8 +347,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb)
|
|
|
* it */
|
|
|
if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
|
|
|
_proto("ACK Requested on %%%u", serial);
|
|
|
- rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED, sp->hdr.serial,
|
|
|
- !(sp->hdr.flags & RXRPC_MORE_PACKETS));
|
|
|
+ rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED, sp->hdr.serial, false);
|
|
|
}
|
|
|
|
|
|
switch (sp->hdr.type) {
|
|
@@ -526,36 +523,38 @@ protocol_error:
|
|
|
* post an incoming packet to the appropriate call/socket to deal with
|
|
|
* - must get rid of the sk_buff, either by freeing it or by queuing it
|
|
|
*/
|
|
|
-static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn,
|
|
|
+static void rxrpc_post_packet_to_call(struct rxrpc_call *call,
|
|
|
struct sk_buff *skb)
|
|
|
{
|
|
|
struct rxrpc_skb_priv *sp;
|
|
|
- struct rxrpc_call *call;
|
|
|
- struct rb_node *p;
|
|
|
- __be32 call_id;
|
|
|
-
|
|
|
- _enter("%p,%p", conn, skb);
|
|
|
|
|
|
- read_lock_bh(&conn->lock);
|
|
|
+ _enter("%p,%p", call, skb);
|
|
|
|
|
|
sp = rxrpc_skb(skb);
|
|
|
|
|
|
- /* look at extant calls by channel number first */
|
|
|
- call = conn->channels[ntohl(sp->hdr.cid) & RXRPC_CHANNELMASK];
|
|
|
- if (!call || call->call_id != sp->hdr.callNumber)
|
|
|
- goto call_not_extant;
|
|
|
-
|
|
|
_debug("extant call [%d]", call->state);
|
|
|
- ASSERTCMP(call->conn, ==, conn);
|
|
|
|
|
|
read_lock(&call->state_lock);
|
|
|
switch (call->state) {
|
|
|
case RXRPC_CALL_LOCALLY_ABORTED:
|
|
|
- if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events))
|
|
|
+ if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events)) {
|
|
|
rxrpc_queue_call(call);
|
|
|
+ goto free_unlock;
|
|
|
+ }
|
|
|
case RXRPC_CALL_REMOTELY_ABORTED:
|
|
|
case RXRPC_CALL_NETWORK_ERROR:
|
|
|
case RXRPC_CALL_DEAD:
|
|
|
+ goto dead_call;
|
|
|
+ case RXRPC_CALL_COMPLETE:
|
|
|
+ case RXRPC_CALL_CLIENT_FINAL_ACK:
|
|
|
+ /* complete server call */
|
|
|
+ if (call->conn->in_clientflag)
|
|
|
+ goto dead_call;
|
|
|
+ /* resend last packet of a completed call */
|
|
|
+ _debug("final ack again");
|
|
|
+ rxrpc_get_call(call);
|
|
|
+ set_bit(RXRPC_CALL_ACK_FINAL, &call->events);
|
|
|
+ rxrpc_queue_call(call);
|
|
|
goto free_unlock;
|
|
|
default:
|
|
|
break;
|
|
@@ -563,7 +562,6 @@ static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn,
|
|
|
|
|
|
read_unlock(&call->state_lock);
|
|
|
rxrpc_get_call(call);
|
|
|
- read_unlock_bh(&conn->lock);
|
|
|
|
|
|
if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
|
|
|
sp->hdr.flags & RXRPC_JUMBO_PACKET)
|
|
@@ -574,78 +572,16 @@ static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn,
|
|
|
rxrpc_put_call(call);
|
|
|
goto done;
|
|
|
|
|
|
-call_not_extant:
|
|
|
- /* search the completed calls in case what we're dealing with is
|
|
|
- * there */
|
|
|
- _debug("call not extant");
|
|
|
-
|
|
|
- call_id = sp->hdr.callNumber;
|
|
|
- p = conn->calls.rb_node;
|
|
|
- while (p) {
|
|
|
- call = rb_entry(p, struct rxrpc_call, conn_node);
|
|
|
-
|
|
|
- if (call_id < call->call_id)
|
|
|
- p = p->rb_left;
|
|
|
- else if (call_id > call->call_id)
|
|
|
- p = p->rb_right;
|
|
|
- else
|
|
|
- goto found_completed_call;
|
|
|
- }
|
|
|
-
|
|
|
dead_call:
|
|
|
- /* it's a either a really old call that we no longer remember or its a
|
|
|
- * new incoming call */
|
|
|
- read_unlock_bh(&conn->lock);
|
|
|
-
|
|
|
- if (sp->hdr.flags & RXRPC_CLIENT_INITIATED &&
|
|
|
- sp->hdr.seq == cpu_to_be32(1)) {
|
|
|
- _debug("incoming call");
|
|
|
- skb_queue_tail(&conn->trans->local->accept_queue, skb);
|
|
|
- rxrpc_queue_work(&conn->trans->local->acceptor);
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- _debug("dead call");
|
|
|
- skb->priority = RX_CALL_DEAD;
|
|
|
- rxrpc_reject_packet(conn->trans->local, skb);
|
|
|
- goto done;
|
|
|
-
|
|
|
- /* resend last packet of a completed call
|
|
|
- * - client calls may have been aborted or ACK'd
|
|
|
- * - server calls may have been aborted
|
|
|
- */
|
|
|
-found_completed_call:
|
|
|
- _debug("completed call");
|
|
|
-
|
|
|
- if (atomic_read(&call->usage) == 0)
|
|
|
- goto dead_call;
|
|
|
-
|
|
|
- /* synchronise any state changes */
|
|
|
- read_lock(&call->state_lock);
|
|
|
- ASSERTIFCMP(call->state != RXRPC_CALL_CLIENT_FINAL_ACK,
|
|
|
- call->state, >=, RXRPC_CALL_COMPLETE);
|
|
|
-
|
|
|
- if (call->state == RXRPC_CALL_LOCALLY_ABORTED ||
|
|
|
- call->state == RXRPC_CALL_REMOTELY_ABORTED ||
|
|
|
- call->state == RXRPC_CALL_DEAD) {
|
|
|
- read_unlock(&call->state_lock);
|
|
|
- goto dead_call;
|
|
|
- }
|
|
|
-
|
|
|
- if (call->conn->in_clientflag) {
|
|
|
- read_unlock(&call->state_lock);
|
|
|
- goto dead_call; /* complete server call */
|
|
|
+ if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) {
|
|
|
+ skb->priority = RX_CALL_DEAD;
|
|
|
+ rxrpc_reject_packet(call->conn->trans->local, skb);
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
-
|
|
|
- _debug("final ack again");
|
|
|
- rxrpc_get_call(call);
|
|
|
- set_bit(RXRPC_CALL_ACK_FINAL, &call->events);
|
|
|
- rxrpc_queue_call(call);
|
|
|
-
|
|
|
free_unlock:
|
|
|
- read_unlock(&call->state_lock);
|
|
|
- read_unlock_bh(&conn->lock);
|
|
|
rxrpc_free_skb(skb);
|
|
|
+unlock:
|
|
|
+ read_unlock(&call->state_lock);
|
|
|
done:
|
|
|
_leave("");
|
|
|
}
|
|
@@ -664,17 +600,42 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
|
|
|
rxrpc_queue_conn(conn);
|
|
|
}
|
|
|
|
|
|
+static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
|
|
|
+ struct sk_buff *skb,
|
|
|
+ struct rxrpc_skb_priv *sp)
|
|
|
+{
|
|
|
+ struct rxrpc_peer *peer;
|
|
|
+ struct rxrpc_transport *trans;
|
|
|
+ struct rxrpc_connection *conn;
|
|
|
+
|
|
|
+ peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr,
|
|
|
+ udp_hdr(skb)->source);
|
|
|
+ if (IS_ERR(peer))
|
|
|
+ goto cant_find_conn;
|
|
|
+
|
|
|
+ trans = rxrpc_find_transport(local, peer);
|
|
|
+ rxrpc_put_peer(peer);
|
|
|
+ if (!trans)
|
|
|
+ goto cant_find_conn;
|
|
|
+
|
|
|
+ conn = rxrpc_find_connection(trans, &sp->hdr);
|
|
|
+ rxrpc_put_transport(trans);
|
|
|
+ if (!conn)
|
|
|
+ goto cant_find_conn;
|
|
|
+
|
|
|
+ return conn;
|
|
|
+cant_find_conn:
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* handle data received on the local endpoint
|
|
|
* - may be called in interrupt context
|
|
|
*/
|
|
|
void rxrpc_data_ready(struct sock *sk, int count)
|
|
|
{
|
|
|
- struct rxrpc_connection *conn;
|
|
|
- struct rxrpc_transport *trans;
|
|
|
struct rxrpc_skb_priv *sp;
|
|
|
struct rxrpc_local *local;
|
|
|
- struct rxrpc_peer *peer;
|
|
|
struct sk_buff *skb;
|
|
|
int ret;
|
|
|
|
|
@@ -749,27 +710,34 @@ void rxrpc_data_ready(struct sock *sk, int count)
|
|
|
(sp->hdr.callNumber == 0 || sp->hdr.seq == 0))
|
|
|
goto bad_message;
|
|
|
|
|
|
- peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr, udp_hdr(skb)->source);
|
|
|
- if (IS_ERR(peer))
|
|
|
- goto cant_route_call;
|
|
|
+ if (sp->hdr.callNumber == 0) {
|
|
|
+ /* This is a connection-level packet. These should be
|
|
|
+ * fairly rare, so the extra overhead of looking them up the
|
|
|
+ * old-fashioned way doesn't really hurt */
|
|
|
+ struct rxrpc_connection *conn;
|
|
|
|
|
|
- trans = rxrpc_find_transport(local, peer);
|
|
|
- rxrpc_put_peer(peer);
|
|
|
- if (!trans)
|
|
|
- goto cant_route_call;
|
|
|
+ conn = rxrpc_conn_from_local(local, skb, sp);
|
|
|
+ if (!conn)
|
|
|
+ goto cant_route_call;
|
|
|
|
|
|
- conn = rxrpc_find_connection(trans, &sp->hdr);
|
|
|
- rxrpc_put_transport(trans);
|
|
|
- if (!conn)
|
|
|
- goto cant_route_call;
|
|
|
-
|
|
|
- _debug("CONN %p {%d}", conn, conn->debug_id);
|
|
|
-
|
|
|
- if (sp->hdr.callNumber == 0)
|
|
|
+ _debug("CONN %p {%d}", conn, conn->debug_id);
|
|
|
rxrpc_post_packet_to_conn(conn, skb);
|
|
|
- else
|
|
|
- rxrpc_post_packet_to_call(conn, skb);
|
|
|
- rxrpc_put_connection(conn);
|
|
|
+ rxrpc_put_connection(conn);
|
|
|
+ } else {
|
|
|
+ struct rxrpc_call *call;
|
|
|
+ u8 in_clientflag = 0;
|
|
|
+
|
|
|
+ if (sp->hdr.flags & RXRPC_CLIENT_INITIATED)
|
|
|
+ in_clientflag = RXRPC_CLIENT_INITIATED;
|
|
|
+ call = rxrpc_find_call_hash(in_clientflag, sp->hdr.cid,
|
|
|
+ sp->hdr.callNumber, sp->hdr.epoch,
|
|
|
+ sp->hdr.serviceId, local, AF_INET,
|
|
|
+ (u8 *)&ip_hdr(skb)->saddr);
|
|
|
+ if (call)
|
|
|
+ rxrpc_post_packet_to_call(call, skb);
|
|
|
+ else
|
|
|
+ goto cant_route_call;
|
|
|
+ }
|
|
|
rxrpc_put_local(local);
|
|
|
return;
|
|
|
|
|
@@ -790,8 +758,10 @@ cant_route_call:
|
|
|
skb->priority = RX_CALL_DEAD;
|
|
|
}
|
|
|
|
|
|
- _debug("reject");
|
|
|
- rxrpc_reject_packet(local, skb);
|
|
|
+ if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) {
|
|
|
+ _debug("reject type %d",sp->hdr.type);
|
|
|
+ rxrpc_reject_packet(local, skb);
|
|
|
+ }
|
|
|
rxrpc_put_local(local);
|
|
|
_leave(" [no call]");
|
|
|
return;
|