Sean, Roland

Here is the updated patch that Jason and I discussed last week.

rdma_resolve_addr() returns an error when attempting to resolve ipv6
link-local address.  This patch fixes the handling of link-local address.

The patch was tested using rping run as such:

Link-local with scope:
# /usr/bin/rping -c -a <remote-system-link-local>%ib0

Link-local w/out scope: (expect failure)
# /usr/bin/rping -c -a <remote-system-link-local>
rdma_resolve_addr error -1

Own interface link local:
# /usr/bin/rping -c -a <remote-system-link-local>%ib0

Other ipv6 address:
# /usr/bin/rping -c -a 2001:db8:1234::2

(server side started with rping -s -P -v -a ::0)

Tested against ofed build OFED-1.5-20091019-0811 and kernel 2.6.30.

Signed-off-by: David Wilder <dwil...@us.ibm.com>

------------------------------------------------------
 drivers/infiniband/core/addr.c |   25 ++++++++++++++++++++++---
 1 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index bd07803..3442256 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -278,6 +278,21 @@ static int addr6_resolve_remote(struct sockaddr_in6 
*src_in,
        fl.nl_u.ip6_u.daddr = dst_in->sin6_addr;
        fl.nl_u.ip6_u.saddr = src_in->sin6_addr;
 
+       if (ipv6_addr_type(&src_in->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
+               if (!src_in->sin6_scope_id)
+                       return -EINVAL;
+               fl.oif = src_in->sin6_scope_id;
+       }
+       if (ipv6_addr_type(&dst_in->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
+               if (dst_in->sin6_scope_id) {
+                       if (fl.oif && fl.oif != dst_in->sin6_scope_id)
+                               return -EINVAL;
+                       fl.oif = dst_in->sin6_scope_id;
+               }
+               if (!fl.oif)
+                       return -EINVAL;
+       }
+
        dst = ip6_route_output(&init_net, NULL, &fl);
        if (!dst)
                return ret;
@@ -390,14 +405,16 @@ static int addr_resolve_local(struct sockaddr *src_in,
        case AF_INET6:
        {
                struct in6_addr *a;
+               int found = 0;
 
                for_each_netdev(&init_net, dev)
                        if (ipv6_chk_addr(&init_net,
                                          &((struct sockaddr_in6 *) 
dst_in)->sin6_addr,
-                                         dev, 1))
+                                         dev, 1)) {
+                               found = 1;
                                break;
-
-               if (!dev)
+                       }
+               if (!found)
                        return -EADDRNOTAVAIL;
 
                a = &((struct sockaddr_in6 *) src_in)->sin6_addr;
@@ -406,6 +423,8 @@ static int addr_resolve_local(struct sockaddr *src_in,
                        src_in->sa_family = dst_in->sa_family;
                        ((struct sockaddr_in6 *) src_in)->sin6_addr =
                                ((struct sockaddr_in6 *) dst_in)->sin6_addr;
+                       ((struct sockaddr_in6 *) src_in)->sin6_scope_id =
+                               ((struct sockaddr_in6 *) dst_in)->sin6_scope_id;
                        ret = rdma_copy_addr(addr, dev, dev->dev_addr);
                } else if (ipv6_addr_loopback(a)) {
                        ret = rdma_translate_ip(dst_in, addr);


_______________________________________________
ewg mailing list
ewg@lists.openfabrics.org
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ewg

Reply via email to