All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] net/dpaa2: add support for VLAN tpid config
@ 2019-02-22 11:15 Hemant Agrawal
  2019-02-22 11:15 ` [PATCH 2/6] mempool/dpaa2: fix to reduce continuous print on empty pool Hemant Agrawal
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Hemant Agrawal @ 2019-02-22 11:15 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, Shreyansh Jain

This patch add support to config custom tpid in dpni.
i.e. value other than 0x8100 and 0x88A8

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/net/dpaa2/dpaa2_ethdev.c    | 39 ++++++++++++
 drivers/net/dpaa2/mc/dpni.c         | 98 +++++++++++++++++++++++++++++
 drivers/net/dpaa2/mc/fsl_dpni.h     | 20 ++++++
 drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 18 ++++++
 4 files changed, 175 insertions(+)

diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 2b90f4021..bc3faa8a3 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -161,6 +161,44 @@ dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	return 0;
 }
 
+static int
+dpaa2_vlan_tpid_set(struct rte_eth_dev *dev,
+		      enum rte_vlan_type vlan_type __rte_unused,
+		      uint16_t tpid)
+{
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = priv->hw;
+	int ret = -ENOTSUP;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* nothing to be done for standard vlan tpids */
+	if (tpid == 0x8100 || tpid == 0x88A8)
+		return 0;
+
+	ret = dpni_add_custom_tpid(dpni, CMD_PRI_LOW,
+				   priv->token, tpid);
+	if (ret < 0)
+		DPAA2_PMD_INFO("Unable to set vlan tpid = %d", ret);
+	/* if already configured tpids, remove them first */
+	if (ret == -EBUSY) {
+		struct dpni_custom_tpid_cfg tpid_list = {0};
+
+		ret = dpni_get_custom_tpid(dpni, CMD_PRI_LOW,
+				   priv->token, &tpid_list);
+		if (ret < 0)
+			goto fail;
+		ret = dpni_remove_custom_tpid(dpni, CMD_PRI_LOW,
+				   priv->token, tpid_list.tpid1);
+		if (ret < 0)
+			goto fail;
+		ret = dpni_add_custom_tpid(dpni, CMD_PRI_LOW,
+					   priv->token, tpid);
+	}
+fail:
+	return ret;
+}
+
 static int
 dpaa2_fw_version_get(struct rte_eth_dev *dev,
 		     char *fw_version,
@@ -1832,6 +1870,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.mtu_set           = dpaa2_dev_mtu_set,
 	.vlan_filter_set      = dpaa2_vlan_filter_set,
 	.vlan_offload_set     = dpaa2_vlan_offload_set,
+	.vlan_tpid_set	      = dpaa2_vlan_tpid_set,
 	.rx_queue_setup    = dpaa2_dev_rx_queue_setup,
 	.rx_queue_release  = dpaa2_dev_rx_queue_release,
 	.tx_queue_setup    = dpaa2_dev_tx_queue_setup,
diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c
index 44b5604d3..0907a3699 100644
--- a/drivers/net/dpaa2/mc/dpni.c
+++ b/drivers/net/dpaa2/mc/dpni.c
@@ -2063,3 +2063,101 @@ int dpni_get_opr(struct fsl_mc_io *mc_io,
 
 	return 0;
 }
+
+/**
+ * dpni_add_custom_tpid() - Configures a distinct Ethertype value
+ *		(or TPID value) to indicate VLAN tag in addition to the common
+ *		TPID values 0x8100 and 0x88A8
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tpid:	New value for TPID
+ *
+ * Only two custom values are accepted. If the function is called for the third
+ * time it will return error.
+ * To replace an existing value use dpni_remove_custom_tpid() to remove
+ * a previous TPID and after that use again the function.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, uint16_t tpid)
+{
+	struct dpni_cmd_add_custom_tpid *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_CUSTOM_TPID,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_add_custom_tpid *)cmd.params;
+	cmd_params->tpid = cpu_to_le16(tpid);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_remove_custom_tpid() - Removes a distinct Ethertype value added
+ *		previously with dpni_add_custom_tpid()
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tpid:	New value for TPID
+ *
+ * Use this function when a TPID value added with dpni_add_custom_tpid() needs
+ * to be replaced.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, uint16_t tpid)
+{
+	struct dpni_cmd_remove_custom_tpid *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_CUSTOM_TPID,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_remove_custom_tpid *)cmd.params;
+	cmd_params->tpid = cpu_to_le16(tpid);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_get_custom_tpid() - Returns custom TPID (vlan tags) values configured
+ *				to detect 802.1q frames
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tpid:	TPID values. Only nonzero members of the structure are valid.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, struct dpni_custom_tpid_cfg *tpid)
+{
+	struct dpni_rsp_get_custom_tpid *rsp_params;
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_CUSTOM_TPID,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* read command response */
+	rsp_params = (struct dpni_rsp_get_custom_tpid *)cmd.params;
+	tpid->tpid1 = le16_to_cpu(rsp_params->tpid1);
+	tpid->tpid2 = le16_to_cpu(rsp_params->tpid2);
+
+	return err;
+}
diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h
index de1bcb5bf..0359a2bc7 100644
--- a/drivers/net/dpaa2/mc/fsl_dpni.h
+++ b/drivers/net/dpaa2/mc/fsl_dpni.h
@@ -1202,4 +1202,24 @@ int dpni_get_opr(struct fsl_mc_io *mc_io,
 		 struct opr_cfg *cfg,
 		 struct opr_qry *qry);
 
+int dpni_add_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, uint16_t tpid);
+
+int dpni_remove_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, uint16_t tpid);
+
+/**
+ * struct dpni_custom_tpid_cfg - custom TPID configuration. Contains custom TPID
+ *	values used in current dpni object to detect 802.1q frames.
+ *	@tpid1: first tag. Not used if zero.
+ *	@tpid2: second tag. Not used if zero.
+ */
+struct dpni_custom_tpid_cfg {
+	uint16_t tpid1;
+	uint16_t tpid2;
+};
+
+int dpni_get_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, struct dpni_custom_tpid_cfg *tpid);
+
 #endif /* __FSL_DPNI_H */
diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h
index 3df5bcf1f..81830ed85 100644
--- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h
+++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h
@@ -91,6 +91,9 @@
 #define DPNI_CMDID_GET_TX_CONFIRMATION_MODE	DPNI_CMD(0x26D)
 #define DPNI_CMDID_SET_OPR			DPNI_CMD(0x26e)
 #define DPNI_CMDID_GET_OPR			DPNI_CMD(0x26f)
+#define DPNI_CMDID_ADD_CUSTOM_TPID		DPNI_CMD(0x275)
+#define DPNI_CMDID_REMOVE_CUSTOM_TPID		DPNI_CMD(0x276)
+#define DPNI_CMDID_GET_CUSTOM_TPID		DPNI_CMD(0x277)
 
 /* Macros for accessing command fields smaller than 1byte */
 #define DPNI_MASK(field)	\
@@ -674,5 +677,20 @@ struct dpni_rsp_get_opr {
 	uint16_t opr_id;
 };
 
+struct dpni_cmd_add_custom_tpid {
+	uint16_t	pad;
+	uint16_t	tpid;
+};
+
+struct dpni_cmd_remove_custom_tpid {
+	uint16_t	pad;
+	uint16_t	tpid;
+};
+
+struct dpni_rsp_get_custom_tpid {
+	uint16_t	tpid1;
+	uint16_t	tpid2;
+};
+
 #pragma pack(pop)
 #endif /* _FSL_DPNI_CMD_H */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] mempool/dpaa2: fix to reduce continuous print on empty pool
  2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
@ 2019-02-22 11:15 ` Hemant Agrawal
  2019-02-22 11:16 ` [PATCH 3/6] bus/fslmc: add enqueue response read routines in qbman Hemant Agrawal
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Hemant Agrawal @ 2019-02-22 11:15 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, Shreyansh Jain, stable

Changing the print to DP_DEBUG to avoid continuous prints when
buffer pools runs out of buffers

Fixes: 3646ccf0b036 ("mempool/dpaa2: support dynamic logging")
Cc: stable@dpdk.org

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/mempool/dpaa2/dpaa2_hw_mempool.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c
index 335eae40e..da66577cc 100644
--- a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c
+++ b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c
@@ -326,8 +326,8 @@ rte_dpaa2_mbuf_alloc_bulk(struct rte_mempool *pool,
 		 * in pool, qbman_swp_acquire returns 0
 		 */
 		if (ret <= 0) {
-			DPAA2_MEMPOOL_ERR("Buffer acquire failed with"
-					  " err code: %d", ret);
+			DPAA2_MEMPOOL_DP_DEBUG(
+				"Buffer acquire failed with err code: %d", ret);
 			/* The API expect the exact number of requested bufs */
 			/* Releasing all buffers allocated */
 			rte_dpaa2_mbuf_release(pool, obj_table, bpid,
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] bus/fslmc: add enqueue response read routines in qbman
  2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
  2019-02-22 11:15 ` [PATCH 2/6] mempool/dpaa2: fix to reduce continuous print on empty pool Hemant Agrawal
@ 2019-02-22 11:16 ` Hemant Agrawal
  2019-02-22 11:16 ` [PATCH 4/6] net/dpaa2: add support for 16 Rx Queues per traffic class Hemant Agrawal
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Hemant Agrawal @ 2019-02-22 11:16 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, Shreyansh Jain, Nipun Gupta

From: Nipun Gupta <nipun.gupta@nxp.com>

Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
---
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c      |  47 ++++
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.h      |   4 +
 drivers/bus/fslmc/portal/dpaa2_hw_pvt.h       |  24 ++
 .../fslmc/qbman/include/fsl_qbman_portal.h    |  56 +++-
 drivers/bus/fslmc/qbman/qbman_portal.c        |  26 ++
 drivers/bus/fslmc/rte_bus_fslmc_version.map   |  16 +-
 drivers/net/dpaa2/dpaa2_ethdev.c              |  42 +++
 drivers/net/dpaa2/dpaa2_ethdev.h              |  13 +-
 drivers/net/dpaa2/dpaa2_rxtx.c                | 255 ++++++++++++++++++
 9 files changed, 480 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index f377f24ae..7bcbde840 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -526,6 +526,18 @@ dpaa2_create_dpio_device(int vdev_fd,
 		goto err;
 	}
 
+	dpio_dev->eqresp = rte_zmalloc(NULL, MAX_EQ_RESP_ENTRIES *
+				     (sizeof(struct qbman_result) +
+				     sizeof(struct eqresp_metadata)),
+				     RTE_CACHE_LINE_SIZE);
+	if (!dpio_dev->eqresp) {
+		DPAA2_BUS_ERR("Memory allocation failed for eqresp");
+		goto err;
+	}
+	dpio_dev->eqresp_meta = (struct eqresp_metadata *)(dpio_dev->eqresp +
+				MAX_EQ_RESP_ENTRIES);
+
+
 	TAILQ_INSERT_TAIL(&dpio_dev_list, dpio_dev, next);
 
 	return 0;
@@ -588,6 +600,41 @@ dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage)
 	return -1;
 }
 
+uint32_t
+dpaa2_free_eq_descriptors(void)
+{
+	struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO;
+	struct qbman_result *eqresp;
+	struct eqresp_metadata *eqresp_meta;
+	struct dpaa2_queue *txq;
+
+	while (dpio_dev->eqresp_ci != dpio_dev->eqresp_pi) {
+		eqresp = &dpio_dev->eqresp[dpio_dev->eqresp_ci];
+		eqresp_meta = &dpio_dev->eqresp_meta[dpio_dev->eqresp_ci];
+
+		if (!qbman_result_eqresp_rspid(eqresp))
+			break;
+
+		if (qbman_result_eqresp_rc(eqresp)) {
+			txq = eqresp_meta->dpaa2_q;
+			txq->cb_eqresp_free(dpio_dev->eqresp_ci);
+		}
+		qbman_result_eqresp_set_rspid(eqresp, 0);
+
+		dpio_dev->eqresp_ci + 1 < MAX_EQ_RESP_ENTRIES ?
+			dpio_dev->eqresp_ci++ : (dpio_dev->eqresp_ci = 0);
+	}
+
+	/* Return 1 less entry so that PI and CI are never same in a
+	 * case there all the EQ responses are in use.
+	 */
+	if (dpio_dev->eqresp_ci > dpio_dev->eqresp_pi)
+		return dpio_dev->eqresp_ci - dpio_dev->eqresp_pi - 1;
+	else
+		return dpio_dev->eqresp_ci - dpio_dev->eqresp_pi +
+			MAX_EQ_RESP_ENTRIES - 1;
+}
+
 static struct rte_dpaa2_object rte_dpaa2_dpio_obj = {
 	.dev_type = DPAA2_IO,
 	.create = dpaa2_create_dpio_device,
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
index 4354c76de..17e7e4fad 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h
@@ -51,4 +51,8 @@ dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage);
 void
 dpaa2_free_dq_storage(struct queue_storage_info_t *q_storage);
 
+/* free the enqueue response descriptors */
+uint32_t
+dpaa2_free_eq_descriptors(void);
+
 #endif /* _DPAA2_HW_DPIO_H_ */
diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
index 626fcbbca..4679e9340 100644
--- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
+++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
@@ -34,6 +34,7 @@
 
 /* Maximum number of slots available in TX ring */
 #define MAX_TX_RING_SLOTS			32
+#define MAX_EQ_RESP_ENTRIES			(MAX_TX_RING_SLOTS + 1)
 
 /* Maximum number of slots available in RX ring */
 #define DPAA2_EQCR_RING_SIZE		8
@@ -50,6 +51,15 @@
 /* EQCR shift to get EQCR size for LX2 (2 >> 5) = 32 for LX2 */
 #define DPAA2_LX2_EQCR_SHIFT		5
 
+/* Flag to determine an ordered queue mbuf */
+#define DPAA2_ENQUEUE_FLAG_ORP		(1ULL << 30)
+/* ORP ID shift and mask */
+#define DPAA2_EQCR_OPRID_SHIFT		16
+#define DPAA2_EQCR_OPRID_MASK		0x3FFF0000
+/* Sequence number shift and mask */
+#define DPAA2_EQCR_SEQNUM_SHIFT		0
+#define DPAA2_EQCR_SEQNUM_MASK		0x0000FFFF
+
 #define DPAA2_SWP_CENA_REGION		0
 #define DPAA2_SWP_CINH_REGION		1
 #define DPAA2_SWP_CENA_MEM_REGION	2
@@ -77,12 +87,23 @@
 
 #define DPAA2_DPCI_MAX_QUEUES 2
 
