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

Reply via email to