The following patch updates the CMA to support the IB socket-based
protocol standard and SDP's private data format.

The CMA now defines RDMA "port spaces".  RDMA identifiers are associated
with a user-specified port space at creation time.

Please respond with any comments on the approach.  Note that these
changes have not been pushed up to userspace yet.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>



Index: ulp/iser/iser_verbs.c
===================================================================
--- ulp/iser/iser_verbs.c       (revision 4356)
+++ ulp/iser/iser_verbs.c       (working copy)
@@ -428,7 +428,8 @@ iser_connect(struct iser_conn *p_iser_co
                 return -1;
        }
        p_iser_conn->cma_id = rdma_create_id(iser_cma_handler,
-                                            (void *)p_iser_conn);
+                                            (void *)p_iser_conn,
+                                            RDMA_PS_TCP);
        if (IS_ERR(p_iser_conn->cma_id)) {
                ret = PTR_ERR(p_iser_conn->cma_id);
                iser_err("rdma_create_id failed: %d\n", ret);
Index: include/rdma/rdma_cm.h
===================================================================
--- include/rdma/rdma_cm.h      (revision 4356)
+++ include/rdma/rdma_cm.h      (working copy)
@@ -54,6 +54,13 @@ enum rdma_cm_event_type {
        RDMA_CM_EVENT_DEVICE_REMOVAL,
 };
 
+enum rdma_port_space {
+       RDMA_PS_SDP  = 0x0001,
+       RDMA_PS_TCP  = 0x0106,
+       RDMA_PS_UDP  = 0x0111,
+       RDMA_PS_SCTP = 0x0183
+};
+
 struct rdma_addr {
        struct sockaddr src_addr;
        u8              src_pad[sizeof(struct sockaddr_in6) -
@@ -97,11 +104,20 @@ struct rdma_cm_id {
        struct ib_qp            *qp;
        rdma_cm_event_handler    event_handler;
        struct rdma_route        route;
+       enum rdma_port_space     ps;
        u8                       port_num;
 };
 
+/**
+ * rdma_create_id - Create an RDMA identifier.
+ *
+ * @event_handler: User callback invoked to report events associated with the
+ *   returned rdma_id.
+ * @context: User specified context associated with the id.
+ * @ps: RDMA port space.
+ */
 struct rdma_cm_id* rdma_create_id(rdma_cm_event_handler event_handler,
-                                 void *context);
+                                 void *context, enum rdma_port_space ps);
 
 void rdma_destroy_id(struct rdma_cm_id *id);
 
Index: core/cma.c
===================================================================
--- core/cma.c  (revision 4356)
+++ core/cma.c  (working copy)
@@ -110,21 +110,35 @@ struct rdma_id_private {
        u8                      srq;
 };
 
-struct cma_addr {
-       u8 version;     /* CMA version: 7:4, IP version: 3:0 */
-       u8 reserved;
-       __u16 port;
+union cma_ip_addr {
+       struct in6_addr ip6;
        struct {
-               union {
-                       struct in6_addr ip6;
-                       struct {
-                               __u32 pad[3];
-                               __u32 addr;
-                       } ip4;
-               } ver;
-       } src_addr, dst_addr;
+               __u32 pad[3];
+               __u32 addr;
+       } ip4;
+};
+
+struct cma_hdr {
+       u8 cma_version;
+       u8 ip_version;  /* IP version: 7:4 */
+       __u16 port;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
 };
 
+struct sdp_hh {
+       u8 sdp_version;
+       u8 ip_version;  /* IP version: 7:4 */
+       u8 sdp_specific1[10];
+       __u16 port;
+       __u16 sdp_specific2;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
+};
+
+#define CMA_VERSION 0x10
+#define SDP_VERSION 0x22
+
 static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp)
 {
        unsigned long flags;
@@ -162,19 +176,24 @@ static enum cma_state cma_exch(struct rd
        return old;
 }
 
-static inline u8 cma_get_ip_ver(struct cma_addr *addr)
+static inline u8 cma_get_ip_ver(struct cma_hdr *hdr)
 {
-       return addr->version & 0xF;
+       return hdr->ip_version >> 4;
 }
 
-static inline u8 cma_get_cma_ver(struct cma_addr *addr)
+static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver)
 {
-       return addr->version >> 4;
+       hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF);
 }
 