+struct dpaa2_queue;
+
+struct eqresp_metadata {
+	struct dpaa2_queue *dpaa2_q;
+	struct rte_mempool *mp;
+};
+
 struct dpaa2_dpio_dev {
 	TAILQ_ENTRY(dpaa2_dpio_dev) next;
 		/**< Pointer to Next device instance */
 	uint16_t index; /**< Index of a instance in the list */
 	rte_atomic16_t ref_count;
 		/**< How many thread contexts are sharing this.*/
+	uint16_t eqresp_ci;
+	uint16_t eqresp_pi;
+	struct qbman_result *eqresp;
+	struct eqresp_metadata *eqresp_meta;
 	struct fsl_mc_io *dpio; /** handle to DPIO portal object */
 	uint16_t token;
 	struct qbman_swp *sw_portal; /** SW portal object */
@@ -125,6 +146,8 @@ typedef void (dpaa2_queue_cb_dqrr_t)(struct qbman_swp *swp,
 		struct dpaa2_queue *rxq,
 		struct rte_event *ev);
 
+typedef void (dpaa2_queue_cb_eqresp_free_t)(uint16_t eqresp_ci);
+
 struct dpaa2_queue {
 	struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */
 	union {
@@ -144,6 +167,7 @@ struct dpaa2_queue {
 	};
 	struct rte_event ev;
 	dpaa2_queue_cb_dqrr_t *cb;
+	dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free;
 	struct dpaa2_bp_info *bp_array;
 };
 
diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h
index 10c72e048..a9192d3cb 100644
--- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h
+++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h
@@ -212,6 +212,23 @@ struct qbman_result {
 			__le32 rid_tok;
 			__le64 ctx;
 		} scn;
+		struct eq_resp {
+			uint8_t verb;
+			uint8_t dca;
+			__le16 seqnum;
+			__le16 oprid;
+			uint8_t reserved;
+			uint8_t rc;
+			__le32 tgtid;
+			__le32 tag;
+			uint16_t qdbin;
+			uint8_t qpri;
+			uint8_t reserved1;
+			__le32 fqid:24;
+			__le32 rspid:8;
+			__le64 rsp_addr;
+			uint8_t fd[32];
+		} eq_resp;
 	};
 };
 
@@ -788,7 +805,6 @@ uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn);
 	/************/
 	/* Enqueues */
 	/************/
-
 /* struct qbman_eq_desc - structure of enqueue descriptor */
 struct qbman_eq_desc {
 	union {
@@ -956,6 +972,44 @@ void qbman_eq_desc_set_eqdi(struct qbman_eq_desc *d, int enable);
 void qbman_eq_desc_set_dca(struct qbman_eq_desc *d, int enable,
 			   uint8_t dqrr_idx, int park);
 
+/**
+ * qbman_result_eqresp_fd() - Get fd from enqueue response.
+ * @eqresp: enqueue response.
+ *
+ * Return the fd pointer.
+ */
+struct qbman_fd *qbman_result_eqresp_fd(struct qbman_result *eqresp);
+
+/**
+ * qbman_result_eqresp_set_rspid() - Set the response id in enqueue response.
+ * @eqresp: enqueue response.
+ * @val: values to set into the response id.
+ *
+ * This value is set into the response id before the enqueue command, which,
+ * get overwritten by qbman once the enqueue command is complete.
+ */
+void qbman_result_eqresp_set_rspid(struct qbman_result *eqresp, uint8_t val);
+
+/**
+ * qbman_result_eqresp_rspid() - Get the response id.
+ * @eqresp: enqueue response.
+ *
+ * Return the response id.
+ *
+ * At the time of enqueue user provides the response id. Response id gets
+ * copied into the enqueue response to determine if the command has been
+ * completed, and response has been updated.
+ */
+uint8_t qbman_result_eqresp_rspid(struct qbman_result *eqresp);
+
+/**
+ * qbman_result_eqresp_rc() - determines if enqueue command is sucessful.
+ * @eqresp: enqueue response.
+ *
+ * Return 0 when command is sucessful.
+ */
+uint8_t qbman_result_eqresp_rc(struct qbman_result *eqresp);
+
 /**
  * qbman_swp_enqueue() - Issue an enqueue command.
  * @s: the software portal used for enqueue.
diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c
index 14f4b0344..f49b18097 100644
--- a/drivers/bus/fslmc/qbman/qbman_portal.c
+++ b/drivers/bus/fslmc/qbman/qbman_portal.c
@@ -1569,6 +1569,32 @@ uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn)
 	return qbman_result_SCN_ctx(scn);
 }
 
+/********************/
+/* Parsing EQ RESP  */
+/********************/
+struct qbman_fd *qbman_result_eqresp_fd(struct qbman_result *eqresp)
+{
+	return (struct qbman_fd *)&eqresp->eq_resp.fd[0];
+}
+
+void qbman_result_eqresp_set_rspid(struct qbman_result *eqresp, uint8_t val)
+{
+	eqresp->eq_resp.rspid = val;
+}
+
+uint8_t qbman_result_eqresp_rspid(struct qbman_result *eqresp)
+{
+	return eqresp->eq_resp.rspid;
+}
+
+uint8_t qbman_result_eqresp_rc(struct qbman_result *eqresp)
+{
+	if (eqresp->eq_resp.rc == 0xE)
+		return 0;
+	else
+		return -1;
+}
+
 /******************/
 /* Buffer release */
 /******************/
diff --git a/drivers/bus/fslmc/rte_bus_fslmc_version.map b/drivers/bus/fslmc/rte_bus_fslmc_version.map
index dcc4e082e..811a2e7b9 100644
--- a/drivers/bus/fslmc/rte_bus_fslmc_version.map
+++ b/drivers/bus/fslmc/rte_bus_fslmc_version.map
@@ -120,7 +120,6 @@ DPDK_18.05 {
 
 DPDK_18.11 {
 	global:
-
 	dpaa2_dqrr_size;
 	dpaa2_eqcr_size;
 	dpci_get_link_state;
@@ -129,3 +128,18 @@ DPDK_18.11 {
 	dpci_set_opr;
 
 } DPDK_18.05;
+
+DPDK_19.05 {
+	global:
+	dpaa2_free_eq_descriptors;
+
+	qbman_eq_desc_set_orp;
+	qbman_eq_desc_set_token;
+	qbman_result_DQ_odpid;
+	qbman_result_DQ_seqnum;
+	qbman_result_eqresp_fd;
+	qbman_result_eqresp_rc;
+	qbman_result_eqresp_rspid;
+	qbman_result_eqresp_set_rspid;
+} DPDK_18.11;
+
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index bc3faa8a3..0ab43cadf 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -665,6 +665,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev,
 			return -ret;
 		}
 	}
+	dpaa2_q->cb_eqresp_free = dpaa2_dev_free_eqresp_buf;
 	dev->data->tx_queues[tx_queue_id] = dpaa2_q;
 	return 0;
 }
@@ -894,6 +895,10 @@ dpaa2_dev_start(struct rte_eth_dev *dev)
 		dpaa2_eth_setup_irqs(dev, 1);
 	}
 
+	/* Change the tx burst function if ordered queues are used */
+	if (priv->en_ordered)
+		dev->tx_pkt_burst = dpaa2_dev_tx_ordered;
+
 	return 0;
 }
 
@@ -1793,6 +1798,8 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev,
 		dpaa2_ethq->cb = dpaa2_dev_process_parallel_event;
 	else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC)
 		dpaa2_ethq->cb = dpaa2_dev_process_atomic_event;
+	else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED)
+		dpaa2_ethq->cb = dpaa2_dev_process_ordered_event;
 	else
 		return -EINVAL;
 
@@ -1807,6 +1814,41 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev,
 		cfg.destination.hold_active = 1;
 	}
 
+	if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED &&
+			!eth_priv->en_ordered) {
+		struct opr_cfg ocfg;
+
+		/* Restoration window size = 256 frames */
+		ocfg.oprrws = 3;
+		/* Restoration window size = 512 frames for LX2 */
+		if (dpaa2_svr_family == SVR_LX2160A)
+			ocfg.oprrws = 4;
+		/* Auto advance NESN window enabled */
+		ocfg.oa = 1;
+		/* Late arrival window size disabled */
+		ocfg.olws = 0;
+		/* ORL resource exhaustaion advance NESN disabled */
+		ocfg.oeane = 0;
+		/* Loose ordering enabled */
+		ocfg.oloe = 1;
+		eth_priv->en_loose_ordered = 1;
+		/* Strict ordering enabled if explicitly set */
+		if (getenv("DPAA2_STRICT_ORDERING_ENABLE")) {
+			ocfg.oloe = 0;
+			eth_priv->en_loose_ordered = 0;
+		}
+
+		ret = dpni_set_opr(dpni, CMD_PRI_LOW, eth_priv->token,
+				   dpaa2_ethq->tc_index, flow_id,
+				   OPR_OPT_CREATE, &ocfg);
+		if (ret) {
+			DPAA2_PMD_ERR("Error setting opr: ret: %d\n", ret);
+			return ret;
+		}
+
+		eth_priv->en_ordered = 1;
+	}
+
 	options |= DPNI_QUEUE_OPT_USER_CTX;
 	cfg.user_context = (size_t)(dpaa2_ethq);
 
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 420ad6446..313cbe4bf 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -96,15 +96,17 @@ struct dpaa2_dev_priv {
 	uint16_t token;
 	uint8_t nb_tx_queues;
 	uint8_t nb_rx_queues;
+	uint32_t options;
 	void *rx_vq[MAX_RX_QUEUES];
 	void *tx_vq[MAX_TX_QUEUES];
 
 	struct dpaa2_bp_list *bp_list; /**<Attached buffer pool list */
-	uint32_t options;
 	uint8_t max_mac_filters;
 	uint8_t max_vlan_filters;
 	uint8_t num_rx_tc;
 	uint8_t flags; /*dpaa2 config flags */
+	uint8_t en_ordered;
+	uint8_t en_loose_ordered;
 };
 
 int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
@@ -135,6 +137,15 @@ void dpaa2_dev_process_atomic_event(struct qbman_swp *swp,
 				    const struct qbman_result *dq,
 				    struct dpaa2_queue *rxq,
 				    struct rte_event *ev);
+void dpaa2_dev_process_ordered_event(struct qbman_swp *swp,
+				     const struct qbman_fd *fd,
+				     const struct qbman_result *dq,
+				     struct dpaa2_queue *rxq,
+				     struct rte_event *ev);
 uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts);
+uint16_t dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs,
+			      uint16_t nb_pkts);
 uint16_t dummy_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts);
+void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci);
+
 #endif /* _DPAA2_ETHDEV_H */
diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c
index 2d4b9ef14..1aa184730 100644
--- a/drivers/net/dpaa2/dpaa2_rxtx.c
+++ b/drivers/net/dpaa2/dpaa2_rxtx.c
@@ -699,6 +699,33 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __attribute__((unused)),
 	DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = ev->mbuf;
 }
 
+void __attribute__((hot))
+dpaa2_dev_process_ordered_event(struct qbman_swp *swp,
+				const struct qbman_fd *fd,
+				const struct qbman_result *dq,
+				struct dpaa2_queue *rxq,
+				struct rte_event *ev)
+{
+	rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
+		DPAA2_FD_PTA_SIZE + 16));
+
+	ev->flow_id = rxq->ev.flow_id;
+	ev->sub_event_type = rxq->ev.sub_event_type;
+	ev->event_type = RTE_EVENT_TYPE_ETHDEV;
+	ev->op = RTE_EVENT_OP_NEW;
+	ev->sched_type = rxq->ev.sched_type;
+	ev->queue_id = rxq->ev.queue_id;
+	ev->priority = rxq->ev.priority;
+
+	ev->mbuf = eth_fd_to_mbuf(fd);
+
+	ev->mbuf->seqn = DPAA2_ENQUEUE_FLAG_ORP;
+	ev->mbuf->seqn |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT;
+	ev->mbuf->seqn |= qbman_result_DQ_seqnum(dq) << DPAA2_EQCR_SEQNUM_SHIFT;
+
+	qbman_swp_dqrr_consume(swp, dq);
+}
+
 /*
  * Callback to handle sending packets through WRIOP based interface
  */
@@ -864,6 +891,234 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	return num_tx;
 }
 
