From: Sunil Kumar Kori <sk...@marvell.com> Implement API to add meter profile for CN10K platform.
Signed-off-by: Sunil Kumar Kori <sk...@marvell.com> Signed-off-by: Rakesh Kudurumalla <rkuduruma...@marvell.com> --- v2: - Rebase support on latest DPDK - Handled multilevel chaining for linear hierarchy - Review comments incorporated drivers/net/cnxk/cn10k_ethdev_mtr.c | 138 ++++++++++++++++++++++++++++ drivers/net/cnxk/cnxk_ethdev.c | 14 +++ drivers/net/cnxk/cnxk_ethdev.h | 13 +++ 3 files changed, 165 insertions(+) diff --git a/drivers/net/cnxk/cn10k_ethdev_mtr.c b/drivers/net/cnxk/cn10k_ethdev_mtr.c index f87871f149..dadfd1c0ff 100644 --- a/drivers/net/cnxk/cn10k_ethdev_mtr.c +++ b/drivers/net/cnxk/cn10k_ethdev_mtr.c @@ -37,6 +37,106 @@ static struct rte_mtr_capabilities mtr_capa = { RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED | RTE_MTR_STATS_N_BYTES_DROPPED}; +static struct cnxk_mtr_profile_node * +nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id) +{ + struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles; + struct cnxk_mtr_profile_node *fmp; + + TAILQ_FOREACH(fmp, fmps, next) + if (profile_id == fmp->id) + return fmp; + + return NULL; +} + +static int +nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id, + struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + int rc = 0; + + PLT_SET_USED(dev); + + if (profile == NULL) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "Meter profile is null."); + + if (profile_id == UINT32_MAX) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile id not valid."); + + switch (profile->alg) { + case RTE_MTR_SRTCM_RFC2697: + if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "CIR exceeds max meter rate"); + + if (profile->srtcm_rfc2697.cbs > ROC_NIX_BPF_BURST_MAX) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "CBS exceeds max meter burst size"); + + if (profile->srtcm_rfc2697.ebs > ROC_NIX_BPF_BURST_MAX) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "EBS exceeds max meter burst size"); + break; + + case RTE_MTR_TRTCM_RFC2698: + if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "CIR exceeds max meter rate"); + + if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "PIR exceeds max meter rate"); + + if (profile->trtcm_rfc2698.cbs > ROC_NIX_BPF_BURST_MAX) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "CBS exceeds max meter burst size"); + + if (profile->trtcm_rfc2698.pbs > ROC_NIX_BPF_BURST_MAX) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "PBS exceeds max meter burst size"); + break; + + case RTE_MTR_TRTCM_RFC4115: + if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) > + mtr_capa.meter_rate_max) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "PIR + EIR exceeds max rate"); + + if (profile->trtcm_rfc4115.cbs > ROC_NIX_BPF_BURST_MAX) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "CBS exceeds max meter burst size"); + + if (profile->trtcm_rfc4115.ebs > ROC_NIX_BPF_BURST_MAX) + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "PBS exceeds max meter burst size"); + break; + + default: + rc = -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "alg is invalid"); + break; + } + + return rc; +} + static int cn10k_nix_mtr_capabilities_get(struct rte_eth_dev *dev, struct rte_mtr_capabilities *capa, @@ -52,8 +152,46 @@ cn10k_nix_mtr_capabilities_get(struct rte_eth_dev *dev, return 0; } +static int +cn10k_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id, + struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); + struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles; + struct cnxk_mtr_profile_node *fmp; + int ret; + + /* Check input params. */ + ret = nix_mtr_profile_validate(dev, profile_id, profile, error); + if (ret) + return ret; + + fmp = nix_mtr_profile_find(dev, profile_id); + if (fmp) { + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Profile already exist"); + } + + fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN); + if (fmp == NULL) + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory " + "alloc failed."); + + fmp->id = profile_id; + fmp->profile = *profile; + + TAILQ_INSERT_TAIL(fmps, fmp, next); + + return 0; +} + const struct rte_mtr_ops nix_mtr_ops = { .capabilities_get = cn10k_nix_mtr_capabilities_get, + .meter_profile_add = cn10k_nix_mtr_profile_add, }; int diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c index 7152dcd002..e952aa5ec5 100644 --- a/drivers/net/cnxk/cnxk_ethdev.c +++ b/drivers/net/cnxk/cnxk_ethdev.c @@ -504,6 +504,14 @@ nix_free_queue_mem(struct cnxk_eth_dev *dev) dev->sqs = NULL; } +static int +nix_ingress_policer_setup(struct cnxk_eth_dev *dev) +{ + TAILQ_INIT(&dev->mtr_profiles); + + return 0; +} + static int nix_rss_default_setup(struct cnxk_eth_dev *dev) { @@ -901,6 +909,12 @@ cnxk_nix_configure(struct rte_eth_dev *eth_dev) goto free_nix_lf; } + rc = nix_ingress_policer_setup(dev); + if (rc) { + plt_err("Failed to setup ingress policer rc=%d", rc); + goto free_nix_lf; + } + rc = roc_nix_tm_hierarchy_enable(nix, ROC_NIX_TM_DEFAULT, false); if (rc) { plt_err("Failed to enable default tm hierarchy, rc=%d", rc); diff --git a/drivers/net/cnxk/cnxk_ethdev.h b/drivers/net/cnxk/cnxk_ethdev.h index 27920c84f2..2b9b5beb83 100644 --- a/drivers/net/cnxk/cnxk_ethdev.h +++ b/drivers/net/cnxk/cnxk_ethdev.h @@ -13,6 +13,7 @@ #include <rte_mbuf.h> #include <rte_mbuf_pool_ops.h> #include <rte_mempool.h> +#include <rte_mtr_driver.h> #include <rte_time.h> #include "roc_api.h" @@ -144,6 +145,15 @@ struct cnxk_timesync_info { uint64_t *tx_tstamp; } __plt_cache_aligned; +struct cnxk_mtr_profile_node { + TAILQ_ENTRY(cnxk_mtr_profile_node) next; + struct rte_mtr_meter_profile profile; /**< Profile detail. */ + uint32_t ref_cnt; /**< Use count. */ + uint32_t id; /**< Profile id. */ +}; + +TAILQ_HEAD(cnxk_mtr_profiles, cnxk_mtr_profile_node); + struct cnxk_eth_dev { /* ROC NIX */ struct roc_nix nix; @@ -211,6 +221,9 @@ struct cnxk_eth_dev { double clk_freq_mult; uint64_t clk_delta; + /* Ingress policer */ + struct cnxk_mtr_profiles mtr_profiles; + /* Rx burst for cleanup(Only Primary) */ eth_rx_burst_t rx_pkt_burst_no_offload; -- 2.25.1