From patchwork Tue Feb 27 19:15:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harman Kalra X-Patchwork-Id: 137381 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 CCA2D43C06; Tue, 27 Feb 2024 20:17:08 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1054942F2B; Tue, 27 Feb 2024 20:16:32 +0100 (CET) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 4042942F37 for ; Tue, 27 Feb 2024 20:16:30 +0100 (CET) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 41RG2VYN023959 for ; Tue, 27 Feb 2024 11:16:29 -0800 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=L91ch2k8CzBwnv8hl0zcU fkKY+EOQKrSEd05MurYeU0=; b=gfFHuxEIG1kUJZMSHUqQK5yK5yMzHPNiB/jo9 JY9xxBtg9+2PjHbXIXavF0wOOXTKQvPrdSw2Vvdoi3QQoDlGa2llSXYtt+wBjP8g 5DiOfDrIZnH+ZXFSKKfgzoVxsFCC1hcAkX80d+QtmuDExnJZYkhUD6hVPT5Z+FZH bsqZR7fH2sEW1SeWxvSIy/xu/bUY1HNsrYyhTBmLn1y06hoT4jfpchLXT1e0Fpee 5Lk3Z4h/EFIF1VewScSo/w5VzIXLbhSDXt3WZdnJi+pTkbjWyy1aQS/gvFpdcGBA PpaA66eQAqYYMBrXm6vY17pd9XJP7zlthfQrJMYV5Jm7W30kg== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3whjwdh15h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 27 Feb 2024 11:16:29 -0800 (PST) Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.1258.12; Tue, 27 Feb 2024 11:16:28 -0800 Received: from DC5-EXCH05.marvell.com (10.69.176.209) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 27 Feb 2024 11:16:28 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Tue, 27 Feb 2024 11:16:28 -0800 Received: from localhost.localdomain (unknown [10.29.52.211]) by maili.marvell.com (Postfix) with ESMTP id C51113F719D; Tue, 27 Feb 2024 11:16:25 -0800 (PST) From: Harman Kalra To: Nithin Dabilpuram , Kiran Kumar K , Sunil Kumar Kori , Satha Rao , Harman Kalra CC: Subject: [PATCH v4 08/23] net/cnxk: eswitch flow configurations Date: Wed, 28 Feb 2024 00:45:35 +0530 Message-ID: <20240227191550.137687-9-hkalra@marvell.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240227191550.137687-1-hkalra@marvell.com> References: <20230811163419.165790-1-hkalra@marvell.com> <20240227191550.137687-1-hkalra@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: rwNz8mLVqhKhMh3cqWhYnf3_YgPSmUlu X-Proofpoint-ORIG-GUID: rwNz8mLVqhKhMh3cqWhYnf3_YgPSmUlu X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-02-27_06,2024-02-27_01,2023-05-22_02 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 Adding flow rules for eswitch PF and VF and implementing interfaces to delete, shift flow rules Signed-off-by: Harman Kalra --- drivers/net/cnxk/cnxk_eswitch.c | 44 +++ drivers/net/cnxk/cnxk_eswitch.h | 25 +- drivers/net/cnxk/cnxk_eswitch_devargs.c | 1 + drivers/net/cnxk/cnxk_eswitch_flow.c | 454 ++++++++++++++++++++++++ drivers/net/cnxk/meson.build | 1 + 5 files changed, 522 insertions(+), 3 deletions(-) create mode 100644 drivers/net/cnxk/cnxk_eswitch_flow.c diff --git a/drivers/net/cnxk/cnxk_eswitch.c b/drivers/net/cnxk/cnxk_eswitch.c index 599ed149ae..25992fddc9 100644 --- a/drivers/net/cnxk/cnxk_eswitch.c +++ b/drivers/net/cnxk/cnxk_eswitch.c @@ -2,11 +2,33 @@ * Copyright(C) 2024 Marvell. */ +#include + #include #include #define CNXK_NIX_DEF_SQ_COUNT 512 +struct cnxk_esw_repr_hw_info * +cnxk_eswitch_representor_hw_info(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func) +{ + struct cnxk_eswitch_devargs *esw_da; + int i, j; + + if (!eswitch_dev) + return NULL; + + /* Traversing the initialized represented list */ + for (i = 0; i < eswitch_dev->nb_esw_da; i++) { + esw_da = &eswitch_dev->esw_da[i]; + for (j = 0; j < esw_da->nb_repr_ports; j++) { + if (esw_da->repr_hw_info[j].hw_func == hw_func) + return &esw_da->repr_hw_info[j]; + } + } + return NULL; +} + static int eswitch_hw_rsrc_cleanup(struct cnxk_eswitch_dev *eswitch_dev, struct rte_pci_device *pci_dev) { @@ -67,6 +89,10 @@ cnxk_eswitch_dev_remove(struct rte_pci_device *pci_dev) if (eswitch_dev->repr_cnt.nb_repr_created) cnxk_rep_dev_remove(eswitch_dev); + /* Cleanup NPC rxtx flow rules */ + cnxk_eswitch_flow_rules_remove_list(eswitch_dev, &eswitch_dev->esw_flow_list, + eswitch_dev->npc.pf_func); + /* Cleanup HW resources */ eswitch_hw_rsrc_cleanup(eswitch_dev, pci_dev); @@ -87,6 +113,21 @@ cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev) goto done; } + /* Install eswitch PF mcam rules */ + rc = cnxk_eswitch_pfvf_flow_rules_install(eswitch_dev, false); + if (rc) { + plt_err("Failed to install rxtx rules, rc %d", rc); + goto done; + } + + /* Configure TPID for Eswitch PF LFs */ + rc = roc_eswitch_nix_vlan_tpid_set(&eswitch_dev->nix, ROC_NIX_VLAN_TYPE_OUTER, + CNXK_ESWITCH_VLAN_TPID, false); + if (rc) { + plt_err("Failed to configure tpid, rc %d", rc); + goto done; + } + rc = roc_npc_mcam_enable_all_entries(&eswitch_dev->npc, 1); if (rc) { plt_err("Failed to enable NPC entries %d", rc); @@ -524,6 +565,9 @@ eswitch_hw_rsrc_setup(struct cnxk_eswitch_dev *eswitch_dev, struct rte_pci_devic if (rc) goto rsrc_cleanup; + /* List for eswitch default flows */ + TAILQ_INIT(&eswitch_dev->esw_flow_list); + return rc; rsrc_cleanup: eswitch_hw_rsrc_cleanup(eswitch_dev, pci_dev); diff --git a/drivers/net/cnxk/cnxk_eswitch.h b/drivers/net/cnxk/cnxk_eswitch.h index dcd5add6d0..5b4e1b0a71 100644 --- a/drivers/net/cnxk/cnxk_eswitch.h +++ b/drivers/net/cnxk/cnxk_eswitch.h @@ -13,11 +13,10 @@ #include "cn10k_tx.h" #define CNXK_ESWITCH_CTRL_MSG_SOCK_PATH "/tmp/cxk_rep_ctrl_msg_sock" +#define CNXK_ESWITCH_VLAN_TPID ROC_ESWITCH_VLAN_TPID #define CNXK_REP_ESWITCH_DEV_MZ "cnxk_eswitch_dev" -#define CNXK_ESWITCH_VLAN_TPID 0x8100 #define CNXK_ESWITCH_MAX_TXQ 256 #define CNXK_ESWITCH_MAX_RXQ 256 -#define CNXK_ESWITCH_LBK_CHAN 63 #define CNXK_ESWITCH_VFPF_SHIFT 8 #define CNXK_ESWITCH_QUEUE_STATE_RELEASED 0 @@ -25,6 +24,7 @@ #define CNXK_ESWITCH_QUEUE_STATE_STARTED 2 #define CNXK_ESWITCH_QUEUE_STATE_STOPPED 3 +TAILQ_HEAD(eswitch_flow_list, roc_npc_flow); enum cnxk_esw_da_pattern_type { CNXK_ESW_DA_TYPE_LIST = 0, CNXK_ESW_DA_TYPE_PFVF, @@ -39,6 +39,9 @@ struct cnxk_esw_repr_hw_info { uint16_t pfvf; /* representor port id assigned to representee */ uint16_t port_id; + uint16_t num_flow_entries; + + TAILQ_HEAD(flow_list, roc_npc_flow) repr_flow_list; }; /* Structure representing per devarg information - this can be per representee @@ -90,7 +93,6 @@ struct cnxk_eswitch_cxq { uint8_t state; }; -TAILQ_HEAD(eswitch_flow_list, roc_npc_flow); struct cnxk_eswitch_dev { /* Input parameters */ struct plt_pci_device *pci_dev; @@ -116,6 +118,13 @@ struct cnxk_eswitch_dev { uint16_t rep_cnt; uint8_t configured; + /* NPC rxtx rules */ + struct flow_list esw_flow_list; + uint16_t num_entries; + bool eswitch_vf_rules_setup; + uint16_t esw_pf_entry; + uint16_t esw_vf_entry; + /* Eswitch Representors Devargs */ uint16_t nb_esw_da; uint16_t last_probed; @@ -144,7 +153,10 @@ cnxk_eswitch_pmd_priv(void) return mz->addr; } +/* HW Resources */ int cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev); +struct cnxk_esw_repr_hw_info *cnxk_eswitch_representor_hw_info(struct cnxk_eswitch_dev *eswitch_dev, + uint16_t hw_func); int cnxk_eswitch_repr_devargs(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswitch_dev); int cnxk_eswitch_representor_info_get(struct cnxk_eswitch_dev *eswitch_dev, struct rte_eth_representor_info *info); @@ -158,4 +170,11 @@ int cnxk_eswitch_rxq_start(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid); int cnxk_eswitch_rxq_stop(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid); int cnxk_eswitch_txq_start(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid); int cnxk_eswitch_txq_stop(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid); +/* Flow Rules */ +int cnxk_eswitch_flow_rules_install(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func); +int cnxk_eswitch_flow_rules_delete(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func); +int cnxk_eswitch_pfvf_flow_rules_install(struct cnxk_eswitch_dev *eswitch_dev, bool is_vf); +int cnxk_eswitch_flow_rule_shift(uint16_t hw_func, uint16_t *new_entry); +int cnxk_eswitch_flow_rules_remove_list(struct cnxk_eswitch_dev *eswitch_dev, + struct flow_list *list, uint16_t hw_func); #endif /* __CNXK_ESWITCH_H__ */ diff --git a/drivers/net/cnxk/cnxk_eswitch_devargs.c b/drivers/net/cnxk/cnxk_eswitch_devargs.c index 58383fb835..8167ce673a 100644 --- a/drivers/net/cnxk/cnxk_eswitch_devargs.c +++ b/drivers/net/cnxk/cnxk_eswitch_devargs.c @@ -72,6 +72,7 @@ populate_repr_hw_info(struct cnxk_eswitch_dev *eswitch_dev, struct rte_eth_devar esw_da->repr_hw_info[i].pfvf = (eth_da->type == RTE_ETH_REPRESENTOR_PF) ? eth_da->ports[0] : eth_da->representor_ports[i]; + TAILQ_INIT(&esw_da->repr_hw_info[i].repr_flow_list); plt_esw_dbg(" HW func %x index %d type %d", hw_func, j, eth_da->type); } diff --git a/drivers/net/cnxk/cnxk_eswitch_flow.c b/drivers/net/cnxk/cnxk_eswitch_flow.c new file mode 100644 index 0000000000..06077bfe92 --- /dev/null +++ b/drivers/net/cnxk/cnxk_eswitch_flow.c @@ -0,0 +1,454 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell. + */ + +#include + +#include + +const uint8_t eswitch_vlan_rss_key[ROC_NIX_RSS_KEY_LEN] = { + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE}; + +int +cnxk_eswitch_flow_rules_remove_list(struct cnxk_eswitch_dev *eswitch_dev, struct flow_list *list, + uint16_t hw_func) +{ + struct roc_npc_flow *flow, *tvar; + int rc = 0; + + RTE_TAILQ_FOREACH_SAFE(flow, list, next, tvar) { + plt_esw_dbg("Removing flow %d", flow->mcam_id); + rc = roc_eswitch_npc_mcam_delete_rule(&eswitch_dev->npc, flow, + hw_func); + if (rc) + plt_err("Failed to delete rule %d", flow->mcam_id); + rc = roc_npc_mcam_free(&eswitch_dev->npc, flow); + if (rc) + plt_err("Failed to free entry %d", flow->mcam_id); + TAILQ_REMOVE(list, flow, next); + rte_free(flow); + } + + return rc; +} + +static int +eswitch_npc_vlan_rss_configure(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct roc_nix *roc_nix = roc_npc->roc_nix; + uint32_t qid, idx, hash, vlan_tci; + uint16_t *reta, reta_sz, id; + int rc = 0; + + id = flow->mcam_id; + /* Setting up the key */ + roc_nix_rss_key_set(roc_nix, eswitch_vlan_rss_key); + + reta_sz = roc_nix->reta_sz; + reta = plt_zmalloc(reta_sz * sizeof(uint16_t), 0); + if (!reta) { + plt_err("Failed to allocate mem for reta table"); + rc = -ENOMEM; + goto fail; + } + for (qid = 0; qid < reta_sz; qid++) { + vlan_tci = (1 << CNXK_ESWITCH_VFPF_SHIFT) | qid; + hash = rte_softrss(&vlan_tci, 1, eswitch_vlan_rss_key); + idx = hash & 0xFF; + reta[idx] = qid; + } + flow->mcam_id = id; + rc = roc_eswitch_npc_rss_action_configure(roc_npc, flow, FLOW_KEY_TYPE_VLAN, reta); + if (rc) { + plt_err("Failed to configure rss action, err %d", rc); + goto done; + } + +done: + plt_free(reta); +fail: + return rc; +} + +static int +eswitch_pfvf_mcam_install_rules(struct cnxk_eswitch_dev *eswitch_dev, struct roc_npc_flow *flow, + bool is_vf) +{ + uint16_t vlan_tci = 0, hw_func; + int rc; + + hw_func = eswitch_dev->npc.pf_func | is_vf; + if (!is_vf) { + /* Eswitch PF RX VLAN rule */ + vlan_tci = 1ULL << CNXK_ESWITCH_VFPF_SHIFT; + rc = roc_eswitch_npc_mcam_rx_rule(&eswitch_dev->npc, flow, hw_func, vlan_tci, + 0xFF00); + if (rc) { + plt_err("Failed to install RX rule for ESW PF to ESW VF, rc %d", rc); + goto exit; + } + plt_esw_dbg("Installed eswitch PF RX rule %d", flow->mcam_id); + rc = eswitch_npc_vlan_rss_configure(&eswitch_dev->npc, flow); + if (rc) + goto exit; + flow->enable = true; + } else { + /* Eswitch VF RX VLAN rule */ + rc = roc_eswitch_npc_mcam_rx_rule(&eswitch_dev->npc, flow, hw_func, vlan_tci, + 0xFF00); + if (rc) { + plt_err("Failed to install RX rule for ESW VF to ESW PF, rc %d", rc); + goto exit; + } + flow->enable = true; + plt_esw_dbg("Installed eswitch PF RX rule %d", flow->mcam_id); + } + + return 0; +exit: + return rc; +} + +static int +eswitch_npc_get_counter(struct roc_npc *npc, struct roc_npc_flow *flow) +{ + uint16_t ctr_id; + int rc; + + rc = roc_npc_mcam_alloc_counter(npc, &ctr_id); + if (rc < 0) { + plt_err("Failed to allocate counter, rc %d", rc); + goto fail; + } + flow->ctr_id = ctr_id; + flow->use_ctr = true; + + rc = roc_npc_mcam_clear_counter(npc, flow->ctr_id); + if (rc < 0) { + plt_err("Failed to clear counter idx %d, rc %d", flow->ctr_id, rc); + goto free; + } + return 0; +free: + roc_npc_mcam_free_counter(npc, ctr_id); +fail: + return rc; +} + +static int +eswitch_npc_get_counter_entry_ref(struct roc_npc *npc, struct roc_npc_flow *flow, + struct roc_npc_flow *ref_flow) +{ + int rc = 0, resp_count; + + rc = eswitch_npc_get_counter(npc, flow); + if (rc) + goto free; + + /* Allocate an entry viz higher priority than ref flow */ + rc = roc_npc_mcam_alloc_entry(npc, flow, ref_flow, NPC_MCAM_HIGHER_PRIO, &resp_count); + if (rc) { + plt_err("Failed to allocate entry, err %d", rc); + goto free; + } + plt_esw_dbg("New entry %d ref entry %d resp_count %d", flow->mcam_id, ref_flow->mcam_id, + resp_count); + + return 0; +free: + roc_npc_mcam_free_counter(npc, flow->ctr_id); + return rc; +} + +int +cnxk_eswitch_flow_rule_shift(uint16_t hw_func, uint16_t *entry) +{ + struct cnxk_esw_repr_hw_info *repr_info; + struct cnxk_eswitch_dev *eswitch_dev; + struct roc_npc_flow *ref_flow, *flow; + uint16_t curr_entry, new_entry; + int rc = 0, resp_count; + + eswitch_dev = cnxk_eswitch_pmd_priv(); + if (!eswitch_dev) { + plt_err("Invalid eswitch_dev handle"); + rc = -EINVAL; + goto fail; + } + + repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func); + if (!repr_info) { + plt_warn("Failed to get representor group for %x", hw_func); + rc = -ENOENT; + goto fail; + } + + ref_flow = TAILQ_FIRST(&repr_info->repr_flow_list); + if (*entry > ref_flow->mcam_id) { + flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0); + if (!flow) { + plt_err("Failed to allocate memory"); + rc = -ENOMEM; + goto fail; + } + + /* Allocate a higher priority flow rule */ + rc = roc_npc_mcam_alloc_entry(&eswitch_dev->npc, flow, ref_flow, + NPC_MCAM_HIGHER_PRIO, &resp_count); + if (rc < 0) { + plt_err("Failed to allocate a newmcam entry, rc %d", rc); + goto fail; + } + + if (flow->mcam_id > ref_flow->mcam_id) { + plt_err("New flow %d is still at higher priority than ref_flow %d", + flow->mcam_id, ref_flow->mcam_id); + rc = -EINVAL; + goto free_entry; + } + + plt_info("Before shift: HW_func %x curr_entry %d ref flow id %d new_entry %d", + hw_func, *entry, ref_flow->mcam_id, flow->mcam_id); + + curr_entry = *entry; + new_entry = flow->mcam_id; + + rc = roc_npc_mcam_move(&eswitch_dev->npc, curr_entry, new_entry); + if (rc) { + plt_err("Failed to shift the new index %d to curr index %d, err %d", *entry, + curr_entry, rc); + goto free_entry; + } + *entry = flow->mcam_id; + + /* Freeing the current entry */ + rc = roc_npc_mcam_free_entry(&eswitch_dev->npc, curr_entry); + if (rc) { + plt_err("Failed to free the old entry. err %d", rc); + goto free_entry; + } + + plt_free(flow); + plt_info("After shift: HW_func %x old_entry %d new_entry %d", hw_func, curr_entry, + *entry); + } + + return 0; +free_entry: + +fail: + return rc; +} + +int +cnxk_eswitch_flow_rules_delete(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func) +{ + struct cnxk_esw_repr_hw_info *repr_info; + struct flow_list *list; + int rc = 0; + + repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func); + if (!repr_info) { + plt_warn("Failed to get representor group for %x", hw_func); + rc = -ENOENT; + goto fail; + } + list = &repr_info->repr_flow_list; + + plt_esw_dbg("Deleting flows for %x", hw_func); + rc = cnxk_eswitch_flow_rules_remove_list(eswitch_dev, list, hw_func); + if (rc) + plt_err("Failed to delete rules for hw func %x", hw_func); + +fail: + return rc; +} + +int +cnxk_eswitch_flow_rules_install(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func) +{ + struct roc_npc_flow *rx_flow, *tx_flow, *flow_iter, *esw_pf_flow = NULL; + struct cnxk_esw_repr_hw_info *repr_info; + struct flow_list *list; + uint16_t vlan_tci; + int rc = 0; + + repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func); + if (!repr_info) { + plt_err("Failed to get representor group for %x", hw_func); + rc = -EINVAL; + goto fail; + } + list = &repr_info->repr_flow_list; + + /* Taking ESW PF as reference entry for installing new rules */ + TAILQ_FOREACH(flow_iter, &eswitch_dev->esw_flow_list, next) { + if (flow_iter->mcam_id == eswitch_dev->esw_pf_entry) { + esw_pf_flow = flow_iter; + break; + } + } + + if (!esw_pf_flow) { + plt_err("Failed to get the ESW PF flow"); + rc = -EINVAL; + goto fail; + } + + /* Installing RX rule */ + rx_flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0); + if (!rx_flow) { + plt_err("Failed to allocate memory"); + rc = -ENOMEM; + goto fail; + } + + rc = eswitch_npc_get_counter_entry_ref(&eswitch_dev->npc, rx_flow, esw_pf_flow); + if (rc) { + plt_err("Failed to get counter and mcam entry, rc %d", rc); + goto free_rx_flow; + } + + /* VLAN TCI value for this representee is the rep id from AF driver */ + vlan_tci = repr_info->rep_id; + rc = roc_eswitch_npc_mcam_rx_rule(&eswitch_dev->npc, rx_flow, hw_func, vlan_tci, 0xFFFF); + if (rc) { + plt_err("Failed to install RX rule for ESW PF to ESW VF, rc %d", rc); + goto free_rx_entry; + } + rx_flow->enable = true; + /* List in ascending order of mcam entries */ + TAILQ_FOREACH(flow_iter, list, next) { + if (flow_iter->mcam_id > rx_flow->mcam_id) { + TAILQ_INSERT_BEFORE(flow_iter, rx_flow, next); + goto done_rx; + } + } + TAILQ_INSERT_TAIL(list, rx_flow, next); +done_rx: + repr_info->num_flow_entries++; + plt_esw_dbg("Installed RX flow rule %d for representee %x with vlan tci %x MCAM id %d", + eswitch_dev->num_entries, hw_func, vlan_tci, rx_flow->mcam_id); + + /* Installing TX rule */ + tx_flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0); + if (!tx_flow) { + plt_err("Failed to allocate memory"); + rc = -ENOMEM; + goto remove_rx_rule; + } + + rc = eswitch_npc_get_counter_entry_ref(&eswitch_dev->npc, tx_flow, esw_pf_flow); + if (rc) { + plt_err("Failed to get counter and mcam entry, rc %d", rc); + goto free_tx_flow; + } + + vlan_tci = (1ULL << CNXK_ESWITCH_VFPF_SHIFT) | repr_info->rep_id; + rc = roc_eswitch_npc_mcam_tx_rule(&eswitch_dev->npc, tx_flow, hw_func, vlan_tci); + if (rc) { + plt_err("Failed to install RX rule for ESW PF to ESW VF, rc %d", rc); + goto free_tx_entry; + } + tx_flow->enable = true; + /* List in ascending order of mcam entries */ + TAILQ_FOREACH(flow_iter, list, next) { + if (flow_iter->mcam_id > tx_flow->mcam_id) { + TAILQ_INSERT_BEFORE(flow_iter, tx_flow, next); + goto done_tx; + } + } + TAILQ_INSERT_TAIL(list, tx_flow, next); +done_tx: + repr_info->num_flow_entries++; + plt_esw_dbg("Installed TX flow rule %d for representee %x with vlan tci %x MCAM id %d", + repr_info->num_flow_entries, hw_func, vlan_tci, tx_flow->mcam_id); + + return 0; +free_tx_entry: + roc_npc_mcam_free(&eswitch_dev->npc, tx_flow); +free_tx_flow: + rte_free(tx_flow); +remove_rx_rule: + TAILQ_REMOVE(list, rx_flow, next); +free_rx_entry: + roc_npc_mcam_free(&eswitch_dev->npc, rx_flow); +free_rx_flow: + rte_free(rx_flow); +fail: + return rc; +} + +int +cnxk_eswitch_pfvf_flow_rules_install(struct cnxk_eswitch_dev *eswitch_dev, bool is_vf) +{ + struct roc_npc_flow *flow, *flow_iter; + struct flow_list *list; + int rc = 0; + + list = &eswitch_dev->esw_flow_list; + flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0); + if (!flow) { + plt_err("Failed to allocate memory"); + rc = -ENOMEM; + goto fail; + } + + rc = eswitch_npc_get_counter(&eswitch_dev->npc, flow); + if (rc) { + plt_err("Failed to get counter and mcam entry, rc %d", rc); + goto free_flow; + } + if (!is_vf) { + /* Reserving an entry for esw VF but will not be installed */ + rc = roc_npc_get_free_mcam_entry(&eswitch_dev->npc, flow); + if (rc < 0) { + plt_err("Failed to allocate entry for vf, err %d", rc); + goto free_flow; + } + eswitch_dev->esw_vf_entry = flow->mcam_id; + /* Allocate an entry for esw PF */ + rc = eswitch_npc_get_counter_entry_ref(&eswitch_dev->npc, flow, flow); + if (rc) { + plt_err("Failed to allocate entry for pf, err %d", rc); + goto free_flow; + } + eswitch_dev->esw_pf_entry = flow->mcam_id; + plt_esw_dbg("Allocated entries for esw: PF %d and VF %d", eswitch_dev->esw_pf_entry, + eswitch_dev->esw_vf_entry); + } else { + flow->mcam_id = eswitch_dev->esw_vf_entry; + } + + rc = eswitch_pfvf_mcam_install_rules(eswitch_dev, flow, is_vf); + if (rc) { + plt_err("Failed to install entries, rc %d", rc); + goto free_flow; + } + + /* 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); + goto done; + } + } + TAILQ_INSERT_TAIL(list, flow, next); +done: + eswitch_dev->num_entries++; + plt_esw_dbg("Installed new eswitch flow rule %d with MCAM id %d", eswitch_dev->num_entries, + flow->mcam_id); + + return 0; + +free_flow: + cnxk_eswitch_flow_rules_remove_list(eswitch_dev, &eswitch_dev->esw_flow_list, + eswitch_dev->npc.pf_func); +fail: + return rc; +} diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build index fcd5d3d569..488e89253d 100644 --- a/drivers/net/cnxk/meson.build +++ b/drivers/net/cnxk/meson.build @@ -30,6 +30,7 @@ sources = files( 'cnxk_ethdev_sec_telemetry.c', 'cnxk_eswitch.c', 'cnxk_eswitch_devargs.c', + 'cnxk_eswitch_flow.c', 'cnxk_link.c', 'cnxk_lookup.c', 'cnxk_ptp.c',