summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDekel Peled <dekelp@mellanox.com>2018-11-01 11:37:32 +0200
committerFerruh Yigit <ferruh.yigit@intel.com>2018-11-05 15:01:25 +0100
commit8ba9eee4ce323219d39ce976e081aa4a70519cca (patch)
tree4e6479f76d94178435d22f09c583c0b857041a12 /drivers
parent4b8727f08b5ec1aa18788254a887d2577bb6a2aa (diff)
downloaddpdk-8ba9eee4ce323219d39ce976e081aa4a70519cca.zip
dpdk-8ba9eee4ce323219d39ce976e081aa4a70519cca.tar.gz
dpdk-8ba9eee4ce323219d39ce976e081aa4a70519cca.tar.xz
net/mlx5: add raw data encap/decap to Direct Verbs
This patch implements the encap and decap actions, using raw data, in DV flow for MLX5 PMD. Signed-off-by: Dekel Peled <dekelp@mellanox.com> Acked-by: Shahaf Shuler <shahafs@mellanox.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/mlx5/mlx5_flow.h12
-rw-r--r--drivers/net/mlx5/mlx5_flow_dv.c246
2 files changed, 241 insertions, 17 deletions
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 68f9227..f26c06c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -96,15 +96,19 @@
#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
#define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
+#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26)
+#define MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
#define MLX5_FLOW_FATE_ACTIONS \
(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
-#define MLX5_FLOW_ENCAP_ACTIONS \
- (MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+#define MLX5_FLOW_ENCAP_ACTIONS (MLX5_FLOW_ACTION_VXLAN_ENCAP | \
+ MLX5_FLOW_ACTION_NVGRE_ENCAP | \
+ MLX5_FLOW_ACTION_RAW_ENCAP)
-#define MLX5_FLOW_DECAP_ACTIONS \
- (MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+#define MLX5_FLOW_DECAP_ACTIONS (MLX5_FLOW_ACTION_VXLAN_DECAP | \
+ MLX5_FLOW_ACTION_NVGRE_DECAP | \
+ MLX5_FLOW_ACTION_RAW_DECAP)
#ifndef IPPROTO_MPLS
#define IPPROTO_MPLS 137
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 156d0d0..106bdcb 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -178,6 +178,101 @@ flow_dv_validate_action_l2_decap(uint64_t action_flags,
}
/**
+ * Validate the raw encap action.
+ *
+ * @param[in] action_flags
+ * Holds the actions detected until now.
+ * @param[in] action
+ * Pointer to the encap action.
+ * @param[in] attr
+ * Pointer to flow attributes
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_encap(uint64_t action_flags,
+ const struct rte_flow_action *action,
+ const struct rte_flow_attr *attr,
+ struct rte_flow_error *error)
+{
+ if (!(action->conf))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "configuration cannot be null");
+ if (action_flags & MLX5_FLOW_ACTION_DROP)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "can't drop and encap in same flow");
+ if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "can only have a single encap"
+ " action in a flow");
+ /* encap without preceding decap is not supported for ingress */
+ if (attr->ingress && !(action_flags & MLX5_FLOW_ACTION_RAW_DECAP))
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+ NULL,
+ "encap action not supported for "
+ "ingress");
+ return 0;
+}
+
+/**
+ * Validate the raw decap action.
+ *
+ * @param[in] action_flags
+ * Holds the actions detected until now.
+ * @param[in] action
+ * Pointer to the encap action.
+ * @param[in] attr
+ * Pointer to flow attributes
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_decap(uint64_t action_flags,
+ const struct rte_flow_action *action,
+ const struct rte_flow_attr *attr,
+ struct rte_flow_error *error)
+{
+ if (action_flags & MLX5_FLOW_ACTION_DROP)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "can't drop and decap in same flow");
+ if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "can't have encap action before"
+ " decap action");
+ if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "can only have a single decap"
+ " action in a flow");
+ /* decap action is valid on egress only if it is followed by encap */
+ if (attr->egress) {
+ for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
+ action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+ action++) {
+ }
+ if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP)
+ return rte_flow_error_set
+ (error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+ NULL, "decap action not supported"
+ " for egress");
+ }
+ return 0;
+}
+
+/**
* Get the size of specific rte_flow_item_type
*
* @param[in] item_type
@@ -431,23 +526,34 @@ flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
{
struct ibv_flow_action *verbs_action = NULL;
const struct rte_flow_item *encap_data;
+ const struct rte_flow_action_raw_encap *raw_encap_data;
struct priv *priv = dev->data->dev_private;
uint8_t buf[MLX5_ENCAP_MAX_LEN];
+ uint8_t *buf_ptr = buf;
size_t size = 0;
int convert_result = 0;
- if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
- encap_data = ((const struct rte_flow_action_vxlan_encap *)
+ if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+ raw_encap_data =
+ (const struct rte_flow_action_raw_encap *)action->conf;
+ buf_ptr = raw_encap_data->data;
+ size = raw_encap_data->size;
+ } else {
+ if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+ encap_data =
+ ((const struct rte_flow_action_vxlan_encap *)
action->conf)->definition;
- else
- encap_data = ((const struct rte_flow_action_nvgre_encap *)
+ else
+ encap_data =
+ ((const struct rte_flow_action_nvgre_encap *)
action->conf)->definition;
- convert_result = flow_dv_convert_encap_data(encap_data, buf,
- &size, error);
- if (convert_result)
- return NULL;
+ convert_result = flow_dv_convert_encap_data(encap_data, buf,
+ &size, error);
+ if (convert_result)
+ return NULL;
+ }
verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
- (priv->ctx, size, buf,
+ (priv->ctx, size, buf_ptr,
MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
if (!verbs_action)
@@ -485,6 +591,50 @@ flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
}
/**
+ * Convert raw decap/encap (L3 tunnel) action to DV specification.
+ *
+ * @param[in] dev
+ * Pointer to rte_eth_dev structure.
+ * @param[in] action
+ * Pointer to action structure.
+ * @param[in] attr
+ * Pointer to the flow attributes.
+ * @param[out] error
+ * Pointer to the error structure.
+ *
+ * @return
+ * Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
+ const struct rte_flow_action *action,
+ const struct rte_flow_attr *attr,
+ struct rte_flow_error *error)
+{
+ struct ibv_flow_action *verbs_action = NULL;
+ const struct rte_flow_action_raw_encap *encap_data;
+ struct priv *priv = dev->data->dev_private;
+ enum mlx5dv_flow_action_packet_reformat_type reformat_type;
+ enum mlx5dv_flow_table_type ft_type;
+
+ encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
+ reformat_type = attr->egress ?
+ MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
+ MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
+ ft_type = attr->egress ?
+ MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+ MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+ verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+ (priv->ctx, encap_data->size,
+ (encap_data->size ? encap_data->data : NULL),
+ reformat_type, ft_type);
+ if (!verbs_action)
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "cannot create encap action");
+ return verbs_action;
+}
+
+/**
* Verify the @p attributes will be correctly understood by the NIC and store
* them in the @p flow if everything is correct.
*
@@ -739,7 +889,6 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
MLX5_FLOW_ACTION_VXLAN_ENCAP :
MLX5_FLOW_ACTION_NVGRE_ENCAP;
-
++actions_n;
break;
case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -752,7 +901,24 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
MLX5_FLOW_ACTION_VXLAN_DECAP :
MLX5_FLOW_ACTION_NVGRE_DECAP;
-
+ ++actions_n;
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+ ret = flow_dv_validate_action_raw_encap(action_flags,
+ actions, attr,
+ error);
+ if (ret < 0)
+ return ret;
+ action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
+ ++actions_n;
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+ ret = flow_dv_validate_action_raw_decap(action_flags,
+ actions, attr,
+ error);
+ if (ret < 0)
+ return ret;
+ action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
++actions_n;
break;
default:
@@ -1467,6 +1633,8 @@ flow_dv_create_item(void *matcher, void *key,
* Flow action to translate.
* @param[in, out] dev_flow
* Pointer to the mlx5_flow.
+ * @param[in] attr
+ * Pointer to the flow attributes.
* @param[out] error
* Pointer to the error structure.
*
@@ -1477,12 +1645,14 @@ static int
flow_dv_create_action(struct rte_eth_dev *dev,
const struct rte_flow_action *action,
struct mlx5_flow *dev_flow,
+ const struct rte_flow_attr *attr,
struct rte_flow_error *error)
{
const struct rte_flow_action_queue *queue;
const struct rte_flow_action_rss *rss;
int actions_n = dev_flow->dv.actions_n;
struct rte_flow *flow = dev_flow->flow;
+ const struct rte_flow_action *action_ptr = action;
switch (action->type) {
case RTE_FLOW_ACTION_TYPE_VOID:
@@ -1558,6 +1728,56 @@ flow_dv_create_action(struct rte_eth_dev *dev,
MLX5_FLOW_ACTION_NVGRE_DECAP;
actions_n++;
break;
+ case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+ /* Handle encap action with preceding decap */
+ if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
+ dev_flow->dv.actions[actions_n].type =
+ MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+ dev_flow->dv.actions[actions_n].action =
+ flow_dv_create_action_raw_encap
+ (dev, action,
+ attr, error);
+ if (!(dev_flow->dv.actions[actions_n].action))
+ return -rte_errno;
+ dev_flow->dv.encap_decap_verbs_action =
+ dev_flow->dv.actions[actions_n].action;
+ } else {
+ /* Handle encap action without preceding decap */
+ dev_flow->dv.actions[actions_n].type =
+ MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+ dev_flow->dv.actions[actions_n].action =
+ flow_dv_create_action_l2_encap
+ (dev, action, error);
+ if (!(dev_flow->dv.actions[actions_n].action))
+ return -rte_errno;
+ dev_flow->dv.encap_decap_verbs_action =
+ dev_flow->dv.actions[actions_n].action;
+ }
+ flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
+ actions_n++;
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+ /* Check if this decap action is followed by encap. */
+ for (; action_ptr->type != RTE_FLOW_ACTION_TYPE_END &&
+ action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+ action_ptr++) {
+ }
+ /* Handle decap action only if it isn't followed by encap */
+ if (action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+ dev_flow->dv.actions[actions_n].type =
+ MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+ dev_flow->dv.actions[actions_n].action =
+ flow_dv_create_action_l2_decap(dev,
+ error);
+ if (!(dev_flow->dv.actions[actions_n].action))
+ return -rte_errno;
+ dev_flow->dv.encap_decap_verbs_action =
+ dev_flow->dv.actions[actions_n].action;
+ actions_n++;
+ }
+ /* If decap is followed by encap, handle it at encap case. */
+ flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP;
+ break;
default:
break;
}
@@ -1702,7 +1922,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
struct mlx5_flow *dev_flow,
const struct rte_flow_attr *attr,
const struct rte_flow_item items[],
- const struct rte_flow_action actions[] __rte_unused,
+ const struct rte_flow_action actions[],
struct rte_flow_error *error)
{
struct priv *priv = dev->data->dev_private;
@@ -1732,7 +1952,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
return -rte_errno;
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
- if (flow_dv_create_action(dev, actions, dev_flow, error))
+ if (flow_dv_create_action(dev, actions, dev_flow, attr, error))
return -rte_errno;
return 0;
}