xref: /openbmc/linux/net/rxrpc/conn_event.c (revision 2953d3b8)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28c3e34a4SDavid Howells /* connection-level event handling
38c3e34a4SDavid Howells  *
48c3e34a4SDavid Howells  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
58c3e34a4SDavid Howells  * Written by David Howells (dhowells@redhat.com)
68c3e34a4SDavid Howells  */
78c3e34a4SDavid Howells 
88c3e34a4SDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c3e34a4SDavid Howells 
108c3e34a4SDavid Howells #include <linux/module.h>
118c3e34a4SDavid Howells #include <linux/net.h>
128c3e34a4SDavid Howells #include <linux/skbuff.h>
138c3e34a4SDavid Howells #include <linux/errqueue.h>
148c3e34a4SDavid Howells #include <net/sock.h>
158c3e34a4SDavid Howells #include <net/af_rxrpc.h>
168c3e34a4SDavid Howells #include <net/ip.h>
178c3e34a4SDavid Howells #include "ar-internal.h"
188c3e34a4SDavid Howells 
198c3e34a4SDavid Howells /*
20a00ce28bSDavid Howells  * Set the completion state on an aborted connection.
21a00ce28bSDavid Howells  */
22a00ce28bSDavid Howells static bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff *skb,
23a00ce28bSDavid Howells 				   s32 abort_code, int err,
24a00ce28bSDavid Howells 				   enum rxrpc_call_completion compl)
25a00ce28bSDavid Howells {
26a00ce28bSDavid Howells 	bool aborted = false;
27a00ce28bSDavid Howells 
28a00ce28bSDavid Howells 	if (conn->state != RXRPC_CONN_ABORTED) {
29a00ce28bSDavid Howells 		spin_lock(&conn->state_lock);
30a00ce28bSDavid Howells 		if (conn->state != RXRPC_CONN_ABORTED) {
31a00ce28bSDavid Howells 			conn->abort_code = abort_code;
32a00ce28bSDavid Howells 			conn->error	 = err;
33a00ce28bSDavid Howells 			conn->completion = compl;
34a00ce28bSDavid Howells 			/* Order the abort info before the state change. */
35a00ce28bSDavid Howells 			smp_store_release(&conn->state, RXRPC_CONN_ABORTED);
36a00ce28bSDavid Howells 			set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
37a00ce28bSDavid Howells 			set_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events);
38a00ce28bSDavid Howells 			aborted = true;
39a00ce28bSDavid Howells 		}
40a00ce28bSDavid Howells 		spin_unlock(&conn->state_lock);
41a00ce28bSDavid Howells 	}
42a00ce28bSDavid Howells 
43a00ce28bSDavid Howells 	return aborted;
44a00ce28bSDavid Howells }
45a00ce28bSDavid Howells 
46a00ce28bSDavid Howells /*
47a00ce28bSDavid Howells  * Mark a socket buffer to indicate that the connection it's on should be aborted.
48a00ce28bSDavid Howells  */
49a00ce28bSDavid Howells int rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb,
5057af281eSDavid Howells 		     s32 abort_code, int err, enum rxrpc_abort_reason why)
51a00ce28bSDavid Howells {
52a00ce28bSDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
53a00ce28bSDavid Howells 
54a00ce28bSDavid Howells 	if (rxrpc_set_conn_aborted(conn, skb, abort_code, err,
55a00ce28bSDavid Howells 				   RXRPC_CALL_LOCALLY_ABORTED)) {
56a00ce28bSDavid Howells 		trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber,
57a00ce28bSDavid Howells 				  sp->hdr.seq, abort_code, err);
58a00ce28bSDavid Howells 		rxrpc_poke_conn(conn, rxrpc_conn_get_poke_abort);
59a00ce28bSDavid Howells 	}
60a00ce28bSDavid Howells 	return -EPROTO;
61a00ce28bSDavid Howells }
62a00ce28bSDavid Howells 
63a00ce28bSDavid Howells /*
64a00ce28bSDavid Howells  * Mark a connection as being remotely aborted.
65a00ce28bSDavid Howells  */
66a00ce28bSDavid Howells static bool rxrpc_input_conn_abort(struct rxrpc_connection *conn,
67a00ce28bSDavid Howells 				   struct sk_buff *skb)
68a00ce28bSDavid Howells {
69a00ce28bSDavid Howells 	return rxrpc_set_conn_aborted(conn, skb, skb->priority, -ECONNABORTED,
70a00ce28bSDavid Howells 				      RXRPC_CALL_REMOTELY_ABORTED);
71a00ce28bSDavid Howells }
72a00ce28bSDavid Howells 
73a00ce28bSDavid Howells /*
7418bfeba5SDavid Howells  * Retransmit terminal ACK or ABORT of the previous call.
7518bfeba5SDavid Howells  */
7630df927bSDavid Howells void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
773136ef49SDavid Howells 				struct sk_buff *skb,
783136ef49SDavid Howells 				unsigned int channel)
7918bfeba5SDavid Howells {
803136ef49SDavid Howells 	struct rxrpc_skb_priv *sp = skb ? rxrpc_skb(skb) : NULL;
8118bfeba5SDavid Howells 	struct rxrpc_channel *chan;
8218bfeba5SDavid Howells 	struct msghdr msg;
835fc62f6aSDavid Howells 	struct kvec iov[3];
8418bfeba5SDavid Howells 	struct {
8518bfeba5SDavid Howells 		struct rxrpc_wire_header whdr;
8618bfeba5SDavid Howells 		union {
875fc62f6aSDavid Howells 			__be32 abort_code;
8818bfeba5SDavid Howells 			struct rxrpc_ackpacket ack;
8918bfeba5SDavid Howells 		};
9018bfeba5SDavid Howells 	} __attribute__((packed)) pkt;
915fc62f6aSDavid Howells 	struct rxrpc_ackinfo ack_info;
9218bfeba5SDavid Howells 	size_t len;
936b47fe1dSDavid Howells 	int ret, ioc;
945fc62f6aSDavid Howells 	u32 serial, mtu, call_id, padding;
9518bfeba5SDavid Howells 
9618bfeba5SDavid Howells 	_enter("%d", conn->debug_id);
9718bfeba5SDavid Howells 
983136ef49SDavid Howells 	chan = &conn->channels[channel];
9918bfeba5SDavid Howells 
10018bfeba5SDavid Howells 	/* If the last call got moved on whilst we were waiting to run, just
10118bfeba5SDavid Howells 	 * ignore this packet.
10218bfeba5SDavid Howells 	 */
10318bfeba5SDavid Howells 	call_id = READ_ONCE(chan->last_call);
10418bfeba5SDavid Howells 	/* Sync with __rxrpc_disconnect_call() */
10518bfeba5SDavid Howells 	smp_rmb();
1063136ef49SDavid Howells 	if (skb && call_id != sp->hdr.callNumber)
10718bfeba5SDavid Howells 		return;
10818bfeba5SDavid Howells 
1092cc80086SDavid Howells 	msg.msg_name	= &conn->peer->srx.transport;
1102cc80086SDavid Howells 	msg.msg_namelen	= conn->peer->srx.transport_len;
11118bfeba5SDavid Howells 	msg.msg_control	= NULL;
11218bfeba5SDavid Howells 	msg.msg_controllen = 0;
11318bfeba5SDavid Howells 	msg.msg_flags	= 0;
11418bfeba5SDavid Howells 
1155fc62f6aSDavid Howells 	iov[0].iov_base	= &pkt;
1165fc62f6aSDavid Howells 	iov[0].iov_len	= sizeof(pkt.whdr);
1175fc62f6aSDavid Howells 	iov[1].iov_base	= &padding;
1185fc62f6aSDavid Howells 	iov[1].iov_len	= 3;
1195fc62f6aSDavid Howells 	iov[2].iov_base	= &ack_info;
1205fc62f6aSDavid Howells 	iov[2].iov_len	= sizeof(ack_info);
1215fc62f6aSDavid Howells 
1223136ef49SDavid Howells 	pkt.whdr.epoch		= htonl(conn->proto.epoch);
123fb1967a6SDavid Howells 	pkt.whdr.cid		= htonl(conn->proto.cid | channel);
1243136ef49SDavid Howells 	pkt.whdr.callNumber	= htonl(call_id);
12518bfeba5SDavid Howells 	pkt.whdr.seq		= 0;
12618bfeba5SDavid Howells 	pkt.whdr.type		= chan->last_type;
12718bfeba5SDavid Howells 	pkt.whdr.flags		= conn->out_clientflag;
12818bfeba5SDavid Howells 	pkt.whdr.userStatus	= 0;
12918bfeba5SDavid Howells 	pkt.whdr.securityIndex	= conn->security_ix;
13018bfeba5SDavid Howells 	pkt.whdr._rsvd		= 0;
13168d6d1aeSDavid Howells 	pkt.whdr.serviceId	= htons(conn->service_id);
13218bfeba5SDavid Howells 
13318bfeba5SDavid Howells 	len = sizeof(pkt.whdr);
13418bfeba5SDavid Howells 	switch (chan->last_type) {
13518bfeba5SDavid Howells 	case RXRPC_PACKET_TYPE_ABORT:
1365fc62f6aSDavid Howells 		pkt.abort_code	= htonl(chan->last_abort);
1375fc62f6aSDavid Howells 		iov[0].iov_len += sizeof(pkt.abort_code);
1385fc62f6aSDavid Howells 		len += sizeof(pkt.abort_code);
1395fc62f6aSDavid Howells 		ioc = 1;
14018bfeba5SDavid Howells 		break;
14118bfeba5SDavid Howells 
14218bfeba5SDavid Howells 	case RXRPC_PACKET_TYPE_ACK:
1432cc80086SDavid Howells 		mtu = conn->peer->if_mtu;
1442cc80086SDavid Howells 		mtu -= conn->peer->hdrsize;
14518bfeba5SDavid Howells 		pkt.ack.bufferSpace	= 0;
1463136ef49SDavid Howells 		pkt.ack.maxSkew		= htons(skb ? skb->priority : 0);
1473136ef49SDavid Howells 		pkt.ack.firstPacket	= htonl(chan->last_seq + 1);
1483136ef49SDavid Howells 		pkt.ack.previousPacket	= htonl(chan->last_seq);
1493136ef49SDavid Howells 		pkt.ack.serial		= htonl(skb ? sp->hdr.serial : 0);
1503136ef49SDavid Howells 		pkt.ack.reason		= skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
15118bfeba5SDavid Howells 		pkt.ack.nAcks		= 0;
1525fc62f6aSDavid Howells 		ack_info.rxMTU		= htonl(rxrpc_rx_mtu);
1535fc62f6aSDavid Howells 		ack_info.maxMTU		= htonl(mtu);
1545fc62f6aSDavid Howells 		ack_info.rwind		= htonl(rxrpc_rx_window_size);
1555fc62f6aSDavid Howells 		ack_info.jumbo_max	= htonl(rxrpc_rx_jumbo_max);
15657494343SDavid Howells 		pkt.whdr.flags		|= RXRPC_SLOW_START_OK;
1575fc62f6aSDavid Howells 		padding			= 0;
1585fc62f6aSDavid Howells 		iov[0].iov_len += sizeof(pkt.ack);
1595fc62f6aSDavid Howells 		len += sizeof(pkt.ack) + 3 + sizeof(ack_info);
1605fc62f6aSDavid Howells 		ioc = 3;
16118bfeba5SDavid Howells 		break;
1625fc62f6aSDavid Howells 
1635fc62f6aSDavid Howells 	default:
1645fc62f6aSDavid Howells 		return;
16518bfeba5SDavid Howells 	}
16618bfeba5SDavid Howells 
16718bfeba5SDavid Howells 	/* Resync with __rxrpc_disconnect_call() and check that the last call
16818bfeba5SDavid Howells 	 * didn't get advanced whilst we were filling out the packets.
16918bfeba5SDavid Howells 	 */
17018bfeba5SDavid Howells 	smp_rmb();
17118bfeba5SDavid Howells 	if (READ_ONCE(chan->last_call) != call_id)
17218bfeba5SDavid Howells 		return;
17318bfeba5SDavid Howells 
17418bfeba5SDavid Howells 	serial = atomic_inc_return(&conn->serial);
17518bfeba5SDavid Howells 	pkt.whdr.serial = htonl(serial);
17618bfeba5SDavid Howells 
17718bfeba5SDavid Howells 	switch (chan->last_type) {
17818bfeba5SDavid Howells 	case RXRPC_PACKET_TYPE_ABORT:
17918bfeba5SDavid Howells 		break;
18018bfeba5SDavid Howells 	case RXRPC_PACKET_TYPE_ACK:
1814764c0daSDavid Howells 		trace_rxrpc_tx_ack(chan->call_debug_id, serial,
182f3f8337cSDavid Howells 				   ntohl(pkt.ack.firstPacket),
183f3f8337cSDavid Howells 				   ntohl(pkt.ack.serial),
184f3f8337cSDavid Howells 				   pkt.ack.reason, 0);
18518bfeba5SDavid Howells 		break;
18618bfeba5SDavid Howells 	}
18718bfeba5SDavid Howells 
1882cc80086SDavid Howells 	ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len);
1892cc80086SDavid Howells 	conn->peer->last_tx_at = ktime_get_seconds();
1906b47fe1dSDavid Howells 	if (ret < 0)
1914764c0daSDavid Howells 		trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret,
1924764c0daSDavid Howells 				    rxrpc_tx_point_call_final_resend);
1934764c0daSDavid Howells 	else
1944764c0daSDavid Howells 		trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr,
1954764c0daSDavid Howells 				      rxrpc_tx_point_call_final_resend);
1966b47fe1dSDavid Howells 
19718bfeba5SDavid Howells 	_leave("");
19818bfeba5SDavid Howells }
19918bfeba5SDavid Howells 
20018bfeba5SDavid Howells /*
2018c3e34a4SDavid Howells  * pass a connection-level abort onto all calls on that connection
2028c3e34a4SDavid Howells  */
203a00ce28bSDavid Howells static void rxrpc_abort_calls(struct rxrpc_connection *conn)
2048c3e34a4SDavid Howells {
2058c3e34a4SDavid Howells 	struct rxrpc_call *call;
206248f219cSDavid Howells 	int i;
2078c3e34a4SDavid Howells 
20864753092SDavid Howells 	_enter("{%d},%x", conn->debug_id, conn->abort_code);
2098c3e34a4SDavid Howells 
210245500d8SDavid Howells 	spin_lock(&conn->bundle->channel_lock);
2118c3e34a4SDavid Howells 
212a1399f8bSDavid Howells 	for (i = 0; i < RXRPC_MAXCALLS; i++) {
213a1399f8bSDavid Howells 		call = rcu_dereference_protected(
214a1399f8bSDavid Howells 			conn->channels[i].call,
215245500d8SDavid Howells 			lockdep_is_held(&conn->bundle->channel_lock));
216a00ce28bSDavid Howells 		if (call)
217a00ce28bSDavid Howells 			rxrpc_set_call_completion(call,
218a00ce28bSDavid Howells 						  conn->completion,
21964753092SDavid Howells 						  conn->abort_code,
22064753092SDavid Howells 						  conn->error);
221ccbd3dbeSDavid Howells 	}
2228c3e34a4SDavid Howells 
223245500d8SDavid Howells 	spin_unlock(&conn->bundle->channel_lock);
2248c3e34a4SDavid Howells 	_leave("");
2258c3e34a4SDavid Howells }
2268c3e34a4SDavid Howells 
2278c3e34a4SDavid Howells /*
2288c3e34a4SDavid Howells  * mark a call as being on a now-secured channel
229248f219cSDavid Howells  * - must be called with BH's disabled.
2308c3e34a4SDavid Howells  */
2318c3e34a4SDavid Howells static void rxrpc_call_is_secure(struct rxrpc_call *call)
2328c3e34a4SDavid Howells {
2338c3e34a4SDavid Howells 	_enter("%p", call);
2348c3e34a4SDavid Howells 	if (call) {
2353dd9c8b5SDavid Howells 		write_lock(&call->state_lock);
236248f219cSDavid Howells 		if (call->state == RXRPC_CALL_SERVER_SECURING) {
2372d914c1bSDavid Howells 			call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
238248f219cSDavid Howells 			rxrpc_notify_socket(call);
239248f219cSDavid Howells 		}
2403dd9c8b5SDavid Howells 		write_unlock(&call->state_lock);
2418c3e34a4SDavid Howells 	}
2428c3e34a4SDavid Howells }
2438c3e34a4SDavid Howells 
2448c3e34a4SDavid Howells /*
2458c3e34a4SDavid Howells  * connection-level Rx packet processor
2468c3e34a4SDavid Howells  */
2478c3e34a4SDavid Howells static int rxrpc_process_event(struct rxrpc_connection *conn,
248a00ce28bSDavid Howells 			       struct sk_buff *skb)
2498c3e34a4SDavid Howells {
2508c3e34a4SDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
251*2953d3b8SDavid Howells 	int ret;
2528c3e34a4SDavid Howells 
253a00ce28bSDavid Howells 	if (conn->state == RXRPC_CONN_ABORTED)
2548c3e34a4SDavid Howells 		return -ECONNABORTED;
2558c3e34a4SDavid Howells 
2568c3e34a4SDavid Howells 	_enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial);
2578c3e34a4SDavid Howells 
2588c3e34a4SDavid Howells 	switch (sp->hdr.type) {
2598c3e34a4SDavid Howells 	case RXRPC_PACKET_TYPE_CHALLENGE:
260a00ce28bSDavid Howells 		return conn->security->respond_to_challenge(conn, skb);
2618c3e34a4SDavid Howells 
2628c3e34a4SDavid Howells 	case RXRPC_PACKET_TYPE_RESPONSE:
263a00ce28bSDavid Howells 		ret = conn->security->verify_response(conn, skb);
2648c3e34a4SDavid Howells 		if (ret < 0)
2658c3e34a4SDavid Howells 			return ret;
2668c3e34a4SDavid Howells 
26741057ebdSDavid Howells 		ret = conn->security->init_connection_security(
2682cc80086SDavid Howells 			conn, conn->key->payload.data[0]);
2698c3e34a4SDavid Howells 		if (ret < 0)
2708c3e34a4SDavid Howells 			return ret;
2718c3e34a4SDavid Howells 
2723dd9c8b5SDavid Howells 		spin_lock(&conn->state_lock);
273*2953d3b8SDavid Howells 		if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING)
274bba304dbSDavid Howells 			conn->state = RXRPC_CONN_SERVICE;
2753dd9c8b5SDavid Howells 		spin_unlock(&conn->state_lock);
2768c3e34a4SDavid Howells 
277*2953d3b8SDavid Howells 		if (conn->state == RXRPC_CONN_SERVICE) {
278*2953d3b8SDavid Howells 			/* Offload call state flipping to the I/O thread.  As
279*2953d3b8SDavid Howells 			 * we've already received the packet, put it on the
280*2953d3b8SDavid Howells 			 * front of the queue.
281*2953d3b8SDavid Howells 			 */
282*2953d3b8SDavid Howells 			skb->mark = RXRPC_SKB_MARK_SERVICE_CONN_SECURED;
283*2953d3b8SDavid Howells 			rxrpc_get_skb(skb, rxrpc_skb_get_conn_secured);
284*2953d3b8SDavid Howells 			skb_queue_head(&conn->local->rx_queue, skb);
285*2953d3b8SDavid Howells 			rxrpc_wake_up_io_thread(conn->local);
286*2953d3b8SDavid Howells 		}
2878c3e34a4SDavid Howells 		return 0;
2888c3e34a4SDavid Howells 
2898c3e34a4SDavid Howells 	default:
29057af281eSDavid Howells 		WARN_ON_ONCE(1);
2918c3e34a4SDavid Howells 		return -EPROTO;
2928c3e34a4SDavid Howells 	}
2938c3e34a4SDavid Howells }
2948c3e34a4SDavid Howells 
2958c3e34a4SDavid Howells /*
2968c3e34a4SDavid Howells  * set up security and issue a challenge
2978c3e34a4SDavid Howells  */
2988c3e34a4SDavid Howells static void rxrpc_secure_connection(struct rxrpc_connection *conn)
2998c3e34a4SDavid Howells {
300a00ce28bSDavid Howells 	if (conn->security->issue_challenge(conn) < 0)
30157af281eSDavid Howells 		rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM,
30257af281eSDavid Howells 				 rxrpc_abort_nomem);
3038c3e34a4SDavid Howells }
3048c3e34a4SDavid Howells 
3058c3e34a4SDavid Howells /*
3063136ef49SDavid Howells  * Process delayed final ACKs that we haven't subsumed into a subsequent call.
3073136ef49SDavid Howells  */
308ddc7834aSDavid Howells void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force)
3093136ef49SDavid Howells {
3103136ef49SDavid Howells 	unsigned long j = jiffies, next_j;
3113136ef49SDavid Howells 	unsigned int channel;
3123136ef49SDavid Howells 	bool set;
3133136ef49SDavid Howells 
3143136ef49SDavid Howells again:
3153136ef49SDavid Howells 	next_j = j + LONG_MAX;
3163136ef49SDavid Howells 	set = false;
3173136ef49SDavid Howells 	for (channel = 0; channel < RXRPC_MAXCALLS; channel++) {
3183136ef49SDavid Howells 		struct rxrpc_channel *chan = &conn->channels[channel];
3193136ef49SDavid Howells 		unsigned long ack_at;
3203136ef49SDavid Howells 
3213136ef49SDavid Howells 		if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags))
3223136ef49SDavid Howells 			continue;
3233136ef49SDavid Howells 
3243136ef49SDavid Howells 		smp_rmb(); /* vs rxrpc_disconnect_client_call */
3253136ef49SDavid Howells 		ack_at = READ_ONCE(chan->final_ack_at);
3263136ef49SDavid Howells 
327ddc7834aSDavid Howells 		if (time_before(j, ack_at) && !force) {
3283136ef49SDavid Howells 			if (time_before(ack_at, next_j)) {
3293136ef49SDavid Howells 				next_j = ack_at;
3303136ef49SDavid Howells 				set = true;
3313136ef49SDavid Howells 			}
3323136ef49SDavid Howells 			continue;
3333136ef49SDavid Howells 		}
3343136ef49SDavid Howells 
3353136ef49SDavid Howells 		if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel,
3363136ef49SDavid Howells 				       &conn->flags))
3373136ef49SDavid Howells 			rxrpc_conn_retransmit_call(conn, NULL, channel);
3383136ef49SDavid Howells 	}
3393136ef49SDavid Howells 
3403136ef49SDavid Howells 	j = jiffies;
3413136ef49SDavid Howells 	if (time_before_eq(next_j, j))
3423136ef49SDavid Howells 		goto again;
3433136ef49SDavid Howells 	if (set)
3443136ef49SDavid Howells 		rxrpc_reduce_conn_timer(conn, next_j);
3453136ef49SDavid Howells }
3463136ef49SDavid Howells 
3473136ef49SDavid Howells /*
3488c3e34a4SDavid Howells  * connection-level event processor
3498c3e34a4SDavid Howells  */
35004d36d74SDavid Howells static void rxrpc_do_process_connection(struct rxrpc_connection *conn)
3518c3e34a4SDavid Howells {
3528c3e34a4SDavid Howells 	struct sk_buff *skb;
3538c3e34a4SDavid Howells 	int ret;
3548c3e34a4SDavid Howells 
3552c4579e4SDavid Howells 	if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events))
3568c3e34a4SDavid Howells 		rxrpc_secure_connection(conn);
3578c3e34a4SDavid Howells 
3588c3e34a4SDavid Howells 	/* go through the conn-level event packets, releasing the ref on this
3598c3e34a4SDavid Howells 	 * connection that each one has when we've finished with it */
3608c3e34a4SDavid Howells 	while ((skb = skb_dequeue(&conn->rx_queue))) {
3619a36a6bcSDavid Howells 		rxrpc_see_skb(skb, rxrpc_skb_see_conn_work);
362a00ce28bSDavid Howells 		ret = rxrpc_process_event(conn, skb);
3638c3e34a4SDavid Howells 		switch (ret) {
3648c2f826dSDavid Howells 		case -ENOMEM:
3658c3e34a4SDavid Howells 		case -EAGAIN:
366a00ce28bSDavid Howells 			skb_queue_head(&conn->rx_queue, skb);
367a00ce28bSDavid Howells 			rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work);
368a00ce28bSDavid Howells 			break;
3698c3e34a4SDavid Howells 		default:
3709a36a6bcSDavid Howells 			rxrpc_free_skb(skb, rxrpc_skb_put_conn_work);
3718c3e34a4SDavid Howells 			break;
3728c3e34a4SDavid Howells 		}
3738c3e34a4SDavid Howells 	}
37404d36d74SDavid Howells }
37504d36d74SDavid Howells 
37604d36d74SDavid Howells void rxrpc_process_connection(struct work_struct *work)
37704d36d74SDavid Howells {
37804d36d74SDavid Howells 	struct rxrpc_connection *conn =
37904d36d74SDavid Howells 		container_of(work, struct rxrpc_connection, processor);
38004d36d74SDavid Howells 
3817fa25105SDavid Howells 	rxrpc_see_connection(conn, rxrpc_conn_see_work);
38204d36d74SDavid Howells 
3830fde882fSDavid Howells 	if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) {
38404d36d74SDavid Howells 		rxrpc_do_process_connection(conn);
3850fde882fSDavid Howells 		rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work);
38604d36d74SDavid Howells 	}
3878c3e34a4SDavid Howells }
3885e6ef4f1SDavid Howells 
3895e6ef4f1SDavid Howells /*
3905e6ef4f1SDavid Howells  * post connection-level events to the connection
3915e6ef4f1SDavid Howells  * - this includes challenges, responses, some aborts and call terminal packet
3925e6ef4f1SDavid Howells  *   retransmission.
3935e6ef4f1SDavid Howells  */
3945e6ef4f1SDavid Howells static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
3955e6ef4f1SDavid Howells 				      struct sk_buff *skb)
3965e6ef4f1SDavid Howells {
3975e6ef4f1SDavid Howells 	_enter("%p,%p", conn, skb);
3985e6ef4f1SDavid Howells 
3995e6ef4f1SDavid Howells 	rxrpc_get_skb(skb, rxrpc_skb_get_conn_work);
4005e6ef4f1SDavid Howells 	skb_queue_tail(&conn->rx_queue, skb);
4015e6ef4f1SDavid Howells 	rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work);
4025e6ef4f1SDavid Howells }
4035e6ef4f1SDavid Howells 
4045e6ef4f1SDavid Howells /*
4055e6ef4f1SDavid Howells  * Input a connection-level packet.
4065e6ef4f1SDavid Howells  */
40757af281eSDavid Howells bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
4085e6ef4f1SDavid Howells {
4095e6ef4f1SDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
4105e6ef4f1SDavid Howells 
4115e6ef4f1SDavid Howells 	switch (sp->hdr.type) {
4125e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_BUSY:
4135e6ef4f1SDavid Howells 		/* Just ignore BUSY packets for now. */
41457af281eSDavid Howells 		return true;
4155e6ef4f1SDavid Howells 
4165e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_ABORT:
417a00ce28bSDavid Howells 		if (rxrpc_is_conn_aborted(conn))
418a00ce28bSDavid Howells 			return true;
419a00ce28bSDavid Howells 		rxrpc_input_conn_abort(conn, skb);
420a00ce28bSDavid Howells 		rxrpc_abort_calls(conn);
421a00ce28bSDavid Howells 		return true;
4225e6ef4f1SDavid Howells 
4235e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_CHALLENGE:
4245e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_RESPONSE:
425a00ce28bSDavid Howells 		if (rxrpc_is_conn_aborted(conn)) {
426a00ce28bSDavid Howells 			if (conn->completion == RXRPC_CALL_LOCALLY_ABORTED)
427a00ce28bSDavid Howells 				rxrpc_send_conn_abort(conn);
428a00ce28bSDavid Howells 			return true;
429a00ce28bSDavid Howells 		}
4305e6ef4f1SDavid Howells 		rxrpc_post_packet_to_conn(conn, skb);
43157af281eSDavid Howells 		return true;
4325e6ef4f1SDavid Howells 
4335e6ef4f1SDavid Howells 	default:
43457af281eSDavid Howells 		WARN_ON_ONCE(1);
43557af281eSDavid Howells 		return true;
4365e6ef4f1SDavid Howells 	}
4375e6ef4f1SDavid Howells }
438f2cce89aSDavid Howells 
439f2cce89aSDavid Howells /*
440f2cce89aSDavid Howells  * Input a connection event.
441f2cce89aSDavid Howells  */
442f2cce89aSDavid Howells void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb)
443f2cce89aSDavid Howells {
444*2953d3b8SDavid Howells 	unsigned int loop;
445*2953d3b8SDavid Howells 
446a00ce28bSDavid Howells 	if (test_and_clear_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events))
447a00ce28bSDavid Howells 		rxrpc_abort_calls(conn);
448a00ce28bSDavid Howells 
449*2953d3b8SDavid Howells 	switch (skb->mark) {
450*2953d3b8SDavid Howells 	case RXRPC_SKB_MARK_SERVICE_CONN_SECURED:
451*2953d3b8SDavid Howells 		if (conn->state != RXRPC_CONN_SERVICE)
452*2953d3b8SDavid Howells 			break;
453*2953d3b8SDavid Howells 
454*2953d3b8SDavid Howells 		spin_lock(&conn->bundle->channel_lock);
455*2953d3b8SDavid Howells 
456*2953d3b8SDavid Howells 		for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
457*2953d3b8SDavid Howells 			rxrpc_call_is_secure(
458*2953d3b8SDavid Howells 				rcu_dereference_protected(
459*2953d3b8SDavid Howells 					conn->channels[loop].call,
460*2953d3b8SDavid Howells 					lockdep_is_held(&conn->bundle->channel_lock)));
461*2953d3b8SDavid Howells 
462*2953d3b8SDavid Howells 		spin_unlock(&conn->bundle->channel_lock);
463*2953d3b8SDavid Howells 		break;
464*2953d3b8SDavid Howells 	}
465*2953d3b8SDavid Howells 
466f2cce89aSDavid Howells 	/* Process delayed ACKs whose time has come. */
467f2cce89aSDavid Howells 	if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK)
468f2cce89aSDavid Howells 		rxrpc_process_delayed_final_acks(conn, false);
469f2cce89aSDavid Howells }
470