}
 }
 
+bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id)
+{
+       struct devx_obj *devx_obj = obj;
+       u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
+
+       if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) {
+               *counter_id = MLX5_GET(dealloc_flow_counter_in,
+                                      devx_obj->dinbox,
+                                      flow_counter_id);
+               return true;
+       }
+
+       return false;
+}
+
 /*
  * As the obj_id in the firmware is not globally unique the object type
  * must be considered upon checking for a valid object id.
 
                uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
        struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
        int len, ret, i;
+       u32 counter_id = 0;
 
        if (!capable(CAP_NET_RAW))
                return -EPERM;
                dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT;
        }
 
+       len = uverbs_attr_get_uobjs_arr(attrs,
+               MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions);
+       if (len) {
+               devx_obj = arr_flow_actions[0]->object;
+
+               if (!mlx5_ib_devx_is_flow_counter(devx_obj, &counter_id))
+                       return -EINVAL;
+               flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       }
        if (dev->rep)
                return -ENOTSUPP;
 
        }
 
        flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, &flow_act,
+                                              counter_id,
                                               cmd_in, inlen,
                                               dest_id, dest_type);
        if (IS_ERR(flow_handler)) {
                             UA_OPTIONAL),
        UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG,
                           UVERBS_ATTR_TYPE(u32),
-                          UA_OPTIONAL));
+                          UA_OPTIONAL),
+       UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
+                            MLX5_IB_OBJECT_DEVX_OBJ,
+                            UVERBS_ACCESS_READ, 1, 1,
+                            UA_OPTIONAL));
 
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
        MLX5_IB_METHOD_DESTROY_FLOW,
 
                      struct mlx5_flow_destination *dst,
                      struct mlx5_ib_flow_matcher  *fs_matcher,
                      struct mlx5_flow_act *flow_act,
-                     void *cmd_in, int inlen)
+                     void *cmd_in, int inlen,
+                     int dst_num)
 {
        struct mlx5_ib_flow_handler *handler;
        struct mlx5_flow_spec *spec;
        spec->match_criteria_enable = fs_matcher->match_criteria_enable;
 
        handler->rule = mlx5_add_flow_rules(ft, spec,
-                                           flow_act, dst, 1);
+                                           flow_act, dst, dst_num);
 
        if (IS_ERR(handler->rule)) {
                err = PTR_ERR(handler->rule);
 mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev,
                        struct mlx5_ib_flow_matcher *fs_matcher,
                        struct mlx5_flow_act *flow_act,
+                       u32 counter_id,
                        void *cmd_in, int inlen, int dest_id,
                        int dest_type)
 {
        struct mlx5_flow_destination *dst;
        struct mlx5_ib_flow_prio *ft_prio;
        struct mlx5_ib_flow_handler *handler;
+       int dst_num = 0;
        bool mcast;
        int err;
 
        if (fs_matcher->priority > MLX5_IB_FLOW_LAST_PRIO)
                return ERR_PTR(-ENOMEM);
 
-       dst = kzalloc(sizeof(*dst), GFP_KERNEL);
+       dst = kzalloc(sizeof(*dst) * 2, GFP_KERNEL);
        if (!dst)
                return ERR_PTR(-ENOMEM);
 
        }
 
        if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR) {
-               dst->type = dest_type;
-               dst->tir_num = dest_id;
+               dst[dst_num].type = dest_type;
+               dst[dst_num].tir_num = dest_id;
                flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
        } else if (dest_type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) {
-               dst->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM;
-               dst->ft_num = dest_id;
+               dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM;
+               dst[dst_num].ft_num = dest_id;
                flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
        } else {
-               dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT;
+               dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_PORT;
                flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
        }
 
+       dst_num++;
+
+       if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+               dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+               dst[dst_num].counter_id = counter_id;
+               dst_num++;
+       }
+
        handler = _create_raw_flow_rule(dev, ft_prio, dst, fs_matcher, flow_act,
-                                       cmd_in, inlen);
+                                       cmd_in, inlen, dst_num);
 
        if (IS_ERR(handler)) {
                err = PTR_ERR(handler);
 
 extern const struct uapi_definition mlx5_ib_flow_defs[];
 struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add(
        struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher,
-       struct mlx5_flow_act *flow_act, void *cmd_in, int inlen,
-       int dest_id, int dest_type);
+       struct mlx5_flow_act *flow_act, u32 counter_id,
+       void *cmd_in, int inlen, int dest_id, int dest_type);
 bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type);
+bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id);
+int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root);
 void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction);
 #else
 static inline int
 
        MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
        MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
        MLX5_IB_ATTR_CREATE_FLOW_TAG,
+       MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
 };
 
 enum mlx5_ib_destoy_flow_attrs {