get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 81630,
    "url": "http://patches.dpdk.org/api/patches/81630/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201020215538.59242-12-ajit.khaparde@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": "<20201020215538.59242-12-ajit.khaparde@broadcom.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201020215538.59242-12-ajit.khaparde@broadcom.com",
    "date": "2020-10-20T21:55:38",
    "name": "[v2,11/11] net/bnxt: add VXLAN decap offload support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "069580d5b86bd4eb3ae821be13cec565053875fc",
    "submitter": {
        "id": 501,
        "url": "http://patches.dpdk.org/api/people/501/?format=api",
        "name": "Ajit Khaparde",
        "email": "ajit.khaparde@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/20201020215538.59242-12-ajit.khaparde@broadcom.com/mbox/",
    "series": [
        {
            "id": 13155,
            "url": "http://patches.dpdk.org/api/series/13155/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=13155",
            "date": "2020-10-20T21:55:27",
            "name": "bnxt fixes and enhancements to TRUFLOW support",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/13155/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/81630/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/81630/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 dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 51D19A04DD;\n\tTue, 20 Oct 2020 23:59:38 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 62A85ACEF;\n\tTue, 20 Oct 2020 23:56:11 +0200 (CEST)",
            "from mail-pg1-f178.google.com (mail-pg1-f178.google.com\n [209.85.215.178]) by dpdk.org (Postfix) with ESMTP id 6FB6CACBD\n for <dev@dpdk.org>; Tue, 20 Oct 2020 23:56:01 +0200 (CEST)",
            "by mail-pg1-f178.google.com with SMTP id j7so168144pgk.5\n for <dev@dpdk.org>; Tue, 20 Oct 2020 14:56:01 -0700 (PDT)",
            "from localhost.localdomain ([192.19.223.252])\n by smtp.gmail.com with ESMTPSA id e6sm24113pfn.190.2020.10.20.14.55.57\n (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);\n Tue, 20 Oct 2020 14:55:57 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com;\n s=google;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version; bh=u59e1B+40ukz5RIummx+JmiTpHwgmkpXmmYxmQv2Fx8=;\n b=KNZsxxMzrKB91IcfEa5K+20pE+ourzRIVB6fjWpcDgyXw4u+wQwFPyXSUs7GxygjBF\n GoHBaj5NpT1SwDsLPX+z0AwegXnCGlFomclmG56QCduIfnaPsSDZOwWqGLc08N5MPFgd\n hRfuzY+FE4PNmFHtL5N7bU5r3xOzNzJpgFz0I=",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version;\n bh=u59e1B+40ukz5RIummx+JmiTpHwgmkpXmmYxmQv2Fx8=;\n b=S9EPHreo9SJhyLadz/IA0KR7dvMwSNkYXz9tAs++csscJdY3HfwO1lDtqpvNhklC/O\n odTa6v03pheyLYa8ftFQtl4Qp/yPoKMroXGoXQuQrMd+bnZgSPuJqzxpbqCXL/8n9QOv\n DYpw+jVZcETySEPbvyLT8cLcBQUM6AxzUhz9luWW0bGgQQPu3GiP2wncLGW0Srxo1kRo\n LfHxSb8/j/6OAqfoXTtTQIjt53qWxUx7sLxSUJDTWUYQGQusCVFLNFy1j2qu3Ywi1ItM\n cJeqsjC41YWH6DMtQulg3w6J8Y4aVFrD7Xc6iC95LaF3xKbYgKfNd+nUblM8hBuMm/DO\n EW5A==",
        "X-Gm-Message-State": "AOAM530Tf8kH48aiZO10/oh/d7qdwQ2CzMdGMfZhylpoF369yJObTTRn\n rrVgMJ9uGVCQtX2Vx9Bih1Ws/v67+21Q8E8wRjFxRZBO7OTNwLvhBzy932bTTTlCKv7nBe5D8b8\n H/x8F3AdWMCdaaTew/2NLmdTGda5n4p2nXQ31r3EVSn7gXXYI3NlGmtFSweLi4arX/g==",
        "X-Google-Smtp-Source": "\n ABdhPJxHz+bEXAkkewlIRA6qA0rvwqSY0PE1/QK368VdjNAQGj3iq1J2Q17IzY6+3Na6gyolerAoXQ==",
        "X-Received": "by 2002:a63:654:: with SMTP id 81mr298487pgg.27.1603230958466;\n Tue, 20 Oct 2020 14:55:58 -0700 (PDT)",
        "From": "Ajit Khaparde <ajit.khaparde@broadcom.com>",
        "To": "dev@dpdk.org",
        "Cc": "Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>,\n Kishore Padmanabha <kishore.padmanabha@broadcom.com>",
        "Date": "Tue, 20 Oct 2020 14:55:38 -0700",
        "Message-Id": "<20201020215538.59242-12-ajit.khaparde@broadcom.com>",
        "X-Mailer": "git-send-email 2.21.1 (Apple Git-122.3)",
        "In-Reply-To": "<20201020215538.59242-1-ajit.khaparde@broadcom.com>",
        "References": "\n <1602916089-18576-1-git-send-email-venkatkumar.duvvuru@broadcom.com>\n <20201020215538.59242-1-ajit.khaparde@broadcom.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-Content-Filtered-By": "Mailman/MimeDel 2.1.15",
        "Subject": "[dpdk-dev] [PATCH v2 11/11] net/bnxt: add VXLAN decap offload\n\tsupport",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "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: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>\n\nVXLAN decap offload can happen in stages. The offload request may\nnot come as a single flow request rather may come as two flow offload\nrequests F1 & F2. This patch is adding support for this two stage\noffload design. The match criteria for F1 is O_DMAC, O_SMAC,\nO_DST_IP, O_UDP_DPORT and actions are COUNT, MARK, JUMP. The match\ncriteria for F2 is O_SRC_IP, O_DST_IP, VNI and inner header fields.\nF1 and F2 flow offload requests can come in any order. If F2 flow\noffload request comes first then F2 can’t be offloaded as there is\nno O_DMAC information in F2. In this case, F2 will be deferred until\nF1 flow offload request arrives. When F1 flow offload request is\nreceived it will have O_DMAC information. Using F1’s O_DMAC, driver\ncreates an L2 context entry in the hardware as part of offloading F1.\nF2 will now use F1’s O_DMAC to get the L2 context id associated with\nthis O_DMAC and other flow fields that are cached already at the time\nof deferring F2 for offloading. F2s that arrive after F1 is offloaded\nwill be directly programmed and not cached.\n\nSigned-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>\nReviewed-by: Kishore Padmanabha <kishore.padmanabha@broadcom.com>\nReviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>\n---\n doc/guides/nics/bnxt.rst                      |  18 +\n doc/guides/rel_notes/release_20_11.rst        |   1 +\n drivers/net/bnxt/meson.build                  |   1 +\n drivers/net/bnxt/tf_ulp/bnxt_tf_common.h      |   4 +-\n drivers/net/bnxt/tf_ulp/bnxt_ulp.c            |  10 +\n drivers/net/bnxt/tf_ulp/bnxt_ulp.h            |  12 +\n drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c       |  84 ++---\n drivers/net/bnxt/tf_ulp/ulp_flow_db.c         | 149 +++++++--\n drivers/net/bnxt/tf_ulp/ulp_flow_db.h         |   2 +\n drivers/net/bnxt/tf_ulp/ulp_mapper.c          |   1 +\n drivers/net/bnxt/tf_ulp/ulp_mapper.h          |   2 +\n drivers/net/bnxt/tf_ulp/ulp_rte_parser.c      |  75 ++++-\n drivers/net/bnxt/tf_ulp/ulp_rte_parser.h      |   4 +-\n .../net/bnxt/tf_ulp/ulp_template_db_enum.h    |   4 +-\n drivers/net/bnxt/tf_ulp/ulp_template_struct.h |   7 +\n drivers/net/bnxt/tf_ulp/ulp_tun.c             | 310 ++++++++++++++++++\n drivers/net/bnxt/tf_ulp/ulp_tun.h             |  92 ++++++\n 17 files changed, 694 insertions(+), 82 deletions(-)\n create mode 100644 drivers/net/bnxt/tf_ulp/ulp_tun.c\n create mode 100644 drivers/net/bnxt/tf_ulp/ulp_tun.h",
    "diff": "diff --git a/doc/guides/nics/bnxt.rst b/doc/guides/nics/bnxt.rst\nindex 28973fc3e..eee10a3cd 100644\n--- a/doc/guides/nics/bnxt.rst\n+++ b/doc/guides/nics/bnxt.rst\n@@ -706,6 +706,24 @@ Notes\n   flows to be directed to one or more queues associated with the VNIC id.\n   This implementation is supported only when TRUFLOW functionality is disabled.\n \n+- An application can issue a VXLAN decap offload request using rte_flow API\n+  either as a single rte_flow request or a combination of two stages.\n+  The PMD currently supports the two stage offload design.\n+  In this approach the offload request may come as two flow offload requests\n+  Flow1 & Flow2.  The match criteria for Flow1 is O_DMAC, O_SMAC, O_DST_IP,\n+  O_UDP_DPORT and actions are COUNT, MARK, JUMP. The match criteria for Flow2\n+  is O_SRC_IP, O_DST_IP, VNI and inner header fields.\n+  Flow1 and Flow2 flow offload requests can come in any order. If Flow2 flow\n+  offload request comes first then Flow2 can’t be offloaded as there is\n+  no O_DMAC information in Flow2. In this case, Flow2 will be deferred until\n+  Flow1 flow offload request arrives. When Flow1 flow offload request is\n+  received it will have O_DMAC information. Using Flow1’s O_DMAC, driver\n+  creates an L2 context entry in the hardware as part of offloading Flow1.\n+  Flow2 will now use Flow1’s O_DMAC to get the L2 context id associated with\n+  this O_DMAC and other flow fields that are cached already at the time\n+  of deferring Flow2 for offloading. Flow2 that arrive after Flow1 is offloaded\n+  will be directly programmed and not cached.\n+\n Note: A VNIC represents a virtual interface in the hardware. It is a resource\n in the RX path of the chip and is used to setup various target actions such as\n RSS, MAC filtering etc. for the physical function in use.\ndiff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst\nindex c8b284e3b..941ca2d9d 100644\n--- a/doc/guides/rel_notes/release_20_11.rst\n+++ b/doc/guides/rel_notes/release_20_11.rst\n@@ -148,6 +148,7 @@ New Features\n   * Updated HWRM structures to 1.10.1.70 version.\n   * Added TRUFLOW support for Stingray devices.\n   * Added support for representors on MAIA cores of SR.\n+  * Added support for VXLAN decap offload using rte_flow.\n \n * **Updated Cisco enic driver.**\n \ndiff --git a/drivers/net/bnxt/meson.build b/drivers/net/bnxt/meson.build\nindex 39521080f..bc74f88c6 100644\n--- a/drivers/net/bnxt/meson.build\n+++ b/drivers/net/bnxt/meson.build\n@@ -64,6 +64,7 @@ sources = files('bnxt_cpr.c',\n \t'tf_ulp/ulp_port_db.c',\n \t'tf_ulp/ulp_def_rules.c',\n \t'tf_ulp/ulp_fc_mgr.c',\n+\t'tf_ulp/ulp_tun.c',\n \t'tf_ulp/ulp_template_db_wh_plus_act.c',\n \t'tf_ulp/ulp_template_db_wh_plus_class.c',\n \t'tf_ulp/ulp_template_db_stingray_act.c',\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_tf_common.h b/drivers/net/bnxt/tf_ulp/bnxt_tf_common.h\nindex f0633f009..b2629e47b 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_tf_common.h\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_tf_common.h\n@@ -33,7 +33,9 @@\n enum bnxt_tf_rc {\n \tBNXT_TF_RC_PARSE_ERR\t= -2,\n \tBNXT_TF_RC_ERROR\t= -1,\n-\tBNXT_TF_RC_SUCCESS\t= 0\n+\tBNXT_TF_RC_SUCCESS\t= 0,\n+\tBNXT_TF_RC_NORMAL\t= 1,\n+\tBNXT_TF_RC_FID\t\t= 2,\n };\n \n /* eth IPv4 Type */\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c\nindex d753b5af9..26fd3009f 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c\n@@ -1321,6 +1321,16 @@ bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context\t*ulp_ctx)\n \treturn ulp_ctx->cfg_data->flow_db;\n }\n \n+/* Function to get the tunnel cache table info from the ulp context. */\n+struct bnxt_tun_cache_entry *\n+bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx)\n+{\n+\tif (!ulp_ctx || !ulp_ctx->cfg_data)\n+\t\treturn NULL;\n+\n+\treturn ulp_ctx->cfg_data->tun_tbl;\n+}\n+\n /* Function to get the ulp context from eth device. */\n struct bnxt_ulp_context\t*\n bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev\t*dev)\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h\nindex c2c5bcb1d..db1ee50c0 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.h\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.h\n@@ -13,6 +13,8 @@\n #include \"rte_ethdev.h\"\n \n #include \"ulp_template_db_enum.h\"\n+#include \"ulp_tun.h\"\n+#include \"bnxt_tf_common.h\"\n \n /* NAT defines to reuse existing inner L2 SMAC and DMAC */\n #define BNXT_ULP_NAT_INNER_L2_HEADER_SMAC\t0x2000\n@@ -55,6 +57,9 @@ struct bnxt_ulp_data {\n \tstruct bnxt_ulp_df_rule_info\tdf_rule_info[RTE_MAX_ETHPORTS];\n \tstruct bnxt_ulp_vfr_rule_info\tvfr_rule_info[RTE_MAX_ETHPORTS];\n \tenum bnxt_ulp_flow_mem_type\tmem_type;\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 };\n \n struct bnxt_ulp_context {\n@@ -151,6 +156,10 @@ bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context\t*ulp_ctx,\n struct bnxt_ulp_flow_db\t*\n bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context\t*ulp_ctx);\n \n+/* Function to get the tunnel cache table info from the ulp context. */\n+struct bnxt_tun_cache_entry *\n+bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context\t*ulp_ctx);\n+\n /* Function to get the ulp context from eth device. */\n struct bnxt_ulp_context\t*\n bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev);\n@@ -214,4 +223,7 @@ bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context\t*ulp_ctx);\n void\n bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context\t*ulp_ctx);\n \n+int32_t\n+ulp_post_process_tun_flow(struct ulp_rte_parser_params *params);\n+\n #endif /* _BNXT_ULP_H_ */\ndiff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c\nindex 47fbaba03..75a7dbe62 100644\n--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c\n+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c\n@@ -77,24 +77,22 @@ bnxt_ulp_set_dir_attributes(struct ulp_rte_parser_params *params,\n void\n bnxt_ulp_init_mapper_params(struct bnxt_ulp_mapper_create_parms *mapper_cparms,\n \t\t\t    struct ulp_rte_parser_params *params,\n-\t\t\t    uint32_t priority, uint32_t class_id,\n-\t\t\t    uint32_t act_tmpl, uint16_t func_id,\n-\t\t\t    uint32_t fid,\n \t\t\t    enum bnxt_ulp_fdb_type flow_type)\n {\n-\tmapper_cparms->app_priority = priority;\n-\tmapper_cparms->dir_attr = params->dir_attr;\n-\n-\tmapper_cparms->class_tid = class_id;\n-\tmapper_cparms->act_tid = act_tmpl;\n-\tmapper_cparms->func_id = func_id;\n-\tmapper_cparms->hdr_bitmap = &params->hdr_bitmap;\n-\tmapper_cparms->hdr_field = params->hdr_field;\n-\tmapper_cparms->comp_fld = params->comp_fld;\n-\tmapper_cparms->act = &params->act_bitmap;\n-\tmapper_cparms->act_prop = &params->act_prop;\n-\tmapper_cparms->flow_type = flow_type;\n-\tmapper_cparms->flow_id = fid;\n+\tmapper_cparms->flow_type\t= flow_type;\n+\tmapper_cparms->app_priority\t= params->priority;\n+\tmapper_cparms->dir_attr\t\t= params->dir_attr;\n+\tmapper_cparms->class_tid\t= params->class_id;\n+\tmapper_cparms->act_tid\t\t= params->act_tmpl;\n+\tmapper_cparms->func_id\t\t= params->func_id;\n+\tmapper_cparms->hdr_bitmap\t= &params->hdr_bitmap;\n+\tmapper_cparms->hdr_field\t= params->hdr_field;\n+\tmapper_cparms->comp_fld\t\t= params->comp_fld;\n+\tmapper_cparms->act\t\t= &params->act_bitmap;\n+\tmapper_cparms->act_prop\t\t= &params->act_prop;\n+\tmapper_cparms->flow_id\t\t= params->fid;\n+\tmapper_cparms->parent_flow\t= params->parent_flow;\n+\tmapper_cparms->parent_fid\t= params->parent_fid;\n }\n \n /* Function to create the rte flow. */\n@@ -109,7 +107,6 @@ bnxt_ulp_flow_create(struct rte_eth_dev *dev,\n \tstruct ulp_rte_parser_params params;\n \tstruct bnxt_ulp_context *ulp_ctx;\n \tint rc, ret = BNXT_TF_RC_ERROR;\n-\tuint32_t class_id, act_tmpl;\n \tstruct rte_flow *flow_id;\n \tuint16_t func_id;\n \tuint32_t fid;\n@@ -118,13 +115,13 @@ bnxt_ulp_flow_create(struct rte_eth_dev *dev,\n \t\t\t\t\tpattern, actions,\n \t\t\t\t\terror) == BNXT_TF_RC_ERROR) {\n \t\tBNXT_TF_DBG(ERR, \"Invalid arguments being passed\\n\");\n-\t\tgoto parse_err1;\n+\t\tgoto flow_error;\n \t}\n \n \tulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);\n \tif (!ulp_ctx) {\n \t\tBNXT_TF_DBG(ERR, \"ULP context is not initialized\\n\");\n-\t\tgoto parse_err1;\n+\t\tgoto flow_error;\n \t}\n \n \t/* Initialize the parser params */\n@@ -145,13 +142,13 @@ bnxt_ulp_flow_create(struct rte_eth_dev *dev,\n \t\t\t\t\t dev->data->port_id,\n \t\t\t\t\t &func_id)) {\n \t\tBNXT_TF_DBG(ERR, \"conversion of port to func id failed\\n\");\n-\t\tgoto parse_err1;\n+\t\tgoto flow_error;\n \t}\n \n \t/* Protect flow creation */\n \tif (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {\n \t\tBNXT_TF_DBG(ERR, \"Flow db lock acquire failed\\n\");\n-\t\tgoto parse_err1;\n+\t\tgoto flow_error;\n \t}\n \n \t/* Allocate a Flow ID for attaching all resources for the flow to.\n@@ -162,50 +159,55 @@ bnxt_ulp_flow_create(struct rte_eth_dev *dev,\n \t\t\t\t   func_id, &fid);\n \tif (rc) {\n \t\tBNXT_TF_DBG(ERR, \"Unable to allocate flow table entry\\n\");\n-\t\tgoto parse_err2;\n+\t\tgoto release_lock;\n \t}\n \n \t/* Parse the rte flow pattern */\n \tret = bnxt_ulp_rte_parser_hdr_parse(pattern, &params);\n \tif (ret != BNXT_TF_RC_SUCCESS)\n-\t\tgoto parse_err3;\n+\t\tgoto free_fid;\n \n \t/* Parse the rte flow action */\n \tret = bnxt_ulp_rte_parser_act_parse(actions, &params);\n \tif (ret != BNXT_TF_RC_SUCCESS)\n-\t\tgoto parse_err3;\n+\t\tgoto free_fid;\n \n+\tparams.fid = fid;\n+\tparams.func_id = func_id;\n+\tparams.priority = attr->priority;\n \t/* Perform the rte flow post process */\n \tret = bnxt_ulp_rte_parser_post_process(&params);\n-\tif (ret != BNXT_TF_RC_SUCCESS)\n-\t\tgoto parse_err3;\n+\tif (ret == BNXT_TF_RC_ERROR)\n+\t\tgoto free_fid;\n+\telse if (ret == BNXT_TF_RC_FID)\n+\t\tgoto return_fid;\n \n-\tret = ulp_matcher_pattern_match(&params, &class_id);\n+\tret = ulp_matcher_pattern_match(&params, &params.class_id);\n \tif (ret != BNXT_TF_RC_SUCCESS)\n-\t\tgoto parse_err3;\n+\t\tgoto free_fid;\n \n-\tret = ulp_matcher_action_match(&params, &act_tmpl);\n+\tret = ulp_matcher_action_match(&params, &params.act_tmpl);\n \tif (ret != BNXT_TF_RC_SUCCESS)\n-\t\tgoto parse_err3;\n+\t\tgoto free_fid;\n \n-\tbnxt_ulp_init_mapper_params(&mapper_cparms, &params, attr->priority,\n-\t\t\t\t    class_id, act_tmpl, func_id, fid,\n+\tbnxt_ulp_init_mapper_params(&mapper_cparms, &params,\n \t\t\t\t    BNXT_ULP_FDB_TYPE_REGULAR);\n \t/* Call the ulp mapper to create the flow in the hardware. */\n \tret = ulp_mapper_flow_create(ulp_ctx, &mapper_cparms);\n \tif (ret)\n-\t\tgoto parse_err3;\n+\t\tgoto free_fid;\n \n+return_fid:\n \tbnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);\n \n \tflow_id = (struct rte_flow *)((uintptr_t)fid);\n \treturn flow_id;\n \n-parse_err3:\n+free_fid:\n \tulp_flow_db_fid_free(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, fid);\n-parse_err2:\n+release_lock:\n \tbnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);\n-parse_err1:\n+flow_error:\n \trte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n \t\t\t   \"Failed to create flow.\");\n \treturn NULL;\n@@ -219,10 +221,10 @@ bnxt_ulp_flow_validate(struct rte_eth_dev *dev,\n \t\t       const struct rte_flow_action actions[],\n \t\t       struct rte_flow_error *error)\n {\n-\tstruct ulp_rte_parser_params\t\tparams;\n+\tstruct ulp_rte_parser_params params;\n+\tstruct bnxt_ulp_context *ulp_ctx;\n \tuint32_t class_id, act_tmpl;\n \tint ret = BNXT_TF_RC_ERROR;\n-\tstruct bnxt_ulp_context *ulp_ctx;\n \n \tif (bnxt_ulp_flow_validate_args(attr,\n \t\t\t\t\tpattern, actions,\n@@ -256,8 +258,10 @@ bnxt_ulp_flow_validate(struct rte_eth_dev *dev,\n \n \t/* Perform the rte flow post process */\n \tret = bnxt_ulp_rte_parser_post_process(&params);\n-\tif (ret != BNXT_TF_RC_SUCCESS)\n+\tif (ret == BNXT_TF_RC_ERROR)\n \t\tgoto parse_error;\n+\telse if (ret == BNXT_TF_RC_FID)\n+\t\treturn 0;\n \n \tret = ulp_matcher_pattern_match(&params, &class_id);\n \n@@ -283,10 +287,10 @@ bnxt_ulp_flow_destroy(struct rte_eth_dev *dev,\n \t\t      struct rte_flow *flow,\n \t\t      struct rte_flow_error *error)\n {\n-\tint ret = 0;\n \tstruct bnxt_ulp_context *ulp_ctx;\n \tuint32_t flow_id;\n \tuint16_t func_id;\n+\tint ret;\n \n \tulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);\n \tif (!ulp_ctx) {\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c\nindex 8780c01cc..5e7c8ab2e 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c\n@@ -11,6 +11,7 @@\n #include \"ulp_mapper.h\"\n #include \"ulp_flow_db.h\"\n #include \"ulp_fc_mgr.h\"\n+#include \"ulp_tun.h\"\n \n #define ULP_FLOW_DB_RES_DIR_BIT\t\t31\n #define ULP_FLOW_DB_RES_DIR_MASK\t0x80000000\n@@ -375,6 +376,101 @@ ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db)\n \t}\n }\n \n+/* internal validation function for parent flow tbl */\n+static struct bnxt_ulp_flow_db *\n+ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,\n+\t\t\t\t  uint32_t fid)\n+{\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+\t\tBNXT_TF_DBG(ERR, \"Invalid Arguments\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\t/* check for max flows */\n+\tif (fid >= flow_db->flow_tbl.num_flows || !fid) {\n+\t\tBNXT_TF_DBG(ERR, \"Invalid flow index\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\t/* No support for parent child db then just exit */\n+\tif (!flow_db->parent_child_db.entries_count) {\n+\t\tBNXT_TF_DBG(ERR, \"parent child db not supported\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\treturn flow_db;\n+}\n+\n+/*\n+ * Set the tunnel index in the parent flow\n+ *\n+ * ulp_ctxt [in] Ptr to ulp_context\n+ * parent_idx [in] The parent index of the parent flow entry\n+ *\n+ * returns index on success and negative on failure.\n+ */\n+static int32_t\n+ulp_flow_db_parent_tun_idx_set(struct bnxt_ulp_context *ulp_ctxt,\n+\t\t\t       uint32_t parent_idx, uint8_t tun_idx)\n+{\n+\tstruct bnxt_ulp_flow_db *flow_db;\n+\tstruct ulp_fdb_parent_child_db *p_pdb;\n+\n+\tflow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);\n+\tif (!flow_db) {\n+\t\tBNXT_TF_DBG(ERR, \"Invalid Arguments\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check for parent idx validity */\n+\tp_pdb = &flow_db->parent_child_db;\n+\tif (parent_idx >= p_pdb->entries_count ||\n+\t    !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {\n+\t\tBNXT_TF_DBG(ERR, \"Invalid parent flow index %x\\n\", parent_idx);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tp_pdb->parent_flow_tbl[parent_idx].tun_idx = tun_idx;\n+\treturn 0;\n+}\n+\n+/*\n+ * Get the tunnel index from the parent flow\n+ *\n+ * ulp_ctxt [in] Ptr to ulp_context\n+ * parent_fid [in] The flow id of the parent flow entry\n+ *\n+ * returns 0 if counter accum is set else -1.\n+ */\n+static int32_t\n+ulp_flow_db_parent_tun_idx_get(struct bnxt_ulp_context *ulp_ctxt,\n+\t\t\t       uint32_t parent_fid, uint8_t *tun_idx)\n+{\n+\tstruct bnxt_ulp_flow_db *flow_db;\n+\tstruct ulp_fdb_parent_child_db *p_pdb;\n+\tuint32_t idx;\n+\n+\t/* validate the arguments */\n+\tflow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);\n+\tif (!flow_db) {\n+\t\tBNXT_TF_DBG(ERR, \"parent child db validation failed\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tp_pdb = &flow_db->parent_child_db;\n+\tfor (idx = 0; idx < p_pdb->entries_count; idx++) {\n+\t\tif (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {\n+\t\t\t*tun_idx = p_pdb->parent_flow_tbl[idx].tun_idx;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\treturn -EINVAL;\n+}\n+\n /*\n  * Initialize the flow database. Memory is allocated in this\n  * call and assigned to the flow database.\n@@ -663,6 +759,9 @@ ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,\n \tstruct bnxt_ulp_flow_tbl *flow_tbl;\n \tstruct ulp_fdb_resource_info *nxt_resource, *fid_resource;\n \tuint32_t nxt_idx = 0;\n+\tstruct bnxt_tun_cache_entry *tun_tbl;\n+\tuint8_t tun_idx = 0;\n+\tint rc;\n \n \tflow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);\n \tif (!flow_db) {\n@@ -739,6 +838,18 @@ ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,\n \t\t\t\t      params->resource_hndl);\n \t}\n \n+\tif (params->resource_func == BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW) {\n+\t\ttun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);\n+\t\tif (!tun_tbl)\n+\t\t\treturn -EINVAL;\n+\n+\t\trc = ulp_flow_db_parent_tun_idx_get(ulp_ctxt, fid, &tun_idx);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\n+\t\tulp_clear_tun_entry(tun_tbl, tun_idx);\n+\t}\n+\n \t/* all good, return success */\n \treturn 0;\n }\n@@ -1159,34 +1270,6 @@ ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,\n \treturn 0;\n }\n \n-/* internal validation function for parent flow tbl */\n-static struct bnxt_ulp_flow_db *\n-ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,\n-\t\t\t\t  uint32_t fid)\n-{\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-\t\tBNXT_TF_DBG(ERR, \"Invalid Arguments\\n\");\n-\t\treturn NULL;\n-\t}\n-\n-\t/* check for max flows */\n-\tif (fid >= flow_db->flow_tbl.num_flows || !fid) {\n-\t\tBNXT_TF_DBG(ERR, \"Invalid flow index\\n\");\n-\t\treturn NULL;\n-\t}\n-\n-\t/* No support for parent child db then just exit */\n-\tif (!flow_db->parent_child_db.entries_count) {\n-\t\tBNXT_TF_DBG(ERR, \"parent child db not supported\\n\");\n-\t\treturn NULL;\n-\t}\n-\n-\treturn flow_db;\n-}\n-\n /*\n  * Allocate the entry in the parent-child database\n  *\n@@ -1559,7 +1642,7 @@ ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)\n \tstruct ulp_flow_db_res_params fid_parms;\n \tuint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC;\n \tstruct ulp_flow_db_res_params res_params;\n-\tint32_t fid_idx;\n+\tint32_t fid_idx, rc;\n \n \t/* create the child flow entry in parent flow table */\n \tfid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid);\n@@ -1596,6 +1679,14 @@ ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)\n \t\t\treturn -1;\n \t\t}\n \t}\n+\n+\trc  = ulp_flow_db_parent_tun_idx_set(parms->ulp_ctx, fid_idx,\n+\t\t\t\t\t     parms->tun_idx);\n+\tif (rc) {\n+\t\tBNXT_TF_DBG(ERR, \"Error setting tun_idx in the parent flow\\n\");\n+\t\treturn rc;\n+\t}\n+\n \treturn 0;\n }\n \ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h\nindex 10e69bae4..f7dfd67be 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h\n@@ -60,6 +60,8 @@ struct ulp_fdb_parent_info {\n \tuint64_t\tpkt_count;\n \tuint64_t\tbyte_count;\n \tuint64_t\t*child_fid_bitset;\n+\tuint32_t\tf2_cnt;\n+\tuint8_t\t\ttun_idx;\n };\n \n /* Structure to maintain parent-child flow relationships */\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c\nindex d5c129b3a..29643232d 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c\n@@ -2815,6 +2815,7 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,\n \tparms.parent_flow = cparms->parent_flow;\n \tparms.parent_fid = cparms->parent_fid;\n \tparms.fid = cparms->flow_id;\n+\tparms.tun_idx = cparms->tun_idx;\n \n \t/* Get the device id from the ulp context */\n \tif (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.h b/drivers/net/bnxt/tf_ulp/ulp_mapper.h\nindex 0595d1555..9bd94f5c2 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_mapper.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.h\n@@ -78,6 +78,7 @@ struct bnxt_ulp_mapper_parms {\n \tstruct bnxt_ulp_device_params           *device_params;\n \tuint32_t\t\t\t\tparent_fid;\n \tuint32_t\t\t\t\tparent_flow;\n+\tuint8_t\t\t\t\t\ttun_idx;\n };\n \n struct bnxt_ulp_mapper_create_parms {\n@@ -98,6 +99,7 @@ struct bnxt_ulp_mapper_create_parms {\n \tuint32_t\t\t\tparent_fid;\n \t/* if set then create a parent flow */\n \tuint32_t\t\t\tparent_flow;\n+\tuint8_t\t\t\t\ttun_idx;\n };\n \n /* Function to initialize any dynamic mapper data. */\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c\nindex 42021ae8d..df38b8370 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c\n+++ b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.c\n@@ -6,11 +6,16 @@\n #include \"bnxt.h\"\n #include \"ulp_template_db_enum.h\"\n #include \"ulp_template_struct.h\"\n+#include \"bnxt_ulp.h\"\n #include \"bnxt_tf_common.h\"\n #include \"ulp_rte_parser.h\"\n+#include \"ulp_matcher.h\"\n #include \"ulp_utils.h\"\n #include \"tfp.h\"\n #include \"ulp_port_db.h\"\n+#include \"ulp_flow_db.h\"\n+#include \"ulp_mapper.h\"\n+#include \"ulp_tun.h\"\n \n /* Local defines for the parsing functions */\n #define ULP_VLAN_PRIORITY_SHIFT\t\t13 /* First 3 bits */\n@@ -243,14 +248,11 @@ bnxt_ulp_comp_fld_intf_update(struct ulp_rte_parser_params *params)\n \t}\n }\n \n-/*\n- * Function to handle the post processing of the parsing details\n- */\n-int32_t\n-bnxt_ulp_rte_parser_post_process(struct ulp_rte_parser_params *params)\n+static int32_t\n+ulp_post_process_normal_flow(struct ulp_rte_parser_params *params)\n {\n-\tenum bnxt_ulp_direction_type dir;\n \tenum bnxt_ulp_intf_type match_port_type, act_port_type;\n+\tenum bnxt_ulp_direction_type dir;\n \tuint32_t act_port_set;\n \n \t/* Get the computed details */\n@@ -305,6 +307,16 @@ bnxt_ulp_rte_parser_post_process(struct ulp_rte_parser_params *params)\n \treturn 0;\n }\n \n+/*\n+ * Function to handle the post processing of the parsing details\n+ */\n+int32_t\n+bnxt_ulp_rte_parser_post_process(struct ulp_rte_parser_params *params)\n+{\n+\tulp_post_process_normal_flow(params);\n+\treturn ulp_post_process_tun_flow(params);\n+}\n+\n /*\n  * Function to compute the flow direction based on the match port details\n  */\n@@ -679,7 +691,16 @@ ulp_rte_eth_hdr_handler(const struct rte_flow_item *item,\n \tparams->field_idx += BNXT_ULP_PROTO_HDR_VLAN_NUM;\n \n \t/* Update the protocol hdr bitmap */\n-\tif (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_O_ETH)) {\n+\tif (ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t     BNXT_ULP_HDR_BIT_O_ETH) ||\n+\t    ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t     BNXT_ULP_HDR_BIT_O_IPV4) ||\n+\t    ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t     BNXT_ULP_HDR_BIT_O_IPV6) ||\n+\t    ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t     BNXT_ULP_HDR_BIT_O_UDP) ||\n+\t    ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t     BNXT_ULP_HDR_BIT_O_TCP)) {\n \t\tULP_BITMAP_SET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_I_ETH);\n \t\tinner_flag = 1;\n \t} else {\n@@ -875,6 +896,22 @@ ulp_rte_ipv4_hdr_handler(const struct rte_flow_item *item,\n \t\treturn BNXT_TF_RC_ERROR;\n \t}\n \n+\tif (!ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t      BNXT_ULP_HDR_BIT_O_ETH) &&\n+\t    !ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t      BNXT_ULP_HDR_BIT_I_ETH)) {\n+\t\t/* Since F2 flow does not include eth item, when parser detects\n+\t\t * IPv4/IPv6 item list and it belongs to the outer header; i.e.,\n+\t\t * o_ipv4/o_ipv6, check if O_ETH and I_ETH is set. If not set,\n+\t\t * then add offset sizeof(o_eth/oo_vlan/oi_vlan) to the index.\n+\t\t * This will allow the parser post processor to update the\n+\t\t * t_dmac in hdr_field[o_eth.dmac]\n+\t\t */\n+\t\tidx += (BNXT_ULP_PROTO_HDR_ETH_NUM +\n+\t\t\tBNXT_ULP_PROTO_HDR_VLAN_NUM);\n+\t\tparams->field_idx = idx;\n+\t}\n+\n \t/*\n \t * Copy the rte_flow_item for ipv4 into hdr_field using ipv4\n \t * header fields\n@@ -1004,6 +1041,22 @@ ulp_rte_ipv6_hdr_handler(const struct rte_flow_item *item,\n \t\treturn BNXT_TF_RC_ERROR;\n \t}\n \n+\tif (!ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t      BNXT_ULP_HDR_BIT_O_ETH) &&\n+\t    !ULP_BITMAP_ISSET(params->hdr_bitmap.bits,\n+\t\t\t      BNXT_ULP_HDR_BIT_I_ETH)) {\n+\t\t/* Since F2 flow does not include eth item, when parser detects\n+\t\t * IPv4/IPv6 item list and it belongs to the outer header; i.e.,\n+\t\t * o_ipv4/o_ipv6, check if O_ETH and I_ETH is set. If not set,\n+\t\t * then add offset sizeof(o_eth/oo_vlan/oi_vlan) to the index.\n+\t\t * This will allow the parser post processor to update the\n+\t\t * t_dmac in hdr_field[o_eth.dmac]\n+\t\t */\n+\t\tidx += (BNXT_ULP_PROTO_HDR_ETH_NUM +\n+\t\t\tBNXT_ULP_PROTO_HDR_VLAN_NUM);\n+\t\tparams->field_idx = idx;\n+\t}\n+\n \t/*\n \t * Copy the rte_flow_item for ipv6 into hdr_field using ipv6\n \t * header fields\n@@ -1109,9 +1162,11 @@ static void\n ulp_rte_l4_proto_type_update(struct ulp_rte_parser_params *param,\n \t\t\t     uint16_t dst_port)\n {\n-\tif (dst_port == tfp_cpu_to_be_16(ULP_UDP_PORT_VXLAN))\n+\tif (dst_port == tfp_cpu_to_be_16(ULP_UDP_PORT_VXLAN)) {\n \t\tULP_BITMAP_SET(param->hdr_fp_bit.bits,\n \t\t\t       BNXT_ULP_HDR_BIT_T_VXLAN);\n+\t\tULP_COMP_FLD_IDX_WR(param, BNXT_ULP_CF_IDX_L3_TUN, 1);\n+\t}\n }\n \n /* Function to handle the parsing of RTE Flow item UDP Header. */\n@@ -1143,6 +1198,7 @@ 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+\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@@ -1689,6 +1745,9 @@ ulp_rte_vxlan_decap_act_handler(const struct rte_flow_action *action_item\n \t/* update the hdr_bitmap with vxlan */\n \tULP_BITMAP_SET(params->act_bitmap.bits,\n \t\t       BNXT_ULP_ACTION_BIT_VXLAN_DECAP);\n+\t/* Update computational field with tunnel decap info */\n+\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L3_TUN_DECAP, 1);\n+\tULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L3_TUN, 1);\n \treturn BNXT_TF_RC_SUCCESS;\n }\n \ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h\nindex a71aabe5f..799631790 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_rte_parser.h\n@@ -12,6 +12,7 @@\n #include \"ulp_template_db_enum.h\"\n #include \"ulp_template_struct.h\"\n #include \"ulp_mapper.h\"\n+#include \"bnxt_tf_common.h\"\n \n /* defines to be used in the tunnel header parsing */\n #define BNXT_ULP_ENCAP_IPV4_VER_HLEN_TOS\t2\n@@ -38,9 +39,6 @@\n void\n bnxt_ulp_init_mapper_params(struct bnxt_ulp_mapper_create_parms *mapper_cparms,\n \t\t\t    struct ulp_rte_parser_params *params,\n-\t\t\t    uint32_t priority, uint32_t class_id,\n-\t\t\t    uint32_t act_tmpl, uint16_t func_id,\n-\t\t\t    uint32_t flow_id,\n \t\t\t    enum bnxt_ulp_fdb_type flow_type);\n \n /* Function to handle the parsing of the RTE port id. */\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 10838f5cc..6802debbb 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@@ -135,7 +135,9 @@ enum bnxt_ulp_cf_idx {\n \tBNXT_ULP_CF_IDX_L4_HDR_CNT = 41,\n \tBNXT_ULP_CF_IDX_VFR_MODE = 42,\n \tBNXT_ULP_CF_IDX_LOOPBACK_PARIF = 43,\n-\tBNXT_ULP_CF_IDX_LAST = 44\n+\tBNXT_ULP_CF_IDX_L3_TUN = 44,\n+\tBNXT_ULP_CF_IDX_L3_TUN_DECAP = 45,\n+\tBNXT_ULP_CF_IDX_LAST = 46\n };\n \n enum bnxt_ulp_cond_opcode {\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_template_struct.h b/drivers/net/bnxt/tf_ulp/ulp_template_struct.h\nindex 69bb61e11..9d690a937 100644\n--- a/drivers/net/bnxt/tf_ulp/ulp_template_struct.h\n+++ b/drivers/net/bnxt/tf_ulp/ulp_template_struct.h\n@@ -72,6 +72,13 @@ struct ulp_rte_parser_params {\n \tstruct ulp_rte_act_bitmap\tact_bitmap;\n \tstruct ulp_rte_act_prop\t\tact_prop;\n \tuint32_t\t\t\tdir_attr;\n+\tuint32_t\t\t\tpriority;\n+\tuint32_t\t\t\tfid;\n+\tuint32_t\t\t\tparent_flow;\n+\tuint32_t\t\t\tparent_fid;\n+\tuint16_t\t\t\tfunc_id;\n+\tuint32_t\t\t\tclass_id;\n+\tuint32_t\t\t\tact_tmpl;\n \tstruct bnxt_ulp_context\t\t*ulp_ctx;\n };\n \ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_tun.c b/drivers/net/bnxt/tf_ulp/ulp_tun.c\nnew file mode 100644\nindex 000000000..e8d286188\n--- /dev/null\n+++ b/drivers/net/bnxt/tf_ulp/ulp_tun.c\n@@ -0,0 +1,310 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2014-2020 Broadcom\n+ * All rights reserved.\n+ */\n+\n+#include <rte_malloc.h>\n+\n+#include \"ulp_tun.h\"\n+#include \"ulp_rte_parser.h\"\n+#include \"ulp_template_db_enum.h\"\n+#include \"ulp_template_struct.h\"\n+#include \"ulp_matcher.h\"\n+#include \"ulp_mapper.h\"\n+#include \"ulp_flow_db.h\"\n+\n+/* This function programs the outer tunnel flow in the hardware. */\n+static int32_t\n+ulp_install_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+\tstruct bnxt_ulp_mapper_create_parms mparms = { 0 };\n+\tint ret;\n+\n+\t/* Reset the JUMP action bit in the action bitmap as we don't\n+\t * offload this action.\n+\t */\n+\tULP_BITMAP_RESET(params->act_bitmap.bits, BNXT_ULP_ACTION_BIT_JUMP);\n+\n+\tULP_BITMAP_SET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_F1);\n+\n+\tret = ulp_matcher_pattern_match(params, &params->class_id);\n+\tif (ret != BNXT_TF_RC_SUCCESS)\n+\t\tgoto err;\n+\n+\tret = ulp_matcher_action_match(params, &params->act_tmpl);\n+\tif (ret != BNXT_TF_RC_SUCCESS)\n+\t\tgoto err;\n+\n+\tparams->parent_flow = true;\n+\tbnxt_ulp_init_mapper_params(&mparms, params,\n+\t\t\t\t    BNXT_ULP_FDB_TYPE_REGULAR);\n+\tmparms.tun_idx = tun_idx;\n+\n+\t/* Call the ulp mapper to create the flow in the hardware. */\n+\tret = ulp_mapper_flow_create(params->ulp_ctx, &mparms);\n+\tif (ret)\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 */\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->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 */\n+\tif (tun_entry->t_dst_ip_valid)\n+\t\tgoto done;\n+\tif (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_O_IPV4))\n+\t\tmemcpy(&tun_entry->t_dst_ip,\n+\t\t       &params->hdr_field[ULP_TUN_O_IPV4_DIP_INDEX].spec,\n+\t\t       sizeof(rte_be32_t));\n+\telse\n+\t\tmemcpy(tun_entry->t_dst_ip6,\n+\t\t       &params->hdr_field[ULP_TUN_O_IPV6_DIP_INDEX].spec,\n+\t\t       sizeof(tun_entry->t_dst_ip6));\n+\ttun_entry->t_dst_ip_valid = true;\n+\n+done:\n+\treturn BNXT_TF_RC_FID;\n+\n+err:\n+\tmemset(tun_entry, 0, sizeof(struct bnxt_tun_cache_entry));\n+\treturn BNXT_TF_RC_ERROR;\n+}\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+{\n+\tstruct bnxt_ulp_mapper_create_parms mparms = { 0 };\n+\tstruct ulp_rte_parser_params *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 */\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+}\n+\n+/* This function either install outer tunnel flow & inner tunnel flow\n+ * or just the outer tunnel flow based on the flow state.\n+ */\n+static int32_t\n+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+\t\treturn ret;\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 */\n+\tif (flow_state != BNXT_ULP_FLOW_STATE_NORMAL)\n+\t\tulp_install_inner_tun_flow(tun_entry);\n+\n+\treturn 0;\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+\t\t\t\t      struct bnxt_tun_cache_entry *tun_entry)\n+{\n+\tint ret;\n+\n+\tret = ulp_matcher_pattern_match(params, &params->class_id);\n+\tif (ret != BNXT_TF_RC_SUCCESS)\n+\t\treturn BNXT_TF_RC_ERROR;\n+\n+\tret = ulp_matcher_action_match(params, &params->act_tmpl);\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 */\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+\n+\t/* F1 and it's related F2s 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+\tif (tun_entry->t_dst_ip_valid)\n+\t\tgoto done;\n+\tif (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_O_IPV4))\n+\t\tmemcpy(&tun_entry->t_dst_ip,\n+\t\t       &params->hdr_field[ULP_TUN_O_IPV4_DIP_INDEX].spec,\n+\t\t       sizeof(rte_be32_t));\n+\telse\n+\t\tmemcpy(tun_entry->t_dst_ip6,\n+\t\t       &params->hdr_field[ULP_TUN_O_IPV6_DIP_INDEX].spec,\n+\t\t       sizeof(tun_entry->t_dst_ip6));\n+\ttun_entry->t_dst_ip_valid = true;\n+\n+done:\n+\treturn BNXT_TF_RC_FID;\n+}\n+\n+/* This function will be called if inner tunnel flow request comes after\n+ * the outer tunnel flow request.\n+ */\n+static int32_t\n+ulp_post_process_inner_tun_flow(struct ulp_rte_parser_params *params,\n+\t\t\t\tstruct bnxt_tun_cache_entry *tun_entry)\n+{\n+\tmemcpy(&params->hdr_field[ULP_TUN_O_DMAC_HDR_FIELD_INDEX],\n+\t       tun_entry->t_dmac, RTE_ETHER_ADDR_LEN);\n+\n+\tparams->parent_fid = tun_entry->outer_tun_flow_id;\n+\n+\treturn BNXT_TF_RC_NORMAL;\n+}\n+\n+static int32_t\n+ulp_get_tun_entry(struct ulp_rte_parser_params *params,\n+\t\t  struct bnxt_tun_cache_entry **tun_entry,\n+\t\t  uint16_t *tun_idx)\n+{\n+\tint i, first_free_entry = BNXT_ULP_TUN_ENTRY_INVALID;\n+\tstruct bnxt_tun_cache_entry *tun_tbl;\n+\tbool tun_entry_found = false, free_entry_found = false;\n+\n+\ttun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(params->ulp_ctx);\n+\tif (!tun_tbl)\n+\t\treturn BNXT_TF_RC_ERROR;\n+\n+\tfor (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) {\n+\t\tif (!memcmp(&tun_tbl[i].t_dst_ip,\n+\t\t\t    &params->hdr_field[ULP_TUN_O_IPV4_DIP_INDEX].spec,\n+\t\t\t    sizeof(rte_be32_t)) ||\n+\t\t    !memcmp(&tun_tbl[i].t_dst_ip6,\n+\t\t\t    &params->hdr_field[ULP_TUN_O_IPV6_DIP_INDEX].spec,\n+\t\t\t    16)) {\n+\t\t\ttun_entry_found = true;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!tun_tbl[i].t_dst_ip_valid && !free_entry_found) {\n+\t\t\tfirst_free_entry = i;\n+\t\t\tfree_entry_found = true;\n+\t\t}\n+\t}\n+\n+\tif (tun_entry_found) {\n+\t\t*tun_entry = &tun_tbl[i];\n+\t\t*tun_idx = i;\n+\t} else {\n+\t\tif (first_free_entry == BNXT_ULP_TUN_ENTRY_INVALID)\n+\t\t\treturn BNXT_TF_RC_ERROR;\n+\t\t*tun_entry = &tun_tbl[first_free_entry];\n+\t\t*tun_idx = first_free_entry;\n+\t}\n+\n+\treturn 0;\n+}\n+\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+\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+\tuint16_t tun_idx;\n+\tint rc;\n+\n+\t/* Computational fields that indicate it's a TUNNEL DECAP flow */\n+\tl3_tun = ULP_COMP_FLD_IDX_RD(params, BNXT_ULP_CF_IDX_L3_TUN);\n+\tl3_tun_decap = ULP_COMP_FLD_IDX_RD(params,\n+\t\t\t\t\t   BNXT_ULP_CF_IDX_L3_TUN_DECAP);\n+\tif (!l3_tun)\n+\t\treturn BNXT_TF_RC_NORMAL;\n+\n+\trc = ulp_get_tun_entry(params, &tun_entry, &tun_idx);\n+\tif (rc == BNXT_TF_RC_ERROR)\n+\t\treturn rc;\n+\n+\tflow_state = tun_entry->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_reject = BNXT_REJECT_OUTER_TUN_FLOW(flow_state,\n+\t\t\t\t\t\t      outer_tun_sig);\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+\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+\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 (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+\telse if (inner_tun_flow)\n+\t\treturn ulp_post_process_inner_tun_flow(params, tun_entry);\n+\telse\n+\t\treturn BNXT_TF_RC_NORMAL;\n+}\n+\n+void\n+ulp_clear_tun_entry(struct bnxt_tun_cache_entry *tun_tbl, uint8_t tun_idx)\n+{\n+\tmemset(&tun_tbl[tun_idx], 0,\n+\t\tsizeof(struct bnxt_tun_cache_entry));\n+}\ndiff --git a/drivers/net/bnxt/tf_ulp/ulp_tun.h b/drivers/net/bnxt/tf_ulp/ulp_tun.h\nnew file mode 100644\nindex 000000000..ad70ae616\n--- /dev/null\n+++ b/drivers/net/bnxt/tf_ulp/ulp_tun.h\n@@ -0,0 +1,92 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2014-2020 Broadcom\n+ * All rights reserved.\n+ */\n+\n+#ifndef _BNXT_TUN_H_\n+#define _BNXT_TUN_H_\n+\n+#include <inttypes.h>\n+#include <stdbool.h>\n+#include <sys/queue.h>\n+\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+\t((l3_tun) &&\t\t\t\t\t\\\n+\t ULP_BITMAP_ISSET((params)->act_bitmap.bits,\t\\\n+\t\t\t  BNXT_ULP_ACTION_BIT_JUMP))\n+#define\tBNXT_INNER_TUN_SIGNATURE(l3_tun, l3_tun_decap, params)\t\t\\\n+\t((l3_tun) && (l3_tun_decap) &&\t\t\t\t\t\\\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+\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+#define\tULP_TUN_O_IPV6_DIP_INDEX\t17\n+\n+/* When a flow offload request comes the following state transitions\n+ * happen based on the order in which the outer & inner flow offload\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+ *\n+ * If outer tunnel flow offload request arrives first then the flow state\n+ * will change from BNXT_ULP_FLOW_STATE_NORMAL to\n+ * BNXT_ULP_FLOW_STATE_TUN_O_OFFLD.\n+ *\n+ * Once the flow state is in BNXT_ULP_FLOW_STATE_TUN_O_OFFLD, any inner\n+ * tunnel flow offload requests after that point will be treated as a\n+ * normal flow and the tunnel flow state remains in\n+ * BNXT_ULP_FLOW_STATE_TUN_O_OFFLD\n+ */\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 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+\t\trte_be32_t\t\tt_dst_ip;\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+};\n+\n+void\n+ulp_clear_tun_entry(struct bnxt_tun_cache_entry *tun_tbl, uint8_t tun_idx);\n+\n+#endif\n",
    "prefixes": [
        "v2",
        "11/11"
    ]
}