-static inline void cma_set_vers(struct cma_addr *addr, u8 cma_ver, u8 ip_ver)
+static inline u8 sdp_get_ip_ver(struct sdp_hh *hh)
 {
-       addr->version = (cma_ver << 4) + (ip_ver & 0xF);
+       return hh->ip_version >> 4;
+}
+
+static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
+{
+       hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
 }
 
 static void cma_attach_to_dev(struct rdma_id_private *id_priv,
@@ -226,17 +245,18 @@ static void cma_release_remove(struct rd
 }
 
 struct rdma_cm_id* rdma_create_id(rdma_cm_event_handler event_handler,
-                                 void *context)
+                                 void *context, enum rdma_port_space ps)
 {
        struct rdma_id_private *id_priv;
 
        id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL);
        if (!id_priv)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        id_priv->state = CMA_IDLE;
        id_priv->id.context = context;
        id_priv->id.event_handler = event_handler;
+       id_priv->id.ps = ps;
        spin_lock_init(&id_priv->lock);
        init_waitqueue_head(&id_priv->wait);
        atomic_set(&id_priv->refcount, 1);
@@ -387,25 +407,93 @@ int rdma_init_qp_attr(struct rdma_cm_id 
 }
 EXPORT_SYMBOL(rdma_init_qp_attr);
 
-static int cma_verify_addr(struct cma_addr *addr,
-                          struct sockaddr_in *ip_addr)
+static inline int cma_any_addr(struct sockaddr *addr)
 {
-       if (cma_get_cma_ver(addr) != 1 || cma_get_ip_ver(addr) != 4)
-               return -EINVAL;
+       struct in6_addr *ip6;
 
-       if (ip_addr->sin_port != addr->port)
-               return -EINVAL;
+       if (addr->sa_family == AF_INET)
+               return ((struct sockaddr_in *) addr)->sin_addr.s_addr ==
+                       INADDR_ANY;
+       else {
+               ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
+               return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
+                       ip6->s6_addr32[3] | ip6->s6_addr32[4]) == 0;
+       }
+}
 
-       if (ip_addr->sin_addr.s_addr &&
-           (ip_addr->sin_addr.s_addr != addr->dst_addr.ver.ip4.addr))
-               return -EINVAL;
+static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
+                           u8 *ip_ver, __u16 *port,
+                           union cma_ip_addr **src, union cma_ip_addr **dst)
+{
+       switch (ps) {
+       case RDMA_PS_SDP:
+               if (((struct sdp_hh *) hdr)->sdp_version != SDP_VERSION)
+                       return -EINVAL;
 
+               *ip_ver = sdp_get_ip_ver(hdr);
+               *port   = ((struct sdp_hh *) hdr)->port;
+               *src    = &((struct sdp_hh *) hdr)->src_addr;
+               *dst    = &((struct sdp_hh *) hdr)->dst_addr;
+               break;
+       default:
+               if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)
+                       return -EINVAL;
+
+               *ip_ver = cma_get_ip_ver(hdr);
+               *port   = ((struct cma_hdr *) hdr)->port;
+               *src    = &((struct cma_hdr *) hdr)->src_addr;
+               *dst    = &((struct cma_hdr *) hdr)->dst_addr;
+               break;
+       }
        return 0;
 }
 
