From patchwork Tue Apr 6 14:41:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nithin Dabilpuram X-Patchwork-Id: 90719 X-Patchwork-Delegate: jerinj@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6618EA0546; Tue, 6 Apr 2021 16:49:12 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 723B0141182; Tue, 6 Apr 2021 16:44:07 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 9AFA21410E3 for ; Tue, 6 Apr 2021 16:44:05 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 136EeBLD001006 for ; Tue, 6 Apr 2021 07:44:04 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=pfpt0220; bh=gE+UJ6PzI8/o5THvs8nXDm8UptQ45E7vCExd28C5UXc=; b=dZVuSISsy4AESgJF3oF6NmdRWUsgo+13VkfVJfzv35r/FNQcn2nt4i8NPjy2NgvJTrSh 5AVXyszPBpQWy+Fbuu1WKINY9WMrDft8QlwTXO08ig1QxACtJ6PVuoM742hE5f8dKtnQ PtxFWjJdtx5xFB68dFpd9pGHWXhB3vwMePFooBT9dndof0JdWSUrK1vvTZP6h59uHSx/ 5TgQoZkc8ROroyL88UYjQzDlKINrS7Z1J5B/3Dif2iGA2lVslHQCWfOwA13YoR7GhQoe XHUYJpjdOWk774n+/w++qPkM0kUtpULmANVK7k0lC0QgTQhks672s4hJFQTxtQuuQhxL Xg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com with ESMTP id 37r72p30nw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 06 Apr 2021 07:44:04 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Tue, 6 Apr 2021 07:44:03 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 6 Apr 2021 07:44:03 -0700 Received: from hyd1588t430.marvell.com (unknown [10.29.52.204]) by maili.marvell.com (Postfix) with ESMTP id E8C203F703F; Tue, 6 Apr 2021 07:44:00 -0700 (PDT) From: Nithin Dabilpuram To: CC: , , , , , , Date: Tue, 6 Apr 2021 20:11:36 +0530 Message-ID: <20210406144144.19925-45-ndabilpuram@marvell.com> X-Mailer: git-send-email 2.8.4 In-Reply-To: <20210406144144.19925-1-ndabilpuram@marvell.com> References: <20210305133918.8005-1-ndabilpuram@marvell.com> <20210406144144.19925-1-ndabilpuram@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: uxXzYs5HXM-C25qOFfu-hic810WPko0O X-Proofpoint-ORIG-GUID: uxXzYs5HXM-C25qOFfu-hic810WPko0O X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.369, 18.0.761 definitions=2021-04-06_03:2021-04-01, 2021-04-06 signatures=0 Subject: [dpdk-dev] [PATCH v5 44/52] common/cnxk: add npc init and fini support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Kiran Kumar K Adding support initialize and fini the npc. Further, adding APIs to create and destroy the npc rules. Signed-off-by: Kiran Kumar K --- drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_npc.c | 713 ++++++++++++++++++++++++++++++++++++++++ drivers/common/cnxk/roc_npc.h | 40 +++ drivers/common/cnxk/version.map | 16 + 4 files changed, 770 insertions(+) create mode 100644 drivers/common/cnxk/roc_npc.c diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build index 9dd4c23..f12e344 100644 --- a/drivers/common/cnxk/meson.build +++ b/drivers/common/cnxk/meson.build @@ -34,6 +34,7 @@ sources = files('roc_dev.c', 'roc_npa.c', 'roc_npa_debug.c', 'roc_npa_irq.c', + 'roc_npc.c', 'roc_npc_mcam.c', 'roc_npc_parse.c', 'roc_npc_utils.c', diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c new file mode 100644 index 0000000..c1ac3c7 --- /dev/null +++ b/drivers/common/cnxk/roc_npc.c @@ -0,0 +1,713 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2021 Marvell. + */ + +#include "roc_api.h" +#include "roc_priv.h" + +int +roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_free_counter(npc, ctr_id); +} + +int +roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, + uint64_t *count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_read_counter(npc, ctr_id, count); +} + +int +roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_clear_counter(npc, ctr_id); +} + +int +roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_free_entry(npc, entry); +} + +int +roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_flow_free_all_resources(npc); +} + +int +roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, + int *alloc_entry, int req_count, int priority, + int *resp_count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_alloc_entries(npc, ref_entry, alloc_entry, req_count, + priority, resp_count); +} + +int +roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, + struct roc_npc_flow *ref_mcam, int prio, + int *resp_count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count); +} + +int +roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, + bool enable) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_ena_dis_entry(npc, mcam, enable); +} + +int +roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_write_entry(npc, mcam); +} + +int +roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + if (roc_model_is_cn10k()) + return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1); + else + return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1); +} + +static int +npc_mcam_tot_entries(void) +{ + /* FIXME: change to reading in AF from NPC_AF_CONST1/2 + * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS + */ + if (roc_model_is_cn10k()) + return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */ + else + return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */ +} + +const char * +roc_npc_profile_name_get(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return (char *)npc->profile_name; +} + +int +roc_npc_init(struct roc_npc *roc_npc) +{ + uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL; + struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix); + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + uint32_t bmap_sz; + int rc = 0, idx; + size_t sz; + + PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ); + + memset(npc, 0, sizeof(*npc)); + npc->mbox = (&nix->dev)->mbox; + roc_npc->channel = nix->rx_chan_base; + roc_npc->pf_func = (&nix->dev)->pf_func; + npc->channel = roc_npc->channel; + npc->pf_func = roc_npc->pf_func; + npc->flow_max_priority = roc_npc->flow_max_priority; + npc->switch_header_type = roc_npc->switch_header_type; + npc->flow_prealloc_size = roc_npc->flow_prealloc_size; + + if (npc->mbox == NULL) + return NPC_ERR_PARAM; + + rc = npc_mcam_fetch_kex_cfg(npc); + if (rc) + goto done; + + roc_npc->kex_capability = npc_get_kex_capability(npc); + roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX]; + + npc->mark_actions = 0; + + npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX]; + + /* Free, free_rev, live and live_rev entries */ + bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries); + mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0); + if (mem == NULL) { + plt_err("Bmap alloc failed"); + rc = NPC_ERR_NO_MEM; + return rc; + } + + sz = npc->flow_max_priority * sizeof(struct npc_mcam_ents_info); + npc->flow_entry_info = plt_zmalloc(sz, 0); + if (npc->flow_entry_info == NULL) { + plt_err("flow_entry_info alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->free_entries = plt_zmalloc(sz, 0); + if (npc->free_entries == NULL) { + plt_err("free_entries alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->free_entries_rev = plt_zmalloc(sz, 0); + if (npc->free_entries_rev == NULL) { + plt_err("free_entries_rev alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->live_entries = plt_zmalloc(sz, 0); + if (npc->live_entries == NULL) { + plt_err("live_entries alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->live_entries_rev = plt_zmalloc(sz, 0); + if (npc->live_entries_rev == NULL) { + plt_err("live_entries_rev alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct npc_flow_list); + npc->flow_list = plt_zmalloc(sz, 0); + if (npc->flow_list == NULL) { + plt_err("flow_list alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + npc_mem = mem; + for (idx = 0; idx < npc->flow_max_priority; idx++) { + TAILQ_INIT(&npc->flow_list[idx]); + + npc->free_entries[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->free_entries_rev[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->live_entries[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->live_entries_rev[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->flow_entry_info[idx].free_ent = 0; + npc->flow_entry_info[idx].live_ent = 0; + npc->flow_entry_info[idx].max_id = 0; + npc->flow_entry_info[idx].min_id = ~(0); + } + + npc->rss_grps = NPC_RSS_GRPS; + + bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps); + nix_mem = plt_zmalloc(bmap_sz, 0); + if (nix_mem == NULL) { + plt_err("Bmap alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz); + + if (!npc->rss_grp_entries) { + plt_err("bitmap init failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + /* Group 0 will be used for RSS, + * 1 -7 will be used for npc_flow RSS action + */ + plt_bitmap_set(npc->rss_grp_entries, 0); + + return rc; + +done: + if (npc->flow_list) + plt_free(npc->flow_list); + if (npc->live_entries_rev) + plt_free(npc->live_entries_rev); + if (npc->live_entries) + plt_free(npc->live_entries); + if (npc->free_entries_rev) + plt_free(npc->free_entries_rev); + if (npc->free_entries) + plt_free(npc->free_entries); + if (npc->flow_entry_info) + plt_free(npc->flow_entry_info); + if (npc_mem) + plt_free(npc_mem); + return rc; +} + +int +roc_npc_fini(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + int rc; + + rc = npc_flow_free_all_resources(npc); + if (rc) { + plt_err("Error when deleting NPC MCAM entries, counters"); + return rc; + } + + if (npc->flow_list) { + plt_free(npc->flow_list); + npc->flow_list = NULL; + } + + if (npc->live_entries_rev) { + plt_free(npc->live_entries_rev); + npc->live_entries_rev = NULL; + } + + if (npc->live_entries) { + plt_free(npc->live_entries); + npc->live_entries = NULL; + } + + if (npc->free_entries_rev) { + plt_free(npc->free_entries_rev); + npc->free_entries_rev = NULL; + } + + if (npc->free_entries) { + plt_free(npc->free_entries); + npc->free_entries = NULL; + } + + if (npc->flow_entry_info) { + plt_free(npc->flow_entry_info); + npc->flow_entry_info = NULL; + } + + return 0; +} + +static int +npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + const struct roc_npc_action_mark *act_mark; + const struct roc_npc_action_queue *act_q; + const struct roc_npc_action_vf *vf_act; + int sel_act, req_act = 0; + uint16_t pf_func, vf_id; + int errcode = 0; + int mark = 0; + int rq = 0; + + /* Initialize actions */ + flow->ctr_id = NPC_COUNTER_NONE; + pf_func = npc->pf_func; + + for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { + switch (actions->type) { + case ROC_NPC_ACTION_TYPE_VOID: + break; + case ROC_NPC_ACTION_TYPE_MARK: + act_mark = (const struct roc_npc_action_mark *) + actions->conf; + if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) { + plt_err("mark value must be < 0xfffe"); + goto err_exit; + } + mark = act_mark->id + 1; + req_act |= ROC_NPC_ACTION_TYPE_MARK; + npc->mark_actions += 1; + break; + + case ROC_NPC_ACTION_TYPE_FLAG: + mark = NPC_FLOW_FLAG_VAL; + req_act |= ROC_NPC_ACTION_TYPE_FLAG; + npc->mark_actions += 1; + break; + + case ROC_NPC_ACTION_TYPE_COUNT: + /* Indicates, need a counter */ + flow->ctr_id = 1; + req_act |= ROC_NPC_ACTION_TYPE_COUNT; + break; + + case ROC_NPC_ACTION_TYPE_DROP: + req_act |= ROC_NPC_ACTION_TYPE_DROP; + break; + + case ROC_NPC_ACTION_TYPE_PF: + req_act |= ROC_NPC_ACTION_TYPE_PF; + pf_func &= (0xfc00); + break; + + case ROC_NPC_ACTION_TYPE_VF: + vf_act = + (const struct roc_npc_action_vf *)actions->conf; + req_act |= ROC_NPC_ACTION_TYPE_VF; + vf_id = vf_act->id & RVU_PFVF_FUNC_MASK; + pf_func &= (0xfc00); + pf_func = (pf_func | (vf_id + 1)); + break; + + case ROC_NPC_ACTION_TYPE_QUEUE: + act_q = (const struct roc_npc_action_queue *) + actions->conf; + rq = act_q->index; + req_act |= ROC_NPC_ACTION_TYPE_QUEUE; + break; + + case ROC_NPC_ACTION_TYPE_RSS: + req_act |= ROC_NPC_ACTION_TYPE_RSS; + break; + + case ROC_NPC_ACTION_TYPE_SEC: + /* Assumes user has already configured security + * session for this flow. Associated conf is + * opaque. When security is implemented, + * we need to verify that for specified security + * session: + * action_type == + * NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL && + * session_protocol == + * NPC_SECURITY_PROTOCOL_IPSEC + * + * RSS is not supported with inline ipsec. Get the + * rq from associated conf, or make + * ROC_NPC_ACTION_TYPE_QUEUE compulsory with this + * action. + * Currently, rq = 0 is assumed. + */ + req_act |= ROC_NPC_ACTION_TYPE_SEC; + rq = 0; + break; + default: + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + } + + /* Check if actions specified are compatible */ + if (attr->egress) { + /* Only DROP/COUNT is supported */ + if (!(req_act & ROC_NPC_ACTION_TYPE_DROP)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } else if (req_act & ~(ROC_NPC_ACTION_TYPE_DROP | + ROC_NPC_ACTION_TYPE_COUNT)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + flow->npc_action = NIX_TX_ACTIONOP_DROP; + goto set_pf_func; + } + + /* We have already verified the attr, this is ingress. + * - Exactly one terminating action is supported + * - Exactly one of MARK or FLAG is supported + * - If terminating action is DROP, only count is valid. + */ + sel_act = req_act & NPC_ACTION_TERM; + if ((sel_act & (sel_act - 1)) != 0) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + if (req_act & ROC_NPC_ACTION_TYPE_DROP) { + sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT; + if ((sel_act & (sel_act - 1)) != 0) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + } + + if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) == + (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + /* Set NIX_RX_ACTIONOP */ + if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) + flow->npc_action |= (uint64_t)rq << 20; + } else if (req_act & ROC_NPC_ACTION_TYPE_DROP) { + flow->npc_action = NIX_RX_ACTIONOP_DROP; + } else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + flow->npc_action |= (uint64_t)rq << 20; + } else if (req_act & ROC_NPC_ACTION_TYPE_RSS) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else if (req_act & ROC_NPC_ACTION_TYPE_SEC) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC; + flow->npc_action |= (uint64_t)rq << 20; + } else if (req_act & + (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) { + /* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end + * This is default action, when user specify only + * COUNT ACTION + */ + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else { + /* Should never reach here */ + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + if (mark) + flow->npc_action |= (uint64_t)mark << 40; + +set_pf_func: + /* Ideally AF must ensure that correct pf_func is set */ + flow->npc_action |= (uint64_t)pf_func << 4; + + return 0; + +err_exit: + return errcode; +} + +typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst); + +static int +npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[], + struct roc_npc_flow *flow, struct npc_parse_state *pst) +{ + npc_parse_stage_func_t parse_stage_funcs[] = { + npc_parse_meta_items, npc_parse_cpt_hdr, npc_parse_higig2_hdr, + npc_parse_la, npc_parse_lb, npc_parse_lc, + npc_parse_ld, npc_parse_le, npc_parse_lf, + npc_parse_lg, npc_parse_lh, + }; + uint8_t layer = 0; + int key_offset; + int rc; + + if (pattern == NULL) + return NPC_ERR_PARAM; + + memset(pst, 0, sizeof(*pst)); + pst->npc = npc; + pst->flow = flow; + + /* Use integral byte offset */ + key_offset = pst->npc->keyx_len[flow->nix_intf]; + key_offset = (key_offset + 7) / 8; + + /* Location where LDATA would begin */ + pst->mcam_data = (uint8_t *)flow->mcam_data; + pst->mcam_mask = (uint8_t *)flow->mcam_mask; + + while (pattern->type != ROC_NPC_ITEM_TYPE_END && + layer < PLT_DIM(parse_stage_funcs)) { + /* Skip place-holders */ + pattern = npc_parse_skip_void_and_any_items(pattern); + + pst->pattern = pattern; + rc = parse_stage_funcs[layer](pst); + if (rc != 0) + return rc; + + layer++; + + /* + * Parse stage function sets pst->pattern to + * 1 past the last item it consumed. + */ + pattern = pst->pattern; + + if (pst->terminate) + break; + } + + /* Skip trailing place-holders */ + pattern = npc_parse_skip_void_and_any_items(pattern); + + /* Are there more items than what we can handle? */ + if (pattern->type != ROC_NPC_ITEM_TYPE_END) + return NPC_ERR_PATTERN_NOTSUP; + + return 0; +} + +static int +npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr, + struct roc_npc_flow *flow) +{ + if (attr == NULL) + return NPC_ERR_PARAM; + else if (attr->priority >= npc->flow_max_priority) + return NPC_ERR_PARAM; + else if ((!attr->egress && !attr->ingress) || + (attr->egress && attr->ingress)) + return NPC_ERR_PARAM; + + if (attr->ingress) + flow->nix_intf = ROC_NPC_INTF_RX; + else + flow->nix_intf = ROC_NPC_INTF_TX; + + flow->priority = attr->priority; + return 0; +} + +static int +npc_parse_rule(struct npc *npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], struct roc_npc_flow *flow, + struct npc_parse_state *pst) +{ + int err; + + /* Check attr */ + err = npc_parse_attr(npc, attr, flow); + if (err) + return err; + + /* Check pattern */ + err = npc_parse_pattern(npc, pattern, flow, pst); + if (err) + return err; + + /* Check action */ + err = npc_parse_actions(npc, attr, actions, flow); + if (err) + return err; + return 0; +} + +int +roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_parse_state parse_state = {0}; + int rc; + + rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); + if (rc) + return rc; + + parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); + + return npc_program_mcam(npc, &parse_state, 0); +} + +struct roc_npc_flow * +roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], int *errcode) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct roc_npc_flow *flow, *flow_iter; + struct npc_parse_state parse_state; + struct npc_flow_list *list; + int rc; + + flow = plt_zmalloc(sizeof(*flow), 0); + if (flow == NULL) { + *errcode = NPC_ERR_NO_MEM; + return NULL; + } + memset(flow, 0, sizeof(*flow)); + + rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); + if (rc != 0) { + *errcode = rc; + goto err_exit; + } + + parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); + + rc = npc_program_mcam(npc, &parse_state, 1); + if (rc != 0) { + *errcode = rc; + goto err_exit; + } + + list = &npc->flow_list[flow->priority]; + /* List in ascending order of mcam entries */ + TAILQ_FOREACH(flow_iter, list, next) { + if (flow_iter->mcam_id > flow->mcam_id) { + TAILQ_INSERT_BEFORE(flow_iter, flow, next); + return flow; + } + } + + TAILQ_INSERT_TAIL(list, flow, next); + return flow; + +err_exit: + plt_free(flow); + return NULL; +} + +int +roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct plt_bitmap *bmap; + uint16_t match_id; + int rc; + + match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & + NPC_RX_ACT_MATCH_MASK; + + if (match_id && match_id < NPC_ACTION_FLAG_DEFAULT) { + if (npc->mark_actions == 0) + return NPC_ERR_PARAM; + } + + rc = npc_mcam_free_entry(npc, flow->mcam_id); + if (rc != 0) + return rc; + + TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next); + + bmap = npc->live_entries[flow->priority]; + plt_bitmap_clear(bmap, flow->mcam_id); + + plt_free(flow); + return 0; +} diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index c841240..996739e 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -126,4 +126,44 @@ struct roc_npc { uint8_t reserved[ROC_NPC_MEM_SZ]; } __plt_cache_aligned; +int __roc_api roc_npc_init(struct roc_npc *roc_npc); +int __roc_api roc_npc_fini(struct roc_npc *roc_npc); +const char *__roc_api roc_npc_profile_name_get(struct roc_npc *roc_npc); + +struct roc_npc_flow *__roc_api +roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], int *errcode); +int __roc_api roc_npc_flow_destroy(struct roc_npc *roc_npc, + struct roc_npc_flow *flow); +int __roc_api roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry); +int __roc_api roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, + struct roc_npc_flow *mcam, + struct roc_npc_flow *ref_mcam, int prio, + int *resp_count); +int __roc_api roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, + int *alloc_entry, int req_count, + int priority, int *resp_count); +int __roc_api roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, + struct roc_npc_flow *mcam, + bool enable); +int __roc_api roc_npc_mcam_write_entry(struct roc_npc *roc_npc, + struct roc_npc_flow *mcam); +int __roc_api roc_npc_flow_parse(struct roc_npc *roc_npc, + const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], + struct roc_npc_flow *flow); +int __roc_api roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc); + +int __roc_api roc_npc_mcam_free_counter(struct roc_npc *roc_npc, + uint16_t ctr_id); + +int __roc_api roc_npc_mcam_read_counter(struct roc_npc *roc_npc, + uint32_t ctr_id, uint64_t *count); +int __roc_api roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, + uint32_t ctr_id); + +int __roc_api roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc); + #endif /* _ROC_NPC_H_ */ diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index f961a23..ed82b56 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -154,6 +154,22 @@ INTERNAL { roc_npa_pool_destroy; roc_npa_pool_op_pc_reset; roc_npa_pool_range_update_check; + roc_npc_fini; + roc_npc_flow_create; + roc_npc_flow_destroy; + roc_npc_flow_parse; + roc_npc_get_low_priority_mcam; + roc_npc_init; + roc_npc_mcam_alloc_entries; + roc_npc_mcam_alloc_entry; + roc_npc_mcam_clear_counter; + roc_npc_mcam_ena_dis_entry; + roc_npc_mcam_free_all_resources; + roc_npc_mcam_free_counter; + roc_npc_mcam_free_entry; + roc_npc_mcam_write_entry; + roc_npc_mcam_read_counter; + roc_npc_profile_name_get; roc_plt_init; roc_plt_init_cb_register;