net/mlx5: fix meter policy creation assert
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index 1672939..15a4a8c 100644 (file)
@@ -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 "