X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow.c;h=15a4a8cd984e513d346d37749ae349d0ac6cc813;hb=9267617bb0a6918ee049b1a16062bf0185e2e843;hp=167293920051aea71196aa47848eda1f75ec2294;hpb=08dfff78f200bb9f077b0006ef05ab59dbc40ac8;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 1672939200..15a4a8cd98 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -175,6 +175,9 @@ mlx5_nsh_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask) enum rte_flow_item_type type; switch (proto_mask & proto_spec) { + case 0: + type = RTE_FLOW_ITEM_TYPE_VOID; + break; case RTE_VXLAN_GPE_TYPE_IPV4: type = RTE_FLOW_ITEM_TYPE_IPV4; break; @@ -196,13 +199,16 @@ mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask) enum rte_flow_item_type type; switch (proto_mask & proto_spec) { + case 0: + type = RTE_FLOW_ITEM_TYPE_VOID; + break; case IPPROTO_UDP: type = RTE_FLOW_ITEM_TYPE_UDP; break; case IPPROTO_TCP: type = RTE_FLOW_ITEM_TYPE_TCP; break; - case IPPROTO_IP: + case IPPROTO_IPIP: type = RTE_FLOW_ITEM_TYPE_IPV4; break; case IPPROTO_IPV6: @@ -221,6 +227,9 @@ mlx5_ethertype_to_item_type(rte_be16_t type_spec, enum rte_flow_item_type type; switch (rte_be_to_cpu_16(type_spec & type_mask)) { + case 0: + type = RTE_FLOW_ITEM_TYPE_VOID; + break; case RTE_ETHER_TYPE_TEB: type = is_tunnel ? RTE_FLOW_ITEM_TYPE_ETH : RTE_FLOW_ITEM_TYPE_END; @@ -879,6 +888,29 @@ mlx5_flow_push(struct rte_eth_dev *dev, uint32_t queue, struct rte_flow_error *error); +static struct rte_flow_action_handle * +mlx5_flow_async_action_handle_create(struct rte_eth_dev *dev, uint32_t queue, + const struct rte_flow_op_attr *attr, + const struct rte_flow_indir_action_conf *conf, + const struct rte_flow_action *action, + void *user_data, + struct rte_flow_error *error); + +static int +mlx5_flow_async_action_handle_update(struct rte_eth_dev *dev, uint32_t queue, + const struct rte_flow_op_attr *attr, + struct rte_flow_action_handle *handle, + const void *update, + void *user_data, + struct rte_flow_error *error); + +static int +mlx5_flow_async_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue, + const struct rte_flow_op_attr *attr, + struct rte_flow_action_handle *handle, + void *user_data, + struct rte_flow_error *error); + static const struct rte_flow_ops mlx5_flow_ops = { .validate = mlx5_flow_validate, .create = mlx5_flow_create, @@ -911,6 +943,9 @@ static const struct rte_flow_ops mlx5_flow_ops = { .async_destroy = mlx5_flow_async_flow_destroy, .pull = mlx5_flow_pull, .push = mlx5_flow_push, + .async_action_handle_create = mlx5_flow_async_action_handle_create, + .async_action_handle_update = mlx5_flow_async_action_handle_update, + .async_action_handle_destroy = mlx5_flow_async_action_handle_destroy, }; /* Tunnel information. */ @@ -1717,6 +1752,12 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action, 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, + "queue action not supported for egress."); + if (mlx5_is_external_rxq(dev, queue->index)) + return 0; if (!priv->rxqs_n) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, @@ -1731,11 +1772,6 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action, RTE_FLOW_ERROR_TYPE_ACTION_CONF, &queue->index, "queue is not configured"); - if (attr->egress) - return rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, - "queue action not supported for " - "egress"); return 0; } @@ -1750,7 +1786,7 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action, * Size of the @p queues array. * @param[out] error * On error, filled with a textual error description. - * @param[out] queue + * @param[out] queue_idx * On error, filled with an offending queue index in @p queues array. * * @return @@ -1762,26 +1798,36 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev, const char **error, uint32_t *queue_idx) { const struct mlx5_priv *priv = dev->data->dev_private; - enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED; + bool is_hairpin = false; + bool is_ext_rss = false; uint32_t i; for (i = 0; i != queues_n; ++i) { - struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, - queues[i]); + struct mlx5_rxq_ctrl *rxq_ctrl; + if (mlx5_is_external_rxq(dev, queues[0])) { + is_ext_rss = true; + continue; + } + if (is_ext_rss) { + *error = "Combining external and regular RSS queues is not supported"; + *queue_idx = i; + return -ENOTSUP; + } if (queues[i] >= priv->rxqs_n) { *error = "queue index out of range"; *queue_idx = i; return -EINVAL; } + rxq_ctrl = mlx5_rxq_ctrl_get(dev, queues[i]); if (rxq_ctrl == NULL) { *error = "queue is not configured"; *queue_idx = i; return -EINVAL; } - if (i == 0) - rxq_type = rxq_ctrl->type; - if (rxq_type != rxq_ctrl->type) { + if (i == 0 && rxq_ctrl->is_hairpin) + is_hairpin = true; + if (is_hairpin != rxq_ctrl->is_hairpin) { *error = "combining hairpin and regular RSS queues is not supported"; *queue_idx = i; return -ENOTSUP; @@ -1868,7 +1914,7 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, "L4 partial RSS requested but L4 RSS" " type not specified"); - if (!priv->rxqs_n) + if (!priv->rxqs_n && priv->ext_rxqs == NULL) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, "No Rx queues configured"); @@ -2900,6 +2946,107 @@ mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item, return ret; } +/** + * Validate GRE optional item. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * @param[in] item + * Item specification. + * @param[in] item_flags + * Bit flags to mark detected items. + * @param[in] attr + * Flow rule attributes. + * @param[in] gre_item + * Pointer to gre_item + * @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_item_gre_option(struct rte_eth_dev *dev, + const struct rte_flow_item *item, + uint64_t item_flags, + const struct rte_flow_attr *attr, + const struct rte_flow_item *gre_item, + struct rte_flow_error *error) +{ + const struct rte_flow_item_gre *gre_spec = gre_item->spec; + const struct rte_flow_item_gre *gre_mask = gre_item->mask; + const struct rte_flow_item_gre_opt *spec = item->spec; + const struct rte_flow_item_gre_opt *mask = item->mask; + struct mlx5_priv *priv = dev->data->dev_private; + int ret = 0; + struct rte_flow_item_gre_opt nic_mask = { + .checksum_rsvd = { + .checksum = RTE_BE16(UINT16_MAX), + .reserved1 = 0x0, + }, + .key = { + .key = RTE_BE32(UINT32_MAX), + }, + .sequence = { + .sequence = RTE_BE32(UINT32_MAX), + }, + }; + + if (!(item_flags & MLX5_FLOW_LAYER_GRE)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "No preceding GRE header"); + if (item_flags & MLX5_FLOW_LAYER_INNER) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "GRE option following a wrong item"); + if (!spec || !mask) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "At least one field gre_option(checksum/key/sequence) must be specified"); + if (!gre_mask) + gre_mask = &rte_flow_item_gre_mask; + if (mask->checksum_rsvd.checksum) + if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x8000)) && + !(gre_spec->c_rsvd0_ver & RTE_BE16(0x8000))) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Checksum bit must be on"); + if (mask->key.key) + if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) && + !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000))) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Key bit must be on"); + if (mask->sequence.sequence) + if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x1000)) && + !(gre_spec->c_rsvd0_ver & RTE_BE16(0x1000))) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Sequence bit must be on"); + if (mask->checksum_rsvd.checksum || mask->sequence.sequence) { + if (priv->sh->steering_format_version == + MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 || + ((attr->group || attr->transfer) && + !priv->sh->misc5_cap) || + (!(priv->sh->tunnel_header_0_1 && + priv->sh->tunnel_header_2_3) && + !attr->group && !attr->transfer)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Checksum/Sequence not supported"); + } + ret = mlx5_flow_item_acceptable + (item, (const uint8_t *)mask, + (const uint8_t *)&nic_mask, + sizeof(struct rte_flow_item_gre_opt), + MLX5_ITEM_RANGE_NOT_ACCEPTED, error); + return ret; +} + /** * Validate GRE item. * @@ -5859,15 +6006,13 @@ flow_create_split_metadata(struct rte_eth_dev *dev, const struct rte_flow_action_queue *queue; queue = qrss->conf; - if (mlx5_rxq_get_type(dev, queue->index) == - MLX5_RXQ_TYPE_HAIRPIN) + if (mlx5_rxq_is_hairpin(dev, queue->index)) qrss = NULL; } else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) { const struct rte_flow_action_rss *rss; rss = qrss->conf; - if (mlx5_rxq_get_type(dev, rss->queue[0]) == - MLX5_RXQ_TYPE_HAIRPIN) + if (mlx5_rxq_is_hairpin(dev, rss->queue[0])) qrss = NULL; } } @@ -6151,6 +6296,8 @@ flow_create_split_meter(struct rte_eth_dev *dev, fm->policy_id, NULL); MLX5_ASSERT(wks->policy); + if (wks->policy->mark) + wks->mark = 1; if (wks->policy->is_hierarchy) { wks->final_policy = mlx5_flow_meter_hierarchy_get_final_policy(dev, @@ -8367,6 +8514,111 @@ mlx5_flow_push(struct rte_eth_dev *dev, return fops->push(dev, queue, error); } +/** + * Create shared action. + * + * @param[in] dev + * Pointer to the rte_eth_dev structure. + * @param[in] queue + * Which queue to be used.. + * @param[in] attr + * Operation attribute. + * @param[in] conf + * Indirect action configuration. + * @param[in] action + * rte_flow action detail. + * @param[in] user_data + * Pointer to the user_data. + * @param[out] error + * Pointer to error structure. + * + * @return + * Action handle on success, NULL otherwise and rte_errno is set. + */ +static struct rte_flow_action_handle * +mlx5_flow_async_action_handle_create(struct rte_eth_dev *dev, uint32_t queue, + const struct rte_flow_op_attr *attr, + const struct rte_flow_indir_action_conf *conf, + const struct rte_flow_action *action, + void *user_data, + struct rte_flow_error *error) +{ + const struct mlx5_flow_driver_ops *fops = + flow_get_drv_ops(MLX5_FLOW_TYPE_HW); + + return fops->async_action_create(dev, queue, attr, conf, action, + user_data, error); +} + +/** + * Update shared action. + * + * @param[in] dev + * Pointer to the rte_eth_dev structure. + * @param[in] queue + * Which queue to be used.. + * @param[in] attr + * Operation attribute. + * @param[in] handle + * Action handle to be updated. + * @param[in] update + * Update value. + * @param[in] user_data + * Pointer to the user_data. + * @param[out] error + * Pointer to error structure. + * + * @return + * 0 on success, negative value otherwise and rte_errno is set. + */ +static int +mlx5_flow_async_action_handle_update(struct rte_eth_dev *dev, uint32_t queue, + const struct rte_flow_op_attr *attr, + struct rte_flow_action_handle *handle, + const void *update, + void *user_data, + struct rte_flow_error *error) +{ + const struct mlx5_flow_driver_ops *fops = + flow_get_drv_ops(MLX5_FLOW_TYPE_HW); + + return fops->async_action_update(dev, queue, attr, handle, + update, user_data, error); +} + +/** + * Destroy shared action. + * + * @param[in] dev + * Pointer to the rte_eth_dev structure. + * @param[in] queue + * Which queue to be used.. + * @param[in] attr + * Operation attribute. + * @param[in] handle + * Action handle to be destroyed. + * @param[in] user_data + * Pointer to the user_data. + * @param[out] error + * Pointer to error structure. + * + * @return + * 0 on success, negative value otherwise and rte_errno is set. + */ +static int +mlx5_flow_async_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue, + const struct rte_flow_op_attr *attr, + struct rte_flow_action_handle *handle, + void *user_data, + struct rte_flow_error *error) +{ + const struct mlx5_flow_driver_ops *fops = + flow_get_drv_ops(MLX5_FLOW_TYPE_HW); + + return fops->async_action_destroy(dev, queue, attr, handle, + user_data, error); +} + /** * Allocate a new memory for the counter values wrapped by all the needed * management. @@ -9439,14 +9691,10 @@ int mlx5_action_handle_attach(struct rte_eth_dev *dev) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_indexed_pool *ipool = - priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS]; - struct mlx5_shared_action_rss *shared_rss, *shared_rss_last; int ret = 0; - uint32_t idx; + struct mlx5_ind_table_obj *ind_tbl, *ind_tbl_last; - ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) { - struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl; + LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { const char *message; uint32_t queue_idx; @@ -9462,9 +9710,7 @@ mlx5_action_handle_attach(struct rte_eth_dev *dev) } if (ret != 0) return ret; - ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) { - struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl; - + LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { ret = mlx5_ind_table_obj_attach(dev, ind_tbl); if (ret != 0) { DRV_LOG(ERR, "Port %u could not attach " @@ -9473,13 +9719,12 @@ mlx5_action_handle_attach(struct rte_eth_dev *dev) goto error; } } + return 0; error: - shared_rss_last = shared_rss; - ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) { - struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl; - - if (shared_rss == shared_rss_last) + ind_tbl_last = ind_tbl; + LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { + if (ind_tbl == ind_tbl_last) break; if (mlx5_ind_table_obj_detach(dev, ind_tbl) != 0) DRV_LOG(CRIT, "Port %u could not detach " @@ -9502,15 +9747,10 @@ int mlx5_action_handle_detach(struct rte_eth_dev *dev) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_indexed_pool *ipool = - priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS]; - struct mlx5_shared_action_rss *shared_rss, *shared_rss_last; int ret = 0; - uint32_t idx; - - ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) { - struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl; + struct mlx5_ind_table_obj *ind_tbl, *ind_tbl_last; + LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { ret = mlx5_ind_table_obj_detach(dev, ind_tbl); if (ret != 0) { DRV_LOG(ERR, "Port %u could not detach " @@ -9521,11 +9761,9 @@ mlx5_action_handle_detach(struct rte_eth_dev *dev) } return 0; error: - shared_rss_last = shared_rss; - ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) { - struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl; - - if (shared_rss == shared_rss_last) + ind_tbl_last = ind_tbl; + LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { + if (ind_tbl == ind_tbl_last) break; if (mlx5_ind_table_obj_attach(dev, ind_tbl) != 0) DRV_LOG(CRIT, "Port %u could not attach "