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