@@ -31,6 +31,7 @@ rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map"
cmd.c
cmd_cq.c
cmd_fallback.c
+ cmd_flow_action.c
cmd_ioctl.c
compat-1_0.c
device.c
new file mode 100644
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018 Mellanox Technologies, Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <infiniband/cmd_ioctl.h>
+#include <rdma/ib_user_ioctl_cmds.h>
+#include <infiniband/driver.h>
+
+static void scrub_esp_encap(struct ibv_flow_action_esp_encap *esp_encap)
+{
+ scrub_ptr_attr(esp_encap->val_ptr);
+ scrub_ptr_attr(esp_encap->next_ptr);
+}
+
+static int copy_flow_action_esp(struct ibv_flow_action_esp_attr *esp,
+ struct ibv_command_buffer *cmd)
+{
+ if (esp->comp_mask & IBV_FLOW_ACTION_ESP_MASK_ESN)
+ fill_attr_in(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
+ &esp->esn, sizeof(esp->esn));
+
+ if (esp->keymat_ptr)
+ fill_attr_in_enum(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
+ esp->keymat_proto,
+ esp->keymat_ptr, esp->keymat_len);
+ if (esp->replay_ptr)
+ fill_attr_in_enum(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
+ esp->replay_proto,
+ esp->replay_ptr, esp->replay_len);
+ if (esp->esp_encap) {
+ scrub_esp_encap(esp->esp_encap);
+ fill_attr_in_ptr(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
+ esp->esp_encap);
+ }
+ if (esp->esp_attr)
+ fill_attr_in_ptr(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
+ esp->esp_attr);
+
+ return 0;
+}
+
+#define FLOW_ACTION_ESP_ATTRS_NUM 6
+int ibv_cmd_create_flow_action_esp(struct ibv_context *ctx,
+ struct ibv_flow_action_esp_attr *attr,
+ struct verbs_flow_action *flow_action,
+ struct ibv_command_buffer *driver)
+{
+ DECLARE_COMMAND_BUFFER_LINK(cmd, UVERBS_OBJECT_FLOW_ACTION,
+ UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
+ FLOW_ACTION_ESP_ATTRS_NUM,
+ driver);
+ struct ib_uverbs_attr *handle =
+ fill_attr_out_obj(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE);
+ int ret;
+
+ ret = copy_flow_action_esp(attr, cmd);
+ if (ret)
+ return ret;
+
+ ret = execute_ioctl(ctx, cmd);
+ if (ret)
+ return errno;
+
+ flow_action->action.context = ctx;
+ flow_action->type = IBV_FLOW_ACTION_ESP;
+ flow_action->handle = read_attr_obj(UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE,
+ handle);
+
+ return 0;
+}
+
+int ibv_cmd_modify_flow_action_esp(struct verbs_flow_action *flow_action,
+ struct ibv_flow_action_esp_attr *attr,
+ struct ibv_command_buffer *driver)
+{
+ DECLARE_COMMAND_BUFFER_LINK(cmd, UVERBS_OBJECT_FLOW_ACTION,
+ UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
+ FLOW_ACTION_ESP_ATTRS_NUM, driver);
+ int ret;
+
+ fill_attr_in_obj(cmd, UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE,
+ flow_action->handle);
+
+ ret = copy_flow_action_esp(attr, cmd);
+ if (ret)
+ return ret;
+
+ return execute_ioctl(flow_action->action.context, cmd);
+}
+
+int ibv_cmd_destroy_flow_action(struct verbs_flow_action *action)
+{
+ DECLARE_COMMAND_BUFFER(cmd, UVERBS_OBJECT_FLOW_ACTION,
+ UVERBS_METHOD_FLOW_ACTION_DESTROY, 1);
+
+ fill_attr_in_obj(cmd, UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
+ action->handle);
+ return execute_ioctl(action->action.context, cmd);
+}
+
@@ -39,6 +39,7 @@
#include <assert.h>
#include <rdma/rdma_user_ioctl_cmds.h>
#include <infiniband/verbs.h>
+#include <ccan/container_of.h>
static inline uint64_t ioctl_ptr_to_u64(const void *ptr)
{
@@ -57,6 +58,18 @@ static inline uint64_t ioctl_ptr_to_u64(const void *ptr)
#endif
}
+static inline void scrub_ptr_attr(void *ptr)
+{
+#if UINTPTR_MAX == UINT64_MAX
+ /* Do nothing */
+#else
+ RDMA_UAPI_PTR(void *, data) *scrub_data;
+
+ scrub_data = container_of(ptr, typeof(*scrub_data), data);
+ scrub_data->data_data_u64 = ioctl_ptr_to_u64(scrub_data->data);
+#endif
+}
+
/*
* The command buffer is organized as a linked list of blocks of attributes.
* Each stack frame allocates its block and then calls up toward to core code
@@ -42,6 +42,7 @@
#include <config.h>
#include <stdbool.h>
#include <rdma/rdma_user_ioctl_cmds.h>
+#include <infiniband/cmd_ioctl.h>
struct verbs_device;
@@ -89,6 +90,17 @@ struct verbs_qp {
struct verbs_xrcd *xrcd;
};
+enum ibv_flow_action_type {
+ IBV_FLOW_ACTION_UNSPECIFIED,
+ IBV_FLOW_ACTION_ESP = 1,
+};
+
+struct verbs_flow_action {
+ struct ibv_flow_action action;
+ uint32_t handle;
+ enum ibv_flow_action_type type;
+};
+
enum {
VERBS_MATCH_SENTINEL = 0,
VERBS_MATCH_PCI = 1,
@@ -202,6 +214,8 @@ struct verbs_context_ops {
struct ibv_cq_init_attr_ex *init_attr);
struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
struct ibv_flow_attr *flow_attr);
+ struct ibv_flow_action *(*create_flow_action_esp)(struct ibv_context *context,
+ struct ibv_flow_action_esp_attr *attr);
struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
struct ibv_qp_init_attr *attr);
struct ibv_qp *(*create_qp_ex)(
@@ -224,6 +238,7 @@ struct verbs_context_ops {
int (*destroy_ah)(struct ibv_ah *ah);
int (*destroy_cq)(struct ibv_cq *cq);
int (*destroy_flow)(struct ibv_flow *flow);
+ int (*destroy_flow_action)(struct ibv_flow_action *action);
int (*destroy_qp)(struct ibv_qp *qp);
int (*destroy_rwq_ind_table)(struct ibv_rwq_ind_table *rwq_ind_table);
int (*destroy_srq)(struct ibv_srq *srq);
@@ -232,6 +247,8 @@ struct verbs_context_ops {
uint16_t lid);
int (*get_srq_num)(struct ibv_srq *srq, uint32_t *srq_num);
int (*modify_cq)(struct ibv_cq *cq, struct ibv_modify_cq_attr *attr);
+ int (*modify_flow_action_esp)(struct ibv_flow_action *action,
+ struct ibv_flow_action_esp_attr *attr);
int (*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
int attr_mask);
int (*modify_qp_rate_limit)(struct ibv_qp *qp,
@@ -330,6 +347,13 @@ int ibv_cmd_query_device(struct ibv_context *context,
struct ibv_device_attr *device_attr,
uint64_t *raw_fw_ver,
struct ibv_query_device *cmd, size_t cmd_size);
+int ibv_cmd_create_flow_action_esp(struct ibv_context *ctx,
+ struct ibv_flow_action_esp_attr *attr,
+ struct verbs_flow_action *flow_action,
+ struct ibv_command_buffer *driver);
+int ibv_cmd_modify_flow_action_esp(struct verbs_flow_action *flow_action,
+ struct ibv_flow_action_esp_attr *attr,
+ struct ibv_command_buffer *driver);
int ibv_cmd_query_device_ex(struct ibv_context *context,
const struct ibv_query_device_ex_input *input,
struct ibv_device_attr_ex *attr, size_t attr_size,
@@ -475,6 +499,7 @@ int ibv_cmd_create_wq(struct ibv_context *context,
size_t resp_core_size,
size_t resp_size);
+int ibv_cmd_destroy_flow_action(struct verbs_flow_action *action);
int ibv_cmd_modify_wq(struct ibv_wq *wq, struct ibv_wq_attr *attr,
struct ibv_modify_wq *cmd, size_t cmd_core_size,
size_t cmd_size);
@@ -113,6 +113,13 @@ static struct ibv_flow *create_flow(struct ibv_qp *qp,
return NULL;
}
+static struct ibv_flow_action *create_flow_action_esp(struct ibv_context *context,
+ struct ibv_flow_action_esp_attr *attr)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
static struct ibv_qp *create_qp(struct ibv_pd *pd,
struct ibv_qp_init_attr *attr)
{
@@ -192,6 +199,11 @@ static int destroy_flow(struct ibv_flow *flow)
return ENOSYS;
}
+static int destroy_flow_action(struct ibv_flow_action *action)
+{
+ return ENOSYS;
+}
+
static int destroy_qp(struct ibv_qp *qp)
{
return ENOSYS;
@@ -228,6 +240,12 @@ static int modify_cq(struct ibv_cq *cq, struct ibv_modify_cq_attr *attr)
return ENOSYS;
}
+static int modify_flow_action_esp(struct ibv_flow_action *action,
+ struct ibv_flow_action_esp_attr *attr)
+{
+ return ENOSYS;
+}
+
static int modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mask)
{
return ENOSYS;
@@ -378,6 +396,7 @@ const struct verbs_context_ops verbs_dummy_ops = {
create_cq,
create_cq_ex,
create_flow,
+ create_flow_action_esp,
create_qp,
create_qp_ex,
create_rwq_ind_table,
@@ -391,6 +410,7 @@ const struct verbs_context_ops verbs_dummy_ops = {
destroy_ah,
destroy_cq,
destroy_flow,
+ destroy_flow_action,
destroy_qp,
destroy_rwq_ind_table,
destroy_srq,
@@ -398,6 +418,7 @@ const struct verbs_context_ops verbs_dummy_ops = {
detach_mcast,
get_srq_num,
modify_cq,
+ modify_flow_action_esp,
modify_qp,
modify_qp_rate_limit,
modify_srq,
@@ -456,6 +477,7 @@ void verbs_set_ops(struct verbs_context *vctx,
SET_OP(ctx, create_cq);
SET_OP(vctx, create_cq_ex);
SET_OP2(vctx, ibv_create_flow, create_flow);
+ SET_OP(vctx, create_flow_action_esp);
SET_OP(ctx, create_qp);
SET_OP(vctx, create_qp_ex);
SET_OP(vctx, create_rwq_ind_table);
@@ -469,6 +491,7 @@ void verbs_set_ops(struct verbs_context *vctx,
SET_OP(ctx, destroy_ah);
SET_OP(ctx, destroy_cq);
SET_OP2(vctx, ibv_destroy_flow, destroy_flow);
+ SET_OP(vctx, destroy_flow_action);
SET_OP(ctx, destroy_qp);
SET_OP(vctx, destroy_rwq_ind_table);
SET_OP(ctx, destroy_srq);
@@ -476,6 +499,7 @@ void verbs_set_ops(struct verbs_context *vctx,
SET_OP(ctx, detach_mcast);
SET_OP(vctx, get_srq_num);
SET_OP(vctx, modify_cq);
+ SET_OP(vctx, modify_flow_action_esp);
SET_OP(ctx, modify_qp);
SET_OP(vctx, modify_qp_rate_limit);
SET_OP(ctx, modify_srq);
@@ -123,6 +123,7 @@ IBVERBS_PRIVATE_@IBVERBS_PABI_VERSION@ {
ibv_cmd_create_cq;
ibv_cmd_create_cq_ex;
ibv_cmd_create_flow;
+ ibv_cmd_create_flow_action_esp;
ibv_cmd_create_qp;
ibv_cmd_create_qp_ex2;
ibv_cmd_create_qp_ex;
@@ -136,12 +137,14 @@ IBVERBS_PRIVATE_@IBVERBS_PABI_VERSION@ {
ibv_cmd_destroy_ah;
ibv_cmd_destroy_cq;
ibv_cmd_destroy_flow;
+ ibv_cmd_destroy_flow_action;
ibv_cmd_destroy_qp;
ibv_cmd_destroy_rwq_ind_table;
ibv_cmd_destroy_srq;
ibv_cmd_destroy_wq;
ibv_cmd_detach_mcast;
ibv_cmd_get_context;
+ ibv_cmd_modify_flow_action_esp;
ibv_cmd_modify_qp;
ibv_cmd_modify_qp_ex;
ibv_cmd_modify_srq;
@@ -1518,6 +1518,31 @@ struct ibv_flow {
uint32_t handle;
};
+struct ibv_flow_action {
+ struct ibv_context *context;
+};
+
+enum ibv_flow_action_esp_mask {
+ IBV_FLOW_ACTION_ESP_MASK_ESN = 1UL << 0,
+};
+
+struct ibv_flow_action_esp_attr {
+ struct ibv_flow_action_esp *esp_attr;
+
+ enum ibv_flow_action_esp_keymat keymat_proto;
+ uint16_t keymat_len;
+ void *keymat_ptr;
+
+ enum ibv_flow_action_esp_replay replay_proto;
+ uint16_t replay_len;
+ void *replay_ptr;
+
+ struct ibv_flow_action_esp_encap *esp_encap;
+
+ uint32_t comp_mask; /* Use enum ibv_flow_action_esp_mask */
+ uint32_t esn;
+};
+
struct ibv_device;
struct ibv_context;
@@ -1665,6 +1690,11 @@ struct ibv_values_ex {
struct verbs_context {
/* "grows up" - new fields go here */
+ int (*modify_flow_action_esp)(struct ibv_flow_action *action,
+ struct ibv_flow_action_esp_attr *attr);
+ int (*destroy_flow_action)(struct ibv_flow_action *action);
+ struct ibv_flow_action *(*create_flow_action_esp)(struct ibv_context *context,
+ struct ibv_flow_action_esp_attr *attr);
int (*modify_qp_rate_limit)(struct ibv_qp *qp,
struct ibv_qp_rate_limit_attr *attr);
struct ibv_pd *(*alloc_parent_domain)(struct ibv_context *context,
@@ -1859,6 +1889,45 @@ static inline int ibv_destroy_flow(struct ibv_flow *flow_id)
return vctx->ibv_destroy_flow(flow_id);
}
+static inline struct ibv_flow_action *
+ibv_create_flow_action_esp(struct ibv_context *ctx,
+ struct ibv_flow_action_esp_attr *esp)
+{
+ struct verbs_context *vctx = verbs_get_ctx_op(ctx,
+ create_flow_action_esp);
+
+ if (!vctx) {
+ errno = ENOSYS;
+ return NULL;
+ }
+
+ return vctx->create_flow_action_esp(ctx, esp);
+}
+
+static inline int
+ibv_modify_flow_action_esp(struct ibv_flow_action *action,
+ struct ibv_flow_action_esp_attr *esp)
+{
+ struct verbs_context *vctx = verbs_get_ctx_op(action->context,
+ modify_flow_action_esp);
+
+ if (!vctx)
+ return ENOSYS;
+
+ return vctx->modify_flow_action_esp(action, esp);
+}
+
+static inline int ibv_destroy_flow_action(struct ibv_flow_action *action)
+{
+ struct verbs_context *vctx = verbs_get_ctx_op(action->context,
+ destroy_flow_action);
+
+ if (!vctx)
+ return ENOSYS;
+
+ return vctx->destroy_flow_action(action);
+}
+
/**
* ibv_open_xrcd - Open an extended connection domain
*/