* shut down and the local endpoint from going away, thus sk_user_data will not
  * be cleared until this function returns.
  */
-void rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
+int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 {
        struct rxrpc_connection *conn;
        struct rxrpc_channel *chan;
 
        _enter("%p", udp_sk);
 
+       if (skb->tstamp == 0)
+               skb->tstamp = ktime_get_real();
+
+       rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+
+       skb_pull(skb, sizeof(struct udphdr));
+
        /* The UDP protocol already released all skb resources;
         * we are free to add our own data there.
         */
                static int lose;
                if ((lose++ & 7) == 7) {
                        trace_rxrpc_rx_lose(sp);
-                       rxrpc_lose_skb(skb, rxrpc_skb_rx_lost);
-                       return;
+                       rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
+                       return 0;
                }
        }
 
        rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
 out:
        trace_rxrpc_rx_done(0, 0);
-       return;
+       return 0;
 
 out_unlock:
        rcu_read_unlock();
        trace_rxrpc_rx_done(skb->mark, skb->priority);
        rxrpc_reject_packet(local, skb);
        _leave(" [badmsg]");
-}
-
-void rxrpc_data_ready(struct sock *udp_sk)
-{
-       struct sk_buff *skb;
-       int ret;
-
-       for (;;) {
-               skb = skb_recv_udp(udp_sk, 0, 1, &ret);
-               if (!skb) {
-                       if (ret == -EAGAIN)
-                               return;
-
-                       /* If there was a transmission failure, we get an error
-                        * here that we need to ignore.
-                        */
-                       _debug("UDP socket error %d", ret);
-                       continue;
-               }
-
-               rxrpc_new_skb(skb, rxrpc_skb_rx_received);
-
-               /* we'll probably need to checksum it (didn't call sock_recvmsg) */
-               if (skb_checksum_complete(skb)) {
-                       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
-                       __UDP_INC_STATS(sock_net(udp_sk), UDP_MIB_INERRORS, 0);
-                       _debug("csum failed");
-                       continue;
-               }
-
-               __UDP_INC_STATS(sock_net(udp_sk), UDP_MIB_INDATAGRAMS, 0);
-
-               rxrpc_input_packet(udp_sk, skb);
-       }
+       return 0;
 }
 
 #include <linux/ip.h>
 #include <linux/hashtable.h>
 #include <net/sock.h>
+#include <net/udp.h>
 #include <net/af_rxrpc.h>
 #include "ar-internal.h"
 
  */
 static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
 {
-       struct sock *sock;
+       struct sock *usk;
        int ret, opt;
 
        _enter("%p{%d,%d}",
        }
 
        /* set the socket up */
-       sock = local->socket->sk;
-       sock->sk_user_data      = local;
-       sock->sk_data_ready     = rxrpc_data_ready;
-       sock->sk_error_report   = rxrpc_error_report;
+       usk = local->socket->sk;
+       inet_sk(usk)->mc_loop = 0;
+
+       /* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */
+       inet_inc_convert_csum(usk);
+
+       rcu_assign_sk_user_data(usk, local);
+
+       udp_sk(usk)->encap_type = UDP_ENCAP_RXRPC;
+       udp_sk(usk)->encap_rcv = rxrpc_input_packet;
+       udp_sk(usk)->encap_destroy = NULL;
+       udp_sk(usk)->gro_receive = NULL;
+       udp_sk(usk)->gro_complete = NULL;
+
+       udp_encap_enable();
+#if IS_ENABLED(CONFIG_IPV6)
+       if (local->srx.transport.family == AF_INET6)
+               udpv6_encap_enable();
+#endif
+       usk->sk_error_report = rxrpc_error_report;
 
        /* if a local address was supplied then bind it */
        if (local->srx.transport_len > sizeof(sa_family_t)) {