+void
+dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci)
+{
+	struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO;
+	struct qbman_fd *fd;
+	struct rte_mbuf *m;
+
+	fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]);
+	m = eth_fd_to_mbuf(fd);
+	rte_pktmbuf_free(m);
+}
+
+static void
+dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q,
+			     struct rte_mbuf *m,
+			     struct qbman_eq_desc *eqdesc)
+{
+	struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
+	struct dpaa2_dev_priv *priv = eth_data->dev_private;
+	struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO;
+	struct eqresp_metadata *eqresp_meta;
+	uint16_t orpid, seqnum;
+	uint8_t dq_idx;
+
+	qbman_eq_desc_set_qd(eqdesc, priv->qdid, dpaa2_q->flow_id,
+			     dpaa2_q->tc_index);
+
+	if (m->seqn & DPAA2_ENQUEUE_FLAG_ORP) {
+		orpid = (m->seqn & DPAA2_EQCR_OPRID_MASK) >>
+			DPAA2_EQCR_OPRID_SHIFT;
+		seqnum = (m->seqn & DPAA2_EQCR_SEQNUM_MASK) >>
+			DPAA2_EQCR_SEQNUM_SHIFT;
+
+		if (!priv->en_loose_ordered) {
+			qbman_eq_desc_set_orp(eqdesc, 1, orpid, seqnum, 0);
+			qbman_eq_desc_set_response(eqdesc, (uint64_t)
+				DPAA2_VADDR_TO_IOVA(&dpio_dev->eqresp[
+				dpio_dev->eqresp_pi]), 1);
+			qbman_eq_desc_set_token(eqdesc, 1);
+
+			eqresp_meta = &dpio_dev->eqresp_meta[
+				dpio_dev->eqresp_pi];
+			eqresp_meta->dpaa2_q = dpaa2_q;
+			eqresp_meta->mp = m->pool;
+
+			dpio_dev->eqresp_pi + 1 < MAX_EQ_RESP_ENTRIES ?
+				dpio_dev->eqresp_pi++ :
+				(dpio_dev->eqresp_pi = 0);
+		} else {
+			qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0);
+		}
+	} else {
+		dq_idx = m->seqn - 1;
+		qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0);
+		DPAA2_PER_LCORE_DQRR_SIZE--;
+		DPAA2_PER_LCORE_DQRR_HELD &= ~(1 << dq_idx);
+	}
+	m->seqn = DPAA2_INVALID_MBUF_SEQN;
+}
+
+/* Callback to handle sending ordered packets through WRIOP based interface */
+uint16_t
+dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	/* Function to transmit the frames to given device and VQ*/
+	struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
+	struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
+	struct dpaa2_dev_priv *priv = eth_data->dev_private;
+	struct dpaa2_queue *order_sendq = (struct dpaa2_queue *)priv->tx_vq[0];
+	struct qbman_fd fd_arr[MAX_TX_RING_SLOTS];
+	struct rte_mbuf *mi;
+	struct rte_mempool *mp;
+	struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS];
+	struct qbman_swp *swp;
+	uint32_t frames_to_send, num_free_eq_desc;
+	uint32_t loop, retry_count;
+	int32_t ret;
+	uint16_t num_tx = 0;
+	uint16_t bpid;
+
+	if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
+		ret = dpaa2_affine_qbman_swp();
+		if (ret) {
+			DPAA2_PMD_ERR("Failure in affining portal");
+			return 0;
+		}
+	}
+	swp = DPAA2_PER_LCORE_PORTAL;
+
+	DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d\n",
+			   eth_data, dpaa2_q->fqid);
+
+	/* This would also handle normal and atomic queues as any type
+	 * of packet can be enqueued when ordered queues are being used.
+	 */
+	while (nb_pkts) {
+		/*Check if the queue is congested*/
+		retry_count = 0;
+		while (qbman_result_SCN_state(dpaa2_q->cscn)) {
+			retry_count++;
+			/* Retry for some time before giving up */
+			if (retry_count > CONG_RETRY_COUNT)
+				goto skip_tx;
+		}
+
+		frames_to_send = (nb_pkts > dpaa2_eqcr_size) ?
+			dpaa2_eqcr_size : nb_pkts;
+
+		if (!priv->en_loose_ordered) {
+			if ((*bufs)->seqn & DPAA2_ENQUEUE_FLAG_ORP) {
+				num_free_eq_desc = dpaa2_free_eq_descriptors();
+				if (num_free_eq_desc < frames_to_send)
+					frames_to_send = num_free_eq_desc;
+			}
+		}
+
+		for (loop = 0; loop < frames_to_send; loop++) {
+			/*Prepare enqueue descriptor*/
+			qbman_eq_desc_clear(&eqdesc[loop]);
+
+			if ((*bufs)->seqn) {
+				/* Use only queue 0 for Tx in case of atomic/
+				 * ordered packets as packets can get unordered
+				 * when being tranmitted out from the interface
+				 */
+				dpaa2_set_enqueue_descriptor(order_sendq,
+							     (*bufs),
+							     &eqdesc[loop]);
+			} else {
+				qbman_eq_desc_set_no_orp(&eqdesc[loop],
+							 DPAA2_EQ_RESP_ERR_FQ);
+				qbman_eq_desc_set_qd(&eqdesc[loop], priv->qdid,
+						     dpaa2_q->flow_id,
+						     dpaa2_q->tc_index);
+			}
+
+			if (likely(RTE_MBUF_DIRECT(*bufs))) {
+				mp = (*bufs)->pool;
+				/* Check the basic scenario and set
+				 * the FD appropriately here itself.
+				 */
+				if (likely(mp && mp->ops_index ==
+				    priv->bp_list->dpaa2_ops_index &&
+				    (*bufs)->nb_segs == 1 &&
+				    rte_mbuf_refcnt_read((*bufs)) == 1)) {
+					if (unlikely((*bufs)->ol_flags
+						& PKT_TX_VLAN_PKT)) {
+					  ret = rte_vlan_insert(bufs);
+					  if (ret)
+						goto send_n_return;
+					}
+					DPAA2_MBUF_TO_CONTIG_FD((*bufs),
+						&fd_arr[loop],
+						mempool_to_bpid(mp));
+					bufs++;
+					continue;
+				}
+			} else {
+				mi = rte_mbuf_from_indirect(*bufs);
+				mp = mi->pool;
+			}
+			/* Not a hw_pkt pool allocated frame */
+			if (unlikely(!mp || !priv->bp_list)) {
+				DPAA2_PMD_ERR("Err: No buffer pool attached");
+				goto send_n_return;
+			}
+
+			if (mp->ops_index != priv->bp_list->dpaa2_ops_index) {
+				DPAA2_PMD_WARN("Non DPAA2 buffer pool");
+				/* alloc should be from the default buffer pool
+				 * attached to this interface
+				 */
+				bpid = priv->bp_list->buf_pool.bpid;
+
+				if (unlikely((*bufs)->nb_segs > 1)) {
+					DPAA2_PMD_ERR(
+						"S/G not supp for non hw offload buffer");
+					goto send_n_return;
+				}
+				if (eth_copy_mbuf_to_fd(*bufs,
+							&fd_arr[loop], bpid)) {
+					goto send_n_return;
+				}
+				/* free the original packet */
+				rte_pktmbuf_free(*bufs);
+			} else {
+				bpid = mempool_to_bpid(mp);
+				if (unlikely((*bufs)->nb_segs > 1)) {
+					if (eth_mbuf_to_sg_fd(*bufs,
+							      &fd_arr[loop],
+							      bpid))
+						goto send_n_return;
+				} else {
+					eth_mbuf_to_fd(*bufs,
+						       &fd_arr[loop], bpid);
+				}
+			}
+			bufs++;
+		}
+		loop = 0;
+		while (loop < frames_to_send) {
+			loop += qbman_swp_enqueue_multiple_desc(swp,
+					&eqdesc[loop], &fd_arr[loop],
+					frames_to_send - loop);
+		}
+
+		num_tx += frames_to_send;
+		nb_pkts -= frames_to_send;
+	}
+	dpaa2_q->tx_pkts += num_tx;
+	return num_tx;
+
+send_n_return:
+	/* send any already prepared fd */
+	if (loop) {
+		unsigned int i = 0;
+
+		while (i < loop) {
+			i += qbman_swp_enqueue_multiple_desc(swp, &eqdesc[loop],
+							&fd_arr[i], loop - i);
+		}
+		num_tx += loop;
+	}
+skip_tx:
+	dpaa2_q->tx_pkts += num_tx;
+	return num_tx;
+}
+
 /**
  * Dummy DPDK callback for TX.
  *
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] net/dpaa2: add support for 16 Rx Queues per traffic class
  2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
  2019-02-22 11:15 ` [PATCH 2/6] mempool/dpaa2: fix to reduce continuous print on empty pool Hemant Agrawal
  2019-02-22 11:16 ` [PATCH 3/6] bus/fslmc: add enqueue response read routines in qbman Hemant Agrawal
@ 2019-02-22 11:16 ` Hemant Agrawal
  2019-02-22 11:16 ` [PATCH 5/6] net/dpaa2: support low level loopback tester Hemant Agrawal
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Hemant Agrawal @ 2019-02-22 11:16 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, Shreyansh Jain, Ashish Jain

From: Ashish Jain <ashish.jain@nxp.com>

Adding support for 16 queues per TC per DPNI port
which is required for LX2 platform.

Signed-off-by: Ashish Jain <ashish.jain@nxp.com>
---
 drivers/net/dpaa2/dpaa2_ethdev.c | 6 ++++--
 drivers/net/dpaa2/dpaa2_ethdev.h | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 0ab43cadf..f8c2983b9 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -266,6 +266,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev)
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 	uint16_t dist_idx;
 	uint32_t vq_id;
+	uint8_t num_rxqueue_per_tc;
 	struct dpaa2_queue *mc_q, *mcq;
 	uint32_t tot_queues;
 	int i;
@@ -273,6 +274,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev)
 
 	PMD_INIT_FUNC_TRACE();
 
+	num_rxqueue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc);
 	tot_queues = priv->nb_rx_queues + priv->nb_tx_queues;
 	mc_q = rte_malloc(NULL, sizeof(struct dpaa2_queue) * tot_queues,
 			  RTE_CACHE_LINE_SIZE);
@@ -311,8 +313,8 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev)
 	vq_id = 0;
 	for (dist_idx = 0; dist_idx < priv->nb_rx_queues; dist_idx++) {
 		mcq = (struct dpaa2_queue *)priv->rx_vq[vq_id];
-		mcq->tc_index = DPAA2_DEF_TC;
-		mcq->flow_id = dist_idx;
+		mcq->tc_index = dist_idx / num_rxqueue_per_tc;
+		mcq->flow_id = dist_idx % num_rxqueue_per_tc;
 		vq_id++;
 	}
 
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 313cbe4bf..13259be7d 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -20,7 +20,7 @@
 #define DPAA2_MAX_RX_PKT_LEN  10240 /*WRIOP support*/
 
 #define MAX_TCS			DPNI_MAX_TC
-#define MAX_RX_QUEUES		16
+#define MAX_RX_QUEUES		128
 #define MAX_TX_QUEUES		16
 
 /*default tc to be used for ,congestion, distribution etc configuration. */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] net/dpaa2: support low level loopback tester
  2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
                   ` (2 preceding siblings ...)
  2019-02-22 11:16 ` [PATCH 4/6] net/dpaa2: add support for 16 Rx Queues per traffic class Hemant Agrawal
