[ofa-general] [PATCH] use scope from ipoib device link-level broadcast address in MGIDs
Rolf Manderscheid
rvm at obsidianresearch.com
Tue Aug 21 16:50:43 PDT 2007
An ipoib subnet on an IB fabric that spans multiple IB subnets can't use
link-local scope in multicast GIDs. This patch takes the scope from the
link level broadcast address of the ipoib device when mapping to an IB
multicast address.
Signed-off-by: Rolf Manderscheid <rvm at obsidianresearch.com>
---
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 9ffb998..2fd1b30 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2560,7 +2560,7 @@ 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;
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 3ec7d07..b636221 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -268,14 +268,17 @@ 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 */
diff --git a/include/net/ip.h b/include/net/ip.h
index abf2820..fbb4dd0 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -266,16 +266,18 @@ 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 */
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 9ab9d53..feb643c 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -214,7 +214,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) {
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0358e60..8275625 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -308,7 +308,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) {
More information about the general
mailing list