net/mlx5: fix meter policy flow match item
Currently when creating meter policy, a src port_id match item will
always be added in switch domain. So if one meter is used by another
port, it will not work correctly.
This issue is solved:
1. If policy fate action is port_id, add the src port_id match item,
and the meter cannot be shared by another port.
2. If policy fate action isn't port_id, don't add the src port_id
match, meter can be shared by another port.
This fix enables one meter being shared by different ports. User can
create a meter flow using a port_id match item to make this meter
shared by other port.
Fixes: afb4aa4f12
("net/mlx5: support meter policy operations")
Cc: stable@dpdk.org
Signed-off-by: Shun Hao <shunh@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
This commit is contained in:
parent
3c481324ba
commit
48fbc1be82
@ -1921,3 +1921,13 @@ all flows with assistance of external tools.
|
||||
.. code-block:: console
|
||||
|
||||
mlx_steering_dump.py -f <output_file> -flowptr <flow_ptr>
|
||||
|
||||
How to share a meter between ports in the same switch domain
|
||||
------------------------------------------------------------
|
||||
|
||||
This section demonstrates how to use the shared meter. A meter M can be created
|
||||
on port X and to be shared with a port Y on the same switch domain by the next way:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
flow create X ingress transfer pattern eth / port_id id is Y / end actions meter mtr_id M / end
|
||||
|
@ -682,6 +682,8 @@ struct mlx5_meter_policy_action_container {
|
||||
|
||||
/* Flow meter policy parameter structure. */
|
||||
struct mlx5_flow_meter_policy {
|
||||
struct rte_eth_dev *dev;
|
||||
/* The port dev on which policy is created. */
|
||||
uint32_t is_rss:1;
|
||||
/* Is RSS policy table. */
|
||||
uint32_t ingress:1;
|
||||
|
@ -5031,6 +5031,8 @@ flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev __rte_unused,
|
||||
* Pointer to the meter action.
|
||||
* @param[in] attr
|
||||
* Attributes of flow that includes this action.
|
||||
* @param[in] port_id_item
|
||||
* Pointer to item indicating port id.
|
||||
* @param[out] error
|
||||
* Pointer to error structure.
|
||||
*
|
||||
@ -5042,6 +5044,7 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
|
||||
uint64_t action_flags,
|
||||
const struct rte_flow_action *action,
|
||||
const struct rte_flow_attr *attr,
|
||||
const struct rte_flow_item *port_id_item,
|
||||
bool *def_policy,
|
||||
struct rte_flow_error *error)
|
||||
{
|
||||
@ -5112,6 +5115,37 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
|
||||
"Flow attributes domain "
|
||||
"have a conflict with current "
|
||||
"meter domain attributes");
|
||||
if (attr->transfer && mtr_policy->dev) {
|
||||
/**
|
||||
* When policy has fate action of port_id,
|
||||
* the flow should have the same src port as policy.
|
||||
*/
|
||||
struct mlx5_priv *policy_port_priv =
|
||||
mtr_policy->dev->data->dev_private;
|
||||
int32_t flow_src_port = priv->representor_id;
|
||||
|
||||
if (port_id_item) {
|
||||
const struct rte_flow_item_port_id *spec =
|
||||
port_id_item->spec;
|
||||
struct mlx5_priv *port_priv =
|
||||
mlx5_port_to_eswitch_info(spec->id,
|
||||
false);
|
||||
if (!port_priv)
|
||||
return rte_flow_error_set(error,
|
||||
rte_errno,
|
||||
RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
|
||||
spec,
|
||||
"Failed to get port info.");
|
||||
flow_src_port = port_priv->representor_id;
|
||||
}
|
||||
if (flow_src_port != policy_port_priv->representor_id)
|
||||
return rte_flow_error_set(error,
|
||||
rte_errno,
|
||||
RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
|
||||
NULL,
|
||||
"Flow and meter policy "
|
||||
"have different src port.");
|
||||
}
|
||||
*def_policy = false;
|
||||
}
|
||||
return 0;
|
||||
@ -6685,6 +6719,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
|
||||
};
|
||||
const struct rte_eth_hairpin_conf *conf;
|
||||
const struct rte_flow_item *rule_items = items;
|
||||
const struct rte_flow_item *port_id_item = NULL;
|
||||
bool def_policy = false;
|
||||
|
||||
if (items == NULL)
|
||||
@ -6726,6 +6761,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
last_item = MLX5_FLOW_ITEM_PORT_ID;
|
||||
port_id_item = items;
|
||||
break;
|
||||
case RTE_FLOW_ITEM_TYPE_ETH:
|
||||
ret = mlx5_flow_validate_item_eth(items, item_flags,
|
||||
@ -7463,6 +7499,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
|
||||
ret = mlx5_flow_validate_action_meter(dev,
|
||||
action_flags,
|
||||
actions, attr,
|
||||
port_id_item,
|
||||
&def_policy,
|
||||
error);
|
||||
if (ret < 0)
|
||||
@ -15348,7 +15385,7 @@ __flow_dv_create_policy_flow(struct rte_eth_dev *dev,
|
||||
uint32_t color_reg_c_idx,
|
||||
enum rte_color color, void *matcher_object,
|
||||
int actions_n, void *actions,
|
||||
bool is_default_policy, void **rule,
|
||||
bool match_src_port, void **rule,
|
||||
const struct rte_flow_attr *attr)
|
||||
{
|
||||
int ret;
|
||||
@ -15362,7 +15399,7 @@ __flow_dv_create_policy_flow(struct rte_eth_dev *dev,
|
||||
};
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
|
||||
if (!is_default_policy && (priv->representor || priv->master)) {
|
||||
if (match_src_port && (priv->representor || priv->master)) {
|
||||
if (flow_dv_translate_item_port_id(dev, matcher.buf,
|
||||
value.buf, NULL, attr)) {
|
||||
DRV_LOG(ERR,
|
||||
@ -15389,7 +15426,7 @@ __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
|
||||
uint16_t priority,
|
||||
struct mlx5_flow_meter_sub_policy *sub_policy,
|
||||
const struct rte_flow_attr *attr,
|
||||
bool is_default_policy,
|
||||
bool match_src_port,
|
||||
struct rte_flow_error *error)
|
||||
{
|
||||
struct mlx5_cache_entry *entry;
|
||||
@ -15413,7 +15450,7 @@ __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
|
||||
|
||||
if (!is_default_policy && (priv->representor || priv->master)) {
|
||||
if (match_src_port && (priv->representor || priv->master)) {
|
||||
if (flow_dv_translate_item_port_id(dev, matcher.mask.buf,
|
||||
value.buf, NULL, attr)) {
|
||||
DRV_LOG(ERR,
|
||||
@ -15458,7 +15495,7 @@ __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
|
||||
static int
|
||||
__flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_sub_policy *sub_policy,
|
||||
uint8_t egress, uint8_t transfer, bool is_default_policy,
|
||||
uint8_t egress, uint8_t transfer, bool match_src_port,
|
||||
struct mlx5_meter_policy_acts acts[RTE_COLORS])
|
||||
{
|
||||
struct rte_flow_error flow_err;
|
||||
@ -15497,7 +15534,7 @@ __flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
|
||||
/* Create matchers for Color. */
|
||||
if (__flow_dv_create_policy_matcher(dev,
|
||||
color_reg_c_idx, i, sub_policy,
|
||||
&attr, is_default_policy, &flow_err))
|
||||
&attr, match_src_port, &flow_err))
|
||||
return -1;
|
||||
}
|
||||
/* Create flow, matching color. */
|
||||
@ -15507,7 +15544,7 @@ __flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
|
||||
sub_policy->color_matcher[i]->matcher_object,
|
||||
acts[i].actions_n,
|
||||
acts[i].dv_actions,
|
||||
is_default_policy,
|
||||
match_src_port,
|
||||
&sub_policy->color_rule[i],
|
||||
&attr))
|
||||
return -1;
|
||||
@ -15527,6 +15564,7 @@ __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_dv_port_id_action_resource *port_action;
|
||||
struct mlx5_hrxq *hrxq;
|
||||
uint8_t egress, transfer;
|
||||
bool match_src_port = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTE_COLORS; i++) {
|
||||
@ -15571,6 +15609,8 @@ __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
|
||||
acts[i].dv_actions[acts[i].actions_n] =
|
||||
port_action->action;
|
||||
acts[i].actions_n++;
|
||||
mtr_policy->dev = dev;
|
||||
match_src_port = true;
|
||||
break;
|
||||
case MLX5_FLOW_FATE_DROP:
|
||||
case MLX5_FLOW_FATE_JUMP:
|
||||
@ -15601,7 +15641,7 @@ __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
|
||||
egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
|
||||
transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
|
||||
if (__flow_dv_create_domain_policy_rules(dev, sub_policy,
|
||||
egress, transfer, false, acts)) {
|
||||
egress, transfer, match_src_port, acts)) {
|
||||
DRV_LOG(ERR,
|
||||
"Failed to create policy rules per domain.");
|
||||
return -1;
|
||||
@ -15709,7 +15749,7 @@ __flow_dv_create_domain_def_policy(struct rte_eth_dev *dev, uint32_t domain)
|
||||
/* Create default policy rules. */
|
||||
ret = __flow_dv_create_domain_policy_rules(dev,
|
||||
&def_policy->sub_policy,
|
||||
egress, transfer, true, acts);
|
||||
egress, transfer, false, acts);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create "
|
||||
"default policy rules.");
|
||||
|
Loading…
Reference in New Issue
Block a user