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 <[EMAIL PROTECTED]>
---
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);
 


_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to