-static inline int cma_any_addr(struct sockaddr *addr)
+static void cma_save_net_info(struct rdma_addr *addr,
+                             struct rdma_addr *listen_addr,
+                             u8 ip_ver, __u16 port,
+                             union cma_ip_addr *src, union cma_ip_addr *dst)
+{
+       struct sockaddr_in *listen4, *ip4;
+       struct sockaddr_in6 *listen6, *ip6;
+
+       switch (ip_ver) {
+       case 4:
+               listen4 = (struct sockaddr_in *) &listen_addr->src_addr;
+               ip4 = (struct sockaddr_in *) &addr->src_addr;
+               ip4->sin_family = listen4->sin_family;
+               ip4->sin_addr.s_addr = dst->ip4.addr;
+               ip4->sin_port = listen4->sin_port;
+
+               ip4 = (struct sockaddr_in *) &addr->dst_addr;
+               ip4->sin_family = listen4->sin_family;
+               ip4->sin_addr.s_addr = src->ip4.addr;
+               ip4->sin_port = port;
+               break;
+       case 6:
+               listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
+               ip6 = (struct sockaddr_in6 *) &addr->src_addr;
+               ip6->sin6_family = listen6->sin6_family;
+               ip6->sin6_addr = dst->ip6;
+               ip6->sin6_port = listen6->sin6_port;
+
+               ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
+               ip6->sin6_family = listen6->sin6_family;
+               ip6->sin6_addr = src->ip6;
+               ip6->sin6_port = port;
+               break;
+       default:
+               break;
+       }
+}
+
+static inline int cma_user_data_offset(enum rdma_port_space ps)
 {
-       return ((struct sockaddr_in *) addr)->sin_addr.s_addr == 0;
+       switch (ps) {
+       case RDMA_PS_SDP:
+               return 0;
+       default:
+               return sizeof(struct cma_hdr);
+       }
 }
 
 static int cma_notify_user(struct rdma_id_private *id_priv,
@@ -640,53 +728,41 @@ static struct rdma_id_private* cma_new_i
 {
        struct rdma_id_private *id_priv;
        struct rdma_cm_id *id;
-       struct rdma_route *route;
-       struct sockaddr_in *ip_addr, *listen_addr;
-       struct ib_sa_path_rec *path_rec;
-       struct cma_addr *addr;
-       int num_paths;
-
-       listen_addr = (struct sockaddr_in *) &listen_id->route.addr.src_addr;
-       if (cma_verify_addr(ib_event->private_data, listen_addr))
-               return NULL;
+       struct rdma_route *rt;
+       union cma_ip_addr *src, *dst;
+       __u16 port;
+       u8 ip_ver;
 
-       num_paths = 1 + (ib_event->param.req_rcvd.alternate_path != NULL);
-       path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
-       if (!path_rec)
+       id = rdma_create_id(listen_id->event_handler, listen_id->context,
+                           listen_id->ps);
+       if (IS_ERR(id))
                return NULL;
 
-       id = rdma_create_id(listen_id->event_handler, listen_id->context);
-       if (!id)
+       rt = &id->route;
+       rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
+       rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, 
GFP_KERNEL);
+       if (!rt->path_rec)
                goto err;
 
-       addr = ib_event->private_data;
-       route = &id->route;
+       if (cma_get_net_info(ib_event->private_data, listen_id->ps,
+                            &ip_ver, &port, &src, &dst))
+               goto err;
 
-       ip_addr = (struct sockaddr_in *) &route->addr.src_addr;
-       ip_addr->sin_family = listen_addr->sin_family;
-       ip_addr->sin_addr.s_addr = addr->dst_addr.ver.ip4.addr;
-       ip_addr->sin_port = listen_addr->sin_port;
-
-       ip_addr = (struct sockaddr_in *) &route->addr.dst_addr;
-       ip_addr->sin_family = listen_addr->sin_family;
-       ip_addr->sin_addr.s_addr = addr->src_addr.ver.ip4.addr;
-       ip_addr->sin_port = addr->port;
-
-       route->num_paths = num_paths;
-       route->path_rec = path_rec;
-       path_rec[0] = *ib_event->param.req_rcvd.primary_path;
-       if (num_paths == 2)
-               path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
-
-       route->addr.addr.ibaddr.sgid = path_rec->sgid;
-       route->addr.addr.ibaddr.dgid = path_rec->dgid;
-       route->addr.addr.ibaddr.pkey = be16_to_cpu(path_rec->pkey);
+       cma_save_net_info(&id->route.addr, &listen_id->route.addr,
+                         ip_ver, port, src, dst);
+       rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
+       if (rt->num_paths == 2)
+               rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
+
+       rt->addr.addr.ibaddr.sgid = rt->path_rec[0].sgid;
+       rt->addr.addr.ibaddr.dgid = rt->path_rec[0].dgid;
+       rt->addr.addr.ibaddr.pkey = be16_to_cpu(rt->path_rec[0].pkey);
 
        id_priv = container_of(id, struct rdma_id_private, id);
        id_priv->state = CMA_CONNECT;
        return id_priv;
 err:
-       kfree(path_rec);
+       rdma_destroy_id(id);
        return NULL;
 }
 
@@ -708,7 +784,6 @@ static int cma_req_handler(struct ib_cm_
                goto out;
        }
 
