get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/93589/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 93589,
    "url": "http://patches.dpdk.org/api/patches/93589/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210530085929.29695-45-venkatkumar.duvvuru@broadcom.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210530085929.29695-45-venkatkumar.duvvuru@broadcom.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210530085929.29695-45-venkatkumar.duvvuru@broadcom.com",
    "date": "2021-05-30T08:59:15",
    "name": "[44/58] net/bnxt: refactor ULP mapper and parser",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "192d33860d3da4c06956dba050cf11b5751f2300",
    "submitter": {
        "id": 1635,
        "url": "http://patches.dpdk.org/api/people/1635/?format=api",
        "name": "Venkat Duvvuru",
        "email": "venkatkumar.duvvuru@broadcom.com"
    },
    "delegate": {
        "id": 1766,
        "url": "http://patches.dpdk.org/api/users/1766/?format=api",
        "username": "ajitkhaparde",
        "first_name": "Ajit",
        "last_name": "Khaparde",
        "email": "ajit.khaparde@broadcom.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20210530085929.29695-45-venkatkumar.duvvuru@broadcom.com/mbox/",
    "series": [
        {
            "id": 17161,
            "url": "http://patches.dpdk.org/api/series/17161/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=17161",
            "date": "2021-05-30T08:58:31",
            "name": "enhancements to host based flow table management",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/17161/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/93589/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/93589/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "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])\n\tby inbox.dpdk.org (Postfix) with ESMTP id E197CA0524;\n\tSun, 30 May 2021 11:06:31 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 863B7411DB;\n\tSun, 30 May 2021 11:01:45 +0200 (CEST)",
            "from relay.smtp-ext.broadcom.com (saphodev.broadcom.com\n [192.19.11.229]) by mails.dpdk.org (Postfix) with ESMTP id 50AD6411EA\n for <dev@dpdk.org>; Sun, 30 May 2021 11:01:43 +0200 (CEST)",
            "from S60.dhcp.broadcom.net (unknown [10.123.66.170])\n (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n (No client certificate requested)\n by relay.smtp-ext.broadcom.com (Postfix) with ESMTPS id AFBE47DC0;\n Sun, 30 May 2021 02:01:41 -0700 (PDT)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 relay.smtp-ext.broadcom.com AFBE47DC0",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com;\n s=dkimrelay; t=1622365302;\n bh=ZqRb/u4v+3mr38MN/P4O+VzBgsSmuKA6sK2KYVBK4Ng=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=To1HK0QJ1As5mDsoDazqnCMlR8udf//Sy/UcoSKQmV+il/IQqzQu+L1Tv/kSl9OTp\n uPbAplHHj/gf+iVPFioYNJ6UDs0N4gcwslKP/0keq7z+9FRjjBad3M6QKE8hqXQpWe\n q2Yp3FHUkVwigRJVPdvKwg6StEBw+1KZxzfkryY4=",
        "From": "Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>",
        "To": "dev@dpdk.org",
        "Cc": "Kishore Padmanabha <kishore.padmanabha@broadcom.com>,\n Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>,\n Jay Ding <jay.ding@broadcom.com>",
        "Date": "Sun, 30 May 2021 14:29:15 +0530",
        "Message-Id": "<20210530085929.29695-45-venkatkumar.duvvuru@broadcom.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20210530085929.29695-1-venkatkumar.duvvuru@broadcom.com>",
        "References": "<20210530085929.29695-1-venkatkumar.duvvuru@broadcom.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH 44/58] net/bnxt: refactor ULP mapper and parser",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Kishore Padmanabha <kishore.padmanabha@broadcom.com>\n\n1. The internal and external exact match table resource types\nis combined since the resource handle contains the encoded\ntype whether it is internal or external exact match entry.\n\n2. When a flow doesn't hit the offloaded rules, the default action is\nto send it to the kernel (L2 driver interface). In order to do that,\nTRUFLOW must know the kernel interface's (PF's) default vnic id.\nThis patch fetches the PF's default vnic id from the dpdk core and\nstores it in port database. It also stores the mac addr for the\nfuture usage. Renamed compute field for layer 4 port enums.\nAdded support for port database opcode that can get port details\nlike mac address which can then be populated in the l2 context entry.\n\n3. Both active and default bit set need to considered to check if a\nspecific flow type is enabled or not.\n\n4. ulp mapper fetches the dpdk port id from the compute field index\nBNXT_ULP_CF_IDX_DEV_PORT_ID which is used to get the interface’s\nmac address eventually. However, the compute field array is not\npopulated with dpdk port id at the index BNXT_ULP_CF_IDX_DEV_PORT_ID.\nThe problem fixed by populating the compute field array correctly.\n\n5. Some dpdk applications may accumulate the flow counters while some\nmay not. In cases where the application is accumulating the counters\nthe PMD need not do the accumulation itself and viceversa to report\nthe correct flow counters.\n\n6. Pointer to bp is added to open session parms to support\nshared session.\n\nSigned-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>\nSigned-off-by: Kishore Padmanabha <kishore.padmanabha@broadcom.com>\nSigned-off-by: Jay Ding <jay.ding@broadcom.com>\nReviewed-by: Lance Richardson <lance.richardson@broadcom.com>\nReviewed-by: Ajit Kumar Khaparde <ajit.khaparde@broadcom.com>\nReviewed-by: Michael Baucom <michael.baucom@broadcom.com>\nReviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>\nReviewed-by: Randy Schacher <stuart.schacher@broadcom.com>\n---\n drivers/net/bnxt/bnxt.h                       |   6 +\n drivers/net/bnxt/bnxt_ethdev.c                |  86 +++++++\n drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |   5 +\n drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |   1 +\n drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c       |   2 +\n drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c          |  25 +-\n drivers/net/bnxt/tf_ulp/ulp_flow_db.c         |  95 +++++---\n drivers/net/bnxt/tf_ulp/ulp_flow_db.h         |   5 +-\n drivers/net/bnxt/tf_ulp/ulp_mapper.c          |  52 +++-\n drivers/net/bnxt/tf_ulp/ulp_port_db.c         |  37 +++\n drivers/net/bnxt/tf_ulp/ulp_port_db.h         |  15 ++\n drivers/net/bnxt/tf_ulp/ulp_rte_parser.c      | 114 +++++++--\n drivers/net/bnxt/tf_ulp/ulp_rte_parser.h      |   8 +\n .../net/bnxt/tf_ulp/ulp_template_db_enum.h    |  59 +++--\n .../tf_ulp/ulp_template_db_stingray_class.c   |   4 +-\n .../tf_ulp/ulp_template_db_wh_plus_class.c    |  48 ++--\n drivers/net/bnxt/tf_ulp/ulp_template_struct.h |   3 +-\n drivers/net/bnxt/tf_ulp/ulp_tun.c             | 227 +++++++++++++-----\n drivers/net/bnxt/tf_ulp/ulp_tun.h             |  44 ++--\n 19 files changed, 637 insertions(+), 199 deletions(-)",
    "diff": "diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h\nindex d3ab57ab8d..246f51fddf 100644\n--- a/drivers/net/bnxt/bnxt.h\n+++ b/drivers/net/bnxt/bnxt.h\n@@ -668,8 +668,11 @@ struct bnxt {\n \tuint32_t\t\t\tflags2;\n #define BNXT_FLAGS2_PTP_TIMESYNC_ENABLED\tBIT(0)\n #define BNXT_FLAGS2_PTP_ALARM_SCHEDULED\t\tBIT(1)\n+#define\tBNXT_FLAGS2_ACCUM_STATS_EN\t\tBIT(2)\n #define BNXT_P5_PTP_TIMESYNC_ENABLED(bp)\t\\\n \t((bp)->flags2 & BNXT_FLAGS2_PTP_TIMESYNC_ENABLED)\n+#define\tBNXT_ACCUM_STATS_EN(bp)\t\t\t\\\n+\t((bp)->flags2 & BNXT_FLAGS2_ACCUM_STATS_EN)\n \n \tuint16_t\t\tchip_num;\n #define CHIP_NUM_58818\t\t0xd818\n@@ -981,7 +984,10 @@ int32_t\n bnxt_ulp_create_vfr_default_rules(struct rte_eth_dev *vfr_ethdev);\n int32_t\n bnxt_ulp_delete_vfr_default_rules(struct bnxt_representor *vfr);\n+void bnxt_get_iface_mac(uint16_t port, enum bnxt_ulp_intf_type type,\n+\t\t\tuint8_t *mac, uint8_t *parent_mac);\n uint16_t bnxt_get_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type);\n+uint16_t bnxt_get_parent_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type);\n struct bnxt *bnxt_get_bp(uint16_t port);\n uint16_t bnxt_get_svif(uint16_t port_id, bool func_svif,\n \t\t       enum bnxt_ulp_intf_type type);\ndiff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c\nindex ebb326b0d1..1c0eeb76b7 100644\n--- a/drivers/net/bnxt/bnxt_ethdev.c\n+++ b/drivers/net/bnxt/bnxt_ethdev.c\n@@ -87,6 +87,7 @@ static const struct rte_pci_id bnxt_pci_id_map[] = {\n \t{ .vendor_id = 0, /* sentinel */ },\n };\n \n+#define\tBNXT_DEVARG_ACCUM_STATS\t\"accum-stats\"\n #define BNXT_DEVARG_FLOW_XSTAT\t\"flow-xstat\"\n #define BNXT_DEVARG_MAX_NUM_KFLOWS  \"max-num-kflows\"\n #define BNXT_DEVARG_REPRESENTOR\t\"representor\"\n@@ -99,6 +100,7 @@ static const struct rte_pci_id bnxt_pci_id_map[] = {\n \n static const char *const bnxt_dev_args[] = {\n \tBNXT_DEVARG_REPRESENTOR,\n+\tBNXT_DEVARG_ACCUM_STATS,\n \tBNXT_DEVARG_FLOW_XSTAT,\n \tBNXT_DEVARG_MAX_NUM_KFLOWS,\n \tBNXT_DEVARG_REP_BASED_PF,\n@@ -110,6 +112,12 @@ static const char *const bnxt_dev_args[] = {\n \tNULL\n };\n \n+/*\n+ * accum-stats == false to disable flow counter accumulation\n+ * accum-stats == true to enable flow counter accumulation\n+ */\n+#define\tBNXT_DEVARG_ACCUM_STATS_INVALID(accum_stats)\t((accum_stats) > 1)\n+\n /*\n  * flow_xstat == false to disable the feature\n  * flow_xstat == true to enable the feature\n@@ -4837,6 +4845,39 @@ bnxt_get_svif(uint16_t port_id, bool func_svif,\n \treturn func_svif ? bp->func_svif : bp->port_svif;\n }\n \n+void\n+bnxt_get_iface_mac(uint16_t port, enum bnxt_ulp_intf_type type,\n+\t\t   uint8_t *mac, uint8_t *parent_mac)\n+{\n+\tstruct rte_eth_dev *eth_dev;\n+\tstruct bnxt *bp;\n+\n+\tif (type != BNXT_ULP_INTF_TYPE_TRUSTED_VF &&\n+\t    type != BNXT_ULP_INTF_TYPE_PF)\n+\t\treturn;\n+\n+\teth_dev = &rte_eth_devices[port];\n+\tbp = eth_dev->data->dev_private;\n+\tmemcpy(mac, bp->mac_addr, RTE_ETHER_ADDR_LEN);\n+\n+\tif (type == BNXT_ULP_INTF_TYPE_TRUSTED_VF)\n+\t\tmemcpy(parent_mac, bp->parent->mac_addr, RTE_ETHER_ADDR_LEN);\n+}\n+\n+uint16_t\n+bnxt_get_parent_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type)\n+{\n+\tstruct rte_eth_dev *eth_dev;\n+\tstruct bnxt *bp;\n+\n+\tif (type != BNXT_ULP_INTF_TYPE_TRUSTED_VF)\n+\t\treturn 0;\n+\n+\teth_dev = &rte_eth_devices[port];\n+\tbp = eth_dev->data->dev_private;\n+\n+\treturn bp->parent->vnic;\n+}\n uint16_t\n bnxt_get_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type)\n {\n@@ -5200,6 +5241,45 @@ static int bnxt_init_resources(struct bnxt *bp, bool reconfig_dev)\n \treturn 0;\n }\n \n+static int\n+bnxt_parse_devarg_accum_stats(__rte_unused const char *key,\n+\t\t\t      const char *value, void *opaque_arg)\n+{\n+\tstruct bnxt *bp = opaque_arg;\n+\tunsigned long accum_stats;\n+\tchar *end = NULL;\n+\n+\tif (!value || !opaque_arg) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Invalid parameter passed to accum-stats devargs.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\taccum_stats = strtoul(value, &end, 10);\n+\tif (end == NULL || *end != '\\0' ||\n+\t    (accum_stats == ULONG_MAX && errno == ERANGE)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Invalid parameter passed to accum-stats devargs.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (BNXT_DEVARG_ACCUM_STATS_INVALID(accum_stats)) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Invalid value passed to accum-stats devargs.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (accum_stats) {\n+\t\tbp->flags2 |= BNXT_FLAGS2_ACCUM_STATS_EN;\n+\t\tPMD_DRV_LOG(INFO, \"Host-based accum-stats feature enabled.\\n\");\n+\t} else {\n+\t\tbp->flags2 &= ~BNXT_FLAGS2_ACCUM_STATS_EN;\n+\t\tPMD_DRV_LOG(INFO, \"Host-based accum-stats feature disabled.\\n\");\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int\n bnxt_parse_devarg_flow_xstat(__rte_unused const char *key,\n \t\t\t     const char *value, void *opaque_arg)\n@@ -5516,6 +5596,12 @@ bnxt_parse_dev_args(struct bnxt *bp, struct rte_devargs *devargs)\n \tif (ret)\n \t\tgoto err;\n \n+\t/*\n+\t * Handler for \"accum-stats\" devarg.\n+\t * Invoked as for ex: \"-a 0000:00:0d.0,accum-stats=1\"\n+\t */\n+\trte_kvargs_process(kvlist, BNXT_DEVARG_ACCUM_STATS,\n+\t\t\t   bnxt_parse_devarg_accum_stats, bp);\n \t/*\n \t * Handler for \"max_num_kflows\" devarg.\n \t * Invoked as for ex: \"-a 000:00:0d.0,max_num_kflows=32\"\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c\nindex 458c37b4e9..d68cc889c6 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c\n@@ -287,6 +287,7 @@ ulp_ctx_session_open(struct bnxt *bp,\n \t\treturn rc;\n \t}\n \n+\tparams.bp = bp;\n \trc = tf_open_session(&bp->tfp, &params);\n \tif (rc) {\n \t\tBNXT_TF_DBG(ERR, \"Failed to open TF session - %s, rc = %d\\n\",\n@@ -1071,6 +1072,10 @@ bnxt_ulp_port_init(struct bnxt *bp)\n \t}\n \t/* create the default rules */\n \tbnxt_ulp_create_df_rules(bp);\n+\n+\tif (BNXT_ACCUM_STATS_EN(bp))\n+\t\tbp->ulp_ctx->cfg_data->accum_stats = true;\n+\n \tBNXT_TF_DBG(DEBUG, \"BNXT Port:%d ULP port init\\n\",\n \t\t    bp->eth_dev->data->port_id);\n \treturn rc;\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h\nindex c2e71430ec..47c9c802e2 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h\n@@ -67,6 +67,7 @@ struct bnxt_ulp_data {\n #define\tBNXT_ULP_TUN_ENTRY_INVALID\t-1\n #define\tBNXT_ULP_MAX_TUN_CACHE_ENTRIES\t16\n \tstruct bnxt_tun_cache_entry\ttun_tbl[BNXT_ULP_MAX_TUN_CACHE_ENTRIES];\n+\tbool\t\t\t\taccum_stats;\n };\n \n struct bnxt_ulp_context {\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c\nindex 0af2f6aaa6..59d75bc496 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c\n@@ -143,6 +143,8 @@ bnxt_ulp_flow_create(struct rte_eth_dev *dev,\n \t/* copy the device port id and direction for further processing */\n \tULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_INCOMING_IF,\n \t\t\t    dev->data->port_id);\n+\tULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_DEV_PORT_ID,\n+\t\t\t    dev->data->port_id);\n \tULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_SVIF_FLAG,\n \t\t\t    BNXT_ULP_INVALID_SVIF_VAL);\n \ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c\nindex 054a76b5ee..65029139e6 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c\n@@ -1,5 +1,5 @@\n /* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright(c) 2014-2020 Broadcom\n+ * Copyright(c) 2014-2021 Broadcom\n  * All rights reserved.\n  */\n \n@@ -317,8 +317,18 @@ static int ulp_get_single_flow_stat(struct bnxt_ulp_context *ctxt,\n \t/* TBD - Get PKT/BYTE COUNT SHIFT/MASK from Template */\n \tsw_cntr_indx = hw_cntr_id - fc_info->shadow_hw_tbl[dir].start_idx;\n \tsw_acc_tbl_entry = &fc_info->sw_acc_tbl[dir][sw_cntr_indx];\n-\tsw_acc_tbl_entry->pkt_count = FLOW_CNTR_PKTS(stats, dparms);\n-\tsw_acc_tbl_entry->byte_count = FLOW_CNTR_BYTES(stats, dparms);\n+\t/* Some dpdk applications may accumulate the flow counters while some\n+\t * may not. In cases where the application is accumulating the counters\n+\t * the PMD need not do the accumulation itself and viceversa to report\n+\t * the correct flow counters.\n+\t */\n+\tif (ctxt->cfg_data->accum_stats) {\n+\t\tsw_acc_tbl_entry->pkt_count += FLOW_CNTR_PKTS(stats, dparms);\n+\t\tsw_acc_tbl_entry->byte_count += FLOW_CNTR_BYTES(stats, dparms);\n+\t} else {\n+\t\tsw_acc_tbl_entry->pkt_count = FLOW_CNTR_PKTS(stats, dparms);\n+\t\tsw_acc_tbl_entry->byte_count = FLOW_CNTR_BYTES(stats, dparms);\n+\t}\n \n \t/* Update the parent counters if it is child flow */\n \tif (sw_acc_tbl_entry->parent_flow_id) {\n@@ -628,11 +638,10 @@ int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,\n \t\tpthread_mutex_unlock(&ulp_fc_info->fc_lock);\n \t} else if (params.resource_sub_type ==\n \t\t\tBNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT_ACC) {\n-\t\t/* Get the stats from the parent child table */\n-\t\tulp_flow_db_parent_flow_count_get(ctxt,\n-\t\t\t\t\t\t  flow_id,\n-\t\t\t\t\t\t  &count->hits,\n-\t\t\t\t\t\t  &count->bytes);\n+\t\t/* Get stats from the parent child table */\n+\t\tulp_flow_db_parent_flow_count_get(ctxt, flow_id,\n+\t\t\t\t\t\t  &count->hits, &count->bytes,\n+\t\t\t\t\t\t  count->reset);\n \t\tcount->hits_set = 1;\n \t\tcount->bytes_set = 1;\n \t} else {\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c\nindex 1326f79ff5..47c8c48456 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c\n@@ -48,17 +48,21 @@ ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db,\n \tuint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;\n \n \tif (flag) {\n-\t\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)\n+\t\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==\n+\t\t    BNXT_ULP_FDB_TYPE_RID)\n \t\t\tULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx],\n \t\t\t\t\t     idx);\n-\t\telse\n+\t\tif (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==\n+\t\t    BNXT_ULP_FDB_TYPE_RID)\n \t\t\tULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx],\n \t\t\t\t\t     idx);\n \t} else {\n-\t\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)\n+\t\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==\n+\t\t    BNXT_ULP_FDB_TYPE_RID)\n \t\t\tULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx],\n \t\t\t\t\t       idx);\n-\t\telse\n+\t\tif (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==\n+\t\t    BNXT_ULP_FDB_TYPE_RID)\n \t\t\tULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx],\n \t\t\t\t\t       idx);\n \t}\n@@ -81,13 +85,21 @@ ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db,\n {\n \tstruct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;\n \tuint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;\n-\n-\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)\n-\t\treturn ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx],\n-\t\t\t\t\t    idx);\n-\telse\n-\t\treturn ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx],\n-\t\t\t\t\t    idx);\n+\tuint32_t reg, dflt;\n+\n+\treg = ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx], idx);\n+\tdflt = ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx], idx);\n+\n+\tswitch (flow_type) {\n+\tcase BNXT_ULP_FDB_TYPE_REGULAR:\n+\t\treturn (reg && !dflt);\n+\tcase BNXT_ULP_FDB_TYPE_DEFAULT:\n+\t\treturn (!reg && dflt);\n+\tcase BNXT_ULP_FDB_TYPE_RID:\n+\t\treturn (reg && dflt);\n+\tdefault:\n+\t\treturn 0;\n+\t}\n }\n \n static inline enum tf_dir\n@@ -140,8 +152,7 @@ ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,\n \t}\n \n \t/* Store the handle as 64bit only for EM table entries */\n-\tif (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE &&\n-\t    params->resource_func != BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {\n+\tif (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {\n \t\tresource_info->resource_hndl = (uint32_t)params->resource_hndl;\n \t\tresource_info->resource_type = params->resource_type;\n \t\tresource_info->resource_sub_type = params->resource_sub_type;\n@@ -170,8 +181,7 @@ ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,\n \tparams->direction = ulp_flow_db_resource_dir_get(resource_info);\n \tparams->resource_func = ulp_flow_db_resource_func_get(resource_info);\n \n-\tif (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||\n-\t    params->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {\n+\tif (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {\n \t\tparams->resource_hndl = resource_info->resource_em_handle;\n \t} else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {\n \t\tparams->resource_hndl = resource_info->resource_hndl;\n@@ -213,7 +223,7 @@ ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db)\n \t\treturn -ENOMEM;\n \t}\n \tsize = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;\n-\tsize =  ULP_BYTE_ROUND_OFF_8(size);\n+\tsize = ULP_BYTE_ROUND_OFF_8(size);\n \tflow_tbl->active_reg_flows = rte_zmalloc(\"active reg flows\", size,\n \t\t\t\t\t\t ULP_BUFFER_ALIGN_64_BYTE);\n \tif (!flow_tbl->active_reg_flows) {\n@@ -617,7 +627,7 @@ ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -674,7 +684,7 @@ ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -688,7 +698,7 @@ ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,\n \n \t/* check if the flow is active or not */\n \tif (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {\n-\t\tBNXT_TF_DBG(ERR, \"flow does not exist\\n\");\n+\t\tBNXT_TF_DBG(ERR, \"flow does not exist %x:%x\\n\", flow_type, fid);\n \t\treturn -EINVAL;\n \t}\n \n@@ -769,7 +779,7 @@ ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -783,7 +793,7 @@ ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,\n \n \t/* check if the flow is active or not */\n \tif (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {\n-\t\tBNXT_TF_DBG(ERR, \"flow does not exist\\n\");\n+\t\tBNXT_TF_DBG(ERR, \"flow does not exist %x:%x\\n\", flow_type, fid);\n \t\treturn -EINVAL;\n \t}\n \n@@ -868,8 +878,9 @@ ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,\n \t\t     enum bnxt_ulp_fdb_type flow_type,\n \t\t     uint32_t fid)\n {\n-\tstruct bnxt_ulp_flow_db *flow_db;\n+\tstruct bnxt_tun_cache_entry *tun_tbl;\n \tstruct bnxt_ulp_flow_tbl *flow_tbl;\n+\tstruct bnxt_ulp_flow_db *flow_db;\n \n \tflow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);\n \tif (!flow_db) {\n@@ -877,7 +888,7 @@ ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -892,7 +903,7 @@ ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,\n \n \t/* check if the flow is active or not */\n \tif (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {\n-\t\tBNXT_TF_DBG(ERR, \"flow does not exist\\n\");\n+\t\tBNXT_TF_DBG(ERR, \"flow does not exist %x:%x\\n\", flow_type, fid);\n \t\treturn -EINVAL;\n \t}\n \tflow_tbl->head_index--;\n@@ -900,6 +911,7 @@ ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,\n \t\tBNXT_TF_DBG(ERR, \"FlowDB: Head Ptr is zero\\n\");\n \t\treturn -ENOENT;\n \t}\n+\n \tflow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;\n \n \t/* Clear the flows bitmap */\n@@ -908,12 +920,18 @@ ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,\n \tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)\n \t\tulp_flow_db_func_id_set(flow_db, fid, 0);\n \n+\ttun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);\n+\tif (!tun_tbl)\n+\t\treturn -EINVAL;\n+\n+\tulp_clear_tun_inner_entry(tun_tbl, fid);\n+\n \t/* all good, return success */\n \treturn 0;\n }\n \n /*\n- * Get the flow database entry details\n+ *Get the flow database entry details\n  *\n  * ulp_ctxt [in] Ptr to ulp_context\n  * flow_type [in] - specify default or regular\n@@ -940,7 +958,7 @@ ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -996,10 +1014,14 @@ ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,\n \tuint64_t *active_flows;\n \tstruct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;\n \n-\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)\n+\tif (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) {\n \t\tactive_flows = flowtbl->active_reg_flows;\n-\telse\n+\t} else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) {\n \t\tactive_flows = flowtbl->active_dflt_flows;\n+\t} else {\n+\t\tBNXT_TF_DBG(ERR, \"Invalid flow type %x\\n\", flow_type);\n+\t\t\treturn -EINVAL;\n+\t}\n \n \tdo {\n \t\t/* increment the flow id to find the next valid flow id */\n@@ -1192,7 +1214,7 @@ ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -1224,9 +1246,7 @@ ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,\n \t\t\t\t}\n \n \t\t\t} else if (resource_func ==\n-\t\t\t\t   BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||\n-\t\t\t\t   resource_func ==\n-\t\t\t\t   BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {\n+\t\t\t\t   BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {\n \t\t\t\tulp_flow_db_res_info_to_params(fid_res,\n \t\t\t\t\t\t\t       params);\n \t\t\t\treturn 0;\n@@ -1594,7 +1614,7 @@ ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {\n+\tif (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid flow type\\n\");\n \t\treturn -EINVAL;\n \t}\n@@ -1812,9 +1832,8 @@ ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,\n  */\n int32_t\n ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,\n-\t\t\t\t  uint32_t parent_fid,\n-\t\t\t\t  uint64_t *packet_count,\n-\t\t\t\t  uint64_t *byte_count)\n+\t\t\t\t  uint32_t parent_fid, uint64_t *packet_count,\n+\t\t\t\t  uint64_t *byte_count, uint8_t count_reset)\n {\n \tstruct bnxt_ulp_flow_db *flow_db;\n \tstruct ulp_fdb_parent_child_db *p_pdb;\n@@ -1835,6 +1854,10 @@ ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,\n \t\t\t\t\tp_pdb->parent_flow_tbl[idx].pkt_count;\n \t\t\t\t*byte_count =\n \t\t\t\t\tp_pdb->parent_flow_tbl[idx].byte_count;\n+\t\t\t\tif (count_reset) {\n+\t\t\t\t\tp_pdb->parent_flow_tbl[idx].pkt_count = 0;\n+\t\t\t\t\tp_pdb->parent_flow_tbl[idx].byte_count = 0;\n+\t\t\t\t}\n \t\t\t}\n \t\t\treturn 0;\n \t\t}\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h\nindex f7dfd67bed..62c914833b 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h\n@@ -1,5 +1,5 @@\n /* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright(c) 2014-2019 Broadcom\n+ * Copyright(c) 2014-2021 Broadcom\n  * All rights reserved.\n  */\n \n@@ -390,7 +390,8 @@ int32_t\n ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,\n \t\t\t\t  uint32_t parent_fid,\n \t\t\t\t  uint64_t *packet_count,\n-\t\t\t\t  uint64_t *byte_count);\n+\t\t\t\t  uint64_t *byte_count,\n+\t\t\t\t  uint8_t count_reset);\n \n /*\n  * reset the parent accumulation counters\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c\nindex bd28556a4b..27c7c871b1 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c\n@@ -18,6 +18,7 @@\n #include \"ulp_flow_db.h\"\n #include \"tf_util.h\"\n #include \"ulp_template_db_tbl.h\"\n+#include \"ulp_port_db.h\"\n \n static uint8_t mapper_fld_ones[16] = {\n \t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n@@ -450,10 +451,6 @@ ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,\n \tint32_t rc;\n \n \tfparms.dir\t\t= res->direction;\n-\tif (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE)\n-\t\tfparms.mem = TF_MEM_EXTERNAL;\n-\telse\n-\t\tfparms.mem = TF_MEM_INTERNAL;\n \tfparms.flow_handle\t= res->resource_hndl;\n \n \trc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);\n@@ -883,6 +880,30 @@ ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,\n \treturn rc;\n }\n \n+static int32_t\n+ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,\n+\t\t\t\t struct bnxt_ulp_mapper_field_info *fld,\n+\t\t\t\t uint32_t port_id,\n+\t\t\t\t uint16_t val16,\n+\t\t\t\t uint8_t **val)\n+{\n+\tenum bnxt_ulp_port_table port_data = val16;\n+\n+\tswitch (port_data) {\n+\tcase BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:\n+\t\tif (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,\n+\t\t\t\t\t\t    val)) {\n+\t\t\tBNXT_TF_DBG(ERR, \"Invalid port id %u\\n\", port_id);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tBNXT_TF_DBG(ERR, \"Invalid port_data %s\\n\", fld->description);\n+\t\treturn -EINVAL;\n+\t}\n+\treturn 0;\n+}\n+\n static int32_t\n ulp_mapper_field_process_inc_dec(struct bnxt_ulp_mapper_field_info *fld,\n \t\t\t\t struct ulp_blob *blob,\n@@ -938,6 +959,7 @@ ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms,\n \tuint16_t const_val = 0;\n \tuint32_t update_flag = 0;\n \tuint64_t src1_val64;\n+\tuint32_t port_id;\n \n \t/* process the field opcode */\n \tif (fld->field_opc != BNXT_ULP_FIELD_OPC_COND_OP) {\n@@ -1081,6 +1103,20 @@ ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms,\n \t\t\t\t\t    name);\n \t\t\t\treturn -EINVAL;\n \t\t\t}\n+\t\t} else if (fld->field_opc == BNXT_ULP_FIELD_OPC_PORT_TABLE) {\n+\t\t\tport_id = ULP_COMP_FLD_IDX_RD(parms, idx);\n+\t\t\tif (ulp_mapper_field_port_db_process(parms, fld,\n+\t\t\t\t\t\t\t     port_id, const_val,\n+\t\t\t\t\t\t\t     &val)) {\n+\t\t\t\tBNXT_TF_DBG(ERR, \"%s field port table failed\\n\",\n+\t\t\t\t\t    name);\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tif (!ulp_blob_push(blob, val, bitlen)) {\n+\t\t\t\tBNXT_TF_DBG(ERR, \"%s push to blob failed\\n\",\n+\t\t\t\t\t    name);\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n \t\t} else {\n \t\t\tsrc1_val64 = ULP_COMP_FLD_IDX_RD(parms, idx);\n \t\t\tif (ulp_mapper_field_process_inc_dec(fld, blob,\n@@ -1951,7 +1987,7 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,\n \t\treturn rc;\n \t}\n \t/* do the transpose for the internal EM keys */\n-\tif (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)\n+\tif (tbl->resource_type == TF_MEM_INTERNAL)\n \t\tulp_blob_perform_byte_reverse(&key);\n \n \trc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,\n@@ -3021,8 +3057,7 @@ ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)\n \t\tcase BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:\n \t\t\trc = ulp_mapper_tcam_tbl_process(parms, tbl);\n \t\t\tbreak;\n-\t\tcase BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:\n-\t\tcase BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:\n+\t\tcase BNXT_ULP_RESOURCE_FUNC_EM_TABLE:\n \t\t\trc = ulp_mapper_em_tbl_process(parms, tbl);\n \t\t\tbreak;\n \t\tcase BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:\n@@ -3101,8 +3136,7 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,\n \tcase BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:\n \t\trc = ulp_mapper_tcam_entry_free(ulp, tfp, res);\n \t\tbreak;\n-\tcase BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:\n-\tcase BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:\n+\tcase BNXT_ULP_RESOURCE_FUNC_EM_TABLE:\n \t\trc = ulp_mapper_em_entry_free(ulp, tfp, res);\n \t\tbreak;\n \tcase BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_port_db.c b/drivers/net/bnxt/tf_ulp/ulp_port_db.c\nindex 94075784d8..2ee79ea3fe 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_port_db.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_port_db.c\n@@ -182,6 +182,13 @@ int32_t\tulp_port_db_dev_port_intf_update(struct bnxt_ulp_context *ulp_ctxt,\n \t\tfunc->ifindex = ifindex;\n \t}\n \n+\t/* When there is no match, the default action is to send the packet to\n+\t * the kernel. And to send it to the kernel, we need the PF's vnic id.\n+\t */\n+\tfunc->func_parent_vnic = bnxt_get_parent_vnic_id(port_id, intf->type);\n+\tbnxt_get_iface_mac(port_id, intf->type, func->func_mac,\n+\t\t\t   func->func_parent_mac);\n+\n \tport_data = &port_db->phy_port_list[func->phy_port_id];\n \tif (!port_data->port_valid) {\n \t\tport_data->port_svif =\n@@ -579,3 +586,33 @@ ulp_port_db_port_func_id_get(struct bnxt_ulp_context *ulp_ctxt,\n \t}\n \treturn 0;\n }\n+\n+/*\n+ * Api to get the parent mac address for a given port id.\n+ *\n+ * ulp_ctxt [in] Ptr to ulp context\n+ * port_id [in].device port id\n+ * mac_addr [out] mac address\n+ *\n+ * Returns 0 on success or negative number on failure.\n+ */\n+int32_t\n+ulp_port_db_parent_mac_addr_get(struct bnxt_ulp_context *ulp_ctxt,\n+\t\t\t\tuint32_t port_id, uint8_t **mac_addr)\n+{\n+\tstruct bnxt_ulp_port_db *port_db;\n+\tuint16_t func_id;\n+\n+\tport_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);\n+\tif (ulp_port_db_port_func_id_get(ulp_ctxt, port_id, &func_id)) {\n+\t\tBNXT_TF_DBG(ERR, \"Invalid port_id %x\\n\", port_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!port_db->ulp_func_id_tbl[func_id].func_valid) {\n+\t\tBNXT_TF_DBG(ERR, \"Invalid func_id %x\\n\", func_id);\n+\t\treturn -ENOENT;\n+\t}\n+\t*mac_addr = port_db->ulp_func_id_tbl[func_id].func_parent_mac;\n+\treturn 0;\n+}\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_port_db.h b/drivers/net/bnxt/tf_ulp/ulp_port_db.h\nindex 7b85987a0c..b10a7ea58c 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_port_db.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_port_db.h\n@@ -46,6 +46,9 @@ struct ulp_func_if_info {\n \tuint16_t\t\tfunc_spif;\n \tuint16_t\t\tfunc_parif;\n \tuint16_t\t\tfunc_vnic;\n+\tuint8_t\t\t\tfunc_mac[RTE_ETHER_ADDR_LEN];\n+\tuint16_t\t\tfunc_parent_vnic;\n+\tuint8_t\t\t\tfunc_parent_mac[RTE_ETHER_ADDR_LEN];\n \tuint16_t\t\tphy_port_id;\n \tuint16_t\t\tifindex;\n };\n@@ -272,4 +275,16 @@ int32_t\n ulp_port_db_port_func_id_get(struct bnxt_ulp_context *ulp_ctxt,\n \t\t\t     uint16_t port_id, uint16_t *func_id);\n \n+/*\n+ * Api to get the parent mac address for a given port id.\n+ *\n+ * ulp_ctxt [in] Ptr to ulp context\n+ * port_id [in].device port id\n+ * mac_addr [out] mac address\n+ *\n+ * Returns 0 on success or negative number on failure.\n+ */\n+int32_t\n+ulp_port_db_parent_mac_addr_get(struct bnxt_ulp_context *ulp_ctxt,\n+\t\t\t\tuint32_t port_id, uint8_t **mac_addr);\n #endif /* _ULP_PORT_DB_H_ */\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c\nindex 5a2249f349..1522328a5d 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c\n@@ -16,6 +16,7 @@\n #include \"ulp_flow_db.h\"\n #include \"ulp_mapper.h\"\n #include \"ulp_tun.h\"\n+#include \"ulp_template_db_tbl.h\"\n \n /* Local defines for the parsing functions */\n #define ULP_VLAN_PRIORITY_SHIFT\t\t13 /* First 3 bits */\n@@ -240,6 +241,11 @@ bnxt_ulp_comp_fld_intf_update(struct ulp_rte_parser_params *params)\n \t\t\t\t\t    BNXT_ULP_CF_IDX_DRV_FUNC_PARIF,\n \t\t\t\t\t    parif);\n \t\t}\n+\t\tif (mtype == BNXT_ULP_INTF_TYPE_PF) {\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_MATCH_PORT_IS_PF,\n+\t\t\t\t\t    1);\n+\t\t}\n \t}\n }\n \n@@ -623,7 +629,7 @@ ulp_rte_l2_proto_type_update(struct ulp_rte_parser_params *param,\n \t}\n }\n \n-/* Internal Function to indentify broadcast or multicast packets */\n+/* Internal Function to identify broadcast or multicast packets */\n static int32_t\n ulp_rte_parser_is_bcmc_addr(const struct rte_ether_addr *eth_addr)\n {\n@@ -740,6 +746,7 @@ ulp_rte_vlan_hdr_handler(const struct rte_flow_item *item,\n \t\tfield = ulp_rte_parser_fld_copy(field,\n \t\t\t\t\t\t&vlan_tag,\n \t\t\t\t\t\tsizeof(vlan_tag));\n+\n \t\tfield = ulp_rte_parser_fld_copy(field,\n \t\t\t\t\t\t&vlan_spec->inner_type,\n \t\t\t\t\t\tsizeof(vlan_spec->inner_type));\n@@ -764,7 +771,7 @@ ulp_rte_vlan_hdr_handler(const struct rte_flow_item *item,\n \t\tvlan_tag = htons(vlan_tag);\n \n \t\t/*\n-\t\t * The priortiy field is ignored since OVS is seting it as\n+\t\t * The priority field is ignored since OVS is setting it as\n \t\t * wild card match and it is not supported. This is a work\n \t\t * around and shall be addressed in the future.\n \t\t */\n@@ -960,7 +967,7 @@ ulp_rte_ipv4_hdr_handler(const struct rte_flow_item *item,\n \t\t\t\t       &ipv4_mask->hdr.version_ihl,\n \t\t\t\t       sizeof(ipv4_mask->hdr.version_ihl));\n \t\t/*\n-\t\t * The tos field is ignored since OVS is seting it as wild card\n+\t\t * The tos field is ignored since OVS is setting it as wild card\n \t\t * match and it is not supported. This is a work around and\n \t\t * shall be addressed in the future.\n \t\t */\n@@ -1008,6 +1015,13 @@ ulp_rte_ipv4_hdr_handler(const struct rte_flow_item *item,\n \t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L3, 1);\n \t}\n \n+\t/* Some of the PMD applications may set the protocol field\n+\t * in the IPv4 spec but don't set the mask. So, consider\n+\t * the mask in the proto value calculation.\n+\t */\n+\tif (ipv4_mask)\n+\t\tproto &= ipv4_mask->hdr.next_proto_id;\n+\n \tif (proto == IPPROTO_GRE)\n \t\tULP_BITMAP_SET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_T_GRE);\n \n@@ -1108,8 +1122,8 @@ ulp_rte_ipv6_hdr_handler(const struct rte_flow_item *item,\n \t\t\t\t       &vtcf_mask,\n \t\t\t\t       size);\n \t\t/*\n-\t\t * The TC and flow lable field are ignored since OVS is seting\n-\t\t * it for match and it is not supported.\n+\t\t * The TC and flow label field are ignored since OVS is\n+\t\t * setting it for match and it is not supported.\n \t\t * This is a work around and\n \t\t * shall be addressed in the future.\n \t\t */\n@@ -1149,6 +1163,13 @@ ulp_rte_ipv6_hdr_handler(const struct rte_flow_item *item,\n \t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L3, 1);\n \t}\n \n+\t/* Some of the PMD applications may set the protocol field\n+\t * in the IPv6 spec but don't set the mask. So, consider\n+\t * the mask in proto value calculation.\n+\t */\n+\tif (ipv6_mask)\n+\t\tproto &= ipv6_mask->hdr.proto;\n+\n \tif (proto == IPPROTO_GRE)\n \t\tULP_BITMAP_SET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_T_GRE);\n \n@@ -1182,7 +1203,7 @@ ulp_rte_udp_hdr_handler(const struct rte_flow_item *item,\n \tstruct ulp_rte_hdr_bitmap *hdr_bitmap = &params->hdr_bitmap;\n \tuint32_t idx = params->field_idx;\n \tuint32_t size;\n-\tuint16_t dport = 0, sport = 0;\n+\tuint16_t dport = 0;\n \tuint32_t cnt;\n \n \tcnt = ULP_COMP_FLD_IDX_RD(params, BNXT_ULP_CF_IDX_L4_HDR_CNT);\n@@ -1200,7 +1221,6 @@ ulp_rte_udp_hdr_handler(const struct rte_flow_item *item,\n \t\tfield = ulp_rte_parser_fld_copy(&params->hdr_field[idx],\n \t\t\t\t\t\t&udp_spec->hdr.src_port,\n \t\t\t\t\t\tsize);\n-\t\tsport = udp_spec->hdr.src_port;\n \t\tsize = sizeof(udp_spec->hdr.dst_port);\n \t\tfield = ulp_rte_parser_fld_copy(field,\n \t\t\t\t\t\t&udp_spec->hdr.dst_port,\n@@ -1238,14 +1258,26 @@ ulp_rte_udp_hdr_handler(const struct rte_flow_item *item,\n \t    ULP_BITMAP_ISSET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_O_TCP)) {\n \t\tULP_BITMAP_SET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_I_UDP);\n \t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_I_L4, 1);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_I_L4_SPORT, sport);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_I_L4_DPORT, dport);\n+\t\tif (udp_mask && udp_mask->hdr.src_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_I_L4_FB_SRC_PORT,\n+\t\t\t\t\t    1);\n+\t\tif (udp_mask && udp_mask->hdr.dst_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_I_L4_FB_DST_PORT,\n+\t\t\t\t\t    1);\n \n \t} else {\n \t\tULP_BITMAP_SET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_O_UDP);\n \t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L4, 1);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L4_SPORT, sport);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L4_DPORT, dport);\n+\t\tif (udp_mask && udp_mask->hdr.src_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT,\n+\t\t\t\t\t    1);\n+\t\tif (udp_mask && udp_mask->hdr.dst_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_O_L4_FB_DST_PORT,\n+\t\t\t\t\t    1);\n \n \t\t/* Update the field protocol hdr bitmap */\n \t\tulp_rte_l4_proto_type_update(params, dport);\n@@ -1264,7 +1296,6 @@ ulp_rte_tcp_hdr_handler(const struct rte_flow_item *item,\n \tstruct ulp_rte_hdr_field *field;\n \tstruct ulp_rte_hdr_bitmap *hdr_bitmap = &params->hdr_bitmap;\n \tuint32_t idx = params->field_idx;\n-\tuint16_t dport = 0, sport = 0;\n \tuint32_t size;\n \tuint32_t cnt;\n \n@@ -1279,12 +1310,10 @@ ulp_rte_tcp_hdr_handler(const struct rte_flow_item *item,\n \t * header fields\n \t */\n \tif (tcp_spec) {\n-\t\tsport = tcp_spec->hdr.src_port;\n \t\tsize = sizeof(tcp_spec->hdr.src_port);\n \t\tfield = ulp_rte_parser_fld_copy(&params->hdr_field[idx],\n \t\t\t\t\t\t&tcp_spec->hdr.src_port,\n \t\t\t\t\t\tsize);\n-\t\tdport = tcp_spec->hdr.dst_port;\n \t\tsize = sizeof(tcp_spec->hdr.dst_port);\n \t\tfield = ulp_rte_parser_fld_copy(field,\n \t\t\t\t\t\t&tcp_spec->hdr.dst_port,\n@@ -1358,13 +1387,25 @@ ulp_rte_tcp_hdr_handler(const struct rte_flow_item *item,\n \t    ULP_BITMAP_ISSET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_O_TCP)) {\n \t\tULP_BITMAP_SET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_I_TCP);\n \t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_I_L4, 1);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_I_L4_SPORT, sport);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_I_L4_DPORT, dport);\n+\t\tif (tcp_mask && tcp_mask->hdr.src_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_I_L4_FB_SRC_PORT,\n+\t\t\t\t\t    1);\n+\t\tif (tcp_mask && tcp_mask->hdr.dst_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_I_L4_FB_DST_PORT,\n+\t\t\t\t\t    1);\n \t} else {\n \t\tULP_BITMAP_SET(hdr_bitmap->bits, BNXT_ULP_HDR_BIT_O_TCP);\n \t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L4, 1);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L4_SPORT, sport);\n-\t\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_O_L4_DPORT, dport);\n+\t\tif (tcp_mask && tcp_mask->hdr.src_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT,\n+\t\t\t\t\t    1);\n+\t\tif (tcp_mask && tcp_mask->hdr.dst_port)\n+\t\t\tULP_COMP_FLD_IDX_WR(params,\n+\t\t\t\t\t    BNXT_ULP_CF_IDX_O_L4_FB_DST_PORT,\n+\t\t\t\t\t    1);\n \t}\n \tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L4_HDR_CNT, ++cnt);\n \treturn BNXT_TF_RC_SUCCESS;\n@@ -2257,3 +2298,40 @@ ulp_rte_jump_act_handler(const struct rte_flow_action *action_item __rte_unused,\n \tULP_BITMAP_SET(params->act_bitmap.bits, BNXT_ULP_ACT_BIT_JUMP);\n \treturn BNXT_TF_RC_SUCCESS;\n }\n+\n+int32_t\n+ulp_rte_sample_act_handler(const struct rte_flow_action *action_item,\n+\t\t\t   struct ulp_rte_parser_params *params)\n+{\n+\tconst struct rte_flow_action_sample *sample;\n+\tint ret;\n+\n+\tsample = action_item->conf;\n+\n+\t/* if SAMPLE bit is set it means this sample action is nested within the\n+\t * actions of another sample action; this is not allowed\n+\t */\n+\tif (ULP_BITMAP_ISSET(params->act_bitmap.bits,\n+\t\t\t     BNXT_ULP_ACT_BIT_SAMPLE))\n+\t\treturn BNXT_TF_RC_ERROR;\n+\n+\t/* a sample action is only allowed as a shared action */\n+\tif (!ULP_BITMAP_ISSET(params->act_bitmap.bits,\n+\t\t\t      BNXT_ULP_ACT_BIT_SHARED))\n+\t\treturn BNXT_TF_RC_ERROR;\n+\n+\t/* only a ratio of 1 i.e. 100% is supported */\n+\tif (sample->ratio != 1)\n+\t\treturn BNXT_TF_RC_ERROR;\n+\n+\tif (!sample->actions)\n+\t\treturn BNXT_TF_RC_ERROR;\n+\n+\t/* parse the nested actions for a sample action */\n+\tret = bnxt_ulp_rte_parser_act_parse(sample->actions, params);\n+\tif (ret == BNXT_TF_RC_SUCCESS)\n+\t\t/* Update the act_bitmap with sample */\n+\t\tULP_BITMAP_SET(params->act_bitmap.bits, BNXT_ULP_ACT_BIT_SAMPLE);\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h\nindex cb9ae02371..48a20e84b1 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h\n@@ -245,4 +245,12 @@ int32_t\n ulp_rte_jump_act_handler(const struct rte_flow_action *action_item,\n \t\t\t struct ulp_rte_parser_params *params);\n \n+int32_t\n+ulp_rte_sample_act_handler(const struct rte_flow_action *action_item,\n+\t\t\t   struct ulp_rte_parser_params *params);\n+\n+int32_t\n+ulp_rte_shared_act_handler(const struct rte_flow_action *action_item,\n+\t\t\t   struct ulp_rte_parser_params *params);\n+\n #endif /* _ULP_RTE_PARSER_H_ */\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h b/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h\nindex 418f6389eb..0223296480 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h\n@@ -145,10 +145,10 @@ enum bnxt_ulp_cf_idx {\n \tBNXT_ULP_CF_IDX_I_L3 = 14,\n \tBNXT_ULP_CF_IDX_O_L4 = 15,\n \tBNXT_ULP_CF_IDX_I_L4 = 16,\n-\tBNXT_ULP_CF_IDX_O_L4_SPORT = 17,\n-\tBNXT_ULP_CF_IDX_O_L4_DPORT = 18,\n-\tBNXT_ULP_CF_IDX_I_L4_SPORT = 19,\n-\tBNXT_ULP_CF_IDX_I_L4_DPORT = 20,\n+\tBNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT = 17,\n+\tBNXT_ULP_CF_IDX_O_L4_FB_DST_PORT = 18,\n+\tBNXT_ULP_CF_IDX_I_L4_FB_SRC_PORT = 19,\n+\tBNXT_ULP_CF_IDX_I_L4_FB_DST_PORT = 20,\n \tBNXT_ULP_CF_IDX_DEV_PORT_ID = 21,\n \tBNXT_ULP_CF_IDX_DRV_FUNC_SVIF = 22,\n \tBNXT_ULP_CF_IDX_DRV_FUNC_SPIF = 23,\n@@ -171,17 +171,18 @@ enum bnxt_ulp_cf_idx {\n \tBNXT_ULP_CF_IDX_ACT_PORT_TYPE = 40,\n \tBNXT_ULP_CF_IDX_MATCH_PORT_TYPE = 41,\n \tBNXT_ULP_CF_IDX_MATCH_PORT_IS_VFREP = 42,\n-\tBNXT_ULP_CF_IDX_VF_TO_VF = 43,\n-\tBNXT_ULP_CF_IDX_L3_HDR_CNT = 44,\n-\tBNXT_ULP_CF_IDX_L4_HDR_CNT = 45,\n-\tBNXT_ULP_CF_IDX_VFR_MODE = 46,\n-\tBNXT_ULP_CF_IDX_L3_TUN = 47,\n-\tBNXT_ULP_CF_IDX_L3_TUN_DECAP = 48,\n-\tBNXT_ULP_CF_IDX_FID = 49,\n-\tBNXT_ULP_CF_IDX_HDR_SIG_ID = 50,\n-\tBNXT_ULP_CF_IDX_FLOW_SIG_ID = 51,\n-\tBNXT_ULP_CF_IDX_WC_MATCH = 52,\n-\tBNXT_ULP_CF_IDX_LAST = 53\n+\tBNXT_ULP_CF_IDX_MATCH_PORT_IS_PF = 43,\n+\tBNXT_ULP_CF_IDX_VF_TO_VF = 44,\n+\tBNXT_ULP_CF_IDX_L3_HDR_CNT = 45,\n+\tBNXT_ULP_CF_IDX_L4_HDR_CNT = 46,\n+\tBNXT_ULP_CF_IDX_VFR_MODE = 47,\n+\tBNXT_ULP_CF_IDX_L3_TUN = 48,\n+\tBNXT_ULP_CF_IDX_L3_TUN_DECAP = 49,\n+\tBNXT_ULP_CF_IDX_FID = 50,\n+\tBNXT_ULP_CF_IDX_HDR_SIG_ID = 51,\n+\tBNXT_ULP_CF_IDX_FLOW_SIG_ID = 52,\n+\tBNXT_ULP_CF_IDX_WC_MATCH = 53,\n+\tBNXT_ULP_CF_IDX_LAST = 54\n };\n \n enum bnxt_ulp_cond_list_opc {\n@@ -266,7 +267,8 @@ enum bnxt_ulp_field_opc {\n \tBNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST = 2,\n \tBNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST = 3,\n \tBNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST = 4,\n-\tBNXT_ULP_FIELD_OPC_LAST = 5\n+\tBNXT_ULP_FIELD_OPC_PORT_TABLE = 5,\n+\tBNXT_ULP_FIELD_OPC_LAST = 6\n };\n \n enum bnxt_ulp_field_src {\n@@ -352,6 +354,27 @@ enum bnxt_ulp_mem_type_opc {\n \tBNXT_ULP_MEM_TYPE_OPC_LAST = 3\n };\n \n+enum bnxt_ulp_port_table {\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC = 0,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC = 1,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_SVIF = 2,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_SPIF = 3,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_PARIF = 4,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_VNIC = 5,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_PHY_PORT = 6,\n+\tBNXT_ULP_PORT_TABLE_DRV_FUNC_MAC = 7,\n+\tBNXT_ULP_PORT_TABLE_VF_FUNC_SVIF = 8,\n+\tBNXT_ULP_PORT_TABLE_VF_FUNC_SPIF = 9,\n+\tBNXT_ULP_PORT_TABLE_VF_FUNC_PARIF = 10,\n+\tBNXT_ULP_PORT_TABLE_VF_FUNC_VNIC = 11,\n+\tBNXT_ULP_PORT_TABLE_VF_FUNC_MAC = 12,\n+\tBNXT_ULP_PORT_TABLE_PHY_PORT_SVIF = 13,\n+\tBNXT_ULP_PORT_TABLE_PHY_PORT_SPIF = 14,\n+\tBNXT_ULP_PORT_TABLE_PHY_PORT_PARIF = 15,\n+\tBNXT_ULP_PORT_TABLE_PHY_PORT_VPORT = 16,\n+\tBNXT_ULP_PORT_TABLE_LAST = 17\n+};\n+\n enum bnxt_ulp_pri_opc {\n \tBNXT_ULP_PRI_OPC_NOT_USED = 0,\n \tBNXT_ULP_PRI_OPC_CONST = 1,\n@@ -427,8 +450,8 @@ enum bnxt_ulp_match_type_bitmask {\n \n enum bnxt_ulp_resource_func {\n \tBNXT_ULP_RESOURCE_FUNC_INVALID = 0x00,\n-\tBNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE = 0x20,\n-\tBNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE = 0x40,\n+\tBNXT_ULP_RESOURCE_FUNC_EM_TABLE = 0x20,\n+\tBNXT_ULP_RESOURCE_FUNC_RSVD1 = 0x40,\n \tBNXT_ULP_RESOURCE_FUNC_RSVD2 = 0x60,\n \tBNXT_ULP_RESOURCE_FUNC_TCAM_TABLE = 0x80,\n \tBNXT_ULP_RESOURCE_FUNC_INDEX_TABLE = 0x81,\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_template_db_stingray_class.c b/drivers/net/bnxt/tf_ulp/ulp_template_db_stingray_class.c\nindex df09de929e..320a89a5d9 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_template_db_stingray_class.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_template_db_stingray_class.c\n@@ -205,7 +205,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_stingray_class_tbl_list[] = {\n \t.encap_num_fields = 0\n \t},\n \t{ /* class_tid: 1, stingray, table: em.int_0 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_INTERNAL,\n \t.direction = TF_DIR_RX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT,\n@@ -228,7 +228,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_stingray_class_tbl_list[] = {\n \t.encap_num_fields = 0\n \t},\n \t{ /* class_tid: 1, stingray, table: eem.ext_0 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_EXTERNAL,\n \t.direction = TF_DIR_RX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT,\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_template_db_wh_plus_class.c b/drivers/net/bnxt/tf_ulp/ulp_template_db_wh_plus_class.c\nindex 5324bd2531..973ba39f82 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_template_db_wh_plus_class.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_template_db_wh_plus_class.c\n@@ -246,7 +246,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 5\n \t},\n \t{ /* class_tid: 1, wh_plus, table: em.ipv4 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_INTERNAL,\n \t.direction = TF_DIR_RX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT,\n@@ -269,7 +269,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 9\n \t},\n \t{ /* class_tid: 1, wh_plus, table: eem.ipv4 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_EXTERNAL,\n \t.direction = TF_DIR_RX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT,\n@@ -292,7 +292,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 9\n \t},\n \t{ /* class_tid: 1, wh_plus, table: em.ipv6 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_INTERNAL,\n \t.direction = TF_DIR_RX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT,\n@@ -315,7 +315,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 9\n \t},\n \t{ /* class_tid: 1, wh_plus, table: eem.ipv6 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_EXTERNAL,\n \t.direction = TF_DIR_RX,\n \t.execute_info = {\n@@ -497,7 +497,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 5\n \t},\n \t{ /* class_tid: 2, wh_plus, table: em.ipv4 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_INTERNAL,\n \t.direction = TF_DIR_TX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT,\n@@ -520,7 +520,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 9\n \t},\n \t{ /* class_tid: 2, wh_plus, table: eem.ipv4 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_EXTERNAL,\n \t.direction = TF_DIR_TX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT,\n@@ -543,7 +543,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 9\n \t},\n \t{ /* class_tid: 2, wh_plus, table: em.ipv6 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_INTERNAL,\n \t.direction = TF_DIR_TX,\n \t.mem_type_opcode = BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT,\n@@ -566,7 +566,7 @@ struct bnxt_ulp_mapper_tbl_info ulp_wh_plus_class_tbl_list[] = {\n \t.result_num_fields = 9\n \t},\n \t{ /* class_tid: 2, wh_plus, table: eem.ipv6 */\n-\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE,\n+\t.resource_func = BNXT_ULP_RESOURCE_FUNC_EM_TABLE,\n \t.resource_type = TF_MEM_EXTERNAL,\n \t.direction = TF_DIR_TX,\n \t.execute_info = {\n@@ -9699,8 +9699,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_SPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_SPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.6\",\n@@ -9709,8 +9709,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_DPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_DPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_DST_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_DST_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.7\",\n@@ -9850,8 +9850,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_SPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_SPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.7\",\n@@ -9860,8 +9860,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_DPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_DPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_DST_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_DST_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.8\",\n@@ -10443,8 +10443,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_SPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_SPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.6\",\n@@ -10453,8 +10453,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_DPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_DPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_DST_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_DST_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.7\",\n@@ -10594,8 +10594,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_SPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_SPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_SRC_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.7\",\n@@ -10604,8 +10604,8 @@ struct bnxt_ulp_mapper_field_info ulp_wh_plus_class_result_field_list[] = {\n \t.field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE,\n \t.field_src1 = BNXT_ULP_FIELD_SRC_CF,\n \t.field_opr1 = {\n-\t\t(BNXT_ULP_CF_IDX_O_L4_DPORT >> 8) & 0xff,\n-\t\tBNXT_ULP_CF_IDX_O_L4_DPORT & 0xff}\n+\t\t(BNXT_ULP_CF_IDX_O_L4_FB_DST_PORT >> 8) & 0xff,\n+\t\tBNXT_ULP_CF_IDX_O_L4_FB_DST_PORT & 0xff}\n \t},\n \t{\n \t.description = \"em_key_mask.8\",\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_template_struct.h b/drivers/net/bnxt/tf_ulp/ulp_template_struct.h\nindex 5150ed2b07..6e2c48e7b6 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_template_struct.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_template_struct.h\n@@ -1,5 +1,5 @@\n /* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright(c) 2014-2019 Broadcom\n+ * Copyright(c) 2014-2021 Broadcom\n  * All rights reserved.\n  */\n \n@@ -63,6 +63,7 @@ struct ulp_rte_act_prop {\n \n /* Structure to be used for passing all the parser functions */\n struct ulp_rte_parser_params {\n+\tSTAILQ_ENTRY(ulp_rte_parser_params)  next;\n \tstruct ulp_rte_hdr_bitmap\thdr_bitmap;\n \tstruct ulp_rte_hdr_bitmap\thdr_fp_bit;\n \tstruct ulp_rte_field_bitmap\tfld_bitmap;\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_tun.c b/drivers/net/bnxt/tf_ulp/ulp_tun.c\nindex dd3d8703fb..a883e0ff08 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_tun.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_tun.c\n@@ -1,8 +1,10 @@\n /* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright(c) 2014-2020 Broadcom\n+ * Copyright(c) 2014-2021 Broadcom\n  * All rights reserved.\n  */\n \n+#include <sys/queue.h>\n+\n #include <rte_malloc.h>\n \n #include \"ulp_tun.h\"\n@@ -48,18 +50,18 @@ ulp_install_outer_tun_flow(struct ulp_rte_parser_params *params,\n \t\tgoto err;\n \n \t/* Store the tunnel dmac in the tunnel cache table and use it while\n-\t * programming tunnel flow F2.\n+\t * programming tunnel inner flow.\n \t */\n \tmemcpy(tun_entry->t_dmac,\n \t       &params->hdr_field[ULP_TUN_O_DMAC_HDR_FIELD_INDEX].spec,\n \t       RTE_ETHER_ADDR_LEN);\n \n-\ttun_entry->valid = true;\n-\ttun_entry->state = BNXT_ULP_FLOW_STATE_TUN_O_OFFLD;\n+\ttun_entry->tun_flow_info[params->port_id].state =\n+\t\t\t\tBNXT_ULP_FLOW_STATE_TUN_O_OFFLD;\n \ttun_entry->outer_tun_flow_id = params->fid;\n \n-\t/* F1 and it's related F2s are correlated based on\n-\t * Tunnel Destination IP Address.\n+\t/* Tunnel outer flow  and it's related inner flows are correlated\n+\t * based on Tunnel Destination IP Address.\n \t */\n \tif (tun_entry->t_dst_ip_valid)\n \t\tgoto done;\n@@ -83,27 +85,32 @@ ulp_install_outer_tun_flow(struct ulp_rte_parser_params *params,\n \n /* This function programs the inner tunnel flow in the hardware. */\n static void\n-ulp_install_inner_tun_flow(struct bnxt_tun_cache_entry *tun_entry)\n+ulp_install_inner_tun_flow(struct bnxt_tun_cache_entry *tun_entry,\n+\t\t\t   struct ulp_rte_parser_params *tun_o_params)\n {\n \tstruct bnxt_ulp_mapper_create_parms mparms = { 0 };\n-\tstruct ulp_rte_parser_params *params;\n+\tstruct ulp_per_port_flow_info *flow_info;\n+\tstruct ulp_rte_parser_params *inner_params;\n \tint ret;\n \n-\t/* F2 doesn't have tunnel dmac, use the tunnel dmac that was\n-\t * stored during F1 programming.\n+\t/* Tunnel inner flow doesn't have tunnel dmac, use the tunnel\n+\t * dmac that was stored during F1 programming.\n \t */\n-\tparams = &tun_entry->first_inner_tun_params;\n-\tmemcpy(&params->hdr_field[ULP_TUN_O_DMAC_HDR_FIELD_INDEX],\n-\t       tun_entry->t_dmac, RTE_ETHER_ADDR_LEN);\n-\tparams->parent_fid = tun_entry->outer_tun_flow_id;\n-\tparams->fid = tun_entry->first_inner_tun_flow_id;\n-\n-\tbnxt_ulp_init_mapper_params(&mparms, params,\n-\t\t\t\t    BNXT_ULP_FDB_TYPE_REGULAR);\n-\n-\tret = ulp_mapper_flow_create(params->ulp_ctx, &mparms);\n-\tif (ret)\n-\t\tPMD_DRV_LOG(ERR, \"Failed to create F2 flow.\");\n+\tflow_info = &tun_entry->tun_flow_info[tun_o_params->port_id];\n+\tSTAILQ_FOREACH(inner_params, &flow_info->tun_i_prms_list, next) {\n+\t\tmemcpy(&inner_params->hdr_field[ULP_TUN_O_DMAC_HDR_FIELD_INDEX],\n+\t\t       tun_entry->t_dmac, RTE_ETHER_ADDR_LEN);\n+\t\tinner_params->parent_fid = tun_entry->outer_tun_flow_id;\n+\n+\t\tbnxt_ulp_init_mapper_params(&mparms, inner_params,\n+\t\t\t\t\t    BNXT_ULP_FDB_TYPE_REGULAR);\n+\n+\t\tret = ulp_mapper_flow_create(inner_params->ulp_ctx, &mparms);\n+\t\tif (ret)\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t    \"Failed to create inner tun flow, FID:%u.\",\n+\t\t\t\t    inner_params->fid);\n+\t}\n }\n \n /* This function either install outer tunnel flow & inner tunnel flow\n@@ -114,30 +121,31 @@ ulp_post_process_outer_tun_flow(struct ulp_rte_parser_params *params,\n \t\t\t     struct bnxt_tun_cache_entry *tun_entry,\n \t\t\t     uint16_t tun_idx)\n {\n-\tenum bnxt_ulp_tun_flow_state flow_state;\n \tint ret;\n \n-\tflow_state = tun_entry->state;\n \tret = ulp_install_outer_tun_flow(params, tun_entry, tun_idx);\n-\tif (ret)\n+\tif (ret == BNXT_TF_RC_ERROR) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to create outer tunnel flow.\");\n \t\treturn ret;\n+\t}\n \n-\t/* If flow_state == BNXT_ULP_FLOW_STATE_NORMAL before installing\n-\t * F1, that means F2 is not deferred. Hence, no need to install F2.\n+\t/* Install any cached tunnel inner flows that came before tunnel\n+\t * outer flow.\n \t */\n-\tif (flow_state != BNXT_ULP_FLOW_STATE_NORMAL)\n-\t\tulp_install_inner_tun_flow(tun_entry);\n+\tulp_install_inner_tun_flow(tun_entry, params);\n \n-\treturn 0;\n+\treturn BNXT_TF_RC_FID;\n }\n \n /* This function will be called if inner tunnel flow request comes before\n  * outer tunnel flow request.\n  */\n static int32_t\n-ulp_post_process_first_inner_tun_flow(struct ulp_rte_parser_params *params,\n+ulp_post_process_cache_inner_tun_flow(struct ulp_rte_parser_params *params,\n \t\t\t\t      struct bnxt_tun_cache_entry *tun_entry)\n {\n+\tstruct ulp_rte_parser_params *inner_tun_params;\n+\tstruct ulp_per_port_flow_info *flow_info;\n \tint ret;\n \n \tret = ulp_matcher_pattern_match(params, &params->class_id);\n@@ -148,18 +156,22 @@ ulp_post_process_first_inner_tun_flow(struct ulp_rte_parser_params *params,\n \tif (ret != BNXT_TF_RC_SUCCESS)\n \t\treturn BNXT_TF_RC_ERROR;\n \n-\t/* If Tunnel F2 flow comes first then we can't install it in the\n-\t * hardware, because, F2 flow will not have L2 context information.\n-\t * So, just cache the F2 information and program it in the context\n-\t * of F1 flow installation.\n+\t/* If Tunnel inner flow comes first then we can't install it in the\n+\t * hardware, because, Tunnel inner flow will not have L2 context\n+\t * information. So, just cache the Tunnel inner flow information\n+\t * and program it in the context of F1 flow installation.\n \t */\n-\tmemcpy(&tun_entry->first_inner_tun_params, params,\n-\t       sizeof(struct ulp_rte_parser_params));\n-\n-\ttun_entry->first_inner_tun_flow_id = params->fid;\n-\ttun_entry->state = BNXT_ULP_FLOW_STATE_TUN_I_CACHED;\n+\tflow_info = &tun_entry->tun_flow_info[params->port_id];\n+\tinner_tun_params = rte_zmalloc(\"ulp_inner_tun_params\",\n+\t\t\t\t       sizeof(struct ulp_rte_parser_params), 0);\n+\tif (!inner_tun_params)\n+\t\treturn BNXT_TF_RC_ERROR;\n+\tmemcpy(inner_tun_params, params, sizeof(struct ulp_rte_parser_params));\n+\tSTAILQ_INSERT_TAIL(&flow_info->tun_i_prms_list, inner_tun_params,\n+\t\t\t   next);\n+\tflow_info->tun_i_cnt++;\n \n-\t/* F1 and it's related F2s are correlated based on\n+\t/* F1 and it's related Tunnel inner flows are correlated based on\n \t * Tunnel Destination IP Address. It could be already set, if\n \t * the inner flow got offloaded first.\n \t */\n@@ -240,8 +252,8 @@ ulp_get_tun_entry(struct ulp_rte_parser_params *params,\n int32_t\n ulp_post_process_tun_flow(struct ulp_rte_parser_params *params)\n {\n-\tbool outer_tun_sig, inner_tun_sig, first_inner_tun_flow;\n-\tbool outer_tun_reject, inner_tun_reject, outer_tun_flow, inner_tun_flow;\n+\tbool inner_tun_sig, cache_inner_tun_flow;\n+\tbool outer_tun_reject, outer_tun_flow, inner_tun_flow;\n \tenum bnxt_ulp_tun_flow_state flow_state;\n \tstruct bnxt_tun_cache_entry *tun_entry;\n \tuint32_t l3_tun, l3_tun_decap;\n@@ -259,40 +271,31 @@ ulp_post_process_tun_flow(struct ulp_rte_parser_params *params)\n \tif (rc == BNXT_TF_RC_ERROR)\n \t\treturn rc;\n \n-\tflow_state = tun_entry->state;\n+\tif (params->port_id >= RTE_MAX_ETHPORTS)\n+\t\treturn BNXT_TF_RC_ERROR;\n+\tflow_state = tun_entry->tun_flow_info[params->port_id].state;\n \t/* Outer tunnel flow validation */\n-\touter_tun_sig = BNXT_OUTER_TUN_SIGNATURE(l3_tun, params);\n-\touter_tun_flow = BNXT_OUTER_TUN_FLOW(outer_tun_sig);\n+\touter_tun_flow = BNXT_OUTER_TUN_FLOW(l3_tun, params);\n \touter_tun_reject = BNXT_REJECT_OUTER_TUN_FLOW(flow_state,\n-\t\t\t\t\t\t      outer_tun_sig);\n+\t\t\t\t\t\t      outer_tun_flow);\n \n \t/* Inner tunnel flow validation */\n \tinner_tun_sig = BNXT_INNER_TUN_SIGNATURE(l3_tun, l3_tun_decap, params);\n-\tfirst_inner_tun_flow = BNXT_FIRST_INNER_TUN_FLOW(flow_state,\n+\tcache_inner_tun_flow = BNXT_CACHE_INNER_TUN_FLOW(flow_state,\n \t\t\t\t\t\t\t inner_tun_sig);\n \tinner_tun_flow = BNXT_INNER_TUN_FLOW(flow_state, inner_tun_sig);\n-\tinner_tun_reject = BNXT_REJECT_INNER_TUN_FLOW(flow_state,\n-\t\t\t\t\t\t      inner_tun_sig);\n \n \tif (outer_tun_reject) {\n \t\ttun_entry->outer_tun_rej_cnt++;\n \t\tBNXT_TF_DBG(ERR,\n \t\t\t    \"Tunnel F1 flow rejected, COUNT: %d\\n\",\n \t\t\t    tun_entry->outer_tun_rej_cnt);\n-\t/* Inner tunnel flow is rejected if it comes between first inner\n-\t * tunnel flow and outer flow requests.\n-\t */\n-\t} else if (inner_tun_reject) {\n-\t\ttun_entry->inner_tun_rej_cnt++;\n-\t\tBNXT_TF_DBG(ERR,\n-\t\t\t    \"Tunnel F2 flow rejected, COUNT: %d\\n\",\n-\t\t\t    tun_entry->inner_tun_rej_cnt);\n \t}\n \n-\tif (outer_tun_reject || inner_tun_reject)\n+\tif (outer_tun_reject)\n \t\treturn BNXT_TF_RC_ERROR;\n-\telse if (first_inner_tun_flow)\n-\t\treturn ulp_post_process_first_inner_tun_flow(params, tun_entry);\n+\telse if (cache_inner_tun_flow)\n+\t\treturn ulp_post_process_cache_inner_tun_flow(params, tun_entry);\n \telse if (outer_tun_flow)\n \t\treturn ulp_post_process_outer_tun_flow(params, tun_entry,\n \t\t\t\t\t\t       tun_idx);\n@@ -302,9 +305,109 @@ ulp_post_process_tun_flow(struct ulp_rte_parser_params *params)\n \t\treturn BNXT_TF_RC_NORMAL;\n }\n \n+void\n+ulp_tun_tbl_init(struct bnxt_tun_cache_entry *tun_tbl)\n+{\n+\tstruct ulp_per_port_flow_info *flow_info;\n+\tint i, j;\n+\n+\tfor (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) {\n+\t\tfor (j = 0; j < RTE_MAX_ETHPORTS; j++) {\n+\t\t\tflow_info = &tun_tbl[i].tun_flow_info[j];\n+\t\t\tSTAILQ_INIT(&flow_info->tun_i_prms_list);\n+\t\t}\n+\t}\n+}\n+\n void\n ulp_clear_tun_entry(struct bnxt_tun_cache_entry *tun_tbl, uint8_t tun_idx)\n {\n+\tstruct ulp_rte_parser_params *inner_params;\n+\tstruct ulp_per_port_flow_info *flow_info;\n+\tint j;\n+\n+\tfor (j = 0; j < RTE_MAX_ETHPORTS; j++) {\n+\t\tflow_info = &tun_tbl[tun_idx].tun_flow_info[j];\n+\t\tSTAILQ_FOREACH(inner_params,\n+\t\t\t       &flow_info->tun_i_prms_list,\n+\t\t\t       next) {\n+\t\t\tSTAILQ_REMOVE(&flow_info->tun_i_prms_list,\n+\t\t\t\t      inner_params,\n+\t\t\t\t      ulp_rte_parser_params, next);\n+\t\t\trte_free(inner_params);\n+\t\t}\n+\t}\n+\n \tmemset(&tun_tbl[tun_idx], 0,\n-\t\tsizeof(struct bnxt_tun_cache_entry));\n+\t\t\tsizeof(struct bnxt_tun_cache_entry));\n+\n+\tfor (j = 0; j < RTE_MAX_ETHPORTS; j++) {\n+\t\tflow_info = &tun_tbl[tun_idx].tun_flow_info[j];\n+\t\tSTAILQ_INIT(&flow_info->tun_i_prms_list);\n+\t}\n+}\n+\n+static bool\n+ulp_chk_and_rem_tun_i_flow(struct bnxt_tun_cache_entry *tun_entry,\n+\t\t\t   struct ulp_per_port_flow_info *flow_info,\n+\t\t\t   uint32_t fid)\n+{\n+\tstruct ulp_rte_parser_params *inner_params;\n+\tint j;\n+\n+\tSTAILQ_FOREACH(inner_params,\n+\t\t       &flow_info->tun_i_prms_list,\n+\t\t       next) {\n+\t\tif (inner_params->fid == fid) {\n+\t\t\tSTAILQ_REMOVE(&flow_info->tun_i_prms_list,\n+\t\t\t\t      inner_params,\n+\t\t\t\t      ulp_rte_parser_params,\n+\t\t\t\t      next);\n+\t\t\trte_free(inner_params);\n+\t\t\tflow_info->tun_i_cnt--;\n+\t\t\t/* When a dpdk application offloads a duplicate\n+\t\t\t * tunnel inner flow on a port that it is not\n+\t\t\t * destined to, there won't be a tunnel outer flow\n+\t\t\t * associated with these duplicate tunnel inner flows.\n+\t\t\t * So, when the last tunnel inner flow ages out, the\n+\t\t\t * driver has to clear the tunnel entry, otherwise\n+\t\t\t * the tunnel entry cannot be reused.\n+\t\t\t */\n+\t\t\tif (!flow_info->tun_i_cnt &&\n+\t\t\t    flow_info->state != BNXT_ULP_FLOW_STATE_TUN_O_OFFLD) {\n+\t\t\t\tmemset(tun_entry, 0,\n+\t\t\t\t       sizeof(struct bnxt_tun_cache_entry));\n+\t\t\t\tfor (j = 0; j < RTE_MAX_ETHPORTS; j++)\n+\t\t\t\t\tSTAILQ_INIT(&flow_info->tun_i_prms_list);\n+\t\t\t}\n+\t\t\treturn true;\n+\t\t}\n+\t}\n+\n+\treturn false;\n+}\n+\n+/* When a dpdk application offloads the same tunnel inner flow\n+ * on all the uplink ports, a tunnel inner flow entry is cached\n+ * even if it is not for the right uplink port. Such tunnel\n+ * inner flows will eventually get aged out as there won't be\n+ * any traffic on these ports. When such a flow destroy is\n+ * called, cleanup the tunnel inner flow entry.\n+ */\n+void\n+ulp_clear_tun_inner_entry(struct bnxt_tun_cache_entry *tun_tbl, uint32_t fid)\n+{\n+\tstruct ulp_per_port_flow_info *flow_info;\n+\tint i, j;\n+\n+\tfor (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) {\n+\t\tif (!tun_tbl[i].t_dst_ip_valid)\n+\t\t\tcontinue;\n+\t\tfor (j = 0; j < RTE_MAX_ETHPORTS; j++) {\n+\t\t\tflow_info = &tun_tbl[i].tun_flow_info[j];\n+\t\t\tif (ulp_chk_and_rem_tun_i_flow(&tun_tbl[i],\n+\t\t\t\t\t\t       flow_info, fid) == true)\n+\t\t\t\treturn;\n+\t\t}\n+\t}\n }\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_tun.h b/drivers/net/bnxt/tf_ulp/ulp_tun.h\nindex 763138218b..2516eaca2c 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_tun.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_tun.h\n@@ -1,5 +1,5 @@\n /* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright(c) 2014-2020 Broadcom\n+ * Copyright(c) 2014-2021 Broadcom\n  * All rights reserved.\n  */\n \n@@ -10,12 +10,17 @@\n #include <stdbool.h>\n #include <sys/queue.h>\n \n+#include \"rte_version.h\"\n #include \"rte_ethdev.h\"\n \n #include \"ulp_template_db_enum.h\"\n #include \"ulp_template_struct.h\"\n \n-#define\tBNXT_OUTER_TUN_SIGNATURE(l3_tun, params)\t\t\\\n+#if RTE_VERSION_NUM(17, 11, 10, 16) == RTE_VERSION\n+#define\tRTE_ETHER_ADDR_LEN\tETHER_ADDR_LEN\n+#endif\n+\n+#define\tBNXT_OUTER_TUN_FLOW(l3_tun, params)\t\t\\\n \t((l3_tun) &&\t\t\t\t\t\\\n \t ULP_BITMAP_ISSET((params)->act_bitmap.bits,\t\\\n \t\t\t  BNXT_ULP_ACT_BIT_JUMP))\n@@ -24,22 +29,16 @@\n \t !ULP_BITMAP_ISSET((params)->hdr_bitmap.bits,\t\t\t\\\n \t\t\t   BNXT_ULP_HDR_BIT_O_ETH))\n \n-#define\tBNXT_FIRST_INNER_TUN_FLOW(state, inner_tun_sig)\t\\\n+#define\tBNXT_CACHE_INNER_TUN_FLOW(state, inner_tun_sig)\t\\\n \t((state) == BNXT_ULP_FLOW_STATE_NORMAL && (inner_tun_sig))\n #define\tBNXT_INNER_TUN_FLOW(state, inner_tun_sig)\t\t\\\n \t((state) == BNXT_ULP_FLOW_STATE_TUN_O_OFFLD && (inner_tun_sig))\n-#define\tBNXT_OUTER_TUN_FLOW(outer_tun_sig)\t\t((outer_tun_sig))\n \n /* It is invalid to get another outer flow offload request\n  * for the same tunnel, while the outer flow is already offloaded.\n  */\n #define\tBNXT_REJECT_OUTER_TUN_FLOW(state, outer_tun_sig)\t\\\n \t((state) == BNXT_ULP_FLOW_STATE_TUN_O_OFFLD && (outer_tun_sig))\n-/* It is invalid to get another inner flow offload request\n- * for the same tunnel, while the outer flow is not yet offloaded.\n- */\n-#define\tBNXT_REJECT_INNER_TUN_FLOW(state, inner_tun_sig)\t\\\n-\t((state) == BNXT_ULP_FLOW_STATE_TUN_I_CACHED && (inner_tun_sig))\n \n #define\tULP_TUN_O_DMAC_HDR_FIELD_INDEX\t1\n #define\tULP_TUN_O_IPV4_DIP_INDEX\t19\n@@ -50,10 +49,10 @@\n  * requests arrive.\n  *\n  * If inner tunnel flow offload request arrives first then the flow\n- * state will change from BNXT_ULP_FLOW_STATE_NORMAL to\n- * BNXT_ULP_FLOW_STATE_TUN_I_CACHED and the following outer tunnel\n- * flow offload request will change the state of the flow to\n- * BNXT_ULP_FLOW_STATE_TUN_O_OFFLD from BNXT_ULP_FLOW_STATE_TUN_I_CACHED.\n+ * state will remain in BNXT_ULP_FLOW_STATE_NORMAL state.\n+ * The following outer tunnel flow offload request will change the\n+ * state of the flow to BNXT_ULP_FLOW_STATE_TUN_O_OFFLD from\n+ * BNXT_ULP_FLOW_STATE_NORMAL.\n  *\n  * If outer tunnel flow offload request arrives first then the flow state\n  * will change from BNXT_ULP_FLOW_STATE_NORMAL to\n@@ -67,12 +66,15 @@\n enum bnxt_ulp_tun_flow_state {\n \tBNXT_ULP_FLOW_STATE_NORMAL = 0,\n \tBNXT_ULP_FLOW_STATE_TUN_O_OFFLD,\n-\tBNXT_ULP_FLOW_STATE_TUN_I_CACHED\n+};\n+\n+struct ulp_per_port_flow_info {\n+\tenum bnxt_ulp_tun_flow_state\t\tstate;\n+\tuint32_t\t\t\t\ttun_i_cnt;\n+\tSTAILQ_HEAD(, ulp_rte_parser_params)\ttun_i_prms_list;\n };\n \n struct bnxt_tun_cache_entry {\n-\tenum bnxt_ulp_tun_flow_state\tstate;\n-\tbool\t\t\t\tvalid;\n \tbool\t\t\t\tt_dst_ip_valid;\n \tuint8_t\t\t\t\tt_dmac[RTE_ETHER_ADDR_LEN];\n \tunion {\n@@ -80,13 +82,17 @@ struct bnxt_tun_cache_entry {\n \t\tuint8_t\t\t\tt_dst_ip6[16];\n \t};\n \tuint32_t\t\t\touter_tun_flow_id;\n-\tuint32_t\t\t\tfirst_inner_tun_flow_id;\n \tuint16_t\t\t\touter_tun_rej_cnt;\n-\tuint16_t\t\t\tinner_tun_rej_cnt;\n-\tstruct ulp_rte_parser_params\tfirst_inner_tun_params;\n+\tstruct ulp_per_port_flow_info\ttun_flow_info[RTE_MAX_ETHPORTS];\n };\n \n+void\n+ulp_tun_tbl_init(struct bnxt_tun_cache_entry *tun_tbl);\n+\n void\n ulp_clear_tun_entry(struct bnxt_tun_cache_entry *tun_tbl, uint8_t tun_idx);\n \n+void\n+ulp_clear_tun_inner_entry(struct bnxt_tun_cache_entry *tun_tbl, uint32_t fid);\n+\n #endif\n",
    "prefixes": [
        "44/58"
    ]
}