@@ -1919,6 +1919,21 @@ err:
}
EXPORT_SYMBOL(rdma_resolve_addr);
+int rdma_set_ib_dest(struct rdma_cm_id *id, struct sockaddr *dst_addr,
+ union ib_gid *dgid)
+{
+ struct rdma_id_private *id_priv;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
+ if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_RESOLVED))
+ return -EINVAL;
+
+ memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
+ ib_addr_set_dgid(&id->route.addr.dev_addr, dgid);
+ return 0;
+}
+EXPORT_SYMBOL(rdma_set_ib_dest);
+
static void cma_bind_port(struct rdma_bind_list *bind_list,
struct rdma_id_private *id_priv)
{
@@ -832,12 +832,35 @@ static int ucma_set_ib_path(struct ucma_context *ctx,
return ucma_event_handler(ctx->cm_id, &event);
}
+static int ucma_set_ib_dest(struct ucma_context *ctx,
+ struct rdma_ucm_ib_dest *ib_dest, size_t optlen)
+{
+ union ib_gid dgid;
+ struct rdma_cm_event event;
+ int ret;
+
+ if (optlen < sizeof(*ib_dest))
+ return -EINVAL;
+
+ memcpy(&dgid, ib_dest->dgid, sizeof dgid);
+ ret = rdma_set_ib_dest(ctx->cm_id, (struct sockaddr *) &ib_dest->dst_addr, &dgid);
+ if (ret)
+ return ret;
+
+ memset(&event, 0, sizeof event);
+ event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
+ return ucma_event_handler(ctx->cm_id, &event);
+}
+
static int ucma_set_option_ib(struct ucma_context *ctx, int optname,
void *optval, size_t optlen)
{
int ret;
switch (optname) {
+ case RDMA_OPTION_IB_DEST:
+ ret = ucma_set_ib_dest(ctx, optval, optlen);
+ break;
case RDMA_OPTION_IB_PATH:
ret = ucma_set_ib_path(ctx, optval, optlen);
break;
@@ -48,6 +48,20 @@
int rdma_set_ib_paths(struct rdma_cm_id *id,
struct ib_sa_path_rec *path_rec, int num_paths);
+/**
+ * rdma_set_ib_dest - Manually set the destination address
+ * @id: Connection identifier associated with the request.
+ * @dst_addr: Destination address information.
+ * @dgid: Destination device address information.
+ *
+ * This call allows the user to specify address mappings for rdma_cm_id's
+ * bound to an Infiniband device. It is called on the client side of a
+ * connection and combined with rdma_bind_addr, replaces the call to
+ * rdma_resolve_addr.
+ */
+int rdma_set_ib_dest(struct rdma_cm_id *id, struct sockaddr *dst_addr,
+ union ib_gid *dgid);
+
/* Global qkey for UDP QPs and multicast groups. */
#define RDMA_UDP_QKEY 0x01234567
@@ -223,6 +223,7 @@ enum {
enum {
RDMA_OPTION_ID_TOS = 0,
+ RDMA_OPTION_IB_DEST = 0,
RDMA_OPTION_IB_PATH = 1
};
@@ -234,6 +235,11 @@ struct rdma_ucm_set_option {
__u32 optlen;
};
+struct rdma_ucm_ib_dest {
+ __u8 dgid[16];
+ struct sockaddr_in6 dst_addr;
+};
+
struct rdma_ucm_migrate_id {
__u64 response;
__u32 id;