-       conn_id->state = CMA_CONNECT;
        atomic_inc(&conn_id->dev_remove);
        ret = cma_acquire_ib_dev(conn_id, &conn_id->id.route.path_rec[0].sgid);
        if (ret) {
@@ -722,7 +797,7 @@ static int cma_req_handler(struct ib_cm_
        cm_id->context = conn_id;
        cm_id->cm_handler = cma_ib_handler;
 
-       offset = sizeof(struct cma_addr);
+       offset = cma_user_data_offset(listen_id->id.ps);
        ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
                              ib_event->private_data + offset,
                              IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
@@ -738,16 +813,16 @@ out:
        return ret;
 }
 
-static __be64 cma_get_service_id(struct sockaddr *addr)
+static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr 
*addr)
 {
-       return cpu_to_be64(((u64)IB_OPENIB_OUI << 48) +
+       return cpu_to_be64(((u64)ps << 16) +
               ((struct sockaddr_in *) addr)->sin_port);
 }
 
 static void cma_set_compare_data(struct sockaddr *addr,
                                 struct ib_cm_private_data_compare *compare)
 {
-       struct cma_addr *data, *mask;
+       struct cma_hdr *data, *mask;
 
        memset(compare, 0, sizeof *compare);
        data = (void *) compare->data;
@@ -755,19 +830,18 @@ static void cma_set_compare_data(struct 
 
        switch (addr->sa_family) {
        case AF_INET:
-               cma_set_vers(data, 0, 4);
-               cma_set_vers(mask, 0, 0xF);
-               data->dst_addr.ver.ip4.addr = ((struct sockaddr_in *) addr)->
-                                               sin_addr.s_addr;
-               mask->dst_addr.ver.ip4.addr = ~0;
+               cma_set_ip_ver(data, 4);
+               cma_set_ip_ver(mask, 0xF);
+               data->dst_addr.ip4.addr = ((struct sockaddr_in *) addr)->
+                                          sin_addr.s_addr;
+               mask->dst_addr.ip4.addr = ~0;
                break;
        case AF_INET6:
-               cma_set_vers(data, 0, 6);
-               cma_set_vers(mask, 0, 0xF);
-               data->dst_addr.ver.ip6 = ((struct sockaddr_in6 *) addr)->
-                                          sin6_addr;
-               memset(&mask->dst_addr.ver.ip6, 1,
-                      sizeof mask->dst_addr.ver.ip6);
+               cma_set_ip_ver(data, 6);
+               cma_set_ip_ver(mask, 0xF);
+               data->dst_addr.ip6 = ((struct sockaddr_in6 *) addr)->
+                                     sin6_addr;
+               memset(&mask->dst_addr.ip6, 1, sizeof mask->dst_addr.ip6);
                break;
        default:
                break;
@@ -787,7 +861,7 @@ static int cma_ib_listen(struct rdma_id_
                return PTR_ERR(id_priv->cm_id);
 
        addr = &id_priv->id.route.addr.src_addr;
-       svc_id = cma_get_service_id(addr);
+       svc_id = cma_get_service_id(id_priv->id.ps, addr);
        if (cma_any_addr(addr))
                ret = ib_cm_listen(id_priv->cm_id, svc_id, 0, NULL);
        else {
@@ -835,7 +909,7 @@ static void cma_listen_on_dev(struct rdm
        struct rdma_cm_id *id;
        int ret;
 
-       id = rdma_create_id(cma_listen_handler, id_priv);
+       id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps);
        if (IS_ERR(id))
                return;
 
@@ -1099,19 +1173,34 @@ err:
 }
 EXPORT_SYMBOL(rdma_bind_addr);
 
-static void cma_format_addr(struct cma_addr *addr, struct rdma_route *route)
+static void cma_format_hdr(void *hdr, enum rdma_port_space ps,
+                          struct rdma_route *route)
 {
-       struct sockaddr_in *ip_addr;
-
-       memset(addr, 0, sizeof *addr);
-       cma_set_vers(addr, 1, 4);
-
-       ip_addr = (struct sockaddr_in *) &route->addr.src_addr;
-       addr->src_addr.ver.ip4.addr = ip_addr->sin_addr.s_addr;
-
-       ip_addr = (struct sockaddr_in *) &route->addr.dst_addr;
-       addr->dst_addr.ver.ip4.addr = ip_addr->sin_addr.s_addr;
-       addr->port = ip_addr->sin_port;
+       struct sockaddr_in *src4, *dst4;
+       struct cma_hdr *cma_hdr;
+       struct sdp_hh *sdp_hdr;
+
+       src4 = (struct sockaddr_in *) &route->addr.src_addr;
+       dst4 = (struct sockaddr_in *) &route->addr.dst_addr;
+
+       switch (ps) {
+       case RDMA_PS_SDP:
+               sdp_hdr = hdr;
+               sdp_hdr->sdp_version = SDP_VERSION;
+               sdp_set_ip_ver(sdp_hdr, 4);
+               sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+               sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+               sdp_hdr->port = src4->sin_port;
+               break;
+       default:
+               cma_hdr = hdr;
+               cma_hdr->cma_version = CMA_VERSION;
+               cma_set_ip_ver(cma_hdr, 4);
+               cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+               cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+               cma_hdr->port = src4->sin_port;
+               break;
+       }
 }
 
 static int cma_connect_ib(struct rdma_id_private *id_priv,
@@ -1119,17 +1208,20 @@ static int cma_connect_ib(struct rdma_id
 {
        struct ib_cm_req_param req;
        struct rdma_route *route;
-       struct cma_addr *addr;
        void *private_data;
-       int ret;
+       int offset, ret;
 
        memset(&req, 0, sizeof req);
-       req.private_data_len = sizeof *addr + conn_param->private_data_len;
-
-       private_data = kmalloc(req.private_data_len, GFP_ATOMIC);
+       offset = cma_user_data_offset(id_priv->id.ps);
+       req.private_data_len = offset + conn_param->private_data_len;
+       private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
        if (!private_data)
                return -ENOMEM;
 
+       if (conn_param->private_data && conn_param->private_data_len)
+               memcpy(private_data + offset, conn_param->private_data,
+                      conn_param->private_data_len);
+
        id_priv->cm_id = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
                                         id_priv);
        if (IS_ERR(id_priv->cm_id)) {
@@ -1137,20 +1229,16 @@ static int cma_connect_ib(struct rdma_id
                goto out;
        }
 
-       addr = private_data;
        route = &id_priv->id.route;
-       cma_format_addr(addr, route);
-
-       if (conn_param->private_data && conn_param->private_data_len)
-               memcpy(addr + 1, conn_param->private_data,
-                      conn_param->private_data_len);
+       cma_format_hdr(private_data, id_priv->id.ps, route);
        req.private_data = private_data;
 
        req.primary_path = &route->path_rec[0];
        if (route->num_paths == 2)
                req.alternate_path = &route->path_rec[1];
 
-       req.service_id = cma_get_service_id(&route->addr.dst_addr);
+       req.service_id = cma_get_service_id(id_priv->id.ps,
+                                           &route->addr.dst_addr);
        req.qp_num = id_priv->qp_num;
        req.qp_type = id_priv->qp_type;
        req.starting_psn = id_priv->seq_num;
@@ -1317,23 +1405,6 @@ out:
 }
 EXPORT_SYMBOL(rdma_disconnect);
 
-/* TODO: add this to the device structure - see Roland's patch */
-static __be64 get_ca_guid(struct ib_device *device)
-{
-       struct ib_device_attr *device_attr;
-       __be64 guid;
-       int ret;
-
-       device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
-       if (!device_attr)
-               return 0;
-
-       ret = ib_query_device(device, device_attr);
-       guid = ret ? 0 : device_attr->node_guid;
-       kfree(device_attr);
-       return guid;
-}
-
 static void cma_add_one(struct ib_device *device)
 {
        struct cma_device *cma_dev;
@@ -1344,7 +1415,7 @@ static void cma_add_one(struct ib_device
                return;
 
        cma_dev->device = device;
-       cma_dev->node_guid = get_ca_guid(device);
+       cma_dev->node_guid = device->node_guid;
        if (!cma_dev->node_guid)
                goto err;
 
Index: core/ucma.c
===================================================================
--- core/ucma.c (revision 4356)
+++ core/ucma.c (working copy)
@@ -287,7 +287,7 @@ static ssize_t ucma_create_id(struct ucm
                return -ENOMEM;
 
        ctx->uid = cmd.uid;
-       ctx->cm_id = rdma_create_id(ucma_event_handler, ctx);
+       ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, RDMA_PS_TCP);
        if (IS_ERR(ctx->cm_id)) {
                ret = PTR_ERR(ctx->cm_id);
                goto err1;



_______________________________________________
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