diff --git a/doc/guides/nics/cnxk.rst b/doc/guides/nics/cnxk.rst
index c2a6fbb..87401f0 100644
--- a/doc/guides/nics/cnxk.rst
+++ b/doc/guides/nics/cnxk.rst
@@ -24,6 +24,7 @@ Features of the CNXK Ethdev PMD are:
 - Multiple queues for TX and RX
 - Receiver Side Scaling (RSS)
 - MAC filtering
+- Generic flow API
 - Inner and Outer Checksum offload
 - Port hardware statistics
 - Link state information
@@ -222,3 +223,120 @@ Debugging Options
    +---+------------+-------------------------------------------------------+
    | 2 | NPC        | --log-level='pmd\.net.cnxk\.flow,8'                   |
    +---+------------+-------------------------------------------------------+
+
+RTE Flow Support
+----------------
+
+The OCTEON CN9K/CN10K SoC family NIC has support for the following patterns and
+actions.
+
+Patterns:
+
+.. _table_cnxk_supported_flow_item_types:
+
+.. table:: Item types
+
+   +----+--------------------------------+
+   | #  | Pattern Type                   |
+   +====+================================+
+   | 1  | RTE_FLOW_ITEM_TYPE_ETH         |
+   +----+--------------------------------+
+   | 2  | RTE_FLOW_ITEM_TYPE_VLAN        |
+   +----+--------------------------------+
+   | 3  | RTE_FLOW_ITEM_TYPE_E_TAG       |
+   +----+--------------------------------+
+   | 4  | RTE_FLOW_ITEM_TYPE_IPV4        |
+   +----+--------------------------------+
+   | 5  | RTE_FLOW_ITEM_TYPE_IPV6        |
+   +----+--------------------------------+
+   | 6  | RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4|
+   +----+--------------------------------+
+   | 7  | RTE_FLOW_ITEM_TYPE_MPLS        |
+   +----+--------------------------------+
+   | 8  | RTE_FLOW_ITEM_TYPE_ICMP        |
+   +----+--------------------------------+
+   | 9  | RTE_FLOW_ITEM_TYPE_UDP         |
+   +----+--------------------------------+
+   | 10 | RTE_FLOW_ITEM_TYPE_TCP         |
+   +----+--------------------------------+
+   | 11 | RTE_FLOW_ITEM_TYPE_SCTP        |
+   +----+--------------------------------+
+   | 12 | RTE_FLOW_ITEM_TYPE_ESP         |
+   +----+--------------------------------+
+   | 13 | RTE_FLOW_ITEM_TYPE_GRE         |
+   +----+--------------------------------+
+   | 14 | RTE_FLOW_ITEM_TYPE_NVGRE       |
+   +----+--------------------------------+
+   | 15 | RTE_FLOW_ITEM_TYPE_VXLAN       |
+   +----+--------------------------------+
+   | 16 | RTE_FLOW_ITEM_TYPE_GTPC        |
+   +----+--------------------------------+
+   | 17 | RTE_FLOW_ITEM_TYPE_GTPU        |
+   +----+--------------------------------+
+   | 18 | RTE_FLOW_ITEM_TYPE_GENEVE      |
+   +----+--------------------------------+
+   | 19 | RTE_FLOW_ITEM_TYPE_VXLAN_GPE   |
+   +----+--------------------------------+
+   | 20 | RTE_FLOW_ITEM_TYPE_IPV6_EXT    |
+   +----+--------------------------------+
+   | 21 | RTE_FLOW_ITEM_TYPE_VOID        |
+   +----+--------------------------------+
+   | 22 | RTE_FLOW_ITEM_TYPE_ANY         |
+   +----+--------------------------------+
+   | 23 | RTE_FLOW_ITEM_TYPE_GRE_KEY     |
+   +----+--------------------------------+
+   | 24 | RTE_FLOW_ITEM_TYPE_HIGIG2      |
+   +----+--------------------------------+
+
+.. note::
+
+   ``RTE_FLOW_ITEM_TYPE_GRE_KEY`` works only when checksum and routing
+   bits in the GRE header are equal to 0.
+
+Actions:
+
+.. _table_cnxk_supported_ingress_action_types:
+
+.. table:: Ingress action types
+
+   +----+-----------------------------------------+
+   | #  | Action Type                             |
+   +====+=========================================+
+   | 1  | RTE_FLOW_ACTION_TYPE_VOID               |
+   +----+-----------------------------------------+
+   | 2  | RTE_FLOW_ACTION_TYPE_MARK               |
+   +----+-----------------------------------------+
+   | 3  | RTE_FLOW_ACTION_TYPE_FLAG               |
+   +----+-----------------------------------------+
+   | 4  | RTE_FLOW_ACTION_TYPE_COUNT              |
+   +----+-----------------------------------------+
+   | 5  | RTE_FLOW_ACTION_TYPE_DROP               |
+   +----+-----------------------------------------+
+   | 6  | RTE_FLOW_ACTION_TYPE_QUEUE              |
+   +----+-----------------------------------------+
+   | 7  | RTE_FLOW_ACTION_TYPE_RSS                |
+   +----+-----------------------------------------+
+   | 8  | RTE_FLOW_ACTION_TYPE_PF                 |
+   +----+-----------------------------------------+
+   | 9  | RTE_FLOW_ACTION_TYPE_VF                 |
+   +----+-----------------------------------------+
+   | 10 | RTE_FLOW_ACTION_TYPE_OF_POP_VLAN        |
+   +----+-----------------------------------------+
+
+.. _table_cnxk_supported_egress_action_types:
+
+.. table:: Egress action types
+
+   +----+-----------------------------------------+
+   | #  | Action Type                             |
+   +====+=========================================+
+   | 1  | RTE_FLOW_ACTION_TYPE_COUNT              |
+   +----+-----------------------------------------+
+   | 2  | RTE_FLOW_ACTION_TYPE_DROP               |
+   +----+-----------------------------------------+
+   | 3  | RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN       |
+   +----+-----------------------------------------+
+   | 4  | RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID    |
+   +----+-----------------------------------------+
+   | 5  | RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP    |
+   +----+-----------------------------------------+
diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini
index 192c15a..3c59494 100644
--- a/doc/guides/nics/features/cnxk.ini
+++ b/doc/guides/nics/features/cnxk.ini
@@ -39,3 +39,45 @@ Module EEPROM dump   = Y
 Linux                = Y
 ARMv8                = Y
 Usage doc            = Y
