#include <rte_malloc.h>
#include <rte_ip.h>
-#include "mlx5.h"
+#include <mlx5_glue.h>
+#include <mlx5_devx_cmds.h>
+#include <mlx5_prm.h>
+
#include "mlx5_defs.h"
+#include "mlx5.h"
#include "mlx5_flow.h"
-#include "mlx5_glue.h"
-#include "mlx5_prm.h"
#include "mlx5_rxtx.h"
/* Dev ops structure defined in mlx5.c */
.flush = mlx5_flow_flush,
.isolate = mlx5_flow_isolate,
.query = mlx5_flow_query,
+ .dev_dump = mlx5_flow_dev_dump,
};
/* Convert FDIR request to Generic flow. */
.tunnel = MLX5_FLOW_LAYER_IPV6_ENCAP,
.ptype = RTE_PTYPE_TUNNEL_IP,
},
+ {
+ .tunnel = MLX5_FLOW_LAYER_GTP,
+ .ptype = RTE_PTYPE_TUNNEL_GTPU,
+ },
};
/**
* The request register on success, a negative errno
* value otherwise and rte_errno is set.
*/
-enum modify_reg
+int
mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
enum mlx5_feature_name feature,
uint32_t id,
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_dev_config *config = &priv->config;
enum modify_reg start_reg;
+ bool skip_mtr_reg = false;
switch (feature) {
case MLX5_HAIRPIN_RX:
return REG_C_0;
}
break;
- case MLX5_COPY_MARK:
case MLX5_MTR_SFX:
/*
- * Metadata COPY_MARK register using is in meter suffix sub
- * flow while with meter. It's safe to share the same register.
+ * If meter color and flow match share one register, flow match
+ * should use the meter color register for match.
*/
- return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3;
+ if (priv->mtr_reg_share)
+ return priv->mtr_color_reg;
+ else
+ return priv->mtr_color_reg != REG_C_2 ? REG_C_2 :
+ REG_C_3;
case MLX5_MTR_COLOR:
RTE_ASSERT(priv->mtr_color_reg != REG_NONE);
return priv->mtr_color_reg;
+ case MLX5_COPY_MARK:
+ /*
+ * Metadata COPY_MARK register using is in meter suffix sub
+ * flow while with meter. It's safe to share the same register.
+ */
+ return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3;
case MLX5_APP_TAG:
/*
- * If meter is enable, it will engage two registers for color
+ * If meter is enable, it will engage the register for color
* match and flow match. If meter color match is not using the
* REG_C_2, need to skip the REG_C_x be used by meter color
* match.
* If meter is disable, free to use all available registers.
*/
- if (priv->mtr_color_reg != REG_NONE)
- start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_3 :
- REG_C_4;
- else
- start_reg = REG_C_2;
+ start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_2 :
+ (priv->mtr_reg_share ? REG_C_3 : REG_C_4);
+ skip_mtr_reg = !!(priv->mtr_en && start_reg == REG_C_2);
if (id > (REG_C_7 - start_reg))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
* If the available index REG_C_y >= REG_C_x, skip the
* color register.
*/
- if (start_reg == REG_C_3 && config->flow_mreg_c
- [id + REG_C_3 - REG_C_0] >= priv->mtr_color_reg) {
- if (config->flow_mreg_c[id + 1 + REG_C_3 - REG_C_0] !=
- REG_NONE)
+ if (skip_mtr_reg && config->flow_mreg_c
+ [id + start_reg - REG_C_0] >= priv->mtr_color_reg) {
+ if (config->flow_mreg_c
+ [id + 1 + start_reg - REG_C_0] != REG_NONE)
return config->flow_mreg_c
- [id + 1 + REG_C_3 - REG_C_0];
+ [id + 1 + start_reg - REG_C_0];
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ITEM,
NULL, "unsupported tag id");
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 flag in same flow");
if (action_flags & MLX5_FLOW_ACTION_MARK)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
&mark->id,
"mark id must in 0 <= id < "
RTE_STR(MLX5_FLOW_MARK_MAX));
- if (action_flags & MLX5_FLOW_ACTION_DROP)
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "can't drop and mark in same flow");
if (action_flags & MLX5_FLOW_ACTION_FLAG)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
int
-mlx5_flow_validate_action_drop(uint64_t action_flags,
+mlx5_flow_validate_action_drop(uint64_t action_flags __rte_unused,
const struct rte_flow_attr *attr,
struct rte_flow_error *error)
{
- if (action_flags & MLX5_FLOW_ACTION_FLAG)
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "can't drop and flag in same flow");
- if (action_flags & MLX5_FLOW_ACTION_MARK)
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "can't drop and mark in same flow");
- if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
- MLX5_FLOW_FATE_ESWITCH_ACTIONS))
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "can't have 2 fate actions in"
- " same flow");
if (attr->egress)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
&rss->types,
"some RSS protocols are not"
" supported");
+ if ((rss->types & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY)) &&
+ !(rss->types & ETH_RSS_IP))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+ "L3 partial RSS requested but L3 RSS"
+ " type not specified");
+ if ((rss->types & (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY)) &&
+ !(rss->types & (ETH_RSS_UDP | ETH_RSS_TCP)))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+ "L4 partial RSS requested but L4 RSS"
+ " type not specified");
if (!priv->rxqs_n)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION_CONF,
mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id);
if (mcp_res) {
/* For non-default rule. */
- if (mark_id)
+ if (mark_id != MLX5_DEFAULT_COPY_ID)
mcp_res->refcnt++;
- assert(mark_id || mcp_res->refcnt == 1);
+ assert(mark_id != MLX5_DEFAULT_COPY_ID || mcp_res->refcnt == 1);
return mcp_res;
}
/* Provide the full width of FLAG specific value. */
if (mark_id == (priv->sh->dv_regc0_mask & MLX5_FLOW_MARK_DEFAULT))
tag_spec.data = MLX5_FLOW_MARK_DEFAULT;
/* Build a new flow. */
- if (mark_id) {
+ if (mark_id != MLX5_DEFAULT_COPY_ID) {
items[0] = (struct rte_flow_item){
.type = MLX5_RTE_FLOW_ITEM_TYPE_TAG,
.spec = &tag_spec,
}
/*
* We do not check availability of metadata registers here,
- * because copy resources are allocated in this case.
+ * because copy resources are not allocated in this case.
*/
if (--mcp_res->refcnt)
return;
/* Check if default flow is registered. */
if (!priv->mreg_cp_tbl)
return;
- mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl, 0ULL);
+ mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl,
+ MLX5_DEFAULT_COPY_ID);
if (!mcp_res)
return;
assert(mcp_res->flow);
!mlx5_flow_ext_mreg_supported(dev) ||
!priv->sh->dv_regc0_mask)
return 0;
- mcp_res = flow_mreg_add_copy_action(dev, 0, error);
+ mcp_res = flow_mreg_add_copy_action(dev, MLX5_DEFAULT_COPY_ID, error);
if (!mcp_res)
return -rte_errno;
return 0;
* Get the id from the qrss_pool to make qrss share the id with meter.
*/
tag_id = flow_qrss_get_id(dev);
- set_tag->data = rte_cpu_to_be_32(tag_id);
+ set_tag->data = tag_id << MLX5_MTR_COLOR_BITS;
tag_action->conf = set_tag;
return tag_id;
}
actions_n = flow_check_meter_action(actions, &mtr);
if (mtr) {
struct mlx5_rte_flow_item_tag *tag_spec;
+ struct mlx5_rte_flow_item_tag *tag_mask;
/* The five prefix actions: meter, decap, encap, tag, end. */
act_size = sizeof(struct rte_flow_action) * (actions_n + 5) +
sizeof(struct rte_flow_action_set_tag);
/* tag, end. */
#define METER_SUFFIX_ITEM 3
item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM +
- sizeof(struct mlx5_rte_flow_item_tag);
+ sizeof(struct mlx5_rte_flow_item_tag) * 2;
sfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0);
if (!sfx_actions)
return rte_flow_error_set(error, ENOMEM,
act_size);
tag_spec = (struct mlx5_rte_flow_item_tag *)(sfx_items +
METER_SUFFIX_ITEM);
- tag_spec->data = rte_cpu_to_be_32(dev_flow->mtr_flow_id);
+ tag_spec->data = dev_flow->mtr_flow_id << MLX5_MTR_COLOR_BITS;
tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0,
error);
+ tag_mask = tag_spec + 1;
+ tag_mask->data = 0xffffff00;
sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG;
sfx_items->spec = tag_spec;
sfx_items->last = NULL;
- sfx_items->mask = NULL;
+ sfx_items->mask = tag_mask;
sfx_items++;
sfx_port_id_item = find_port_id_item(items);
if (sfx_port_id_item) {
sfx_items++;
}
sfx_items->type = RTE_FLOW_ITEM_TYPE_END;
- sfx_items -= METER_SUFFIX_ITEM;
+ sfx_items -= sfx_port_id_item ? 2 : 1;
/* Setting the sfx group atrr. */
sfx_attr.group = sfx_attr.transfer ?
(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
config->flow_mreg_c[n] = REG_NONE;
return 0;
}
+
+/**
+ * Dump flow raw hw data to file
+ *
+ * @param[in] dev
+ * The pointer to Ethernet device.
+ * @param[in] file
+ * A pointer to a file for output.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. PMDs initialize this
+ * structure in case of error only.
+ * @return
+ * 0 on success, a nagative value otherwise.
+ */
+int
+mlx5_flow_dev_dump(struct rte_eth_dev *dev,
+ FILE *file,
+ struct rte_flow_error *error __rte_unused)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_ibv_shared *sh = priv->sh;
+
+ return mlx5_devx_cmd_flow_dump(sh->fdb_domain, sh->rx_domain,
+ sh->tx_domain, file);
+}