diff mbox series

net/octeontx2: support for rte_flow_dev_dump api

Message ID 20210208130158.2270443-1-psatheesh@marvell.com (mailing list archive)
State Accepted
Delegated to: Jerin Jacob
Headers show
Series net/octeontx2: support for rte_flow_dev_dump api | expand

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/travis-robot warning Travis build: failed
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-testing warning Testing issues
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/intel-Testing success Testing PASS
ci/Intel-compilation success Compilation OK

Commit Message

psatheesh@marvell.com Feb. 8, 2021, 1:01 p.m. UTC
From: Satheesh Paul <psatheesh@marvell.com>

  Add support to dump hardware internal representation information of
rte flow to file.

Every flow rule added will be dumped in the below format.

MCAM Index:1881
Interface :NIX-RX (0)
Priority  :1
NPC RX Action:0X00000000404001
        ActionOp:NIX_RX_ACTIONOP_UCAST (1)
        PF_FUNC: 0X400
        RQ Index:0X004
        Match Id:0000
        Flow Key Alg:0
NPC RX VTAG Action:0X00000000008100
        VTAG0:relptr:0
        lid:0X1
        type:0
Patterns:
        NPC_PARSE_NIBBLE_CHAN:000
        NPC_PARSE_NIBBLE_LA_LTYPE:LA_ETHER
        NPC_PARSE_NIBBLE_LB_LTYPE:NONE
        NPC_PARSE_NIBBLE_LC_LTYPE:LC_IP
        NPC_PARSE_NIBBLE_LD_LTYPE:LD_TCP
        NPC_PARSE_NIBBLE_LE_LTYPE:NONE
        LA_ETHER, hdr offset:0, len:0X6, key offset:0X8,\
		Data:0X4AE124FC7FFF, Mask:0XFFFFFFFFFFFF
        LA_ETHER, hdr offset:0XC, len:0X2, key offset:0X4, Data:0XCA5A,\
		Mask:0XFFFF
        LC_IP, hdr offset:0XC, len:0X8, key offset:0X10,\
		Data:0X0A01010300000000, Mask:0XFFFFFFFF00000000
        LD_TCP, hdr offset:0, len:0X4, key offset:0X18, Data:0X03450000,\
		Mask:0XFFFF0000
MCAM Raw Data :
        DW0     :0000CA5A01202000
        DW0_Mask:0000FFFF0FF0F000
        DW1     :00004AE124FC7FFF
        DW1_Mask:0000FFFFFFFFFFFF
        DW2     :0A01010300000000
        DW2_Mask:FFFFFFFF00000000
        DW3     :0000000003450000
        DW3_Mask:00000000FFFF0000
        DW4     :0000000000000000
        DW4_Mask:0000000000000000
        DW5     :0000000000000000
        DW5_Mask:0000000000000000
        DW6     :0000000000000000
        DW6_Mask:0000000000000000

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
 drivers/net/octeontx2/meson.build       |   1 +
 drivers/net/octeontx2/otx2_flow.c       |  33 ++
 drivers/net/octeontx2/otx2_flow.h       |  10 +
 drivers/net/octeontx2/otx2_flow_dump.c  | 592 ++++++++++++++++++++++++
 drivers/net/octeontx2/otx2_flow_utils.c |   4 +
 5 files changed, 640 insertions(+)
 create mode 100644 drivers/net/octeontx2/otx2_flow_dump.c

Comments

Jerin Jacob March 8, 2021, 1:12 p.m. UTC | #1
On Mon, Feb 8, 2021 at 6:32 PM <psatheesh@marvell.com> wrote:
>
> From: Satheesh Paul <psatheesh@marvell.com>
>
>   Add support to dump hardware internal representation information of
> rte flow to file.
>
> Every flow rule added will be dumped in the below format.


Fixed the subject as "net/octeontx2: support rte flow dump ops"

Acked-by: Jerin Jacob <jerinj@marvell.com>
Applied to dpdk-next-net-mrvl/for-main. Thanks



