From patchwork Tue Apr 13 00:10:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Zhang X-Patchwork-Id: 91134 X-Patchwork-Delegate: rasland@nvidia.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id CF68CA0524; Tue, 13 Apr 2021 02:11:43 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C4FE71608C9; Tue, 13 Apr 2021 02:10:54 +0200 (CEST) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 5007C16089D for ; Tue, 13 Apr 2021 02:10:45 +0200 (CEST) Received: from Internal Mail-Server by MTLPINE1 (envelope-from lizh@nvidia.com) with SMTP; 13 Apr 2021 03:10:39 +0300 Received: from nvidia.com (c-235-17-1-009.mtl.labs.mlnx [10.235.17.9]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 13D0AbkE021795; Tue, 13 Apr 2021 03:10:39 +0300 From: Li Zhang To: dekelp@nvidia.com, orika@nvidia.com, viacheslavo@nvidia.com, matan@nvidia.com, shahafs@nvidia.com Cc: dev@dpdk.org, thomas@monjalon.net, rasland@nvidia.com, roniba@nvidia.com Date: Tue, 13 Apr 2021 03:10:27 +0300 Message-Id: <20210413001033.1999355-10-lizh@nvidia.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20210413001033.1999355-1-lizh@nvidia.com> References: <20210331073632.1443011-1-lizh@nvidia.com> <20210413001033.1999355-1-lizh@nvidia.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 09/14] net/mlx5: flow meter pool to manage meter object X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add ASO flow meter pool to manage meter object Signed-off-by: Li Zhang Acked-by: Matan Azrad --- drivers/net/mlx5/mlx5.c | 2 +- drivers/net/mlx5/mlx5.h | 207 ++++++++++++- drivers/net/mlx5/mlx5_flow.c | 70 ++++- drivers/net/mlx5/mlx5_flow.h | 196 +++---------- drivers/net/mlx5/mlx5_flow_dv.c | 203 ++++++++++++- drivers/net/mlx5/mlx5_flow_meter.c | 450 ++++++++++++++++++----------- 6 files changed, 769 insertions(+), 359 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 734dee9f19..6440edbc92 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -280,7 +280,7 @@ static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = { * for meter idx, so not set grow_trunk to avoid meter index * not jump continually. */ - .size = sizeof(struct mlx5_flow_meter), + .size = sizeof(struct mlx5_legacy_flow_meter), .trunk_size = 64, .need_lock = 1, .release_mem_en = 1, diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index b50acaca41..2017df4bd5 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -573,6 +574,193 @@ struct mlx5_dev_shared_port { /* Aging information for per port. */ }; +/*ASO flow meter structures*/ +/* Modify this value if enum rte_mtr_color changes. */ +#define RTE_MTR_DROPPED RTE_COLORS + +/* Meter policer statistics */ +struct mlx5_flow_policer_stats { + uint32_t pass_cnt; + /**< Color counter for pass. */ + uint32_t drop_cnt; + /**< Color counter for drop. */ +}; + +/* Meter table structure. */ +struct mlx5_meter_domain_info { + struct mlx5_flow_tbl_resource *tbl; + /**< Meter table. */ + struct mlx5_flow_tbl_resource *sfx_tbl; + /**< Meter suffix table. */ + struct mlx5_flow_dv_matcher *drop_matcher; + /**< Matcher for Drop. */ + struct mlx5_flow_dv_matcher *color_matcher; + /**< Matcher for Color. */ + void *jump_actn; + /**< Meter match action. */ + void *green_rule; + /**< Meter green rule. */ + void *drop_rule; + /**< Meter drop rule. */ +}; + +/* Meter table set for TX RX FDB. */ +struct mlx5_meter_domains_infos { + uint32_t ref_cnt; + /**< Table user count. */ + struct mlx5_meter_domain_info egress; + /**< TX meter table. */ + struct mlx5_meter_domain_info ingress; + /**< RX meter table. */ + struct mlx5_meter_domain_info transfer; + /**< FDB meter table. */ + void *drop_actn; + /**< Drop action as not matched. */ + void *green_count; + /**< Counters for green rule. */ + void *drop_count; + /**< Counters for green rule. */ + void *meter_action; + /**< Flow meter action. */ +}; + +/* Meter parameter structure. */ +struct mlx5_flow_meter_info { + uint32_t meter_id; + /**< Meter id. */ + struct mlx5_flow_meter_profile *profile; + /**< Meter profile parameters. */ + rte_spinlock_t sl; /**< Meter action spinlock. */ + /** Policer actions (per meter output color). */ + enum rte_mtr_policer_action action[RTE_COLORS]; + /** Set of stats counters to be enabled. + * @see enum rte_mtr_stats_type + */ + uint32_t green_bytes:1; + /** Set green bytes stats to be enabled. */ + uint32_t green_pkts:1; + /** Set green packets stats to be enabled. */ + uint32_t red_bytes:1; + /** Set red bytes stats to be enabled. */ + uint32_t red_pkts:1; + /** Set red packets stats to be enabled. */ + uint32_t bytes_dropped:1; + /** Set bytes dropped stats to be enabled. */ + uint32_t pkts_dropped:1; + /** Set packets dropped stats to be enabled. */ + uint32_t active_state:1; + /**< Meter hw active state. */ + uint32_t shared:1; + /**< Meter shared or not. */ + uint32_t is_enable:1; + /**< Meter disable/enable state. */ + uint32_t ingress:1; + /**< Rule applies to egress traffic. */ + uint32_t egress:1; + /** + * Instead of simply matching the properties of traffic as it would + * appear on a given DPDK port ID, enabling this attribute transfers + * a flow rule to the lowest possible level of any device endpoints + * found in the pattern. + * + * When supported, this effectively enables an application to + * re-route traffic not necessarily intended for it (e.g. coming + * from or addressed to different physical ports, VFs or + * applications) at the device level. + * + * It complements the behavior of some pattern items such as + * RTE_FLOW_ITEM_TYPE_PHY_PORT and is meaningless without them. + * + * When transferring flow rules, ingress and egress attributes keep + * their original meaning, as if processing traffic emitted or + * received by the application. + */ + uint32_t transfer:1; + struct mlx5_meter_domains_infos *mfts; + /**< Flow table created for this meter. */ + struct mlx5_flow_policer_stats policer_stats; + /**< Meter policer statistics. */ + uint32_t ref_cnt; + /**< Use count. */ + struct mlx5_indexed_pool *flow_ipool; + /**< Index pool for flow id. */ +}; + +/* RFC2697 parameter structure. */ +struct mlx5_flow_meter_srtcm_rfc2697_prm { + rte_be32_t cbs_cir; + /* + * bit 24-28: cbs_exponent, bit 16-23 cbs_mantissa, + * bit 8-12: cir_exponent, bit 0-7 cir_mantissa. + */ + rte_be32_t ebs_eir; + /* + * bit 24-28: ebs_exponent, bit 16-23 ebs_mantissa, + * bit 8-12: eir_exponent, bit 0-7 eir_mantissa. + */ +}; + +/* Flow meter profile structure. */ +struct mlx5_flow_meter_profile { + TAILQ_ENTRY(mlx5_flow_meter_profile) next; + /**< Pointer to the next flow meter structure. */ + uint32_t id; /**< Profile id. */ + struct rte_mtr_meter_profile profile; /**< Profile detail. */ + union { + struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm_prm; + /**< srtcm_rfc2697 struct. */ + }; + uint32_t ref_cnt; /**< Use count. */ +}; + +/* 2 meters in each ASO cache line */ +#define MLX5_MTRS_CONTAINER_RESIZE 64 +/* + * The pool index and offset of meter in the pool array makes up the + * meter index. In case the meter is from pool 0 and offset 0, it + * should plus 1 to avoid index 0, since 0 means invalid meter index + * currently. + */ +#define MLX5_MAKE_MTR_IDX(pi, offset) \ + ((pi) * MLX5_ASO_MTRS_PER_POOL + (offset) + 1) + +/*aso flow meter state*/ +enum mlx5_aso_mtr_state { + ASO_METER_FREE, /* In free list. */ + ASO_METER_WAIT, /* ACCESS_ASO WQE in progress. */ + ASO_METER_READY, /* CQE received. */ +}; + +/* Generic aso_flow_meter information. */ +struct mlx5_aso_mtr { + LIST_ENTRY(mlx5_aso_mtr) next; + struct mlx5_flow_meter_info fm; + /**< Pointer to the next aso flow meter structure. */ + uint8_t state; /**< ASO flow meter state. */ + uint8_t offset; +}; + +/* Generic aso_flow_meter pool structure. */ +struct mlx5_aso_mtr_pool { + struct mlx5_aso_mtr mtrs[MLX5_ASO_MTRS_PER_POOL]; + /*Must be the first in pool*/ + struct mlx5_devx_obj *devx_obj; + /* The devx object of the minimum aso flow meter ID. */ + uint32_t index; /* Pool index in management structure. */ +}; + +LIST_HEAD(aso_meter_list, mlx5_aso_mtr); +/* Pools management structure for ASO flow meter pools. */ +struct mlx5_aso_mtr_pools_mng { + volatile uint16_t n_valid; /* Number of valid pools. */ + uint16_t n; /* Number of pools. */ + rte_spinlock_t mtrsl; /* The ASO flow meter free list lock. */ + struct mlx5_l3t_tbl *mtr_idx_tbl; /* Meter index lookup table. */ + struct aso_meter_list meters; /* Free ASO flow meter list. */ + struct mlx5_aso_sq sq; /*SQ using by ASO flow meter. */ + struct mlx5_aso_mtr_pool **pools; /* ASO flow meter pool array. */ +}; + /* Table key of the hash organization. */ union mlx5_flow_tbl_key { struct { @@ -699,6 +887,7 @@ struct mlx5_dev_ctx_shared { uint32_t rq_ts_format:2; /* RQ timestamp formats supported. */ uint32_t sq_ts_format:2; /* SQ timestamp formats supported. */ uint32_t qp_ts_format:2; /* QP timestamp formats supported. */ + uint32_t meter_aso_en:1; /* Flow Meter ASO is supported. */ uint32_t max_port; /* Maximal IB device port index. */ struct mlx5_bond_info bond; /* Bonding information. */ void *ctx; /* Verbs/DV/DevX context. */ @@ -759,6 +948,8 @@ struct mlx5_dev_ctx_shared { struct mlx5_geneve_tlv_option_resource *geneve_tlv_option_resource; /* Management structure for geneve tlv option */ rte_spinlock_t geneve_tlv_opt_sl; /* Lock for geneve tlv resource */ + struct mlx5_aso_mtr_pools_mng *mtrmng; + /* Meter pools management structure. */ struct mlx5_dev_shared_port port[]; /* per device port data array. */ }; @@ -776,7 +967,7 @@ struct mlx5_proc_priv { /* MTR profile list. */ TAILQ_HEAD(mlx5_mtr_profiles, mlx5_flow_meter_profile); /* MTR list. */ -TAILQ_HEAD(mlx5_flow_meters, mlx5_flow_meter); +TAILQ_HEAD(mlx5_legacy_flow_meters, mlx5_legacy_flow_meter); /* RSS description. */ struct mlx5_flow_rss_desc { @@ -994,7 +1185,7 @@ struct mlx5_priv { uint8_t mtr_sfx_reg; /* Meter prefix-suffix flow match REG_C. */ uint8_t mtr_color_reg; /* Meter color match REG_C. */ struct mlx5_mtr_profiles flow_meter_profiles; /* MTR profile list. */ - struct mlx5_flow_meters flow_meters; /* MTR list. */ + struct mlx5_legacy_flow_meters flow_meters; /* MTR list. */ uint8_t skip_default_rss_reta; /* Skip configuration of default reta. */ uint8_t fdb_def_rule; /* Whether fdb jump to table 1 is configured. */ struct mlx5_mp_id mp_id; /* ID of a multi-process process */ @@ -1273,13 +1464,15 @@ int mlx5_pmd_socket_init(void); /* mlx5_flow_meter.c */ int mlx5_flow_meter_ops_get(struct rte_eth_dev *dev, void *arg); -struct mlx5_flow_meter *mlx5_flow_meter_find(struct mlx5_priv *priv, - uint32_t meter_id); +struct mlx5_flow_meter_info *mlx5_flow_meter_find(struct mlx5_priv *priv, + uint32_t meter_id, uint32_t *mtr_idx); +struct mlx5_flow_meter_info * +flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx); int mlx5_flow_meter_attach(struct mlx5_priv *priv, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr, struct rte_flow_error *error); -void mlx5_flow_meter_detach(struct mlx5_flow_meter *fm); +void mlx5_flow_meter_detach(struct mlx5_flow_meter_info *fm); /* mlx5_os.c */ struct rte_pci_driver; @@ -1324,7 +1517,7 @@ void mlx5_txpp_interrupt_handler(void *cb_arg); eth_tx_burst_t mlx5_select_tx_function(struct rte_eth_dev *dev); -/* mlx5_flow_age.c */ +/* mlx5_flow_aso.c */ int mlx5_aso_queue_init(struct mlx5_dev_ctx_shared *sh); int mlx5_aso_queue_start(struct mlx5_dev_ctx_shared *sh); diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 9f4b926cc3..ac39ac13ab 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -4359,6 +4359,8 @@ flow_create_split_inner(struct rte_eth_dev *dev, * * @param[in] dev * Pointer to Ethernet device. + * @param[in] flow + * Parent flow structure pointer. * @param[in] fm * Pointer to flow meter structure. * @param[in] items @@ -4371,10 +4373,6 @@ flow_create_split_inner(struct rte_eth_dev *dev, * Suffix flow actions. * @param[out] actions_pre * Prefix flow actions. - * @param[out] pattern_sfx - * The pattern items for the suffix flow. - * @param[out] tag_sfx - * Pointer to suffix flow tag. * @param[out] error * Perform verbose error reporting if not NULL. * @@ -4383,7 +4381,8 @@ flow_create_split_inner(struct rte_eth_dev *dev, */ static uint32_t flow_meter_split_prep(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct rte_flow *flow, + struct mlx5_flow_meter_info *fm, const struct rte_flow_item items[], struct rte_flow_item sfx_items[], const struct rte_flow_action actions[], @@ -4504,7 +4503,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev, 0, error), .offset = mtr_id_offset, .length = mtr_reg_bits, - .data = fm->idx, + .data = flow->meter, }; /* * The color Reg bits used by flow_id are growing from @@ -5232,9 +5231,10 @@ flow_create_split_meter(struct rte_eth_dev *dev, struct rte_flow_item *sfx_items = NULL; struct mlx5_flow *dev_flow = NULL; struct rte_flow_attr sfx_attr = *attr; - struct mlx5_flow_meter *fm = NULL; + struct mlx5_flow_meter_info *fm = NULL; bool has_mtr = false; uint32_t meter_id; + uint32_t mtr_idx = 0; uint32_t mtr_tag_id = 0; size_t act_size; size_t item_size; @@ -5246,14 +5246,13 @@ flow_create_split_meter(struct rte_eth_dev *dev, &meter_id); if (has_mtr) { if (flow->meter) { - fm = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], - flow->meter); + fm = flow_dv_meter_find_by_idx(priv, flow->meter); if (!fm) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Meter not found."); } else { - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx); if (!fm) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, @@ -5262,7 +5261,7 @@ flow_create_split_meter(struct rte_eth_dev *dev, &sfx_attr, error); if (ret) return -rte_errno; - flow->meter = fm->idx; + flow->meter = mtr_idx; } wks->fm = fm; /* The prefix actions: meter, decap, encap, tag, end. */ @@ -5282,9 +5281,10 @@ flow_create_split_meter(struct rte_eth_dev *dev, sfx_items = (struct rte_flow_item *)((char *)sfx_actions + act_size); pre_actions = sfx_actions + actions_n; - mtr_tag_id = flow_meter_split_prep(dev, fm, items, sfx_items, - actions, sfx_actions, - pre_actions, error); + mtr_tag_id = flow_meter_split_prep(dev, flow, fm, items, + sfx_items, actions, + sfx_actions, pre_actions, + error); if (!mtr_tag_id) { ret = -rte_errno; goto exit; @@ -6621,7 +6621,7 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev, */ int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr) { const struct mlx5_flow_driver_ops *fops; @@ -6643,7 +6643,7 @@ mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev, */ int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr) { const struct mlx5_flow_driver_ops *fops; @@ -6652,6 +6652,44 @@ mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev, return fops->destroy_policer_rules(dev, fm, attr); } +/** + * Allocate the needed aso flow meter id. + * + * @param[in] dev + * Pointer to Ethernet device. + * + * @return + * Index to aso flow meter on success, NULL otherwise. + */ +uint32_t +mlx5_flow_mtr_alloc(struct rte_eth_dev *dev) +{ + const struct mlx5_flow_driver_ops *fops; + + fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); + return fops->create_meter(dev); +} + +/** + * Free the aso flow meter id. + * + * @param[in] dev + * Pointer to Ethernet device. + * @param[in] mtr_idx + * Index to aso flow meter to be free. + * + * @return + * 0 on success. + */ +void +mlx5_flow_mtr_free(struct rte_eth_dev *dev, uint32_t mtr_idx) +{ + const struct mlx5_flow_driver_ops *fops; + + fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); + fops->free_meter(dev, mtr_idx); +} + /** * Allocate a counter. * diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 11482f178f..b0a743477c 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -827,148 +827,17 @@ struct mlx5_flow { #define MLX5_FLOW_METER_DISABLE 0 #define MLX5_FLOW_METER_ENABLE 1 -#define MLX5_MAN_WIDTH 8 -/* Modify this value if enum rte_mtr_color changes. */ -#define RTE_MTR_DROPPED RTE_COLORS - -/* Meter policer statistics */ -struct mlx5_flow_policer_stats { - uint32_t pass_cnt; - /**< Color counter for pass. */ - uint32_t drop_cnt; - /**< Color counter for drop. */ -}; - -/* Meter table structure. */ -struct mlx5_meter_domain_info { - struct mlx5_flow_tbl_resource *tbl; - /**< Meter table. */ - struct mlx5_flow_tbl_resource *sfx_tbl; - /**< Meter suffix table. */ - struct mlx5_flow_dv_matcher *drop_matcher; - /**< Matcher for Drop. */ - struct mlx5_flow_dv_matcher *color_matcher; - /**< Matcher for Color. */ - void *jump_actn; - /**< Meter match action. */ - void *green_rule; - /**< Meter green rule. */ - void *drop_rule; - /**< Meter drop rule. */ -}; - -/* Meter table set for TX RX FDB. */ -struct mlx5_meter_domains_infos { - uint32_t ref_cnt; - /**< Table user count. */ - struct mlx5_meter_domain_info egress; - /**< TX meter table. */ - struct mlx5_meter_domain_info ingress; - /**< RX meter table. */ - struct mlx5_meter_domain_info transfer; - /**< FDB meter table. */ - void *green_count; - /**< Counters for green rule. */ - void *drop_count; - /**< Counters for green rule. */ - uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)]; - /**< Flow meter parameter. */ - size_t fmp_size; - /**< Flow meter parameter size. */ - void *meter_action; - /**< Flow meter action. */ -}; +#define MLX5_ASO_CQE_RESPONSE_DELAY 10 +#define MLX5_MTR_POLL_CQE_TIMES 100000u -/* Meter parameter structure. */ -struct mlx5_flow_meter { - TAILQ_ENTRY(mlx5_flow_meter) next; +#define MLX5_MAN_WIDTH 8 +/* Legacy Meter parameter structure. */ +struct mlx5_legacy_flow_meter { + struct mlx5_flow_meter_info fm; + /* Must be the first in struct. */ + TAILQ_ENTRY(mlx5_legacy_flow_meter) next; /**< Pointer to the next flow meter structure. */ uint32_t idx; /* Index to meter object. */ - uint32_t meter_id; - /**< Meter id. */ - struct mlx5_flow_meter_profile *profile; - /**< Meter profile parameters. */ - - rte_spinlock_t sl; /**< Meter action spinlock. */ - - /** Policer actions (per meter output color). */ - enum rte_mtr_policer_action action[RTE_COLORS]; - - uint32_t green_bytes:1; - /** Set green bytes stats to be enabled. */ - uint32_t green_pkts:1; - /** Set green packets stats to be enabled. */ - uint32_t red_bytes:1; - /** Set red bytes stats to be enabled. */ - uint32_t red_pkts:1; - /** Set red packets stats to be enabled. */ - uint32_t bytes_dropped:1; - /** Set bytes dropped stats to be enabled. */ - uint32_t pkts_dropped:1; - /** Set packets dropped stats to be enabled. */ - - /**< Rule applies to ingress traffic. */ - uint32_t ingress:1; - - /**< Rule applies to egress traffic. */ - uint32_t egress:1; - /** - * Instead of simply matching the properties of traffic as it would - * appear on a given DPDK port ID, enabling this attribute transfers - * a flow rule to the lowest possible level of any device endpoints - * found in the pattern. - * - * When supported, this effectively enables an application to - * re-route traffic not necessarily intended for it (e.g. coming - * from or addressed to different physical ports, VFs or - * applications) at the device level. - * - * It complements the behavior of some pattern items such as - * RTE_FLOW_ITEM_TYPE_PHY_PORT and is meaningless without them. - * - * When transferring flow rules, ingress and egress attributes keep - * their original meaning, as if processing traffic emitted or - * received by the application. - */ - uint32_t transfer:1; - struct mlx5_meter_domains_infos *mfts; - /**< Flow table created for this meter. */ - struct mlx5_flow_policer_stats policer_stats; - /**< Meter policer statistics. */ - uint32_t ref_cnt; - /**< Use count. */ - uint32_t active_state:1; - /**< Meter state. */ - uint32_t shared:1; - /**< Meter shared or not. */ - struct mlx5_indexed_pool *flow_ipool; - /**< Index pool for flow id. */ -}; - -/* RFC2697 parameter structure. */ -struct mlx5_flow_meter_srtcm_rfc2697_prm { - /* green_saturation_value = cbs_mantissa * 2^cbs_exponent */ - uint32_t cbs_exponent:5; - uint32_t cbs_mantissa:8; - /* cir = 8G * cir_mantissa * 1/(2^cir_exponent) Bytes/Sec */ - uint32_t cir_exponent:5; - uint32_t cir_mantissa:8; - /* yellow _saturation_value = ebs_mantissa * 2^ebs_exponent */ - uint32_t ebs_exponent:5; - uint32_t ebs_mantissa:8; -}; - -/* Flow meter profile structure. */ -struct mlx5_flow_meter_profile { - TAILQ_ENTRY(mlx5_flow_meter_profile) next; - /**< Pointer to the next flow meter structure. */ - uint32_t meter_profile_id; /**< Profile id. */ - struct rte_mtr_meter_profile profile; /**< Profile detail. */ - union { - struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm_prm; - /**< srtcm_rfc2697 struct. */ - }; - uint32_t ref_cnt; /**< Use count. */ }; #define MLX5_MAX_TUNNELS 256 @@ -1094,7 +963,7 @@ struct rte_flow { /**< Device flow handles that are part of the flow. */ uint32_t drv_type:2; /**< Driver type. */ uint32_t tunnel:1; - uint32_t meter:16; /**< Holds flow meter id. */ + uint32_t meter:24; /**< Holds flow meter id. */ uint32_t rix_mreg_copy; /**< Index to metadata register copy table resource. */ uint32_t counter; /**< Holds flow counter. */ @@ -1181,7 +1050,7 @@ struct mlx5_flow_workspace { struct mlx5_flow_rss_desc rss_desc; uint32_t rssq_num; /* Allocated queue num in rss_desc. */ uint32_t flow_idx; /* Intermediate device flow index. */ - struct mlx5_flow_meter *fm; /* Pointer to the meter in flow. */ + struct mlx5_flow_meter_info *fm; /* Pointer to the meter in flow. */ }; struct mlx5_flow_split_info { @@ -1227,12 +1096,16 @@ typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev, struct mlx5_meter_domains_infos *tbls); typedef int (*mlx5_flow_create_policer_rules_t) (struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr); typedef int (*mlx5_flow_destroy_policer_rules_t) (struct rte_eth_dev *dev, - const struct mlx5_flow_meter *fm, + const struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr); +typedef uint32_t (*mlx5_flow_mtr_alloc_t) + (struct rte_eth_dev *dev); +typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev, + uint32_t mtr_idx); typedef uint32_t (*mlx5_flow_counter_alloc_t) (struct rte_eth_dev *dev); typedef void (*mlx5_flow_counter_free_t)(struct rte_eth_dev *dev, @@ -1287,6 +1160,8 @@ struct mlx5_flow_driver_ops { mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls; mlx5_flow_create_policer_rules_t prepare_policer_rules; mlx5_flow_destroy_policer_rules_t destroy_policer_rules; + mlx5_flow_mtr_alloc_t create_meter; + mlx5_flow_mtr_free_t free_meter; mlx5_flow_counter_alloc_t counter_alloc; mlx5_flow_counter_free_t counter_free; mlx5_flow_counter_query_t counter_query; @@ -1346,6 +1221,32 @@ tunnel_use_standard_attr_group_translate return verdict; } +/** + * Get DV flow aso meter by index. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * @param[in] idx + * mlx5 flow aso meter index in the container. + * @param[out] ppool + * mlx5 flow aso meter pool in the container, + * + * @return + * Pointer to the aso meter, NULL otherwise. + */ +static inline struct mlx5_aso_mtr * +mlx5_aso_meter_by_idx(struct mlx5_priv *priv, uint32_t idx) +{ + struct mlx5_aso_mtr_pool *pool; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + + /* Decrease to original index. */ + idx--; + MLX5_ASSERT(idx / MLX5_ASO_MTRS_PER_POOL < mtrmng->n); + pool = mtrmng->pools[idx / MLX5_ASO_MTRS_PER_POOL]; + return &pool->mtrs[idx % MLX5_ASO_MTRS_PER_POOL]; +} + int mlx5_flow_group_to_table(struct rte_eth_dev *dev, const struct mlx5_flow_tunnel *tunnel, uint32_t group, uint32_t *table, @@ -1489,10 +1390,10 @@ struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev, struct mlx5_meter_domains_infos *tbl); int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr); int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr); int mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error); @@ -1588,12 +1489,11 @@ struct mlx5_aso_age_action *flow_aso_age_get_by_idx(struct rte_eth_dev *dev, int flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev, const struct rte_flow_item *item, struct rte_flow_error *error); - void flow_release_workspace(void *data); int mlx5_flow_os_init_workspace_once(void); void *mlx5_flow_os_get_specific_workspace(void); int mlx5_flow_os_set_specific_workspace(struct mlx5_flow_workspace *data); void mlx5_flow_os_release_workspace(void); - - +uint32_t mlx5_flow_mtr_alloc(struct rte_eth_dev *dev); +void mlx5_flow_mtr_free(struct rte_eth_dev *dev, uint32_t mtr_idx); #endif /* RTE_PMD_MLX5_FLOW_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index b0bb2eb053..fda87bf845 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -4865,7 +4865,7 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev, { struct mlx5_priv *priv = dev->data->dev_private; const struct rte_flow_action_meter *am = action->conf; - struct mlx5_flow_meter *fm; + struct mlx5_flow_meter_info *fm; if (!am) return rte_flow_error_set(error, EINVAL, @@ -4885,7 +4885,7 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "meter action not supported"); - fm = mlx5_flow_meter_find(priv, am->mtr_id); + fm = mlx5_flow_meter_find(priv, am->mtr_id, NULL); if (!fm) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL, @@ -5938,6 +5938,161 @@ flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t counter) } } +/** + * Resize a meter id container. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * + * @return + * 0 on success, otherwise negative errno value and rte_errno is set. + */ +static int +flow_dv_mtr_container_resize(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + void *old_pools = mtrmng->pools; + uint32_t resize = mtrmng->n + MLX5_MTRS_CONTAINER_RESIZE; + uint32_t mem_size = sizeof(struct mlx5_aso_mtr_pool *) * resize; + void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY); + + if (!pools) { + rte_errno = ENOMEM; + return -ENOMEM; + } + if (old_pools) + memcpy(pools, old_pools, mtrmng->n * + sizeof(struct mlx5_aso_mtr_pool *)); + mtrmng->n = resize; + mtrmng->pools = pools; + if (old_pools) + mlx5_free(old_pools); + return 0; +} + +/** + * Prepare a new meter and/or a new meter pool. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * @param[out] mtr_free + * Where to put the pointer of a new meter.g. + * + * @return + * The meter pool pointer and @mtr_free is set on success, + * NULL otherwise and rte_errno is set. + */ +static struct mlx5_aso_mtr_pool * +flow_dv_mtr_pool_create(struct rte_eth_dev *dev, + struct mlx5_aso_mtr **mtr_free) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + struct mlx5_aso_mtr_pool *pool = NULL; + struct mlx5_devx_obj *dcs = NULL; + uint32_t i; + uint32_t log_obj_size; + + log_obj_size = rte_log2_u32(MLX5_ASO_MTRS_PER_POOL >> 1); + dcs = mlx5_devx_cmd_create_flow_meter_aso_obj(priv->sh->ctx, + priv->sh->pdn, log_obj_size); + if (!dcs) { + rte_errno = ENODATA; + return NULL; + } + pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY); + if (!pool) { + rte_errno = ENOMEM; + claim_zero(mlx5_devx_cmd_destroy(dcs)); + return NULL; + } + pool->devx_obj = dcs; + pool->index = mtrmng->n_valid; + if (pool->index == mtrmng->n && flow_dv_mtr_container_resize(dev)) { + mlx5_free(pool); + claim_zero(mlx5_devx_cmd_destroy(dcs)); + return NULL; + } + mtrmng->pools[pool->index] = pool; + mtrmng->n_valid++; + for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) { + pool->mtrs[i].offset = i; + pool->mtrs[i].fm.meter_id = UINT32_MAX; + LIST_INSERT_HEAD(&mtrmng->meters, + &pool->mtrs[i], next); + } + pool->mtrs[0].offset = 0; + pool->mtrs[0].fm.meter_id = UINT32_MAX; + *mtr_free = &pool->mtrs[0]; + return pool; +} + +/** + * Release a flow meter into pool. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * @param[in] mtr_idx + * Index to aso flow meter. + */ +static void +flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + struct mlx5_aso_mtr *aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx); + + MLX5_ASSERT(aso_mtr); + rte_spinlock_lock(&mtrmng->mtrsl); + memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info)); + aso_mtr->state = ASO_METER_FREE; + aso_mtr->fm.meter_id = UINT32_MAX; + LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next); + rte_spinlock_unlock(&mtrmng->mtrsl); +} + +/** + * Allocate a aso flow meter. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * + * @return + * Index to aso flow meter on success, 0 otherwise and rte_errno is set. + */ +static uint32_t +flow_dv_mtr_alloc(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr *mtr_free = NULL; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + struct mlx5_aso_mtr_pool *pool; + uint32_t mtr_idx = 0; + + if (!priv->config.devx) { + rte_errno = ENOTSUP; + return 0; + } + /* Allocate the flow meter memory. */ + /* Get free meters from management. */ + rte_spinlock_lock(&mtrmng->mtrsl); + mtr_free = LIST_FIRST(&mtrmng->meters); + if (mtr_free) + LIST_REMOVE(mtr_free, next); + if (!mtr_free && !flow_dv_mtr_pool_create(dev, &mtr_free)) { + rte_spinlock_unlock(&mtrmng->mtrsl); + return 0; + } + mtr_free->state = ASO_METER_WAIT; + rte_spinlock_unlock(&mtrmng->mtrsl); + pool = container_of(mtr_free, + struct mlx5_aso_mtr_pool, + mtrs[mtr_free->offset]); + mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset); + return mtr_idx; +} + /** * Verify the @p attributes will be correctly understood by the NIC and store * them in the @p flow if everything is correct. @@ -12568,7 +12723,7 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) { struct mlx5_flow_handle *dev_handle; struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meter *fm = NULL; + struct mlx5_flow_meter_info *fm = NULL; uint32_t srss = 0; if (!flow) @@ -12579,8 +12734,7 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) flow->counter = 0; } if (flow->meter) { - fm = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], - flow->meter); + fm = flow_dv_meter_find_by_idx(priv, flow->meter); if (fm) mlx5_flow_meter_detach(fm); flow->meter = 0; @@ -13678,7 +13832,7 @@ flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev, */ static int flow_dv_destroy_policer_rules(struct rte_eth_dev *dev, - const struct mlx5_flow_meter *fm, + const struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr) { struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL; @@ -13701,6 +13855,8 @@ flow_dv_destroy_policer_rules(struct rte_eth_dev *dev, * Pointer to Ethernet device. * @param[in] fm * Pointer to flow meter structure. + * @param[in] mtr_idx + * meter index. * @param[in] mtb * Pointer to DV meter table set. * @param[out] drop_rule @@ -13713,7 +13869,8 @@ flow_dv_destroy_policer_rules(struct rte_eth_dev *dev, */ static int flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, + uint32_t mtr_idx, struct mlx5_meter_domain_info *dtb, void **drop_rule, void **green_rule) @@ -13761,7 +13918,7 @@ flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev, /* Create Drop flow, matching meter_id only. */ i = 0; flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c, - (fm->idx << mtr_id_offset), UINT32_MAX); + (mtr_idx << mtr_id_offset), UINT32_MAX); if (mtb->drop_count) actions[i++] = mtb->drop_count; actions[i++] = priv->sh->dr_drop_action; @@ -13775,7 +13932,7 @@ flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev, i = 0; if (priv->mtr_reg_share) { flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c, - ((fm->idx << mtr_id_offset) | + ((mtr_idx << mtr_id_offset) | rte_col_2_mlx5_col(RTE_COLOR_GREEN)), UINT32_MAX); } else { @@ -13783,7 +13940,7 @@ flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev, rte_col_2_mlx5_col(RTE_COLOR_GREEN), UINT32_MAX); flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c, - fm->idx, UINT32_MAX); + mtr_idx, UINT32_MAX); } if (mtb->green_count) actions[i++] = mtb->green_count; @@ -13816,9 +13973,10 @@ flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev, */ static int flow_dv_prepare_policer_rules(struct rte_eth_dev *dev, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr) { + struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_meter_domains_infos *mtb = fm->mfts; bool initialized = false; struct mlx5_flow_counter *cnt; @@ -13828,6 +13986,7 @@ flow_dv_prepare_policer_rules(struct rte_eth_dev *dev, void *ingress_green_rule = NULL; void *transfer_drop_rule = NULL; void *transfer_green_rule = NULL; + uint32_t mtr_idx; int ret; /* Get the statistics counters for green/drop. */ @@ -13854,9 +14013,23 @@ flow_dv_prepare_policer_rules(struct rte_eth_dev *dev, */ if (mtb->egress.drop_rule) initialized = true; + if (priv->sh->meter_aso_en) { + struct mlx5_aso_mtr *aso_mtr = NULL; + struct mlx5_aso_mtr_pool *pool; + + aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm); + pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool, + mtrs[aso_mtr->offset]); + mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset); + } else { + struct mlx5_legacy_flow_meter *legacy_fm; + + legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm); + mtr_idx = legacy_fm->idx; + } if (attr->egress) { ret = flow_dv_create_policer_forward_rule(dev, - fm, &mtb->egress, + fm, mtr_idx, &mtb->egress, &egress_drop_rule, &egress_green_rule); if (ret) { DRV_LOG(ERR, "Failed to create egress policer."); @@ -13865,7 +14038,7 @@ flow_dv_prepare_policer_rules(struct rte_eth_dev *dev, } if (attr->ingress) { ret = flow_dv_create_policer_forward_rule(dev, - fm, &mtb->ingress, + fm, mtr_idx, &mtb->ingress, &ingress_drop_rule, &ingress_green_rule); if (ret) { DRV_LOG(ERR, "Failed to create ingress policer."); @@ -13874,7 +14047,7 @@ flow_dv_prepare_policer_rules(struct rte_eth_dev *dev, } if (attr->transfer) { ret = flow_dv_create_policer_forward_rule(dev, - fm, &mtb->transfer, + fm, mtr_idx, &mtb->transfer, &transfer_drop_rule, &transfer_green_rule); if (ret) { DRV_LOG(ERR, "Failed to create transfer policer."); @@ -14214,6 +14387,8 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = { .destroy_mtr_tbls = flow_dv_destroy_mtr_tbl, .prepare_policer_rules = flow_dv_prepare_policer_rules, .destroy_policer_rules = flow_dv_destroy_policer_rules, + .create_meter = flow_dv_mtr_alloc, + .free_meter = flow_dv_aso_mtr_release_to_pool, .counter_alloc = flow_dv_counter_allocate, .counter_free = flow_dv_counter_free, .counter_query = flow_dv_counter_query, diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c index 2a37decaaf..956a6c33e7 100644 --- a/drivers/net/mlx5/mlx5_flow_meter.c +++ b/drivers/net/mlx5/mlx5_flow_meter.c @@ -28,40 +28,43 @@ */ static void * mlx5_flow_meter_action_create(struct mlx5_priv *priv, - struct mlx5_flow_meter *fm) + struct mlx5_flow_meter_info *fm) { #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER struct mlx5dv_dr_flow_meter_attr mtr_init; - void *attr = fm->mfts->fmp; + uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)]; struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fm->profile->srtcm_prm; + uint32_t cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir); + uint32_t ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir); + uint32_t val; - fm->mfts->fmp_size = MLX5_ST_SZ_BYTES(flow_meter_parameters); - memset(attr, 0, fm->mfts->fmp_size); - MLX5_SET(flow_meter_parameters, attr, valid, 1); - MLX5_SET(flow_meter_parameters, attr, bucket_overflow, 1); - MLX5_SET(flow_meter_parameters, attr, - start_color, MLX5_FLOW_COLOR_GREEN); - MLX5_SET(flow_meter_parameters, attr, both_buckets_on_green, 0); - MLX5_SET(flow_meter_parameters, - attr, cbs_exponent, srtcm->cbs_exponent); - MLX5_SET(flow_meter_parameters, - attr, cbs_mantissa, srtcm->cbs_mantissa); - MLX5_SET(flow_meter_parameters, - attr, cir_exponent, srtcm->cir_exponent); - MLX5_SET(flow_meter_parameters, - attr, cir_mantissa, srtcm->cir_mantissa); - MLX5_SET(flow_meter_parameters, - attr, ebs_exponent, srtcm->ebs_exponent); - MLX5_SET(flow_meter_parameters, - attr, ebs_mantissa, srtcm->ebs_mantissa); + memset(fmp, 0, MLX5_ST_SZ_BYTES(flow_meter_parameters)); + MLX5_SET(flow_meter_parameters, fmp, valid, 1); + MLX5_SET(flow_meter_parameters, fmp, bucket_overflow, 1); + MLX5_SET(flow_meter_parameters, fmp, + start_color, MLX5_FLOW_COLOR_GREEN); + MLX5_SET(flow_meter_parameters, fmp, both_buckets_on_green, 0); + val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK; + MLX5_SET(flow_meter_parameters, fmp, cbs_exponent, val); + val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK; + MLX5_SET(flow_meter_parameters, fmp, cbs_mantissa, val); + val = (cbs_cir >> ASO_DSEG_CIR_EXP_OFFSET) & ASO_DSEG_EXP_MASK; + MLX5_SET(flow_meter_parameters, fmp, cir_exponent, val); + val = (cbs_cir & ASO_DSEG_MAN_MASK); + MLX5_SET(flow_meter_parameters, fmp, cir_mantissa, val); + val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK; + MLX5_SET(flow_meter_parameters, fmp, ebs_exponent, val); + val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK; + MLX5_SET(flow_meter_parameters, fmp, ebs_mantissa, val); mtr_init.next_table = fm->transfer ? fm->mfts->transfer.tbl->obj : - fm->egress ? fm->mfts->egress.tbl->obj : - fm->mfts->ingress.tbl->obj; + fm->egress ? fm->mfts->egress.tbl->obj : + fm->mfts->ingress.tbl->obj; mtr_init.reg_c_index = priv->mtr_color_reg - REG_C_0; - mtr_init.flow_meter_parameter = fm->mfts->fmp; - mtr_init.flow_meter_parameter_sz = fm->mfts->fmp_size; + mtr_init.flow_meter_parameter = fmp; + mtr_init.flow_meter_parameter_sz = + MLX5_ST_SZ_BYTES(flow_meter_parameters); mtr_init.active = fm->active_state; return mlx5_glue->dv_create_flow_action_meter(&mtr_init); #else @@ -89,7 +92,7 @@ mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id) struct mlx5_flow_meter_profile *fmp; TAILQ_FOREACH(fmp, fmps, next) - if (meter_profile_id == fmp->meter_profile_id) + if (meter_profile_id == fmp->id) return fmp; return NULL; } @@ -239,44 +242,51 @@ mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, { struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm; uint8_t man, exp; + uint32_t cbs_exp, cbs_man, cir_exp, cir_man; + uint32_t ebs_exp, ebs_man; if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697) return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, "Metering algorithm not supported."); + /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */ + mlx5_flow_meter_cir_man_exp_calc(fmp->profile.srtcm_rfc2697.cir, + &man, &exp); + /* Check if cir mantissa is too large. */ + if (exp > ASO_DSEG_CIR_EXP_MASK) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "meter profile parameter cir is" + " not supported."); + cir_man = man; + cir_exp = exp; /* cbs = cbs_mantissa * 2^cbs_exponent */ mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.cbs, &man, &exp); - srtcm->cbs_mantissa = man; - srtcm->cbs_exponent = exp; /* Check if cbs mantissa is too large. */ - if (srtcm->cbs_exponent != exp) - return -rte_mtr_error_set(error, EINVAL, + if (exp > ASO_DSEG_EXP_MASK) + return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, - "Metering profile parameter cbs is" - " invalid."); - /* ebs = ebs_mantissa * 2^ebs_exponent */ + "meter profile parameter cbs is" + " not supported."); + cbs_man = man; + cbs_exp = exp; + srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET | + cbs_man << ASO_DSEG_CBS_MAN_OFFSET | + cir_exp << ASO_DSEG_CIR_EXP_OFFSET | + cir_man); mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.ebs, &man, &exp); - srtcm->ebs_mantissa = man; - srtcm->ebs_exponent = exp; /* Check if ebs mantissa is too large. */ - if (srtcm->ebs_exponent != exp) - return -rte_mtr_error_set(error, EINVAL, - RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, - "Metering profile parameter ebs is" - " invalid."); - /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */ - mlx5_flow_meter_cir_man_exp_calc(fmp->profile.srtcm_rfc2697.cir, - &man, &exp); - srtcm->cir_mantissa = man; - srtcm->cir_exponent = exp; - /* Check if cir mantissa is too large. */ - if (srtcm->cir_exponent != exp) - return -rte_mtr_error_set(error, EINVAL, + if (exp > ASO_DSEG_EXP_MASK) + return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, - "Metering profile parameter cir is" - " invalid."); + "meter profile parameter ebs is" + " not supported."); + ebs_man = man; + ebs_exp = exp; + srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET | + ebs_man << ASO_DSEG_EBS_MAN_OFFSET); return 0; } @@ -306,7 +316,11 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); memset(cap, 0, sizeof(*cap)); - cap->n_max = 1 << qattr->log_max_flow_meter; + if (priv->sh->meter_aso_en) + /* 2 meters per one ASO cache line. */ + cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1); + else + cap->n_max = 1 << qattr->log_max_flow_meter; cap->n_shared_max = cap->n_max; cap->identical = 1; cap->shared_identical = 1; @@ -365,7 +379,7 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev, NULL, "Meter profile memory " "alloc failed."); /* Fill profile info. */ - fmp->meter_profile_id = meter_profile_id; + fmp->id = meter_profile_id; fmp->profile = *profile; /* Fill the flow meter parameters for the PRM. */ ret = mlx5_flow_meter_param_fill(fmp, error); @@ -499,7 +513,7 @@ mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id, NULL, "Green color only supports recolor green action."); /* Validate meter id. */ - if (mlx5_flow_meter_find(priv, meter_id)) + if (mlx5_flow_meter_find(priv, meter_id, NULL)) return -rte_mtr_error_set(error, EEXIST, RTE_MTR_ERROR_TYPE_MTR_ID, NULL, "Meter object already exists."); @@ -524,7 +538,7 @@ mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id, */ static int mlx5_flow_meter_action_modify(struct mlx5_priv *priv, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm, uint64_t modify_bits, uint32_t active_state) { @@ -533,33 +547,37 @@ mlx5_flow_meter_action_modify(struct mlx5_priv *priv, uint32_t *attr; struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 }; int ret; + uint32_t cbs_cir, ebs_eir, val; /* Fill command parameters. */ mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0; mod_attr.flow_meter_parameter = in; - mod_attr.flow_meter_parameter_sz = fm->mfts->fmp_size; + mod_attr.flow_meter_parameter_sz = + MLX5_ST_SZ_BYTES(flow_meter_parameters); if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) mod_attr.active = !!active_state; else mod_attr.active = 0; attr = in; + cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir); + ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir); if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) { - MLX5_SET(flow_meter_parameters, - attr, cbs_exponent, srtcm->cbs_exponent); - MLX5_SET(flow_meter_parameters, - attr, cbs_mantissa, srtcm->cbs_mantissa); + val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK; + MLX5_SET(flow_meter_parameters, attr, cbs_exponent, val); + val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK; + MLX5_SET(flow_meter_parameters, attr, cbs_mantissa, val); } if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) { - MLX5_SET(flow_meter_parameters, - attr, cir_exponent, srtcm->cir_exponent); - MLX5_SET(flow_meter_parameters, - attr, cir_mantissa, srtcm->cir_mantissa); + val = (cbs_cir >> ASO_DSEG_CIR_EXP_OFFSET) & ASO_DSEG_EXP_MASK; + MLX5_SET(flow_meter_parameters, attr, cir_exponent, val); + val = cbs_cir & ASO_DSEG_MAN_MASK; + MLX5_SET(flow_meter_parameters, attr, cir_mantissa, val); } if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) { - MLX5_SET(flow_meter_parameters, - attr, ebs_exponent, srtcm->ebs_exponent); - MLX5_SET(flow_meter_parameters, - attr, ebs_mantissa, srtcm->ebs_mantissa); + val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK; + MLX5_SET(flow_meter_parameters, attr, ebs_exponent, val); + val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK; + MLX5_SET(flow_meter_parameters, attr, ebs_mantissa, val); } /* Apply modifications to meter only if it was created. */ if (fm->mfts->meter_action) { @@ -572,26 +590,6 @@ mlx5_flow_meter_action_modify(struct mlx5_priv *priv, /* Update succeedded modify meter parameters. */ if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) fm->active_state = !!active_state; - attr = fm->mfts->fmp; - if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) { - MLX5_SET(flow_meter_parameters, - attr, cbs_exponent, srtcm->cbs_exponent); - MLX5_SET(flow_meter_parameters, - attr, cbs_mantissa, srtcm->cbs_mantissa); - } - if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) { - MLX5_SET(flow_meter_parameters, - attr, cir_exponent, srtcm->cir_exponent); - MLX5_SET(flow_meter_parameters, - attr, cir_mantissa, srtcm->cir_mantissa); - } - if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) { - MLX5_SET(flow_meter_parameters, - attr, ebs_exponent, srtcm->ebs_exponent); - MLX5_SET(flow_meter_parameters, - attr, ebs_mantissa, srtcm->ebs_mantissa); - } - return 0; #else (void)priv; @@ -604,7 +602,7 @@ mlx5_flow_meter_action_modify(struct mlx5_priv *priv, } static void -mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter *fm, +mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm, uint64_t stats_mask) { fm->green_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN) ? 1 : 0; @@ -639,9 +637,10 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meters *fms = &priv->flow_meters; + struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; struct mlx5_flow_meter_profile *fmp; - struct mlx5_flow_meter *fm; + struct mlx5_legacy_flow_meter *legacy_fm; + struct mlx5_flow_meter_info *fm; const struct rte_flow_attr attr = { .ingress = 1, .egress = 1, @@ -653,8 +652,9 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, .need_lock = 1, .type = "mlx5_flow_mtr_flow_id_pool", }; + struct mlx5_aso_mtr *aso_mtr; + uint32_t mtr_idx; int ret; - uint32_t idx = 0; uint8_t mtr_id_bits; uint8_t mtr_reg_bits = priv->mtr_reg_share ? MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS; @@ -674,19 +674,31 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, "Meter profile id not valid."); /* Allocate the flow meter memory. */ - fm = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MTR], &idx); - if (fm == NULL) - return -rte_mtr_error_set(error, ENOMEM, - RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, - "Memory alloc failed for meter."); - mtr_id_bits = MLX5_REG_BITS - __builtin_clz(idx); + if (priv->sh->meter_aso_en) { + mtr_idx = mlx5_flow_mtr_alloc(dev); + if (!mtr_idx) + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Memory alloc failed for meter."); + aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx); + fm = &aso_mtr->fm; + } else { + legacy_fm = mlx5_ipool_zmalloc + (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx); + if (legacy_fm == NULL) + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Memory alloc failed for meter."); + legacy_fm->idx = mtr_idx; + fm = &legacy_fm->fm; + } + mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx); if ((mtr_id_bits + priv->max_mtr_flow_bits) > mtr_reg_bits) { DRV_LOG(ERR, "Meter number exceeds max limit."); goto error; } if (mtr_id_bits > priv->max_mtr_bits) priv->max_mtr_bits = mtr_id_bits; - fm->idx = idx; /* Fill the flow meter parameters. */ fm->meter_id = meter_id; fm->profile = fmp; @@ -712,10 +724,11 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, if (ret) goto error; /* Add to the flow meter list. */ - TAILQ_INSERT_TAIL(fms, fm, next); + if (!priv->sh->meter_aso_en) + TAILQ_INSERT_TAIL(fms, legacy_fm, next); fm->active_state = 1; /* Config meter starts as active. */ fm->shared = !!shared; - fm->profile->ref_cnt++; + __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED); fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg); if (!fm->flow_ipool) goto error; @@ -729,12 +742,57 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, mlx5_counter_free(dev, fm->policer_stats.pass_cnt); if (fm->policer_stats.drop_cnt) mlx5_counter_free(dev, fm->policer_stats.drop_cnt); - mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], idx); + if (priv->sh->meter_aso_en) + mlx5_flow_mtr_free(dev, mtr_idx); + else + mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx); return -rte_mtr_error_set(error, -ret, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Failed to create devx meter."); } +static int +mlx5_flow_meter_params_flush(struct rte_eth_dev *dev, + struct mlx5_flow_meter_info *fm, + const struct rte_flow_attr *attr, + uint32_t mtr_idx) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; + struct mlx5_flow_meter_profile *fmp; + struct mlx5_legacy_flow_meter *legacy_fm = NULL; + + /* Meter object must not have any owner. */ + MLX5_ASSERT(!fm->ref_cnt); + /* Get meter profile. */ + fmp = fm->profile; + if (fmp == NULL) + return -1; + /* Update dependencies. */ + __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED); + /* Remove from list. */ + if (!priv->sh->meter_aso_en) { + legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm); + TAILQ_REMOVE(fms, legacy_fm, next); + } + /* Free policer counters. */ + if (fm->policer_stats.pass_cnt) + mlx5_counter_free(dev, fm->policer_stats.pass_cnt); + if (fm->policer_stats.drop_cnt) + mlx5_counter_free(dev, fm->policer_stats.drop_cnt); + /* Free meter flow table. */ + if (fm->flow_ipool) + mlx5_ipool_destroy(fm->flow_ipool); + mlx5_flow_destroy_policer_rules(dev, fm, attr); + mlx5_flow_destroy_mtr_tbls(dev, fm->mfts); + if (priv->sh->meter_aso_en) + mlx5_flow_mtr_free(dev, mtr_idx); + else + mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], + legacy_fm->idx); + return 0; +} + /** * Destroy meter rules. * @@ -753,21 +811,21 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meters *fms = &priv->flow_meters; - struct mlx5_flow_meter_profile *fmp; - struct mlx5_flow_meter *fm; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + struct mlx5_flow_meter_info *fm; const struct rte_flow_attr attr = { .ingress = 1, .egress = 1, .transfer = priv->config.dv_esw_en ? 1 : 0, }; + uint32_t mtr_idx = 0; if (!priv->mtr_en) return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); /* Meter object must exist. */ - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx); if (fm == NULL) return -rte_mtr_error_set(error, ENOENT, RTE_MTR_ERROR_TYPE_MTR_ID, @@ -777,24 +835,17 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id, return -rte_mtr_error_set(error, EBUSY, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter object is being used."); - /* Get the meter profile. */ - fmp = fm->profile; - MLX5_ASSERT(fmp); - /* Update dependencies. */ - fmp->ref_cnt--; - /* Remove from the flow meter list. */ - TAILQ_REMOVE(fms, fm, next); - /* Free policer counters. */ - if (fm->policer_stats.pass_cnt) - mlx5_counter_free(dev, fm->policer_stats.pass_cnt); - if (fm->policer_stats.drop_cnt) - mlx5_counter_free(dev, fm->policer_stats.drop_cnt); - /* Free meter flow table */ - if (fm->flow_ipool) - mlx5_ipool_destroy(fm->flow_ipool); - mlx5_flow_destroy_policer_rules(dev, fm, &attr); - mlx5_flow_destroy_mtr_tbls(dev, fm->mfts); - mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], fm->idx); + if (priv->sh->meter_aso_en) { + if (mlx5_l3t_clear_entry(mtrmng->mtr_idx_tbl, meter_id)) + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Fail to delete ASO Meter in index table."); + } + /* Destroy the meter profile. */ + if (mlx5_flow_meter_params_flush(dev, fm, &attr, mtr_idx)) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "MTR object meter profile invalid."); return 0; } @@ -815,17 +866,13 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id, */ static int mlx5_flow_meter_modify_state(struct mlx5_priv *priv, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, uint32_t new_state, struct rte_mtr_error *error) { static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = { - .cbs_exponent = 20, - .cbs_mantissa = 191, - .cir_exponent = 0, - .cir_mantissa = 200, - .ebs_exponent = 0, - .ebs_mantissa = 0, + .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL), + .ebs_eir = 0, }; uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS | MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR; @@ -867,7 +914,7 @@ mlx5_flow_meter_enable(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meter *fm; + struct mlx5_flow_meter_info *fm; int ret; if (!priv->mtr_en) @@ -875,7 +922,7 @@ mlx5_flow_meter_enable(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); /* Meter object must exist. */ - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, NULL); if (fm == NULL) return -rte_mtr_error_set(error, ENOENT, RTE_MTR_ERROR_TYPE_MTR_ID, @@ -908,7 +955,7 @@ mlx5_flow_meter_disable(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meter *fm; + struct mlx5_flow_meter_info *fm; int ret; if (!priv->mtr_en) @@ -916,7 +963,7 @@ mlx5_flow_meter_disable(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); /* Meter object must exist. */ - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, NULL); if (fm == NULL) return -rte_mtr_error_set(error, ENOENT, RTE_MTR_ERROR_TYPE_MTR_ID, @@ -954,7 +1001,7 @@ mlx5_flow_meter_profile_update(struct rte_eth_dev *dev, struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_meter_profile *fmp; struct mlx5_flow_meter_profile *old_fmp; - struct mlx5_flow_meter *fm; + struct mlx5_flow_meter_info *fm; uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS | MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR; int ret; @@ -970,7 +1017,7 @@ mlx5_flow_meter_profile_update(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, "Meter profile not found."); /* Meter object must exist. */ - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, NULL); if (fm == NULL) return -rte_mtr_error_set(error, ENOENT, RTE_MTR_ERROR_TYPE_MTR_ID, @@ -1020,7 +1067,7 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meter *fm; + struct mlx5_flow_meter_info *fm; const struct rte_flow_attr attr = { .ingress = 1, .egress = 1, @@ -1034,7 +1081,7 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); /* Meter object must exist. */ - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, NULL); if (fm == NULL) return -rte_mtr_error_set(error, ENOENT, RTE_MTR_ERROR_TYPE_MTR_ID, @@ -1134,7 +1181,7 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meter *fm; + struct mlx5_flow_meter_info *fm; struct mlx5_flow_policer_stats *ps; uint64_t pkts; uint64_t bytes; @@ -1145,7 +1192,7 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); /* Meter object must exist. */ - fm = mlx5_flow_meter_find(priv, meter_id); + fm = mlx5_flow_meter_find(priv, meter_id, NULL); if (fm == NULL) return -rte_mtr_error_set(error, ENOENT, RTE_MTR_ERROR_TYPE_MTR_ID, @@ -1239,18 +1286,68 @@ mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg) * @return * Pointer to the profile found on success, NULL otherwise. */ -struct mlx5_flow_meter * -mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id) +struct mlx5_flow_meter_info * +mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id, + uint32_t *mtr_idx) { - struct mlx5_flow_meters *fms = &priv->flow_meters; - struct mlx5_flow_meter *fm; + struct mlx5_legacy_flow_meter *legacy_fm; + struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; + struct mlx5_aso_mtr *aso_mtr; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + union mlx5_l3t_data data; - TAILQ_FOREACH(fm, fms, next) - if (meter_id == fm->meter_id) - return fm; + if (priv->sh->meter_aso_en) { + rte_spinlock_lock(&mtrmng->mtrsl); + if (!mtrmng->n_valid) { + rte_spinlock_unlock(&mtrmng->mtrsl); + return NULL; + } + if (mlx5_l3t_get_entry(mtrmng->mtr_idx_tbl, meter_id, &data) || + !data.dword) { + rte_spinlock_unlock(&mtrmng->mtrsl); + return NULL; + } + if (mtr_idx) + *mtr_idx = data.dword; + aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword); + mlx5_l3t_clear_entry(mtrmng->mtr_idx_tbl, meter_id); + if (meter_id == aso_mtr->fm.meter_id) { + rte_spinlock_unlock(&mtrmng->mtrsl); + return &aso_mtr->fm; + } + rte_spinlock_unlock(&mtrmng->mtrsl); + } else { + TAILQ_FOREACH(legacy_fm, fms, next) + if (meter_id == legacy_fm->fm.meter_id) + return &legacy_fm->fm; + } return NULL; } +/** + * Find meter by index. + * + * @param priv + * Pointer to mlx5_priv. + * @param idx + * Meter index. + * + * @return + * Pointer to the profile found on success, NULL otherwise. + */ +struct mlx5_flow_meter_info * +flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx) +{ + struct mlx5_aso_mtr *aso_mtr; + + if (priv->sh->meter_aso_en) { + aso_mtr = mlx5_aso_meter_by_idx(priv, idx); + return &aso_mtr->fm; + } else { + return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx); + } +} + /** * Attach meter to flow. * Unidirectional Meter creation can only be done @@ -1270,7 +1367,7 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id) */ int mlx5_flow_meter_attach(struct mlx5_priv *priv, - struct mlx5_flow_meter *fm, + struct mlx5_flow_meter_info *fm, const struct rte_flow_attr *attr, struct rte_flow_error *error) { @@ -1319,7 +1416,7 @@ mlx5_flow_meter_attach(struct mlx5_priv *priv, * Pointer to flow meter. */ void -mlx5_flow_meter_detach(struct mlx5_flow_meter *fm) +mlx5_flow_meter_detach(struct mlx5_flow_meter_info *fm) { #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER rte_spinlock_lock(&fm->sl); @@ -1352,39 +1449,46 @@ int mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_meters *fms = &priv->flow_meters; + struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng; + struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; struct mlx5_flow_meter_profile *fmp; - struct mlx5_flow_meter *fm; + struct mlx5_legacy_flow_meter *legacy_fm; + struct mlx5_flow_meter_info *fm; + struct mlx5_aso_mtr_pool *mtr_pool; const struct rte_flow_attr attr = { .ingress = 1, .egress = 1, .transfer = priv->config.dv_esw_en ? 1 : 0, }; void *tmp; + uint32_t i, offset, mtr_idx; - TAILQ_FOREACH_SAFE(fm, fms, next, tmp) { - /* Meter object must not have any owner. */ - MLX5_ASSERT(!fm->ref_cnt); - /* Get meter profile. */ - fmp = fm->profile; - if (fmp == NULL) - return -rte_mtr_error_set(error, EINVAL, - RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, - NULL, "MTR object meter profile invalid."); - /* Update dependencies. */ - fmp->ref_cnt--; - /* Remove from list. */ - TAILQ_REMOVE(fms, fm, next); - /* Free policer counters. */ - if (fm->policer_stats.pass_cnt) - mlx5_counter_free(dev, fm->policer_stats.pass_cnt); - if (fm->policer_stats.drop_cnt) - mlx5_counter_free(dev, fm->policer_stats.drop_cnt); - /* Free meter flow table. */ - mlx5_flow_destroy_policer_rules(dev, fm, &attr); - mlx5_flow_destroy_mtr_tbls(dev, fm->mfts); - mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], fm->idx); + if (priv->sh->meter_aso_en) { + i = mtrmng->n_valid; + while (i--) { + mtr_pool = mtrmng->pools[i]; + for (offset = 0; offset < MLX5_ASO_MTRS_PER_POOL; + offset++) { + fm = &mtr_pool->mtrs[offset].fm; + mtr_idx = MLX5_MAKE_MTR_IDX(i, offset); + if (fm->meter_id != UINT32_MAX && + mlx5_flow_meter_params_flush(dev, + fm, &attr, mtr_idx)) + return -rte_mtr_error_set + (error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "MTR object meter profile invalid."); + } + } + } else { + TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) { + fm = &legacy_fm->fm; + if (mlx5_flow_meter_params_flush(dev, fm, &attr, 0)) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "MTR object meter profile invalid."); + } } TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) { /* Check unused. */