+
+[rte_flow items]
+any                  = Y
+arp_eth_ipv4         = Y
+esp                  = Y
+eth                  = Y
+e_tag                = Y
+geneve               = Y
+gre                  = Y
+gre_key              = Y
+gtpc                 = Y
+gtpu                 = Y
+higig2               = Y
+icmp                 = Y
+ipv4                 = Y
+ipv6                 = Y
+ipv6_ext             = Y
+mpls                 = Y
+nvgre                = Y
+raw                  = Y
+sctp                 = Y
+tcp                  = Y
+udp                  = Y
+vlan                 = Y
+vxlan                = Y
+vxlan_gpe            = Y
+
+[rte_flow actions]
+count                = Y
+drop                 = Y
+flag                 = Y
+mark                 = Y
+of_pop_vlan          = Y
+of_push_vlan         = Y
+of_set_vlan_pcp      = Y
+of_set_vlan_vid      = Y
+pf                   = Y
+port_id              = Y
+queue                = Y
+rss                  = Y
+security             = Y
+vf                   = Y
diff --git a/drivers/net/cnxk/cnxk_rte_flow.c b/drivers/net/cnxk/cnxk_rte_flow.c
new file mode 100644
index 0000000..d0e7bdc
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_rte_flow.c
@@ -0,0 +1,282 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+#include <cnxk_rte_flow.h>
+
+static int
+cnxk_map_actions(struct rte_eth_dev *dev,
+		 const struct rte_flow_action actions[],
+		 struct roc_npc_action in_actions[])
+{
+	struct cnxk_eth_dev *hw = dev->data->dev_private;
+	const struct rte_flow_action_count *act_count;
+	const struct rte_flow_action_queue *act_q;
+	int rq;
+	int i = 0;
+
+	RTE_SET_USED(hw);
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_VOID;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_MARK:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
+			in_actions[i].conf = actions->conf;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_FLAG:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_FLAG;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			act_count = (const struct rte_flow_action_count *)
+					    actions->conf;
+
+			if (act_count->shared == 1) {
+				plt_npc_dbg("Shared counter is not supported");
+				goto err_exit;
+			}
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_COUNT;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_DROP:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_DROP;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_PF:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_PF;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_VF:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_VF;
+			in_actions[i].conf = actions->conf;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_QUEUE:
+			act_q = (const struct rte_flow_action_queue *)
+					actions->conf;
+			rq = act_q->index;
+			if (rq >= dev->data->nb_rx_queues) {
+				plt_npc_dbg("Invalid queue index");
+				goto err_exit;
+			}
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
+			in_actions[i].conf = actions->conf;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_RSS:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_SECURITY:
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
+			break;
+		default:
+			plt_npc_dbg("Action is not supported = %d",
+				    actions->type);
+			goto err_exit;
+		}
+		i++;
+	}
+	in_actions[i].type = ROC_NPC_ACTION_TYPE_END;
+	return 0;
+
+err_exit:
+	return -EINVAL;
+}
+
+static int
+cnxk_map_flow_data(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+		   const struct rte_flow_item pattern[],
+		   const struct rte_flow_action actions[],
+		   struct roc_npc_attr *in_attr,
+		   struct roc_npc_item_info in_pattern[],
+		   struct roc_npc_action in_actions[])
+{
+	int i = 0;
+
+	in_attr->priority = attr->priority;
+	in_attr->ingress = attr->ingress;
+	in_attr->egress = attr->egress;
+
+	while (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
+		in_pattern[i].spec = pattern->spec;
+		in_pattern[i].last = pattern->last;
+		in_pattern[i].mask = pattern->mask;
+		in_pattern[i].type = term[pattern->type].item_type;
+		in_pattern[i].size = term[pattern->type].item_size;
+		pattern++;
+		i++;
+	}
+	in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
+
+	return cnxk_map_actions(dev, actions, in_actions);
+}
+
+static int
+cnxk_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+		   const struct rte_flow_item pattern[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow_error *error)
+{
+	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
+	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
+	struct cnxk_eth_dev *hw = dev->data->dev_private;
+	struct roc_npc *npc = &hw->npc;
+	struct roc_npc_attr in_attr;
+	struct roc_npc_flow flow;
+	int rc;
+
+	memset(&flow, 0, sizeof(flow));
+
+	rc = cnxk_map_flow_data(dev, attr, pattern, actions, &in_attr,
+				in_pattern, in_actions);
+	if (rc) {
+		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				   NULL, "Failed to map flow data");
+		return rc;
+	}
+
+	return roc_npc_flow_parse(npc, &in_attr, in_pattern, in_actions, &flow);
+}
+
+static struct rte_flow *
+cnxk_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+		 const struct rte_flow_item pattern[],
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error)
+{
+	struct cnxk_eth_dev *hw = dev->data->dev_private;
+	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
+	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
+	struct roc_npc *npc = &hw->npc;
+	struct roc_npc_attr in_attr;
+	struct roc_npc_flow *flow;
+	int errcode;
+	int rc;
+
+	rc = cnxk_map_flow_data(dev, attr, pattern, actions, &in_attr,
+				in_pattern, in_actions);
+	if (rc) {
+		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				   NULL, "Failed to map flow data");
+		return NULL;
+	}
+
+	flow = roc_npc_flow_create(npc, &in_attr, in_pattern, in_actions,
+				   &errcode);
+	if (errcode != 0) {
+		rte_flow_error_set(error, errcode, errcode, NULL,
+				   roc_error_msg_get(errcode));
+		return NULL;
+	}
+
+	return (struct rte_flow *)flow;
+}
+
+static int
+cnxk_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
+		  struct rte_flow_error *error)
+{
+	struct roc_npc_flow *in_flow = (struct roc_npc_flow *)flow;
+	struct cnxk_eth_dev *hw = dev->data->dev_private;
+	struct roc_npc *npc = &hw->npc;
+	int rc;
+
+	rc = roc_npc_flow_destroy(npc, in_flow);
+	if (rc)
+		rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "Flow Destroy failed");
+	return rc;
+}
+
+static int
+cnxk_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
+{
+	struct cnxk_eth_dev *hw = dev->data->dev_private;
+	struct roc_npc *npc = &hw->npc;
+	int rc;
+
+	rc = roc_npc_mcam_free_all_resources(npc);
+	if (rc) {
+		rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "Failed to flush filter");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+static int
+cnxk_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
+		const struct rte_flow_action *action, void *data,
+		struct rte_flow_error *error)
+{
+	struct roc_npc_flow *in_flow = (struct roc_npc_flow *)flow;
+	struct cnxk_eth_dev *hw = dev->data->dev_private;
+	struct roc_npc *npc = &hw->npc;
+	struct rte_flow_query_count *query = data;
+	const char *errmsg = NULL;
+	int errcode = ENOTSUP;
+	int rc;
+
+	if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
+		errmsg = "Only COUNT is supported in query";
+		goto err_exit;
+	}
+
+	if (in_flow->ctr_id == NPC_COUNTER_NONE) {
+		errmsg = "Counter is not available";
+		goto err_exit;
+	}
+
+	rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	if (rc != 0) {
+		errcode = EIO;
+		errmsg = "Error reading flow counter";
+		goto err_exit;
+	}
+	query->hits_set = 1;
+	query->bytes_set = 0;
+
+	if (query->reset)
+		rc = roc_npc_mcam_clear_counter(npc, in_flow->ctr_id);
+	if (rc != 0) {
+		errcode = EIO;
+		errmsg = "Error clearing flow counter";
+		goto err_exit;
+	}
+
+	return 0;
+
+err_exit:
+	rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			   NULL, errmsg);
+	return -rte_errno;
+}
+
+static int
+cnxk_flow_isolate(struct rte_eth_dev *dev __rte_unused, int enable __rte_unused,
+		  struct rte_flow_error *error)
+{
+	/* If we support, we need to un-install the default mcam
+	 * entry for this port.
+	 */
+
+	rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			   NULL, "Flow isolation not supported");
+
+	return -rte_errno;
+}
+
+const struct rte_flow_ops cnxk_flow_ops = {
+	.validate = cnxk_flow_validate,
+	.create = cnxk_flow_create,
+	.destroy = cnxk_flow_destroy,
+	.flush = cnxk_flow_flush,
+	.query = cnxk_flow_query,
+	.isolate = cnxk_flow_isolate,
+};
diff --git a/drivers/net/cnxk/cnxk_rte_flow.h b/drivers/net/cnxk/cnxk_rte_flow.h
new file mode 100644
index 0000000..3740226
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_rte_flow.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+#ifndef __CNXK_RTE_FLOW_H__
+#define __CNXK_RTE_FLOW_H__
+
+#include <rte_flow_driver.h>
+#include <rte_malloc.h>
+
+#include "cnxk_ethdev.h"
+#include "roc_api.h"
+#include "roc_npc_priv.h"
+
+struct cnxk_rte_flow_term_info {
+	uint16_t item_type;
+	uint16_t item_size;
+};
+
+struct cnxk_rte_flow_term_info term[] = {
+	[RTE_FLOW_ITEM_TYPE_ETH] = {ROC_NPC_ITEM_TYPE_ETH,
+				    sizeof(struct rte_flow_item_eth)},
+	[RTE_FLOW_ITEM_TYPE_VLAN] = {ROC_NPC_ITEM_TYPE_VLAN,
+				     sizeof(struct rte_flow_item_vlan)},
+	[RTE_FLOW_ITEM_TYPE_E_TAG] = {ROC_NPC_ITEM_TYPE_E_TAG,
+				      sizeof(struct rte_flow_item_e_tag)},
+	[RTE_FLOW_ITEM_TYPE_IPV4] = {ROC_NPC_ITEM_TYPE_IPV4,
+				     sizeof(struct rte_flow_item_ipv4)},
+	[RTE_FLOW_ITEM_TYPE_IPV6] = {ROC_NPC_ITEM_TYPE_IPV6,
+				     sizeof(struct rte_flow_item_ipv6)},
+	[RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4] = {ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
+		 sizeof(struct rte_flow_item_arp_eth_ipv4)},
+	[RTE_FLOW_ITEM_TYPE_MPLS] = {ROC_NPC_ITEM_TYPE_MPLS,
+				     sizeof(struct rte_flow_item_mpls)},
+	[RTE_FLOW_ITEM_TYPE_ICMP] = {ROC_NPC_ITEM_TYPE_ICMP,
+				     sizeof(struct rte_flow_item_icmp)},
+	[RTE_FLOW_ITEM_TYPE_UDP] = {ROC_NPC_ITEM_TYPE_UDP,
+				    sizeof(struct rte_flow_item_udp)},
+	[RTE_FLOW_ITEM_TYPE_TCP] = {ROC_NPC_ITEM_TYPE_TCP,
+				    sizeof(struct rte_flow_item_tcp)},
+	[RTE_FLOW_ITEM_TYPE_SCTP] = {ROC_NPC_ITEM_TYPE_SCTP,
+				     sizeof(struct rte_flow_item_sctp)},
+	[RTE_FLOW_ITEM_TYPE_ESP] = {ROC_NPC_ITEM_TYPE_ESP,
+				    sizeof(struct rte_flow_item_esp)},
+	[RTE_FLOW_ITEM_TYPE_GRE] = {ROC_NPC_ITEM_TYPE_GRE,
+				    sizeof(struct rte_flow_item_gre)},
+	[RTE_FLOW_ITEM_TYPE_NVGRE] = {ROC_NPC_ITEM_TYPE_NVGRE,
+				      sizeof(struct rte_flow_item_nvgre)},
+	[RTE_FLOW_ITEM_TYPE_VXLAN] = {ROC_NPC_ITEM_TYPE_VXLAN,
+				      sizeof(struct rte_flow_item_vxlan)},
+	[RTE_FLOW_ITEM_TYPE_GTPC] = {ROC_NPC_ITEM_TYPE_GTPC,
+				     sizeof(struct rte_flow_item_gtp)},
+	[RTE_FLOW_ITEM_TYPE_GTPU] = {ROC_NPC_ITEM_TYPE_GTPU,
+				     sizeof(struct rte_flow_item_gtp)},
+	[RTE_FLOW_ITEM_TYPE_GENEVE] = {ROC_NPC_ITEM_TYPE_GENEVE,
+				       sizeof(struct rte_flow_item_geneve)},
+	[RTE_FLOW_ITEM_TYPE_VXLAN_GPE] = {ROC_NPC_ITEM_TYPE_VXLAN_GPE,
+			sizeof(struct rte_flow_item_vxlan_gpe)},
+	[RTE_FLOW_ITEM_TYPE_IPV6_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_EXT,
+					 sizeof(struct rte_flow_item_ipv6_ext)},
+	[RTE_FLOW_ITEM_TYPE_VOID] = {ROC_NPC_ITEM_TYPE_VOID, 0},
+	[RTE_FLOW_ITEM_TYPE_ANY] = {ROC_NPC_ITEM_TYPE_ANY, 0},
+	[RTE_FLOW_ITEM_TYPE_GRE_KEY] = {ROC_NPC_ITEM_TYPE_GRE_KEY,
+					sizeof(uint32_t)},
+	[RTE_FLOW_ITEM_TYPE_HIGIG2] = {
+		ROC_NPC_ITEM_TYPE_HIGIG2,
+		sizeof(struct rte_flow_item_higig2_hdr)}
+};
+
+#endif /* __CNXK_RTE_FLOW_H__ */
diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build
index e0ab9d6..92ef8f0 100644
--- a/drivers/net/cnxk/meson.build
+++ b/drivers/net/cnxk/meson.build
@@ -13,6 +13,7 @@ sources = files('cnxk_ethdev.c',
 		'cnxk_ethdev_devargs.c',
 		'cnxk_link.c',
 		'cnxk_lookup.c',
+		'cnxk_rte_flow.c',
 		'cnxk_stats.c')
 
 # CN9K
