diff mbox

[rdma-core,03/11] verbs: Add flow_action create, modify and destroy verbs

Message ID 1521655800-7287-4-git-send-email-yishaih@mellanox.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Yishai Hadas March 21, 2018, 6:09 p.m. UTC
From: Matan Barak <matanb@mellanox.com>

A verbs application may receive and transmits packets using a data
path pipeline. Sometimes, the first stage in the receive pipeline or
the last stage in the transmit pipeline involves transforming a
packet, either in order to make it easier for later stages to process
it or to prepare it for transmission over the wire. Such transformation
could be stripping/encapsulating the packet (i.e. vxlan),
decrypting/encrypting it (i.e. ipsec), altering headers, doing some
complex FPGA changes, etc.

Some hardware could do such transformations without software data path
intervention at all. The flow steering API supports steering a
packet (either to a QP or dropping it) and some simple packet
immutable actions (i.e. tagging a packet). Complex actions, that may
change the packet, could bloat the flow steering API extensively.
Sometimes the same action should be applied to several flows.
In this case, it's easier to bind several flows to the same action and
modify it than change all matching flows.

Introducing a new flow_action object that abstracts any packet
transformation (out of a standard and well defined set of actions).
This flow_action object could be tied to a flow steering rule via a
new specification.

Currently, we support esp flow_action, which encrypts or decrypts a
packet according to the given parameters. However, we present a
flexible schema that could be used to other transformation actions tied
to flow rules.

We add create, modify and destroy flow_action ESP verbs.
These new verbs are implemented using the new ioctl() schema.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
---
 libibverbs/CMakeLists.txt    |   1 +
 libibverbs/cmd_flow_action.c | 128 +++++++++++++++++++++++++++++++++++++++++++
 libibverbs/cmd_ioctl.h       |  13 +++++
 libibverbs/driver.h          |  25 +++++++++
 libibverbs/dummy_ops.c       |  24 ++++++++
 libibverbs/libibverbs.map.in |   3 +
 libibverbs/verbs.h           |  69 +++++++++++++++++++++++
 7 files changed, 263 insertions(+)
 create mode 100644 libibverbs/cmd_flow_action.c
diff mbox

Patch

diff --git a/libibverbs/CMakeLists.txt b/libibverbs/CMakeLists.txt
index 04f5b1b..b0e57b5 100644
--- a/libibverbs/CMakeLists.txt
+++ b/libibverbs/CMakeLists.txt
@@ -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
diff --git a/libibverbs/cmd_flow_action.c b/libibverbs/cmd_flow_action.c
new file mode 100644
index 0000000..122ad04
--- /dev/null
+++ b/libibverbs/cmd_flow_action.c
@@ -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);
+}
+
diff --git a/libibverbs/cmd_ioctl.h b/libibverbs/cmd_ioctl.h
index 94814c1..862ac66 100644
--- a/libibverbs/cmd_ioctl.h
+++ b/libibverbs/cmd_ioctl.h
@@ -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
diff --git a/libibverbs/driver.h b/libibverbs/driver.h
index a4097c0..55622fc 100644
--- a/libibverbs/driver.h
+++ b/libibverbs/driver.h
@@ -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);
diff --git a/libibverbs/dummy_ops.c b/libibverbs/dummy_ops.c
index c67ad83..2e5a8cb 100644
--- a/libibverbs/dummy_ops.c
+++ b/libibverbs/dummy_ops.c
@@ -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);
diff --git a/libibverbs/libibverbs.map.in b/libibverbs/libibverbs.map.in
index e97548d..2eb02c8 100644
--- a/libibverbs/libibverbs.map.in
+++ b/libibverbs/libibverbs.map.in
@@ -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;
diff --git a/libibverbs/verbs.h b/libibverbs/verbs.h
index b4bb85d..4e4a658 100644
--- a/libibverbs/verbs.h
+++ b/libibverbs/verbs.h
@@ -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
  */