[PATCH for-rc] IB/rxe: Improve loopback marking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently a packet is marked for loopback only if the source and
destination addresses match, This is not enough when multiple gids are
present in rxe device's gid table and the traffic is from one gid to
another, this patch fixes this by marking the packet for loopback if the
destination address found in the rxe's netdevice address list.

Fixes: 8700e3e7c485 ("Soft RoCE driver")
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@xxxxxxxxx>
Signed-off-by: Kamal Heib <kamalheib1@xxxxxxxxx>
---
 drivers/infiniband/sw/rxe/rxe_net.c | 45 +++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 8fd03ae20efc..6ee984b7793b 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -368,6 +368,25 @@ static void prepare_ipv6_hdr(struct dst_entry *dst, struct sk_buff *skb,
 	ip6h->payload_len = htons(skb->len - sizeof(*ip6h));
 }
 
+static inline bool same_rxe4(struct net_device *ndev, struct in_addr *daddr)
+{
+	struct in_device *in_dev;
+	bool same_rxe = false;
+
+	in_dev = in_dev_get(ndev);
+	if (!in_dev)
+		return false;
+
+	for_ifa(in_dev)
+		if (!memcmp(&ifa->ifa_address, daddr, sizeof(*daddr))) {
+			same_rxe = true;
+			break;
+		}
+	endfor_ifa(in_dev);
+	in_dev_put(in_dev);
+	return same_rxe;
+}
+
 static int prepare4(struct rxe_pkt_info *pkt, struct sk_buff *skb,
 		    struct rxe_av *av)
 {
@@ -384,7 +403,7 @@ static int prepare4(struct rxe_pkt_info *pkt, struct sk_buff *skb,
 		return -EHOSTUNREACH;
 	}
 
-	if (!memcmp(saddr, daddr, sizeof(*daddr)))
+	if (same_rxe4(skb->dev, daddr))
 		pkt->mask |= RXE_LOOPBACK_MASK;
 
 	prepare_udp_hdr(skb, cpu_to_be16(qp->src_port),
@@ -397,6 +416,28 @@ static int prepare4(struct rxe_pkt_info *pkt, struct sk_buff *skb,
 	return 0;
 }
 
+static inline bool same_rxe6(struct net_device *ndev, struct in6_addr *daddr)
+{
+	struct inet6_dev *in6_dev;
+	struct inet6_ifaddr *ifp;
+	bool same_rxe = false;
+
+	in6_dev = in6_dev_get(ndev);
+	if (!in6_dev)
+		return false;
+
+	read_lock_bh(&in6_dev->lock);
+	list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
+		if (!memcmp(&ifp->addr, daddr, sizeof(*daddr))) {
+			same_rxe = true;
+			break;
+		}
+	}
+	read_unlock_bh(&in6_dev->lock);
+	in6_dev_put(in6_dev);
+	return same_rxe;
+}
+
 static int prepare6(struct rxe_pkt_info *pkt, struct sk_buff *skb,
 		    struct rxe_av *av)
 {
@@ -411,7 +452,7 @@ static int prepare6(struct rxe_pkt_info *pkt, struct sk_buff *skb,
 		return -EHOSTUNREACH;
 	}
 
-	if (!memcmp(saddr, daddr, sizeof(*daddr)))
+	if (same_rxe6(skb->dev, daddr))
 		pkt->mask |= RXE_LOOPBACK_MASK;
 
 	prepare_udp_hdr(skb, cpu_to_be16(qp->src_port),
-- 
2.20.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux