Skip to content

Commit

Permalink
net/mlx5: support flow port action with HWS
Browse files Browse the repository at this point in the history
This patch implements creating and caching of port action for use with
HW Steering FDB flows.

Actions are created on flow template API configuration and created
only on the port designated as the master. Attaching and detaching ports
in the same switching domain causes an update to the port actions cache
by, respectively, creating and destroying actions.

A new devarg fdb_def_rule_en is being added and it's used to control
the default dedicated E-Switch rules that are created by the PMD
implicitly or not, and PMD sets this value to 1 by default.

If set to 0, the default E-Switch rule will not be created and the user
can create the specific E-Switch rules on the root table if needed.

Signed-off-by: Dariusz Sosnowski <[email protected]>
Acked-by: Viacheslav Ovsiienko <[email protected]>
  • Loading branch information
sodar authored and raslandarawsheh committed Oct 26, 2022
1 parent 0f4aa72 commit 1939eb6
Show file tree
Hide file tree
Showing 10 changed files with 1,596 additions and 118 deletions.
10 changes: 10 additions & 0 deletions doc/guides/nics/mlx5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,16 @@ for an additional list of options shared with other mlx5 drivers.

Enabled by default if supported.

- ``fdb_def_rule_en`` parameter [int]

A non-zero value enables to create a dedicated rule on E-Switch root table.
This dedicated rule forwards all incoming packets into table 1.
Other rules will be created in E-Switch table original table level plus one,
to improve the flow insertion rate due to skipping root table managed by firmware.
If set to 0, all rules will be created on the original E-Switch table level.

By default, the PMD will set this value to 1.

- ``lacp_by_user`` parameter [int]

A nonzero value enables the control of LACP traffic by the user application.
Expand Down
16 changes: 15 additions & 1 deletion drivers/net/mlx5/linux/mlx5_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1564,11 +1564,18 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
}
rte_rwlock_init(&priv->ind_tbls_lock);
if (priv->sh->config.dv_flow_en == 2) {
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
#ifdef HAVE_MLX5_HWS_SUPPORT
if (priv->vport_meta_mask)
flow_hw_set_port_info(eth_dev);
/* Only HWS requires this information. */
flow_hw_init_tags_set(eth_dev);
if (priv->sh->config.dv_esw_en &&
flow_hw_create_vport_action(eth_dev)) {
DRV_LOG(ERR, "port %u failed to create vport action",
eth_dev->data->port_id);
err = EINVAL;
goto error;
}
return eth_dev;
#else
DRV_LOG(ERR, "DV support is missing for HWS.");
Expand Down Expand Up @@ -1633,6 +1640,13 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
return eth_dev;
error:
if (priv) {
#ifdef HAVE_MLX5_HWS_SUPPORT
if (eth_dev &&
priv->sh &&
priv->sh->config.dv_flow_en == 2 &&
priv->sh->config.dv_esw_en)
flow_hw_destroy_vport_action(eth_dev);
#endif
if (priv->mreg_cp_tbl)
mlx5_hlist_destroy(priv->mreg_cp_tbl);
if (priv->sh)
Expand Down
14 changes: 14 additions & 0 deletions drivers/net/mlx5/mlx5.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@
/* Device parameter to configure the delay drop when creating Rxqs. */
#define MLX5_DELAY_DROP "delay_drop"

/* Device parameter to create the fdb default rule in PMD */
#define MLX5_FDB_DEFAULT_RULE_EN "fdb_def_rule_en"

/* Shared memory between primary and secondary processes. */
struct mlx5_shared_data *mlx5_shared_data;

Expand Down Expand Up @@ -1239,6 +1242,8 @@ mlx5_dev_args_check_handler(const char *key, const char *val, void *opaque)
config->decap_en = !!tmp;
} else if (strcmp(MLX5_ALLOW_DUPLICATE_PATTERN, key) == 0) {
config->allow_duplicate_pattern = !!tmp;
} else if (strcmp(MLX5_FDB_DEFAULT_RULE_EN, key) == 0) {
config->fdb_def_rule = !!tmp;
}
return 0;
}
Expand Down Expand Up @@ -1274,6 +1279,7 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,
MLX5_RECLAIM_MEM,
MLX5_DECAP_EN,
MLX5_ALLOW_DUPLICATE_PATTERN,
MLX5_FDB_DEFAULT_RULE_EN,
NULL,
};
int ret = 0;
Expand All @@ -1285,6 +1291,7 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,
config->dv_flow_en = 1;
config->decap_en = 1;
config->allow_duplicate_pattern = 1;
config->fdb_def_rule = 1;
if (mkvlist != NULL) {
/* Process parameters. */
ret = mlx5_kvargs_process(mkvlist, params,
Expand Down Expand Up @@ -1360,6 +1367,7 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,
DRV_LOG(DEBUG, "\"decap_en\" is %u.", config->decap_en);
DRV_LOG(DEBUG, "\"allow_duplicate_pattern\" is %u.",
config->allow_duplicate_pattern);
DRV_LOG(DEBUG, "\"fdb_def_rule_en\" is %u.", config->fdb_def_rule);
return 0;
}

Expand Down Expand Up @@ -1943,6 +1951,7 @@ mlx5_dev_close(struct rte_eth_dev *dev)
mlx5_flex_parser_ecpri_release(dev);
mlx5_flex_item_port_cleanup(dev);
#ifdef HAVE_MLX5_HWS_SUPPORT
flow_hw_destroy_vport_action(dev);
flow_hw_resource_release(dev);
flow_hw_clear_port_info(dev);
if (priv->sh->config.dv_flow_en == 2)
Expand Down Expand Up @@ -2644,6 +2653,11 @@ mlx5_probe_again_args_validate(struct mlx5_common_device *cdev,
sh->ibdev_name);
goto error;
}
if (sh->config.fdb_def_rule ^ config->fdb_def_rule) {
DRV_LOG(ERR, "\"fdb_def_rule_en\" configuration mismatch for shared %s context.",
sh->ibdev_name);
goto error;
}
if (sh->config.l3_vxlan_en ^ config->l3_vxlan_en) {
DRV_LOG(ERR, "\"l3_vxlan_en\" "
"configuration mismatch for shared %s context.",
Expand Down
26 changes: 22 additions & 4 deletions drivers/net/mlx5/mlx5.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ struct mlx5_sh_config {
uint32_t allow_duplicate_pattern:1;
uint32_t lro_allowed:1; /* Whether LRO is allowed. */
/* Allow/Prevent the duplicate rules pattern. */
uint32_t fdb_def_rule:1; /* Create FDB default jump rule */
};


Expand Down Expand Up @@ -342,13 +343,17 @@ enum {
MLX5_HW_Q_JOB_TYPE_DESTROY, /* Flow destroy job type. */
};

#define MLX5_HW_MAX_ITEMS (16)

/* HW steering flow management job descriptor. */
struct mlx5_hw_q_job {
uint32_t type; /* Job type. */
struct rte_flow_hw *flow; /* Flow attached to the job. */
void *user_data; /* Job user data. */
uint8_t *encap_data; /* Encap data. */
struct mlx5_modification_cmd *mhdr_cmd;
struct rte_flow_item *items;
struct rte_flow_item_ethdev port_spec;
};

/* HW steering job descriptor LIFO pool. */
Expand Down Expand Up @@ -1212,6 +1217,8 @@ struct mlx5_dev_ctx_shared {
uint32_t flow_priority_check_flag:1; /* Check Flag for flow priority. */
uint32_t metadata_regc_check_flag:1; /* Check Flag for metadata REGC. */
uint32_t hws_tags:1; /* Check if tags info for HWS initialized. */
uint32_t shared_mark_enabled:1;
/* If mark action is enabled on Rxqs (shared E-Switch domain). */
uint32_t max_port; /* Maximal IB device port index. */
struct mlx5_bond_info bond; /* Bonding information. */
struct mlx5_common_device *cdev; /* Backend mlx5 device. */
Expand Down Expand Up @@ -1463,6 +1470,12 @@ struct mlx5_obj_ops {

#define MLX5_RSS_HASH_FIELDS_LEN RTE_DIM(mlx5_rss_hash_fields)

struct mlx5_hw_ctrl_flow {
LIST_ENTRY(mlx5_hw_ctrl_flow) next;
struct rte_eth_dev *owner_dev;
struct rte_flow *flow;
};

struct mlx5_priv {
struct rte_eth_dev_data *dev_data; /* Pointer to device data. */
struct mlx5_dev_ctx_shared *sh; /* Shared device context. */
Expand Down Expand Up @@ -1503,6 +1516,11 @@ struct mlx5_priv {
unsigned int reta_idx_n; /* RETA index size. */
struct mlx5_drop drop_queue; /* Flow drop queues. */
void *root_drop_action; /* Pointer to root drop action. */
rte_spinlock_t hw_ctrl_lock;
LIST_HEAD(hw_ctrl_flow, mlx5_hw_ctrl_flow) hw_ctrl_flows;
struct rte_flow_template_table *hw_esw_sq_miss_root_tbl;
struct rte_flow_template_table *hw_esw_sq_miss_tbl;
struct rte_flow_template_table *hw_esw_zero_tbl;
struct mlx5_indexed_pool *flows[MLX5_FLOW_TYPE_MAXI];
/* RTE Flow rules. */
uint32_t ctrl_flows; /* Control flow rules. */
Expand Down Expand Up @@ -1563,11 +1581,11 @@ struct mlx5_priv {
struct mlx5_hw_q *hw_q;
/* HW steering rte flow table list header. */
LIST_HEAD(flow_hw_tbl, rte_flow_template_table) flow_hw_tbl;
struct mlx5dr_action **hw_vport;
/* HW steering global drop action. */
struct mlx5dr_action *hw_drop[MLX5_HW_ACTION_FLAG_MAX]
[MLX5DR_TABLE_TYPE_MAX];
/* HW steering global drop action. */
struct mlx5dr_action *hw_tag[MLX5_HW_ACTION_FLAG_MAX];
struct mlx5dr_action *hw_drop[2];
/* HW steering global tag action. */
struct mlx5dr_action *hw_tag[2];
struct mlx5_indexed_pool *acts_ipool; /* Action data indexed pool. */
#endif
};
Expand Down
96 changes: 80 additions & 16 deletions drivers/net/mlx5/mlx5_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ static const struct rte_flow_ops mlx5_flow_ops = {
.flex_item_create = mlx5_flow_flex_item_create,
.flex_item_release = mlx5_flow_flex_item_release,
.info_get = mlx5_flow_info_get,
.pick_transfer_proxy = mlx5_flow_pick_transfer_proxy,
.configure = mlx5_flow_port_configure,
.pattern_template_create = mlx5_flow_pattern_template_create,
.pattern_template_destroy = mlx5_flow_pattern_template_destroy,
Expand Down Expand Up @@ -1240,7 +1241,7 @@ mlx5_get_lowest_priority(struct rte_eth_dev *dev,
{
struct mlx5_priv *priv = dev->data->dev_private;

if (!attr->group && !attr->transfer)
if (!attr->group && !(attr->transfer && priv->fdb_def_rule))
return priv->sh->flow_max_priority - 2;
return MLX5_NON_ROOT_FLOW_MAX_PRIO - 1;
}
Expand All @@ -1267,11 +1268,14 @@ mlx5_get_matcher_priority(struct rte_eth_dev *dev,
uint16_t priority = (uint16_t)attr->priority;
struct mlx5_priv *priv = dev->data->dev_private;

/* NIC root rules */
if (!attr->group && !attr->transfer) {
if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)
priority = priv->sh->flow_max_priority - 1;
return mlx5_os_flow_adjust_priority(dev, priority, subpriority);
} else if (!external && attr->transfer && attr->group == 0 &&
/* FDB root rules */
} else if (attr->transfer && (!external || !priv->fdb_def_rule) &&
attr->group == 0 &&
attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) {
return (priv->sh->flow_max_priority - 1) * 3;
}
Expand Down Expand Up @@ -1479,13 +1483,32 @@ flow_rxq_mark_flag_set(struct rte_eth_dev *dev)
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_rxq_ctrl *rxq_ctrl;
uint16_t port_id;

if (priv->mark_enabled)
if (priv->sh->shared_mark_enabled)
return;
LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) {
rxq_ctrl->rxq.mark = 1;
if (priv->master || priv->representor) {
MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
struct mlx5_priv *opriv =
rte_eth_devices[port_id].data->dev_private;

if (!opriv ||
opriv->sh != priv->sh ||
opriv->domain_id != priv->domain_id ||
opriv->mark_enabled)
continue;
LIST_FOREACH(rxq_ctrl, &opriv->rxqsctrl, next) {
rxq_ctrl->rxq.mark = 1;
}
opriv->mark_enabled = 1;
}
} else {
LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) {
rxq_ctrl->rxq.mark = 1;
}
priv->mark_enabled = 1;
}
priv->mark_enabled = 1;
priv->sh->shared_mark_enabled = 1;
}

/**
Expand Down Expand Up @@ -1621,6 +1644,7 @@ flow_rxq_flags_clear(struct rte_eth_dev *dev)
rxq->ctrl->rxq.tunnel = 0;
}
priv->mark_enabled = 0;
priv->sh->shared_mark_enabled = 0;
}

/**
Expand Down Expand Up @@ -2806,8 +2830,8 @@ mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
* Item specification.
* @param[in] item_flags
* Bit-fields that holds the items detected until now.
* @param[in] attr
* Flow rule attributes.
* @param root
* Whether action is on root table.
* @param[out] error
* Pointer to error structure.
*
Expand All @@ -2819,7 +2843,7 @@ mlx5_flow_validate_item_vxlan(struct rte_eth_dev *dev,
uint16_t udp_dport,
const struct rte_flow_item *item,
uint64_t item_flags,
const struct rte_flow_attr *attr,
bool root,
struct rte_flow_error *error)
{
const struct rte_flow_item_vxlan *spec = item->spec;
Expand Down Expand Up @@ -2856,12 +2880,11 @@ mlx5_flow_validate_item_vxlan(struct rte_eth_dev *dev,
if (priv->sh->steering_format_version !=
MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
!udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN) {
/* FDB domain & NIC domain non-zero group */
if ((attr->transfer || attr->group) && priv->sh->misc5_cap)
/* non-root table */
if (!root && priv->sh->misc5_cap)
valid_mask = &nic_mask;
/* Group zero in NIC domain */
if (!attr->group && !attr->transfer &&
priv->sh->tunnel_header_0_1)
if (!root && priv->sh->tunnel_header_0_1)
valid_mask = &nic_mask;
}
ret = mlx5_flow_item_acceptable
Expand Down Expand Up @@ -3100,11 +3123,11 @@ mlx5_flow_validate_item_gre_option(struct rte_eth_dev *dev,
if (mask->checksum_rsvd.checksum || mask->sequence.sequence) {
if (priv->sh->steering_format_version ==
MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
((attr->group || attr->transfer) &&
((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
!priv->sh->misc5_cap) ||
(!(priv->sh->tunnel_header_0_1 &&
priv->sh->tunnel_header_2_3) &&
!attr->group && !attr->transfer))
!attr->group && (!attr->transfer || !priv->fdb_def_rule)))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item,
Expand Down Expand Up @@ -6161,7 +6184,8 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
}
if (qrss) {
/* Check if it is in meter suffix table. */
mtr_sfx = attr->group == (attr->transfer ?
mtr_sfx = attr->group ==
((attr->transfer && priv->fdb_def_rule) ?
(MLX5_FLOW_TABLE_LEVEL_METER - 1) :
MLX5_FLOW_TABLE_LEVEL_METER);
/*
Expand Down Expand Up @@ -11116,3 +11140,43 @@ int mlx5_flow_get_item_vport_id(struct rte_eth_dev *dev,

return 0;
}

int
mlx5_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
uint16_t *proxy_port_id,
struct rte_flow_error *error)
{
const struct mlx5_priv *priv = dev->data->dev_private;
uint16_t port_id;

if (!priv->sh->config.dv_esw_en)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL,
"unable to provide a proxy port"
" without E-Switch configured");
if (!priv->master && !priv->representor)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL,
"unable to provide a proxy port"
" for port which is not a master"
" or a representor port");
if (priv->master) {
*proxy_port_id = dev->data->port_id;
return 0;
}
MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
const struct rte_eth_dev *port_dev = &rte_eth_devices[port_id];
const struct mlx5_priv *port_priv = port_dev->data->dev_private;

if (port_priv->master &&
port_priv->domain_id == priv->domain_id) {
*proxy_port_id = port_id;
return 0;
}
}
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "unable to find a proxy port");
}
Loading

0 comments on commit 1939eb6

Please sign in to comment.