aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/sw/rxe/rxe_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/sw/rxe/rxe_net.c')
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index d8610960630a..c3a140ed4df2 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -84,34 +84,6 @@ struct rxe_dev *get_rxe_by_name(const char *name)
struct rxe_recv_sockets recv_sockets;
-static __be64 rxe_mac_to_eui64(struct net_device *ndev)
-{
- unsigned char *mac_addr = ndev->dev_addr;
- __be64 eui64;
- unsigned char *dst = (unsigned char *)&eui64;
-
- dst[0] = mac_addr[0] ^ 2;
- dst[1] = mac_addr[1];
- dst[2] = mac_addr[2];
- dst[3] = 0xff;
- dst[4] = 0xfe;
- dst[5] = mac_addr[3];
- dst[6] = mac_addr[4];
- dst[7] = mac_addr[5];
-
- return eui64;
-}
-
-__be64 rxe_node_guid(struct rxe_dev *rxe)
-{
- return rxe_mac_to_eui64(rxe->ndev);
-}
-
-__be64 rxe_port_guid(struct rxe_dev *rxe)
-{
- return rxe_mac_to_eui64(rxe->ndev);
-}
-
struct device *rxe_dma_device(struct rxe_dev *rxe)
{
struct net_device *ndev;
@@ -210,6 +182,39 @@ static struct dst_entry *rxe_find_route6(struct net_device *ndev,
#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;
@@ -301,7 +306,7 @@ static void prepare_ipv4_hdr(struct dst_entry *dst, struct sk_buff *skb,
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));
@@ -349,13 +354,14 @@ static void prepare_ipv6_hdr(struct dst_entry *dst, struct sk_buff *skb,
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;
@@ -369,17 +375,24 @@ static int prepare4(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
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;
@@ -394,6 +407,12 @@ static int prepare6(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
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;
}