xref: /openbmc/linux/net/rxrpc/conn_event.c (revision f789bff2)
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 	 */
1039d35d880SDavid Howells 	call_id = chan->last_call;
1043136ef49SDavid Howells 	if (skb && call_id != sp->hdr.callNumber)
10518bfeba5SDavid Howells 		return;
10618bfeba5SDavid Howells 
1072cc80086SDavid Howells 	msg.msg_name	= &conn->peer->srx.transport;
1082cc80086SDavid Howells 	msg.msg_namelen	= conn->peer->srx.transport_len;
10918bfeba5SDavid Howells 	msg.msg_control	= NULL;
11018bfeba5SDavid Howells 	msg.msg_controllen = 0;
11118bfeba5SDavid Howells 	msg.msg_flags	= 0;
11218bfeba5SDavid Howells 
1135fc62f6aSDavid Howells 	iov[0].iov_base	= &pkt;
1145fc62f6aSDavid Howells 	iov[0].iov_len	= sizeof(pkt.whdr);
1155fc62f6aSDavid Howells 	iov[1].iov_base	= &padding;
1165fc62f6aSDavid Howells 	iov[1].iov_len	= 3;
1175fc62f6aSDavid Howells 	iov[2].iov_base	= &ack_info;
1185fc62f6aSDavid Howells 	iov[2].iov_len	= sizeof(ack_info);
1195fc62f6aSDavid Howells 
1209d35d880SDavid Howells 	serial = atomic_inc_return(&conn->serial);
1219d35d880SDavid 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);
1259d35d880SDavid Howells 	pkt.whdr.serial		= htonl(serial);
12618bfeba5SDavid Howells 	pkt.whdr.seq		= 0;
12718bfeba5SDavid Howells 	pkt.whdr.type		= chan->last_type;
12818bfeba5SDavid Howells 	pkt.whdr.flags		= conn->out_clientflag;
12918bfeba5SDavid Howells 	pkt.whdr.userStatus	= 0;
13018bfeba5SDavid Howells 	pkt.whdr.securityIndex	= conn->security_ix;
13118bfeba5SDavid Howells 	pkt.whdr._rsvd		= 0;
13268d6d1aeSDavid Howells 	pkt.whdr.serviceId	= htons(conn->service_id);
13318bfeba5SDavid Howells 
13418bfeba5SDavid Howells 	len = sizeof(pkt.whdr);
13518bfeba5SDavid Howells 	switch (chan->last_type) {
13618bfeba5SDavid Howells 	case RXRPC_PACKET_TYPE_ABORT:
1375fc62f6aSDavid Howells 		pkt.abort_code	= htonl(chan->last_abort);
1385fc62f6aSDavid Howells 		iov[0].iov_len += sizeof(pkt.abort_code);
1395fc62f6aSDavid Howells 		len += sizeof(pkt.abort_code);
1405fc62f6aSDavid Howells 		ioc = 1;
14118bfeba5SDavid Howells 		break;
14218bfeba5SDavid Howells 
14318bfeba5SDavid Howells 	case RXRPC_PACKET_TYPE_ACK:
1442cc80086SDavid Howells 		mtu = conn->peer->if_mtu;
1452cc80086SDavid Howells 		mtu -= conn->peer->hdrsize;
14618bfeba5SDavid Howells 		pkt.ack.bufferSpace	= 0;
1473136ef49SDavid Howells 		pkt.ack.maxSkew		= htons(skb ? skb->priority : 0);
1483136ef49SDavid Howells 		pkt.ack.firstPacket	= htonl(chan->last_seq + 1);
1493136ef49SDavid Howells 		pkt.ack.previousPacket	= htonl(chan->last_seq);
1503136ef49SDavid Howells 		pkt.ack.serial		= htonl(skb ? sp->hdr.serial : 0);
1513136ef49SDavid Howells 		pkt.ack.reason		= skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
15218bfeba5SDavid Howells 		pkt.ack.nAcks		= 0;
1535fc62f6aSDavid Howells 		ack_info.rxMTU		= htonl(rxrpc_rx_mtu);
1545fc62f6aSDavid Howells 		ack_info.maxMTU		= htonl(mtu);
1555fc62f6aSDavid Howells 		ack_info.rwind		= htonl(rxrpc_rx_window_size);
1565fc62f6aSDavid Howells 		ack_info.jumbo_max	= htonl(rxrpc_rx_jumbo_max);
15757494343SDavid Howells 		pkt.whdr.flags		|= RXRPC_SLOW_START_OK;
1585fc62f6aSDavid Howells 		padding			= 0;
1595fc62f6aSDavid Howells 		iov[0].iov_len += sizeof(pkt.ack);
1605fc62f6aSDavid Howells 		len += sizeof(pkt.ack) + 3 + sizeof(ack_info);
1615fc62f6aSDavid Howells 		ioc = 3;
1625fc62f6aSDavid Howells 
1634764c0daSDavid Howells 		trace_rxrpc_tx_ack(chan->call_debug_id, serial,
164f3f8337cSDavid Howells 				   ntohl(pkt.ack.firstPacket),
165f3f8337cSDavid Howells 				   ntohl(pkt.ack.serial),
166*f789bff2SDavid Howells 				   pkt.ack.reason, 0, rxrpc_rx_window_size);
16718bfeba5SDavid Howells 		break;
1689d35d880SDavid Howells 
1699d35d880SDavid Howells 	default:
1709d35d880SDavid Howells 		return;
17118bfeba5SDavid Howells 	}
17218bfeba5SDavid Howells 
1732cc80086SDavid Howells 	ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len);
1742cc80086SDavid Howells 	conn->peer->last_tx_at = ktime_get_seconds();
1756b47fe1dSDavid Howells 	if (ret < 0)
1764764c0daSDavid Howells 		trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret,
1774764c0daSDavid Howells 				    rxrpc_tx_point_call_final_resend);
1784764c0daSDavid Howells 	else
1794764c0daSDavid Howells 		trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr,
1804764c0daSDavid Howells 				      rxrpc_tx_point_call_final_resend);
1816b47fe1dSDavid Howells 
18218bfeba5SDavid Howells 	_leave("");
18318bfeba5SDavid Howells }
18418bfeba5SDavid Howells 
18518bfeba5SDavid Howells /*
1868c3e34a4SDavid Howells  * pass a connection-level abort onto all calls on that connection
1878c3e34a4SDavid Howells  */
188a00ce28bSDavid Howells static void rxrpc_abort_calls(struct rxrpc_connection *conn)
1898c3e34a4SDavid Howells {
1908c3e34a4SDavid Howells 	struct rxrpc_call *call;
191248f219cSDavid Howells 	int i;
1928c3e34a4SDavid Howells 
19364753092SDavid Howells 	_enter("{%d},%x", conn->debug_id, conn->abort_code);
1948c3e34a4SDavid Howells 
195a1399f8bSDavid Howells 	for (i = 0; i < RXRPC_MAXCALLS; i++) {
1969d35d880SDavid Howells 		call = conn->channels[i].call;
197a00ce28bSDavid Howells 		if (call)
198a00ce28bSDavid Howells 			rxrpc_set_call_completion(call,
199a00ce28bSDavid Howells 						  conn->completion,
20064753092SDavid Howells 						  conn->abort_code,
20164753092SDavid Howells 						  conn->error);
202ccbd3dbeSDavid Howells 	}
2038c3e34a4SDavid Howells 
2048c3e34a4SDavid Howells 	_leave("");
2058c3e34a4SDavid Howells }
2068c3e34a4SDavid Howells 
2078c3e34a4SDavid Howells /*
2088c3e34a4SDavid Howells  * mark a call as being on a now-secured channel
209248f219cSDavid Howells  * - must be called with BH's disabled.
2108c3e34a4SDavid Howells  */
2118c3e34a4SDavid Howells static void rxrpc_call_is_secure(struct rxrpc_call *call)
2128c3e34a4SDavid Howells {
21396b4059fSDavid Howells 	if (call && __rxrpc_call_state(call) == RXRPC_CALL_SERVER_SECURING) {
21496b4059fSDavid Howells 		rxrpc_set_call_state(call, RXRPC_CALL_SERVER_RECV_REQUEST);
215248f219cSDavid Howells 		rxrpc_notify_socket(call);
216248f219cSDavid Howells 	}
2178c3e34a4SDavid Howells }
2188c3e34a4SDavid Howells 
2198c3e34a4SDavid Howells /*
2208c3e34a4SDavid Howells  * connection-level Rx packet processor
2218c3e34a4SDavid Howells  */
2228c3e34a4SDavid Howells static int rxrpc_process_event(struct rxrpc_connection *conn,
223a00ce28bSDavid Howells 			       struct sk_buff *skb)
2248c3e34a4SDavid Howells {
2258c3e34a4SDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
2262953d3b8SDavid Howells 	int ret;
2278c3e34a4SDavid Howells 
228a00ce28bSDavid Howells 	if (conn->state == RXRPC_CONN_ABORTED)
2298c3e34a4SDavid Howells 		return -ECONNABORTED;
2308c3e34a4SDavid Howells 
2318c3e34a4SDavid Howells 	_enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial);
2328c3e34a4SDavid Howells 
2338c3e34a4SDavid Howells 	switch (sp->hdr.type) {
2348c3e34a4SDavid Howells 	case RXRPC_PACKET_TYPE_CHALLENGE:
235a00ce28bSDavid Howells 		return conn->security->respond_to_challenge(conn, skb);
2368c3e34a4SDavid Howells 
2378c3e34a4SDavid Howells 	case RXRPC_PACKET_TYPE_RESPONSE:
238a00ce28bSDavid Howells 		ret = conn->security->verify_response(conn, skb);
2398c3e34a4SDavid Howells 		if (ret < 0)
2408c3e34a4SDavid Howells 			return ret;
2418c3e34a4SDavid Howells 
24241057ebdSDavid Howells 		ret = conn->security->init_connection_security(
2432cc80086SDavid Howells 			conn, conn->key->payload.data[0]);
2448c3e34a4SDavid Howells 		if (ret < 0)
2458c3e34a4SDavid Howells 			return ret;
2468c3e34a4SDavid Howells 
2473dd9c8b5SDavid Howells 		spin_lock(&conn->state_lock);
2482953d3b8SDavid Howells 		if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING)
249bba304dbSDavid Howells 			conn->state = RXRPC_CONN_SERVICE;
2503dd9c8b5SDavid Howells 		spin_unlock(&conn->state_lock);
2518c3e34a4SDavid Howells 
2522953d3b8SDavid Howells 		if (conn->state == RXRPC_CONN_SERVICE) {
2532953d3b8SDavid Howells 			/* Offload call state flipping to the I/O thread.  As
2542953d3b8SDavid Howells 			 * we've already received the packet, put it on the
2552953d3b8SDavid Howells 			 * front of the queue.
2562953d3b8SDavid Howells 			 */
2572953d3b8SDavid Howells 			skb->mark = RXRPC_SKB_MARK_SERVICE_CONN_SECURED;
2582953d3b8SDavid Howells 			rxrpc_get_skb(skb, rxrpc_skb_get_conn_secured);
2592953d3b8SDavid Howells 			skb_queue_head(&conn->local->rx_queue, skb);
2602953d3b8SDavid Howells 			rxrpc_wake_up_io_thread(conn->local);
2612953d3b8SDavid Howells 		}
2628c3e34a4SDavid Howells 		return 0;
2638c3e34a4SDavid Howells 
2648c3e34a4SDavid Howells 	default:
26557af281eSDavid Howells 		WARN_ON_ONCE(1);
2668c3e34a4SDavid Howells 		return -EPROTO;
2678c3e34a4SDavid Howells 	}
2688c3e34a4SDavid Howells }
2698c3e34a4SDavid Howells 
2708c3e34a4SDavid Howells /*
2718c3e34a4SDavid Howells  * set up security and issue a challenge
2728c3e34a4SDavid Howells  */
2738c3e34a4SDavid Howells static void rxrpc_secure_connection(struct rxrpc_connection *conn)
2748c3e34a4SDavid Howells {
275a00ce28bSDavid Howells 	if (conn->security->issue_challenge(conn) < 0)
27657af281eSDavid Howells 		rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM,
27757af281eSDavid Howells 				 rxrpc_abort_nomem);
2788c3e34a4SDavid Howells }
2798c3e34a4SDavid Howells 
2808c3e34a4SDavid Howells /*
2813136ef49SDavid Howells  * Process delayed final ACKs that we haven't subsumed into a subsequent call.
2823136ef49SDavid Howells  */
283ddc7834aSDavid Howells void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force)
2843136ef49SDavid Howells {
2853136ef49SDavid Howells 	unsigned long j = jiffies, next_j;
2863136ef49SDavid Howells 	unsigned int channel;
2873136ef49SDavid Howells 	bool set;
2883136ef49SDavid Howells 
2893136ef49SDavid Howells again:
2903136ef49SDavid Howells 	next_j = j + LONG_MAX;
2913136ef49SDavid Howells 	set = false;
2923136ef49SDavid Howells 	for (channel = 0; channel < RXRPC_MAXCALLS; channel++) {
2933136ef49SDavid Howells 		struct rxrpc_channel *chan = &conn->channels[channel];
2943136ef49SDavid Howells 		unsigned long ack_at;
2953136ef49SDavid Howells 
2963136ef49SDavid Howells 		if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags))
2973136ef49SDavid Howells 			continue;
2983136ef49SDavid Howells 
2999d35d880SDavid Howells 		ack_at = chan->final_ack_at;
300ddc7834aSDavid Howells 		if (time_before(j, ack_at) && !force) {
3013136ef49SDavid Howells 			if (time_before(ack_at, next_j)) {
3023136ef49SDavid Howells 				next_j = ack_at;
3033136ef49SDavid Howells 				set = true;
3043136ef49SDavid Howells 			}
3053136ef49SDavid Howells 			continue;
3063136ef49SDavid Howells 		}
3073136ef49SDavid Howells 
3083136ef49SDavid Howells 		if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel,
3093136ef49SDavid Howells 				       &conn->flags))
3103136ef49SDavid Howells 			rxrpc_conn_retransmit_call(conn, NULL, channel);
3113136ef49SDavid Howells 	}
3123136ef49SDavid Howells 
3133136ef49SDavid Howells 	j = jiffies;
3143136ef49SDavid Howells 	if (time_before_eq(next_j, j))
3153136ef49SDavid Howells 		goto again;
3163136ef49SDavid Howells 	if (set)
3173136ef49SDavid Howells 		rxrpc_reduce_conn_timer(conn, next_j);
3183136ef49SDavid Howells }
3193136ef49SDavid Howells 
3203136ef49SDavid Howells /*
3218c3e34a4SDavid Howells  * connection-level event processor
3228c3e34a4SDavid Howells  */
32304d36d74SDavid Howells static void rxrpc_do_process_connection(struct rxrpc_connection *conn)
3248c3e34a4SDavid Howells {
3258c3e34a4SDavid Howells 	struct sk_buff *skb;
3268c3e34a4SDavid Howells 	int ret;
3278c3e34a4SDavid Howells 
3282c4579e4SDavid Howells 	if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events))
3298c3e34a4SDavid Howells 		rxrpc_secure_connection(conn);
3308c3e34a4SDavid Howells 
3318c3e34a4SDavid Howells 	/* go through the conn-level event packets, releasing the ref on this
3328c3e34a4SDavid Howells 	 * connection that each one has when we've finished with it */
3338c3e34a4SDavid Howells 	while ((skb = skb_dequeue(&conn->rx_queue))) {
3349a36a6bcSDavid Howells 		rxrpc_see_skb(skb, rxrpc_skb_see_conn_work);
335a00ce28bSDavid Howells 		ret = rxrpc_process_event(conn, skb);
3368c3e34a4SDavid Howells 		switch (ret) {
3378c2f826dSDavid Howells 		case -ENOMEM:
3388c3e34a4SDavid Howells 		case -EAGAIN:
339a00ce28bSDavid Howells 			skb_queue_head(&conn->rx_queue, skb);
340a00ce28bSDavid Howells 			rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work);
341a00ce28bSDavid Howells 			break;
3428c3e34a4SDavid Howells 		default:
3439a36a6bcSDavid Howells 			rxrpc_free_skb(skb, rxrpc_skb_put_conn_work);
3448c3e34a4SDavid Howells 			break;
3458c3e34a4SDavid Howells 		}
3468c3e34a4SDavid Howells 	}
34704d36d74SDavid Howells }
34804d36d74SDavid Howells 
34904d36d74SDavid Howells void rxrpc_process_connection(struct work_struct *work)
35004d36d74SDavid Howells {
35104d36d74SDavid Howells 	struct rxrpc_connection *conn =
35204d36d74SDavid Howells 		container_of(work, struct rxrpc_connection, processor);
35304d36d74SDavid Howells 
3547fa25105SDavid Howells 	rxrpc_see_connection(conn, rxrpc_conn_see_work);
35504d36d74SDavid Howells 
3560fde882fSDavid Howells 	if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) {
35704d36d74SDavid Howells 		rxrpc_do_process_connection(conn);
3580fde882fSDavid Howells 		rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work);
35904d36d74SDavid Howells 	}
3608c3e34a4SDavid Howells }
3615e6ef4f1SDavid Howells 
3625e6ef4f1SDavid Howells /*
3635e6ef4f1SDavid Howells  * post connection-level events to the connection
3645e6ef4f1SDavid Howells  * - this includes challenges, responses, some aborts and call terminal packet
3655e6ef4f1SDavid Howells  *   retransmission.
3665e6ef4f1SDavid Howells  */
3675e6ef4f1SDavid Howells static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
3685e6ef4f1SDavid Howells 				      struct sk_buff *skb)
3695e6ef4f1SDavid Howells {
3705e6ef4f1SDavid Howells 	_enter("%p,%p", conn, skb);
3715e6ef4f1SDavid Howells 
3725e6ef4f1SDavid Howells 	rxrpc_get_skb(skb, rxrpc_skb_get_conn_work);
3735e6ef4f1SDavid Howells 	skb_queue_tail(&conn->rx_queue, skb);
3745e6ef4f1SDavid Howells 	rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work);
3755e6ef4f1SDavid Howells }
3765e6ef4f1SDavid Howells 
3775e6ef4f1SDavid Howells /*
3785e6ef4f1SDavid Howells  * Input a connection-level packet.
3795e6ef4f1SDavid Howells  */
38057af281eSDavid Howells bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
3815e6ef4f1SDavid Howells {
3825e6ef4f1SDavid Howells 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
3835e6ef4f1SDavid Howells 
3845e6ef4f1SDavid Howells 	switch (sp->hdr.type) {
3855e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_BUSY:
3865e6ef4f1SDavid Howells 		/* Just ignore BUSY packets for now. */
38757af281eSDavid Howells 		return true;
3885e6ef4f1SDavid Howells 
3895e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_ABORT:
390a00ce28bSDavid Howells 		if (rxrpc_is_conn_aborted(conn))
391a00ce28bSDavid Howells 			return true;
392a00ce28bSDavid Howells 		rxrpc_input_conn_abort(conn, skb);
393a00ce28bSDavid Howells 		rxrpc_abort_calls(conn);
394a00ce28bSDavid Howells 		return true;
3955e6ef4f1SDavid Howells 
3965e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_CHALLENGE:
3975e6ef4f1SDavid Howells 	case RXRPC_PACKET_TYPE_RESPONSE:
398a00ce28bSDavid Howells 		if (rxrpc_is_conn_aborted(conn)) {
399a00ce28bSDavid Howells 			if (conn->completion == RXRPC_CALL_LOCALLY_ABORTED)
400a00ce28bSDavid Howells 				rxrpc_send_conn_abort(conn);
401a00ce28bSDavid Howells 			return true;
402a00ce28bSDavid Howells 		}
4035e6ef4f1SDavid Howells 		rxrpc_post_packet_to_conn(conn, skb);
40457af281eSDavid Howells 		return true;
4055e6ef4f1SDavid Howells 
4065e6ef4f1SDavid Howells 	default:
40757af281eSDavid Howells 		WARN_ON_ONCE(1);
40857af281eSDavid Howells 		return true;
4095e6ef4f1SDavid Howells 	}
4105e6ef4f1SDavid Howells }
411f2cce89aSDavid Howells 
412f2cce89aSDavid Howells /*
413f2cce89aSDavid Howells  * Input a connection event.
414f2cce89aSDavid Howells  */
415f2cce89aSDavid Howells void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb)
416f2cce89aSDavid Howells {
4172953d3b8SDavid Howells 	unsigned int loop;
4182953d3b8SDavid Howells 
419a00ce28bSDavid Howells 	if (test_and_clear_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events))
420a00ce28bSDavid Howells 		rxrpc_abort_calls(conn);
421a00ce28bSDavid Howells 
4222953d3b8SDavid Howells 	switch (skb->mark) {
4232953d3b8SDavid Howells 	case RXRPC_SKB_MARK_SERVICE_CONN_SECURED:
4242953d3b8SDavid Howells 		if (conn->state != RXRPC_CONN_SERVICE)
4252953d3b8SDavid Howells 			break;
4262953d3b8SDavid Howells 
4272953d3b8SDavid Howells 		for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
4289d35d880SDavid Howells 			rxrpc_call_is_secure(conn->channels[loop].call);
4292953d3b8SDavid Howells 		break;
4302953d3b8SDavid Howells 	}
4312953d3b8SDavid Howells 
432f2cce89aSDavid Howells 	/* Process delayed ACKs whose time has come. */
433f2cce89aSDavid Howells 	if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK)
434f2cce89aSDavid Howells 		rxrpc_process_delayed_final_acks(conn, false);
435f2cce89aSDavid Howells }
436