Skip to content

Commit 446b3e1

Browse files
committed
rxrpc: Move packet reception processing into I/O thread
Split the packet input handler to make the softirq side just dump the received packet into the local endpoint receive queue and then call the remainder of the input function from the I/O thread. Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent a275da6 commit 446b3e1

File tree

5 files changed

+47
-25
lines changed

5 files changed

+47
-25
lines changed

net/rxrpc/ar-internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct rxrpc_txbuf;
3636
* to pass supplementary information.
3737
*/
3838
enum rxrpc_skb_mark {
39+
RXRPC_SKB_MARK_PACKET, /* Received packet */
3940
RXRPC_SKB_MARK_REJECT_BUSY, /* Reject with BUSY */
4041
RXRPC_SKB_MARK_REJECT_ABORT, /* Reject with ABORT (code in skb->priority) */
4142
};
@@ -957,7 +958,7 @@ void rxrpc_input_implicit_end_call(struct rxrpc_sock *, struct rxrpc_connection
957958
/*
958959
* io_thread.c
959960
*/
960-
int rxrpc_input_packet(struct sock *, struct sk_buff *);
961+
int rxrpc_encap_rcv(struct sock *, struct sk_buff *);
961962
int rxrpc_io_thread(void *data);
962963
static inline void rxrpc_wake_up_io_thread(struct rxrpc_local *local)
963964
{

net/rxrpc/call_event.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
8383
rxrpc_inc_stat(call->rxnet, stat_tx_acks[ack_reason]);
8484

8585
txb = rxrpc_alloc_txbuf(call, RXRPC_PACKET_TYPE_ACK,
86-
in_softirq() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS);
86+
rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS);
8787
if (!txb) {
8888
kleave(" = -ENOMEM");
8989
return;
@@ -111,7 +111,7 @@ void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
111111
spin_unlock_bh(&local->ack_tx_lock);
112112
trace_rxrpc_send_ack(call, why, ack_reason, serial);
113113

114-
if (in_task()) {
114+
if (!rcu_read_lock_held()) {
115115
rxrpc_transmit_ack_packets(call->peer->local);
116116
} else {
117117
rxrpc_get_local(local, rxrpc_local_get_queue);

net/rxrpc/call_object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
632632
del_timer_sync(&call->timer);
633633
cancel_work(&call->processor);
634634

635-
if (in_softirq() || work_busy(&call->processor))
635+
if (rcu_read_lock_held() || work_busy(&call->processor))
636636
/* Can't use the rxrpc workqueue as we need to cancel/flush
637637
* something that may be running/waiting there.
638638
*/

net/rxrpc/io_thread.c

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,34 @@
99

1010
#include "ar-internal.h"
1111

12+
/*
13+
* handle data received on the local endpoint
14+
* - may be called in interrupt context
15+
*
16+
* [!] Note that as this is called from the encap_rcv hook, the socket is not
17+
* held locked by the caller and nothing prevents sk_user_data on the UDP from
18+
* being cleared in the middle of processing this function.
19+
*
20+
* Called with the RCU read lock held from the IP layer via UDP.
21+
*/
22+
int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
23+
{
24+
struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
25+
26+
if (unlikely(!local)) {
27+
kfree_skb(skb);
28+
return 0;
29+
}
30+
if (skb->tstamp == 0)
31+
skb->tstamp = ktime_get_real();
32+
33+
skb->mark = RXRPC_SKB_MARK_PACKET;
34+
rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
35+
skb_queue_tail(&local->rx_queue, skb);
36+
rxrpc_wake_up_io_thread(local);
37+
return 0;
38+
}
39+
1240
/*
1341
* post connection-level events to the connection
1442
* - this includes challenges, responses, some aborts and call terminal packet
@@ -98,18 +126,10 @@ static bool rxrpc_extract_abort(struct sk_buff *skb)
98126
}
99127

100128
/*
101-
* handle data received on the local endpoint
102-
* - may be called in interrupt context
103-
*
104-
* [!] Note that as this is called from the encap_rcv hook, the socket is not
105-
* held locked by the caller and nothing prevents sk_user_data on the UDP from
106-
* being cleared in the middle of processing this function.
107-
*
108-
* Called with the RCU read lock held from the IP layer via UDP.
129+
* Process packets received on the local endpoint
109130
*/
110-
int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
131+
static int rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff *skb)
111132
{
112-
struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
113133
struct rxrpc_connection *conn;
114134
struct rxrpc_channel *chan;
115135
struct rxrpc_call *call = NULL;
@@ -118,17 +138,9 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
118138
struct rxrpc_sock *rx = NULL;
119139
unsigned int channel;
120140

121-
_enter("%p", udp_sk);
122-
123-
if (unlikely(!local)) {
124-
kfree_skb(skb);
125-
return 0;
126-
}
127141
if (skb->tstamp == 0)
128142
skb->tstamp = ktime_get_real();
129143

130-
rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
131-
132144
skb_pull(skb, sizeof(struct udphdr));
133145

134146
/* The UDP protocol already released all skb resources;
@@ -387,8 +399,17 @@ int rxrpc_io_thread(void *data)
387399

388400
/* Process received packets and errors. */
389401
if ((skb = __skb_dequeue(&rx_queue))) {
390-
// TODO: Input packet
391-
rxrpc_free_skb(skb, rxrpc_skb_put_input);
402+
switch (skb->mark) {
403+
case RXRPC_SKB_MARK_PACKET:
404+
rcu_read_lock();
405+
rxrpc_input_packet(local, skb);
406+
rcu_read_unlock();
407+
break;
408+
default:
409+
WARN_ON_ONCE(1);
410+
rxrpc_free_skb(skb, rxrpc_skb_put_unknown);
411+
break;
412+
}
392413
continue;
393414
}
394415

net/rxrpc/local_object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
154154
}
155155

156156
tuncfg.encap_type = UDP_ENCAP_RXRPC;
157-
tuncfg.encap_rcv = rxrpc_input_packet;
157+
tuncfg.encap_rcv = rxrpc_encap_rcv;
158158
tuncfg.encap_err_rcv = rxrpc_encap_err_rcv;
159159
tuncfg.sk_user_data = local;
160160
setup_udp_tunnel_sock(net, local->socket, &tuncfg);

0 commit comments

Comments
 (0)