162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* RxRPC packet reception 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2007, 2016, 2022 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "ar-internal.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistatic int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn, 1362306a36Sopenharmony_ci struct sockaddr_rxrpc *peer_srx, 1462306a36Sopenharmony_ci struct sk_buff *skb); 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* 1762306a36Sopenharmony_ci * handle data received on the local endpoint 1862306a36Sopenharmony_ci * - may be called in interrupt context 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * [!] Note that as this is called from the encap_rcv hook, the socket is not 2162306a36Sopenharmony_ci * held locked by the caller and nothing prevents sk_user_data on the UDP from 2262306a36Sopenharmony_ci * being cleared in the middle of processing this function. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Called with the RCU read lock held from the IP layer via UDP. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ciint rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci struct sk_buff_head *rx_queue; 2962306a36Sopenharmony_ci struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (unlikely(!local)) { 3262306a36Sopenharmony_ci kfree_skb(skb); 3362306a36Sopenharmony_ci return 0; 3462306a36Sopenharmony_ci } 3562306a36Sopenharmony_ci if (skb->tstamp == 0) 3662306a36Sopenharmony_ci skb->tstamp = ktime_get_real(); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci skb->mark = RXRPC_SKB_MARK_PACKET; 3962306a36Sopenharmony_ci rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv); 4062306a36Sopenharmony_ci rx_queue = &local->rx_queue; 4162306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY 4262306a36Sopenharmony_ci if (rxrpc_inject_rx_delay || 4362306a36Sopenharmony_ci !skb_queue_empty(&local->rx_delay_queue)) { 4462306a36Sopenharmony_ci skb->tstamp = ktime_add_ms(skb->tstamp, rxrpc_inject_rx_delay); 4562306a36Sopenharmony_ci rx_queue = &local->rx_delay_queue; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci skb_queue_tail(rx_queue, skb); 5062306a36Sopenharmony_ci rxrpc_wake_up_io_thread(local); 5162306a36Sopenharmony_ci return 0; 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* 5562306a36Sopenharmony_ci * Handle an error received on the local endpoint. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_civoid rxrpc_error_report(struct sock *sk) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct rxrpc_local *local; 6062306a36Sopenharmony_ci struct sk_buff *skb; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci rcu_read_lock(); 6362306a36Sopenharmony_ci local = rcu_dereference_sk_user_data(sk); 6462306a36Sopenharmony_ci if (unlikely(!local)) { 6562306a36Sopenharmony_ci rcu_read_unlock(); 6662306a36Sopenharmony_ci return; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci while ((skb = skb_dequeue(&sk->sk_error_queue))) { 7062306a36Sopenharmony_ci skb->mark = RXRPC_SKB_MARK_ERROR; 7162306a36Sopenharmony_ci rxrpc_new_skb(skb, rxrpc_skb_new_error_report); 7262306a36Sopenharmony_ci skb_queue_tail(&local->rx_queue, skb); 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci rxrpc_wake_up_io_thread(local); 7662306a36Sopenharmony_ci rcu_read_unlock(); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * Directly produce an abort from a packet. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_cibool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why, 8362306a36Sopenharmony_ci s32 abort_code, int err) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, 8862306a36Sopenharmony_ci abort_code, err); 8962306a36Sopenharmony_ci skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; 9062306a36Sopenharmony_ci skb->priority = abort_code; 9162306a36Sopenharmony_ci return false; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic bool rxrpc_bad_message(struct sk_buff *skb, enum rxrpc_abort_reason why) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci return rxrpc_direct_abort(skb, why, RX_PROTOCOL_ERROR, -EBADMSG); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define just_discard true 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* 10262306a36Sopenharmony_ci * Process event packets targeted at a local endpoint. 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_cistatic bool rxrpc_input_version(struct rxrpc_local *local, struct sk_buff *skb) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 10762306a36Sopenharmony_ci char v; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci _enter(""); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci rxrpc_see_skb(skb, rxrpc_skb_see_version); 11262306a36Sopenharmony_ci if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), &v, 1) >= 0) { 11362306a36Sopenharmony_ci if (v == 0) 11462306a36Sopenharmony_ci rxrpc_send_version_request(local, &sp->hdr, skb); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci return true; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * Extract the wire header from a packet and translate the byte order. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_cistatic bool rxrpc_extract_header(struct rxrpc_skb_priv *sp, 12462306a36Sopenharmony_ci struct sk_buff *skb) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct rxrpc_wire_header whdr; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* dig out the RxRPC connection details */ 12962306a36Sopenharmony_ci if (skb_copy_bits(skb, 0, &whdr, sizeof(whdr)) < 0) 13062306a36Sopenharmony_ci return rxrpc_bad_message(skb, rxrpc_badmsg_short_hdr); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci memset(sp, 0, sizeof(*sp)); 13362306a36Sopenharmony_ci sp->hdr.epoch = ntohl(whdr.epoch); 13462306a36Sopenharmony_ci sp->hdr.cid = ntohl(whdr.cid); 13562306a36Sopenharmony_ci sp->hdr.callNumber = ntohl(whdr.callNumber); 13662306a36Sopenharmony_ci sp->hdr.seq = ntohl(whdr.seq); 13762306a36Sopenharmony_ci sp->hdr.serial = ntohl(whdr.serial); 13862306a36Sopenharmony_ci sp->hdr.flags = whdr.flags; 13962306a36Sopenharmony_ci sp->hdr.type = whdr.type; 14062306a36Sopenharmony_ci sp->hdr.userStatus = whdr.userStatus; 14162306a36Sopenharmony_ci sp->hdr.securityIndex = whdr.securityIndex; 14262306a36Sopenharmony_ci sp->hdr._rsvd = ntohs(whdr._rsvd); 14362306a36Sopenharmony_ci sp->hdr.serviceId = ntohs(whdr.serviceId); 14462306a36Sopenharmony_ci return true; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/* 14862306a36Sopenharmony_ci * Extract the abort code from an ABORT packet and stash it in skb->priority. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_cistatic bool rxrpc_extract_abort(struct sk_buff *skb) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci __be32 wtmp; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), 15562306a36Sopenharmony_ci &wtmp, sizeof(wtmp)) < 0) 15662306a36Sopenharmony_ci return false; 15762306a36Sopenharmony_ci skb->priority = ntohl(wtmp); 15862306a36Sopenharmony_ci return true; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* 16262306a36Sopenharmony_ci * Process packets received on the local endpoint 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_cistatic bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci struct rxrpc_connection *conn; 16762306a36Sopenharmony_ci struct sockaddr_rxrpc peer_srx; 16862306a36Sopenharmony_ci struct rxrpc_skb_priv *sp; 16962306a36Sopenharmony_ci struct rxrpc_peer *peer = NULL; 17062306a36Sopenharmony_ci struct sk_buff *skb = *_skb; 17162306a36Sopenharmony_ci bool ret = false; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci skb_pull(skb, sizeof(struct udphdr)); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci sp = rxrpc_skb(skb); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* dig out the RxRPC connection details */ 17862306a36Sopenharmony_ci if (!rxrpc_extract_header(sp, skb)) 17962306a36Sopenharmony_ci return just_discard; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) { 18262306a36Sopenharmony_ci static int lose; 18362306a36Sopenharmony_ci if ((lose++ & 7) == 7) { 18462306a36Sopenharmony_ci trace_rxrpc_rx_lose(sp); 18562306a36Sopenharmony_ci return just_discard; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci trace_rxrpc_rx_packet(sp); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci switch (sp->hdr.type) { 19262306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_VERSION: 19362306a36Sopenharmony_ci if (rxrpc_to_client(sp)) 19462306a36Sopenharmony_ci return just_discard; 19562306a36Sopenharmony_ci return rxrpc_input_version(local, skb); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_BUSY: 19862306a36Sopenharmony_ci if (rxrpc_to_server(sp)) 19962306a36Sopenharmony_ci return just_discard; 20062306a36Sopenharmony_ci fallthrough; 20162306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_ACK: 20262306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_ACKALL: 20362306a36Sopenharmony_ci if (sp->hdr.callNumber == 0) 20462306a36Sopenharmony_ci return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call); 20562306a36Sopenharmony_ci break; 20662306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_ABORT: 20762306a36Sopenharmony_ci if (!rxrpc_extract_abort(skb)) 20862306a36Sopenharmony_ci return just_discard; /* Just discard if malformed */ 20962306a36Sopenharmony_ci break; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_DATA: 21262306a36Sopenharmony_ci if (sp->hdr.callNumber == 0) 21362306a36Sopenharmony_ci return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call); 21462306a36Sopenharmony_ci if (sp->hdr.seq == 0) 21562306a36Sopenharmony_ci return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Unshare the packet so that it can be modified for in-place 21862306a36Sopenharmony_ci * decryption. 21962306a36Sopenharmony_ci */ 22062306a36Sopenharmony_ci if (sp->hdr.securityIndex != 0) { 22162306a36Sopenharmony_ci skb = skb_unshare(skb, GFP_ATOMIC); 22262306a36Sopenharmony_ci if (!skb) { 22362306a36Sopenharmony_ci rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem); 22462306a36Sopenharmony_ci *_skb = NULL; 22562306a36Sopenharmony_ci return just_discard; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (skb != *_skb) { 22962306a36Sopenharmony_ci rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare); 23062306a36Sopenharmony_ci *_skb = skb; 23162306a36Sopenharmony_ci rxrpc_new_skb(skb, rxrpc_skb_new_unshared); 23262306a36Sopenharmony_ci sp = rxrpc_skb(skb); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci break; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_CHALLENGE: 23862306a36Sopenharmony_ci if (rxrpc_to_server(sp)) 23962306a36Sopenharmony_ci return just_discard; 24062306a36Sopenharmony_ci break; 24162306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_RESPONSE: 24262306a36Sopenharmony_ci if (rxrpc_to_client(sp)) 24362306a36Sopenharmony_ci return just_discard; 24462306a36Sopenharmony_ci break; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* Packet types 9-11 should just be ignored. */ 24762306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_PARAMS: 24862306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_10: 24962306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_11: 25062306a36Sopenharmony_ci return just_discard; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci default: 25362306a36Sopenharmony_ci return rxrpc_bad_message(skb, rxrpc_badmsg_unsupported_packet); 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (sp->hdr.serviceId == 0) 25762306a36Sopenharmony_ci return rxrpc_bad_message(skb, rxrpc_badmsg_zero_service); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (WARN_ON_ONCE(rxrpc_extract_addr_from_skb(&peer_srx, skb) < 0)) 26062306a36Sopenharmony_ci return just_discard; /* Unsupported address type. */ 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (peer_srx.transport.family != local->srx.transport.family && 26362306a36Sopenharmony_ci (peer_srx.transport.family == AF_INET && 26462306a36Sopenharmony_ci local->srx.transport.family != AF_INET6)) { 26562306a36Sopenharmony_ci pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n", 26662306a36Sopenharmony_ci peer_srx.transport.family, 26762306a36Sopenharmony_ci local->srx.transport.family); 26862306a36Sopenharmony_ci return just_discard; /* Wrong address type. */ 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci if (rxrpc_to_client(sp)) { 27262306a36Sopenharmony_ci rcu_read_lock(); 27362306a36Sopenharmony_ci conn = rxrpc_find_client_connection_rcu(local, &peer_srx, skb); 27462306a36Sopenharmony_ci conn = rxrpc_get_connection_maybe(conn, rxrpc_conn_get_call_input); 27562306a36Sopenharmony_ci rcu_read_unlock(); 27662306a36Sopenharmony_ci if (!conn) 27762306a36Sopenharmony_ci return rxrpc_protocol_error(skb, rxrpc_eproto_no_client_conn); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci ret = rxrpc_input_packet_on_conn(conn, &peer_srx, skb); 28062306a36Sopenharmony_ci rxrpc_put_connection(conn, rxrpc_conn_put_call_input); 28162306a36Sopenharmony_ci return ret; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* We need to look up service connections by the full protocol 28562306a36Sopenharmony_ci * parameter set. We look up the peer first as an intermediate step 28662306a36Sopenharmony_ci * and then the connection from the peer's tree. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci rcu_read_lock(); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci peer = rxrpc_lookup_peer_rcu(local, &peer_srx); 29162306a36Sopenharmony_ci if (!peer) { 29262306a36Sopenharmony_ci rcu_read_unlock(); 29362306a36Sopenharmony_ci return rxrpc_new_incoming_call(local, NULL, NULL, &peer_srx, skb); 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci conn = rxrpc_find_service_conn_rcu(peer, skb); 29762306a36Sopenharmony_ci conn = rxrpc_get_connection_maybe(conn, rxrpc_conn_get_call_input); 29862306a36Sopenharmony_ci if (conn) { 29962306a36Sopenharmony_ci rcu_read_unlock(); 30062306a36Sopenharmony_ci ret = rxrpc_input_packet_on_conn(conn, &peer_srx, skb); 30162306a36Sopenharmony_ci rxrpc_put_connection(conn, rxrpc_conn_put_call_input); 30262306a36Sopenharmony_ci return ret; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci peer = rxrpc_get_peer_maybe(peer, rxrpc_peer_get_input); 30662306a36Sopenharmony_ci rcu_read_unlock(); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci ret = rxrpc_new_incoming_call(local, peer, NULL, &peer_srx, skb); 30962306a36Sopenharmony_ci rxrpc_put_peer(peer, rxrpc_peer_put_input); 31062306a36Sopenharmony_ci return ret; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* 31462306a36Sopenharmony_ci * Deal with a packet that's associated with an extant connection. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_cistatic int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn, 31762306a36Sopenharmony_ci struct sockaddr_rxrpc *peer_srx, 31862306a36Sopenharmony_ci struct sk_buff *skb) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 32162306a36Sopenharmony_ci struct rxrpc_channel *chan; 32262306a36Sopenharmony_ci struct rxrpc_call *call = NULL; 32362306a36Sopenharmony_ci unsigned int channel; 32462306a36Sopenharmony_ci bool ret; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (sp->hdr.securityIndex != conn->security_ix) 32762306a36Sopenharmony_ci return rxrpc_direct_abort(skb, rxrpc_eproto_wrong_security, 32862306a36Sopenharmony_ci RXKADINCONSISTENCY, -EBADMSG); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (sp->hdr.serviceId != conn->service_id) { 33162306a36Sopenharmony_ci int old_id; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (!test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags)) 33462306a36Sopenharmony_ci return rxrpc_protocol_error(skb, rxrpc_eproto_reupgrade); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci old_id = cmpxchg(&conn->service_id, conn->orig_service_id, 33762306a36Sopenharmony_ci sp->hdr.serviceId); 33862306a36Sopenharmony_ci if (old_id != conn->orig_service_id && 33962306a36Sopenharmony_ci old_id != sp->hdr.serviceId) 34062306a36Sopenharmony_ci return rxrpc_protocol_error(skb, rxrpc_eproto_bad_upgrade); 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci if (after(sp->hdr.serial, conn->hi_serial)) 34462306a36Sopenharmony_ci conn->hi_serial = sp->hdr.serial; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* It's a connection-level packet if the call number is 0. */ 34762306a36Sopenharmony_ci if (sp->hdr.callNumber == 0) 34862306a36Sopenharmony_ci return rxrpc_input_conn_packet(conn, skb); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* Call-bound packets are routed by connection channel. */ 35162306a36Sopenharmony_ci channel = sp->hdr.cid & RXRPC_CHANNELMASK; 35262306a36Sopenharmony_ci chan = &conn->channels[channel]; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* Ignore really old calls */ 35562306a36Sopenharmony_ci if (sp->hdr.callNumber < chan->last_call) 35662306a36Sopenharmony_ci return just_discard; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (sp->hdr.callNumber == chan->last_call) { 35962306a36Sopenharmony_ci if (chan->call || 36062306a36Sopenharmony_ci sp->hdr.type == RXRPC_PACKET_TYPE_ABORT) 36162306a36Sopenharmony_ci return just_discard; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* For the previous service call, if completed successfully, we 36462306a36Sopenharmony_ci * discard all further packets. 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_ci if (rxrpc_conn_is_service(conn) && 36762306a36Sopenharmony_ci chan->last_type == RXRPC_PACKET_TYPE_ACK) 36862306a36Sopenharmony_ci return just_discard; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci /* But otherwise we need to retransmit the final packet from 37162306a36Sopenharmony_ci * data cached in the connection record. 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA) 37462306a36Sopenharmony_ci trace_rxrpc_rx_data(chan->call_debug_id, 37562306a36Sopenharmony_ci sp->hdr.seq, 37662306a36Sopenharmony_ci sp->hdr.serial, 37762306a36Sopenharmony_ci sp->hdr.flags); 37862306a36Sopenharmony_ci rxrpc_conn_retransmit_call(conn, skb, channel); 37962306a36Sopenharmony_ci return just_discard; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci call = rxrpc_try_get_call(chan->call, rxrpc_call_get_input); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if (sp->hdr.callNumber > chan->call_id) { 38562306a36Sopenharmony_ci if (rxrpc_to_client(sp)) { 38662306a36Sopenharmony_ci rxrpc_put_call(call, rxrpc_call_put_input); 38762306a36Sopenharmony_ci return rxrpc_protocol_error(skb, 38862306a36Sopenharmony_ci rxrpc_eproto_unexpected_implicit_end); 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (call) { 39262306a36Sopenharmony_ci rxrpc_implicit_end_call(call, skb); 39362306a36Sopenharmony_ci rxrpc_put_call(call, rxrpc_call_put_input); 39462306a36Sopenharmony_ci call = NULL; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (!call) { 39962306a36Sopenharmony_ci if (rxrpc_to_client(sp)) 40062306a36Sopenharmony_ci return rxrpc_protocol_error(skb, rxrpc_eproto_no_client_call); 40162306a36Sopenharmony_ci return rxrpc_new_incoming_call(conn->local, conn->peer, conn, 40262306a36Sopenharmony_ci peer_srx, skb); 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci ret = rxrpc_input_call_event(call, skb); 40662306a36Sopenharmony_ci rxrpc_put_call(call, rxrpc_call_put_input); 40762306a36Sopenharmony_ci return ret; 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci/* 41162306a36Sopenharmony_ci * I/O and event handling thread. 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_ciint rxrpc_io_thread(void *data) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci struct rxrpc_connection *conn; 41662306a36Sopenharmony_ci struct sk_buff_head rx_queue; 41762306a36Sopenharmony_ci struct rxrpc_local *local = data; 41862306a36Sopenharmony_ci struct rxrpc_call *call; 41962306a36Sopenharmony_ci struct sk_buff *skb; 42062306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY 42162306a36Sopenharmony_ci ktime_t now; 42262306a36Sopenharmony_ci#endif 42362306a36Sopenharmony_ci bool should_stop; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci complete(&local->io_thread_ready); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci skb_queue_head_init(&rx_queue); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci set_user_nice(current, MIN_NICE); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci for (;;) { 43262306a36Sopenharmony_ci rxrpc_inc_stat(local->rxnet, stat_io_loop); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci /* Deal with connections that want immediate attention. */ 43562306a36Sopenharmony_ci conn = list_first_entry_or_null(&local->conn_attend_q, 43662306a36Sopenharmony_ci struct rxrpc_connection, 43762306a36Sopenharmony_ci attend_link); 43862306a36Sopenharmony_ci if (conn) { 43962306a36Sopenharmony_ci spin_lock_bh(&local->lock); 44062306a36Sopenharmony_ci list_del_init(&conn->attend_link); 44162306a36Sopenharmony_ci spin_unlock_bh(&local->lock); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci rxrpc_input_conn_event(conn, NULL); 44462306a36Sopenharmony_ci rxrpc_put_connection(conn, rxrpc_conn_put_poke); 44562306a36Sopenharmony_ci continue; 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER, 44962306a36Sopenharmony_ci &local->client_conn_flags)) 45062306a36Sopenharmony_ci rxrpc_discard_expired_client_conns(local); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* Deal with calls that want immediate attention. */ 45362306a36Sopenharmony_ci if ((call = list_first_entry_or_null(&local->call_attend_q, 45462306a36Sopenharmony_ci struct rxrpc_call, 45562306a36Sopenharmony_ci attend_link))) { 45662306a36Sopenharmony_ci spin_lock_bh(&local->lock); 45762306a36Sopenharmony_ci list_del_init(&call->attend_link); 45862306a36Sopenharmony_ci spin_unlock_bh(&local->lock); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci trace_rxrpc_call_poked(call); 46162306a36Sopenharmony_ci rxrpc_input_call_event(call, NULL); 46262306a36Sopenharmony_ci rxrpc_put_call(call, rxrpc_call_put_poke); 46362306a36Sopenharmony_ci continue; 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (!list_empty(&local->new_client_calls)) 46762306a36Sopenharmony_ci rxrpc_connect_client_calls(local); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* Process received packets and errors. */ 47062306a36Sopenharmony_ci if ((skb = __skb_dequeue(&rx_queue))) { 47162306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 47262306a36Sopenharmony_ci switch (skb->mark) { 47362306a36Sopenharmony_ci case RXRPC_SKB_MARK_PACKET: 47462306a36Sopenharmony_ci skb->priority = 0; 47562306a36Sopenharmony_ci if (!rxrpc_input_packet(local, &skb)) 47662306a36Sopenharmony_ci rxrpc_reject_packet(local, skb); 47762306a36Sopenharmony_ci trace_rxrpc_rx_done(skb->mark, skb->priority); 47862306a36Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_put_input); 47962306a36Sopenharmony_ci break; 48062306a36Sopenharmony_ci case RXRPC_SKB_MARK_ERROR: 48162306a36Sopenharmony_ci rxrpc_input_error(local, skb); 48262306a36Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_put_error_report); 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci case RXRPC_SKB_MARK_SERVICE_CONN_SECURED: 48562306a36Sopenharmony_ci rxrpc_input_conn_event(sp->conn, skb); 48662306a36Sopenharmony_ci rxrpc_put_connection(sp->conn, rxrpc_conn_put_poke); 48762306a36Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_put_conn_secured); 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci default: 49062306a36Sopenharmony_ci WARN_ON_ONCE(1); 49162306a36Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_put_unknown); 49262306a36Sopenharmony_ci break; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci continue; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* Inject a delay into packets if requested. */ 49862306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY 49962306a36Sopenharmony_ci now = ktime_get_real(); 50062306a36Sopenharmony_ci while ((skb = skb_peek(&local->rx_delay_queue))) { 50162306a36Sopenharmony_ci if (ktime_before(now, skb->tstamp)) 50262306a36Sopenharmony_ci break; 50362306a36Sopenharmony_ci skb = skb_dequeue(&local->rx_delay_queue); 50462306a36Sopenharmony_ci skb_queue_tail(&local->rx_queue, skb); 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci#endif 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (!skb_queue_empty(&local->rx_queue)) { 50962306a36Sopenharmony_ci spin_lock_irq(&local->rx_queue.lock); 51062306a36Sopenharmony_ci skb_queue_splice_tail_init(&local->rx_queue, &rx_queue); 51162306a36Sopenharmony_ci spin_unlock_irq(&local->rx_queue.lock); 51262306a36Sopenharmony_ci continue; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 51662306a36Sopenharmony_ci should_stop = kthread_should_stop(); 51762306a36Sopenharmony_ci if (!skb_queue_empty(&local->rx_queue) || 51862306a36Sopenharmony_ci !list_empty(&local->call_attend_q) || 51962306a36Sopenharmony_ci !list_empty(&local->conn_attend_q) || 52062306a36Sopenharmony_ci !list_empty(&local->new_client_calls) || 52162306a36Sopenharmony_ci test_bit(RXRPC_CLIENT_CONN_REAP_TIMER, 52262306a36Sopenharmony_ci &local->client_conn_flags)) { 52362306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 52462306a36Sopenharmony_ci continue; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (should_stop) 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY 53162306a36Sopenharmony_ci skb = skb_peek(&local->rx_delay_queue); 53262306a36Sopenharmony_ci if (skb) { 53362306a36Sopenharmony_ci unsigned long timeout; 53462306a36Sopenharmony_ci ktime_t tstamp = skb->tstamp; 53562306a36Sopenharmony_ci ktime_t now = ktime_get_real(); 53662306a36Sopenharmony_ci s64 delay_ns = ktime_to_ns(ktime_sub(tstamp, now)); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (delay_ns <= 0) { 53962306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 54062306a36Sopenharmony_ci continue; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci timeout = nsecs_to_jiffies(delay_ns); 54462306a36Sopenharmony_ci timeout = max(timeout, 1UL); 54562306a36Sopenharmony_ci schedule_timeout(timeout); 54662306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 54762306a36Sopenharmony_ci continue; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci#endif 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci schedule(); 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 55562306a36Sopenharmony_ci rxrpc_see_local(local, rxrpc_local_stop); 55662306a36Sopenharmony_ci rxrpc_destroy_local(local); 55762306a36Sopenharmony_ci local->io_thread = NULL; 55862306a36Sopenharmony_ci rxrpc_see_local(local, rxrpc_local_stopped); 55962306a36Sopenharmony_ci return 0; 56062306a36Sopenharmony_ci} 561