Add support to the userspace RDMA CM library for joining multicast group
based on IP addressing.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>
---
diff -up svn3/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma_abi.h
svn/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma_abi.h
--- svn3/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma_abi.h 
2006-06-06 17:35:31.000000000 -0700
+++ svn/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma_abi.h  
2006-06-12 10:16:44.598117880 -0700
@@ -60,7 +60,9 @@ enum {
        UCMA_CMD_GET_EVENT,
        UCMA_CMD_GET_OPTION,
        UCMA_CMD_SET_OPTION,
-       UCMA_CMD_GET_DST_ATTR
+       UCMA_CMD_GET_DST_ATTR,
+       UCMA_CMD_JOIN_MCAST,
+       UCMA_CMD_LEAVE_MCAST
 };
 
 struct ucma_abi_cmd_hdr {
@@ -178,6 +180,17 @@ struct ucma_abi_init_qp_attr {
        __u32 qp_state;
 };
 
+struct ucma_abi_join_mcast {
+       __u32 id;
+       struct sockaddr_in6 addr;
+       __u64 uid;
+};
+
+struct ucma_abi_leave_mcast {
+       __u32 id;
+       struct sockaddr_in6 addr;
+};
+
 struct ucma_abi_dst_attr_resp {
        __u32 remote_qpn;
        __u32 remote_qkey;
diff -up svn3/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma.h
svn/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma.h
--- svn3/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma.h     
2006-06-06 17:35:31.000000000 -0700
+++ svn/gen2/trunk/src/userspace/librdmacm/include/rdma/rdma_cma.h      
2006-06-06 12:26:21.000000000 -0700
@@ -52,6 +52,8 @@ enum rdma_cm_event_type {
        RDMA_CM_EVENT_ESTABLISHED,
        RDMA_CM_EVENT_DISCONNECTED,
        RDMA_CM_EVENT_DEVICE_REMOVAL,
+       RDMA_CM_EVENT_MULTICAST_JOIN,
+       RDMA_CM_EVENT_MULTICAST_ERROR
 };
 
 enum rdma_port_space {
@@ -99,6 +101,13 @@ struct rdma_cm_id {
        uint8_t                  port_num;
 };
 
+struct rdma_multicast_data {
+       void            *context;
+       struct sockaddr addr;
+       uint8_t         pad[sizeof(struct sockaddr_in6) -
+                           sizeof(struct sockaddr)];
+};
+
 struct rdma_cm_event {
        struct rdma_cm_id       *id;
        struct rdma_cm_id       *listen_id;
@@ -245,6 +254,24 @@ int rdma_reject(struct rdma_cm_id *id, c
 int rdma_disconnect(struct rdma_cm_id *id);
 
 /**
+ * rdma_join_multicast - Join the multicast group specified by the given
+ *   address.
+ * @id: Communication identifier associated with the request.
+ * @addr: Multicast address identifying the group to join.
+ * @context: User-defined context associated with the join request.  The
+ *   context is returned to the user through the private_data field in
+ *   the rdma_cm_event.
+ */
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+                       void *context);
+
+/**
+ * rdma_leave_multicast - Leave the multicast group specified by the given
+ *   address.
+ */
+int rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);
+
+/**
  * rdma_get_cm_event - Retrieves the next pending communications event,
  *   if no event is pending waits for an event.
  * @channel: Event channel to check for events.
diff -up svn3/gen2/trunk/src/userspace/librdmacm/src/cma.c 
svn/gen2/trunk/src/userspace/librdmacm/src/cma.c
--- svn3/gen2/trunk/src/userspace/librdmacm/src/cma.c   2006-06-06 
17:35:31.000000000 -0700
+++ svn/gen2/trunk/src/userspace/librdmacm/src/cma.c    2006-06-06 
17:30:17.000000000 -0700
@@ -896,6 +896,66 @@ int rdma_disconnect(struct rdma_cm_id *i
        return 0;
 }
 
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+                       void *context)
+{
+       struct ucma_abi_join_mcast *cmd;
+       struct cma_id_private *id_priv;
+       void *msg;
+       int ret, size, addrlen;
+       
+       addrlen = ucma_addrlen(addr);
+       if (!addrlen)
+               return -EINVAL;
+
+       CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_JOIN_MCAST, size);
+       id_priv = container_of(id, struct cma_id_private, id);
+       cmd->id = id_priv->handle;
+       memcpy(&cmd->addr, addr, addrlen);
+       cmd->uid = (uintptr_t) context;
+
+       ret = write(id->channel->fd, msg, size);
+       if (ret != size)
+               return (ret > 0) ? -ENODATA : ret;
+
+       return 0;
+}
+
+int rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+       struct ucma_abi_leave_mcast *cmd;
+       struct cma_id_private *id_priv;
+       void *msg;
+       int ret, size, addrlen;
+       struct ibv_ah_attr ah_attr;
+       uint32_t qp_info;
+       
+       addrlen = ucma_addrlen(addr);
+       if (!addrlen)
+               return -EINVAL;
+
+       CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_LEAVE_MCAST, size);
+       id_priv = container_of(id, struct cma_id_private, id);
+       cmd->id = id_priv->handle;
+       memcpy(&cmd->addr, addr, addrlen);
+
+       if (id->qp) {
+               ret = rdma_get_dst_attr(id, addr, &ah_attr, &qp_info, &qp_info);
+               if (ret)
+                       goto out;
+
+               ret = ibv_detach_mcast(id->qp, &ah_attr.grh.dgid, ah_attr.dlid);
+               if (ret)
+                       goto out;
+       }
+       
+       ret = write(id->channel->fd, msg, size);
+       if (ret != size)
+               ret = (ret > 0) ? -ENODATA : ret;
+out:
+       return ret;
+}
+
 static void ucma_copy_event_from_kern(struct rdma_cm_event *dst,
                                      struct ucma_abi_event_resp *src)
 {
@@ -1004,6 +1064,36 @@ static int ucma_process_establish(struct
        return ret;
 }
 
+static void ucma_process_mcast(struct rdma_cm_id *id, struct rdma_cm_event 
*evt)
+{
+       struct ucma_abi_join_mcast kmc_data;
+       struct rdma_multicast_data *mc_data;
+       struct ibv_ah_attr ah_attr;
+       uint32_t qp_info;
+
+       kmc_data = *(struct ucma_abi_join_mcast *) evt->private_data;
+
+       mc_data = evt->private_data;
+       mc_data->context = (void *) (uintptr_t) kmc_data.uid;
+       memcpy(&mc_data->addr, &kmc_data.addr,
+              ucma_addrlen((struct sockaddr *) &kmc_data.addr));
+
+       if (evt->status || !id->qp)
+               return;
+
+       evt->status = rdma_get_dst_attr(id, &mc_data->addr, &ah_attr,
+                                       &qp_info, &qp_info);
+       if (evt->status)
+               goto err;
+
+       evt->status = ibv_attach_mcast(id->qp, &ah_attr.grh.dgid, ah_attr.dlid);
+       if (evt->status)
+               goto err;
+       return;
+err:
+       evt->event = RDMA_CM_EVENT_MULTICAST_ERROR;
+}
+
 int rdma_get_cm_event(struct rdma_event_channel *channel,
                      struct rdma_cm_event **event)
 {
@@ -1085,6 +1175,10 @@ retry:
                        goto retry;
                }
                break;
+       case RDMA_CM_EVENT_MULTICAST_JOIN:
+       case RDMA_CM_EVENT_MULTICAST_ERROR:
+               ucma_process_mcast(&id_priv->id, evt);
+               break;
        default:
                break;
        }
diff -up svn3/gen2/trunk/src/userspace/librdmacm/src/librdmacm.map 
svn/gen2/trunk/src/userspace/librdmacm/src/librdmacm.map
--- svn3/gen2/trunk/src/userspace/librdmacm/src/librdmacm.map   2006-06-06 
17:35:31.000000000 -0700
+++ svn/gen2/trunk/src/userspace/librdmacm/src/librdmacm.map    2006-06-01 
15:03:13.000000000 -0700
@@ -19,5 +19,7 @@ RDMACM_1.0 {
                rdma_get_option;
                rdma_set_option;
                rdma_get_dst_attr;
+               rdma_join_multicast;
+               rdma_leave_multicast;
        local: *;
 };


_______________________________________________
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