From: Jin Liu <jin....@corigine.com> Add the rte_flow meter action logic, flow with meter action can offload and work well.
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> --- doc/guides/nics/features/nfp.ini | 1 + doc/guides/rel_notes/release_23_03.rst | 1 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 16 +++++ drivers/net/nfp/nfp_flow.c | 86 +++++++++++++++++++++++- drivers/net/nfp/nfp_flow.h | 1 + drivers/net/nfp/nfp_mtr.c | 16 +++++ drivers/net/nfp/nfp_mtr.h | 2 + 7 files changed, 122 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini index 9e075a680b..a4eb760675 100644 --- a/doc/guides/nics/features/nfp.ini +++ b/doc/guides/nics/features/nfp.ini @@ -44,6 +44,7 @@ vxlan = Y count = Y drop = Y jump = Y +meter = Y of_pop_vlan = Y of_push_vlan = Y of_set_vlan_pcp = Y diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst index 0ce6fbf8ee..2c45e1f09f 100644 --- a/doc/guides/rel_notes/release_23_03.rst +++ b/doc/guides/rel_notes/release_23_03.rst @@ -58,6 +58,7 @@ New Features * **Updated Corigine nfp driver.** * Added support for meter options. + * Added support for rte_flow meter action. Removed Items ------------- diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h index 2f4cd68730..96e080a8e9 100644 --- a/drivers/net/nfp/flower/nfp_flower_cmsg.h +++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h @@ -901,6 +901,22 @@ struct nfp_fl_act_set_tun { rte_be16_t tun_proto; /* Only valid for NFP_FL_TUNNEL_GENEVE */ } __rte_packed; +/* + * Meter + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | res | opcode | res | len_lw| reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Profile ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct nfp_fl_act_meter { + struct nfp_fl_act_head head; + rte_be16_t reserved; + rte_be32_t profile_id; +}; + int nfp_flower_cmsg_mac_repr(struct nfp_app_fw_flower *app_fw_flower); int nfp_flower_cmsg_repr_reify(struct nfp_app_fw_flower *app_fw_flower, struct nfp_flower_representor *repr); diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c index 6f79d950db..ab9a9c23f5 100644 --- a/drivers/net/nfp/nfp_flow.c +++ b/drivers/net/nfp/nfp_flow.c @@ -356,7 +356,7 @@ nfp_flow_alloc(struct nfp_fl_key_ls *key_layer) goto free_flow; nfp_flow->length = len; - + nfp_flow->mtr_id = NFP_MAX_MTR_CNT; payload = &nfp_flow->payload; payload->meta = (struct nfp_fl_rule_metadata *)tmp; payload->unmasked_data = tmp + sizeof(struct nfp_fl_rule_metadata); @@ -866,6 +866,7 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], struct nfp_fl_key_ls *key_ls) { int ret = 0; + bool meter_flag = false; bool tc_hl_flag = false; bool mac_set_flag = false; bool ip_set_flag = false; @@ -1012,6 +1013,16 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], case RTE_FLOW_ACTION_TYPE_RAW_DECAP: PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_DECAP detected"); break; + case RTE_FLOW_ACTION_TYPE_METER: + PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_METER detected"); + if (!meter_flag) { + key_ls->act_size += sizeof(struct nfp_fl_act_meter); + meter_flag = true; + } else { + PMD_DRV_LOG(ERR, "Only support one meter action."); + return -ENOTSUP; + } + break; default: PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type); return -ENOTSUP; @@ -3232,6 +3243,48 @@ nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower, return ret; } +static int +nfp_flow_action_meter(struct nfp_flower_representor *representor, + const struct rte_flow_action *action, + char *act_data, + uint32_t *mtr_id) +{ + struct nfp_mtr *mtr; + struct nfp_fl_act_meter *fl_meter; + struct nfp_app_fw_flower *app_fw_flower; + const struct rte_flow_action_meter *meter; + size_t act_size = sizeof(struct nfp_fl_act_meter); + + meter = action->conf; + fl_meter = (struct nfp_fl_act_meter *)act_data; + app_fw_flower = representor->app_fw_flower; + + mtr = nfp_mtr_find_by_mtr_id(app_fw_flower->mtr_priv, meter->mtr_id); + if (mtr == NULL) { + PMD_DRV_LOG(ERR, "Meter id not exist"); + return -EINVAL; + } + + if (!mtr->enable) { + PMD_DRV_LOG(ERR, "Requested meter disable"); + return -EINVAL; + } + + if (!mtr->shared && mtr->ref_cnt > 0) { + PMD_DRV_LOG(ERR, "Can't use a used unshared meter"); + return -EINVAL; + } + + *mtr_id = meter->mtr_id; + + fl_meter->head.jump_id = NFP_FL_ACTION_OPCODE_METER; + fl_meter->head.len_lw = act_size >> NFP_FL_LW_SIZ; + fl_meter->reserved = 0; + fl_meter->profile_id = rte_cpu_to_be_32(mtr->mtr_profile->profile_id); + + return 0; +} + static int nfp_flow_compile_action(struct nfp_flower_representor *representor, const struct rte_flow_action actions[], @@ -3435,6 +3488,14 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor, if (action->conf != NULL) nfp_flow->tun.payload.v6_flag = 1; break; + case RTE_FLOW_ACTION_TYPE_METER: + PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_METER"); + ret = nfp_flow_action_meter(representor, action, + position, &nfp_flow->mtr_id); + if (ret != 0) + return -EINVAL; + position += sizeof(struct nfp_fl_act_meter); + break; default: PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type); return -ENOTSUP; @@ -3685,6 +3746,18 @@ nfp_flow_create(struct rte_eth_dev *dev, goto flow_teardown; } + /* Update meter object ref count */ + if (nfp_flow->mtr_id != NFP_MAX_MTR_CNT) { + ret = nfp_mtr_update_ref_cnt(app_fw_flower->mtr_priv, + nfp_flow->mtr_id, true); + if (ret != 0) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Update meter ref_cnt failed."); + goto flow_teardown; + } + } + return nfp_flow; flow_teardown: @@ -3777,6 +3850,17 @@ nfp_flow_destroy(struct rte_eth_dev *dev, goto exit; } + /* Update meter object ref count */ + if (nfp_flow->mtr_id != NFP_MAX_MTR_CNT) { + ret = nfp_mtr_update_ref_cnt(app_fw_flower->mtr_priv, + nfp_flow->mtr_id, false); + if (ret != 0) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Update meter ref_cnt failed."); + } + } + exit: nfp_flow_free(nfp_flow); diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h index b0c2aaf6d8..b8da752a9d 100644 --- a/drivers/net/nfp/nfp_flow.h +++ b/drivers/net/nfp/nfp_flow.h @@ -222,6 +222,7 @@ struct rte_flow { struct nfp_fl_tun tun; size_t length; uint32_t hash_key; + uint32_t mtr_id; bool install_flag; enum nfp_flow_type type; }; diff --git a/drivers/net/nfp/nfp_mtr.c b/drivers/net/nfp/nfp_mtr.c index f77381dcb3..356bcdb370 100644 --- a/drivers/net/nfp/nfp_mtr.c +++ b/drivers/net/nfp/nfp_mtr.c @@ -1125,3 +1125,19 @@ nfp_mtr_priv_uninit(struct nfp_pf_dev *pf_dev) rte_free(priv); } + +int +nfp_mtr_update_ref_cnt(struct nfp_mtr_priv *priv, + uint32_t mtr_id, + bool add) +{ + struct nfp_mtr *mtr; + + mtr = nfp_mtr_find_by_mtr_id(priv, mtr_id); + if (mtr == NULL) + return -EINVAL; + + mtr->ref_cnt += add ? 1 : -1; + + return 0; +} diff --git a/drivers/net/nfp/nfp_mtr.h b/drivers/net/nfp/nfp_mtr.h index 7bfc935e7d..41c472f139 100644 --- a/drivers/net/nfp/nfp_mtr.h +++ b/drivers/net/nfp/nfp_mtr.h @@ -176,5 +176,7 @@ struct nfp_mtr *nfp_mtr_find_by_mtr_id(struct nfp_mtr_priv *priv, uint32_t mtr_id); struct nfp_mtr *nfp_mtr_find_by_profile_id(struct nfp_mtr_priv *priv, uint32_t profile_id); +int nfp_mtr_update_ref_cnt(struct nfp_mtr_priv *priv, + uint32_t mtr_id, bool add); #endif /* __NFP_MTR_H__ */ -- 2.29.3