> MCAM Index:1881
> Interface :NIX-RX (0)
> Priority  :1
> NPC RX Action:0X00000000404001
>         ActionOp:NIX_RX_ACTIONOP_UCAST (1)
>         PF_FUNC: 0X400
>         RQ Index:0X004
>         Match Id:0000
>         Flow Key Alg:0
> NPC RX VTAG Action:0X00000000008100
>         VTAG0:relptr:0
>         lid:0X1
>         type:0
> Patterns:
>         NPC_PARSE_NIBBLE_CHAN:000
>         NPC_PARSE_NIBBLE_LA_LTYPE:LA_ETHER
>         NPC_PARSE_NIBBLE_LB_LTYPE:NONE
>         NPC_PARSE_NIBBLE_LC_LTYPE:LC_IP
>         NPC_PARSE_NIBBLE_LD_LTYPE:LD_TCP
>         NPC_PARSE_NIBBLE_LE_LTYPE:NONE
>         LA_ETHER, hdr offset:0, len:0X6, key offset:0X8,\
>                 Data:0X4AE124FC7FFF, Mask:0XFFFFFFFFFFFF
>         LA_ETHER, hdr offset:0XC, len:0X2, key offset:0X4, Data:0XCA5A,\
>                 Mask:0XFFFF
>         LC_IP, hdr offset:0XC, len:0X8, key offset:0X10,\
>                 Data:0X0A01010300000000, Mask:0XFFFFFFFF00000000
>         LD_TCP, hdr offset:0, len:0X4, key offset:0X18, Data:0X03450000,\
>                 Mask:0XFFFF0000
> MCAM Raw Data :
>         DW0     :0000CA5A01202000
>         DW0_Mask:0000FFFF0FF0F000
>         DW1     :00004AE124FC7FFF
>         DW1_Mask:0000FFFFFFFFFFFF
>         DW2     :0A01010300000000
>         DW2_Mask:FFFFFFFF00000000
>         DW3     :0000000003450000
>         DW3_Mask:00000000FFFF0000
>         DW4     :0000000000000000
>         DW4_Mask:0000000000000000
>         DW5     :0000000000000000
>         DW5_Mask:0000000000000000
>         DW6     :0000000000000000
>         DW6_Mask:0000000000000000
>
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---
>  drivers/net/octeontx2/meson.build       |   1 +
>  drivers/net/octeontx2/otx2_flow.c       |  33 ++
>  drivers/net/octeontx2/otx2_flow.h       |  10 +
>  drivers/net/octeontx2/otx2_flow_dump.c  | 592 ++++++++++++++++++++++++
>  drivers/net/octeontx2/otx2_flow_utils.c |   4 +
>  5 files changed, 640 insertions(+)
>  create mode 100644 drivers/net/octeontx2/otx2_flow_dump.c
>
> diff --git a/drivers/net/octeontx2/meson.build b/drivers/net/octeontx2/meson.build
> index e2c139a8b..779a75b5d 100644
> --- a/drivers/net/octeontx2/meson.build
> +++ b/drivers/net/octeontx2/meson.build
> @@ -28,6 +28,7 @@ sources = files('otx2_rx.c',
>                 'otx2_lookup.c',
>                 'otx2_ethdev.c',
>                 'otx2_flow_ctrl.c',
> +               'otx2_flow_dump.c',
>                 'otx2_flow_parse.c',
>                 'otx2_flow_utils.c',
>                 'otx2_ethdev_irq.c',
> diff --git a/drivers/net/octeontx2/otx2_flow.c b/drivers/net/octeontx2/otx2_flow.c
> index a5900f349..14ac9bc76 100644
> --- a/drivers/net/octeontx2/otx2_flow.c
> +++ b/drivers/net/octeontx2/otx2_flow.c
> @@ -805,6 +805,38 @@ otx2_flow_query(struct rte_eth_dev *dev,
>         return -rte_errno;
>  }
>
> +static int
> +otx2_flow_dev_dump(struct rte_eth_dev *dev,
> +                 FILE *file,
> +                 struct rte_flow_error *error)
> +{
> +       struct otx2_eth_dev *hw = dev->data->dev_private;
> +       struct otx2_flow_list *list;
> +       struct rte_flow *flow_iter;
> +       uint32_t max_prio, i;
> +
> +       if (file == NULL) {
> +               rte_flow_error_set(error, EINVAL,
> +                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +                                  NULL,
> +                                  "Invalid file");
> +               return -EINVAL;
> +       }
> +
> +       max_prio = hw->npc_flow.flow_max_priority;
> +
> +       for (i = 0; i < max_prio; i++) {
> +               list = &hw->npc_flow.flow_list[i];
> +
> +               /* List in ascending order of mcam entries */
> +               TAILQ_FOREACH(flow_iter, list, next) {
> +                       otx2_flow_dump(file, hw, flow_iter);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
>  const struct rte_flow_ops otx2_flow_ops = {
>         .validate = otx2_flow_validate,
>         .create = otx2_flow_create,
> @@ -812,6 +844,7 @@ const struct rte_flow_ops otx2_flow_ops = {
>         .flush = otx2_flow_flush,
>         .query = otx2_flow_query,
>         .isolate = otx2_flow_isolate,
> +       .dev_dump = otx2_flow_dev_dump,
>  };
>
>  static int
> diff --git a/drivers/net/octeontx2/otx2_flow.h b/drivers/net/octeontx2/otx2_flow.h
> index 30a823c8a..f8a19055b 100644
> --- a/drivers/net/octeontx2/otx2_flow.h
> +++ b/drivers/net/octeontx2/otx2_flow.h
> @@ -149,6 +149,11 @@ struct otx2_mcam_ents_info {
>         uint32_t live_ent;
>  };
>
> +struct otx2_flow_dump_data {
> +       uint8_t lid;
> +       uint16_t ltype;
> +};
> +
>  struct rte_flow {
>         uint8_t  nix_intf;
>         uint32_t  mcam_id;
> @@ -159,6 +164,8 @@ struct rte_flow {
>         uint64_t mcam_mask[OTX2_MAX_MCAM_WIDTH_DWORDS];
>         uint64_t npc_action;
>         uint64_t vtag_action;
> +       struct otx2_flow_dump_data dump_data[32];
> +       uint16_t num_patterns;
>         TAILQ_ENTRY(rte_flow) next;
>  };
>
> @@ -401,4 +408,7 @@ int otx2_flow_parse_actions(struct rte_eth_dev *dev,
>  int otx2_flow_free_all_resources(struct otx2_eth_dev *hw);
>
>  int otx2_flow_parse_mpls(struct otx2_parse_state *pst, int lid);
> +
> +void otx2_flow_dump(FILE *file, struct otx2_eth_dev *hw,
> +                   struct rte_flow *flow);
>  #endif /* __OTX2_FLOW_H__ */
> diff --git a/drivers/net/octeontx2/otx2_flow_dump.c b/drivers/net/octeontx2/otx2_flow_dump.c
> new file mode 100644
> index 000000000..d11ee3b28
> --- /dev/null
> +++ b/drivers/net/octeontx2/otx2_flow_dump.c
> @@ -0,0 +1,592 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2019 Marvell International Ltd.
> + */
> +
> +#include "otx2_ethdev.h"
> +#include "otx2_ethdev_sec.h"
> +#include "otx2_flow.h"
> +
> +#define NPC_MAX_FIELD_NAME_SIZE 80
> +#define NPC_RX_ACTIONOP_MASK           GENMASK(3, 0)
> +#define NPC_RX_ACTION_PFFUNC_MASK      GENMASK(19, 4)
> +#define NPC_RX_ACTION_INDEX_MASK       GENMASK(39, 20)
> +#define NPC_RX_ACTION_MATCH_MASK       GENMASK(55, 40)
> +#define NPC_RX_ACTION_FLOWKEY_MASK     GENMASK(60, 56)
> +
> +#define NPC_TX_ACTION_INDEX_MASK       GENMASK(31, 12)
> +#define NPC_TX_ACTION_MATCH_MASK       GENMASK(47, 32)
> +
> +#define NIX_RX_VTAGACT_VTAG0_RELPTR_MASK       GENMASK(7, 0)
> +#define NIX_RX_VTAGACT_VTAG0_LID_MASK          GENMASK(10, 8)
> +#define NIX_RX_VTAGACT_VTAG0_TYPE_MASK         GENMASK(14, 12)
> +#define NIX_RX_VTAGACT_VTAG0_VALID_MASK                BIT_ULL(15)
> +
> +#define NIX_RX_VTAGACT_VTAG1_RELPTR_MASK       GENMASK(39, 32)
> +#define NIX_RX_VTAGACT_VTAG1_LID_MASK          GENMASK(42, 40)
> +#define NIX_RX_VTAGACT_VTAG1_TYPE_MASK         GENMASK(46, 44)
> +#define NIX_RX_VTAGACT_VTAG1_VALID_MASK                BIT_ULL(47)
> +
> +#define NIX_TX_VTAGACT_VTAG0_RELPTR_MASK       GENMASK(7, 0)
> +#define NIX_TX_VTAGACT_VTAG0_LID_MASK          GENMASK(10, 8)
> +#define NIX_TX_VTAGACT_VTAG0_OP_MASK           GENMASK(13, 12)
> +#define NIX_TX_VTAGACT_VTAG0_DEF_MASK          GENMASK(25, 16)
> +
> +#define NIX_TX_VTAGACT_VTAG1_RELPTR_MASK       GENMASK(39, 32)
> +#define NIX_TX_VTAGACT_VTAG1_LID_MASK          GENMASK(42, 40)
> +#define NIX_TX_VTAGACT_VTAG1_OP_MASK           GENMASK(45, 44)
> +#define NIX_TX_VTAGACT_VTAG1_DEF_MASK          GENMASK(57, 48)
> +
> +struct npc_rx_parse_nibble_s {
> +       uint16_t chan         : 3;
> +       uint16_t errlev       : 1;
> +       uint16_t errcode      : 2;
> +       uint16_t l2l3bm       : 1;
> +       uint16_t laflags      : 2;
> +       uint16_t latype       : 1;
> +       uint16_t lbflags      : 2;
> +       uint16_t lbtype       : 1;
> +       uint16_t lcflags      : 2;
> +       uint16_t lctype       : 1;
> +       uint16_t ldflags      : 2;
> +       uint16_t ldtype       : 1;
> +       uint16_t leflags      : 2;
> +       uint16_t letype       : 1;
> +       uint16_t lfflags      : 2;
> +       uint16_t lftype       : 1;
> +       uint16_t lgflags      : 2;
> +       uint16_t lgtype       : 1;
> +       uint16_t lhflags      : 2;
> +       uint16_t lhtype       : 1;
> +} __rte_packed;
> +
> +const char *intf_str[] = {
> +       "NIX-RX",
> +       "NIX-TX",
> +};
> +
> +const char *ltype_str[NPC_MAX_LID][NPC_MAX_LT] = {
> +       [NPC_LID_LA][0] = "NONE",
> +       [NPC_LID_LA][NPC_LT_LA_ETHER] = "LA_ETHER",
> +       [NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER] = "LA_IH_NIX_ETHER",
> +       [NPC_LID_LA][NPC_LT_LA_HIGIG2_ETHER] = "LA_HIGIG2_ETHER",
> +       [NPC_LID_LA][NPC_LT_LA_IH_NIX_HIGIG2_ETHER] = "LA_IH_NIX_HIGIG2_ETHER",
> +       [NPC_LID_LB][0] = "NONE",
> +       [NPC_LID_LB][NPC_LT_LB_CTAG] = "LB_CTAG",
> +       [NPC_LID_LB][NPC_LT_LB_STAG_QINQ] = "LB_STAG_QINQ",
> +       [NPC_LID_LB][NPC_LT_LB_ETAG] = "LB_ETAG",
> +       [NPC_LID_LC][0] = "NONE",
> +       [NPC_LID_LC][NPC_LT_LC_IP] = "LC_IP",
> +       [NPC_LID_LC][NPC_LT_LC_IP6] = "LC_IP6",
> +       [NPC_LID_LC][NPC_LT_LC_ARP] = "LC_ARP",
> +       [NPC_LID_LC][NPC_LT_LC_IP6_EXT] = "LC_IP6_EXT",
> +       [NPC_LID_LD][0] = "NONE",
> +       [NPC_LID_LD][NPC_LT_LD_ICMP] = "LD_ICMP",
> +       [NPC_LID_LD][NPC_LT_LD_ICMP6] = "LD_ICMP6",
> +       [NPC_LID_LD][NPC_LT_LD_UDP] = "LD_UDP",
> +       [NPC_LID_LD][NPC_LT_LD_TCP] = "LD_TCP",
> +       [NPC_LID_LD][NPC_LT_LD_SCTP] = "LD_SCTP",
> +       [NPC_LID_LD][NPC_LT_LD_GRE] = "LD_GRE",
> +       [NPC_LID_LD][NPC_LT_LD_NVGRE] = "LD_NVGRE",
> +       [NPC_LID_LE][0] = "NONE",
> +       [NPC_LID_LE][NPC_LT_LE_VXLAN] = "LE_VXLAN",
> +       [NPC_LID_LE][NPC_LT_LE_ESP] = "LE_ESP",
> +       [NPC_LID_LE][NPC_LT_LE_GTPC] = "LE_GTPC",
> +       [NPC_LID_LE][NPC_LT_LE_GTPU] = "LE_GTPU",
> +       [NPC_LID_LE][NPC_LT_LE_GENEVE] = "LE_GENEVE",
> +       [NPC_LID_LE][NPC_LT_LE_VXLANGPE] = "LE_VXLANGPE",
> +       [NPC_LID_LF][0] = "NONE",
> +       [NPC_LID_LF][NPC_LT_LF_TU_ETHER] = "LF_TU_ETHER",
> +       [NPC_LID_LG][0] = "NONE",
> +       [NPC_LID_LG][NPC_LT_LG_TU_IP] = "LG_TU_IP",
> +       [NPC_LID_LG][NPC_LT_LG_TU_IP6] = "LG_TU_IP6",
> +       [NPC_LID_LH][0] = "NONE",
> +       [NPC_LID_LH][NPC_LT_LH_TU_UDP] = "LH_TU_UDP",
> +       [NPC_LID_LH][NPC_LT_LH_TU_TCP] = "LH_TU_TCP",
> +       [NPC_LID_LH][NPC_LT_LH_TU_SCTP] = "LH_TU_SCTP",
> +       [NPC_LID_LH][NPC_LT_LH_TU_ESP] = "LH_TU_ESP",
> +};
> +
> +static uint16_t
> +otx2_get_nibbles(struct rte_flow *flow, uint16_t size, uint32_t bit_offset)
> +{
> +       uint32_t byte_index, noffset;
> +       uint16_t data, mask;
> +       uint8_t *bytes;
> +
> +       bytes = (uint8_t *)flow->mcam_data;
> +       mask = (1ULL << (size * 4)) - 1;
> +       byte_index = bit_offset / 8;
> +       noffset = bit_offset % 8;
> +       data = *(uint16_t *)&bytes[byte_index];
> +       data >>= noffset;
> +       data &= mask;
> +
> +       return data;
> +}
> +
> +static void
> +otx2_flow_print_parse_nibbles(FILE *file, struct rte_flow *flow,
> +                             uint64_t parse_nibbles)
> +{
> +       struct npc_rx_parse_nibble_s *rx_parse;
> +       uint32_t data, offset = 0;
> +
> +       rx_parse = (struct npc_rx_parse_nibble_s *)&parse_nibbles;
> +
> +       if (rx_parse->chan) {
> +               data = otx2_get_nibbles(flow, 3, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_CHAN:%#03X\n", data);
> +               offset += 12;
> +       }
> +
> +       if (rx_parse->errlev) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_ERRLEV:%#X\n", data);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->errcode) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_ERRCODE:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->l2l3bm) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_L2L3_BCAST:%#X\n", data);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->latype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LA][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->laflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LA_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->lbtype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LB][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->lbflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LB_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->lctype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LC][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->lcflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LC_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->ldtype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LD][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->ldflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LD_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->letype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LE][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->leflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LE_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->lftype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LF][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->lfflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LF_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->lgtype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LG][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->lgflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LG_FLAGS:%#02X\n", data);
> +               offset += 8;
> +       }
> +
> +       if (rx_parse->lhtype) {
> +               data = otx2_get_nibbles(flow, 1, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n",
> +                       ltype_str[NPC_LID_LH][data]);
> +               offset += 4;
> +       }
> +
> +       if (rx_parse->lhflags) {
> +               data = otx2_get_nibbles(flow, 2, offset);
> +               fprintf(file, "\tNPC_PARSE_NIBBLE_LH_FLAGS:%#02X\n", data);
> +       }
> +}
> +
> +static void
> +otx2_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo,
> +                          struct rte_flow *flow, int lid, int lt)
> +{
> +       uint8_t *datastart, *maskstart;
> +       int i;
> +
> +       datastart = (uint8_t *)&flow->mcam_data + lfinfo->key_off;
> +       maskstart = (uint8_t *)&flow->mcam_mask + lfinfo->key_off;
> +
> +       fprintf(file, "\t%s, hdr offset:%#X, len:%#X, key offset:%#X, ",
> +               ltype_str[lid][lt], lfinfo->hdr_off,
> +               lfinfo->len, lfinfo->key_off);
> +
> +       fprintf(file, "Data:0X");
> +       for (i = lfinfo->len - 1; i >= 0; i--)
> +               fprintf(file, "%02X", datastart[i]);
> +
> +       fprintf(file, ", ");
> +
> +       fprintf(file, "Mask:0X");
> +
> +       for (i = lfinfo->len - 1; i >= 0; i--)
> +               fprintf(file, "%02X", maskstart[i]);
> +
> +       fprintf(file, "\n");
> +}
> +
> +static void
> +otx2_flow_print_item(FILE *file, struct otx2_eth_dev *hw,
> +                    struct npc_xtract_info *xinfo, struct rte_flow *flow,
> +                    int intf, int lid, int lt, int ld)
> +{
> +       struct otx2_npc_flow_info *npc_flow = &hw->npc_flow;
> +       struct npc_xtract_info *lflags_info;
> +       int i, lf_cfg;
> +
> +       otx2_flow_print_xtractinfo(file, xinfo, flow, lid, lt);
> +
> +       if (xinfo->flags_enable) {
> +               lf_cfg = npc_flow->prx_lfcfg[ld].i;
> +
> +               if (lf_cfg == lid) {
> +                       for (i = 0; i < NPC_MAX_LFL; i++) {
> +                               lflags_info = npc_flow->prx_fxcfg[intf]
> +                                                       [ld][i].xtract;
> +
> +                               otx2_flow_print_xtractinfo(file, lflags_info,
> +                                                          flow, lid, lt);
> +                       }
> +               }
> +       }
> +}
> +
> +static void
> +otx2_flow_dump_patterns(FILE *file, struct otx2_eth_dev *hw,
> +                       struct rte_flow *flow)
> +{
> +       struct otx2_npc_flow_info *npc_flow = &hw->npc_flow;
> +       struct npc_lid_lt_xtract_info *lt_xinfo;
> +       struct npc_xtract_info *xinfo;
> +       uint32_t intf, lid, ld, i;
> +       uint64_t parse_nibbles;
> +       uint16_t ltype;
> +
> +       intf = flow->nix_intf;
> +       parse_nibbles = npc_flow->keyx_supp_nmask[intf];
> +       otx2_flow_print_parse_nibbles(file, flow, parse_nibbles);
> +
> +       for (i = 0; i < flow->num_patterns; i++) {
> +               lid = flow->dump_data[i].lid;
> +               ltype = flow->dump_data[i].ltype;
> +               lt_xinfo = &npc_flow->prx_dxcfg[intf][lid][ltype];
> +
> +               for (ld = 0; ld < NPC_MAX_LD; ld++) {
> +                       xinfo = &lt_xinfo->xtract[ld];
> +                       if (!xinfo->enable)
> +                               continue;
> +                       otx2_flow_print_item(file, hw, xinfo, flow, intf, lid,
> +                                            ltype, ld);
> +               }
> +       }
> +}
> +
> +static void
> +otx2_flow_dump_tx_action(FILE *file, uint64_t npc_action)
> +{
> +       char index_name[NPC_MAX_FIELD_NAME_SIZE] = "Index:";
> +       uint32_t tx_op, index, match_id;
> +
> +       tx_op = npc_action & NPC_RX_ACTIONOP_MASK;
> +
> +       fprintf(file, "\tActionOp:");
> +
> +       switch (tx_op) {
> +       case NIX_TX_ACTIONOP_DROP:
> +               fprintf(file, "NIX_TX_ACTIONOP_DROP (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_DROP);
> +               break;
> +       case NIX_TX_ACTIONOP_UCAST_DEFAULT:
> +               fprintf(file, "NIX_TX_ACTIONOP_UCAST_DEFAULT (%lu)\n",
> +                       (uint64_t)NIX_TX_ACTIONOP_UCAST_DEFAULT);
> +               break;
> +       case NIX_TX_ACTIONOP_UCAST_CHAN:
> +               fprintf(file, "NIX_TX_ACTIONOP_UCAST_DEFAULT (%lu)\n",
> +                       (uint64_t)NIX_TX_ACTIONOP_UCAST_CHAN);
> +               strncpy(index_name, "Transmit Channel:",
> +                       NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       case NIX_TX_ACTIONOP_MCAST:
> +               fprintf(file, "NIX_TX_ACTIONOP_MCAST (%lu)\n",
> +                       (uint64_t)NIX_TX_ACTIONOP_MCAST);
> +               strncpy(index_name, "Multicast Table Index:",
> +                       NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       case NIX_TX_ACTIONOP_DROP_VIOL:
> +               fprintf(file, "NIX_TX_ACTIONOP_DROP_VIOL (%lu)\n",
> +                       (uint64_t)NIX_TX_ACTIONOP_DROP_VIOL);
> +               break;
> +       }
> +
> +       index = ((npc_action & NPC_TX_ACTION_INDEX_MASK) >> 12) & 0xFFFFF;
> +
> +       fprintf(file, "\t%s:%#05X\n", index_name, index);
> +
> +       match_id = ((npc_action & NPC_TX_ACTION_MATCH_MASK) >> 32) & 0xFFFF;
> +
> +       fprintf(file, "\tMatch Id:%#04X\n", match_id);
> +}
> +
> +static void
> +otx2_flow_dump_rx_action(FILE *file, uint64_t npc_action)
> +{
> +       uint32_t rx_op, pf_func, index, match_id, flowkey_alg;
> +       char index_name[NPC_MAX_FIELD_NAME_SIZE] = "Index:";
> +
> +       rx_op = npc_action & NPC_RX_ACTIONOP_MASK;
> +
> +       fprintf(file, "\tActionOp:");
> +
> +       switch (rx_op) {
> +       case NIX_RX_ACTIONOP_DROP:
> +               fprintf(file, "NIX_RX_ACTIONOP_DROP (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_DROP);
> +               break;
> +       case NIX_RX_ACTIONOP_UCAST:
> +               fprintf(file, "NIX_RX_ACTIONOP_UCAST (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_UCAST);
> +               strncpy(index_name, "RQ Index", NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       case NIX_RX_ACTIONOP_UCAST_IPSEC:
> +               fprintf(file, "NIX_RX_ACTIONOP_UCAST_IPSEC (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_UCAST_IPSEC);
> +               strncpy(index_name, "RQ Index:", NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       case NIX_RX_ACTIONOP_MCAST:
> +               fprintf(file, "NIX_RX_ACTIONOP_MCAST (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_MCAST);
> +               strncpy(index_name, "Multicast/mirror table index",
> +                       NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       case NIX_RX_ACTIONOP_RSS:
> +               fprintf(file, "NIX_RX_ACTIONOP_RSS (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_RSS);
> +               strncpy(index_name, "RSS Group Index",
> +                       NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       case NIX_RX_ACTIONOP_PF_FUNC_DROP:
> +               fprintf(file, "NIX_RX_ACTIONOP_PF_FUNC_DROP (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_PF_FUNC_DROP);
> +               break;
> +       case NIX_RX_ACTIONOP_MIRROR:
> +               fprintf(file, "NIX_RX_ACTIONOP_MIRROR (%lu)\n",
> +                       (uint64_t)NIX_RX_ACTIONOP_MIRROR);
> +               strncpy(index_name, "Multicast/mirror table index",
> +                       NPC_MAX_FIELD_NAME_SIZE);
> +               break;
> +       }
> +
> +       pf_func = ((npc_action & NPC_RX_ACTION_PFFUNC_MASK) >> 4) & 0xFFFF;
> +
> +       fprintf(file, "\tPF_FUNC: %#04X\n", pf_func);
> +
> +       index = ((npc_action & NPC_RX_ACTION_INDEX_MASK) >> 20) & 0xFFFFF;
> +
> +       fprintf(file, "\t%s:%#05X\n", index_name, index);
> +
> +       match_id = ((npc_action & NPC_RX_ACTION_MATCH_MASK) >> 40) & 0xFFFF;
> +
> +       fprintf(file, "\tMatch Id:%#04X\n", match_id);
> +
> +       flowkey_alg = ((npc_action & NPC_RX_ACTION_FLOWKEY_MASK) >> 56) & 0x1F;
> +
> +       fprintf(file, "\tFlow Key Alg:%#X\n", flowkey_alg);
> +}
> +
> +static void
> +otx2_flow_dump_parsed_action(FILE *file, uint64_t npc_action, bool is_rx)
> +{
> +       if (is_rx) {
> +               fprintf(file, "NPC RX Action:%#016lX\n", npc_action);
> +               otx2_flow_dump_rx_action(file, npc_action);
> +       } else {
> +               fprintf(file, "NPC TX Action:%#016lX\n", npc_action);
> +               otx2_flow_dump_tx_action(file, npc_action);
> +       }
> +}
> +
> +static void
> +otx2_flow_dump_rx_vtag_action(FILE *file, uint64_t vtag_action)
> +{
> +       uint32_t type, lid, relptr;
> +
> +       if (vtag_action & NIX_RX_VTAGACT_VTAG0_VALID_MASK) {
> +               relptr = vtag_action & NIX_RX_VTAGACT_VTAG0_RELPTR_MASK;
> +               lid = ((vtag_action & NIX_RX_VTAGACT_VTAG0_LID_MASK) >> 8)
> +                       & 0x7;
> +               type = ((vtag_action & NIX_RX_VTAGACT_VTAG0_TYPE_MASK) >> 12)
> +                       & 0x7;
> +
> +               fprintf(file, "\tVTAG0:relptr:%#X\n", relptr);
> +               fprintf(file, "\tlid:%#X\n", lid);
> +               fprintf(file, "\ttype:%#X\n", type);
> +       }
> +
> +       if (vtag_action & NIX_RX_VTAGACT_VTAG1_VALID_MASK) {
> +               relptr = ((vtag_action & NIX_RX_VTAGACT_VTAG1_RELPTR_MASK)
> +                          >> 32) & 0xFF;
> +               lid = ((vtag_action & NIX_RX_VTAGACT_VTAG1_LID_MASK) >> 40)
> +                       & 0x7;
> +               type = ((vtag_action & NIX_RX_VTAGACT_VTAG1_TYPE_MASK) >> 44)
> +                       & 0x7;
> +
> +               fprintf(file, "\tVTAG1:relptr:%#X\n", relptr);
> +               fprintf(file, "\tlid:%#X\n", lid);
> +               fprintf(file, "\ttype:%#X\n", type);
> +       }
> +}
> +
> +static void
> +otx2_get_vtag_opname(uint32_t op, char *opname, int len)
> +{
> +       switch (op) {
> +       case 0x0:
> +               strncpy(opname, "NOP", len - 1);
> +               break;
> +       case 0x1:
> +               strncpy(opname, "INSERT", len - 1);
> +               break;
> +       case 0x2:
> +               strncpy(opname, "REPLACE", len - 1);
> +               break;
> +       }
> +}
> +
> +static void
> +otx2_flow_dump_tx_vtag_action(FILE *file, uint64_t vtag_action)
> +{
> +       uint32_t relptr, lid, op, vtag_def;
> +       char opname[10];
> +
> +       relptr = vtag_action & NIX_TX_VTAGACT_VTAG0_RELPTR_MASK;
> +       lid = ((vtag_action & NIX_TX_VTAGACT_VTAG0_LID_MASK) >> 8) & 0x7;
> +       op = ((vtag_action & NIX_TX_VTAGACT_VTAG0_OP_MASK) >> 12) & 0x3;
> +       vtag_def = ((vtag_action & NIX_TX_VTAGACT_VTAG0_DEF_MASK) >> 16)
> +                  & 0x3FF;
> +
> +       otx2_get_vtag_opname(op, opname, sizeof(opname));
> +
> +       fprintf(file, "\tVTAG0 relptr:%#X\n", relptr);
> +       fprintf(file, "\tlid:%#X\n", lid);
> +       fprintf(file, "\top:%s\n", opname);
> +       fprintf(file, "\tvtag_def:%#X\n", vtag_def);
> +
> +       relptr = ((vtag_action & NIX_TX_VTAGACT_VTAG1_RELPTR_MASK) >> 32)
> +                & 0xFF;
> +       lid = ((vtag_action & NIX_TX_VTAGACT_VTAG1_LID_MASK) >> 40) & 0x7;
> +       op = ((vtag_action & NIX_TX_VTAGACT_VTAG1_OP_MASK) >> 44) & 0x3;
> +       vtag_def = ((vtag_action & NIX_TX_VTAGACT_VTAG1_DEF_MASK) >> 48)
> +                  & 0x3FF;
> +
> +       otx2_get_vtag_opname(op, opname, sizeof(opname));
> +
> +       fprintf(file, "\tVTAG1:relptr:%#X\n", relptr);
> +       fprintf(file, "\tlid:%#X\n", lid);
> +       fprintf(file, "\top:%s\n", opname);
> +       fprintf(file, "\tvtag_def:%#X\n", vtag_def);
> +}
> +
> +static void
> +otx2_flow_dump_vtag_action(FILE *file, uint64_t vtag_action, bool is_rx)
> +{
> +       if (is_rx) {
> +               fprintf(file, "NPC RX VTAG Action:%#016lX\n", vtag_action);
> +               otx2_flow_dump_rx_vtag_action(file, vtag_action);
> +       } else {
> +               fprintf(file, "NPC TX VTAG Action:%#016lX\n", vtag_action);
> +               otx2_flow_dump_tx_vtag_action(file, vtag_action);
> +       }
> +}
> +
> +void
> +otx2_flow_dump(FILE *file, struct otx2_eth_dev *hw, struct rte_flow *flow)
> +{
> +       bool is_rx = 0;
> +       int i;
> +
> +       fprintf(file, "MCAM Index:%d\n", flow->mcam_id);
> +       fprintf(file, "Interface :%s (%d)\n", intf_str[flow->nix_intf],
> +               flow->nix_intf);
> +       fprintf(file, "Priority  :%d\n", flow->priority);
> +
> +       if (flow->nix_intf == NIX_INTF_RX)
> +               is_rx = 1;
> +
> +       otx2_flow_dump_parsed_action(file, flow->npc_action, is_rx);
> +       otx2_flow_dump_vtag_action(file, flow->vtag_action, is_rx);
> +       fprintf(file, "Patterns:\n");
> +       otx2_flow_dump_patterns(file, hw, flow);
> +
> +       fprintf(file, "MCAM Raw Data :\n");
> +
> +       for (i = 0; i < OTX2_MAX_MCAM_WIDTH_DWORDS; i++)  {
> +               fprintf(file, "\tDW%d     :%016lX\n", i, flow->mcam_data[i]);
> +               fprintf(file, "\tDW%d_Mask:%016lX\n", i, flow->mcam_mask[i]);
> +       }
> +
> +       fprintf(file, "\n");
> +}
> diff --git a/drivers/net/octeontx2/otx2_flow_utils.c b/drivers/net/octeontx2/otx2_flow_utils.c
> index 7ed86ba74..d5f0645dc 100644
> --- a/drivers/net/octeontx2/otx2_flow_utils.c
> +++ b/drivers/net/octeontx2/otx2_flow_utils.c
> @@ -271,6 +271,7 @@ otx2_flow_update_parse_state(struct otx2_parse_state *pst,
>                              uint8_t flags)
>  {
>         struct npc_lid_lt_xtract_info *xinfo;
> +       struct otx2_flow_dump_data *dump;
>         struct npc_xtract_info *lfinfo;
>         int intf, lf_cfg;
>         int i, j, rc = 0;
> @@ -320,6 +321,9 @@ otx2_flow_update_parse_state(struct otx2_parse_state *pst,
>         }
>
>  done:
> +       dump = &pst->flow->dump_data[pst->flow->num_patterns++];
> +       dump->lid = lid;
> +       dump->ltype = lt;
>         /* Next pattern to parse by subsequent layers */
>         pst->pattern++;
>         return 0;
> --
> 2.25.4
>
diff mbox series

Patch

diff --git a/drivers/net/octeontx2/meson.build b/drivers/net/octeontx2/meson.build
index e2c139a8b..779a75b5d 100644
--- a/drivers/net/octeontx2/meson.build
+++ b/drivers/net/octeontx2/meson.build
@@ -28,6 +28,7 @@  sources = files('otx2_rx.c',
 		'otx2_lookup.c',
 		'otx2_ethdev.c',
 		'otx2_flow_ctrl.c',
+		'otx2_flow_dump.c',
 		'otx2_flow_parse.c',
 		'otx2_flow_utils.c',
 		'otx2_ethdev_irq.c',
diff --git a/drivers/net/octeontx2/otx2_flow.c b/drivers/net/octeontx2/otx2_flow.c
index a5900f349..14ac9bc76 100644
--- a/drivers/net/octeontx2/otx2_flow.c
+++ b/drivers/net/octeontx2/otx2_flow.c
@@ -805,6 +805,38 @@  otx2_flow_query(struct rte_eth_dev *dev,
 	return -rte_errno;
 }
 
+static int
+otx2_flow_dev_dump(struct rte_eth_dev *dev,
+		  FILE *file,
+		  struct rte_flow_error *error)
+{
+	struct otx2_eth_dev *hw = dev->data->dev_private;
+	struct otx2_flow_list *list;
+	struct rte_flow *flow_iter;
+	uint32_t max_prio, i;
+
+	if (file == NULL) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "Invalid file");
+		return -EINVAL;
+	}
+
+	max_prio = hw->npc_flow.flow_max_priority;
+
+	for (i = 0; i < max_prio; i++) {
+		list = &hw->npc_flow.flow_list[i];
+
+		/* List in ascending order of mcam entries */
+		TAILQ_FOREACH(flow_iter, list, next) {
+			otx2_flow_dump(file, hw, flow_iter);
+		}
+	}
+
+	return 0;
+}
+
 const struct rte_flow_ops otx2_flow_ops = {
 	.validate = otx2_flow_validate,
 	.create = otx2_flow_create,
@@ -812,6 +844,7 @@  const struct rte_flow_ops otx2_flow_ops = {
 	.flush = otx2_flow_flush,
 	.query = otx2_flow_query,
 	.isolate = otx2_flow_isolate,
+	.dev_dump = otx2_flow_dev_dump,
 };
 
 static int
diff --git a/drivers/net/octeontx2/otx2_flow.h b/drivers/net/octeontx2/otx2_flow.h
index 30a823c8a..f8a19055b 100644
--- a/drivers/net/octeontx2/otx2_flow.h
+++ b/drivers/net/octeontx2/otx2_flow.h
@@ -149,6 +149,11 @@  struct otx2_mcam_ents_info {
 	uint32_t live_ent;
 };
 
+struct otx2_flow_dump_data {
+	uint8_t lid;
+	uint16_t ltype;
+};
+
 struct rte_flow {
 	uint8_t  nix_intf;
 	uint32_t  mcam_id;
@@ -159,6 +164,8 @@  struct rte_flow {
 	uint64_t mcam_mask[OTX2_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t npc_action;
 	uint64_t vtag_action;
+	struct otx2_flow_dump_data dump_data[32];
+	uint16_t num_patterns;
 	TAILQ_ENTRY(rte_flow) next;
 };
 
@@ -401,4 +408,7 @@  int otx2_flow_parse_actions(struct rte_eth_dev *dev,
 int otx2_flow_free_all_resources(struct otx2_eth_dev *hw);
 
 int otx2_flow_parse_mpls(struct otx2_parse_state *pst, int lid);
+
+void otx2_flow_dump(FILE *file, struct otx2_eth_dev *hw,
+		    struct rte_flow *flow);
 #endif /* __OTX2_FLOW_H__ */
diff --git a/drivers/net/octeontx2/otx2_flow_dump.c b/drivers/net/octeontx2/otx2_flow_dump.c
new file mode 100644
index 000000000..d11ee3b28
--- /dev/null
+++ b/drivers/net/octeontx2/otx2_flow_dump.c
@@ -0,0 +1,592 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2019 Marvell International Ltd.
+ */
+
+#include "otx2_ethdev.h"
+#include "otx2_ethdev_sec.h"
+#include "otx2_flow.h"
+
+#define NPC_MAX_FIELD_NAME_SIZE 80
+#define NPC_RX_ACTIONOP_MASK		GENMASK(3, 0)
+#define NPC_RX_ACTION_PFFUNC_MASK	GENMASK(19, 4)
+#define NPC_RX_ACTION_INDEX_MASK	GENMASK(39, 20)
+#define NPC_RX_ACTION_MATCH_MASK	GENMASK(55, 40)
+#define NPC_RX_ACTION_FLOWKEY_MASK	GENMASK(60, 56)
+
+#define NPC_TX_ACTION_INDEX_MASK	GENMASK(31, 12)
+#define NPC_TX_ACTION_MATCH_MASK	GENMASK(47, 32)
+
+#define NIX_RX_VTAGACT_VTAG0_RELPTR_MASK	GENMASK(7, 0)
+#define NIX_RX_VTAGACT_VTAG0_LID_MASK		GENMASK(10, 8)
+#define NIX_RX_VTAGACT_VTAG0_TYPE_MASK		GENMASK(14, 12)
+#define NIX_RX_VTAGACT_VTAG0_VALID_MASK		BIT_ULL(15)
+
+#define NIX_RX_VTAGACT_VTAG1_RELPTR_MASK	GENMASK(39, 32)
+#define NIX_RX_VTAGACT_VTAG1_LID_MASK		GENMASK(42, 40)
+#define NIX_RX_VTAGACT_VTAG1_TYPE_MASK		GENMASK(46, 44)
+#define NIX_RX_VTAGACT_VTAG1_VALID_MASK		BIT_ULL(47)
+
+#define NIX_TX_VTAGACT_VTAG0_RELPTR_MASK	GENMASK(7, 0)
+#define NIX_TX_VTAGACT_VTAG0_LID_MASK		GENMASK(10, 8)
+#define NIX_TX_VTAGACT_VTAG0_OP_MASK		GENMASK(13, 12)
+#define NIX_TX_VTAGACT_VTAG0_DEF_MASK		GENMASK(25, 16)
+
+#define NIX_TX_VTAGACT_VTAG1_RELPTR_MASK	GENMASK(39, 32)
+#define NIX_TX_VTAGACT_VTAG1_LID_MASK		GENMASK(42, 40)
+#define NIX_TX_VTAGACT_VTAG1_OP_MASK		GENMASK(45, 44)
+#define NIX_TX_VTAGACT_VTAG1_DEF_MASK		GENMASK(57, 48)
+
+struct npc_rx_parse_nibble_s {
+	uint16_t chan         : 3;
+	uint16_t errlev       : 1;
+	uint16_t errcode      : 2;
+	uint16_t l2l3bm       : 1;
+	uint16_t laflags      : 2;
+	uint16_t latype       : 1;
+	uint16_t lbflags      : 2;
+	uint16_t lbtype       : 1;
+	uint16_t lcflags      : 2;
+	uint16_t lctype       : 1;
+	uint16_t ldflags      : 2;
+	uint16_t ldtype       : 1;
+	uint16_t leflags      : 2;
+	uint16_t letype       : 1;
+	uint16_t lfflags      : 2;
+	uint16_t lftype       : 1;
+	uint16_t lgflags      : 2;
+	uint16_t lgtype       : 1;
+	uint16_t lhflags      : 2;
+	uint16_t lhtype       : 1;
+} __rte_packed;
+
+const char *intf_str[] = {
+	"NIX-RX",
+	"NIX-TX",
+};
+
+const char *ltype_str[NPC_MAX_LID][NPC_MAX_LT] = {
+	[NPC_LID_LA][0] = "NONE",
+	[NPC_LID_LA][NPC_LT_LA_ETHER] = "LA_ETHER",
+	[NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER] = "LA_IH_NIX_ETHER",
+	[NPC_LID_LA][NPC_LT_LA_HIGIG2_ETHER] = "LA_HIGIG2_ETHER",
+	[NPC_LID_LA][NPC_LT_LA_IH_NIX_HIGIG2_ETHER] = "LA_IH_NIX_HIGIG2_ETHER",
+	[NPC_LID_LB][0] = "NONE",
+	[NPC_LID_LB][NPC_LT_LB_CTAG] = "LB_CTAG",
+	[NPC_LID_LB][NPC_LT_LB_STAG_QINQ] = "LB_STAG_QINQ",
+	[NPC_LID_LB][NPC_LT_LB_ETAG] = "LB_ETAG",
+	[NPC_LID_LC][0] = "NONE",
+	[NPC_LID_LC][NPC_LT_LC_IP] = "LC_IP",
+	[NPC_LID_LC][NPC_LT_LC_IP6] = "LC_IP6",
+	[NPC_LID_LC][NPC_LT_LC_ARP] = "LC_ARP",
+	[NPC_LID_LC][NPC_LT_LC_IP6_EXT] = "LC_IP6_EXT",
+	[NPC_LID_LD][0] = "NONE",
+	[NPC_LID_LD][NPC_LT_LD_ICMP] = "LD_ICMP",
+	[NPC_LID_LD][NPC_LT_LD_ICMP6] = "LD_ICMP6",
+	[NPC_LID_LD][NPC_LT_LD_UDP] = "LD_UDP",
+	[NPC_LID_LD][NPC_LT_LD_TCP] = "LD_TCP",
+	[NPC_LID_LD][NPC_LT_LD_SCTP] = "LD_SCTP",
+	[NPC_LID_LD][NPC_LT_LD_GRE] = "LD_GRE",
+	[NPC_LID_LD][NPC_LT_LD_NVGRE] = "LD_NVGRE",
+	[NPC_LID_LE][0] = "NONE",
+	[NPC_LID_LE][NPC_LT_LE_VXLAN] = "LE_VXLAN",
+	[NPC_LID_LE][NPC_LT_LE_ESP] = "LE_ESP",
+	[NPC_LID_LE][NPC_LT_LE_GTPC] = "LE_GTPC",
+	[NPC_LID_LE][NPC_LT_LE_GTPU] = "LE_GTPU",
+	[NPC_LID_LE][NPC_LT_LE_GENEVE] = "LE_GENEVE",
+	[NPC_LID_LE][NPC_LT_LE_VXLANGPE] = "LE_VXLANGPE",
+	[NPC_LID_LF][0] = "NONE",
+	[NPC_LID_LF][NPC_LT_LF_TU_ETHER] = "LF_TU_ETHER",
+	[NPC_LID_LG][0] = "NONE",
+	[NPC_LID_LG][NPC_LT_LG_TU_IP] = "LG_TU_IP",
+	[NPC_LID_LG][NPC_LT_LG_TU_IP6] = "LG_TU_IP6",
+	[NPC_LID_LH][0] = "NONE",
+	[NPC_LID_LH][NPC_LT_LH_TU_UDP] = "LH_TU_UDP",
+	[NPC_LID_LH][NPC_LT_LH_TU_TCP] = "LH_TU_TCP",
+	[NPC_LID_LH][NPC_LT_LH_TU_SCTP] = "LH_TU_SCTP",
+	[NPC_LID_LH][NPC_LT_LH_TU_ESP] = "LH_TU_ESP",
+};
+
+static uint16_t
+otx2_get_nibbles(struct rte_flow *flow, uint16_t size, uint32_t bit_offset)
+{
+	uint32_t byte_index, noffset;
+	uint16_t data, mask;
+	uint8_t *bytes;
+
+	bytes = (uint8_t *)flow->mcam_data;
+	mask = (1ULL << (size * 4)) - 1;
+	byte_index = bit_offset / 8;
+	noffset = bit_offset % 8;
+	data = *(uint16_t *)&bytes[byte_index];
+	data >>= noffset;
+	data &= mask;
+
+	return data;
+}
+
+static void
+otx2_flow_print_parse_nibbles(FILE *file, struct rte_flow *flow,
+			      uint64_t parse_nibbles)
+{
+	struct npc_rx_parse_nibble_s *rx_parse;
+	uint32_t data, offset = 0;
+
+	rx_parse = (struct npc_rx_parse_nibble_s *)&parse_nibbles;
+
+	if (rx_parse->chan) {
+		data = otx2_get_nibbles(flow, 3, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_CHAN:%#03X\n", data);
+		offset += 12;
+	}
+
+	if (rx_parse->errlev) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRLEV:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse->errcode) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRCODE:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->l2l3bm) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_L2L3_BCAST:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse->latype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n",
+			ltype_str[NPC_LID_LA][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->laflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->lbtype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n",
+			ltype_str[NPC_LID_LB][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->lbflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->lctype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n",
+			ltype_str[NPC_LID_LC][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->lcflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->ldtype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n",
+			ltype_str[NPC_LID_LD][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->ldflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->letype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n",
+			ltype_str[NPC_LID_LE][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->leflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->lftype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n",
+			ltype_str[NPC_LID_LF][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->lfflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->lgtype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n",
+			ltype_str[NPC_LID_LG][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->lgflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse->lhtype) {
+		data = otx2_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n",
+			ltype_str[NPC_LID_LH][data]);
+		offset += 4;
+	}
+
+	if (rx_parse->lhflags) {
+		data = otx2_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_FLAGS:%#02X\n", data);
+	}
+}
+
+static void
+otx2_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo,
+			   struct rte_flow *flow, int lid, int lt)
+{
+	uint8_t *datastart, *maskstart;
+	int i;
+
+	datastart = (uint8_t *)&flow->mcam_data + lfinfo->key_off;
+	maskstart = (uint8_t *)&flow->mcam_mask + lfinfo->key_off;
+
+	fprintf(file, "\t%s, hdr offset:%#X, len:%#X, key offset:%#X, ",
+		ltype_str[lid][lt], lfinfo->hdr_off,
+		lfinfo->len, lfinfo->key_off);
+
+	fprintf(file, "Data:0X");
+	for (i = lfinfo->len - 1; i >= 0; i--)
+		fprintf(file, "%02X", datastart[i]);
+
+	fprintf(file, ", ");
+
+	fprintf(file, "Mask:0X");
+
+	for (i = lfinfo->len - 1; i >= 0; i--)
+		fprintf(file, "%02X", maskstart[i]);
+
+	fprintf(file, "\n");
+}
+
+static void
+otx2_flow_print_item(FILE *file, struct otx2_eth_dev *hw,
+		     struct npc_xtract_info *xinfo, struct rte_flow *flow,
+		     int intf, int lid, int lt, int ld)
+{
+	struct otx2_npc_flow_info *npc_flow = &hw->npc_flow;
+	struct npc_xtract_info *lflags_info;
+	int i, lf_cfg;
+
+	otx2_flow_print_xtractinfo(file, xinfo, flow, lid, lt);
+
+	if (xinfo->flags_enable) {
+		lf_cfg = npc_flow->prx_lfcfg[ld].i;
+
+		if (lf_cfg == lid) {
+			for (i = 0; i < NPC_MAX_LFL; i++) {
+				lflags_info = npc_flow->prx_fxcfg[intf]
+							[ld][i].xtract;
+
+				otx2_flow_print_xtractinfo(file, lflags_info,
+							   flow, lid, lt);
+			}
+		}
+	}
+}
+
+static void
+otx2_flow_dump_patterns(FILE *file, struct otx2_eth_dev *hw,
+			struct rte_flow *flow)
+{
+	struct otx2_npc_flow_info *npc_flow = &hw->npc_flow;
+	struct npc_lid_lt_xtract_info *lt_xinfo;
+	struct npc_xtract_info *xinfo;
+	uint32_t intf, lid, ld, i;
+	uint64_t parse_nibbles;
+	uint16_t ltype;
+
+	intf = flow->nix_intf;
+	parse_nibbles = npc_flow->keyx_supp_nmask[intf];
+	otx2_flow_print_parse_nibbles(file, flow, parse_nibbles);
+
+	for (i = 0; i < flow->num_patterns; i++) {
+		lid = flow->dump_data[i].lid;
+		ltype = flow->dump_data[i].ltype;
+		lt_xinfo = &npc_flow->prx_dxcfg[intf][lid][ltype];
+
+		for (ld = 0; ld < NPC_MAX_LD; ld++) {
+			xinfo = &lt_xinfo->xtract[ld];
+			if (!xinfo->enable)
+				continue;
+			otx2_flow_print_item(file, hw, xinfo, flow, intf, lid,
+					     ltype, ld);
+		}
+	}
+}
+
+static void
+otx2_flow_dump_tx_action(FILE *file, uint64_t npc_action)
+{
+	char index_name[NPC_MAX_FIELD_NAME_SIZE] = "Index:";
+	uint32_t tx_op, index, match_id;
+
+	tx_op = npc_action & NPC_RX_ACTIONOP_MASK;
+
+	fprintf(file, "\tActionOp:");
+
+	switch (tx_op) {
+	case NIX_TX_ACTIONOP_DROP:
+		fprintf(file, "NIX_TX_ACTIONOP_DROP (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_DROP);
+		break;
+	case NIX_TX_ACTIONOP_UCAST_DEFAULT:
+		fprintf(file, "NIX_TX_ACTIONOP_UCAST_DEFAULT (%lu)\n",
+			(uint64_t)NIX_TX_ACTIONOP_UCAST_DEFAULT);
+		break;
+	case NIX_TX_ACTIONOP_UCAST_CHAN:
+		fprintf(file, "NIX_TX_ACTIONOP_UCAST_DEFAULT (%lu)\n",
+			(uint64_t)NIX_TX_ACTIONOP_UCAST_CHAN);
+		strncpy(index_name, "Transmit Channel:",
+			NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	case NIX_TX_ACTIONOP_MCAST:
+		fprintf(file, "NIX_TX_ACTIONOP_MCAST (%lu)\n",
+			(uint64_t)NIX_TX_ACTIONOP_MCAST);
+		strncpy(index_name, "Multicast Table Index:",
+			NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	case NIX_TX_ACTIONOP_DROP_VIOL:
+		fprintf(file, "NIX_TX_ACTIONOP_DROP_VIOL (%lu)\n",
+			(uint64_t)NIX_TX_ACTIONOP_DROP_VIOL);
+		break;
+	}
+
+	index = ((npc_action & NPC_TX_ACTION_INDEX_MASK) >> 12) & 0xFFFFF;
+
+	fprintf(file, "\t%s:%#05X\n", index_name, index);
+
+	match_id = ((npc_action & NPC_TX_ACTION_MATCH_MASK) >> 32) & 0xFFFF;
+
+	fprintf(file, "\tMatch Id:%#04X\n", match_id);
+}
+
+static void
+otx2_flow_dump_rx_action(FILE *file, uint64_t npc_action)
+{
+	uint32_t rx_op, pf_func, index, match_id, flowkey_alg;
+	char index_name[NPC_MAX_FIELD_NAME_SIZE] = "Index:";
+
+	rx_op = npc_action & NPC_RX_ACTIONOP_MASK;
+
+	fprintf(file, "\tActionOp:");
+
+	switch (rx_op) {
+	case NIX_RX_ACTIONOP_DROP:
+		fprintf(file, "NIX_RX_ACTIONOP_DROP (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_DROP);
+		break;
+	case NIX_RX_ACTIONOP_UCAST:
+		fprintf(file, "NIX_RX_ACTIONOP_UCAST (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_UCAST);
+		strncpy(index_name, "RQ Index", NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	case NIX_RX_ACTIONOP_UCAST_IPSEC:
+		fprintf(file, "NIX_RX_ACTIONOP_UCAST_IPSEC (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_UCAST_IPSEC);
+		strncpy(index_name, "RQ Index:", NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	case NIX_RX_ACTIONOP_MCAST:
+		fprintf(file, "NIX_RX_ACTIONOP_MCAST (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_MCAST);
+		strncpy(index_name, "Multicast/mirror table index",
+			NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	case NIX_RX_ACTIONOP_RSS:
+		fprintf(file, "NIX_RX_ACTIONOP_RSS (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_RSS);
+		strncpy(index_name, "RSS Group Index",
+			NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	case NIX_RX_ACTIONOP_PF_FUNC_DROP:
+		fprintf(file, "NIX_RX_ACTIONOP_PF_FUNC_DROP (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_PF_FUNC_DROP);
+		break;
+	case NIX_RX_ACTIONOP_MIRROR:
+		fprintf(file, "NIX_RX_ACTIONOP_MIRROR (%lu)\n",
+			(uint64_t)NIX_RX_ACTIONOP_MIRROR);
+		strncpy(index_name, "Multicast/mirror table index",
+			NPC_MAX_FIELD_NAME_SIZE);
+		break;
+	}
+
+	pf_func = ((npc_action & NPC_RX_ACTION_PFFUNC_MASK) >> 4) & 0xFFFF;
+
+	fprintf(file, "\tPF_FUNC: %#04X\n", pf_func);
+
+	index = ((npc_action & NPC_RX_ACTION_INDEX_MASK) >> 20) & 0xFFFFF;
+
+	fprintf(file, "\t%s:%#05X\n", index_name, index);
+
+	match_id = ((npc_action & NPC_RX_ACTION_MATCH_MASK) >> 40) & 0xFFFF;
+
+	fprintf(file, "\tMatch Id:%#04X\n", match_id);
+
+	flowkey_alg = ((npc_action & NPC_RX_ACTION_FLOWKEY_MASK) >> 56) & 0x1F;
+
+	fprintf(file, "\tFlow Key Alg:%#X\n", flowkey_alg);
+}
+
+static void
+otx2_flow_dump_parsed_action(FILE *file, uint64_t npc_action, bool is_rx)
+{
+	if (is_rx) {
+		fprintf(file, "NPC RX Action:%#016lX\n", npc_action);
+		otx2_flow_dump_rx_action(file, npc_action);
+	} else {
+		fprintf(file, "NPC TX Action:%#016lX\n", npc_action);
+		otx2_flow_dump_tx_action(file, npc_action);
+	}
+}
+
+static void
+otx2_flow_dump_rx_vtag_action(FILE *file, uint64_t vtag_action)
+{
+	uint32_t type, lid, relptr;
+
+	if (vtag_action & NIX_RX_VTAGACT_VTAG0_VALID_MASK) {
+		relptr = vtag_action & NIX_RX_VTAGACT_VTAG0_RELPTR_MASK;
+		lid = ((vtag_action & NIX_RX_VTAGACT_VTAG0_LID_MASK) >> 8)
+			& 0x7;
+		type = ((vtag_action & NIX_RX_VTAGACT_VTAG0_TYPE_MASK) >> 12)
+			& 0x7;
+
+		fprintf(file, "\tVTAG0:relptr:%#X\n", relptr);
+		fprintf(file, "\tlid:%#X\n", lid);
+		fprintf(file, "\ttype:%#X\n", type);
+	}
+
+	if (vtag_action & NIX_RX_VTAGACT_VTAG1_VALID_MASK) {
+		relptr = ((vtag_action & NIX_RX_VTAGACT_VTAG1_RELPTR_MASK)
+			   >> 32) & 0xFF;
+		lid = ((vtag_action & NIX_RX_VTAGACT_VTAG1_LID_MASK) >> 40)
+			& 0x7;
+		type = ((vtag_action & NIX_RX_VTAGACT_VTAG1_TYPE_MASK) >> 44)
+			& 0x7;
+
+		fprintf(file, "\tVTAG1:relptr:%#X\n", relptr);
+		fprintf(file, "\tlid:%#X\n", lid);
+		fprintf(file, "\ttype:%#X\n", type);
+	}
+}
+
+static void
+otx2_get_vtag_opname(uint32_t op, char *opname, int len)
+{
+	switch (op) {
+	case 0x0:
+		strncpy(opname, "NOP", len - 1);
+		break;
+	case 0x1:
+		strncpy(opname, "INSERT", len - 1);
+		break;
+	case 0x2:
+		strncpy(opname, "REPLACE", len - 1);
+		break;
+	}
+}
+
+static void
+otx2_flow_dump_tx_vtag_action(FILE *file, uint64_t vtag_action)
+{
+	uint32_t relptr, lid, op, vtag_def;
+	char opname[10];
+
+	relptr = vtag_action & NIX_TX_VTAGACT_VTAG0_RELPTR_MASK;
+	lid = ((vtag_action & NIX_TX_VTAGACT_VTAG0_LID_MASK) >> 8) & 0x7;
+	op = ((vtag_action & NIX_TX_VTAGACT_VTAG0_OP_MASK) >> 12) & 0x3;
+	vtag_def = ((vtag_action & NIX_TX_VTAGACT_VTAG0_DEF_MASK) >> 16)
+		   & 0x3FF;
+
+	otx2_get_vtag_opname(op, opname, sizeof(opname));
+
+	fprintf(file, "\tVTAG0 relptr:%#X\n", relptr);
+	fprintf(file, "\tlid:%#X\n", lid);
+	fprintf(file, "\top:%s\n", opname);
+	fprintf(file, "\tvtag_def:%#X\n", vtag_def);
+
+	relptr = ((vtag_action & NIX_TX_VTAGACT_VTAG1_RELPTR_MASK) >> 32)
+		 & 0xFF;
+	lid = ((vtag_action & NIX_TX_VTAGACT_VTAG1_LID_MASK) >> 40) & 0x7;
+	op = ((vtag_action & NIX_TX_VTAGACT_VTAG1_OP_MASK) >> 44) & 0x3;
+	vtag_def = ((vtag_action & NIX_TX_VTAGACT_VTAG1_DEF_MASK) >> 48)
+		   & 0x3FF;
+
+	otx2_get_vtag_opname(op, opname, sizeof(opname));
+
+	fprintf(file, "\tVTAG1:relptr:%#X\n", relptr);
+	fprintf(file, "\tlid:%#X\n", lid);
+	fprintf(file, "\top:%s\n", opname);
+	fprintf(file, "\tvtag_def:%#X\n", vtag_def);
+}
+
+static void
+otx2_flow_dump_vtag_action(FILE *file, uint64_t vtag_action, bool is_rx)
+{
+	if (is_rx) {
+		fprintf(file, "NPC RX VTAG Action:%#016lX\n", vtag_action);
+		otx2_flow_dump_rx_vtag_action(file, vtag_action);
+	} else {
+		fprintf(file, "NPC TX VTAG Action:%#016lX\n", vtag_action);
+		otx2_flow_dump_tx_vtag_action(file, vtag_action);
+	}
+}
+
+void
+otx2_flow_dump(FILE *file, struct otx2_eth_dev *hw, struct rte_flow *flow)
+{
+	bool is_rx = 0;
+	int i;
+
+	fprintf(file, "MCAM Index:%d\n", flow->mcam_id);
+	fprintf(file, "Interface :%s (%d)\n", intf_str[flow->nix_intf],
+		flow->nix_intf);
+	fprintf(file, "Priority  :%d\n", flow->priority);
+
+	if (flow->nix_intf == NIX_INTF_RX)
+		is_rx = 1;
+
+	otx2_flow_dump_parsed_action(file, flow->npc_action, is_rx);
+	otx2_flow_dump_vtag_action(file, flow->vtag_action, is_rx);
+	fprintf(file, "Patterns:\n");
+	otx2_flow_dump_patterns(file, hw, flow);
+
+	fprintf(file, "MCAM Raw Data :\n");
+
+	for (i = 0; i < OTX2_MAX_MCAM_WIDTH_DWORDS; i++)  {
+		fprintf(file, "\tDW%d     :%016lX\n", i, flow->mcam_data[i]);
+		fprintf(file, "\tDW%d_Mask:%016lX\n", i, flow->mcam_mask[i]);
+	}
+
+	fprintf(file, "\n");
+}
diff --git a/drivers/net/octeontx2/otx2_flow_utils.c b/drivers/net/octeontx2/otx2_flow_utils.c
index 7ed86ba74..d5f0645dc 100644
--- a/drivers/net/octeontx2/otx2_flow_utils.c
+++ b/drivers/net/octeontx2/otx2_flow_utils.c
@@ -271,6 +271,7 @@  otx2_flow_update_parse_state(struct otx2_parse_state *pst,
 			     uint8_t flags)
 {
 	struct npc_lid_lt_xtract_info *xinfo;
+	struct otx2_flow_dump_data *dump;
 	struct npc_xtract_info *lfinfo;
 	int intf, lf_cfg;
 	int i, j, rc = 0;
@@ -320,6 +321,9 @@  otx2_flow_update_parse_state(struct otx2_parse_state *pst,
 	}
 
 done:
+	dump = &pst->flow->dump_data[pst->flow->num_patterns++];
+	dump->lid = lid;
+	dump->ltype = lt;
 	/* Next pattern to parse by subsequent layers */
 	pst->pattern++;
 	return 0;