On Thu, Jan 24, 2019 at 04:44:34PM +0200, Kamal Heib wrote: > Currently a packet is marked for loopback only if the source and > destination addresses match, This is not enough when multiple gids are s/match,/equals. > 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. s/another, this patch fixes this/ another. Fix it > > 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); To me at first glance it is unclear why lock is not needed when traveling the v4 list. Suggesting to comment on that. > + 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; Thanks Kamal! Reviewed-by: Yuval Shaia <yuval.shaia@xxxxxxxxxx> Will give it a short test today. > > prepare_udp_hdr(skb, cpu_to_be16(qp->src_port), > -- > 2.20.1 >