]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
ib/ipoib: improve IPv4/IPv6 mcast mapping functions
authorRolf Manderscheid <rvm@obsidianresearch.com>
Tue, 11 Dec 2007 17:10:33 +0000 (09:10 -0800)
committerSean Hefty <sean.hefty@intel.com>
Tue, 11 Dec 2007 17:10:33 +0000 (09:10 -0800)
An ipoib subnet on an IB fabric that spans multiple IB subnets can't
use link-local scope in multicast GIDs.  The existing routines that
map IP/IPv6 multicast addresses into IB link-level addresses hard-code
the scope to link-local, they also leave the partition key field
uninitialised.  This patch adds a parameter (the link-level broadcast
address) to the mapping routines allowing them to initialise both the
scope and the pkey appropriately, and fixes up the call sites.  The
next step will be to add a way to configure the scope for an ipoib device.

Signed-off-by: Rolf Manderscheid <rvm@obsidianresearch.com>
drivers/infiniband/core/cma.c
include/net/if_inet6.h
include/net/ip.h
net/ipv4/arp.c
net/ipv6/ndisc.c

index 0751697ef984a87e7f688238a10760127fd7383f..2ebf58c9f4c099dc3030899db381fa9faf2d1ea6 100644 (file)
@@ -2598,11 +2598,9 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
                /* IPv6 address is an SA assigned MGID. */
                memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
        } else {
-               ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
+               ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map);
                if (id_priv->id.ps == RDMA_PS_UDP)
                        mc_map[7] = 0x01;       /* Use RDMA CM signature */
-               mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
-               mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
                *mgid = *(union ib_gid *) (mc_map + 4);
        }
 }
index 448eccb206384f541a43c530fa5ac3add38eb329..b24508abb8505bff87d1ba1f139f25db0f4a10e6 100644 (file)
@@ -269,18 +269,21 @@ static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
        buf[0] = 0x00;
 }
 
-static inline void ipv6_ib_mc_map(struct in6_addr *addr, char *buf)
+static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
+                                 const unsigned char *broadcast, char *buf)
 {
+       unsigned char scope = broadcast[5] & 0xF;
+
        buf[0]  = 0;            /* Reserved */
        buf[1]  = 0xff;         /* Multicast QPN */
        buf[2]  = 0xff;
        buf[3]  = 0xff;
        buf[4]  = 0xff;
-       buf[5]  = 0x12;         /* link local scope */
+       buf[5]  = 0x10 | scope; /* scope from broadcast address */
        buf[6]  = 0x60;         /* IPv6 signature */
        buf[7]  = 0x1b;
-       buf[8]  = 0;            /* P_Key */
-       buf[9]  = 0;
+       buf[8]  = broadcast[8]; /* P_Key */
+       buf[9]  = broadcast[9];
        memcpy(buf + 10, addr->s6_addr + 6, 10);
 }
 #endif
index 840dd91b513b0ec5000738af3773eda478bba13b..50c8889b1b8d7e6625cf4580a673c9a516e27bfd 100644 (file)
@@ -266,20 +266,22 @@ static inline void ip_eth_mc_map(__be32 naddr, char *buf)
  *     Leave P_Key as 0 to be filled in by driver.
  */
 
-static inline void ip_ib_mc_map(__be32 naddr, char *buf)
+static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
 {
        __u32 addr;
+       unsigned char scope = broadcast[5] & 0xF;
+
        buf[0]  = 0;            /* Reserved */
        buf[1]  = 0xff;         /* Multicast QPN */
        buf[2]  = 0xff;
        buf[3]  = 0xff;
        addr    = ntohl(naddr);
        buf[4]  = 0xff;
-       buf[5]  = 0x12;         /* link local scope */
+       buf[5]  = 0x10 | scope; /* scope from broadcast address */
        buf[6]  = 0x40;         /* IPv4 signature */
        buf[7]  = 0x1b;
-       buf[8]  = 0;            /* P_Key */
-       buf[9]  = 0;
+       buf[8]  = broadcast[8];         /* P_Key */
+       buf[9]  = broadcast[9];
        buf[10] = 0;
        buf[11] = 0;
        buf[12] = 0;
index 36d6798947b59026eb400c6b06882099fddd8ba0..3a0786479f4d78cdb17cfeaf2aab05d0637ac254 100644 (file)
@@ -215,7 +215,7 @@ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
                ip_tr_mc_map(addr, haddr);
                return 0;
        case ARPHRD_INFINIBAND:
-               ip_ib_mc_map(addr, haddr);
+               ip_ib_mc_map(addr, dev->broadcast, haddr);
                return 0;
        default:
                if (dir) {
index 67997a74ddce15d85e43c8146a9ed62f91085f77..6d54f7eb8e90bdc38ced78a4d1c21194dc8b668e 100644 (file)
@@ -337,7 +337,7 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d
                ipv6_arcnet_mc_map(addr, buf);
                return 0;
        case ARPHRD_INFINIBAND:
-               ipv6_ib_mc_map(addr, buf);
+               ipv6_ib_mc_map(addr, dev->broadcast, buf);
                return 0;
        default:
                if (dir) {