From: Jin Liu <jin....@corigine.com> Add support for meter policy options, include add a new policy and delete a exist policy, the meter policy indicate that action to be performed for messages of different colors.
Signed-off-by: Jin Liu <jin....@corigine.com> Signed-off-by: Peng Zhang <peng.zh...@corigine.com> Reviewed-by: Chaoyong He <chaoyong...@corigine.com> Reviewed-by: Niklas Söderlund <niklas.soderl...@corigine.com> --- drivers/net/nfp/nfp_mtr.c | 179 ++++++++++++++++++++++++++++++++++++++ drivers/net/nfp/nfp_mtr.h | 18 ++++ 2 files changed, 197 insertions(+) diff --git a/drivers/net/nfp/nfp_mtr.c b/drivers/net/nfp/nfp_mtr.c index 50efb56879..c8caf97262 100644 --- a/drivers/net/nfp/nfp_mtr.c +++ b/drivers/net/nfp/nfp_mtr.c @@ -371,10 +371,182 @@ nfp_mtr_profile_delete(struct rte_eth_dev *dev, return 0; } +static struct nfp_mtr_policy * +nfp_mtr_policy_search(struct nfp_mtr_priv *priv, uint32_t mtr_policy_id) +{ + struct nfp_mtr_policy *mtr_policy; + + LIST_FOREACH(mtr_policy, &priv->policies, next) + if (mtr_policy->policy_id == mtr_policy_id) + break; + + return mtr_policy; +} + +static int +nfp_mtr_policy_validate(uint32_t mtr_policy_id, + struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + const struct rte_flow_action *action; + + /* Policy must not be NULL */ + if (policy == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY, + NULL, "Meter policy is null."); + } + + /* Meter policy ID must be valid. */ + if (mtr_policy_id >= NFP_MAX_POLICY_CNT) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy id not valid."); + } + + /* Check green action + * Actions equal NULL means end action + */ + action = policy->actions[RTE_COLOR_GREEN]; + if (action != NULL && action->type != RTE_FLOW_ACTION_TYPE_VOID) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY, + NULL, "Green action must be void or end"); + } + + /* Check yellow action + * Actions equal NULL means end action + */ + action = policy->actions[RTE_COLOR_YELLOW]; + if (action != NULL && action->type != RTE_FLOW_ACTION_TYPE_VOID) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY, + NULL, "Yellow action must be void or end"); + } + + /* Check red action */ + action = policy->actions[RTE_COLOR_RED]; + if (action == NULL || action->type != RTE_FLOW_ACTION_TYPE_DROP) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY, + NULL, "Red action must be drop"); + } + + return 0; +} + +/** + * Callback to add MTR policy. + * + * @param[in] dev + * Pointer to Ethernet device. + * @param[in] mtr_policy_id + * Meter policy id. + * @param[in] policy + * Pointer to meter policy detail. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative value otherwise and rte_errno is set. + */ +static int +nfp_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t mtr_policy_id, + struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + int ret; + struct nfp_mtr_priv *priv; + struct nfp_mtr_policy *mtr_policy; + struct nfp_flower_representor *representor; + + representor = dev->data->dev_private; + priv = representor->app_fw_flower->mtr_priv; + + /* Check if mtr policy id exist */ + mtr_policy = nfp_mtr_policy_search(priv, mtr_policy_id); + if (mtr_policy != NULL) { + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy already exist"); + } + + /* Check input params */ + ret = nfp_mtr_policy_validate(mtr_policy_id, policy, error); + if (ret != 0) + return ret; + + /* Meter policy memory alloc */ + mtr_policy = rte_zmalloc(NULL, sizeof(struct nfp_mtr_policy), 0); + if (mtr_policy == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, + NULL, "Meter policy alloc failed"); + } + + mtr_policy->policy_id = mtr_policy_id; + rte_memcpy(&mtr_policy->policy, policy, + sizeof(struct rte_mtr_meter_policy_params)); + + /* Insert policy into policy list */ + LIST_INSERT_HEAD(&priv->policies, mtr_policy, next); + + return 0; +} + +/** + * Callback to delete MTR policy. + * + * @param[in] dev + * Pointer to Ethernet device. + * @param[in] mtr_policy_id + * Meter policy id. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative value otherwise and rte_errno is set. + */ +static int +nfp_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t mtr_policy_id, + struct rte_mtr_error *error) +{ + struct nfp_mtr_priv *priv; + struct nfp_mtr_policy *mtr_policy; + struct nfp_flower_representor *representor; + + representor = dev->data->dev_private; + priv = representor->app_fw_flower->mtr_priv; + + /* Check if mtr policy id exist */ + mtr_policy = nfp_mtr_policy_search(priv, mtr_policy_id); + if (mtr_policy == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Request meter policy not exist"); + } + + if (mtr_policy->ref_cnt > 0) { + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY, + NULL, "Request mtr policy is been used"); + } + + /* Remove profile from profile list */ + LIST_REMOVE(mtr_policy, next); + rte_free(mtr_policy); + + return 0; +} + static const struct rte_mtr_ops nfp_mtr_ops = { .capabilities_get = nfp_mtr_cap_get, .meter_profile_add = nfp_mtr_profile_add, .meter_profile_delete = nfp_mtr_profile_delete, + .meter_policy_add = nfp_mtr_policy_add, + .meter_policy_delete = nfp_mtr_policy_delete, }; int @@ -406,6 +578,7 @@ nfp_mtr_priv_init(struct nfp_pf_dev *pf_dev) app_fw_flower->mtr_priv = priv; LIST_INIT(&priv->profiles); + LIST_INIT(&priv->policies); return 0; } @@ -414,6 +587,7 @@ void nfp_mtr_priv_uninit(struct nfp_pf_dev *pf_dev) { struct nfp_mtr_priv *priv; + struct nfp_mtr_policy *mtr_policy; struct nfp_mtr_profile *mtr_profile; struct nfp_app_fw_flower *app_fw_flower; @@ -425,5 +599,10 @@ nfp_mtr_priv_uninit(struct nfp_pf_dev *pf_dev) rte_free(mtr_profile); } + LIST_FOREACH(mtr_policy, &priv->policies, next) { + LIST_REMOVE(mtr_policy, next); + rte_free(mtr_policy); + } + rte_free(priv); } diff --git a/drivers/net/nfp/nfp_mtr.h b/drivers/net/nfp/nfp_mtr.h index 05919c2bde..4fea0cf926 100644 --- a/drivers/net/nfp/nfp_mtr.h +++ b/drivers/net/nfp/nfp_mtr.h @@ -6,6 +6,8 @@ #ifndef __NFP_MTR_H__ #define __NFP_MTR_H__ +#include <rte_mtr.h> + /** * The max meter count is determined by firmware. * The max count is 65536 defined by OF_METER_COUNT. @@ -79,12 +81,28 @@ struct nfp_mtr_profile { bool in_use; }; +/** + * Struct nfp_mtr_policy - meter policy information + * @next: next meter policy object + * @policy_id: meter policy id + * @ref_cnt: reference count by meter + * @policy: RTE_FLOW policy information + */ +struct nfp_mtr_policy { + LIST_ENTRY(nfp_mtr_policy) next; + uint32_t policy_id; + uint32_t ref_cnt; + struct rte_mtr_meter_policy_params policy; +}; + /** * Struct nfp_mtr_priv - meter private data * @profiles: the head node of profile list + * @policies: the head node of policy list */ struct nfp_mtr_priv { LIST_HEAD(, nfp_mtr_profile) profiles; + LIST_HEAD(, nfp_mtr_policy) policies; }; int nfp_net_mtr_ops_get(struct rte_eth_dev *dev, void *arg); -- 2.29.3