@ 2019-02-22 11:16 ` Hemant Agrawal
  2019-02-22 11:16 ` [PATCH 6/6] net/dpaa2: add basic support for generic flow Hemant Agrawal
  2019-02-27  9:30 ` [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Ferruh Yigit
  5 siblings, 0 replies; 7+ messages in thread
From: Hemant Agrawal @ 2019-02-22 11:16 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, Shreyansh Jain

Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 doc/guides/nics/dpaa2.rst                     |   5 +
 .../fslmc/qbman/include/fsl_qbman_portal.h    |  18 ++
 drivers/bus/fslmc/qbman/qbman_portal.c        | 161 ++++++++++++++++++
 drivers/bus/fslmc/rte_bus_fslmc_version.map   |   1 +
 drivers/net/dpaa2/dpaa2_ethdev.c              |  57 ++++++-
 drivers/net/dpaa2/dpaa2_ethdev.h              |   3 +
 drivers/net/dpaa2/dpaa2_rxtx.c                | 161 ++++++++++++++++++
 7 files changed, 402 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst
index 769dc4e12..392ab0580 100644
--- a/doc/guides/nics/dpaa2.rst
+++ b/doc/guides/nics/dpaa2.rst
@@ -499,6 +499,11 @@ for details.
       Done
       testpmd>
 
+
+* Use dev arg option ``drv_loopback=1`` to loopback packets at
+  driver level. Any packet received will be reflected back by the
+  driver on same port.
+
 Enabling logs
 -------------
 
diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h
index a9192d3cb..07b8a4372 100644
--- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h
+++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h
@@ -1039,6 +1039,24 @@ int qbman_swp_enqueue_multiple(struct qbman_swp *s,
 			       const struct qbman_fd *fd,
 			       uint32_t *flags,
 			       int num_frames);
+
+/**
+ * qbman_swp_enqueue_multiple_fd() - Enqueue multiple frames with same
+				  eq descriptor
+ * @s: the software portal used for enqueue.
+ * @d: the enqueue descriptor.
+ * @fd: the frame descriptor to be enqueued.
+ * @flags: bit-mask of QBMAN_ENQUEUE_FLAG_*** options
+ * @num_frames: the number of the frames to be enqueued.
+ *
+ * Return the number of enqueued frames, -EBUSY if the EQCR is not ready.
+ */
+int qbman_swp_enqueue_multiple_fd(struct qbman_swp *s,
+				  const struct qbman_eq_desc *d,
+				  struct qbman_fd **fd,
+				  uint32_t *flags,
+				  int num_frames);
+
 /**
  * qbman_swp_enqueue_multiple_desc() - Enqueue multiple frames with
  *				       individual eq descriptor.
diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c
index f49b18097..20da8b921 100644
--- a/drivers/bus/fslmc/qbman/qbman_portal.c
+++ b/drivers/bus/fslmc/qbman/qbman_portal.c
@@ -93,6 +93,20 @@ qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
 		uint32_t *flags,
 		int num_frames);
 
+static int
+qbman_swp_enqueue_multiple_fd_direct(struct qbman_swp *s,
+		const struct qbman_eq_desc *d,
+		struct qbman_fd **fd,
+		uint32_t *flags,
+		int num_frames);
+
+static int
+qbman_swp_enqueue_multiple_fd_mem_back(struct qbman_swp *s,
+		const struct qbman_eq_desc *d,
+		struct qbman_fd **fd,
+		uint32_t *flags,
+		int num_frames);
+
 static int
 qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
 		const struct qbman_eq_desc *d,
@@ -139,6 +153,13 @@ static int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
 		int num_frames)
 	= qbman_swp_enqueue_multiple_direct;
 
+static int (*qbman_swp_enqueue_multiple_fd_ptr)(struct qbman_swp *s,
+		const struct qbman_eq_desc *d,
+		struct qbman_fd **fd,
+		uint32_t *flags,
+		int num_frames)
+	= qbman_swp_enqueue_multiple_fd_direct;
+
 static int (*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
 		const struct qbman_eq_desc *d,
 		const struct qbman_fd *fd,
@@ -243,6 +264,8 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
 				qbman_swp_enqueue_ring_mode_mem_back;
 		qbman_swp_enqueue_multiple_ptr =
 				qbman_swp_enqueue_multiple_mem_back;
+		qbman_swp_enqueue_multiple_fd_ptr =
+				qbman_swp_enqueue_multiple_fd_mem_back;
 		qbman_swp_enqueue_multiple_desc_ptr =
 				qbman_swp_enqueue_multiple_desc_mem_back;
 		qbman_swp_pull_ptr = qbman_swp_pull_mem_back;
@@ -862,6 +885,144 @@ inline int qbman_swp_enqueue_multiple(struct qbman_swp *s,
 	return qbman_swp_enqueue_multiple_ptr(s, d, fd, flags, num_frames);
 }
 
+static int qbman_swp_enqueue_multiple_fd_direct(struct qbman_swp *s,
+						const struct qbman_eq_desc *d,
+						struct qbman_fd **fd,
+						uint32_t *flags,
+						int num_frames)
+{
+	uint32_t *p = NULL;
+	const uint32_t *cl = qb_cl(d);
+	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
+	int i, num_enqueued = 0;
+	uint64_t addr_cena;
+
+	half_mask = (s->eqcr.pi_ci_mask>>1);
+	full_mask = s->eqcr.pi_ci_mask;
+	if (!s->eqcr.available) {
+		eqcr_ci = s->eqcr.ci;
+		s->eqcr.ci = qbman_cena_read_reg(&s->sys,
+				QBMAN_CENA_SWP_EQCR_CI) & full_mask;
+		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
+				eqcr_ci, s->eqcr.ci);
+		if (!s->eqcr.available)
+			return 0;
+	}
+
+	eqcr_pi = s->eqcr.pi;
+	num_enqueued = (s->eqcr.available < num_frames) ?
+			s->eqcr.available : num_frames;
+	s->eqcr.available -= num_enqueued;
+	/* Fill in the EQCR ring */
+	for (i = 0; i < num_enqueued; i++) {
+		p = qbman_cena_write_start_wo_shadow(&s->sys,
+				QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
+		memcpy(&p[1], &cl[1], 28);
+		memcpy(&p[8], fd[i], sizeof(struct qbman_fd));
+		eqcr_pi++;
+	}
+
+	lwsync();
+
+	/* Set the verb byte, have to substitute in the valid-bit */
+	eqcr_pi = s->eqcr.pi;
+	for (i = 0; i < num_enqueued; i++) {
+		p = qbman_cena_write_start_wo_shadow(&s->sys,
+				QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
+		p[0] = cl[0] | s->eqcr.pi_vb;
+		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
+			struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
+
+			d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
+				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
+		}
+		eqcr_pi++;
+		if (!(eqcr_pi & half_mask))
+			s->eqcr.pi_vb ^= QB_VALID_BIT;
+	}
+
+	/* Flush all the cacheline without load/store in between */
+	eqcr_pi = s->eqcr.pi;
+	addr_cena = (size_t)s->sys.addr_cena;
+	for (i = 0; i < num_enqueued; i++) {
+		dcbf(addr_cena +
+			QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
+		eqcr_pi++;
+	}
+	s->eqcr.pi = eqcr_pi & full_mask;
+
+	return num_enqueued;
+}
+
+static int qbman_swp_enqueue_multiple_fd_mem_back(struct qbman_swp *s,
+						  const struct qbman_eq_desc *d,
+						  struct qbman_fd **fd,
+						  uint32_t *flags,
+						  int num_frames)
+{
+	uint32_t *p = NULL;
+	const uint32_t *cl = qb_cl(d);
+	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
+	int i, num_enqueued = 0;
+
+	half_mask = (s->eqcr.pi_ci_mask>>1);
+	full_mask = s->eqcr.pi_ci_mask;
+	if (!s->eqcr.available) {
+		eqcr_ci = s->eqcr.ci;
+		s->eqcr.ci = qbman_cena_read_reg(&s->sys,
+				QBMAN_CENA_SWP_EQCR_CI_MEMBACK) & full_mask;
+		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
+					eqcr_ci, s->eqcr.ci);
+		if (!s->eqcr.available)
+			return 0;
+	}
+
+	eqcr_pi = s->eqcr.pi;
+	num_enqueued = (s->eqcr.available < num_frames) ?
+			s->eqcr.available : num_frames;
+	s->eqcr.available -= num_enqueued;
+	/* Fill in the EQCR ring */
+	for (i = 0; i < num_enqueued; i++) {
+		p = qbman_cena_write_start_wo_shadow(&s->sys,
+				QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
+		memcpy(&p[1], &cl[1], 28);
+		memcpy(&p[8], fd[i], sizeof(struct qbman_fd));
+		eqcr_pi++;
+	}
+
+	/* Set the verb byte, have to substitute in the valid-bit */
+	eqcr_pi = s->eqcr.pi;
+	for (i = 0; i < num_enqueued; i++) {
+		p = qbman_cena_write_start_wo_shadow(&s->sys,
+				QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
+		p[0] = cl[0] | s->eqcr.pi_vb;
+		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
+			struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
+
+			d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
+				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
+		}
+		eqcr_pi++;
+		if (!(eqcr_pi & half_mask))
+			s->eqcr.pi_vb ^= QB_VALID_BIT;
+	}
+	s->eqcr.pi = eqcr_pi & full_mask;
+
+	dma_wmb();
+	qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_EQCR_PI,
+				(QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
+	return num_enqueued;
+}
+
+inline int qbman_swp_enqueue_multiple_fd(struct qbman_swp *s,
+					 const struct qbman_eq_desc *d,
+					 struct qbman_fd **fd,
+					 uint32_t *flags,
+					 int num_frames)
+{
+	return qbman_swp_enqueue_multiple_fd_ptr(s, d, fd, flags, num_frames);
+}
+
 static int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
 					const struct qbman_eq_desc *d,
 					const struct qbman_fd *fd,
diff --git a/drivers/bus/fslmc/rte_bus_fslmc_version.map b/drivers/bus/fslmc/rte_bus_fslmc_version.map
index 811a2e7b9..aa844dd80 100644
--- a/drivers/bus/fslmc/rte_bus_fslmc_version.map
+++ b/drivers/bus/fslmc/rte_bus_fslmc_version.map
@@ -141,5 +141,6 @@ DPDK_19.05 {
 	qbman_result_eqresp_rc;
 	qbman_result_eqresp_rspid;
 	qbman_result_eqresp_set_rspid;
+	qbman_swp_enqueue_multiple_fd;
 } DPDK_18.11;
 
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index f8c2983b9..08a95a14a 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -27,6 +27,8 @@
 #include "dpaa2_ethdev.h"
 #include <fsl_qbman_debug.h>
 
+#define DRIVER_LOOPBACK_MODE "drv_looback"
+
 /* Supported Rx offloads */
 static uint64_t dev_rx_offloads_sup =
 		DEV_RX_OFFLOAD_VLAN_STRIP |
@@ -732,7 +734,8 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_UNKNOWN
 	};
 
-	if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx)
+	if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx ||
+		dev->rx_pkt_burst == dpaa2_dev_loopback_rx)
 		return ptypes;
 	return NULL;
 }
@@ -1997,6 +2000,43 @@ populate_mac_addr(struct fsl_mc_io *dpni_dev, struct dpaa2_dev_priv *priv,
 	return -1;
 }
 
+static int
+check_devargs_handler(__rte_unused const char *key, const char *value,
+		      __rte_unused void *opaque)
+{
+	if (strcmp(value, "1"))
+		return -1;
+
+	return 0;
+}
+
+static int
+dpaa2_get_devargs(struct rte_devargs *devargs, const char *key)
+{
+	struct rte_kvargs *kvlist;
+
+	if (!devargs)
+		return 0;
+
+	kvlist = rte_kvargs_parse(devargs->args, NULL);
+	if (!kvlist)
+		return 0;
+
+	if (!rte_kvargs_count(kvlist, key)) {
+		rte_kvargs_free(kvlist);
+		return 0;
+	}
+
+	if (rte_kvargs_process(kvlist, key,
+			       check_devargs_handler, NULL) < 0) {
+		rte_kvargs_free(kvlist);
+		return 0;
+	}
+	rte_kvargs_free(kvlist);
+
+	return 1;
+}
+
 static int
 dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 {
@@ -2016,7 +2056,10 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 		 * plugged.
 		 */
 		eth_dev->dev_ops = &dpaa2_ethdev_ops;
-		eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx;
+		if (dpaa2_get_devargs(dev->devargs, DRIVER_LOOPBACK_MODE))
+			eth_dev->rx_pkt_burst = dpaa2_dev_loopback_rx;
+		else
+			eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx;
 		eth_dev->tx_pkt_burst = dpaa2_dev_tx;
 		return 0;
 	}
@@ -2133,7 +2176,12 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 
 	eth_dev->dev_ops = &dpaa2_ethdev_ops;
 
-	eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx;
+	if (dpaa2_get_devargs(dev->devargs, DRIVER_LOOPBACK_MODE)) {
+		eth_dev->rx_pkt_burst = dpaa2_dev_loopback_rx;
+		DPAA2_PMD_INFO("Loopback mode");
+	} else {
+		eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx;
+	}
 	eth_dev->tx_pkt_burst = dpaa2_dev_tx;
 
 	RTE_LOG(INFO, PMD, "%s: netdev created\n", eth_dev->data->name);
@@ -2251,7 +2299,8 @@ static struct rte_dpaa2_driver rte_dpaa2_pmd = {
 };
 
 RTE_PMD_REGISTER_DPAA2(net_dpaa2, rte_dpaa2_pmd);
-
+RTE_PMD_REGISTER_PARAM_STRING(net_dpaa2,
+		DRIVER_LOOPBACK_MODE "=<int>");
 RTE_INIT(dpaa2_pmd_init_log)
 {
 	dpaa2_logtype_pmd = rte_log_register("pmd.net.dpaa2");
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 13259be7d..7148104ec 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -125,6 +125,9 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev,
 int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev,
 		int eth_rx_queue_id);
 
+uint16_t dpaa2_dev_loopback_rx(void *queue, struct rte_mbuf **bufs,
+				uint16_t nb_pkts);
+
 uint16_t dpaa2_dev_prefetch_rx(void *queue, struct rte_mbuf **bufs,
 			       uint16_t nb_pkts);
 void dpaa2_dev_process_parallel_event(struct qbman_swp *swp,
diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c
index 1aa184730..c6e50123c 100644
--- a/drivers/net/dpaa2/dpaa2_rxtx.c
+++ b/drivers/net/dpaa2/dpaa2_rxtx.c
@@ -1143,3 +1143,164 @@ dummy_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	(void)nb_pkts;
 	return 0;
 }
+
+#if defined(RTE_TOOLCHAIN_GCC)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#elif defined(RTE_TOOLCHAIN_CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-qual"
+#endif
+
+/* This function loopbacks all the received packets.*/
+uint16_t
+dpaa2_dev_loopback_rx(void *queue,
+		      struct rte_mbuf **bufs __rte_unused,
+		      uint16_t nb_pkts)
+{
+	/* Function receive frames for a given device and VQ*/
+	struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
+	struct qbman_result *dq_storage, *dq_storage1 = NULL;
+	uint32_t fqid = dpaa2_q->fqid;
+	int ret, num_rx = 0, num_tx = 0, pull_size;
+	uint8_t pending, status;
+	struct qbman_swp *swp;
+	struct qbman_fd *fd[DPAA2_LX2_DQRR_RING_SIZE];
+	struct qbman_pull_desc pulldesc;
+	struct qbman_eq_desc eqdesc;
+	struct queue_storage_info_t *q_storage = dpaa2_q->q_storage;
+	struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
+	struct dpaa2_dev_priv *priv = eth_data->dev_private;
+	struct dpaa2_queue *tx_q = priv->tx_vq[0];
+	/* todo - currently we are using 1st TX queue only for loopback*/
+
+	if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) {
+		ret = dpaa2_affine_qbman_ethrx_swp();
+		if (ret) {
+			DPAA2_PMD_ERR("Failure in affining portal");
+			return 0;
+		}
+	}
+	swp = DPAA2_PER_LCORE_ETHRX_PORTAL;
+	pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts;
+	if (unlikely(!q_storage->active_dqs)) {
+		q_storage->toggle = 0;
+		dq_storage = q_storage->dq_storage[q_storage->toggle];
+		q_storage->last_num_pkts = pull_size;
+		qbman_pull_desc_clear(&pulldesc);
+		qbman_pull_desc_set_numframes(&pulldesc,
+					      q_storage->last_num_pkts);
+		qbman_pull_desc_set_fq(&pulldesc, fqid);
+		qbman_pull_desc_set_storage(&pulldesc, dq_storage,
+			(size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
+		if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) {
+			while (!qbman_check_command_complete(
+			       get_swp_active_dqs(
+			       DPAA2_PER_LCORE_ETHRX_DPIO->index)))
+				;
+			clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index);
+		}
+		while (1) {
+			if (qbman_swp_pull(swp, &pulldesc)) {
+				DPAA2_PMD_DP_DEBUG(
+					"VDQ command not issued.QBMAN busy\n");
+				/* Portal was busy, try again */
+				continue;
+			}
+			break;
+		}
+		q_storage->active_dqs = dq_storage;
+		q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index;
+		set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index,
+				   dq_storage);
+	}
+
+	dq_storage = q_storage->active_dqs;
+	rte_prefetch0((void *)(size_t)(dq_storage));
+	rte_prefetch0((void *)(size_t)(dq_storage + 1));
+
+	/* Prepare next pull descriptor. This will give space for the
+	 * prefething done on DQRR entries
+	 */
+	q_storage->toggle ^= 1;
+	dq_storage1 = q_storage->dq_storage[q_storage->toggle];
+	qbman_pull_desc_clear(&pulldesc);
+	qbman_pull_desc_set_numframes(&pulldesc, pull_size);
+	qbman_pull_desc_set_fq(&pulldesc, fqid);
+	qbman_pull_desc_set_storage(&pulldesc, dq_storage1,
+		(size_t)(DPAA2_VADDR_TO_IOVA(dq_storage1)), 1);
+
+	/*Prepare enqueue descriptor*/
+	qbman_eq_desc_clear(&eqdesc);
+	qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ);
+	qbman_eq_desc_set_response(&eqdesc, 0, 0);
+	qbman_eq_desc_set_fq(&eqdesc, tx_q->fqid);
+
+	/* Check if the previous issued command is completed.
+	 * Also seems like the SWP is shared between the Ethernet Driver
+	 * and the SEC driver.
+	 */
+	while (!qbman_check_command_complete(dq_storage))
+		;
+	if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id))
+		clear_swp_active_dqs(q_storage->active_dpio_id);
+
+	pending = 1;
+
+	do {
+		/* Loop until the dq_storage is updated with
+		 * new token by QBMAN
+		 */
+		while (!qbman_check_new_result(dq_storage))
+			;
+		rte_prefetch0((void *)((size_t)(dq_storage + 2)));
+		/* Check whether Last Pull command is Expired and
+		 * setting Condition for Loop termination
+		 */
+		if (qbman_result_DQ_is_pull_complete(dq_storage)) {
+			pending = 0;
+			/* Check for valid frame. */
+			status = qbman_result_DQ_flags(dq_storage);
+			if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0))
+				continue;
+		}
+		fd[num_rx] = (struct qbman_fd *)qbman_result_DQ_fd(dq_storage);
+
+		dq_storage++;
+		num_rx++;
+	} while (pending);
+
+	while (num_tx < num_rx) {
+		num_tx += qbman_swp_enqueue_multiple_fd(swp, &eqdesc,
+				&fd[num_tx], 0, num_rx - num_tx);
+	}
+
+	if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) {
+		while (!qbman_check_command_complete(
+		       get_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)))
+			;
+		clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index);
+	}
+	/* issue a volatile dequeue command for next pull */
+	while (1) {
+		if (qbman_swp_pull(swp, &pulldesc)) {
+			DPAA2_PMD_DP_DEBUG("VDQ command is not issued."
+					  "QBMAN is busy (2)\n");
+			continue;
+		}
+		break;
+	}
+	q_storage->active_dqs = dq_storage1;
+	q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index;
+	set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, dq_storage1);
+
+	dpaa2_q->rx_pkts += num_rx;
+	dpaa2_q->tx_pkts += num_tx;
+
+	return 0;
+}
+#if defined(RTE_TOOLCHAIN_GCC)
+#pragma GCC diagnostic pop
+#elif defined(RTE_TOOLCHAIN_CLANG)
+#pragma clang diagnostic pop
+#endif
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] net/dpaa2: add basic support for generic flow
  2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
                   ` (3 preceding siblings ...)
  2019-02-22 11:16 ` [PATCH 5/6] net/dpaa2: support low level loopback tester Hemant Agrawal
@ 2019-02-22 11:16 ` Hemant Agrawal
  2019-02-27  9:30 ` [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Ferruh Yigit
  5 siblings, 0 replies; 7+ messages in thread
From: Hemant Agrawal @ 2019-02-22 11:16 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, Shreyansh Jain, Sunil Kumar Kori

From: Sunil Kumar Kori <sunil.kori@nxp.com>

Signed-off-by: Sunil Kumar Kori <sunil.kori@nxp.com>
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 drivers/net/dpaa2/Makefile             |    1 +
 drivers/net/dpaa2/base/dpaa2_hw_dpni.c |    4 +-
 drivers/net/dpaa2/dpaa2_ethdev.c       |   90 +-
 drivers/net/dpaa2/dpaa2_ethdev.h       |   22 +
 drivers/net/dpaa2/dpaa2_flow.c         | 1972 ++++++++++++++++++++++++
 drivers/net/dpaa2/mc/dpni.c            |  312 ++++
 drivers/net/dpaa2/mc/fsl_dpni.h        |  154 ++
 drivers/net/dpaa2/mc/fsl_dpni_cmd.h    |   88 ++
 drivers/net/dpaa2/meson.build          |    1 +
 9 files changed, 2635 insertions(+), 9 deletions(-)
 create mode 100644 drivers/net/dpaa2/dpaa2_flow.c

diff --git a/drivers/net/dpaa2/Makefile b/drivers/net/dpaa2/Makefile
index 562551175..8bd269bfa 100644
--- a/drivers/net/dpaa2/Makefile
+++ b/drivers/net/dpaa2/Makefile
@@ -33,6 +33,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += base/dpaa2_hw_dpni.c
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_mux.c
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += mc/dpni.c
 SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += mc/dpkg.c
diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
index 11f14931e..56e2e56a3 100644
--- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
+++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
@@ -23,7 +23,7 @@
 
 #include "../dpaa2_ethdev.h"
 
-static int
+int
 dpaa2_distset_to_dpkg_profile_cfg(
 		uint64_t req_dist_set,
 		struct dpkg_profile_cfg *kg_cfg);
@@ -170,7 +170,7 @@ int dpaa2_remove_flow_dist(
 	return ret;
 }
 
-static int
+int
 dpaa2_distset_to_dpkg_profile_cfg(
 		uint64_t req_dist_set,
 		struct dpkg_profile_cfg *kg_cfg)
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 08a95a14a..a8f0e3002 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -17,6 +17,7 @@
 #include <rte_kvargs.h>
 #include <rte_dev.h>
 #include <rte_fslmc.h>
+#include <rte_flow_driver.h>
 
 #include "dpaa2_pmd_logs.h"
 #include <fslmc_vfio.h>
@@ -83,6 +84,14 @@ static const struct rte_dpaa2_xstats_name_off dpaa2_xstats_strings[] = {
 	{"egress_confirmed_frames", 2, 4},
 };
 
+static const enum rte_filter_op dpaa2_supported_filter_ops[] = {
+	RTE_ETH_FILTER_ADD,
+	RTE_ETH_FILTER_DELETE,
+	RTE_ETH_FILTER_UPDATE,
+	RTE_ETH_FILTER_FLUSH,
+	RTE_ETH_FILTER_GET
+};
+
 static struct rte_dpaa2_driver rte_dpaa2_pmd;
 static int dpaa2_dev_uninit(struct rte_eth_dev *eth_dev);
 static int dpaa2_dev_link_update(struct rte_eth_dev *dev,
@@ -1892,6 +1901,47 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev,
 	return ret;
 }
 
+static inline int
+dpaa2_dev_verify_filter_ops(enum rte_filter_op filter_op)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(dpaa2_supported_filter_ops); i++) {
+		if (dpaa2_supported_filter_ops[i] == filter_op)
+			return 0;
+	}
+	return -ENOTSUP;
+}
+
+static int
+dpaa2_dev_flow_ctrl(struct rte_eth_dev *dev,
+		    enum rte_filter_type filter_type,
+				 enum rte_filter_op filter_op,
+				 void *arg)
+{
+	int ret = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	switch (filter_type) {
+	case RTE_ETH_FILTER_GENERIC:
+		if (dpaa2_dev_verify_filter_ops(filter_op) < 0) {
+			ret = -ENOTSUP;
+			break;
+		}
+		*(const void **)arg = &dpaa2_flow_ops;
+		dpaa2_filter_type |= filter_type;
+		break;
+	default:
+		RTE_LOG(ERR, PMD, "Filter type (%d) not supported",
+			filter_type);
+		ret = -ENOTSUP;
+		break;
+	}
+	return ret;
+}
+
 static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.dev_configure	  = dpaa2_eth_dev_configure,
 	.dev_start	      = dpaa2_dev_start,
@@ -1930,6 +1980,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.mac_addr_set         = dpaa2_dev_set_mac_addr,
 	.rss_hash_update      = dpaa2_dev_rss_hash_update,
 	.rss_hash_conf_get    = dpaa2_dev_rss_hash_conf_get,
+	.filter_ctrl          = dpaa2_dev_flow_ctrl,
 };
 
 /* Populate the mac address from physically available (u-boot/firmware) and/or
@@ -2046,7 +2097,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 	struct dpni_attr attr;
 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
 	struct dpni_buffer_layout layout;
-	int ret, hw_id;
+	int ret, hw_id, i;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -2102,11 +2153,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 
 	priv->num_rx_tc = attr.num_rx_tcs;
 
-	/* Resetting the "num_rx_queues" to equal number of queues in first TC
-	 * as only one TC is supported on Rx Side. Once Multiple TCs will be
-	 * in use for Rx processing then this will be changed or removed.
-	 */
-	priv->nb_rx_queues = attr.num_queues;
+	for (i = 0; i < attr.num_rx_tcs; i++)
+		priv->nb_rx_queues += attr.num_queues;
 
 	/* Using number of TX queues as number of TX TCs */
 	priv->nb_tx_queues = attr.num_tx_tcs;
@@ -2184,6 +2232,26 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 	}
 	eth_dev->tx_pkt_burst = dpaa2_dev_tx;
 
+	/*Init fields w.r.t. classficaition*/
+	memset(&priv->extract.qos_key_cfg, 0, sizeof(struct dpkg_profile_cfg));
+	priv->extract.qos_extract_param = (size_t)rte_malloc(NULL, 256, 64);
+	if (!priv->extract.qos_extract_param) {
+		DPAA2_PMD_ERR(" Error(%d) in allocation resources for flow "
+			    " classificaiton ", ret);
+		goto init_err;
+	}
+	for (i = 0; i < MAX_TCS; i++) {
+		memset(&priv->extract.fs_key_cfg[i], 0,
+			sizeof(struct dpkg_profile_cfg));
+		priv->extract.fs_extract_param[i] =
+			(size_t)rte_malloc(NULL, 256, 64);
+		if (!priv->extract.fs_extract_param[i]) {
+			DPAA2_PMD_ERR(" Error(%d) in allocation resources for flow classificaiton",
+				     ret);
+			goto init_err;
+		}
+	}
+
 	RTE_LOG(INFO, PMD, "%s: netdev created\n", eth_dev->data->name);
 	return 0;
 init_err:
@@ -2196,7 +2264,7 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 {
 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
 	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
-	int ret;
+	int i, ret;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -2224,6 +2292,14 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 	priv->hw = NULL;
 	rte_free(dpni);
 
+	for (i = 0; i < MAX_TCS; i++) {
+		if (priv->extract.fs_extract_param[i])
+			rte_free((void *)(size_t)priv->extract.fs_extract_param[i]);
+	}
+
+	if (priv->extract.qos_extract_param)
+		rte_free((void *)(size_t)priv->extract.qos_extract_param);
+
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 7148104ec..0ef1bf368 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -89,6 +89,13 @@
 /* enable timestamp in mbuf*/
 extern enum pmd_dpaa2_ts dpaa2_enable_ts;
 
+#define DPAA2_QOS_TABLE_RECONFIGURE	1
+#define DPAA2_FS_TABLE_RECONFIGURE	2
+
+/*Externaly defined*/
+extern const struct rte_flow_ops dpaa2_flow_ops;
+extern enum rte_filter_type dpaa2_filter_type;
+
 struct dpaa2_dev_priv {
 	void *hw;
 	int32_t hw_id;
@@ -107,8 +114,23 @@ struct dpaa2_dev_priv {
 	uint8_t flags; /*dpaa2 config flags */
 	uint8_t en_ordered;
 	uint8_t en_loose_ordered;
+
+	struct pattern_s {
+		uint8_t item_count;
+		uint8_t pattern_type[DPKG_MAX_NUM_OF_EXTRACTS];
+	} pattern[MAX_TCS + 1];
+
+	struct extract_s {
+		struct dpkg_profile_cfg qos_key_cfg;
+		struct dpkg_profile_cfg fs_key_cfg[MAX_TCS];
+		uint64_t qos_extract_param;
+		uint64_t fs_extract_param[MAX_TCS];
+	} extract;
 };
 
+int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set,
+				      struct dpkg_profile_cfg *kg_cfg);
+
 int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
 			  uint64_t req_dist_set);
 
diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c
new file mode 100644
index 000000000..20de3da53
--- /dev/null
+++ b/drivers/net/dpaa2/dpaa2_flow.c
@@ -0,0 +1,1972 @@
+/* * SPDX-License-Identifier: BSD-3-Clause
+ *   Copyright 2018 NXP
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_eth_ctrl.h>
+#include <rte_malloc.h>
+#include <rte_flow_driver.h>
+#include <rte_tailq.h>
+
+#include <fsl_dpni.h>
+#include <fsl_dpkg.h>
+
+#include <dpaa2_ethdev.h>
+#include <dpaa2_pmd_logs.h>
+
+struct rte_flow {
+	struct dpni_rule_cfg rule;
+	uint8_t key_size;
+	uint8_t tc_id;
+	uint8_t flow_type;
+	uint8_t index;
+	enum rte_flow_action_type action;
+	uint16_t flow_id;
+};
+
+/* Layout for rule compositions for supported patterns */
+/* TODO: Current design only supports Ethernet + IPv4 based classification. */
+/* So corresponding offset macros are valid only. Rest are placeholder for */
+/* now. Once support for other netwrok headers will be added then */
+/* corresponding macros will be updated with correct values*/
+#define DPAA2_CLS_RULE_OFFSET_ETH	0	/*Start of buffer*/
+#define DPAA2_CLS_RULE_OFFSET_VLAN	14	/* DPAA2_CLS_RULE_OFFSET_ETH */
+						/*	+ Sizeof Eth fields  */
+#define DPAA2_CLS_RULE_OFFSET_IPV4	14	/* DPAA2_CLS_RULE_OFFSET_VLAN */
+						/*	+ Sizeof VLAN fields */
+#define DPAA2_CLS_RULE_OFFSET_IPV6	25	/* DPAA2_CLS_RULE_OFFSET_IPV4 */
+						/*	+ Sizeof IPV4 fields */
+#define DPAA2_CLS_RULE_OFFSET_ICMP	58	/* DPAA2_CLS_RULE_OFFSET_IPV6 */
+						/*	+ Sizeof IPV6 fields */
+#define DPAA2_CLS_RULE_OFFSET_UDP	60	/* DPAA2_CLS_RULE_OFFSET_ICMP */
+						/*	+ Sizeof ICMP fields */
+#define DPAA2_CLS_RULE_OFFSET_TCP	64	/* DPAA2_CLS_RULE_OFFSET_UDP  */
+						/*	+ Sizeof UDP fields  */
+#define DPAA2_CLS_RULE_OFFSET_SCTP	68	/* DPAA2_CLS_RULE_OFFSET_TCP  */
+						/*	+ Sizeof TCP fields  */
+#define DPAA2_CLS_RULE_OFFSET_GRE	72	/* DPAA2_CLS_RULE_OFFSET_SCTP */
+						/*	+ Sizeof SCTP fields */
+
+static const
+enum rte_flow_item_type dpaa2_supported_pattern_type[] = {
+	RTE_FLOW_ITEM_TYPE_END,
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_GRE,
+};
+
+static const
+enum rte_flow_action_type dpaa2_supported_action_type[] = {
+	RTE_FLOW_ACTION_TYPE_END,
+	RTE_FLOW_ACTION_TYPE_QUEUE,
+	RTE_FLOW_ACTION_TYPE_RSS
+};
+
+enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE;
+static const void *default_mask;
+
+static int
+dpaa2_configure_flow_eth(struct rte_flow *flow,
+			 struct rte_eth_dev *dev,
+			 const struct rte_flow_attr *attr,
+			 const struct rte_flow_item *pattern,
+			 const struct rte_flow_action actions[] __rte_unused,
+			 struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_eth *spec, *mask;
+
+	/* TODO: Currently upper bound of range parameter is not implemented */
+	const struct rte_flow_item_eth *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	/* TODO: pattern is an array of 9 elements where 9th pattern element */
+	/* is for QoS table and 1-8th pattern element is for FS tables. */
+	/* It can be changed to macro. */
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_SA;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_DA;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_TYPE;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_SA;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_DA;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_TYPE;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_eth *)pattern->spec;
+	last	= (const struct rte_flow_item_eth *)pattern->last;
+	mask	= (const struct rte_flow_item_eth *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	/* Key rule */
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_ETH;
+	memcpy((void *)key_iova, (const void *)(spec->src.addr_bytes),
+						sizeof(struct ether_addr));
+	key_iova += sizeof(struct ether_addr);
+	memcpy((void *)key_iova, (const void *)(spec->dst.addr_bytes),
+						sizeof(struct ether_addr));
+	key_iova += sizeof(struct ether_addr);
+	memcpy((void *)key_iova, (const void *)(&spec->type),
+						sizeof(rte_be16_t));
+
+	/* Key mask */
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_ETH;
+	memcpy((void *)mask_iova, (const void *)(mask->src.addr_bytes),
+						sizeof(struct ether_addr));
+	mask_iova += sizeof(struct ether_addr);
+	memcpy((void *)mask_iova, (const void *)(mask->dst.addr_bytes),
+						sizeof(struct ether_addr));
+	mask_iova += sizeof(struct ether_addr);
+	memcpy((void *)mask_iova, (const void *)(&mask->type),
+						sizeof(rte_be16_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_ETH +
+				((2  * sizeof(struct ether_addr)) +
+				sizeof(rte_be16_t)));
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_vlan(struct rte_flow *flow,
+			  struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_vlan *spec, *mask;
+
+	const struct rte_flow_item_vlan *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/*  more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_VLAN;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_VLAN_TCI;
+		priv->extract.qos_key_cfg.num_extracts++;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_VLAN;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_VLAN_TCI;
+		priv->extract.fs_key_cfg[group].num_extracts++;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_vlan *)pattern->spec;
+	last	= (const struct rte_flow_item_vlan *)pattern->last;
+	mask	= (const struct rte_flow_item_vlan *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_VLAN;
+	memcpy((void *)key_iova, (const void *)(&spec->tci),
+							sizeof(rte_be16_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_VLAN;
+	memcpy((void *)mask_iova, (const void *)(&mask->tci),
+							sizeof(rte_be16_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_VLAN + sizeof(rte_be16_t));
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_ipv4(struct rte_flow *flow,
+			  struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_ipv4 *spec, *mask;
+
+	const struct rte_flow_item_ipv4 *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_ipv4 *)pattern->spec;
+	last	= (const struct rte_flow_item_ipv4 *)pattern->last;
+	mask	= (const struct rte_flow_item_ipv4 *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4;
+	memcpy((void *)key_iova, (const void *)&spec->hdr.src_addr,
+							sizeof(uint32_t));
+	key_iova += sizeof(uint32_t);
+	memcpy((void *)key_iova, (const void *)&spec->hdr.dst_addr,
+							sizeof(uint32_t));
+	key_iova += sizeof(uint32_t);
+	memcpy((void *)key_iova, (const void *)&spec->hdr.next_proto_id,
+							sizeof(uint8_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_IPV4;
+	memcpy((void *)mask_iova, (const void *)&mask->hdr.src_addr,
+							sizeof(uint32_t));
+	mask_iova += sizeof(uint32_t);
+	memcpy((void *)mask_iova, (const void *)&mask->hdr.dst_addr,
+							sizeof(uint32_t));
+	mask_iova += sizeof(uint32_t);
+	memcpy((void *)mask_iova, (const void *)&mask->hdr.next_proto_id,
+							sizeof(uint8_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_IPV4 +
+				(2 * sizeof(uint32_t)) + sizeof(uint8_t));
+
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_ipv6(struct rte_flow *flow,
+			  struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_ipv6 *spec, *mask;
+
+	const struct rte_flow_item_ipv6 *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more	than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_ipv6 *)pattern->spec;
+	last	= (const struct rte_flow_item_ipv6 *)pattern->last;
+	mask	= (const struct rte_flow_item_ipv6 *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV6;
+	memcpy((void *)key_iova, (const void *)(spec->hdr.src_addr),
+						sizeof(spec->hdr.src_addr));
+	key_iova += sizeof(spec->hdr.src_addr);
+	memcpy((void *)key_iova, (const void *)(spec->hdr.dst_addr),
+						sizeof(spec->hdr.dst_addr));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_IPV6;
+	memcpy((void *)mask_iova, (const void *)(mask->hdr.src_addr),
+						sizeof(mask->hdr.src_addr));
+	mask_iova += sizeof(mask->hdr.src_addr);
+	memcpy((void *)mask_iova, (const void *)(mask->hdr.dst_addr),
+						sizeof(mask->hdr.dst_addr));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_IPV6 +
+					sizeof(spec->hdr.src_addr) +
+					sizeof(mask->hdr.dst_addr));
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_icmp(struct rte_flow *flow,
+			  struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_icmp *spec, *mask;
+
+	const struct rte_flow_item_icmp *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ICMP_TYPE;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ICMP_CODE;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ICMP_TYPE;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ICMP_CODE;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_icmp *)pattern->spec;
+	last	= (const struct rte_flow_item_icmp *)pattern->last;
+	mask	= (const struct rte_flow_item_icmp *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_ICMP;
+	memcpy((void *)key_iova, (const void *)&spec->hdr.icmp_type,
+							sizeof(uint8_t));
+	key_iova += sizeof(uint8_t);
+	memcpy((void *)key_iova, (const void *)&spec->hdr.icmp_code,
+							sizeof(uint8_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_ICMP;
+	memcpy((void *)mask_iova, (const void *)&mask->hdr.icmp_type,
+							sizeof(uint8_t));
+	key_iova += sizeof(uint8_t);
+	memcpy((void *)mask_iova, (const void *)&mask->hdr.icmp_code,
+							sizeof(uint8_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_ICMP +
+				(2 * sizeof(uint8_t)));
+
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_udp(struct rte_flow *flow,
+			 struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_udp *spec, *mask;
+
+	const struct rte_flow_item_udp *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			 entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_UDP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_SRC;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type = DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_UDP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_DST;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_UDP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_SRC;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_UDP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_DST;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_udp *)pattern->spec;
+	last	= (const struct rte_flow_item_udp *)pattern->last;
+	mask	= (const struct rte_flow_item_udp *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4 +
+					(2 * sizeof(uint32_t));
+	memset((void *)key_iova, 0x11, sizeof(uint8_t));
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_UDP;
+	memcpy((void *)key_iova, (const void *)(&spec->hdr.src_port),
+							sizeof(uint16_t));
+	key_iova +=  sizeof(uint16_t);
+	memcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port),
+							sizeof(uint16_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_UDP;
+	memcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port),
+							sizeof(uint16_t));
+	mask_iova +=  sizeof(uint16_t);
+	memcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port),
+							sizeof(uint16_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_UDP +
+				(2 * sizeof(uint16_t)));
+
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_tcp(struct rte_flow *flow,
+			 struct rte_eth_dev *dev,
+			 const struct rte_flow_attr *attr,
+			 const struct rte_flow_item *pattern,
+			 const struct rte_flow_action actions[] __rte_unused,
+			 struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_tcp *spec, *mask;
+
+	const struct rte_flow_item_tcp *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_TCP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_SRC;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_TCP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_DST;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_TCP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_SRC;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_TCP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_DST;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_tcp *)pattern->spec;
+	last	= (const struct rte_flow_item_tcp *)pattern->last;
+	mask	= (const struct rte_flow_item_tcp *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4 +
+					(2 * sizeof(uint32_t));
+	memset((void *)key_iova, 0x06, sizeof(uint8_t));
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_TCP;
+	memcpy((void *)key_iova, (const void *)(&spec->hdr.src_port),
+							sizeof(uint16_t));
+	key_iova += sizeof(uint16_t);
+	memcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port),
+							sizeof(uint16_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_TCP;
+	memcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port),
+							sizeof(uint16_t));
+	mask_iova += sizeof(uint16_t);
+	memcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port),
+							sizeof(uint16_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_TCP +
+				(2 * sizeof(uint16_t)));
+
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_sctp(struct rte_flow *flow,
+			  struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_sctp *spec, *mask;
+
+	const struct rte_flow_item_sctp *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_SRC;
+		index++;
+
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_DST;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_SRC;
+		index++;
+
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_DST;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_sctp *)pattern->spec;
+	last	= (const struct rte_flow_item_sctp *)pattern->last;
+	mask	= (const struct rte_flow_item_sctp *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4 +
+						(2 * sizeof(uint32_t));
+	memset((void *)key_iova, 0x84, sizeof(uint8_t));
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_SCTP;
+	memcpy((void *)key_iova, (const void *)(&spec->hdr.src_port),
+							sizeof(uint16_t));
+	key_iova += sizeof(uint16_t);
+	memcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port),
+							sizeof(uint16_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_SCTP;
+	memcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port),
+							sizeof(uint16_t));
+	mask_iova += sizeof(uint16_t);
+	memcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port),
+							sizeof(uint16_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_SCTP +
+				(2 * sizeof(uint16_t)));
+	return device_configured;
+}
+
+static int
+dpaa2_configure_flow_gre(struct rte_flow *flow,
+			 struct rte_eth_dev *dev,
+			 const struct rte_flow_attr *attr,
+			 const struct rte_flow_item *pattern,
+			 const struct rte_flow_action actions[] __rte_unused,
+			 struct rte_flow_error *error __rte_unused)
+{
+	int index, j = 0;
+	size_t key_iova;
+	size_t mask_iova;
+	int device_configured = 0, entry_found = 0;
+	uint32_t group;
+	const struct rte_flow_item_gre *spec, *mask;
+
+	const struct rte_flow_item_gre *last __rte_unused;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+	group = attr->group;
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */
+	if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n",
+						DPKG_MAX_NUM_OF_EXTRACTS);
+		return -ENOTSUP;
+	}
+
+	for (j = 0; j < priv->pattern[8].item_count; j++) {
+		if (priv->pattern[8].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[8].pattern_type[j] = pattern->type;
+		priv->pattern[8].item_count++;
+		device_configured |= DPAA2_QOS_TABLE_RECONFIGURE;
+	}
+
+	entry_found = 0;
+	for (j = 0; j < priv->pattern[group].item_count; j++) {
+		if (priv->pattern[group].pattern_type[j] != pattern->type) {
+			continue;
+		} else {
+			entry_found = 1;
+			break;
+		}
+	}
+
+	if (!entry_found) {
+		priv->pattern[group].pattern_type[j] = pattern->type;
+		priv->pattern[group].item_count++;
+		device_configured |= DPAA2_FS_TABLE_RECONFIGURE;
+	}
+
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->index = attr->priority;
+
+	if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+		index = priv->extract.qos_key_cfg.num_extracts;
+		priv->extract.qos_key_cfg.extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_GRE;
+		priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_GRE_TYPE;
+		index++;
+
+		priv->extract.qos_key_cfg.num_extracts = index;
+	}
+
+	if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+		index = priv->extract.fs_key_cfg[group].num_extracts;
+		priv->extract.fs_key_cfg[group].extracts[index].type =
+							DPKG_EXTRACT_FROM_HDR;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_GRE;
+		priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_GRE_TYPE;
+		index++;
+
+		priv->extract.fs_key_cfg[group].num_extracts = index;
+	}
+
+	/* Parse pattern list to get the matching parameters */
+	spec	= (const struct rte_flow_item_gre *)pattern->spec;
+	last	= (const struct rte_flow_item_gre *)pattern->last;
+	mask	= (const struct rte_flow_item_gre *)
+			(pattern->mask ? pattern->mask : default_mask);
+
+	key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_GRE;
+	memcpy((void *)key_iova, (const void *)(&spec->protocol),
+							sizeof(rte_be16_t));
+
+	mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_GRE;
+	memcpy((void *)mask_iova, (const void *)(&mask->protocol),
+							sizeof(rte_be16_t));
+
+	flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_GRE + sizeof(rte_be16_t));
+
+	return device_configured;
+}
+
+static int
+dpaa2_generic_flow_set(struct rte_flow *flow,
+		       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)
+{
+	const struct rte_flow_action_queue *dest_queue;
+	const struct rte_flow_action_rss *rss_conf;
+	uint16_t index;
+	int is_keycfg_configured = 0, end_of_list = 0;
+	int ret = 0, i = 0, j = 0;
+	struct dpni_attr nic_attr;
+	struct dpni_rx_tc_dist_cfg tc_cfg;
+	struct dpni_qos_tbl_cfg qos_cfg;
+	struct dpkg_profile_cfg key_cfg;
+	struct dpni_fs_action_cfg action;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+	size_t param;
+
+	/* Parse pattern list to get the matching parameters */
+	while (!end_of_list) {
+		switch (pattern[i].type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			is_keycfg_configured = dpaa2_configure_flow_eth(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			is_keycfg_configured = dpaa2_configure_flow_vlan(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			is_keycfg_configured = dpaa2_configure_flow_ipv4(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			is_keycfg_configured = dpaa2_configure_flow_ipv6(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_ICMP:
+			is_keycfg_configured = dpaa2_configure_flow_icmp(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			is_keycfg_configured = dpaa2_configure_flow_udp(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			is_keycfg_configured = dpaa2_configure_flow_tcp(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			is_keycfg_configured = dpaa2_configure_flow_sctp(flow,
+									dev, attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			is_keycfg_configured = dpaa2_configure_flow_gre(flow,
+									dev,
+									attr,
+									&pattern[i],
+									actions,
+									error);
+			break;
+		case RTE_FLOW_ITEM_TYPE_END:
+			end_of_list = 1;
+			break; /*End of List*/
+		default:
+			DPAA2_PMD_ERR("Invalid action type");
+			ret = -ENOTSUP;
+			break;
+		}
+		i++;
+	}
+
+	/* Let's parse action on matching traffic */
+	end_of_list = 0;
+	while (!end_of_list) {
+		switch (actions[j].type) {
+		case RTE_FLOW_ACTION_TYPE_QUEUE:
+			dest_queue = (const struct rte_flow_action_queue *)(actions[j].conf);
+			flow->flow_id = dest_queue->index;
+			flow->action = RTE_FLOW_ACTION_TYPE_QUEUE;
+			memset(&action, 0, sizeof(struct dpni_fs_action_cfg));
+			action.flow_id = flow->flow_id;
+			if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
+				if (dpkg_prepare_key_cfg(&priv->extract.qos_key_cfg,
+							 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
+					DPAA2_PMD_ERR(
+					"Unable to prepare extract parameters");
+					return -1;
+				}
+
+				memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
+				qos_cfg.discard_on_miss = true;
+				qos_cfg.keep_entries = true;
+				qos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param;
+				ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
+							 priv->token, &qos_cfg);
+				if (ret < 0) {
+					DPAA2_PMD_ERR(
+					"Distribution cannot be configured.(%d)"
+					, ret);
+					return -1;
+				}
+			}
+			if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+				if (dpkg_prepare_key_cfg(&priv->extract.fs_key_cfg[flow->tc_id],
+						(uint8_t *)(size_t)priv->extract.fs_extract_param[flow->tc_id]) < 0) {
+					DPAA2_PMD_ERR(
+					"Unable to prepare extract parameters");
+					return -1;
+				}
+
+				memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
+				tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc;
+				tc_cfg.dist_mode = DPNI_DIST_MODE_FS;
+				tc_cfg.key_cfg_iova =
+					(uint64_t)priv->extract.fs_extract_param[flow->tc_id];
+				tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;
+				tc_cfg.fs_cfg.keep_entries = true;
+				ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,
+							 priv->token,
+							 flow->tc_id, &tc_cfg);
+				if (ret < 0) {
+					DPAA2_PMD_ERR(
+					"Distribution cannot be configured.(%d)"
+					, ret);
+					return -1;
+				}
+			}
+			/* Configure QoS table first */
+			memset(&nic_attr, 0, sizeof(struct dpni_attr));
+			ret = dpni_get_attributes(dpni, CMD_PRI_LOW,
+						 priv->token, &nic_attr);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"Failure to get attribute. dpni@%p err code(%d)\n",
+				dpni, ret);
+				return ret;
+			}
+
+			action.flow_id = action.flow_id % nic_attr.num_rx_tcs;
+			index = flow->index + (flow->tc_id * nic_attr.fs_entries);
+			ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
+						priv->token, &flow->rule,
+						flow->tc_id, index);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"Error in addnig entry to QoS table(%d)", ret);
+				return ret;
+			}
+
+			/* Then Configure FS table */
+			ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token,
+						flow->tc_id, flow->index,
+						&flow->rule, &action);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"Error in adding entry to FS table(%d)", ret);
+				return ret;
+			}
+			break;
+		case RTE_FLOW_ACTION_TYPE_RSS:
+			ret = dpni_get_attributes(dpni, CMD_PRI_LOW,
+						 priv->token, &nic_attr);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"Failure to get attribute. dpni@%p err code(%d)\n",
+				dpni, ret);
+				return ret;
+			}
+			rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf);
+			for (i = 0; i < (int)rss_conf->queue_num; i++) {
+				if (rss_conf->queue[i] < (attr->group * nic_attr.num_queues) ||
+				    rss_conf->queue[i] >= ((attr->group + 1) * nic_attr.num_queues)) {
+					DPAA2_PMD_ERR(
+					"Queue/Group combination are not supported\n");
+					return -ENOTSUP;
+				}
+			}
+
+			flow->action = RTE_FLOW_ACTION_TYPE_RSS;
+			ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,
+								&key_cfg);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"unable to set flow distribution.please check queue config\n");
+				return ret;
+			}
+
+			/* Allocate DMA'ble memory to write the rules */
+			param = (size_t)rte_malloc(NULL, 256, 64);
+			if (!param) {
+				DPAA2_PMD_ERR("Memory allocation failure\n");
+				return -1;
+			}
+
+			if (dpkg_prepare_key_cfg(&key_cfg, (uint8_t *)param) < 0) {
+				DPAA2_PMD_ERR(
+				"Unable to prepare extract parameters");
+				rte_free((void *)param);
+				return -1;
+			}
+
+			memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
+			tc_cfg.dist_size = rss_conf->queue_num;
+			tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
+			tc_cfg.key_cfg_iova = (size_t)param;
+			tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;
+
+			ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,
+						 priv->token, flow->tc_id,
+						 &tc_cfg);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"Distribution cannot be configured: %d\n", ret);
+				rte_free((void *)param);
+				return -1;
+			}
+
+			rte_free((void *)param);
+			if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {
+				if (dpkg_prepare_key_cfg(&priv->extract.qos_key_cfg,
+					(uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
+					DPAA2_PMD_ERR(
+					"Unable to prepare extract parameters");
+					return -1;
+				}
+				memset(&qos_cfg, 0,
+					sizeof(struct dpni_qos_tbl_cfg));
+				qos_cfg.discard_on_miss = true;
+				qos_cfg.keep_entries = true;
+				qos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param;
+				ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
+							 priv->token, &qos_cfg);
+				if (ret < 0) {
+					DPAA2_PMD_ERR(
+					"Distribution can not be configured(%d)\n",
+					ret);
+					return -1;
+				}
+			}
+
+			/* Add Rule into QoS table */
+			index = flow->index + (flow->tc_id * nic_attr.fs_entries);
+			ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token,
+						&flow->rule, flow->tc_id,
+						index);
+			if (ret < 0) {
+				DPAA2_PMD_ERR(
+				"Error in entry addition in QoS table(%d)",
+				ret);
+				return ret;
+			}
+			break;
+		case RTE_FLOW_ACTION_TYPE_END:
+			end_of_list = 1;
+			break;
+		default:
+			DPAA2_PMD_ERR("Invalid action type");
+			ret = -ENOTSUP;
+			break;
+		}
+		j++;
+	}
+
+	return ret;
+}
+
+static inline int
+dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr,
+		      const struct rte_flow_attr *attr)
+{
+	int ret = 0;
+
+	if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) {
+		DPAA2_PMD_ERR("Priority group is out of range\n");
+		ret = -ENOTSUP;
+	}
+	if (unlikely(attr->priority >= dpni_attr->fs_entries)) {
+		DPAA2_PMD_ERR("Priority within the group is out of range\n");
+		ret = -ENOTSUP;
+	}
+	if (unlikely(attr->egress)) {
+		DPAA2_PMD_ERR(
+			"Flow configuration is not supported on egress side\n");
+		ret = -ENOTSUP;
+	}
+	if (unlikely(!attr->ingress)) {
+		DPAA2_PMD_ERR("Ingress flag must be configured\n");
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static inline void
+dpaa2_dev_update_default_mask(const struct rte_flow_item *pattern)
+{
+	switch (pattern->type) {
+	case RTE_FLOW_ITEM_TYPE_ETH:
+		default_mask = (const void *)&rte_flow_item_eth_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_VLAN:
+		default_mask = (const void *)&rte_flow_item_vlan_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV4:
+		default_mask = (const void *)&rte_flow_item_ipv4_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV6:
+		default_mask = (const void *)&rte_flow_item_ipv6_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_ICMP:
+		default_mask = (const void *)&rte_flow_item_icmp_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_UDP:
+		default_mask = (const void *)&rte_flow_item_udp_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_TCP:
+		default_mask = (const void *)&rte_flow_item_tcp_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_SCTP:
+		default_mask = (const void *)&rte_flow_item_sctp_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_GRE:
+		default_mask = (const void *)&rte_flow_item_gre_mask;
+		break;
+	default:
+		DPAA2_PMD_ERR("Invalid pattern type");
+	}
+}
+
+static inline int
+dpaa2_dev_verify_patterns(struct dpaa2_dev_priv *dev_priv,
+			  const struct rte_flow_item pattern[])
+{
+	unsigned int i, j, k, is_found = 0;
+	int ret = 0;
+
+	for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
+		for (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) {
+			if (dpaa2_supported_pattern_type[i] == pattern[j].type) {
+				is_found = 1;
+				break;
+			}
+		}
+		if (!is_found) {
+			ret = -ENOTSUP;
+			break;
+		}
+	}
+	/* Lets verify other combinations of given pattern rules */
+	for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
+		if (!pattern[j].spec) {
+			ret = -EINVAL;
+			break;
+		}
+		if ((pattern[j].last) && (!pattern[j].mask))
+			dpaa2_dev_update_default_mask(&pattern[j]);
+	}
+
+	/* DPAA2 platform has a limitation that extract parameter can not be */
+	/* more	than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */
+	for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
+		for (j = 0; j < MAX_TCS + 1; j++) {
+				for (k = 0; k < DPKG_MAX_NUM_OF_EXTRACTS; j++) {
+					if (dev_priv->pattern[j].pattern_type[k] == pattern[i].type)
+						break;
+				}
+			if (dev_priv->pattern[j].item_count >= DPKG_MAX_NUM_OF_EXTRACTS)
+				ret = -ENOTSUP;
+		}
+	}
+	return ret;
+}
+
+static inline int
+dpaa2_dev_verify_actions(const struct rte_flow_action actions[])
+{
+	unsigned int i, j, is_found = 0;
+	int ret = 0;
+
+	for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
+		for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) {
+			if (dpaa2_supported_action_type[i] == actions[j].type) {
+				is_found = 1;
+				break;
+			}
+		}
+		if (!is_found) {
+			ret = -ENOTSUP;
+			break;
+		}
+	}
+	for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
+		if ((actions[j].type != RTE_FLOW_ACTION_TYPE_DROP) && (!actions[j].conf))
+			ret = -EINVAL;
+	}
+	return ret;
+}
+
+static
+int dpaa2_flow_validate(struct rte_eth_dev *dev,
+			const struct rte_flow_attr *flow_attr,
+			const struct rte_flow_item pattern[],
+			const struct rte_flow_action actions[],
+			struct rte_flow_error *error __rte_unused)
+{
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct dpni_attr dpni_attr;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+	uint16_t token = priv->token;
+	int ret = 0;
+
+	memset(&dpni_attr, 0, sizeof(struct dpni_attr));
+	ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr);
+	if (ret < 0) {
+		DPAA2_PMD_ERR(
+			"Failure to get dpni@%p attribute, err code  %d\n",
+			dpni, ret);
+		return ret;
+	}
+
+	/* Verify input attributes */
+	ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr);
+	if (ret < 0) {
+		DPAA2_PMD_ERR(
+			"Invalid attributes are given\n");
+		goto not_valid_params;
+	}
+	/* Verify input pattern list */
+	ret = dpaa2_dev_verify_patterns(priv, pattern);
+	if (ret < 0) {
+		DPAA2_PMD_ERR(
+			"Invalid pattern list is given\n");
+		goto not_valid_params;
+	}
+	/* Verify input action list */
+	ret = dpaa2_dev_verify_actions(actions);
+	if (ret < 0) {
+		DPAA2_PMD_ERR(
+			"Invalid action list is given\n");
+		goto not_valid_params;
+	}
+not_valid_params:
+	return ret;
+}
+
+static
+struct rte_flow *dpaa2_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 rte_flow *flow = NULL;
+	size_t key_iova = 0, mask_iova = 0;
+	int ret;
+
+	flow = rte_malloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);
+	if (!flow) {
+		DPAA2_PMD_ERR("Failure to allocate memory for flow");
+		return NULL;
+	}
+	/* Allocate DMA'ble memory to write the rules */
+	key_iova = (size_t)rte_malloc(NULL, 256, 64);
+	if (!key_iova) {
+		DPAA2_PMD_ERR(
+			"Memory allocation failure for rule configration\n");
+		goto creation_error;
+	}
+	mask_iova = (size_t)rte_malloc(NULL, 256, 64);
+	if (!mask_iova) {
+		DPAA2_PMD_ERR(
+			"Memory allocation failure for rule configration\n");
+		goto creation_error;
+	}
+
+	flow->rule.key_iova = key_iova;
+	flow->rule.mask_iova = mask_iova;
+	flow->rule.key_size = 0;
+
+	switch (dpaa2_filter_type) {
+	case RTE_ETH_FILTER_GENERIC:
+		ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
+					     actions, error);
+		if (ret < 0) {
+			DPAA2_PMD_ERR(
+			"Failure to create flow, return code (%d)", ret);
+			goto creation_error;
+		}
+		break;
+	default:
+		DPAA2_PMD_ERR("Filter type (%d) not supported",
+		dpaa2_filter_type);
+		break;
+	}
+
+	return flow;
+
+creation_error:
+	if (flow)
+		rte_free((void *)flow);
+	if (key_iova)
+		rte_free((void *)key_iova);
+	if (mask_iova)
+		rte_free((void *)mask_iova);
+	return NULL;
+}
+
+static
+int dpaa2_flow_destroy(struct rte_eth_dev *dev,
+		       struct rte_flow *flow,
+		       struct rte_flow_error *error __rte_unused)
+{
+	int ret = 0;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+
+	switch (flow->action) {
+	case RTE_FLOW_ACTION_TYPE_QUEUE:
+		/* Remove entry from QoS table first */
+		ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
+					   &flow->rule);
+		if (ret < 0) {
+			DPAA2_PMD_ERR(
+				"Error in adding entry to QoS table(%d)", ret);
+			goto error;
+		}
+
+		/* Then remove entry from FS table */
+		ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
+					   flow->tc_id, &flow->rule);
+		if (ret < 0) {
+			DPAA2_PMD_ERR(
+				"Error in entry addition in FS table(%d)", ret);
+			goto error;
+		}
+		break;
+	case RTE_FLOW_ACTION_TYPE_RSS:
+		ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
+					   &flow->rule);
+		if (ret < 0) {
+			DPAA2_PMD_ERR(
+			"Error in entry addition in QoS table(%d)", ret);
+			goto error;
+		}
+		break;
+	default:
+		DPAA2_PMD_ERR(
+		"Action type (%d) is not supported", flow->action);
+		ret = -ENOTSUP;
+		break;
+	}
+
+	/* Now free the flow */
+	rte_free(flow);
+
+error:
+	return ret;
+}
+
+static int
+dpaa2_flow_flush(struct rte_eth_dev *dev,
+		 struct rte_flow_error *error __rte_unused)
+{
+	int ret = 0, tc_id;
+	struct dpni_rx_tc_dist_cfg tc_cfg;
+	struct dpni_qos_tbl_cfg qos_cfg;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+
+	/* Reset QoS table */
+	qos_cfg.default_tc = 0;
+	qos_cfg.discard_on_miss = false;
+	qos_cfg.keep_entries = false;
+	qos_cfg.key_cfg_iova = priv->extract.qos_extract_param;
+	ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, &qos_cfg);
+	if (ret < 0)
+		DPAA2_PMD_ERR(
+			"QoS table is not reset to default: %d\n", ret);
+
+	for (tc_id = 0; tc_id < priv->num_rx_tc; tc_id++) {
+		/* Reset FS table */
+		memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
+		ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token,
+					 tc_id, &tc_cfg);
+		if (ret < 0)
+			DPAA2_PMD_ERR(
+			"Error (%d) in flushing entries for TC (%d)",
+			ret, tc_id);
+	}
+	return ret;
+}
+
+static int
+dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
+		struct rte_flow *flow __rte_unused,
+		const struct rte_flow_action *actions __rte_unused,
+		void *data __rte_unused,
+		struct rte_flow_error *error __rte_unused)
+{
+	return 0;
+}
+
+const struct rte_flow_ops dpaa2_flow_ops = {
+	.create	= dpaa2_flow_create,
+	.validate = dpaa2_flow_validate,
+	.destroy = dpaa2_flow_destroy,
+	.flush	= dpaa2_flow_flush,
+	.query	= dpaa2_flow_query,
+};
diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c
index 0907a3699..6c12a0ae1 100644
--- a/drivers/net/dpaa2/mc/dpni.c
+++ b/drivers/net/dpaa2/mc/dpni.c
@@ -1528,6 +1528,248 @@ int dpni_set_tx_confirmation_mode(struct fsl_mc_io *mc_io,
 	return mc_send_command(mc_io, &cmd);
 }
 
+/**
+ * dpni_set_qos_table() - Set QoS mapping table
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	QoS table configuration
+ *
+ * This function and all QoS-related functions require that
+ *'max_tcs > 1' was set at DPNI creation.
+ *
+ * warning: Before calling this function, call dpkg_prepare_key_cfg() to
+ *			prepare the key_cfg_iova parameter
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_qos_table(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       const struct dpni_qos_tbl_cfg *cfg)
+{
+	struct dpni_cmd_set_qos_table *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_set_qos_table *)cmd.params;
+	cmd_params->default_tc = cfg->default_tc;
+	cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
+	dpni_set_field(cmd_params->discard_on_miss,
+		       ENABLE,
+		       cfg->discard_on_miss);
+	dpni_set_field(cmd_params->discard_on_miss,
+					KEEP_QOS_ENTRIES,
+			       cfg->keep_entries);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	QoS rule to add
+ * @tc_id:	Traffic class selection (0-7)
+ * @index:	Location in the QoS table where to insert the entry.
+ *		Only relevant if MASKING is enabled for QoS classification on
+ *		this DPNI, it is ignored for exact match.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_qos_entry(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       const struct dpni_rule_cfg *cfg,
+		       uint8_t tc_id,
+		       uint16_t index)
+{
+	struct dpni_cmd_add_qos_entry *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_QOS_ENT,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_add_qos_entry *)cmd.params;
+	cmd_params->tc_id = tc_id;
+	cmd_params->key_size = cfg->key_size;
+	cmd_params->index = cpu_to_le16(index);
+	cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
+	cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_remove_qos_entry() - Remove QoS mapping entry
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	QoS rule to remove
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_qos_entry(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  const struct dpni_rule_cfg *cfg)
+{
+	struct dpni_cmd_remove_qos_entry *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_QOS_ENT,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_remove_qos_entry *)cmd.params;
+	cmd_params->key_size = cfg->key_size;
+	cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
+	cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_clear_qos_table() - Clear all QoS mapping entries
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * Following this function call, all frames are directed to
+ * the default traffic class (0)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_qos_table(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_QOS_TBL,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class
+ *			(to select a flow ID)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @index:	Location in the QoS table where to insert the entry.
+ *		Only relevant if MASKING is enabled for QoS classification
+ *		on this DPNI, it is ignored for exact match.
+ * @cfg:	Flow steering rule to add
+ * @action:	Action to be taken as result of a classification hit
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      uint8_t tc_id,
+		      uint16_t index,
+		      const struct dpni_rule_cfg *cfg,
+		      const struct dpni_fs_action_cfg *action)
+{
+	struct dpni_cmd_add_fs_entry *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params;
+	cmd_params->tc_id = tc_id;
+	cmd_params->key_size = cfg->key_size;
+	cmd_params->index = cpu_to_le16(index);
+	cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
+	cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
+	cmd_params->options = cpu_to_le16(action->options);
+	cmd_params->flow_id = cpu_to_le16(action->flow_id);
+	cmd_params->flc = cpu_to_le64(action->flc);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific
+ *			traffic class
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	Flow steering rule to remove
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 uint8_t tc_id,
+			 const struct dpni_rule_cfg *cfg)
+{
+	struct dpni_cmd_remove_fs_entry *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_remove_fs_entry *)cmd.params;
+	cmd_params->tc_id = tc_id;
+	cmd_params->key_size = cfg->key_size;
+	cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
+	cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_clear_fs_entries() - Clear all Flow Steering entries of a specific
+ *			traffic class
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_fs_entries(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  uint8_t tc_id)
+{
+	struct dpni_cmd_clear_fs_entries *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_FS_ENT,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_clear_fs_entries *)cmd.params;
+	cmd_params->tc_id = tc_id;
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
 /**
  * dpni_set_congestion_notification() - Set traffic class congestion
  *	notification configuration
@@ -2064,6 +2306,76 @@ int dpni_get_opr(struct fsl_mc_io *mc_io,
 	return 0;
 }
 
+/**
+ * dpni_set_rx_fs_dist() - Set Rx traffic class FS distribution
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg: Distribution configuration
+ * If the FS is already enabled with a previous call the classification
+ *		key will be changed but all the table rules are kept. If the
+ *		existing rules do not match the key the results will not be
+ *		predictable. It is the user responsibility to keep key integrity
+ * If cfg.enable is set to 1 the command will create a flow steering table
+ *		and will classify packets according to this table. The packets
+ *		that miss all the table rules will be classified according to
+ *		settings made in dpni_set_rx_hash_dist()
+ * If cfg.enable is set to 0 the command will clear flow steering table. The
+ *		packets will be classified according to settings made in
+ *		dpni_set_rx_hash_dist()
+ */
+int dpni_set_rx_fs_dist(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, const struct dpni_rx_dist_cfg *cfg)
+{
+	struct dpni_cmd_set_rx_fs_dist *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FS_DIST,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_set_rx_fs_dist *)cmd.params;
+	cmd_params->dist_size	= cpu_to_le16(cfg->dist_size);
+	dpni_set_field(cmd_params->enable, RX_FS_DIST_ENABLE, cfg->enable);
+	cmd_params->tc = cfg->tc;
+	cmd_params->miss_flow_id = cpu_to_le16(cfg->fs_miss_flow_id);
+	cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpni_set_rx_hash_dist() - Set Rx traffic class HASH distribution
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg: Distribution configuration
+ * If cfg.enable is set to 1 the packets will be classified using a hash
+ *		function based on the key received in cfg.key_cfg_iova parameter
+ * If cfg.enable is set to 0 the packets will be sent to the queue configured in
+ *		dpni_set_rx_dist_default_queue() call
+ */
+int dpni_set_rx_hash_dist(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, const struct dpni_rx_dist_cfg *cfg)
+{
+	struct dpni_cmd_set_rx_hash_dist *cmd_params;
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_HASH_DIST,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpni_cmd_set_rx_hash_dist *)cmd.params;
+	cmd_params->dist_size	= cpu_to_le16(cfg->dist_size);
+	dpni_set_field(cmd_params->enable, RX_FS_DIST_ENABLE, cfg->enable);
+	cmd_params->tc_id		= cfg->tc;
+	cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
 /**
  * dpni_add_custom_tpid() - Configures a distinct Ethertype value
  *		(or TPID value) to indicate VLAN tag in addition to the common
diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h
index 0359a2bc7..aecdc8d1f 100644
--- a/drivers/net/dpaa2/mc/fsl_dpni.h
+++ b/drivers/net/dpaa2/mc/fsl_dpni.h
@@ -1071,6 +1071,123 @@ int dpni_get_tx_confirmation_mode(struct fsl_mc_io *mc_io,
 				  uint16_t token,
 				  enum dpni_confirmation_mode *mode);
 
+/**
+ * struct dpni_qos_tbl_cfg - Structure representing QOS table configuration
+ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
+ *		key extractions to be used as the QoS criteria by calling
+ *		dpkg_prepare_key_cfg()
+ * @discard_on_miss: Set to '1' to discard frames in case of no match (miss);
+ *		'0' to use the 'default_tc' in such cases
+ * @keep_entries: if set to one will not delele existing table entries. This
+ *		option will work properly only for dpni objects created with
+ *		DPNI_OPT_HAS_KEY_MASKING option. All previous QoS entries must
+ *		be compatible with new key composition rule.
+ *		It is the caller's job to delete incompatible entries before
+ *		executing this function.
+ * @default_tc: Used in case of no-match and 'discard_on_miss'= 0
+ */
+struct dpni_qos_tbl_cfg {
+	uint64_t key_cfg_iova;
+	int discard_on_miss;
+	int keep_entries;
+	uint8_t default_tc;
+};
+
+int dpni_set_qos_table(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       const struct dpni_qos_tbl_cfg *cfg);
+
+/**
+ * struct dpni_rule_cfg - Rule configuration for table lookup
+ * @key_iova: I/O virtual address of the key (must be in DMA-able memory)
+ * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory)
+ * @key_size: key and mask size (in bytes)
+ */
+struct dpni_rule_cfg {
+	uint64_t key_iova;
+	uint64_t mask_iova;
+	uint8_t key_size;
+};
+
+int dpni_add_qos_entry(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       const struct dpni_rule_cfg *cfg,
+		       uint8_t tc_id,
+		       uint16_t index);
+
+int dpni_remove_qos_entry(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  const struct dpni_rule_cfg *cfg);
+
+int dpni_clear_qos_table(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token);
+
+/**
+ * Discard matching traffic.  If set, this takes precedence over any other
+ * configuration and matching traffic is always discarded.
+ */
+ #define DPNI_FS_OPT_DISCARD            0x1
+
+/**
+ * Set FLC value.  If set, flc member of truct dpni_fs_action_cfg is used to
+ * override the FLC value set per queue.
+ * For more details check the Frame Descriptor section in the hardware
+ * documentation.
+ */
+#define DPNI_FS_OPT_SET_FLC            0x2
+
+/*
+ * Indicates whether the 6 lowest significant bits of FLC are used for stash
+ * control.  If set, the 6 least significant bits in value are interpreted as
+ * follows:
+ *     - bits 0-1: indicates the number of 64 byte units of context that are
+ *     stashed.  FLC value is interpreted as a memory address in this case,
+ *     excluding the 6 LS bits.
+ *     - bits 2-3: indicates the number of 64 byte units of frame annotation
+ *     to be stashed.  Annotation is placed at FD[ADDR].
+ *     - bits 4-5: indicates the number of 64 byte units of frame data to be
+ *     stashed.  Frame data is placed at FD[ADDR] + FD[OFFSET].
+ * This flag is ignored if DPNI_FS_OPT_SET_FLC is not specified.
+ */
+#define DPNI_FS_OPT_SET_STASH_CONTROL  0x4
+
+/**
+ * struct dpni_fs_action_cfg - Action configuration for table look-up
+ * @flc: FLC value for traffic matching this rule.  Please check the Frame
+ * Descriptor section in the hardware documentation for more information.
+ * @flow_id: Identifies the Rx queue used for matching traffic.  Supported
+ *     values are in range 0 to num_queue-1.
+ * @options: Any combination of DPNI_FS_OPT_ values.
+ */
+struct dpni_fs_action_cfg {
+	uint64_t flc;
+	uint16_t flow_id;
+	uint16_t options;
+};
+
+int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      uint8_t tc_id,
+		      uint16_t index,
+		      const struct dpni_rule_cfg *cfg,
+		      const struct dpni_fs_action_cfg *action);
+
+int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 uint8_t tc_id,
+			 const struct dpni_rule_cfg *cfg);
+
+int dpni_clear_fs_entries(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  uint8_t tc_id);
+
 int dpni_get_api_version(struct fsl_mc_io *mc_io,
 			 uint32_t cmd_flags,
 			 uint16_t *major_ver,
@@ -1202,6 +1319,43 @@ int dpni_get_opr(struct fsl_mc_io *mc_io,
 		 struct opr_cfg *cfg,
 		 struct opr_qry *qry);
 
+/**
+ * When used for queue_idx in function dpni_set_rx_dist_default_queue will
+ * signal to dpni to drop all unclassified frames
+ */
+#define DPNI_FS_MISS_DROP		((uint16_t)-1)
+
+/**
+ * struct dpni_rx_dist_cfg - distribution configuration
+ * @dist_size:	distribution size; supported values: 1,2,3,4,6,7,8,
+ *		12,14,16,24,28,32,48,56,64,96,112,128,192,224,256,384,448,
+ *		512,768,896,1024
+ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
+ *		the extractions to be used for the distribution key by calling
+ *		dpkg_prepare_key_cfg() relevant only when enable!=0 otherwise
+ *		it can be '0'
+ * @enable: enable/disable the distribution.
+ * @tc: TC id for which distribution is set
+ * @fs_miss_flow_id: when packet misses all rules from flow steering table and
+ *		hash is disabled it will be put into this queue id; use
+ *		DPNI_FS_MISS_DROP to drop frames. The value of this field is
+ *		used only when flow steering distribution is enabled and hash
+ *		distribution is disabled
+ */
+struct dpni_rx_dist_cfg {
+	uint16_t dist_size;
+	uint64_t key_cfg_iova;
+	uint8_t enable;
+	uint8_t tc;
+	uint16_t fs_miss_flow_id;
+};
+
+int dpni_set_rx_fs_dist(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, const struct dpni_rx_dist_cfg *cfg);
+
+int dpni_set_rx_hash_dist(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
+		uint16_t token, const struct dpni_rx_dist_cfg *cfg);
+
 int dpni_add_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,
 		uint16_t token, uint16_t tpid);
 
diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h
index 81830ed85..9116e417e 100644
--- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h
+++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h
@@ -69,6 +69,14 @@
 
 #define DPNI_CMDID_SET_RX_TC_DIST		DPNI_CMD_V3(0x235)
 
+#define DPNI_CMDID_SET_QOS_TBL			DPNI_CMD_V2(0x240)
+#define DPNI_CMDID_ADD_QOS_ENT			DPNI_CMD(0x241)
+#define DPNI_CMDID_REMOVE_QOS_ENT		DPNI_CMD(0x242)
+#define DPNI_CMDID_CLR_QOS_TBL			DPNI_CMD(0x243)
+#define DPNI_CMDID_ADD_FS_ENT			DPNI_CMD(0x244)
+#define DPNI_CMDID_REMOVE_FS_ENT		DPNI_CMD(0x245)
+#define DPNI_CMDID_CLR_FS_ENT			DPNI_CMD(0x246)
+
 #define DPNI_CMDID_GET_STATISTICS		DPNI_CMD_V2(0x25D)
 #define DPNI_CMDID_RESET_STATISTICS		DPNI_CMD(0x25E)
 #define DPNI_CMDID_GET_QUEUE			DPNI_CMD(0x25F)
@@ -91,6 +99,8 @@
 #define DPNI_CMDID_GET_TX_CONFIRMATION_MODE	DPNI_CMD(0x26D)
 #define DPNI_CMDID_SET_OPR			DPNI_CMD(0x26e)
 #define DPNI_CMDID_GET_OPR			DPNI_CMD(0x26f)
+#define DPNI_CMDID_SET_RX_FS_DIST		DPNI_CMD(0x273)
+#define DPNI_CMDID_SET_RX_HASH_DIST		DPNI_CMD(0x274)
 #define DPNI_CMDID_ADD_CUSTOM_TPID		DPNI_CMD(0x275)
 #define DPNI_CMDID_REMOVE_CUSTOM_TPID		DPNI_CMD(0x276)
 #define DPNI_CMDID_GET_CUSTOM_TPID		DPNI_CMD(0x277)
@@ -495,6 +505,63 @@ struct dpni_cmd_set_queue {
 	uint64_t user_context;
 };
 
+#define DPNI_DISCARD_ON_MISS_SHIFT	0
+#define DPNI_DISCARD_ON_MISS_SIZE	1
+#define DPNI_KEEP_QOS_ENTRIES_SHIFT		1
+#define DPNI_KEEP_QOS_ENTRIES_SIZE		1
+
+struct dpni_cmd_set_qos_table {
+	uint32_t pad;
+	uint8_t default_tc;
+	/* only the LSB */
+	uint8_t discard_on_miss;
+	uint16_t pad1[21];
+	uint64_t key_cfg_iova;
+};
+
+struct dpni_cmd_add_qos_entry {
+	uint16_t pad;
+	uint8_t tc_id;
+	uint8_t key_size;
+	uint16_t index;
+	uint16_t pad2;
+	uint64_t key_iova;
+	uint64_t mask_iova;
+};
+
+struct dpni_cmd_remove_qos_entry {
+	uint8_t pad1[3];
+	uint8_t key_size;
+	uint32_t pad2;
+	uint64_t key_iova;
+	uint64_t mask_iova;
+};
+
+struct dpni_cmd_add_fs_entry {
+	uint16_t options;
+	uint8_t tc_id;
+	uint8_t key_size;
+	uint16_t index;
+	uint16_t flow_id;
+	uint64_t key_iova;
+	uint64_t mask_iova;
+	uint64_t flc;
+};
+
+struct dpni_cmd_remove_fs_entry {
+	uint16_t pad1;
+	uint8_t tc_id;
+	uint8_t key_size;
+	uint32_t pad2;
+	uint64_t key_iova;
+	uint64_t mask_iova;
+};
+
+struct dpni_cmd_clear_fs_entries {
+	uint16_t pad;
+	uint8_t tc_id;
+};
+
 #define DPNI_DROP_ENABLE_SHIFT	0
 #define DPNI_DROP_ENABLE_SIZE	1
 #define DPNI_DROP_UNITS_SHIFT	2
@@ -692,5 +759,26 @@ struct dpni_rsp_get_custom_tpid {
 	uint16_t	tpid2;
 };
 
+#define DPNI_RX_FS_DIST_ENABLE_SHIFT	0
+#define DPNI_RX_FS_DIST_ENABLE_SIZE		1
+struct dpni_cmd_set_rx_fs_dist {
+	uint16_t	dist_size;
+	uint8_t		enable;
+	uint8_t		tc;
+	uint16_t	miss_flow_id;
+	uint16_t	pad1;
+	uint64_t	key_cfg_iova;
+};
+
+#define DPNI_RX_HASH_DIST_ENABLE_SHIFT	0
+#define DPNI_RX_HASH_DIST_ENABLE_SIZE		1
+struct dpni_cmd_set_rx_hash_dist {
+	uint16_t	dist_size;
+	uint8_t		enable;
+	uint8_t		tc_id;
+	uint32_t	pad;
+	uint64_t	key_cfg_iova;
+};
+
 #pragma pack(pop)
 #endif /* _FSL_DPNI_CMD_H */
diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build
index 801cbf5d7..53e1d8189 100644
--- a/drivers/net/dpaa2/meson.build
+++ b/drivers/net/dpaa2/meson.build
@@ -11,6 +11,7 @@ deps += ['mempool_dpaa2']
 sources = files('base/dpaa2_hw_dpni.c',
 		'dpaa2_mux.c',
 		'dpaa2_ethdev.c',
+		'dpaa2_flow.c',
 		'dpaa2_rxtx.c',
 		'mc/dpkg.c',
 		'mc/dpdmux.c',
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/6] net/dpaa2: add support for VLAN tpid config
  2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
                   ` (4 preceding siblings ...)
  2019-02-22 11:16 ` [PATCH 6/6] net/dpaa2: add basic support for generic flow Hemant Agrawal
@ 2019-02-27  9:30 ` Ferruh Yigit
  5 siblings, 0 replies; 7+ messages in thread
