#endif
 
+static struct dst_entry *rxe_find_route(struct rxe_dev *rxe,
+                                       struct rxe_qp *qp,
+                                       struct rxe_av *av)
+{
+       struct dst_entry *dst = NULL;
+
+       if (qp_type(qp) == IB_QPT_RC)
+               dst = sk_dst_get(qp->sk->sk);
+
+       if (!dst || !(dst->obsolete && dst->ops->check(dst, 0))) {
+               if (dst)
+                       dst_release(dst);
+
+               if (av->network_type == RDMA_NETWORK_IPV4) {
+                       struct in_addr *saddr;
+                       struct in_addr *daddr;
+
+                       saddr = &av->sgid_addr._sockaddr_in.sin_addr;
+                       daddr = &av->dgid_addr._sockaddr_in.sin_addr;
+                       dst = rxe_find_route4(rxe->ndev, saddr, daddr);
+               } else if (av->network_type == RDMA_NETWORK_IPV6) {
+                       struct in6_addr *saddr6;
+                       struct in6_addr *daddr6;
+
+                       saddr6 = &av->sgid_addr._sockaddr_in6.sin6_addr;
+                       daddr6 = &av->dgid_addr._sockaddr_in6.sin6_addr;
+                       dst = rxe_find_route6(rxe->ndev, saddr6, daddr6);
+               }
+       }
+
+       return dst;
+}
+
 static int rxe_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
        struct udphdr *udph;
        skb_scrub_packet(skb, xnet);
 
        skb_clear_hash(skb);
-       skb_dst_set(skb, dst);
+       skb_dst_set(skb, dst_clone(dst));
        memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
        skb_push(skb, sizeof(struct iphdr));
 static int prepare4(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
                    struct sk_buff *skb, struct rxe_av *av)
 {
+       struct rxe_qp *qp = pkt->qp;
        struct dst_entry *dst;
        bool xnet = false;
        __be16 df = htons(IP_DF);
        struct in_addr *saddr = &av->sgid_addr._sockaddr_in.sin_addr;
        struct in_addr *daddr = &av->dgid_addr._sockaddr_in.sin_addr;
 
-       dst = rxe_find_route4(rxe->ndev, saddr, daddr);
+       dst = rxe_find_route(rxe, qp, av);
        if (!dst) {
                pr_err("Host not reachable\n");
                return -EHOSTUNREACH;
 
        prepare_ipv4_hdr(dst, skb, saddr->s_addr, daddr->s_addr, IPPROTO_UDP,
                         av->grh.traffic_class, av->grh.hop_limit, df, xnet);
+
+       if (qp_type(qp) == IB_QPT_RC)
+               sk_dst_set(qp->sk->sk, dst);
+       else
+               dst_release(dst);
+
        return 0;
 }
 
 static int prepare6(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
                    struct sk_buff *skb, struct rxe_av *av)
 {
-       struct dst_entry *dst;
+       struct rxe_qp *qp = pkt->qp;
+       struct dst_entry *dst = NULL;
        struct in6_addr *saddr = &av->sgid_addr._sockaddr_in6.sin6_addr;
        struct in6_addr *daddr = &av->dgid_addr._sockaddr_in6.sin6_addr;
 
-       dst = rxe_find_route6(rxe->ndev, saddr, daddr);
+       dst = rxe_find_route(rxe, qp, av);
        if (!dst) {
                pr_err("Host not reachable\n");
                return -EHOSTUNREACH;
        prepare_ipv6_hdr(dst, skb, saddr, daddr, IPPROTO_UDP,
                         av->grh.traffic_class,
                         av->grh.hop_limit);
+
+       if (qp_type(qp) == IB_QPT_RC)
+               sk_dst_set(qp->sk->sk, dst);
+       else
+               dst_release(dst);
+
        return 0;
 }