Skip to content

Commit 5271953

Browse files
committed
rxrpc: Use the UDP encap_rcv hook
Use the UDP encap_rcv hook to cut the bit out of the rxrpc packet reception in which a packet is placed onto the UDP receive queue and then immediately removed again by rxrpc. Going via the queue in this manner seems like it should be unnecessary. This does, however, require the invention of a value to place in encap_type as that's one of the conditions to switch packets out to the encap_rcv hook. Possibly the value doesn't actually matter for anything other than sockopts on the UDP socket, which aren't accessible outside of rxrpc anyway. This seems to cut a bit of time out of the time elapsed between each sk_buff being timestamped and turning up in rxrpc (the final number in the following trace excerpts). I measured this by making the rxrpc_rx_packet trace point print the time elapsed between the skb being timestamped and the current time (in ns), e.g.: ... 424.278721: rxrpc_rx_packet: ... ACK 25026 So doing a 512MiB DIO read from my test server, with an unmodified kernel: N min max sum mean stddev 27605 2626 7581 7.83992e+07 2840.04 181.029 and with the patch applied: N min max sum mean stddev 27547 1895 12165 6.77461e+07 2459.29 255.02 Signed-off-by: David Howells <[email protected]>
1 parent 2cfa227 commit 5271953

File tree

4 files changed

+36
-44
lines changed

4 files changed

+36
-44
lines changed

include/uapi/linux/udp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,6 @@ struct udphdr {
4040
#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
4141
#define UDP_ENCAP_GTP0 4 /* GSM TS 09.60 */
4242
#define UDP_ENCAP_GTP1U 5 /* 3GPP TS 29.060 */
43+
#define UDP_ENCAP_RXRPC 6
4344

4445
#endif /* _UAPI_LINUX_UDP_H */

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
966966
/*
967967
* input.c
968968
*/
969-
void rxrpc_data_ready(struct sock *);
969+
int rxrpc_input_packet(struct sock *, struct sk_buff *);
970970

971971
/*
972972
* insecure.c

net/rxrpc/input.c

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb)
11211121
* shut down and the local endpoint from going away, thus sk_user_data will not
11221122
* be cleared until this function returns.
11231123
*/
1124-
void rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
1124+
int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
11251125
{
11261126
struct rxrpc_connection *conn;
11271127
struct rxrpc_channel *chan;
@@ -1135,6 +1135,13 @@ void rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
11351135

11361136
_enter("%p", udp_sk);
11371137

1138+
if (skb->tstamp == 0)
1139+
skb->tstamp = ktime_get_real();
1140+
1141+
rxrpc_new_skb(skb, rxrpc_skb_rx_received);
1142+
1143+
skb_pull(skb, sizeof(struct udphdr));
1144+
11381145
/* The UDP protocol already released all skb resources;
11391146
* we are free to add our own data there.
11401147
*/
@@ -1148,8 +1155,8 @@ void rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
11481155
static int lose;
11491156
if ((lose++ & 7) == 7) {
11501157
trace_rxrpc_rx_lose(sp);
1151-
rxrpc_lose_skb(skb, rxrpc_skb_rx_lost);
1152-
return;
1158+
rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
1159+
return 0;
11531160
}
11541161
}
11551162

@@ -1332,7 +1339,7 @@ void rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
13321339
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
13331340
out:
13341341
trace_rxrpc_rx_done(0, 0);
1335-
return;
1342+
return 0;
13361343

13371344
out_unlock:
13381345
rcu_read_unlock();
@@ -1371,38 +1378,5 @@ void rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
13711378
trace_rxrpc_rx_done(skb->mark, skb->priority);
13721379
rxrpc_reject_packet(local, skb);
13731380
_leave(" [badmsg]");
1374-
}
1375-
1376-
void rxrpc_data_ready(struct sock *udp_sk)
1377-
{
1378-
struct sk_buff *skb;
1379-
int ret;
1380-
1381-
for (;;) {
1382-
skb = skb_recv_udp(udp_sk, 0, 1, &ret);
1383-
if (!skb) {
1384-
if (ret == -EAGAIN)
1385-
return;
1386-
1387-
/* If there was a transmission failure, we get an error
1388-
* here that we need to ignore.
1389-
*/
1390-
_debug("UDP socket error %d", ret);
1391-
continue;
1392-
}
1393-
1394-
rxrpc_new_skb(skb, rxrpc_skb_rx_received);
1395-
1396-
/* we'll probably need to checksum it (didn't call sock_recvmsg) */
1397-
if (skb_checksum_complete(skb)) {
1398-
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
1399-
__UDP_INC_STATS(sock_net(udp_sk), UDP_MIB_INERRORS, 0);
1400-
_debug("csum failed");
1401-
continue;
1402-
}
1403-
1404-
__UDP_INC_STATS(sock_net(udp_sk), UDP_MIB_INDATAGRAMS, 0);
1405-
1406-
rxrpc_input_packet(udp_sk, skb);
1407-
}
1381+
return 0;
14081382
}

net/rxrpc/local_object.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/ip.h>
2020
#include <linux/hashtable.h>
2121
#include <net/sock.h>
22+
#include <net/udp.h>
2223
#include <net/af_rxrpc.h>
2324
#include "ar-internal.h"
2425

@@ -108,7 +109,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
108109
*/
109110
static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
110111
{
111-
struct sock *sock;
112+
struct sock *usk;
112113
int ret, opt;
113114

114115
_enter("%p{%d,%d}",
@@ -123,10 +124,26 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
123124
}
124125

125126
/* set the socket up */
126-
sock = local->socket->sk;
127-
sock->sk_user_data = local;
128-
sock->sk_data_ready = rxrpc_data_ready;
129-
sock->sk_error_report = rxrpc_error_report;
127+
usk = local->socket->sk;
128+
inet_sk(usk)->mc_loop = 0;
129+
130+
/* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */
131+
inet_inc_convert_csum(usk);
132+
133+
rcu_assign_sk_user_data(usk, local);
134+
135+
udp_sk(usk)->encap_type = UDP_ENCAP_RXRPC;
136+
udp_sk(usk)->encap_rcv = rxrpc_input_packet;
137+
udp_sk(usk)->encap_destroy = NULL;
138+
udp_sk(usk)->gro_receive = NULL;
139+
udp_sk(usk)->gro_complete = NULL;
140+
141+
udp_encap_enable();
142+
#if IS_ENABLED(CONFIG_IPV6)
143+
if (local->srx.transport.family == AF_INET6)
144+
udpv6_encap_enable();
145+
#endif
146+
usk->sk_error_report = rxrpc_error_report;
130147

131148
/* if a local address was supplied then bind it */
132149
if (local->srx.transport_len > sizeof(sa_family_t)) {

0 commit comments

Comments
 (0)