From: Ferruh Yigit @ 2019-02-27  9:30 UTC (permalink / raw)
  To: Hemant Agrawal, dev; +Cc: Shreyansh Jain

On 2/22/2019 11:15 AM, Hemant Agrawal wrote:
> This patch add support to config custom tpid in dpni.
> i.e. value other than 0x8100 and 0x88A8
> 
> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>

Series applied to dpdk-next-net/master, thanks.

Hi Hemant,

What do you think adding a release notes update related to the changes, at least
rte_flow support looks like to me something to mention in release notes?

Thanks,
ferruh

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-02-27  9:30 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-22 11:15 [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Hemant Agrawal
2019-02-22 11:15 ` [PATCH 2/6] mempool/dpaa2: fix to reduce continuous print on empty pool Hemant Agrawal
2019-02-22 11:16 ` [PATCH 3/6] bus/fslmc: add enqueue response read routines in qbman Hemant Agrawal
2019-02-22 11:16 ` [PATCH 4/6] net/dpaa2: add support for 16 Rx Queues per traffic class Hemant Agrawal
2019-02-22 11:16 ` [PATCH 5/6] net/dpaa2: support low level loopback tester Hemant Agrawal
2019-02-22 11:16 ` [PATCH 6/6] net/dpaa2: add basic support for generic flow Hemant Agrawal
2019-02-27  9:30 ` [PATCH 1/6] net/dpaa2: add support for VLAN tpid config Ferruh Yigit

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.