Add kernel support for retrieving and setting options on an rdma_cm_id.
This provides functionality conceptually similar to getsockopt/getsockopt.

Add an option to retrieve possible routes (path records) for a connection.
A client may use this to select a path that a connection will use when
being established.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>
---
Index: core/ucma.c
===================================================================
--- core/ucma.c (revision 6884)
+++ core/ucma.c (working copy)
@@ -41,6 +41,8 @@
 #include <rdma/ib_marshall.h>
 #include <rdma/rdma_cm.h>
 
+#include "ucma_ib.h"
+
 MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
 MODULE_LICENSE("Dual BSD/GPL");
@@ -656,6 +658,83 @@ out:
        return ret;
 }
 
+static ssize_t ucma_get_option(struct ucma_file *file, const char __user 
*inbuf,
+                              int in_len, int out_len)
+{
+       struct rdma_ucm_get_option cmd;
+       struct rdma_ucm_get_option_resp resp;
+       struct ucma_context *ctx;
+       int ret;
+
+       if (out_len < sizeof(resp))
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+               return -EFAULT;
+
+       ctx = ucma_get_ctx(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
+       resp.optlen = cmd.optlen;
+
+       switch (cmd.level) {
+       case RDMA_PROTO_IP:
+               ret = -ENOSYS;
+               break;
+       case RDMA_PROTO_IB:
+               ret = ucma_get_ib_option(ctx->cm_id, cmd.optname,
+                                        (void *) (unsigned long) cmd.optval,
+                                        &resp.optlen);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       if (ret)
+               goto out;
+
+       if (copy_to_user((void __user *)(unsigned long)cmd.response,
+                        &resp, sizeof(resp)))
+               ret = -EFAULT;
+out:
+       ucma_put_ctx(ctx);
+       return ret;
+}
+
+static ssize_t ucma_set_option(struct ucma_file *file, const char __user 
*inbuf,
+                              int in_len, int out_len)
+{
+       struct rdma_ucm_set_option cmd;
+       struct ucma_context *ctx;
+       int ret;
+
+       if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+               return -EFAULT;
+
+       ctx = ucma_get_ctx(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
+       switch (cmd.level) {
+       case RDMA_PROTO_IP:
+               ret = -ENOSYS;
+               break;
+       case RDMA_PROTO_IB:
+               ret = ucma_set_ib_option(ctx->cm_id, cmd.optname,
+                                        (void *) (unsigned long) cmd.optval,
+                                        cmd.optlen);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       ucma_put_ctx(ctx);
+       return ret;
+}
+
 static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
                                   const char __user *inbuf,
                                   int in_len, int out_len) = {
@@ -671,7 +750,9 @@ static ssize_t (*ucma_cmd_table[])(struc
        [RDMA_USER_CM_CMD_REJECT]       = ucma_reject,
        [RDMA_USER_CM_CMD_DISCONNECT]   = ucma_disconnect,
        [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr,
-       [RDMA_USER_CM_CMD_GET_EVENT]    = ucma_get_event
+       [RDMA_USER_CM_CMD_GET_EVENT]    = ucma_get_event,
+       [RDMA_USER_CM_CMD_GET_OPTION]   = ucma_get_option,
+       [RDMA_USER_CM_CMD_SET_OPTION]   = ucma_set_option
 };
 
 static ssize_t ucma_write(struct file *filp, const char __user *buf,
Index: core/ucma_ib.c
===================================================================
--- core/ucma_ib.c      (revision 0)
+++ core/ucma_ib.c      (revision 0)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#include <rdma/ib_addr.h>
+#include <rdma/ib_local_sa.h>
+#include <rdma/ib_marshall.h>
+#include <rdma/rdma_cm_ib.h>
+#include <rdma/rdma_user_cm.h>
+
+#include "ucma_ib.h"
+
+static int ucma_get_paths(struct rdma_cm_id *id,
+                         void __user *paths, size_t *len)
+{
+       struct ib_sa_cursor *cursor;
+       struct ib_sa_path_rec *path;
+       struct ib_user_path_rec user_path;
+       union ib_gid *gid;
+       int left, ret = 0;
+       u16 pkey;
+
+       if (!id->device)
+               return -ENODEV;
+
+       gid = ib_addr_get_dgid(&id->route.addr.dev_addr);
+       pkey = ib_addr_get_pkey(&id->route.addr.dev_addr);
+       cursor = ib_create_path_cursor(id->device, id->port_num, gid);
+       if (IS_ERR(cursor))
+               return PTR_ERR(cursor);
+
+       gid = ib_addr_get_sgid(&id->route.addr.dev_addr);
+       left = *len;
+       *len = 0;
+
+       for (path = ib_get_next_sa_attr(&cursor); path;
+            path = ib_get_next_sa_attr(&cursor)) {
+               if (pkey == path->pkey &&
+                   !memcmp(gid, path->sgid.raw, sizeof *gid)) {
+                       if (paths) {
+                               ib_copy_path_rec_to_user(&user_path, path);
+                               if (copy_to_user(paths, &user_path,
+                                                sizeof(user_path))) {
+                                       ret = -EFAULT;
+                                       break;
+                               }
+                               left -= sizeof(user_path);
+                               if (left < sizeof(user_path))
+                                       break;
+                               paths += sizeof(user_path);
+                       }
+                       *len += sizeof(user_path);
+               }
+       }
+
+       ib_free_sa_cursor(cursor);
+       return ret;
+}
+
+int ucma_get_ib_option(struct rdma_cm_id *id, int optname,
+                      void *optval, size_t *optlen)
+{
+       switch (optname) {
+       case IB_PATH_OPTIONS:
+               return ucma_get_paths(id, optval, optlen);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int ucma_set_paths(struct rdma_cm_id *id,
+                         void __user *paths, size_t len)
+{
+       struct ib_sa_path_rec *path_rec;
+       struct ib_user_path_rec *user_path;
+       int ret, num_paths, i;
+
+       if (len == sizeof(*user_path))
+               num_paths = 1;
+       else if (len == (sizeof(*user_path) << 1))
+               num_paths = 2;
+       else
+               return -EINVAL;
+
+       path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
+       if (!path_rec)
+               return -ENOMEM;
+
+       user_path = kmalloc(sizeof *user_path * num_paths, GFP_KERNEL);
+       if (!user_path) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       if (copy_from_user(user_path, paths, sizeof *user_path * num_paths)) {
+               ret = -EFAULT;
+               goto out2;
+       }
+
+       for (i = 0; i < num_paths; i++)
+               ib_copy_path_rec_from_user(path_rec + i, user_path + i);
+
+       ret = rdma_set_ib_paths(id, path_rec, num_paths);
+out2:
+       kfree(user_path);
+out:
+       kfree(path_rec);
+       return ret;
+}
+
+int ucma_set_ib_option(struct rdma_cm_id *id, int optname,
+                      void *optval, size_t optlen)
+{
+       switch (optname) {
+       case IB_PATH_OPTIONS:
+               return ucma_set_paths(id, optval, optlen);
+       default:
+               return -EINVAL;
+       }
+}

Property changes on: core/ucma_ib.c
___________________________________________________________________
Name: svn:executable
   + *

Index: core/ucma_ib.h
===================================================================
--- core/ucma_ib.h      (revision 0)
+++ core/ucma_ib.h      (revision 0)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(UCMA_IB_H)
+#define UCMA_IB_H
+
+#include <rdma/rdma_cm.h>
+
+int ucma_get_ib_option(struct rdma_cm_id *id, int optname,
+                      void *optval, size_t *optlen);
+
+int ucma_set_ib_option(struct rdma_cm_id *id, int optname,
+                      void *optval, size_t optlen);
+
+#endif /* UCMA_IB_H */

Property changes on: core/ucma_ib.h
___________________________________________________________________
Name: svn:executable
   + *

Index: core/Makefile
===================================================================
--- core/Makefile       (revision 6884)
+++ core/Makefile       (working copy)
@@ -22,7 +22,7 @@ ib_cm-y :=                    cm.o
 
 rdma_cm-y :=                   cma.o
 
-rdma_ucm-y :=                  ucma.o
+rdma_ucm-y :=                  ucma.o ucma_ib.o
 
 ib_addr-y :=                   addr.o
 
Index: include/rdma/rdma_user_cm.h
===================================================================
--- include/rdma/rdma_user_cm.h (revision 6884)
+++ include/rdma/rdma_user_cm.h (working copy)
@@ -55,7 +55,9 @@ enum {
        RDMA_USER_CM_CMD_REJECT,
        RDMA_USER_CM_CMD_DISCONNECT,
        RDMA_USER_CM_CMD_INIT_QP_ATTR,
-       RDMA_USER_CM_CMD_GET_EVENT
+       RDMA_USER_CM_CMD_GET_EVENT,
+       RDMA_USER_CM_CMD_GET_OPTION,
+       RDMA_USER_CM_CMD_SET_OPTION,
 };
 
 /*
@@ -183,4 +185,36 @@ struct rdma_ucm_event_resp {
        __u8  private_data[RDMA_MAX_PRIVATE_DATA];
 };
 
+struct rdma_ucm_get_option {
+       __u64 response;
+       __u64 optval;
+       __u32 id;
+       __u32 level;
+       __u32 optname;
+       __u32 optlen;
+};
+
+/* Protocol levels for get/set options. */
+enum {
+       RDMA_PROTO_IP = 0,
+       RDMA_PROTO_IB = 1,
+};
+
+/* IB specific option names for get/set. */
+enum {
+       IB_PATH_OPTIONS = 1,
+};
+
+struct rdma_ucm_get_option_resp {
+       __u32 optlen;
+};
+
+struct rdma_ucm_set_option {
+       __u64 optval;
+       __u32 id;
+       __u32 level;
+       __u32 optname;
+       __u32 optlen;
+};
+
 #endif /* RDMA_USER_CM_H */

_______________________________________________
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