xref: /openbmc/linux/net/rxrpc/io_thread.c (revision af094824)
196b2d69bSDavid Howells // SPDX-License-Identifier: GPL-2.0-or-later
296b2d69bSDavid Howells /* RxRPC packet reception
396b2d69bSDavid Howells  *
4a275da62SDavid Howells  * Copyright (C) 2007, 2016, 2022 Red Hat, Inc. All Rights Reserved.
596b2d69bSDavid Howells  * Written by David Howells (dhowells@redhat.com)
696b2d69bSDavid Howells  */
796b2d69bSDavid Howells 
896b2d69bSDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
996b2d69bSDavid Howells 
1096b2d69bSDavid Howells #include "ar-internal.h"
1196b2d69bSDavid Howells 
125e6ef4f1SDavid Howells static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
135e6ef4f1SDavid Howells 				      struct sockaddr_rxrpc *peer_srx,
145e6ef4f1SDavid Howells 				      struct sk_buff *skb);
155e6ef4f1SDavid Howells 
1696b2d69bSDavid Howells /*
17446b3e14SDavid Howells  * handle data received on the local endpoint
18446b3e14SDavid Howells  * - may be called in interrupt context
19446b3e14SDavid Howells  *
20446b3e14SDavid Howells  * [!] Note that as this is called from the encap_rcv hook, the socket is not
21446b3e14SDavid Howells  * held locked by the caller and nothing prevents sk_user_data on the UDP from
22446b3e14SDavid Howells  * being cleared in the middle of processing this function.
23446b3e14SDavid Howells  *
24446b3e14SDavid Howells  * Called with the RCU read lock held from the IP layer via UDP.
25446b3e14SDavid Howells  */
rxrpc_encap_rcv(struct sock * udp_sk,struct sk_buff * skb)26446b3e14SDavid Howells int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
27446b3e14SDavid Howells {
28*af094824SDavid Howells 	struct sk_buff_head *rx_queue;
29446b3e14SDavid Howells 	struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
30446b3e14SDavid Howells 
31446b3e14SDavid Howells 	if (unlikely(!local)) {
32446b3e14SDavid Howells 		kfree_skb(skb);
33446b3e14SDavid Howells 		return 0;
34446b3e14SDavid Howells 	}
35446b3e14SDavid Howells 	if (skb->tstamp == 0)
36446b3e14SDavid Howells 		skb->tstamp = ktime_get_real();
37446b3e14SDavid Howells 
38446b3e14SDavid Howells 	skb->mark = RXRPC_SKB_MARK_PACKET;
39446b3e14SDavid Howells 	rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
40*af094824SDavid Howells 	rx_queue = &local->rx_queue;
41*af094824SDavid Howells #ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
42*af094824SDavid Howells 	if (rxrpc_inject_rx_delay ||
43*af094824SDavid Howells 	    !skb_queue_empty(&local->rx_delay_queue)) {
44*af094824SDavid Howells 		skb->tstamp = ktime_add_ms(skb->tstamp, rxrpc_inject_rx_delay);
45*af094824SDavid Howells 		rx_queue = &local->rx_delay_queue;
46*af094824SDavid Howells 	}
47*af094824SDavid Howells #endif
48*af094824SDavid Howells 
49*af094824SDavid Howells 	skb_queue_tail(rx_queue, skb);
50446b3e14SDavid Howells 	rxrpc_wake_up_io_thread(local);
51446b3e14SDavid Howells 	return 0;
52446b3e14SDavid Howells }
53446b3e14SDavid Howells 
54446b3e14SDavid Howells /*
55ff734825SDavid Howells  * Handle an error received on the local endpoint.
56ff734825SDavid Howells  */
rxrpc_error_report(struct sock * sk)57ff734825SDavid Howells void rxrpc_error_report(struct sock *sk)
58ff734825SDavid Howells {
59ff734825SDavid Howells 	struct rxrpc_local *local;
60ff734825SDavid Howells 	struct sk_buff *skb;
61ff734825SDavid Howells 
62ff734825SDavid Howells 	rcu_read_lock();
63ff734825SDavid Howells 	local = rcu_dereference_sk_user_data(sk);
64ff734825SDavid Howells 	if (unlikely(!local)) {
65ff734825SDavid Howells 		rcu_read_unlock();
66ff734825SDavid Howells 		return;
67ff734825SDavid Howells 	}
68ff734825SDavid Howells 
69ff734825SDavid Howells 	while ((skb = skb_dequeue(&sk->sk_error_queue))) {
70ff734825SDavid Howells 		skb->mark = RXRPC_SKB_MARK_ERROR;
71ff734825SDavid Howells 		rxrpc_new_skb(skb, rxrpc_skb_new_error_report);
72ff734825SDavid Howells 		skb_queue_tail(&local->rx_queue, skb);
73ff734825SDavid Howells 	}
74ff734825SDavid Howells 
75ff734825SDavid Howells 	rxrpc_wake_up_io_thread(local);
76ff734825SDavid Howells 	rcu_read_unlock();
77ff734825SDavid Howells }
78ff734825SDavid Howells 
79ff734825SDavid Howells /*
8057af281eSDavid Howells  * Directly produce an abort from a packet.
8157af281eSDavid Howells  */
rxrpc_direct_abort(struct sk_buff * skb,enum rxrpc_abort_reason why,s32 abort_code,int err)8257af281eSDavid Howells bool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
8357af281eSDavid Howells 			s32 abort_code, int err)
8457af281eSDavid Howells {
8557af281eSDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
8657af281eSDavid Howells 
8757af281eSDavid Howells 	trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
8857af281eSDavid Howells 			  abort_code, err);
8957af281eSDavid Howells 	skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
9057af281eSDavid Howells 	skb->priority = abort_code;
9157af281eSDavid Howells 	return false;
9257af281eSDavid Howells }
9357af281eSDavid Howells 
rxrpc_bad_message(struct sk_buff * skb,enum rxrpc_abort_reason why)9457af281eSDavid Howells static bool rxrpc_bad_message(struct sk_buff *skb, enum rxrpc_abort_reason why)
9557af281eSDavid Howells {
9657af281eSDavid Howells 	return rxrpc_direct_abort(skb, why, RX_PROTOCOL_ERROR, -EBADMSG);
9757af281eSDavid Howells }
9857af281eSDavid Howells 
9957af281eSDavid Howells #define just_discard true
10057af281eSDavid Howells 
10157af281eSDavid Howells /*
1025e6ef4f1SDavid Howells  * Process event packets targeted at a local endpoint.
10396b2d69bSDavid Howells  */
rxrpc_input_version(struct rxrpc_local * local,struct sk_buff * skb)10457af281eSDavid Howells static bool rxrpc_input_version(struct rxrpc_local *local, struct sk_buff *skb)
10596b2d69bSDavid Howells {
1065e6ef4f1SDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
1075e6ef4f1SDavid Howells 	char v;
10896b2d69bSDavid Howells 
1095e6ef4f1SDavid Howells 	_enter("");
11096b2d69bSDavid Howells 
1115e6ef4f1SDavid Howells 	rxrpc_see_skb(skb, rxrpc_skb_see_version);
1125e6ef4f1SDavid Howells 	if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), &v, 1) >= 0) {
1135e6ef4f1SDavid Howells 		if (v == 0)
1145e6ef4f1SDavid Howells 			rxrpc_send_version_request(local, &sp->hdr, skb);
11596b2d69bSDavid Howells 	}
11657af281eSDavid Howells 
11757af281eSDavid Howells 	return true;
11896b2d69bSDavid Howells }
11996b2d69bSDavid Howells 
12096b2d69bSDavid Howells /*
12196b2d69bSDavid Howells  * Extract the wire header from a packet and translate the byte order.
12296b2d69bSDavid Howells  */
rxrpc_extract_header(struct rxrpc_skb_priv * sp,struct sk_buff * skb)12357af281eSDavid Howells static bool rxrpc_extract_header(struct rxrpc_skb_priv *sp,
12457af281eSDavid Howells 				 struct sk_buff *skb)
12596b2d69bSDavid Howells {
12696b2d69bSDavid Howells 	struct rxrpc_wire_header whdr;
12796b2d69bSDavid Howells 
12896b2d69bSDavid Howells 	/* dig out the RxRPC connection details */
12957af281eSDavid Howells 	if (skb_copy_bits(skb, 0, &whdr, sizeof(whdr)) < 0)
13057af281eSDavid Howells 		return rxrpc_bad_message(skb, rxrpc_badmsg_short_hdr);
13196b2d69bSDavid Howells 
13296b2d69bSDavid Howells 	memset(sp, 0, sizeof(*sp));
13396b2d69bSDavid Howells 	sp->hdr.epoch		= ntohl(whdr.epoch);
13496b2d69bSDavid Howells 	sp->hdr.cid		= ntohl(whdr.cid);
13596b2d69bSDavid Howells 	sp->hdr.callNumber	= ntohl(whdr.callNumber);
13696b2d69bSDavid Howells 	sp->hdr.seq		= ntohl(whdr.seq);
13796b2d69bSDavid Howells 	sp->hdr.serial		= ntohl(whdr.serial);
13896b2d69bSDavid Howells 	sp->hdr.flags		= whdr.flags;
13996b2d69bSDavid Howells 	sp->hdr.type		= whdr.type;
14096b2d69bSDavid Howells 	sp->hdr.userStatus	= whdr.userStatus;
14196b2d69bSDavid Howells 	sp->hdr.securityIndex	= whdr.securityIndex;
14296b2d69bSDavid Howells 	sp->hdr._rsvd		= ntohs(whdr._rsvd);
14396b2d69bSDavid Howells 	sp->hdr.serviceId	= ntohs(whdr.serviceId);
14457af281eSDavid Howells 	return true;
14596b2d69bSDavid Howells }
14696b2d69bSDavid Howells 
14796b2d69bSDavid Howells /*
14896b2d69bSDavid Howells  * Extract the abort code from an ABORT packet and stash it in skb->priority.
14996b2d69bSDavid Howells  */
rxrpc_extract_abort(struct sk_buff * skb)15096b2d69bSDavid Howells static bool rxrpc_extract_abort(struct sk_buff *skb)
15196b2d69bSDavid Howells {
15296b2d69bSDavid Howells 	__be32 wtmp;
15396b2d69bSDavid Howells 
15496b2d69bSDavid Howells 	if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
15596b2d69bSDavid Howells 			  &wtmp, sizeof(wtmp)) < 0)
15696b2d69bSDavid Howells 		return false;
15796b2d69bSDavid Howells 	skb->priority = ntohl(wtmp);
15896b2d69bSDavid Howells 	return true;
15996b2d69bSDavid Howells }
16096b2d69bSDavid Howells 
16196b2d69bSDavid Howells /*
162446b3e14SDavid Howells  * Process packets received on the local endpoint
16396b2d69bSDavid Howells  */
rxrpc_input_packet(struct rxrpc_local * local,struct sk_buff ** _skb)16457af281eSDavid Howells static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb)
16596b2d69bSDavid Howells {
16696b2d69bSDavid Howells 	struct rxrpc_connection *conn;
167393a2a20SDavid Howells 	struct sockaddr_rxrpc peer_srx;
16896b2d69bSDavid Howells 	struct rxrpc_skb_priv *sp;
16996b2d69bSDavid Howells 	struct rxrpc_peer *peer = NULL;
1702d1faf7aSDavid Howells 	struct sk_buff *skb = *_skb;
17157af281eSDavid Howells 	bool ret = false;
17296b2d69bSDavid Howells 
17396b2d69bSDavid Howells 	skb_pull(skb, sizeof(struct udphdr));
17496b2d69bSDavid Howells 
17596b2d69bSDavid Howells 	sp = rxrpc_skb(skb);
17696b2d69bSDavid Howells 
17796b2d69bSDavid Howells 	/* dig out the RxRPC connection details */
17857af281eSDavid Howells 	if (!rxrpc_extract_header(sp, skb))
17957af281eSDavid Howells 		return just_discard;
18096b2d69bSDavid Howells 
18196b2d69bSDavid Howells 	if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) {
18296b2d69bSDavid Howells 		static int lose;
18396b2d69bSDavid Howells 		if ((lose++ & 7) == 7) {
18496b2d69bSDavid Howells 			trace_rxrpc_rx_lose(sp);
18557af281eSDavid Howells 			return just_discard;
18696b2d69bSDavid Howells 		}
18796b2d69bSDavid Howells 	}
18896b2d69bSDavid Howells 
18996b2d69bSDavid Howells 	trace_rxrpc_rx_packet(sp);
19096b2d69bSDavid Howells 
19196b2d69bSDavid Howells 	switch (sp->hdr.type) {
19296b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_VERSION:
19396b2d69bSDavid Howells 		if (rxrpc_to_client(sp))
19457af281eSDavid Howells 			return just_discard;
19557af281eSDavid Howells 		return rxrpc_input_version(local, skb);
19696b2d69bSDavid Howells 
19796b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_BUSY:
19896b2d69bSDavid Howells 		if (rxrpc_to_server(sp))
19957af281eSDavid Howells 			return just_discard;
20096b2d69bSDavid Howells 		fallthrough;
20196b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_ACK:
20296b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_ACKALL:
20396b2d69bSDavid Howells 		if (sp->hdr.callNumber == 0)
20457af281eSDavid Howells 			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
20596b2d69bSDavid Howells 		break;
20696b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_ABORT:
20796b2d69bSDavid Howells 		if (!rxrpc_extract_abort(skb))
20857af281eSDavid Howells 			return just_discard; /* Just discard if malformed */
20996b2d69bSDavid Howells 		break;
21096b2d69bSDavid Howells 
21196b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_DATA:
21257af281eSDavid Howells 		if (sp->hdr.callNumber == 0)
21357af281eSDavid Howells 			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
21457af281eSDavid Howells 		if (sp->hdr.seq == 0)
21557af281eSDavid Howells 			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq);
21696b2d69bSDavid Howells 
21796b2d69bSDavid Howells 		/* Unshare the packet so that it can be modified for in-place
21896b2d69bSDavid Howells 		 * decryption.
21996b2d69bSDavid Howells 		 */
22096b2d69bSDavid Howells 		if (sp->hdr.securityIndex != 0) {
2212d1faf7aSDavid Howells 			skb = skb_unshare(skb, GFP_ATOMIC);
2222d1faf7aSDavid Howells 			if (!skb) {
2232d1faf7aSDavid Howells 				rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem);
2242d1faf7aSDavid Howells 				*_skb = NULL;
22557af281eSDavid Howells 				return just_discard;
22696b2d69bSDavid Howells 			}
22796b2d69bSDavid Howells 
2282d1faf7aSDavid Howells 			if (skb != *_skb) {
2292d1faf7aSDavid Howells 				rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare);
2302d1faf7aSDavid Howells 				*_skb = skb;
23196b2d69bSDavid Howells 				rxrpc_new_skb(skb, rxrpc_skb_new_unshared);
23296b2d69bSDavid Howells 				sp = rxrpc_skb(skb);
23396b2d69bSDavid Howells 			}
23496b2d69bSDavid Howells 		}
23596b2d69bSDavid Howells 		break;
23696b2d69bSDavid Howells 
23796b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_CHALLENGE:
23896b2d69bSDavid Howells 		if (rxrpc_to_server(sp))
23957af281eSDavid Howells 			return just_discard;
24096b2d69bSDavid Howells 		break;
24196b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_RESPONSE:
24296b2d69bSDavid Howells 		if (rxrpc_to_client(sp))
24357af281eSDavid Howells 			return just_discard;
24496b2d69bSDavid Howells 		break;
24596b2d69bSDavid Howells 
24696b2d69bSDavid Howells 		/* Packet types 9-11 should just be ignored. */
24796b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_PARAMS:
24896b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_10:
24996b2d69bSDavid Howells 	case RXRPC_PACKET_TYPE_11:
25057af281eSDavid Howells 		return just_discard;
25196b2d69bSDavid Howells 
25296b2d69bSDavid Howells 	default:
25357af281eSDavid Howells 		return rxrpc_bad_message(skb, rxrpc_badmsg_unsupported_packet);
25496b2d69bSDavid Howells 	}
25596b2d69bSDavid Howells 
25696b2d69bSDavid Howells 	if (sp->hdr.serviceId == 0)
25757af281eSDavid Howells 		return rxrpc_bad_message(skb, rxrpc_badmsg_zero_service);
25896b2d69bSDavid Howells 
259393a2a20SDavid Howells 	if (WARN_ON_ONCE(rxrpc_extract_addr_from_skb(&peer_srx, skb) < 0))
26057af281eSDavid Howells 		return just_discard; /* Unsupported address type. */
261393a2a20SDavid Howells 
262393a2a20SDavid Howells 	if (peer_srx.transport.family != local->srx.transport.family &&
263393a2a20SDavid Howells 	    (peer_srx.transport.family == AF_INET &&
264393a2a20SDavid Howells 	     local->srx.transport.family != AF_INET6)) {
265393a2a20SDavid Howells 		pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n",
266393a2a20SDavid Howells 				    peer_srx.transport.family,
267393a2a20SDavid Howells 				    local->srx.transport.family);
26857af281eSDavid Howells 		return just_discard; /* Wrong address type. */
269393a2a20SDavid Howells 	}
270393a2a20SDavid Howells 
2715e6ef4f1SDavid Howells 	if (rxrpc_to_client(sp)) {
2725e6ef4f1SDavid Howells 		rcu_read_lock();
2735e6ef4f1SDavid Howells 		conn = rxrpc_find_client_connection_rcu(local, &peer_srx, skb);
2745e6ef4f1SDavid Howells 		conn = rxrpc_get_connection_maybe(conn, rxrpc_conn_get_call_input);
2755e6ef4f1SDavid Howells 		rcu_read_unlock();
27657af281eSDavid Howells 		if (!conn)
27757af281eSDavid Howells 			return rxrpc_protocol_error(skb, rxrpc_eproto_no_client_conn);
2785e6ef4f1SDavid Howells 
2795e6ef4f1SDavid Howells 		ret = rxrpc_input_packet_on_conn(conn, &peer_srx, skb);
2805e6ef4f1SDavid Howells 		rxrpc_put_connection(conn, rxrpc_conn_put_call_input);
2815e6ef4f1SDavid Howells 		return ret;
2825e6ef4f1SDavid Howells 	}
2835e6ef4f1SDavid Howells 
2845e6ef4f1SDavid Howells 	/* We need to look up service connections by the full protocol
2855e6ef4f1SDavid Howells 	 * parameter set.  We look up the peer first as an intermediate step
2865e6ef4f1SDavid Howells 	 * and then the connection from the peer's tree.
2875e6ef4f1SDavid Howells 	 */
288cd21effbSDavid Howells 	rcu_read_lock();
289cd21effbSDavid Howells 
2905e6ef4f1SDavid Howells 	peer = rxrpc_lookup_peer_rcu(local, &peer_srx);
2915e6ef4f1SDavid Howells 	if (!peer) {
292cd21effbSDavid Howells 		rcu_read_unlock();
2935e6ef4f1SDavid Howells 		return rxrpc_new_incoming_call(local, NULL, NULL, &peer_srx, skb);
29496b2d69bSDavid Howells 	}
29596b2d69bSDavid Howells 
2965e6ef4f1SDavid Howells 	conn = rxrpc_find_service_conn_rcu(peer, skb);
2975e6ef4f1SDavid Howells 	conn = rxrpc_get_connection_maybe(conn, rxrpc_conn_get_call_input);
29896b2d69bSDavid Howells 	if (conn) {
2995e6ef4f1SDavid Howells 		rcu_read_unlock();
3005e6ef4f1SDavid Howells 		ret = rxrpc_input_packet_on_conn(conn, &peer_srx, skb);
3015e6ef4f1SDavid Howells 		rxrpc_put_connection(conn, rxrpc_conn_put_call_input);
3025e6ef4f1SDavid Howells 		return ret;
3035e6ef4f1SDavid Howells 	}
3045e6ef4f1SDavid Howells 
3055e6ef4f1SDavid Howells 	peer = rxrpc_get_peer_maybe(peer, rxrpc_peer_get_input);
3065e6ef4f1SDavid Howells 	rcu_read_unlock();
3075e6ef4f1SDavid Howells 
3085e6ef4f1SDavid Howells 	ret = rxrpc_new_incoming_call(local, peer, NULL, &peer_srx, skb);
3095e6ef4f1SDavid Howells 	rxrpc_put_peer(peer, rxrpc_peer_put_input);
31057af281eSDavid Howells 	return ret;
3115e6ef4f1SDavid Howells }
3125e6ef4f1SDavid Howells 
3135e6ef4f1SDavid Howells /*
3145e6ef4f1SDavid Howells  * Deal with a packet that's associated with an extant connection.
3155e6ef4f1SDavid Howells  */
rxrpc_input_packet_on_conn(struct rxrpc_connection * conn,struct sockaddr_rxrpc * peer_srx,struct sk_buff * skb)3165e6ef4f1SDavid Howells static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
3175e6ef4f1SDavid Howells 				      struct sockaddr_rxrpc *peer_srx,
3185e6ef4f1SDavid Howells 				      struct sk_buff *skb)
3195e6ef4f1SDavid Howells {
3205e6ef4f1SDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
3215e6ef4f1SDavid Howells 	struct rxrpc_channel *chan;
3225e6ef4f1SDavid Howells 	struct rxrpc_call *call = NULL;
3235e6ef4f1SDavid Howells 	unsigned int channel;
32457af281eSDavid Howells 	bool ret;
3255e6ef4f1SDavid Howells 
32696b2d69bSDavid Howells 	if (sp->hdr.securityIndex != conn->security_ix)
32757af281eSDavid Howells 		return rxrpc_direct_abort(skb, rxrpc_eproto_wrong_security,
32857af281eSDavid Howells 					  RXKADINCONSISTENCY, -EBADMSG);
32996b2d69bSDavid Howells 
33096b2d69bSDavid Howells 	if (sp->hdr.serviceId != conn->service_id) {
33196b2d69bSDavid Howells 		int old_id;
33296b2d69bSDavid Howells 
33396b2d69bSDavid Howells 		if (!test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags))
33457af281eSDavid Howells 			return rxrpc_protocol_error(skb, rxrpc_eproto_reupgrade);
33557af281eSDavid Howells 
33696b2d69bSDavid Howells 		old_id = cmpxchg(&conn->service_id, conn->orig_service_id,
33796b2d69bSDavid Howells 				 sp->hdr.serviceId);
33896b2d69bSDavid Howells 		if (old_id != conn->orig_service_id &&
33996b2d69bSDavid Howells 		    old_id != sp->hdr.serviceId)
34057af281eSDavid Howells 			return rxrpc_protocol_error(skb, rxrpc_eproto_bad_upgrade);
34196b2d69bSDavid Howells 	}
34296b2d69bSDavid Howells 
3435e6ef4f1SDavid Howells 	if (after(sp->hdr.serial, conn->hi_serial))
34496b2d69bSDavid Howells 		conn->hi_serial = sp->hdr.serial;
34596b2d69bSDavid Howells 
3465e6ef4f1SDavid Howells 	/* It's a connection-level packet if the call number is 0. */
3475e6ef4f1SDavid Howells 	if (sp->hdr.callNumber == 0)
3485e6ef4f1SDavid Howells 		return rxrpc_input_conn_packet(conn, skb);
3495e6ef4f1SDavid Howells 
35096b2d69bSDavid Howells 	/* Call-bound packets are routed by connection channel. */
35196b2d69bSDavid Howells 	channel = sp->hdr.cid & RXRPC_CHANNELMASK;
35296b2d69bSDavid Howells 	chan = &conn->channels[channel];
35396b2d69bSDavid Howells 
35496b2d69bSDavid Howells 	/* Ignore really old calls */
3555e6ef4f1SDavid Howells 	if (sp->hdr.callNumber < chan->last_call)
35657af281eSDavid Howells 		return just_discard;
35796b2d69bSDavid Howells 
35896b2d69bSDavid Howells 	if (sp->hdr.callNumber == chan->last_call) {
35996b2d69bSDavid Howells 		if (chan->call ||
3605e6ef4f1SDavid Howells 		    sp->hdr.type == RXRPC_PACKET_TYPE_ABORT)
36157af281eSDavid Howells 			return just_discard;
36296b2d69bSDavid Howells 
3635e6ef4f1SDavid Howells 		/* For the previous service call, if completed successfully, we
3645e6ef4f1SDavid Howells 		 * discard all further packets.
36596b2d69bSDavid Howells 		 */
36696b2d69bSDavid Howells 		if (rxrpc_conn_is_service(conn) &&
3675e6ef4f1SDavid Howells 		    chan->last_type == RXRPC_PACKET_TYPE_ACK)
36857af281eSDavid Howells 			return just_discard;
36996b2d69bSDavid Howells 
3705e6ef4f1SDavid Howells 		/* But otherwise we need to retransmit the final packet from
3715e6ef4f1SDavid Howells 		 * data cached in the connection record.
37296b2d69bSDavid Howells 		 */
37396b2d69bSDavid Howells 		if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA)
37496b2d69bSDavid Howells 			trace_rxrpc_rx_data(chan->call_debug_id,
37596b2d69bSDavid Howells 					    sp->hdr.seq,
37696b2d69bSDavid Howells 					    sp->hdr.serial,
37796b2d69bSDavid Howells 					    sp->hdr.flags);
37830df927bSDavid Howells 		rxrpc_conn_retransmit_call(conn, skb, channel);
37957af281eSDavid Howells 		return just_discard;
38096b2d69bSDavid Howells 	}
38196b2d69bSDavid Howells 
3829d35d880SDavid Howells 	call = rxrpc_try_get_call(chan->call, rxrpc_call_get_input);
38396b2d69bSDavid Howells 
38496b2d69bSDavid Howells 	if (sp->hdr.callNumber > chan->call_id) {
385cd21effbSDavid Howells 		if (rxrpc_to_client(sp)) {
3865e6ef4f1SDavid Howells 			rxrpc_put_call(call, rxrpc_call_put_input);
38757af281eSDavid Howells 			return rxrpc_protocol_error(skb,
38857af281eSDavid Howells 						    rxrpc_eproto_unexpected_implicit_end);
389cd21effbSDavid Howells 		}
39096b2d69bSDavid Howells 
39196b2d69bSDavid Howells 		if (call) {
3925e6ef4f1SDavid Howells 			rxrpc_implicit_end_call(call, skb);
3935e6ef4f1SDavid Howells 			rxrpc_put_call(call, rxrpc_call_put_input);
3945e6ef4f1SDavid Howells 			call = NULL;
39596b2d69bSDavid Howells 		}
39696b2d69bSDavid Howells 	}
39796b2d69bSDavid Howells 
398cd21effbSDavid Howells 	if (!call) {
3995e6ef4f1SDavid Howells 		if (rxrpc_to_client(sp))
40057af281eSDavid Howells 			return rxrpc_protocol_error(skb, rxrpc_eproto_no_client_call);
40157af281eSDavid Howells 		return rxrpc_new_incoming_call(conn->local, conn->peer, conn,
40257af281eSDavid Howells 					       peer_srx, skb);
40396b2d69bSDavid Howells 	}
404cd21effbSDavid Howells 
40557af281eSDavid Howells 	ret = rxrpc_input_call_event(call, skb);
406cd21effbSDavid Howells 	rxrpc_put_call(call, rxrpc_call_put_input);
40757af281eSDavid Howells 	return ret;
40896b2d69bSDavid Howells }
409a275da62SDavid Howells 
410a275da62SDavid Howells /*
411a275da62SDavid Howells  * I/O and event handling thread.
412a275da62SDavid Howells  */
rxrpc_io_thread(void * data)413a275da62SDavid Howells int rxrpc_io_thread(void *data)
414a275da62SDavid Howells {
415f2cce89aSDavid Howells 	struct rxrpc_connection *conn;
416a275da62SDavid Howells 	struct sk_buff_head rx_queue;
417a275da62SDavid Howells 	struct rxrpc_local *local = data;
41815f661dcSDavid Howells 	struct rxrpc_call *call;
419a275da62SDavid Howells 	struct sk_buff *skb;
420*af094824SDavid Howells #ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
421*af094824SDavid Howells 	ktime_t now;
422*af094824SDavid Howells #endif
423743d1768SDavid Howells 	bool should_stop;
424a275da62SDavid Howells 
4258fbcc833SDavid Howells 	complete(&local->io_thread_ready);
4268fbcc833SDavid Howells 
427a275da62SDavid Howells 	skb_queue_head_init(&rx_queue);
428a275da62SDavid Howells 
429a275da62SDavid Howells 	set_user_nice(current, MIN_NICE);
430a275da62SDavid Howells 
431a275da62SDavid Howells 	for (;;) {
432a275da62SDavid Howells 		rxrpc_inc_stat(local->rxnet, stat_io_loop);
433a275da62SDavid Howells 
434f2cce89aSDavid Howells 		/* Deal with connections that want immediate attention. */
435f2cce89aSDavid Howells 		conn = list_first_entry_or_null(&local->conn_attend_q,
436f2cce89aSDavid Howells 						struct rxrpc_connection,
437f2cce89aSDavid Howells 						attend_link);
438f2cce89aSDavid Howells 		if (conn) {
439f2cce89aSDavid Howells 			spin_lock_bh(&local->lock);
440f2cce89aSDavid Howells 			list_del_init(&conn->attend_link);
441f2cce89aSDavid Howells 			spin_unlock_bh(&local->lock);
442f2cce89aSDavid Howells 
443f2cce89aSDavid Howells 			rxrpc_input_conn_event(conn, NULL);
444f2cce89aSDavid Howells 			rxrpc_put_connection(conn, rxrpc_conn_put_poke);
445f2cce89aSDavid Howells 			continue;
446f2cce89aSDavid Howells 		}
447f2cce89aSDavid Howells 
4480d6bf319SDavid Howells 		if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
4490d6bf319SDavid Howells 				       &local->client_conn_flags))
4500d6bf319SDavid Howells 			rxrpc_discard_expired_client_conns(local);
4510d6bf319SDavid Howells 
45215f661dcSDavid Howells 		/* Deal with calls that want immediate attention. */
45315f661dcSDavid Howells 		if ((call = list_first_entry_or_null(&local->call_attend_q,
45415f661dcSDavid Howells 						     struct rxrpc_call,
45515f661dcSDavid Howells 						     attend_link))) {
45615f661dcSDavid Howells 			spin_lock_bh(&local->lock);
45715f661dcSDavid Howells 			list_del_init(&call->attend_link);
45815f661dcSDavid Howells 			spin_unlock_bh(&local->lock);
45915f661dcSDavid Howells 
46015f661dcSDavid Howells 			trace_rxrpc_call_poked(call);
46115f661dcSDavid Howells 			rxrpc_input_call_event(call, NULL);
46215f661dcSDavid Howells 			rxrpc_put_call(call, rxrpc_call_put_poke);
46315f661dcSDavid Howells 			continue;
46415f661dcSDavid Howells 		}
46515f661dcSDavid Howells 
4669d35d880SDavid Howells 		if (!list_empty(&local->new_client_calls))
4679d35d880SDavid Howells 			rxrpc_connect_client_calls(local);
4689d35d880SDavid Howells 
469a275da62SDavid Howells 		/* Process received packets and errors. */
470a275da62SDavid Howells 		if ((skb = __skb_dequeue(&rx_queue))) {
4712953d3b8SDavid Howells 			struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
472446b3e14SDavid Howells 			switch (skb->mark) {
473446b3e14SDavid Howells 			case RXRPC_SKB_MARK_PACKET:
4742d1faf7aSDavid Howells 				skb->priority = 0;
47557af281eSDavid Howells 				if (!rxrpc_input_packet(local, &skb))
47657af281eSDavid Howells 					rxrpc_reject_packet(local, skb);
4772d1faf7aSDavid Howells 				trace_rxrpc_rx_done(skb->mark, skb->priority);
4782d1faf7aSDavid Howells 				rxrpc_free_skb(skb, rxrpc_skb_put_input);
479446b3e14SDavid Howells 				break;
480ff734825SDavid Howells 			case RXRPC_SKB_MARK_ERROR:
481ff734825SDavid Howells 				rxrpc_input_error(local, skb);
482ff734825SDavid Howells 				rxrpc_free_skb(skb, rxrpc_skb_put_error_report);
483ff734825SDavid Howells 				break;
4842953d3b8SDavid Howells 			case RXRPC_SKB_MARK_SERVICE_CONN_SECURED:
4852953d3b8SDavid Howells 				rxrpc_input_conn_event(sp->conn, skb);
4862953d3b8SDavid Howells 				rxrpc_put_connection(sp->conn, rxrpc_conn_put_poke);
4872953d3b8SDavid Howells 				rxrpc_free_skb(skb, rxrpc_skb_put_conn_secured);
488f2cce89aSDavid Howells 				break;
489446b3e14SDavid Howells 			default:
490446b3e14SDavid Howells 				WARN_ON_ONCE(1);
491446b3e14SDavid Howells 				rxrpc_free_skb(skb, rxrpc_skb_put_unknown);
492446b3e14SDavid Howells 				break;
493446b3e14SDavid Howells 			}
494a275da62SDavid Howells 			continue;
495a275da62SDavid Howells 		}
496a275da62SDavid Howells 
497*af094824SDavid Howells 		/* Inject a delay into packets if requested. */
498*af094824SDavid Howells #ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
499*af094824SDavid Howells 		now = ktime_get_real();
500*af094824SDavid Howells 		while ((skb = skb_peek(&local->rx_delay_queue))) {
501*af094824SDavid Howells 			if (ktime_before(now, skb->tstamp))
502*af094824SDavid Howells 				break;
503*af094824SDavid Howells 			skb = skb_dequeue(&local->rx_delay_queue);
504*af094824SDavid Howells 			skb_queue_tail(&local->rx_queue, skb);
505*af094824SDavid Howells 		}
506*af094824SDavid Howells #endif
507*af094824SDavid Howells 
508a275da62SDavid Howells 		if (!skb_queue_empty(&local->rx_queue)) {
509a275da62SDavid Howells 			spin_lock_irq(&local->rx_queue.lock);
510a275da62SDavid Howells 			skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
511a275da62SDavid Howells 			spin_unlock_irq(&local->rx_queue.lock);
512a275da62SDavid Howells 			continue;
513a275da62SDavid Howells 		}
514a275da62SDavid Howells 
515a275da62SDavid Howells 		set_current_state(TASK_INTERRUPTIBLE);
516743d1768SDavid Howells 		should_stop = kthread_should_stop();
51715f661dcSDavid Howells 		if (!skb_queue_empty(&local->rx_queue) ||
518f2cce89aSDavid Howells 		    !list_empty(&local->call_attend_q) ||
5199d35d880SDavid Howells 		    !list_empty(&local->conn_attend_q) ||
5209d35d880SDavid Howells 		    !list_empty(&local->new_client_calls) ||
5219d35d880SDavid Howells 		    test_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
5229d35d880SDavid Howells 			     &local->client_conn_flags)) {
523a275da62SDavid Howells 			__set_current_state(TASK_RUNNING);
524a275da62SDavid Howells 			continue;
525a275da62SDavid Howells 		}
526a275da62SDavid Howells 
527743d1768SDavid Howells 		if (should_stop)
528a275da62SDavid Howells 			break;
529*af094824SDavid Howells 
530*af094824SDavid Howells #ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
531*af094824SDavid Howells 		skb = skb_peek(&local->rx_delay_queue);
532*af094824SDavid Howells 		if (skb) {
533*af094824SDavid Howells 			unsigned long timeout;
534*af094824SDavid Howells 			ktime_t tstamp = skb->tstamp;
535*af094824SDavid Howells 			ktime_t now = ktime_get_real();
536*af094824SDavid Howells 			s64 delay_ns = ktime_to_ns(ktime_sub(tstamp, now));
537*af094824SDavid Howells 
538*af094824SDavid Howells 			if (delay_ns <= 0) {
539*af094824SDavid Howells 				__set_current_state(TASK_RUNNING);
540*af094824SDavid Howells 				continue;
541*af094824SDavid Howells 			}
542*af094824SDavid Howells 
543*af094824SDavid Howells 			timeout = nsecs_to_jiffies(delay_ns);
544*af094824SDavid Howells 			timeout = max(timeout, 1UL);
545*af094824SDavid Howells 			schedule_timeout(timeout);
546*af094824SDavid Howells 			__set_current_state(TASK_RUNNING);
547*af094824SDavid Howells 			continue;
548*af094824SDavid Howells 		}
549*af094824SDavid Howells #endif
550*af094824SDavid Howells 
551a275da62SDavid Howells 		schedule();
552a275da62SDavid Howells 	}
553a275da62SDavid Howells 
554a275da62SDavid Howells 	__set_current_state(TASK_RUNNING);
555a275da62SDavid Howells 	rxrpc_see_local(local, rxrpc_local_stop);
556a275da62SDavid Howells 	rxrpc_destroy_local(local);
557a275da62SDavid Howells 	local->io_thread = NULL;
558a275da62SDavid Howells 	rxrpc_see_local(local, rxrpc_local_stopped);
559a275da62SDavid Howells 	return 0;
560a275da62SDavid Howells }
561