Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9e527e3 authored by Rolf Manderscheid's avatar Rolf Manderscheid Committed by Roland Dreier
Browse files

IPoIB: improve IPv4/IPv6 to IB mcast mapping functions



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, and 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 P_Key appropriately, and fixes up the call sites.

The next step will be to add a way to configure the scope for an IPoIB
interface.

Signed-off-by: default avatarRolf Manderscheid <rvm@obsidianresearch.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 755807a2
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -2610,11 +2610,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);
	}
}
+0 −4
Original line number Diff line number Diff line
@@ -788,10 +788,6 @@ void ipoib_mcast_restart_task(struct work_struct *work)

		memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid);

		/* Add in the P_Key */
		mgid.raw[4] = (priv->pkey >> 8) & 0xff;
		mgid.raw[5] = priv->pkey & 0xff;

		mcast = __ipoib_mcast_find(dev, &mgid);
		if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
			struct ipoib_mcast *nmcast;
+7 −4
Original line number Diff line number Diff line
@@ -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
+6 −4
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -211,7 +211,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) {
Loading