The new action is an internal mlx5 action that will call the rdma-core function MLX5DV_FLOW_ACTION_DEFAULT_MISS.
The default miss action will be used when a bond is configured to allow traffic realted to the bond to be managed in the kernel. Signed-off-by: Shiri Kuzin <shi...@mellanox.com> --- drivers/net/mlx5/mlx5.h | 5 +++ drivers/net/mlx5/mlx5_flow.c | 72 ++++++++++++++++++++++++++++++++ drivers/net/mlx5/mlx5_flow.h | 10 ++++- drivers/net/mlx5/mlx5_flow_dv.c | 91 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 175 insertions(+), 3 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 2908c8b..bc57fb5 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -509,6 +509,9 @@ struct mlx5_ibv_shared { uint32_t port_id_action_list; /* List of port ID actions. */ uint32_t push_vlan_action_list; /* List of push VLAN actions. */ struct mlx5_flow_counter_mng cmng; /* Counters management structure. */ + void *default_miss_action; /* Pointer to the rdma-core action. */ + rte_atomic32_t default_miss_refcnt; + /* Default miss action reference counter. */ struct mlx5_indexed_pool *ipool[MLX5_IPOOL_MAX]; /* Memory Pool for mlx5 flow resources. */ /* Shared interrupt handler section. */ @@ -801,6 +804,8 @@ int mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev, int mlx5_ctrl_flow(struct rte_eth_dev *dev, struct rte_flow_item_eth *eth_spec, struct rte_flow_item_eth *eth_mask); +int mlx5_flow_default_miss(struct rte_eth_dev *dev, + struct rte_flow_item_eth *eth_spec); struct rte_flow *mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev); int mlx5_flow_create_drop_queue(struct rte_eth_dev *dev); void mlx5_flow_delete_drop_queue(struct rte_eth_dev *dev); diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index f2c3cf9..d3eb42e 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1242,6 +1242,30 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority, } /* + * Validate the default miss action. + * + * @param[in] action_flags + * Bit-fields that holds the actions detected until now. + * @param[out] error + * Pointer to error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_flow_validate_action_default_miss(uint64_t action_flags, + struct rte_flow_error *error) +{ + + if (action_flags & MLX5_FLOW_FATE_ACTIONS) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "can't have 2 fate actions in" + " same flow"); + return 0; +} + +/* * Validate the count action. * * @param[in] dev @@ -4988,6 +5012,54 @@ struct rte_flow * } /** + * Deafult miss flow + * + * @param dev + * Pointer to Ethernet device. + * @param eth_spec + * An Ethernet flow spec to apply. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_flow_default_miss(struct rte_eth_dev *dev, + struct rte_flow_item_eth *eth_spec) +{ + struct mlx5_priv *priv = dev->data->dev_private; + const struct rte_flow_attr attr = { + .ingress = 1, + .priority = 0, + }; + struct rte_flow_item items[] = { + { + .type = RTE_FLOW_ITEM_TYPE_ETH, + .spec = eth_spec, + }, + { + .type = RTE_FLOW_ITEM_TYPE_END, + }, + }; + struct rte_flow_action actions[] = { + { + .type = MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS, + }, + { + .type = RTE_FLOW_ACTION_TYPE_END, + }, + }; + + struct rte_flow_error error; + uint32_t flow_idx; + + flow_idx = flow_list_create(dev, &priv->ctrl_flows, + &attr, items, actions, false, &error); + if (!flow_idx) + return -rte_errno; + return 0; +} + +/** * Destroy a flow. * * @see rte_flow_destroy() diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 2c96677..d489f64 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -43,6 +43,7 @@ enum mlx5_rte_flow_action_type { MLX5_RTE_FLOW_ACTION_TYPE_TAG, MLX5_RTE_FLOW_ACTION_TYPE_MARK, MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, + MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS, }; /* Matches on selected register. */ @@ -200,10 +201,12 @@ enum mlx5_feature_name { #define MLX5_FLOW_ACTION_SET_IPV4_DSCP (1ull << 32) #define MLX5_FLOW_ACTION_SET_IPV6_DSCP (1ull << 33) #define MLX5_FLOW_ACTION_AGE (1ull << 34) +#define MLX5_FLOW_ACTION_DEFAULT_MISS (1ull << 35) #define MLX5_FLOW_FATE_ACTIONS \ (MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | \ - MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_JUMP) + MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_JUMP | \ + MLX5_FLOW_ACTION_DEFAULT_MISS) #define MLX5_FLOW_FATE_ESWITCH_ACTIONS \ (MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_PORT_ID | \ @@ -365,6 +368,7 @@ enum mlx5_flow_fate_type { MLX5_FLOW_FATE_PORT_ID, MLX5_FLOW_FATE_DROP, MLX5_FLOW_FATE_MAX, + MLX5_FLOW_FATE_DEFAULT_MISS }; /* Matcher PRM representation */ @@ -537,7 +541,7 @@ struct mlx5_flow_handle { void *ib_flow; /**< Verbs flow pointer. */ uint32_t split_flow_id:28; /**< Sub flow unique match flow id. */ uint32_t mark:1; /**< Metadate rxq mark flag. */ - uint32_t fate_action:3; /**< Fate action type. */ + uint32_t fate_action:4; /**< Fate action type. */ union { uint32_t rix_hrxq; /**< Hash Rx queue object index. */ uint32_t rix_jump; /**< Index to the jump action resource. */ @@ -946,6 +950,8 @@ int mlx5_flow_validate_action_rss(const struct rte_flow_action *action, const struct rte_flow_attr *attr, uint64_t item_flags, struct rte_flow_error *error); +int mlx5_flow_validate_action_default_miss(uint64_t action_flags, + struct rte_flow_error *error); int mlx5_flow_validate_attributes(struct rte_eth_dev *dev, const struct rte_flow_attr *attributes, struct rte_flow_error *error); diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index e481831..70d9cc3 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -2675,6 +2675,44 @@ struct field_modify_info modify_tcp[] = { } /** + * Find existing default miss resource or create and register a new one. + * + * @param[in, out] dev + * Pointer to rte_eth_dev structure. + * @param[in, out] tbl + * Pointer to flow table resource. + * @parm[in, out] dev_flow + * Pointer to the dev_flow. + * @param[out] error + * pointer to error structure. + * + * @return + * 0 on success otherwise -errno and errno is set. + */ +static int +flow_dv_default_miss_resource_register(struct rte_eth_dev *dev, + struct rte_flow_error *error) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_ibv_shared *sh = priv->sh; + int cnt; + + cnt = rte_atomic32_read(&sh->default_miss_refcnt); + if (!cnt){ + sh->default_miss_action = + mlx5_glue->dr_create_flow_action_default_miss; + if (sh->default_miss_action) + return rte_flow_error_set(error, ENOMEM, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "cannot create default miss action"); + DRV_LOG(DEBUG, "new default miss resource %p: refcnt %d++", + (void *)sh->default_miss_action, cnt); + } + rte_atomic32_inc(&sh->default_miss_refcnt); + return 0; +} + +/** * Find existing table port ID resource or create and register a new one. * * @param[in, out] dev @@ -5215,6 +5253,15 @@ struct field_modify_info modify_tcp[] = { action_flags |= MLX5_FLOW_ACTION_RSS; ++actions_n; break; + case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS: + ret = + mlx5_flow_validate_action_default_miss(action_flags, + error); + if (ret < 0) + return ret; + action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS; + ++actions_n; + break; case RTE_FLOW_ACTION_TYPE_COUNT: ret = flow_dv_validate_action_count(dev, error); if (ret < 0) @@ -8178,6 +8225,14 @@ struct field_modify_info modify_tcp[] = { return -rte_errno; action_flags |= MLX5_FLOW_ACTION_SET_TAG; break; + case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS: + if (flow_dv_default_miss_resource_register + (dev, error)) + return -rte_errno; + action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS; + dev_flow->handle->fate_action = + MLX5_FLOW_FATE_DEFAULT_MISS; + break; case RTE_FLOW_ACTION_TYPE_METER: mtr = actions->conf; if (!flow->meter) { @@ -8270,7 +8325,11 @@ struct field_modify_info modify_tcp[] = { flow_dv_translate_item_eth(match_mask, match_value, items, tunnel, dev_flow->dv.group); - matcher.priority = MLX5_PRIORITY_MAP_L2; + matcher.priority = + ((action_flags & MLX5_FLOW_ACTION_DEFAULT_MISS) & + (!dev_flow->external)) ? + MLX5_PRIORITY_MAP_L3 : + MLX5_PRIORITY_MAP_L2; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : MLX5_FLOW_LAYER_OUTER_L2; break; @@ -8732,6 +8791,34 @@ struct field_modify_info modify_tcp[] = { } /** + * Release a default miss resource. + * + * @param dev + * Pointer to Ethernet device. + * @return + * 1 while a reference on it exists, 0 when freed. + */ +static int +flow_dv_default_miss_resource_release(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_ibv_shared *sh = priv->sh; + + MLX5_ASSERT(sh->default_miss_action); + DRV_LOG(DEBUG, "default miss resource %p: refcnt %d--", + (void *)sh->default_miss_action, + rte_atomic32_read(&sh->default_miss_refcnt)); + if (rte_atomic32_dec_and_test(&sh->default_miss_refcnt)){ + claim_zero(mlx5_glue->destroy_flow_action + (sh->default_miss_action)); + DRV_LOG(DEBUG, "default miss resource %p: removed", + (void *)sh->default_miss_action); + return 0; + } + return 1; +} + +/** * Release a modify-header resource. * * @param handle @@ -8866,6 +8953,8 @@ struct field_modify_info modify_tcp[] = { flow_dv_jump_tbl_resource_release(dev, handle); else if (handle->fate_action == MLX5_FLOW_FATE_PORT_ID) flow_dv_port_id_action_resource_release(dev, handle); + else if (handle->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) + flow_dv_default_miss_resource_release(dev); else DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action); handle->rix_fate = 0; -- 1.8.3.1