* [dpdk-dev] [RFC 5/8] net/mlx5: flow meter pool to manage meter object
2020-12-15 7:31 [dpdk-dev] [RFC 0/8] net/mlx5: enhancement metering support Li Zhang
` (3 preceding siblings ...)
2020-12-15 7:31 ` [dpdk-dev] [RFC 4/8] common/mlx5: add DevX API to create ASO flow meter object Li Zhang
@ 2020-12-15 7:31 ` Li Zhang
2020-12-15 7:31 ` [dpdk-dev] [RFC 6/8] net/mlx5: init/uninit flow meter queue for WQE Li Zhang
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Li Zhang @ 2020-12-15 7:31 UTC (permalink / raw)
To: dekelp, orika, viacheslavo, matan; +Cc: dev, thomas, rasland
Add ASO flow meter pool to manage meter object
Signed-off-by: Li Zhang <lizh@nvidia.com>
---
drivers/net/mlx5/mlx5.c | 2 +-
drivers/net/mlx5/mlx5.h | 190 ++++++++++++-
drivers/net/mlx5/mlx5_flow.c | 44 ++-
drivers/net/mlx5/mlx5_flow.h | 186 ++++---------
drivers/net/mlx5/mlx5_flow_dv.c | 208 +++++++++++++-
drivers/net/mlx5/mlx5_flow_meter.c | 426 +++++++++++++++++------------
6 files changed, 723 insertions(+), 333 deletions(-)
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 71a81e7f7b..a66e441f67 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[] = {
},
#endif
[MLX5_IPOOL_MTR] = {
- .size = sizeof(struct mlx5_flow_meter),
+ .size = sizeof(struct mlx5_legacy_flow_meter),
.trunk_size = 64,
.grow_trunk = 3,
.grow_shift = 2,
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 9e59bfb375..41f2aed53b 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -20,6 +20,7 @@
#include <rte_interrupts.h>
#include <rte_errno.h>
#include <rte_flow.h>
+#include <rte_mtr.h>
#include <mlx5_glue.h>
#include <mlx5_devx_cmds.h>
@@ -597,6 +598,177 @@ 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 cnt[RTE_COLORS + 1];
+ /**< Color counter, extra for drop. */
+ uint64_t stats_mask;
+ /**< Statistics mask for the colors. */
+};
+
+/* 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. */
+ void *any_matcher;
+ /**< Meter color not match default criteria. */
+ void *color_matcher;
+ /**< Meter color match criteria. */
+ void *jump_actn;
+ /**< Meter match action. */
+ void *policer_rules[RTE_MTR_DROPPED + 1];
+ /**< Meter policer for the match. */
+};
+
+/* 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 *count_actns[RTE_MTR_DROPPED + 1];
+ /**< Counters for match and unmatched statistics. */
+ 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
+ */
+ uint64_t stats_mask;
+ /**< 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 hw active state. */
+ uint32_t shared:1;
+ /**< Meter shared or not. */
+ uint32_t is_enable:1;
+ /**< Meter disable/enable state. */
+};
+
+/* 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 {
@@ -718,6 +890,7 @@ struct mlx5_dev_ctx_shared {
uint16_t bond_dev; /* Bond primary device id. */
uint32_t devx:1; /* Opened with DV. */
uint32_t flow_hit_aso_en:1; /* Flow Hit ASO is supported. */
+ uint32_t meter_aso_en:1; /* Flow Meter ASO is supported. */
uint32_t eqn; /* Event Queue number. */
uint32_t max_port; /* Maximal IB device port index. */
void *ctx; /* Verbs/DV/DevX context. */
@@ -778,6 +951,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. */
};
@@ -792,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 {
@@ -1013,7 +1188,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 */
@@ -1275,14 +1450,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 *mlx5_flow_meter_attach
+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 *mlx5_flow_meter_attach
(struct mlx5_priv *priv,
uint32_t meter_id,
const struct rte_flow_attr *attr,
+ uint32_t *mtr_idx,
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;
@@ -1327,7 +1503,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 1cfa817ae9..2f047bbe01 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6467,7 +6467,7 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
*/
struct mlx5_meter_domains_infos *
mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev,
- const struct mlx5_flow_meter *fm)
+ const struct mlx5_flow_meter_info *fm)
{
const struct mlx5_flow_driver_ops *fops;
@@ -6511,7 +6511,7 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
*/
int
mlx5_flow_create_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;
@@ -6533,7 +6533,7 @@ mlx5_flow_create_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;
@@ -6542,6 +6542,44 @@ mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
return fops->destroy_policer_rules(dev, fm, attr);
}
+/**
+ * Allcate 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 6bb7bae1bf..1c01c611e4 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -811,136 +811,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 cnt[RTE_COLORS + 1];
- /**< Color counter, extra for drop. */
- uint64_t stats_mask;
- /**< Statistics mask for the colors. */
-};
-
-/* 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. */
- void *any_matcher;
- /**< Meter color not match default criteria. */
- void *color_matcher;
- /**< Meter color match criteria. */
- void *jump_actn;
- /**< Meter match action. */
- void *policer_rules[RTE_MTR_DROPPED + 1];
- /**< Meter policer for the match. */
-};
-
-/* 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 *count_actns[RTE_MTR_DROPPED + 1];
- /**< Counters for match and unmatched statistics. */
- 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 /* 1s*/
-/* 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];
-
- /** Set of stats counters to be enabled.
- * @see enum rte_mtr_stats_type
- */
- uint64_t stats_mask;
-
- /**< 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. */
-};
-
-/* 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
@@ -1066,7 +947,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. */
@@ -1135,6 +1016,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_info *fm;/* the flow meter pointer. */
};
struct mlx5_flow_split_info {
@@ -1175,18 +1057,22 @@ typedef int (*mlx5_flow_query_t)(struct rte_eth_dev *dev,
void *data,
struct rte_flow_error *error);
typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)
- (struct rte_eth_dev *dev,
- const struct mlx5_flow_meter *fm);
+ (struct rte_eth_dev *dev,
+ const struct mlx5_flow_meter_info *fm);
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,
@@ -1241,6 +1127,8 @@ struct mlx5_flow_driver_ops {
mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
mlx5_flow_create_policer_rules_t create_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;
@@ -1300,6 +1188,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,
@@ -1434,14 +1348,14 @@ int mlx5_flow_validate_item_ecpri(const struct rte_flow_item *item,
struct rte_flow_error *error);
struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls
(struct rte_eth_dev *dev,
- const struct mlx5_flow_meter *fm);
+ const struct mlx5_flow_meter_info *fm);
int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
struct mlx5_meter_domains_infos *tbl);
int mlx5_flow_create_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);
@@ -1537,4 +1451,6 @@ 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);
+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 7905923665..5e1eb51c43 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -4188,7 +4188,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,
@@ -4208,7 +4208,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,
@@ -5236,6 +5236,184 @@ flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t counter)
}
}
+/**
+ * Find meter by index.
+ *
+ * @param priv
+ * Pointer to mlx5_priv.
+ * @param idx
+ * Meter index.
+ *
+ * @return
+ * Pointer to the profile found on success, NULL otherwise.
+ */
+static 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);
+ }
+}
+
+/**
+ * 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);
+ 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.
@@ -10132,8 +10310,9 @@ flow_dv_translate(struct rte_eth_dev *dev,
struct mlx5_flow_dv_port_id_action_resource port_id_resource;
int action_type = actions->type;
const struct rte_flow_action *found_action = NULL;
- struct mlx5_flow_meter *fm = NULL;
+ struct mlx5_flow_meter_info *fm = NULL;
uint32_t jump_group = 0;
+ uint32_t mtr_idx;
if (!mlx5_flow_os_action_supported(action_type))
return rte_flow_error_set(error, ENOTSUP,
@@ -10560,7 +10739,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
mtr = actions->conf;
if (!flow->meter) {
fm = mlx5_flow_meter_attach(priv, mtr->mtr_id,
- attr, error);
+ attr, &mtr_idx, error);
if (!fm)
return rte_flow_error_set(error,
rte_errno,
@@ -10568,12 +10747,12 @@ flow_dv_translate(struct rte_eth_dev *dev,
NULL,
"meter not found "
"or invalid parameters");
- flow->meter = fm->idx;
+ flow->meter = mtr_idx;
+ wks->fm = fm;
}
/* Set the meter action. */
if (!fm) {
- fm = mlx5_ipool_get(priv->sh->ipool
- [MLX5_IPOOL_MTR], flow->meter);
+ fm = wks->fm;
if (!fm)
return rte_flow_error_set(error,
rte_errno,
@@ -11699,10 +11878,9 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
flow->counter = 0;
}
if (flow->meter) {
- struct mlx5_flow_meter *fm;
+ struct mlx5_flow_meter_info *fm;
- 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;
@@ -12585,7 +12763,7 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,
*/
static struct mlx5_meter_domains_infos *
flow_dv_create_mtr_tbl(struct rte_eth_dev *dev,
- const struct mlx5_flow_meter *fm)
+ const struct mlx5_flow_meter_info *fm)
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_meter_domains_infos *mtb;
@@ -12682,7 +12860,7 @@ flow_dv_destroy_domain_policer_rule(struct mlx5_meter_domain_info *dt)
*/
static int
flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused,
- 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;
@@ -12712,7 +12890,7 @@ flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused,
* 0 on success, -1 otherwise.
*/
static int
-flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,
+flow_dv_create_policer_forward_rule(struct mlx5_flow_meter_info *fm,
struct mlx5_meter_domain_info *dtb,
uint8_t mtr_reg_c)
{
@@ -12775,7 +12953,7 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,
*/
static int
flow_dv_create_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;
@@ -13090,6 +13268,8 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
.query = flow_dv_query,
.create_mtr_tbls = flow_dv_create_mtr_tbl,
.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,
+ .create_meter = flow_dv_mtr_alloc,
+ .free_meter = flow_dv_aso_mtr_release_to_pool,
.create_policer_rules = flow_dv_create_policer_rules,
.destroy_policer_rules = flow_dv_destroy_policer_rules,
.counter_alloc = flow_dv_counter_allocate,
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 03a5e79eb8..b17a71033d 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);
@@ -495,7 +509,7 @@ mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
action2error(params->action[i]), NULL,
"Recolor action not supported.");
/* 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.");
@@ -520,7 +534,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)
{
@@ -529,33 +543,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) {
@@ -568,26 +586,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;
@@ -622,9 +620,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,
@@ -632,7 +631,8 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
};
int ret;
unsigned int i;
- uint32_t idx = 0;
+ struct mlx5_aso_mtr *aso_mtr;
+ uint32_t mtr_idx;
if (!priv->mtr_en)
return -rte_mtr_error_set(error, ENOTSUP,
@@ -649,12 +649,24 @@ 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.");
- fm->idx = 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;
+ }
/* Fill the flow meter parameters. */
fm->meter_id = meter_id;
fm->profile = fmp;
@@ -674,11 +686,12 @@ 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->policer_stats.stats_mask = params->stats_mask;
- fm->profile->ref_cnt++;
+ __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
rte_spinlock_init(&fm->sl);
return 0;
error:
@@ -688,12 +701,56 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
if (fm->policer_stats.cnt[i])
mlx5_counter_free(dev, fm->policer_stats.cnt[i]);
- 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;
+ uint32_t i;
+
+ /* 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. */
+ for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
+ if (fm->policer_stats.cnt[i])
+ mlx5_counter_free(dev,
+ fm->policer_stats.cnt[i]);
+ /* Free meter flow table. */
+ 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.
*
@@ -712,22 +769,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,
};
- unsigned int i;
+ 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,
@@ -737,21 +793,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. */
- for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
- if (fm->policer_stats.cnt[i])
- mlx5_counter_free(dev, fm->policer_stats.cnt[i]);
- /* 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) {
+ 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;
}
@@ -772,17 +824,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;
@@ -824,7 +872,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)
@@ -832,7 +880,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,
@@ -865,7 +913,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)
@@ -873,7 +921,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,
@@ -911,7 +959,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;
@@ -927,7 +975,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,
@@ -977,14 +1025,14 @@ 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;
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, NULL);
if (fm == NULL)
return -rte_mtr_error_set(error, ENOENT,
RTE_MTR_ERROR_TYPE_MTR_ID,
@@ -1027,7 +1075,7 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED
};
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_dropped = 0;
uint64_t bytes_dropped = 0;
@@ -1041,7 +1089,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,
@@ -1134,15 +1182,41 @@ 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;
}
@@ -1162,15 +1236,15 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id)
*
* @return the flow meter pointer, NULL otherwise.
*/
-struct mlx5_flow_meter *
+struct mlx5_flow_meter_info *
mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,
- const struct rte_flow_attr *attr,
+ const struct rte_flow_attr *attr, uint32_t *mtr_idx,
struct rte_flow_error *error)
{
- struct mlx5_flow_meter *fm;
+ struct mlx5_flow_meter_info *fm;
int ret = 0;
- fm = mlx5_flow_meter_find(priv, meter_id);
+ fm = mlx5_flow_meter_find(priv, meter_id, mtr_idx);
if (fm == NULL) {
rte_flow_error_set(error, ENOENT,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -1220,7 +1294,7 @@ mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,
* 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);
@@ -1253,40 +1327,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;
+ 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. */
- for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
- if (fm->policer_stats.cnt[i])
- mlx5_counter_free(dev,
- fm->policer_stats.cnt[i]);
- /* 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. */
--
2.27.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [dpdk-dev] [RFC 7/8] net/mlx5: aso flow meter send WQE and CQE handle
2020-12-15 7:31 [dpdk-dev] [RFC 0/8] net/mlx5: enhancement metering support Li Zhang
` (5 preceding siblings ...)
2020-12-15 7:31 ` [dpdk-dev] [RFC 6/8] net/mlx5: init/uninit flow meter queue for WQE Li Zhang
@ 2020-12-15 7:31 ` Li Zhang
2020-12-15 7:31 ` [dpdk-dev] [RFC 8/8] net/mlx5: add support of ASO meter action Li Zhang
7 siblings, 0 replies; 9+ messages in thread
From: Li Zhang @ 2020-12-15 7:31 UTC (permalink / raw)
To: dekelp, orika, viacheslavo, matan; +Cc: dev, thomas, rasland
ASO flow meter send WQE and CQE handle functions
Signed-off-by: Li Zhang <lizh@nvidia.com>
---
drivers/net/mlx5/mlx5.h | 4 +
drivers/net/mlx5/mlx5_flow.h | 2 +-
drivers/net/mlx5/mlx5_flow_aso.c | 182 +++++++++++++++++++++++++++++
drivers/net/mlx5/mlx5_flow_dv.c | 5 +-
drivers/net/mlx5/mlx5_flow_meter.c | 144 ++++++++++++++---------
5 files changed, 279 insertions(+), 58 deletions(-)
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index d0c30939d2..73d3698f1d 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1517,5 +1517,9 @@ int mlx5_aso_flow_hit_queue_poll_start(struct mlx5_dev_ctx_shared *sh);
int mlx5_aso_flow_hit_queue_poll_stop(struct mlx5_dev_ctx_shared *sh);
void mlx5_aso_queue_uninit(struct mlx5_dev_ctx_shared *sh,
enum mlx5_access_aso_opc_mod aso_opc_mod);
+int mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
+ struct mlx5_aso_mtr *mtr);
+int mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
+ struct mlx5_aso_mtr *mtr);
#endif /* RTE_PMD_MLX5_H_ */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index ab83f67638..eaaa923778 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1016,7 +1016,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_info *fm;/* the flow meter pointer. */
+ uint32_t mtr_idx;/* The aso meter index. */
};
struct mlx5_flow_split_info {
diff --git a/drivers/net/mlx5/mlx5_flow_aso.c b/drivers/net/mlx5/mlx5_flow_aso.c
index b2555724d2..c9280b1f9d 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -737,3 +737,185 @@ mlx5_aso_flow_hit_queue_poll_stop(struct mlx5_dev_ctx_shared *sh)
}
return -rte_errno;
}
+
+static uint16_t
+mlx5_aso_mtr_sq_enqueue_single(struct mlx5_aso_sq *sq,
+ struct mlx5_aso_mtr *aso_mtr)
+{
+ volatile struct mlx5_aso_wqe *wqe = NULL;
+ struct mlx5_flow_meter_info *fm = NULL;
+ uint16_t size = 1 << sq->log_desc_n;
+ uint16_t mask = size - 1;
+ uint16_t res = size - (uint16_t)(sq->head - sq->tail);
+ uint32_t dseg_idx = 0;
+ struct mlx5_aso_mtr_pool *pool = NULL;
+
+ if (unlikely(!res)) {
+ DRV_LOG(ERR, "Fail: SQ is full and no free WQE to send");
+ return 0;
+ }
+ wqe = &sq->wqes[sq->head & mask];
+ rte_prefetch0(&sq->wqes[(sq->head + 1) & mask]);
+ /* Fill next WQE. */
+ fm = &aso_mtr->fm;
+ sq->elts[sq->head & mask].mtr = aso_mtr;
+ pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
+ mtrs[aso_mtr->offset]);
+ wqe->general_cseg.misc = rte_cpu_to_be_32(pool->devx_obj->id +
+ (aso_mtr->offset >> 1));
+ wqe->general_cseg.opcode = rte_cpu_to_be_32(MLX5_OPCODE_ACCESS_ASO |
+ (ASO_OPC_MOD_POLICER <<
+ WQE_CSEG_OPC_MOD_OFFSET) |
+ sq->pi << WQE_CSEG_WQE_INDEX_OFFSET);
+ /* There are 2 meters in one ASO cache line. */
+ dseg_idx = aso_mtr->offset & 0x1;
+ wqe->aso_cseg.data_mask =
+ RTE_BE64(MLX5_IFC_FLOW_METER_PARAM_MASK << (32 * !dseg_idx));
+ if (fm->is_enable) {
+ wqe->aso_dseg.mtrs[dseg_idx].cbs_cir =
+ fm->profile->srtcm_prm.cbs_cir;
+ wqe->aso_dseg.mtrs[dseg_idx].ebs_eir =
+ fm->profile->srtcm_prm.ebs_eir;
+ } else {
+ wqe->aso_dseg.mtrs[dseg_idx].cbs_cir =
+ RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL);
+ wqe->aso_dseg.mtrs[dseg_idx].ebs_eir = 0;
+ }
+ sq->head++;
+ sq->pi += 2;/* Each WQE contains 2 WQEBB's. */
+ rte_io_wmb();
+ sq->db_rec[MLX5_SND_DBR] = rte_cpu_to_be_32(sq->pi);
+ rte_wmb();
+ *sq->uar_addr = *(volatile uint64_t *)wqe; /* Assume 64 bit ARCH. */
+ rte_wmb();
+ return 1;
+}
+
+static void
+mlx5_aso_mtrs_status_update(struct mlx5_aso_sq *sq, uint16_t aso_mtrs_nums)
+{
+ uint16_t size = 1 << sq->log_desc_n;
+ uint16_t mask = size - 1;
+ uint16_t i;
+ struct mlx5_aso_mtr *aso_mtr = NULL;
+ uint8_t exp_state = ASO_METER_WAIT;
+
+ for (i = 0; i < aso_mtrs_nums; ++i) {
+ aso_mtr = sq->elts[(sq->tail + i) & mask].mtr;
+ MLX5_ASSERT(aso_mtr);
+ __atomic_compare_exchange_n(&aso_mtr->state,
+ &exp_state, ASO_METER_READY,
+ false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+ }
+}
+
+static void
+mlx5_aso_mtr_completion_handle(struct mlx5_aso_sq *sq)
+{
+ struct mlx5_aso_cq *cq = &sq->cq;
+ volatile struct mlx5_cqe *restrict cqe;
+ const unsigned int cq_size = 1 << cq->log_desc_n;
+ const unsigned int mask = cq_size - 1;
+ uint32_t idx;
+ uint32_t next_idx = cq->cq_ci & mask;
+ const uint16_t max = (uint16_t)(sq->head - sq->tail);
+ uint16_t n = 0;
+ int ret;
+
+ if (unlikely(!max))
+ return;
+ do {
+ idx = next_idx;
+ next_idx = (cq->cq_ci + 1) & mask;
+ rte_prefetch0(&cq->cqes[next_idx]);
+ cqe = &cq->cqes[idx];
+ ret = check_cqe(cqe, cq_size, cq->cq_ci);
+ /*
+ * Be sure owner read is done before any other cookie field or
+ * opaque field.
+ */
+ rte_io_rmb();
+ if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
+ if (likely(ret == MLX5_CQE_STATUS_HW_OWN))
+ break;
+ mlx5_aso_cqe_err_handle(sq);
+ } else {
+ n++;
+ }
+ cq->cq_ci++;
+ } while (1);
+ if (likely(n)) {
+ mlx5_aso_mtrs_status_update(sq, n);
+ sq->tail += n;
+ rte_io_wmb();
+ cq->db_rec[0] = rte_cpu_to_be_32(cq->cq_ci);
+ }
+}
+
+/**
+ * Update meter parameter by send WQE.
+ *
+ * @param[in] dev
+ * Pointer to Ethernet device.
+ * @param[in] priv
+ * Pointer to mlx5 private data structure.
+ * @param[in] fm
+ * Pointer to flow meter to be modified.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
+ struct mlx5_aso_mtr *mtr)
+{
+ struct mlx5_aso_sq *sq = &sh->mtrmng->sq;
+ uint32_t poll_wqe_times = MLX5_MTR_POLL_WQE_CQE_TIMES;
+
+ do {
+ mlx5_aso_mtr_completion_handle(sq);
+ if (mlx5_aso_mtr_sq_enqueue_single(sq, mtr))
+ return 0;
+ /* Waiting for wqe resource. */
+ usleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
+ } while (--poll_wqe_times);
+ DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
+ mtr->fm.meter_id);
+ return -1;
+}
+
+/**
+ * Wait for meter to be ready.
+ *
+ * @param[in] dev
+ * Pointer to Ethernet device.
+ * @param[in] priv
+ * Pointer to mlx5 private data structure.
+ * @param[in] fm
+ * Pointer to flow meter to be modified.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
+ struct mlx5_aso_mtr *mtr)
+{
+ struct mlx5_aso_sq *sq = &sh->mtrmng->sq;
+ uint32_t poll_cqe_times = MLX5_MTR_POLL_WQE_CQE_TIMES;
+
+ if (__atomic_load_n(&mtr->state, __ATOMIC_RELAXED) ==
+ ASO_METER_READY)
+ return 0;
+ do {
+ mlx5_aso_mtr_completion_handle(sq);
+ if (__atomic_load_n(&mtr->state, __ATOMIC_RELAXED) ==
+ ASO_METER_READY)
+ return 0;
+ /* Waiting for CQE ready. */
+ usleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
+ } while (--poll_cqe_times);
+ DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
+ mtr->fm.meter_id);
+ return -1;
+}
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 9bac7d3a02..cc84cb3a52 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -10753,11 +10753,12 @@ flow_dv_translate(struct rte_eth_dev *dev,
"meter not found "
"or invalid parameters");
flow->meter = mtr_idx;
- wks->fm = fm;
+ wks->mtr_idx = mtr_idx;
}
/* Set the meter action. */
if (!fm) {
- fm = wks->fm;
+ fm = flow_dv_meter_find_by_idx(priv,
+ wks->mtr_idx);
if (!fm)
return rte_flow_error_set(error,
rte_errno,
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index b17a71033d..31bbe00173 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -536,56 +536,79 @@ static int
mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
struct mlx5_flow_meter_info *fm,
const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
- uint64_t modify_bits, uint32_t active_state)
+ uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
{
#ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
uint32_t *attr;
struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
int ret;
+ struct mlx5_aso_mtr *aso_mtr = NULL;
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 =
+ if (priv->sh->meter_aso_en) {
+ fm->is_enable = !!is_enable;
+ aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
+ ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
+ if (ret)
+ return ret;
+ ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
+ if (ret)
+ return ret;
+ } else {
+ /* 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 =
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) {
- 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) {
- 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) {
- 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) {
- ret = mlx5_glue->dv_modify_flow_action_meter
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ ret = mlx5_glue->dv_modify_flow_action_meter
(fm->mfts->meter_action, &mod_attr,
rte_cpu_to_be_64(modify_bits));
- if (ret)
- return ret;
+ if (ret)
+ return ret;
+ }
+ /* Update succeedded modify meter parameters. */
+ if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
+ fm->active_state = !!active_state;
}
- /* Update succeedded modify meter parameters. */
- if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
- fm->active_state = !!active_state;
return 0;
#else
(void)priv;
@@ -624,6 +647,7 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
struct mlx5_flow_meter_profile *fmp;
struct mlx5_legacy_flow_meter *legacy_fm;
struct mlx5_flow_meter_info *fm;
+ struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng;
const struct rte_flow_attr attr = {
.ingress = 1,
.egress = 1,
@@ -632,6 +656,7 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
int ret;
unsigned int i;
struct mlx5_aso_mtr *aso_mtr;
+ union mlx5_l3t_data data;
uint32_t mtr_idx;
if (!priv->mtr_en)
@@ -672,7 +697,6 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
fm->profile = fmp;
memcpy(fm->action, params->action, sizeof(params->action));
fm->stats_mask = params->stats_mask;
-
/* Alloc policer counters. */
for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++) {
fm->policer_stats.cnt[i] = mlx5_counter_alloc(dev);
@@ -689,10 +713,21 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
if (!priv->sh->meter_aso_en)
TAILQ_INSERT_TAIL(fms, legacy_fm, next);
fm->active_state = 1; /* Config meter starts as active. */
+ fm->is_enable = 1;
fm->shared = !!shared;
fm->policer_stats.stats_mask = params->stats_mask;
__atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
rte_spinlock_init(&fm->sl);
+ /* If ASO meter supported, allocate ASO flow meter. */
+ if (priv->sh->meter_aso_en) {
+ aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
+ ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
+ if (ret)
+ goto error;
+ data.dword = mtr_idx;
+ if (mlx5_l3t_set_entry(mtrmng->mtr_idx_tbl, meter_id, &data))
+ goto error;
+ }
return 0;
error:
mlx5_flow_destroy_policer_rules(dev, fm, &attr);
@@ -837,12 +872,12 @@ mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
int ret;
if (new_state == MLX5_FLOW_METER_DISABLE)
- ret = mlx5_flow_meter_action_modify(priv, fm, &srtcm,
- modify_bits, 0);
+ ret = mlx5_flow_meter_action_modify(priv, fm,
+ &srtcm, modify_bits, 0, 0);
else
ret = mlx5_flow_meter_action_modify(priv, fm,
&fm->profile->srtcm_prm,
- modify_bits, 0);
+ modify_bits, 0, 1);
if (ret)
return -rte_mtr_error_set(error, -ret,
RTE_MTR_ERROR_TYPE_MTR_PARAMS,
@@ -990,7 +1025,7 @@ mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
if (fm->active_state == MLX5_FLOW_METER_DISABLE)
return 0;
ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
- modify_bits, fm->active_state);
+ modify_bits, fm->active_state, 1);
if (ret) {
fm->profile = old_fmp;
return -rte_mtr_error_set(error, -ret,
@@ -1178,6 +1213,8 @@ mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
* Pointer to mlx5_priv.
* @param meter_id
* Meter id.
+ * @param mtr_idx
+ * Pointer to Meter index.
*
* @return
* Pointer to the profile found on success, NULL otherwise.
@@ -1194,10 +1231,6 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
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);
@@ -1206,17 +1239,18 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
if (mtr_idx)
*mtr_idx = data.dword;
aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
+ /* Remove reference taken by the mlx5_l3t_get_entry. */
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;
- }
+ MLX5_ASSERT(meter_id == aso_mtr->fm.meter_id);
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 &aso_mtr->fm;
}
+ TAILQ_FOREACH(legacy_fm, fms, next)
+ if (meter_id == legacy_fm->fm.meter_id) {
+ if (mtr_idx)
+ *mtr_idx = legacy_fm->idx;
+ return &legacy_fm->fm;
+ }
return NULL;
}
--
2.27.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [dpdk-dev] [RFC 8/8] net/mlx5: add support of ASO meter action
2020-12-15 7:31 [dpdk-dev] [RFC 0/8] net/mlx5: enhancement metering support Li Zhang
` (6 preceding siblings ...)
2020-12-15 7:31 ` [dpdk-dev] [RFC 7/8] net/mlx5: aso flow meter send WQE and CQE handle Li Zhang
@ 2020-12-15 7:31 ` Li Zhang
7 siblings, 0 replies; 9+ messages in thread
From: Li Zhang @ 2020-12-15 7:31 UTC (permalink / raw)
To: dekelp, orika, viacheslavo, matan; +Cc: dev, thomas, rasland, Shun Hao
When ASO action is available, use it as the meter action
Signed-off-by: Shun Hao <shunh@nvidia.com>
Signed-off-by: Li Zhang <lizh@nvidia.com>
---
drivers/net/mlx5/linux/mlx5_os.c | 4 +-
drivers/net/mlx5/mlx5.c | 8 ++
drivers/net/mlx5/mlx5.h | 18 ++---
drivers/net/mlx5/mlx5_flow.c | 66 +++++++++++-----
drivers/net/mlx5/mlx5_flow_dv.c | 74 ++++++++++--------
drivers/net/mlx5/mlx5_flow_meter.c | 118 ++++++++++++++++++-----------
6 files changed, 184 insertions(+), 104 deletions(-)
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 01b019c28d..28e383c7e2 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1233,7 +1233,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
"required for coalescing is %d bytes",
config->hca_attr.lro_min_mss_size);
}
-#if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER)
+#if defined(HAVE_MLX5DV_DR) && \
+ (defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER) || \
+ defined(HAVE_MLX5_DR_CREATE_ACTION_ASO))
if (config->hca_attr.qos.sup &&
config->hca_attr.qos.srtcm_sup &&
config->dv_flow_en) {
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 9d77265e2e..224c8e3965 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -584,13 +584,21 @@ static void
mlx5_aso_flow_mtrs_mng_close(struct mlx5_dev_ctx_shared *sh)
{
struct mlx5_aso_mtr_pool *mtr_pool;
+ struct mlx5_aso_mtr *aso_mtr;
struct mlx5_aso_mtr_pools_mng *mtrmng = sh->mtrmng;
uint32_t idx;
+ int i;
mlx5_aso_queue_uninit(sh, ASO_OPC_MOD_POLICER);
idx = mtrmng->n_valid;
while (idx--) {
mtr_pool = mtrmng->pools[idx];
+ for (i = 0; i < MLX5_ASO_MTRS_PER_POOL; i++) {
+ aso_mtr = &mtr_pool->mtrs[i];
+ if (aso_mtr->fm.meter_action)
+ claim_zero(mlx5_glue->destroy_flow_action
+ (aso_mtr->fm.meter_action));
+ }
claim_zero(mlx5_devx_cmd_destroy
(mtr_pool->devx_obj));
mtrmng->n_valid--;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 73d3698f1d..b4bd76e792 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -645,8 +645,6 @@ struct mlx5_meter_domains_infos {
/**< Drop action as not matched. */
void *count_actns[RTE_MTR_DROPPED + 1];
/**< Counters for match and unmatched statistics. */
- void *meter_action;
- /**< Flow meter action. */
};
/* Meter parameter structure. */
@@ -697,6 +695,8 @@ struct mlx5_flow_meter_info {
/**< Meter shared or not. */
uint32_t is_enable:1;
/**< Meter disable/enable state. */
+ void *meter_action;
+ /**< Flow meter action. */
};
/* RFC2697 parameter structure. */
@@ -800,7 +800,7 @@ struct mlx5_flow_tbl_resource {
/* Tables for metering splits should be added here. */
#define MLX5_FLOW_TABLE_LEVEL_SUFFIX (MLX5_MAX_TABLES - 3)
#define MLX5_FLOW_TABLE_LEVEL_METER (MLX5_MAX_TABLES - 4)
-#define MLX5_MAX_TABLES_EXTERNAL MLX5_FLOW_TABLE_LEVEL_METER
+#define MLX5_MAX_TABLES_EXTERNAL (MLX5_FLOW_TABLE_LEVEL_METER - 1)
#define MLX5_MAX_TABLES_FDB UINT16_MAX
#define MLX5_FLOW_TABLE_FACTOR 10
@@ -1458,13 +1458,11 @@ int mlx5_pmd_socket_init(void);
int mlx5_flow_meter_ops_get(struct rte_eth_dev *dev, void *arg);
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 *mlx5_flow_meter_attach
- (struct mlx5_priv *priv,
- uint32_t meter_id,
- const struct rte_flow_attr *attr,
- uint32_t *mtr_idx,
- struct rte_flow_error *error);
-void mlx5_flow_meter_detach(struct mlx5_flow_meter_info *fm);
+uint32_t mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,
+ const struct rte_flow_attr *attr,
+ struct rte_flow_error *error);
+void mlx5_flow_meter_detach(struct mlx5_priv *priv,
+ struct mlx5_flow_meter_info *fm);
/* mlx5_os.c */
struct rte_pci_driver;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 2f047bbe01..0142b546df 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -4282,6 +4282,7 @@ flow_create_split_inner(struct rte_eth_dev *dev,
*/
static int
flow_meter_split_prep(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
const struct rte_flow_item items[],
struct rte_flow_item sfx_items[],
const struct rte_flow_action actions[],
@@ -4300,33 +4301,44 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
uint32_t tag_id = 0;
uint32_t reg_id = 0;
bool copy_vlan = false;
+ struct rte_flow_action *hw_mtr_action;
+ struct rte_flow_action_jump *jump_data;
+ /* For ASO meter, meter must be before tag in TX direction. */
+ bool mtr_first = priv->sh->meter_aso_en &&
+ (attr->egress ||
+ (attr->transfer && priv->representor_id != -1));
+ struct rte_flow_action *action_pre_head =
+ mtr_first ? actions_pre++ : NULL;
/* Prepare the actions for prefix and suffix flow. */
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
- struct rte_flow_action **action_cur = NULL;
+ struct rte_flow_action *action_cur = NULL;
switch (actions->type) {
case RTE_FLOW_ACTION_TYPE_METER:
- /* Add the extra tag action first. */
- tag_action = actions_pre;
+ if (mtr_first) {
+ action_cur = action_pre_head;
+ tag_action = actions_pre++;
+ } else {
+ tag_action = actions_pre++;
+ action_cur = actions_pre++;
+ }
tag_action->type = (enum rte_flow_action_type)
MLX5_RTE_FLOW_ACTION_TYPE_TAG;
- actions_pre++;
- action_cur = &actions_pre;
break;
case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
- action_cur = &actions_pre;
+ action_cur = actions_pre++;
break;
case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
raw_encap = actions->conf;
if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE)
- action_cur = &actions_pre;
+ action_cur = actions_pre++;
break;
case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
raw_decap = actions->conf;
if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
- action_cur = &actions_pre;
+ action_cur = actions_pre++;
break;
case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
@@ -4336,14 +4348,30 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
break;
}
if (!action_cur)
- action_cur = &actions_sfx;
- memcpy(*action_cur, actions, sizeof(struct rte_flow_action));
- (*action_cur)++;
+ action_cur = actions_sfx++;
+ memcpy(action_cur, actions, sizeof(struct rte_flow_action));
}
/* Add end action to the actions. */
actions_sfx->type = RTE_FLOW_ACTION_TYPE_END;
- actions_pre->type = RTE_FLOW_ACTION_TYPE_END;
- actions_pre++;
+ if (priv->sh->meter_aso_en) {
+ /** For ASO meter, need to add an extra jump action explicitly,
+ * to jump from meter to policer table.
+ */
+ hw_mtr_action = actions_pre;
+ hw_mtr_action->type = RTE_FLOW_ACTION_TYPE_JUMP;
+ actions_pre++;
+ actions_pre->type = RTE_FLOW_ACTION_TYPE_END;
+ actions_pre++;
+ jump_data = (void *)actions_pre;
+ jump_data->group = attr->transfer ?
+ (MLX5_FLOW_TABLE_LEVEL_METER - 1) :
+ MLX5_FLOW_TABLE_LEVEL_METER;
+ hw_mtr_action->conf = jump_data;
+ actions_pre++;
+ } else {
+ actions_pre->type = RTE_FLOW_ACTION_TYPE_END;
+ actions_pre++;
+ }
/* Set the tag. */
set_tag = (void *)actions_pre;
reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);
@@ -5116,12 +5144,16 @@ flow_create_split_meter(struct rte_eth_dev *dev,
size_t item_size;
int actions_n = 0;
int ret;
+ uint8_t pre_action_num;
if (priv->mtr_en)
actions_n = flow_check_meter_action(actions, &mtr);
if (mtr) {
/* The five prefix actions: meter, decap, encap, tag, end. */
- act_size = sizeof(struct rte_flow_action) * (actions_n + 5) +
+ /* For aso meter, need 2 more space for jump. */
+ pre_action_num = priv->sh->meter_aso_en ? 7 : 5;
+ act_size = sizeof(struct rte_flow_action) *
+ (actions_n + pre_action_num) +
sizeof(struct mlx5_rte_flow_action_set_tag);
/* tag, vlan, port id, end. */
#define METER_SUFFIX_ITEM 4
@@ -5137,9 +5169,9 @@ 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, items, sfx_items,
- actions, sfx_actions,
- pre_actions);
+ mtr_tag_id = flow_meter_split_prep(dev, &sfx_attr, items,
+ sfx_items, actions,
+ sfx_actions, pre_actions);
if (!mtr_tag_id) {
ret = -rte_errno;
goto exit;
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index cc84cb3a52..b0803e4847 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -4213,9 +4213,11 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"Meter not found");
- if (fm->ref_cnt && (!(fm->transfer == attr->transfer ||
+ /* aso meter can always be shared by different domains */
+ if (fm->ref_cnt && !priv->sh->meter_aso_en &&
+ !(fm->transfer == attr->transfer ||
(!fm->ingress && !attr->ingress && attr->egress) ||
- (!fm->egress && !attr->egress && attr->ingress))))
+ (!fm->egress && !attr->egress && attr->ingress)))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"Flow attributes are either invalid "
@@ -5394,6 +5396,8 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
struct mlx5_aso_mtr *mtr_free = NULL;
struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng;
struct mlx5_aso_mtr_pool *pool;
+ struct rte_flow_error error;
+ uint8_t reg_id;
uint32_t mtr_idx = 0;
if (!priv->config.devx) {
@@ -5416,6 +5420,20 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
struct mlx5_aso_mtr_pool,
mtrs[mtr_free->offset]);
mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
+ if (!mtr_free->fm.meter_action) {
+ reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &error);
+ mtr_free->fm.meter_action =
+ mlx5_glue->dv_create_flow_action_aso
+ (priv->sh->rx_domain,
+ pool->devx_obj->obj,
+ mtr_free->offset,
+ (1 << MLX5_FLOW_COLOR_GREEN),
+ reg_id - REG_C_0);
+ if (!mtr_free->fm.meter_action) {
+ flow_dv_aso_mtr_release_to_pool(dev, mtr_idx);
+ return 0;
+ }
+ }
return mtr_idx;
}
@@ -10317,7 +10335,6 @@ flow_dv_translate(struct rte_eth_dev *dev,
const struct rte_flow_action *found_action = NULL;
struct mlx5_flow_meter_info *fm = NULL;
uint32_t jump_group = 0;
- uint32_t mtr_idx;
if (!mlx5_flow_os_action_supported(action_type))
return rte_flow_error_set(error, ENOTSUP,
@@ -10743,32 +10760,23 @@ flow_dv_translate(struct rte_eth_dev *dev,
case RTE_FLOW_ACTION_TYPE_METER:
mtr = actions->conf;
if (!flow->meter) {
- fm = mlx5_flow_meter_attach(priv, mtr->mtr_id,
- attr, &mtr_idx, error);
- if (!fm)
- return rte_flow_error_set(error,
- rte_errno,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "meter not found "
- "or invalid parameters");
- flow->meter = mtr_idx;
- wks->mtr_idx = mtr_idx;
+ flow->meter =
+ mlx5_flow_meter_attach(priv,
+ mtr->mtr_id,
+ attr,
+ error);
+ if (!flow->meter)
+ return -rte_errno;
+ wks->mtr_idx = flow->meter;
}
- /* Set the meter action. */
- if (!fm) {
- fm = flow_dv_meter_find_by_idx(priv,
- wks->mtr_idx);
- if (!fm)
- return rte_flow_error_set(error,
- rte_errno,
+ fm = flow_dv_meter_find_by_idx(priv, wks->mtr_idx);
+ if (!fm)
+ return rte_flow_error_set(error, ENOENT,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
- "meter not found "
- "or invalid parameters");
- }
- dev_flow->dv.actions[actions_n++] =
- fm->mfts->meter_action;
+ "failed to get flow meter.");
+ /* Set the meter action. */
+ dev_flow->dv.actions[actions_n++] = fm->meter_action;
action_flags |= MLX5_FLOW_ACTION_METER;
break;
case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
@@ -11888,7 +11896,7 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
fm = flow_dv_meter_find_by_idx(priv, flow->meter);
if (fm)
- mlx5_flow_meter_detach(fm);
+ mlx5_flow_meter_detach(priv, fm);
flow->meter = 0;
}
if (flow->age)
@@ -12678,10 +12686,12 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_dev_ctx_shared *sh = priv->sh;
struct mlx5_flow_dv_match_params mask = {
- .size = sizeof(mask.buf),
+ .size = sizeof(mask.buf) -
+ MLX5_ST_SZ_BYTES(fte_match_set_misc4),
};
struct mlx5_flow_dv_match_params value = {
- .size = sizeof(value.buf),
+ .size = sizeof(value.buf) -
+ MLX5_ST_SZ_BYTES(fte_match_set_misc4),
};
struct mlx5dv_flow_matcher_attr dv_attr = {
.type = IBV_FLOW_ATTR_NORMAL,
@@ -12901,10 +12911,12 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter_info *fm,
uint8_t mtr_reg_c)
{
struct mlx5_flow_dv_match_params matcher = {
- .size = sizeof(matcher.buf),
+ .size = sizeof(matcher.buf) -
+ MLX5_ST_SZ_BYTES(fte_match_set_misc4),
};
struct mlx5_flow_dv_match_params value = {
- .size = sizeof(value.buf),
+ .size = sizeof(value.buf) -
+ MLX5_ST_SZ_BYTES(fte_match_set_misc4),
};
struct mlx5_meter_domains_infos *mtb = fm->mfts;
void *actions[METER_ACTIONS];
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 31bbe00173..b01aae2301 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -598,9 +598,9 @@ mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
ebs_mantissa, val);
}
/* Apply modifications to meter only if it was created. */
- if (fm->mfts->meter_action) {
+ if (fm->meter_action) {
ret = mlx5_glue->dv_modify_flow_action_meter
- (fm->mfts->meter_action, &mod_attr,
+ (fm->meter_action, &mod_attr,
rte_cpu_to_be_64(modify_bits));
if (ret)
return ret;
@@ -1268,74 +1268,102 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
* @param [out] error
* Pointer to error structure.
*
- * @return the flow meter pointer, NULL otherwise.
+ * @return
+ * The meter idx on success, 0 otherwise and rte_errno is set.
*/
-struct mlx5_flow_meter_info *
-mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,
- const struct rte_flow_attr *attr, uint32_t *mtr_idx,
- struct rte_flow_error *error)
+uint32_t mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,
+ const struct rte_flow_attr *attr,
+ struct rte_flow_error *error)
{
struct mlx5_flow_meter_info *fm;
+ struct mlx5_aso_mtr *aso_mtr;
+ uint32_t mtr_idx;
int ret = 0;
- fm = mlx5_flow_meter_find(priv, meter_id, mtr_idx);
- if (fm == NULL) {
+ fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
+ if (!fm) {
rte_flow_error_set(error, ENOENT,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
- "Meter object id not valid");
- return fm;
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "Meter not found ");
+ return 0;
}
- rte_spinlock_lock(&fm->sl);
- if (fm->mfts->meter_action) {
- if (fm->shared &&
- attr->transfer == fm->transfer &&
- attr->ingress == fm->ingress &&
- attr->egress == fm->egress)
+ if (priv->sh->meter_aso_en) {
+ aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
+ if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
+ rte_flow_error_set(error, ENOENT,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Timeout in meter configuration");
+ return 0;
+ }
+ rte_spinlock_lock(&fm->sl);
+ if (fm->shared || !fm->ref_cnt) {
fm->ref_cnt++;
- else
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter cannot be shared");
ret = -1;
+ }
+ rte_spinlock_unlock(&fm->sl);
} else {
- fm->ingress = attr->ingress;
- fm->egress = attr->egress;
- fm->transfer = attr->transfer;
- fm->ref_cnt = 1;
- /* This also creates the meter object. */
- fm->mfts->meter_action = mlx5_flow_meter_action_create(priv,
- fm);
- if (!fm->mfts->meter_action) {
- fm->ref_cnt = 0;
- fm->ingress = 0;
- fm->egress = 0;
- fm->transfer = 0;
- ret = -1;
- DRV_LOG(ERR, "Meter action create failed.");
+ rte_spinlock_lock(&fm->sl);
+ if (fm->meter_action) {
+ if (fm->shared &&
+ attr->transfer == fm->transfer &&
+ attr->ingress == fm->ingress &&
+ attr->egress == fm->egress) {
+ fm->ref_cnt++;
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ fm->shared ?
+ "Meter attr not match." :
+ "Meter cannot be shared.");
+ ret = -1;
+ }
+ } else {
+ fm->ingress = attr->ingress;
+ fm->egress = attr->egress;
+ fm->transfer = attr->transfer;
+ fm->ref_cnt = 1;
+ /* This also creates the meter object. */
+ fm->meter_action = mlx5_flow_meter_action_create(priv,
+ fm);
+ if (!fm->meter_action) {
+ fm->ref_cnt = 0;
+ fm->ingress = 0;
+ fm->egress = 0;
+ fm->transfer = 0;
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter action create failed.");
+ ret = -1;
+ }
}
+ rte_spinlock_unlock(&fm->sl);
}
- rte_spinlock_unlock(&fm->sl);
- if (ret)
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
- fm->mfts->meter_action ?
- "Meter attr not match" :
- "Meter action create failed");
- return ret ? NULL : fm;
+ return (ret < 0) ? 0 : mtr_idx;
}
/**
* Detach meter from flow.
*
+ * @param [in] priv
+ * Pointer to mlx5 private data.
* @param [in] fm
* Pointer to flow meter.
*/
void
-mlx5_flow_meter_detach(struct mlx5_flow_meter_info *fm)
+mlx5_flow_meter_detach(struct mlx5_priv *priv,
+ struct mlx5_flow_meter_info *fm)
{
#ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
rte_spinlock_lock(&fm->sl);
MLX5_ASSERT(fm->ref_cnt);
- if (--fm->ref_cnt == 0) {
- mlx5_glue->destroy_flow_action(fm->mfts->meter_action);
- fm->mfts->meter_action = NULL;
+ if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
+ mlx5_glue->destroy_flow_action(fm->meter_action);
+ fm->meter_action = NULL;
fm->ingress = 0;
fm->egress = 0;
fm->transfer = 0;
--
2.27.0
^ permalink raw reply [flat|nested] 9+ messages in thread