[openib-general] [PATCH] multicast: add support for MGID 0

Sean Hefty sean.hefty at intel.com
Wed Jul 26 17:10:26 PDT 2006


Add support to join a multicast group with MGID = 0, with the actual
MGID of the group returned by the SA.  The multicast module must be able
to handle multiple requests for MGID = 0, with each request causing a
new multicast group to be created.

Also enhance the API for ib_get_mcmember_rec() to support a requested
MGID of 0.  In this case, a default MCMemberRecord is returned to the
user and may be used when creating a new multicast group.  Currently,
the default values are hard-coded by the multicast module, but that can
be extended in the future or overridden by the user before creating
the group.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
Index: include/rdma/ib_multicast.h
===================================================================
--- include/rdma/ib_multicast.h	(revision 8647)
+++ include/rdma/ib_multicast.h	(working copy)
@@ -88,8 +88,13 @@ void ib_free_multicast(struct ib_multica
  * @device: Device associated with the multicast group.
  * @port_num: Port on the specified device to associate with the multicast
  *   group.
- * @mgid: MGID of multicast group.
+ * @mgid: optional MGID of multicast group.
  * @rec: Location to copy SA multicast member record.
+ *
+ * If an MGID is specified, returns an existing multicast member record if
+ * one is found for the local port.  If no MGID is specified, or the specified
+ * MGID is 0, returns a multicast member record filled in with default values
+ * that may be used to create a new multicast group.
  */
 int ib_get_mcmember_rec(struct ib_device *device, u8 port_num,
 			union ib_gid *mgid, struct ib_sa_mcmember_rec *rec);
Index: core/multicast.c
===================================================================
--- core/multicast.c	(revision 8695)
+++ core/multicast.c	(working copy)
@@ -37,8 +37,10 @@
 #include <linux/index.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/random.h>
 
 #include <rdma/ib_multicast.h>
+#include <rdma/ib_cache.h>
 
 MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("InfiniBand multicast membership handling");
@@ -63,6 +65,7 @@ static struct ib_client mcast_client = {
 
 static struct ib_event_handler	event_handler;
 static struct workqueue_struct	*mcast_wq;
+static union ib_gid mgid0;
 
 struct mcast_device;
 
@@ -144,7 +147,8 @@ static struct mcast_group *mcast_find(st
 }
 
 static struct mcast_group *mcast_insert(struct mcast_port *port,
-					struct mcast_group *group)
+					struct mcast_group *group,
+					int allow_duplicates)
 {
 	struct rb_node **link = &port->table.rb_node;
 	struct rb_node *parent = NULL;
@@ -161,6 +165,8 @@ static struct mcast_group *mcast_insert(
 			link = &(*link)->rb_left;
 		else if (ret > 0)
 			link = &(*link)->rb_right;
+		else if (allow_duplicates)
+			link = &(*link)->rb_left;
 		else
 			return cur_group;
 	}
@@ -476,6 +482,10 @@ static void join_handler(int status, str
 	else {
 		spin_lock_irq(&group->port->lock);
 		group->rec = *rec;
+		if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
+			rb_erase(&group->node, &group->port->table);
+			mcast_insert(group->port, group, 1);
+		}
 		spin_unlock_irq(&group->port->lock);
 	}
 	mcast_work_handler(group);
@@ -492,12 +502,16 @@ static struct mcast_group *acquire_group
 {
 	struct mcast_group *group, *cur_group;
 	unsigned long flags;
+	int is_mgid0;
 
-	spin_lock_irqsave(&port->lock, flags);
-	group = mcast_find(port, mgid);
-	if (group)
-		goto found;
-	spin_unlock_irqrestore(&port->lock, flags);
+	is_mgid0 = !memcmp(&mgid0, mgid, sizeof mgid0);
+	if (!is_mgid0) {
+		spin_lock_irqsave(&port->lock, flags);
+		group = mcast_find(port, mgid);
+		if (group)
+			goto found;
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
 
 	group = kzalloc(sizeof *group, gfp_mask);
 	if (!group)
@@ -511,7 +525,7 @@ static struct mcast_group *acquire_group
 	spin_lock_init(&group->lock);
 
 	spin_lock_irqsave(&port->lock, flags);
-	cur_group = mcast_insert(port, group);
+	cur_group = mcast_insert(port, group, is_mgid0);
 	if (cur_group) {
 		kfree(group);
 		group = cur_group;
@@ -619,19 +633,30 @@ int ib_get_mcmember_rec(struct ib_device
 	struct mcast_port *port;
 	struct mcast_group *group;
 	unsigned long flags;
+	int ret = 0;
 
 	dev = ib_get_client_data(device, &mcast_client);
 	if (!dev)
 		return -ENODEV;
 
 	port = &dev->port[port_num - dev->start_port];
-	spin_lock_irqsave(&port->lock, flags);
-	group = mcast_find(port, mgid);
-	if (group)
-		*rec = group->rec;
-	spin_unlock_irqrestore(&port->lock, flags);
+	if (mgid && memcmp(mgid, &mgid0, sizeof mgid0)) {
+		spin_lock_irqsave(&port->lock, flags);
+		group = mcast_find(port, mgid);
+		if (group)
+			*rec = group->rec;
+		else
+			ret = -EADDRNOTAVAIL;
+		spin_unlock_irqrestore(&port->lock, flags);
+	} else {
+		memset(rec, 0, sizeof *rec);
+		ib_get_cached_gid(device, port_num, 0, &rec->port_gid);
+		rec->pkey = 0xFFFF;
+		get_random_bytes(&rec->qkey, sizeof rec->qkey);
+		rec->join_state = 1;
+	}
 
-	return group ? 0 : -EADDRNOTAVAIL;
+	return ret;
 }
 EXPORT_SYMBOL(ib_get_mcmember_rec);
 





More information about the general mailing list