DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/3] common/cnxk: support mirror flow action
@ 2023-12-14 10:58 psatheesh
  2023-12-14 10:58 ` [dpdk-dev] [PATCH 2/3] net/cnxk: " psatheesh
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: psatheesh @ 2023-12-14 10:58 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Add ROC API to support mirror flow action.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 drivers/common/cnxk/roc_mbox.h      | 56 +++++++++++++++++
 drivers/common/cnxk/roc_nix.h       |  8 ++-
 drivers/common/cnxk/roc_nix_mcast.c | 86 ++++++++++++++++++++++++++
 drivers/common/cnxk/roc_npc.c       | 94 +++++++++++++++++++++++++----
 drivers/common/cnxk/roc_npc.h       | 19 +++++-
 drivers/common/cnxk/roc_npc_mcam.c  | 56 +++++++++++++----
 drivers/common/cnxk/roc_npc_priv.h  |  3 +-
 drivers/common/cnxk/version.map     |  2 +
 8 files changed, 295 insertions(+), 29 deletions(-)

diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index 05434aec5a..3257a370bc 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -298,6 +298,11 @@ struct mbox_msghdr {
 	M(NIX_FREE_BPIDS, 0x8029, nix_free_bpids, nix_bpids, msg_rsp)          \
 	M(NIX_RX_CHAN_CFG, 0x802a, nix_rx_chan_cfg, nix_rx_chan_cfg,           \
 	  nix_rx_chan_cfg)                                                     \
+	M(NIX_MCAST_GRP_CREATE, 0x802b, nix_mcast_grp_create, nix_mcast_grp_create_req,            \
+	  nix_mcast_grp_create_rsp)                                                                \
+	M(NIX_MCAST_GRP_DESTROY, 0x802c, nix_mcast_grp_destroy, nix_mcast_grp_destroy_req, msg_rsp)\
+	M(NIX_MCAST_GRP_UPDATE, 0x802d, nix_mcast_grp_update, nix_mcast_grp_update_req,            \
+	  nix_mcast_grp_update_rsp)                                                                \
 	/* MCS mbox IDs (range 0xa000 - 0xbFFF) */                                                 \
 	M(MCS_ALLOC_RESOURCES, 0xa000, mcs_alloc_resources, mcs_alloc_rsrc_req,                    \
 	  mcs_alloc_rsrc_rsp)                                                                      \
@@ -1768,6 +1773,57 @@ struct nix_rx_chan_cfg {
 	uint64_t __io rsvd;
 };
 
+struct nix_mcast_grp_create_req {
+	struct mbox_msghdr hdr;
+#define NIX_MCAST_INGRESS 0
+#define NIX_MCAST_EGRESS  1
+	uint8_t __io dir;
+	uint8_t __io reserved[11];
+	/* Reserving few bytes for future requirement */
+};
+
+struct nix_mcast_grp_create_rsp {
+	struct mbox_msghdr hdr;
+	/* This mcast_grp_idx should be passed during MCAM
+	 * write entry for multicast. AF will identify the
+	 * corresponding multicast table index associated
+	 * with the group id and program the same to MCAM entry.
+	 * This group id is also needed during group delete
+	 * and update request.
+	 */
+	uint32_t __io mcast_grp_idx;
+};
+struct nix_mcast_grp_destroy_req {
+	struct mbox_msghdr hdr;
+	/* Group id returned by nix_mcast_grp_create_rsp */
+	uint32_t __io mcast_grp_idx;
+};
+
+struct nix_mcast_grp_update_req {
+	struct mbox_msghdr hdr;
+	/* Group id returned by nix_mcast_grp_create_rsp */
+	uint32_t __io mcast_grp_idx;
+	/* Number of multicast/mirror entries requested */
+	uint32_t __io num_mce_entry;
+#define NIX_MCE_ENTRY_MAX 64
+#define NIX_RX_RQ	  0
+#define NIX_RX_RSS	  1
+	/* Receive queue or RSS index within pf_func */
+	uint32_t __io rq_rss_index[NIX_MCE_ENTRY_MAX];
+	uint16_t __io pcifunc[NIX_MCE_ENTRY_MAX];
+	uint16_t __io channel[NIX_MCE_ENTRY_MAX];
+#define NIX_MCAST_OP_ADD_ENTRY 0
+#define NIX_MCAST_OP_DEL_ENTRY 1
+	/* Destination type. 0:Receive queue, 1:RSS*/
+	uint8_t __io dest_type[NIX_MCE_ENTRY_MAX];
+	uint8_t __io op;
+};
+
+struct nix_mcast_grp_update_rsp {
+	struct mbox_msghdr hdr;
+	uint32_t __io mce_start_index;
+};
+
 /* Global NIX inline IPSec configuration */
 struct nix_inline_ipsec_cfg {
 	struct mbox_msghdr hdr;
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index 82997c38ce..c1ebf971f7 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -1005,6 +1005,10 @@ int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
 					     struct mcam_entry *entry,
 					     uint32_t index, uint8_t intf,
 					     uint64_t action);
-int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix,
-					       uint32_t index, bool enable);
+int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
+					       bool enable);
+int __roc_api roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries,
+				       uint16_t *pf_funcs, uint16_t *channels, uint32_t *rqs,
+				       uint32_t *grp_index, uint32_t *start_index);
+int __roc_api roc_nix_mcast_list_free(struct mbox *mbox, uint32_t mcast_grp_index);
 #endif /* _ROC_NIX_H_ */
diff --git a/drivers/common/cnxk/roc_nix_mcast.c b/drivers/common/cnxk/roc_nix_mcast.c
index 3d74111274..615014e820 100644
--- a/drivers/common/cnxk/roc_nix_mcast.c
+++ b/drivers/common/cnxk/roc_nix_mcast.c
@@ -107,3 +107,89 @@ roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
 	mbox_put(mbox);
 	return rc;
 }
+
+int
+roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries, uint16_t *pf_funcs,
+			 uint16_t *channels, uint32_t *rqs, uint32_t *grp_index,
+			 uint32_t *start_index)
+{
+	struct nix_mcast_grp_create_req *mce_grp_create_req;
+	struct nix_mcast_grp_create_rsp *mce_grp_create_rsp;
+	struct nix_mcast_grp_update_req *mce_grp_update_req;
+	struct nix_mcast_grp_update_rsp *mce_grp_update_rsp;
+	int rc = 0, i;
+
+	mbox_get(mbox);
+
+	mce_grp_create_req = mbox_alloc_msg_nix_mcast_grp_create(mbox);
+	if (mce_grp_create_req == NULL) {
+		rc = -ENOSPC;
+		goto exit;
+	}
+
+	mce_grp_create_req->dir = intf;
+	rc = mbox_process_msg(mbox, (void *)&mce_grp_create_rsp);
+	if (rc) {
+		plt_err("Failed to create mirror list");
+		goto exit;
+	}
+
+	*grp_index = mce_grp_create_rsp->mcast_grp_idx;
+
+	mce_grp_update_req = mbox_alloc_msg_nix_mcast_grp_update(mbox);
+	if (mce_grp_update_req == NULL) {
+		rc = -ENOSPC;
+		goto exit;
+	}
+
+	mce_grp_update_req->mcast_grp_idx = *grp_index;
+	mce_grp_update_req->op = NIX_MCAST_OP_ADD_ENTRY;
+	mce_grp_update_req->num_mce_entry = nb_entries;
+	for (i = 0; i < nb_entries; i++) {
+		mce_grp_update_req->pcifunc[i] = pf_funcs[i];
+		mce_grp_update_req->channel[i] = channels[i];
+		mce_grp_update_req->rq_rss_index[i] = rqs[i];
+		mce_grp_update_req->dest_type[i] = NIX_RX_RQ;
+	}
+
+	rc = mbox_process_msg(mbox, (void *)&mce_grp_update_rsp);
+	if (rc) {
+		plt_err("Failed to create mirror list");
+		goto exit;
+	}
+
+	*start_index = (mce_grp_update_rsp->mce_start_index & 0xFFFFF);
+
+	rc = 0;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
+int
+roc_nix_mcast_list_free(struct mbox *mbox, uint32_t mcast_grp_index)
+{
+	struct nix_mcast_grp_destroy_req *mce_grp_destroy_req;
+	struct nix_mcast_grp_destroy_rsp *mce_grp_destroy_rsp;
+	int rc = 0;
+
+	mbox_get(mbox);
+
+	mce_grp_destroy_req = mbox_alloc_msg_nix_mcast_grp_destroy(mbox);
+	if (mce_grp_destroy_req == NULL) {
+		rc = -ENOSPC;
+		goto exit;
+	}
+
+	mce_grp_destroy_req->mcast_grp_idx = mcast_grp_index;
+	rc = mbox_process_msg(mbox, (void *)&mce_grp_destroy_rsp);
+	if (rc) {
+		plt_err("Failed to destroy mirror group index");
+		goto exit;
+	}
+
+	rc = 0;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 1958b3089d..65f99549c9 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -497,6 +497,39 @@ npc_parse_spi_to_sa_action(struct roc_npc *roc_npc, const struct roc_npc_action
 	return 0;
 }
 
+static int
+roc_npc_process_sample_action(struct roc_npc *roc_npc,
+			      const struct roc_npc_action_sample *sample_action,
+			      struct roc_npc_flow *flow)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);
+	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+	flow->is_sampling_rule = true;
+
+	switch (sample_action->action_type) {
+	case ROC_NPC_ACTION_TYPE_PORT_ID:
+		flow->mcast_pf_funcs[0] = sample_action->pf_func;
+		flow->mcast_channels[0] = sample_action->channel;
+		break;
+	case ROC_NPC_ACTION_TYPE_PF:
+		flow->mcast_pf_funcs[0] = roc_npc->pf_func;
+		flow->mcast_channels[0] = npc->channel;
+		break;
+	case ROC_NPC_ACTION_TYPE_VF:
+		if (sample_action->pf_func >= nix->dev.maxvf)
+			return -EINVAL;
+		flow->mcast_pf_funcs[0] =
+			((roc_npc->pf_func & 0xfc00) | (sample_action->pf_func + 1));
+		flow->mcast_channels[0] = npc->channel;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int
 npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		  const struct roc_npc_action actions[], struct roc_npc_flow *flow,
@@ -504,6 +537,7 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 	const struct roc_npc_action *sec_action = NULL;
+	const struct roc_npc_action_sample *act_sample;
 	const struct roc_npc_action_mark *act_mark;
 	const struct roc_npc_action_meter *act_mtr;
 	const struct roc_npc_action_queue *act_q;
@@ -562,8 +596,7 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 			break;
 
 		case ROC_NPC_ACTION_TYPE_VF:
-			vf_act =
-				(const struct roc_npc_action_vf *)actions->conf;
+			vf_act = (const struct roc_npc_action_vf *)actions->conf;
 			req_act |= ROC_NPC_ACTION_TYPE_VF;
 			vf_id = vf_act->id & RVU_PFVF_FUNC_MASK;
 			pf_func &= (0xfc00);
@@ -576,9 +609,8 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 			break;
 
 		case ROC_NPC_ACTION_TYPE_QUEUE:
-			act_q = (const struct roc_npc_action_queue *)
-					actions->conf;
-			rq = act_q->index;
+			act_q = (const struct roc_npc_action_queue *)actions->conf;
+			rq = act_q->index & 0xFFFFF;
 			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
 			break;
 
@@ -648,6 +680,13 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 				goto err_exit;
 			req_act |= ROC_NPC_ACTION_TYPE_AGE;
 			break;
+		case ROC_NPC_ACTION_TYPE_SAMPLE:
+			req_act |= ROC_NPC_ACTION_TYPE_SAMPLE;
+			act_sample = actions->conf;
+			errcode = roc_npc_process_sample_action(roc_npc, act_sample, flow);
+			if (errcode)
+				goto err_exit;
+			break;
 		default:
 			errcode = NPC_ERR_ACTION_NOTSUP;
 			goto err_exit;
@@ -688,6 +727,27 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		goto err_exit;
 	}
 
+	if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {
+		/* One entry for the mce list PF and channel comes from the sample subaction.
+		 * Another one is the action target of the flow rule getting created.
+		 */
+		flow->mcast_pf_funcs[1] = pf_func;
+		flow->mcast_channels[1] = npc->channel;
+		if (req_act & (ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_SEC |
+			       ROC_NPC_ACTION_TYPE_RSS)) {
+			plt_err("Drop/RSS/SEC not supported with action type sample");
+			return -EINVAL;
+		}
+		if (flow->mcast_pf_funcs[0] == flow->mcast_pf_funcs[1]) {
+			plt_err("Sample destination and target cannot be same");
+			return -EINVAL;
+		}
+		if ((attr->egress) && (flow->mcast_channels[0] == flow->mcast_channels[1])) {
+			plt_err("Mirroring within PF and VF not allowed");
+			return -EINVAL;
+		}
+	}
+
 	/* Check if actions specified are compatible */
 	if (attr->egress) {
 		if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
@@ -697,11 +757,10 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		}
 
 		if (req_act &
-		    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT |
-		      ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
-		      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT |
-		      ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) {
-			plt_err("Only VLAN insert, drop, count supported on Egress");
+		    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT | ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
+		      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT | ROC_NPC_ACTION_TYPE_DROP |
+		      ROC_NPC_ACTION_TYPE_COUNT | ROC_NPC_ACTION_TYPE_SAMPLE)) {
+			plt_err("Only VLAN insert, drop, count, sample supported on Egress");
 			errcode = NPC_ERR_ACTION_NOTSUP;
 			goto err_exit;
 		}
@@ -724,6 +783,11 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 			goto err_exit;
 		}
 
+		if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {
+			flow->mcast_pf_funcs[1] = pf_func;
+			flow->mcast_channels[1] = npc->channel;
+		}
+
 		goto set_pf_func;
 	} else {
 		if (vlan_insert_action) {
@@ -771,13 +835,13 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		} else {
 			flow->npc_action = NIX_RX_ACTIONOP_UCAST;
 			if (req_act & ROC_NPC_ACTION_TYPE_QUEUE)
-				flow->npc_action |= (uint64_t)rq << 20;
+				flow->recv_queue = rq;
 		}
 	} else if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
 		flow->npc_action = NIX_RX_ACTIONOP_DROP;
 	} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
-		flow->npc_action |= (uint64_t)rq << 20;
+		flow->recv_queue = rq;
 	} else if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
 	} else if (req_act & ROC_NPC_ACTION_TYPE_SEC) {
@@ -797,6 +861,9 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		goto err_exit;
 	}
 
+	if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE)
+		flow->npc_action = NIX_RX_ACTIONOP_MCAST;
+
 	if (mark)
 		flow->npc_action |= (uint64_t)mark << 40;
 
@@ -1639,6 +1706,9 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 			return rc;
 	}
 
+	if (flow->is_sampling_rule)
+		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
+
 	rc = roc_npc_mcam_free(roc_npc, flow);
 	if (rc != 0)
 		return rc;
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index cb59db2220..e880a7fa67 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -196,11 +196,19 @@ enum roc_npc_action_type {
 	ROC_NPC_ACTION_TYPE_PORT_ID = (1 << 16),
 	ROC_NPC_ACTION_TYPE_METER = (1 << 17),
 	ROC_NPC_ACTION_TYPE_AGE = (1 << 18),
+	ROC_NPC_ACTION_TYPE_SAMPLE = (1 << 19),
 };
 
 struct roc_npc_action {
 	enum roc_npc_action_type type; /**< Action type. */
-	const void *conf; /**< Pointer to action configuration object. */
+	const void *conf;	       /**< Pointer to action configuration object. */
+};
+
+struct roc_npc_action_sample {
+	uint32_t ratio;	      /**< packets sampled equals to '1/ratio'. */
+	uint32_t action_type; /* PF or VF or PORT_ID target. */
+	uint16_t pf_func;
+	uint16_t channel;
 };
 
 struct roc_npc_action_mark {
@@ -294,6 +302,8 @@ struct roc_npc_spi_to_sa_action_info {
 	bool has_action;
 };
 
+struct mbox;
+
 struct roc_npc_flow {
 	uint8_t nix_intf;
 	uint8_t enable;
@@ -322,6 +332,13 @@ struct roc_npc_flow {
 	void *age_context;
 	uint32_t timeout;
 	bool has_age_action;
+	bool is_sampling_rule;
+	uint32_t recv_queue;
+	uint32_t mcast_grp_index;
+	uint32_t mce_start_index;
+#define ROC_NPC_MIRROR_LIST_SIZE 2
+	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
+	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
 
 	TAILQ_ENTRY(roc_npc_flow) next;
 };
diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c
index 41edec7d8d..3ef189e184 100644
--- a/drivers/common/cnxk/roc_npc_mcam.c
+++ b/drivers/common/cnxk/roc_npc_mcam.c
@@ -680,6 +680,40 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		}
 	}
 
+	if (flow->nix_intf == NIX_INTF_TX) {
+		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
+
+		pf_func = plt_cpu_to_be_16(pf_func);
+
+		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
+		if (rc)
+			return rc;
+	}
+
+	if (flow->is_sampling_rule) {
+		/* Save and restore any mark value set */
+		uint16_t mark = (flow->npc_action >> 40) & 0xffff;
+		uint16_t mce_index = 0;
+		uint32_t rqs[2] = {};
+
+		rqs[1] = flow->recv_queue;
+		rc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,
+					      flow->mcast_channels, rqs, &flow->mcast_grp_index,
+					      &flow->mce_start_index);
+		if (rc)
+			return rc;
+
+		flow->npc_action = NIX_RX_ACTIONOP_MCAST;
+		mce_index = flow->mce_start_index;
+		if (flow->nix_intf == NIX_INTF_TX) {
+			flow->npc_action |= (uint64_t)mce_index << 12;
+			flow->npc_action |= (uint64_t)mark << 32;
+		} else {
+			flow->npc_action |= (uint64_t)mce_index << 20;
+			flow->npc_action |= (uint64_t)mark << 40;
+		}
+	}
+
 	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
 	if (req == NULL) {
 		rc = -ENOSPC;
@@ -691,6 +725,8 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 
 	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
 	req->enable_entry = 1;
+	if (flow->nix_intf == NIX_INTF_RX)
+		flow->npc_action |= (uint64_t)flow->recv_queue << 20;
 	req->entry_data.action = flow->npc_action;
 
 	/*
@@ -707,16 +743,6 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	 */
 	req->entry_data.vtag_action = flow->vtag_action;
 
-	if (flow->nix_intf == NIX_INTF_TX) {
-		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
-
-		pf_func = plt_cpu_to_be_16(pf_func);
-
-		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
-		if (rc)
-			return rc;
-	}
-
 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
 		req->entry_data.kw[idx] = flow->mcam_data[idx];
 		req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
@@ -746,7 +772,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		 */
 		if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
 			la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
-						       ((1ULL << 9 /* LA offset */) - 1));
+						   ((1ULL << 9 /* LA offset */) - 1));
 			la_offset *= 4;
 
 			mask = ~((0xfULL << la_offset));
@@ -778,8 +804,11 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	if (flow->use_ctr)
 		flow->ctr_id = ctr;
 	rc = 0;
+
 exit:
 	mbox_put(mbox);
+	if (rc)
+		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 	return rc;
 }
 
@@ -836,7 +865,7 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	 */
 	if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
 		lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-						   ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+					       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
 		lcflag_offset *= 4;
 
 		mask = (0xfULL << lcflag_offset);
@@ -1020,6 +1049,9 @@ npc_flow_free_all_resources(struct npc *npc)
 				rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
 			}
 
+			if (flow->is_sampling_rule)
+				roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
+
 			npc_delete_prio_list_entry(npc, flow);
 
 			TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index 424f8e207a..c0809407a6 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -493,8 +493,7 @@ void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *fl
 uint32_t npc_aged_flows_get(void *args);
 int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc);
 void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc);
-int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc,
-				 const struct roc_npc_action_age *age,
+int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, const struct roc_npc_action_age *age,
 				 struct roc_npc_flow *flow);
 void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc);
 #endif /* _ROC_NPC_PRIV_H_ */
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 52faf676ba..1b531da36d 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -294,6 +294,8 @@ INTERNAL {
 	roc_nix_mac_promisc_mode_enable;
 	roc_nix_mac_rxtx_start_stop;
 	roc_nix_max_pkt_len;
+	roc_nix_mcast_list_free;
+	roc_nix_mcast_list_setup;
 	roc_nix_mcast_mcam_entry_alloc;
 	roc_nix_mcast_mcam_entry_ena_dis;
 	roc_nix_mcast_mcam_entry_free;
-- 
2.39.2


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

* [dpdk-dev] [PATCH 2/3] net/cnxk: support mirror flow action
  2023-12-14 10:58 [dpdk-dev] [PATCH 1/3] common/cnxk: support mirror flow action psatheesh
@ 2023-12-14 10:58 ` psatheesh
  2023-12-14 13:43   ` [EXT] " Jerin Jacob Kollanukkaran
  2023-12-14 10:58 ` [dpdk-dev] [PATCH 3/3] common/cnxk: add egress mirror support psatheesh
  2023-12-14 14:50 ` [dpdk-dev] [PATCH v2 1/3] common/cnxk: support mirror flow action psatheesh
  2 siblings, 1 reply; 8+ messages in thread
From: psatheesh @ 2023-12-14 10:58 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added RTE_FLOW_ACTION_TYPE_SAMPLE action type for cnxk device.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 doc/guides/nics/features/cnxk.ini |   1 +
 drivers/net/cnxk/cnxk_flow.c      | 121 ++++++++++++++++++++++++++++--
 2 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini
index cc7deaeaa9..94e7a6ab8d 100644
--- a/doc/guides/nics/features/cnxk.ini
+++ b/doc/guides/nics/features/cnxk.ini
@@ -97,6 +97,7 @@ port_id              = Y
 queue                = Y
 represented_port     = Y
 rss                  = Y
+sample               = Y
 security             = Y
 skip_cman            = Y
 vf                   = Y
diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c
index 2eee44ed09..11670d37e0 100644
--- a/drivers/net/cnxk/cnxk_flow.c
+++ b/drivers/net/cnxk/cnxk_flow.c
@@ -114,14 +114,102 @@ npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev,
 	*flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss->types, rss->level);
 }
 
+static int
+npc_parse_port_id_action(struct rte_eth_dev *eth_dev, const struct rte_flow_action *action,
+			 uint16_t *dst_pf_func, uint16_t *dst_channel)
+{
+	const struct rte_flow_action_port_id *port_act;
+	struct rte_eth_dev *portid_eth_dev;
+	char if_name[RTE_ETH_NAME_MAX_LEN];
+	struct cnxk_eth_dev *hw_dst;
+	struct roc_npc *roc_npc_dst;
+	int rc = 0;
+
+	port_act = (const struct rte_flow_action_port_id *)action->conf;
+
+	rc = rte_eth_dev_get_name_by_port(port_act->id, if_name);
+	if (rc) {
+		plt_err("Name not found for output port id");
+		goto err_exit;
+	}
+	portid_eth_dev = rte_eth_dev_allocated(if_name);
+	if (!portid_eth_dev) {
+		plt_err("eth_dev not found for output port id");
+		goto err_exit;
+	}
+	if (strcmp(portid_eth_dev->device->driver->name, eth_dev->device->driver->name) != 0) {
+		plt_err("Output port not under same driver");
+		goto err_exit;
+	}
+	hw_dst = portid_eth_dev->data->dev_private;
+	roc_npc_dst = &hw_dst->npc;
+	*dst_pf_func = roc_npc_dst->pf_func;
+	*dst_channel = hw_dst->npc.channel;
+
+	return 0;
+
+err_exit:
+	return -EINVAL;
+}
+
+static int
+roc_npc_parse_sample_subaction(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[],
+			       struct roc_npc_action_sample *sample_action)
+{
+	uint16_t dst_pf_func = 0, dst_channel = 0;
+	const struct roc_npc_action_vf *vf_act;
+	int rc = 0, count = 0;
+	bool is_empty = true;
+
+	if (sample_action->ratio != 1) {
+		plt_err("Sample ratio must be 1");
+		return -EINVAL;
+	}
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		is_empty = false;
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_PF:
+			count++;
+			sample_action->action_type |= ROC_NPC_ACTION_TYPE_PF;
+			break;
+		case RTE_FLOW_ACTION_TYPE_VF:
+			count++;
+			vf_act = (const struct roc_npc_action_vf *)actions->conf;
+			sample_action->action_type |= ROC_NPC_ACTION_TYPE_VF;
+			sample_action->pf_func = vf_act->id & NPC_PFVF_FUNC_MASK;
+			break;
+		case RTE_FLOW_ACTION_TYPE_PORT_ID:
+			rc = npc_parse_port_id_action(eth_dev, actions, &dst_pf_func, &dst_channel);
+			if (rc)
+				return -EINVAL;
+
+			count++;
+			sample_action->action_type |= ROC_NPC_ACTION_TYPE_PORT_ID;
+			sample_action->pf_func = dst_pf_func;
+			sample_action->channel = dst_channel;
+			break;
+		default:
+			continue;
+		}
+	}
+
+	if (count > 1 || is_empty)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int
 cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 		 const struct rte_flow_action actions[], struct roc_npc_action in_actions[],
-		 uint32_t *flowkey_cfg, uint16_t *dst_pf_func)
+		 struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
+		 uint16_t *dst_pf_func)
 {
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
 	const struct rte_flow_action_queue *act_q = NULL;
 	const struct rte_flow_action_ethdev *act_ethdev;
+	const struct rte_flow_action_sample *act_sample;
 	const struct rte_flow_action_port_id *port_act;
 	struct rte_eth_dev *portid_eth_dev;
 	char if_name[RTE_ETH_NAME_MAX_LEN];
@@ -237,9 +325,21 @@ cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 			in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE;
 			in_actions[i].conf = actions->conf;
 			break;
+		case RTE_FLOW_ACTION_TYPE_SAMPLE:
+			act_sample = actions->conf;
+			in_sample_actions->ratio = act_sample->ratio;
+			rc = roc_npc_parse_sample_subaction(eth_dev, act_sample->actions,
+							    in_sample_actions);
+			if (rc) {
+				plt_err("Sample subaction parsing failed.");
+				goto err_exit;
+			}
+
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_SAMPLE;
+			in_actions[i].conf = in_sample_actions;
+			break;
 		default:
-			plt_npc_dbg("Action is not supported = %d",
-				    actions->type);
+			plt_npc_dbg("Action is not supported = %d", actions->type);
 			goto err_exit;
 		}
 		i++;
@@ -263,7 +363,9 @@ static int
 cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 		   const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
 		   struct roc_npc_attr *in_attr, struct roc_npc_item_info in_pattern[],
-		   struct roc_npc_action in_actions[], uint32_t *flowkey_cfg, uint16_t *dst_pf_func)
+		   struct roc_npc_action in_actions[],
+		   struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
+		   uint16_t *dst_pf_func)
 {
 	int i = 0;
 
@@ -282,7 +384,8 @@ cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr
 	}
 	in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
 
-	return cnxk_map_actions(eth_dev, attr, actions, in_actions, flowkey_cfg, dst_pf_func);
+	return cnxk_map_actions(eth_dev, attr, actions, in_actions, in_sample_actions, flowkey_cfg,
+				dst_pf_func);
 }
 
 static int
@@ -293,6 +396,7 @@ cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr
 	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
 	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_npc_action_sample in_sample_action;
 	struct roc_npc *npc = &dev->npc;
 	struct roc_npc_attr in_attr;
 	struct roc_npc_flow flow;
@@ -306,10 +410,11 @@ cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr
 		return 0;
 
 	memset(&flow, 0, sizeof(flow));
+	memset(&in_sample_action, 0, sizeof(in_sample_action));
 	flow.is_validate = true;
 
 	rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
-				&flowkey_cfg, &dst_pf_func);
+				&in_sample_action, &flowkey_cfg, &dst_pf_func);
 	if (rc) {
 		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
 				   "Failed to map flow data");
@@ -335,6 +440,7 @@ cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
 	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
 	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
+	struct roc_npc_action_sample in_sample_action;
 	struct roc_npc *npc = &dev->npc;
 	struct roc_npc_attr in_attr;
 	struct roc_npc_flow *flow;
@@ -342,8 +448,9 @@ cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 	int errcode = 0;
 	int rc;
 
+	memset(&in_sample_action, 0, sizeof(in_sample_action));
 	rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
-				&npc->flowkey_cfg_state, &dst_pf_func);
+				&in_sample_action, &npc->flowkey_cfg_state, &dst_pf_func);
 	if (rc) {
 		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
 				   "Failed to map flow data");
-- 
2.39.2


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

* [dpdk-dev] [PATCH 3/3] common/cnxk: add egress mirror support
  2023-12-14 10:58 [dpdk-dev] [PATCH 1/3] common/cnxk: support mirror flow action psatheesh
  2023-12-14 10:58 ` [dpdk-dev] [PATCH 2/3] net/cnxk: " psatheesh
@ 2023-12-14 10:58 ` psatheesh
  2023-12-14 14:50 ` [dpdk-dev] [PATCH v2 1/3] common/cnxk: support mirror flow action psatheesh
  2 siblings, 0 replies; 8+ messages in thread
From: psatheesh @ 2023-12-14 10:58 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: dev, Satheesh Paul

From: Satha Rao <skoteshwar@marvell.com>

Added ROC api to send packets on multiple links when egress mirror
enabled.

Signed-off-by: Satha Rao <skoteshwar@marvell.com>
Reviewed-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
Reviewed-by: Satheesh Paul <psatheesh@marvell.com>
---
 drivers/common/cnxk/roc_nix.h        |  2 +
 drivers/common/cnxk/roc_nix_tm_ops.c | 70 ++++++++++++++++++++++++++++
 drivers/common/cnxk/roc_npc.c        | 26 +++++++++++
 drivers/common/cnxk/version.map      |  1 +
 4 files changed, 99 insertions(+)

diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index c1ebf971f7..84e6fc3df5 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -755,6 +755,8 @@ int __roc_api roc_nix_tm_mark_config(struct roc_nix *roc_nix,
 				     int mark_red);
 uint64_t __roc_api roc_nix_tm_mark_format_get(struct roc_nix *roc_nix,
 					      uint64_t *flags);
+int __roc_api roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func,
+					     bool enable);
 
 /* Ingress Policer API */
 int __roc_api roc_nix_bpf_timeunit_get(struct roc_nix *roc_nix,
diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c b/drivers/common/cnxk/roc_nix_tm_ops.c
index 2c53472047..900b182c76 100644
--- a/drivers/common/cnxk/roc_nix_tm_ops.c
+++ b/drivers/common/cnxk/roc_nix_tm_ops.c
@@ -1316,3 +1316,73 @@ roc_nix_tm_root_has_sp(struct roc_nix *roc_nix)
 		return false;
 	return true;
 }
+
+static inline struct nix *
+pf_func_to_nix_get(uint16_t pf_func)
+{
+	struct roc_nix *roc_nix_tmp = NULL;
+	struct roc_nix_list *nix_list;
+
+	nix_list = roc_idev_nix_list_get();
+	if (nix_list == NULL)
+		return NULL;
+
+	/* Find the NIX of given pf_func */
+	TAILQ_FOREACH(roc_nix_tmp, nix_list, next) {
+		struct nix *nix = roc_nix_to_nix_priv(roc_nix_tmp);
+
+		if (nix->dev.pf_func == pf_func)
+			return nix;
+	}
+
+	return NULL;
+}
+
+int
+roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func, bool enable)
+{
+	struct nix *src_nix = roc_nix_to_nix_priv(roc_nix), *dst_nix;
+	struct mbox *mbox = (&src_nix->dev)->mbox;
+	struct nix_txschq_config *req = NULL;
+	struct nix_tm_node_list *list;
+	struct nix_tm_node *node;
+	int rc = 0, k;
+
+	dst_nix = pf_func_to_nix_get(dst_pf_func);
+	if (!dst_nix)
+		return -EINVAL;
+
+	if (dst_nix == src_nix)
+		return 0;
+
+	list = nix_tm_node_list(src_nix, src_nix->tm_tree);
+	TAILQ_FOREACH(node, list, node) {
+		if (node->hw_lvl != src_nix->tm_link_cfg_lvl)
+			continue;
+
+		if (!(node->flags & NIX_TM_NODE_HWRES))
+			continue;
+
+		/* Allocating TL3 request */
+		req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
+		req->lvl = src_nix->tm_link_cfg_lvl;
+		k = 0;
+
+		/* Enable PFC/pause on the identified TL3 */
+		req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, dst_nix->tx_link);
+		if (enable)
+			req->regval[k] |= BIT_ULL(12);
+		else
+			req->regval[k] &= ~(BIT_ULL(12));
+		req->regval_mask[k] = ~(BIT_ULL(12));
+		k++;
+
+		req->num_regs = k;
+		rc = mbox_process(mbox);
+		mbox_put(mbox);
+		if (rc)
+			goto err;
+	}
+err:
+	return rc;
+}
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 65f99549c9..9a0fe5f4e2 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -1595,6 +1595,21 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		goto err_exit;
 	}
 
+	/* If Egress mirror requested then enable TL3_TL2_LINK_CFG */
+	if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
+		if (flow->mcast_pf_funcs[0] == npc->pf_func)
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[1], true);
+		else
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[0], true);
+		if (rc) {
+			plt_err("Adding egress mirror failed");
+			*errcode = rc;
+			goto err_exit;
+		}
+	}
+
 	rc = npc_rss_action_program(roc_npc, actions, flow);
 	if (rc != 0) {
 		*errcode = rc;
@@ -1706,6 +1721,17 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 			return rc;
 	}
 
+	/* Disable egress mirror rule */
+	if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
+		if (flow->mcast_pf_funcs[0] == npc->pf_func)
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[1], false);
+		else
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[0], false);
+		if (rc)
+			plt_err("Failed to remove egress mirror rule");
+	}
 	if (flow->is_sampling_rule)
 		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 1b531da36d..7b6afa63a9 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -355,6 +355,7 @@ INTERNAL {
 	roc_nix_switch_hdr_set;
 	roc_nix_eeprom_info_get;
 	roc_nix_smq_flush;
+	roc_nix_tm_egress_link_cfg_set;
 	roc_nix_tm_dump;
 	roc_nix_tm_err_to_rte_err;
 	roc_nix_tm_fini;
-- 
2.39.2


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

* RE: [EXT] [dpdk-dev] [PATCH 2/3] net/cnxk: support mirror flow action
  2023-12-14 10:58 ` [dpdk-dev] [PATCH 2/3] net/cnxk: " psatheesh
@ 2023-12-14 13:43   ` Jerin Jacob Kollanukkaran
  0 siblings, 0 replies; 8+ messages in thread
From: Jerin Jacob Kollanukkaran @ 2023-12-14 13:43 UTC (permalink / raw)
  To: Satheesh Paul Antonysamy, Nithin Kumar Dabilpuram,
	Kiran Kumar Kokkilagadda, Sunil Kumar Kori,
	Satha Koteswara Rao Kottidi
  Cc: dev, Satheesh Paul Antonysamy



> -----Original Message-----
> From: psatheesh@marvell.com <psatheesh@marvell.com>
> Sent: Thursday, December 14, 2023 4:28 PM
> To: Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>; Kiran Kumar
> Kokkilagadda <kirankumark@marvell.com>; Sunil Kumar Kori
> <skori@marvell.com>; Satha Koteswara Rao Kottidi
> <skoteshwar@marvell.com>
> Cc: dev@dpdk.org; Satheesh Paul Antonysamy <psatheesh@marvell.com>
> Subject: [EXT] [dpdk-dev] [PATCH 2/3] net/cnxk: support mirror flow action
> 
> External Email
> 
> ----------------------------------------------------------------------
> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Added RTE_FLOW_ACTION_TYPE_SAMPLE action type for cnxk device.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>


Please update the release notes for this new feature.

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

* [dpdk-dev] [PATCH v2 1/3] common/cnxk: support mirror flow action
  2023-12-14 10:58 [dpdk-dev] [PATCH 1/3] common/cnxk: support mirror flow action psatheesh
  2023-12-14 10:58 ` [dpdk-dev] [PATCH 2/3] net/cnxk: " psatheesh
  2023-12-14 10:58 ` [dpdk-dev] [PATCH 3/3] common/cnxk: add egress mirror support psatheesh
@ 2023-12-14 14:50 ` psatheesh
  2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 2/3] net/cnxk: " psatheesh
  2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 3/3] common/cnxk: add egress mirror support psatheesh
  2 siblings, 2 replies; 8+ messages in thread
From: psatheesh @ 2023-12-14 14:50 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Add ROC API to support mirror flow action.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
v2:
* Updated release notes.

Depends-on: series-30556 ("common/cnxk: support PPPoE flow item type in ROC API")

 drivers/common/cnxk/roc_mbox.h      | 56 +++++++++++++++++
 drivers/common/cnxk/roc_nix.h       |  8 ++-
 drivers/common/cnxk/roc_nix_mcast.c | 86 ++++++++++++++++++++++++++
 drivers/common/cnxk/roc_npc.c       | 94 +++++++++++++++++++++++++----
 drivers/common/cnxk/roc_npc.h       | 19 +++++-
 drivers/common/cnxk/roc_npc_mcam.c  | 56 +++++++++++++----
 drivers/common/cnxk/roc_npc_priv.h  |  3 +-
 drivers/common/cnxk/version.map     |  2 +
 8 files changed, 295 insertions(+), 29 deletions(-)

diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index 05434aec5a..3257a370bc 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -298,6 +298,11 @@ struct mbox_msghdr {
 	M(NIX_FREE_BPIDS, 0x8029, nix_free_bpids, nix_bpids, msg_rsp)          \
 	M(NIX_RX_CHAN_CFG, 0x802a, nix_rx_chan_cfg, nix_rx_chan_cfg,           \
 	  nix_rx_chan_cfg)                                                     \
+	M(NIX_MCAST_GRP_CREATE, 0x802b, nix_mcast_grp_create, nix_mcast_grp_create_req,            \
+	  nix_mcast_grp_create_rsp)                                                                \
+	M(NIX_MCAST_GRP_DESTROY, 0x802c, nix_mcast_grp_destroy, nix_mcast_grp_destroy_req, msg_rsp)\
+	M(NIX_MCAST_GRP_UPDATE, 0x802d, nix_mcast_grp_update, nix_mcast_grp_update_req,            \
+	  nix_mcast_grp_update_rsp)                                                                \
 	/* MCS mbox IDs (range 0xa000 - 0xbFFF) */                                                 \
 	M(MCS_ALLOC_RESOURCES, 0xa000, mcs_alloc_resources, mcs_alloc_rsrc_req,                    \
 	  mcs_alloc_rsrc_rsp)                                                                      \
@@ -1768,6 +1773,57 @@ struct nix_rx_chan_cfg {
 	uint64_t __io rsvd;
 };
 
+struct nix_mcast_grp_create_req {
+	struct mbox_msghdr hdr;
+#define NIX_MCAST_INGRESS 0
+#define NIX_MCAST_EGRESS  1
+	uint8_t __io dir;
+	uint8_t __io reserved[11];
+	/* Reserving few bytes for future requirement */
+};
+
+struct nix_mcast_grp_create_rsp {
+	struct mbox_msghdr hdr;
+	/* This mcast_grp_idx should be passed during MCAM
+	 * write entry for multicast. AF will identify the
+	 * corresponding multicast table index associated
+	 * with the group id and program the same to MCAM entry.
+	 * This group id is also needed during group delete
+	 * and update request.
+	 */
+	uint32_t __io mcast_grp_idx;
+};
+struct nix_mcast_grp_destroy_req {
+	struct mbox_msghdr hdr;
+	/* Group id returned by nix_mcast_grp_create_rsp */
+	uint32_t __io mcast_grp_idx;
+};
+
+struct nix_mcast_grp_update_req {
+	struct mbox_msghdr hdr;
+	/* Group id returned by nix_mcast_grp_create_rsp */
+	uint32_t __io mcast_grp_idx;
+	/* Number of multicast/mirror entries requested */
+	uint32_t __io num_mce_entry;
+#define NIX_MCE_ENTRY_MAX 64
+#define NIX_RX_RQ	  0
+#define NIX_RX_RSS	  1
+	/* Receive queue or RSS index within pf_func */
+	uint32_t __io rq_rss_index[NIX_MCE_ENTRY_MAX];
+	uint16_t __io pcifunc[NIX_MCE_ENTRY_MAX];
+	uint16_t __io channel[NIX_MCE_ENTRY_MAX];
+#define NIX_MCAST_OP_ADD_ENTRY 0
+#define NIX_MCAST_OP_DEL_ENTRY 1
+	/* Destination type. 0:Receive queue, 1:RSS*/
+	uint8_t __io dest_type[NIX_MCE_ENTRY_MAX];
+	uint8_t __io op;
+};
+
+struct nix_mcast_grp_update_rsp {
+	struct mbox_msghdr hdr;
+	uint32_t __io mce_start_index;
+};
+
 /* Global NIX inline IPSec configuration */
 struct nix_inline_ipsec_cfg {
 	struct mbox_msghdr hdr;
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index 82997c38ce..c1ebf971f7 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -1005,6 +1005,10 @@ int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
 					     struct mcam_entry *entry,
 					     uint32_t index, uint8_t intf,
 					     uint64_t action);
-int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix,
-					       uint32_t index, bool enable);
+int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
+					       bool enable);
+int __roc_api roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries,
+				       uint16_t *pf_funcs, uint16_t *channels, uint32_t *rqs,
+				       uint32_t *grp_index, uint32_t *start_index);
+int __roc_api roc_nix_mcast_list_free(struct mbox *mbox, uint32_t mcast_grp_index);
 #endif /* _ROC_NIX_H_ */
diff --git a/drivers/common/cnxk/roc_nix_mcast.c b/drivers/common/cnxk/roc_nix_mcast.c
index 3d74111274..615014e820 100644
--- a/drivers/common/cnxk/roc_nix_mcast.c
+++ b/drivers/common/cnxk/roc_nix_mcast.c
@@ -107,3 +107,89 @@ roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
 	mbox_put(mbox);
 	return rc;
 }
+
+int
+roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries, uint16_t *pf_funcs,
+			 uint16_t *channels, uint32_t *rqs, uint32_t *grp_index,
+			 uint32_t *start_index)
+{
+	struct nix_mcast_grp_create_req *mce_grp_create_req;
+	struct nix_mcast_grp_create_rsp *mce_grp_create_rsp;
+	struct nix_mcast_grp_update_req *mce_grp_update_req;
+	struct nix_mcast_grp_update_rsp *mce_grp_update_rsp;
+	int rc = 0, i;
+
+	mbox_get(mbox);
+
+	mce_grp_create_req = mbox_alloc_msg_nix_mcast_grp_create(mbox);
+	if (mce_grp_create_req == NULL) {
+		rc = -ENOSPC;
+		goto exit;
+	}
+
+	mce_grp_create_req->dir = intf;
+	rc = mbox_process_msg(mbox, (void *)&mce_grp_create_rsp);
+	if (rc) {
+		plt_err("Failed to create mirror list");
+		goto exit;
+	}
+
+	*grp_index = mce_grp_create_rsp->mcast_grp_idx;
+
+	mce_grp_update_req = mbox_alloc_msg_nix_mcast_grp_update(mbox);
+	if (mce_grp_update_req == NULL) {
+		rc = -ENOSPC;
+		goto exit;
+	}
+
+	mce_grp_update_req->mcast_grp_idx = *grp_index;
+	mce_grp_update_req->op = NIX_MCAST_OP_ADD_ENTRY;
+	mce_grp_update_req->num_mce_entry = nb_entries;
+	for (i = 0; i < nb_entries; i++) {
+		mce_grp_update_req->pcifunc[i] = pf_funcs[i];
+		mce_grp_update_req->channel[i] = channels[i];
+		mce_grp_update_req->rq_rss_index[i] = rqs[i];
+		mce_grp_update_req->dest_type[i] = NIX_RX_RQ;
+	}
+
+	rc = mbox_process_msg(mbox, (void *)&mce_grp_update_rsp);
+	if (rc) {
+		plt_err("Failed to create mirror list");
+		goto exit;
+	}
+
+	*start_index = (mce_grp_update_rsp->mce_start_index & 0xFFFFF);
+
+	rc = 0;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
+int
+roc_nix_mcast_list_free(struct mbox *mbox, uint32_t mcast_grp_index)
+{
+	struct nix_mcast_grp_destroy_req *mce_grp_destroy_req;
+	struct nix_mcast_grp_destroy_rsp *mce_grp_destroy_rsp;
+	int rc = 0;
+
+	mbox_get(mbox);
+
+	mce_grp_destroy_req = mbox_alloc_msg_nix_mcast_grp_destroy(mbox);
+	if (mce_grp_destroy_req == NULL) {
+		rc = -ENOSPC;
+		goto exit;
+	}
+
+	mce_grp_destroy_req->mcast_grp_idx = mcast_grp_index;
+	rc = mbox_process_msg(mbox, (void *)&mce_grp_destroy_rsp);
+	if (rc) {
+		plt_err("Failed to destroy mirror group index");
+		goto exit;
+	}
+
+	rc = 0;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 1958b3089d..65f99549c9 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -497,6 +497,39 @@ npc_parse_spi_to_sa_action(struct roc_npc *roc_npc, const struct roc_npc_action
 	return 0;
 }
 
+static int
+roc_npc_process_sample_action(struct roc_npc *roc_npc,
+			      const struct roc_npc_action_sample *sample_action,
+			      struct roc_npc_flow *flow)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);
+	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+	flow->is_sampling_rule = true;
+
+	switch (sample_action->action_type) {
+	case ROC_NPC_ACTION_TYPE_PORT_ID:
+		flow->mcast_pf_funcs[0] = sample_action->pf_func;
+		flow->mcast_channels[0] = sample_action->channel;
+		break;
+	case ROC_NPC_ACTION_TYPE_PF:
+		flow->mcast_pf_funcs[0] = roc_npc->pf_func;
+		flow->mcast_channels[0] = npc->channel;
+		break;
+	case ROC_NPC_ACTION_TYPE_VF:
+		if (sample_action->pf_func >= nix->dev.maxvf)
+			return -EINVAL;
+		flow->mcast_pf_funcs[0] =
+			((roc_npc->pf_func & 0xfc00) | (sample_action->pf_func + 1));
+		flow->mcast_channels[0] = npc->channel;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int
 npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		  const struct roc_npc_action actions[], struct roc_npc_flow *flow,
@@ -504,6 +537,7 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 	const struct roc_npc_action *sec_action = NULL;
+	const struct roc_npc_action_sample *act_sample;
 	const struct roc_npc_action_mark *act_mark;
 	const struct roc_npc_action_meter *act_mtr;
 	const struct roc_npc_action_queue *act_q;
@@ -562,8 +596,7 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 			break;
 
 		case ROC_NPC_ACTION_TYPE_VF:
-			vf_act =
-				(const struct roc_npc_action_vf *)actions->conf;
+			vf_act = (const struct roc_npc_action_vf *)actions->conf;
 			req_act |= ROC_NPC_ACTION_TYPE_VF;
 			vf_id = vf_act->id & RVU_PFVF_FUNC_MASK;
 			pf_func &= (0xfc00);
@@ -576,9 +609,8 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 			break;
 
 		case ROC_NPC_ACTION_TYPE_QUEUE:
-			act_q = (const struct roc_npc_action_queue *)
-					actions->conf;
-			rq = act_q->index;
+			act_q = (const struct roc_npc_action_queue *)actions->conf;
+			rq = act_q->index & 0xFFFFF;
 			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
 			break;
 
@@ -648,6 +680,13 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 				goto err_exit;
 			req_act |= ROC_NPC_ACTION_TYPE_AGE;
 			break;
+		case ROC_NPC_ACTION_TYPE_SAMPLE:
+			req_act |= ROC_NPC_ACTION_TYPE_SAMPLE;
+			act_sample = actions->conf;
+			errcode = roc_npc_process_sample_action(roc_npc, act_sample, flow);
+			if (errcode)
+				goto err_exit;
+			break;
 		default:
 			errcode = NPC_ERR_ACTION_NOTSUP;
 			goto err_exit;
@@ -688,6 +727,27 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		goto err_exit;
 	}
 
+	if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {
+		/* One entry for the mce list PF and channel comes from the sample subaction.
+		 * Another one is the action target of the flow rule getting created.
+		 */
+		flow->mcast_pf_funcs[1] = pf_func;
+		flow->mcast_channels[1] = npc->channel;
+		if (req_act & (ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_SEC |
+			       ROC_NPC_ACTION_TYPE_RSS)) {
+			plt_err("Drop/RSS/SEC not supported with action type sample");
+			return -EINVAL;
+		}
+		if (flow->mcast_pf_funcs[0] == flow->mcast_pf_funcs[1]) {
+			plt_err("Sample destination and target cannot be same");
+			return -EINVAL;
+		}
+		if ((attr->egress) && (flow->mcast_channels[0] == flow->mcast_channels[1])) {
+			plt_err("Mirroring within PF and VF not allowed");
+			return -EINVAL;
+		}
+	}
+
 	/* Check if actions specified are compatible */
 	if (attr->egress) {
 		if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
@@ -697,11 +757,10 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		}
 
 		if (req_act &
-		    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT |
-		      ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
-		      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT |
-		      ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) {
-			plt_err("Only VLAN insert, drop, count supported on Egress");
+		    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT | ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
+		      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT | ROC_NPC_ACTION_TYPE_DROP |
+		      ROC_NPC_ACTION_TYPE_COUNT | ROC_NPC_ACTION_TYPE_SAMPLE)) {
+			plt_err("Only VLAN insert, drop, count, sample supported on Egress");
 			errcode = NPC_ERR_ACTION_NOTSUP;
 			goto err_exit;
 		}
@@ -724,6 +783,11 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 			goto err_exit;
 		}
 
+		if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {
+			flow->mcast_pf_funcs[1] = pf_func;
+			flow->mcast_channels[1] = npc->channel;
+		}
+
 		goto set_pf_func;
 	} else {
 		if (vlan_insert_action) {
@@ -771,13 +835,13 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		} else {
 			flow->npc_action = NIX_RX_ACTIONOP_UCAST;
 			if (req_act & ROC_NPC_ACTION_TYPE_QUEUE)
-				flow->npc_action |= (uint64_t)rq << 20;
+				flow->recv_queue = rq;
 		}
 	} else if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
 		flow->npc_action = NIX_RX_ACTIONOP_DROP;
 	} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
-		flow->npc_action |= (uint64_t)rq << 20;
+		flow->recv_queue = rq;
 	} else if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
 	} else if (req_act & ROC_NPC_ACTION_TYPE_SEC) {
@@ -797,6 +861,9 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		goto err_exit;
 	}
 
+	if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE)
+		flow->npc_action = NIX_RX_ACTIONOP_MCAST;
+
 	if (mark)
 		flow->npc_action |= (uint64_t)mark << 40;
 
@@ -1639,6 +1706,9 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 			return rc;
 	}
 
+	if (flow->is_sampling_rule)
+		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
+
 	rc = roc_npc_mcam_free(roc_npc, flow);
 	if (rc != 0)
 		return rc;
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index cb59db2220..e880a7fa67 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -196,11 +196,19 @@ enum roc_npc_action_type {
 	ROC_NPC_ACTION_TYPE_PORT_ID = (1 << 16),
 	ROC_NPC_ACTION_TYPE_METER = (1 << 17),
 	ROC_NPC_ACTION_TYPE_AGE = (1 << 18),
+	ROC_NPC_ACTION_TYPE_SAMPLE = (1 << 19),
 };
 
 struct roc_npc_action {
 	enum roc_npc_action_type type; /**< Action type. */
-	const void *conf; /**< Pointer to action configuration object. */
+	const void *conf;	       /**< Pointer to action configuration object. */
+};
+
+struct roc_npc_action_sample {
+	uint32_t ratio;	      /**< packets sampled equals to '1/ratio'. */
+	uint32_t action_type; /* PF or VF or PORT_ID target. */
+	uint16_t pf_func;
+	uint16_t channel;
 };
 
 struct roc_npc_action_mark {
@@ -294,6 +302,8 @@ struct roc_npc_spi_to_sa_action_info {
 	bool has_action;
 };
 
+struct mbox;
+
 struct roc_npc_flow {
 	uint8_t nix_intf;
 	uint8_t enable;
@@ -322,6 +332,13 @@ struct roc_npc_flow {
 	void *age_context;
 	uint32_t timeout;
 	bool has_age_action;
+	bool is_sampling_rule;
+	uint32_t recv_queue;
+	uint32_t mcast_grp_index;
+	uint32_t mce_start_index;
+#define ROC_NPC_MIRROR_LIST_SIZE 2
+	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
+	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
 
 	TAILQ_ENTRY(roc_npc_flow) next;
 };
diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c
index 41edec7d8d..3ef189e184 100644
--- a/drivers/common/cnxk/roc_npc_mcam.c
+++ b/drivers/common/cnxk/roc_npc_mcam.c
@@ -680,6 +680,40 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		}
 	}
 
+	if (flow->nix_intf == NIX_INTF_TX) {
+		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
+
+		pf_func = plt_cpu_to_be_16(pf_func);
+
+		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
+		if (rc)
+			return rc;
+	}
+
+	if (flow->is_sampling_rule) {
+		/* Save and restore any mark value set */
+		uint16_t mark = (flow->npc_action >> 40) & 0xffff;
+		uint16_t mce_index = 0;
+		uint32_t rqs[2] = {};
+
+		rqs[1] = flow->recv_queue;
+		rc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,
+					      flow->mcast_channels, rqs, &flow->mcast_grp_index,
+					      &flow->mce_start_index);
+		if (rc)
+			return rc;
+
+		flow->npc_action = NIX_RX_ACTIONOP_MCAST;
+		mce_index = flow->mce_start_index;
+		if (flow->nix_intf == NIX_INTF_TX) {
+			flow->npc_action |= (uint64_t)mce_index << 12;
+			flow->npc_action |= (uint64_t)mark << 32;
+		} else {
+			flow->npc_action |= (uint64_t)mce_index << 20;
+			flow->npc_action |= (uint64_t)mark << 40;
+		}
+	}
+
 	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
 	if (req == NULL) {
 		rc = -ENOSPC;
@@ -691,6 +725,8 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 
 	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
 	req->enable_entry = 1;
+	if (flow->nix_intf == NIX_INTF_RX)
+		flow->npc_action |= (uint64_t)flow->recv_queue << 20;
 	req->entry_data.action = flow->npc_action;
 
 	/*
@@ -707,16 +743,6 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	 */
 	req->entry_data.vtag_action = flow->vtag_action;
 
-	if (flow->nix_intf == NIX_INTF_TX) {
-		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
-
-		pf_func = plt_cpu_to_be_16(pf_func);
-
-		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
-		if (rc)
-			return rc;
-	}
-
 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
 		req->entry_data.kw[idx] = flow->mcam_data[idx];
 		req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
@@ -746,7 +772,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		 */
 		if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
 			la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
-						       ((1ULL << 9 /* LA offset */) - 1));
+						   ((1ULL << 9 /* LA offset */) - 1));
 			la_offset *= 4;
 
 			mask = ~((0xfULL << la_offset));
@@ -778,8 +804,11 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	if (flow->use_ctr)
 		flow->ctr_id = ctr;
 	rc = 0;
+
 exit:
 	mbox_put(mbox);
+	if (rc)
+		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 	return rc;
 }
 
@@ -836,7 +865,7 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	 */
 	if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
 		lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-						   ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+					       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
 		lcflag_offset *= 4;
 
 		mask = (0xfULL << lcflag_offset);
@@ -1020,6 +1049,9 @@ npc_flow_free_all_resources(struct npc *npc)
 				rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
 			}
 
+			if (flow->is_sampling_rule)
+				roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
+
 			npc_delete_prio_list_entry(npc, flow);
 
 			TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index 424f8e207a..c0809407a6 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -493,8 +493,7 @@ void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *fl
 uint32_t npc_aged_flows_get(void *args);
 int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc);
 void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc);
-int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc,
-				 const struct roc_npc_action_age *age,
+int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, const struct roc_npc_action_age *age,
 				 struct roc_npc_flow *flow);
 void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc);
 #endif /* _ROC_NPC_PRIV_H_ */
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 52faf676ba..1b531da36d 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -294,6 +294,8 @@ INTERNAL {
 	roc_nix_mac_promisc_mode_enable;
 	roc_nix_mac_rxtx_start_stop;
 	roc_nix_max_pkt_len;
+	roc_nix_mcast_list_free;
+	roc_nix_mcast_list_setup;
 	roc_nix_mcast_mcam_entry_alloc;
 	roc_nix_mcast_mcam_entry_ena_dis;
 	roc_nix_mcast_mcam_entry_free;
-- 
2.39.2


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

* [dpdk-dev] [PATCH v2 2/3] net/cnxk: support mirror flow action
  2023-12-14 14:50 ` [dpdk-dev] [PATCH v2 1/3] common/cnxk: support mirror flow action psatheesh
@ 2023-12-14 14:50   ` psatheesh
  2023-12-15  5:34     ` Jerin Jacob
  2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 3/3] common/cnxk: add egress mirror support psatheesh
  1 sibling, 1 reply; 8+ messages in thread
From: psatheesh @ 2023-12-14 14:50 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added RTE_FLOW_ACTION_TYPE_SAMPLE action type for cnxk device.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 doc/guides/nics/features/cnxk.ini      |   1 +
 doc/guides/rel_notes/release_24_03.rst |   1 +
 drivers/net/cnxk/cnxk_flow.c           | 121 +++++++++++++++++++++++--
 3 files changed, 116 insertions(+), 7 deletions(-)

diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini
index cc7deaeaa9..94e7a6ab8d 100644
--- a/doc/guides/nics/features/cnxk.ini
+++ b/doc/guides/nics/features/cnxk.ini
@@ -97,6 +97,7 @@ port_id              = Y
 queue                = Y
 represented_port     = Y
 rss                  = Y
+sample               = Y
 security             = Y
 skip_cman            = Y
 vf                   = Y
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 866dd60fbf..282a3f9c8c 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -65,6 +65,7 @@ New Features
 * **Updated Marvell cnxk net driver.**
 
   * Added support for ``RTE_FLOW_ITEM_TYPE_PPPOES`` flow item.
+  * Added support for ``RTE_FLOW_ACTION_TYPE_SAMPLE`` flow item.
 
 Removed Items
 -------------
diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c
index 2eee44ed09..11670d37e0 100644
--- a/drivers/net/cnxk/cnxk_flow.c
+++ b/drivers/net/cnxk/cnxk_flow.c
@@ -114,14 +114,102 @@ npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev,
 	*flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss->types, rss->level);
 }
 
+static int
+npc_parse_port_id_action(struct rte_eth_dev *eth_dev, const struct rte_flow_action *action,
+			 uint16_t *dst_pf_func, uint16_t *dst_channel)
+{
+	const struct rte_flow_action_port_id *port_act;
+	struct rte_eth_dev *portid_eth_dev;
+	char if_name[RTE_ETH_NAME_MAX_LEN];
+	struct cnxk_eth_dev *hw_dst;
+	struct roc_npc *roc_npc_dst;
+	int rc = 0;
+
+	port_act = (const struct rte_flow_action_port_id *)action->conf;
+
+	rc = rte_eth_dev_get_name_by_port(port_act->id, if_name);
+	if (rc) {
+		plt_err("Name not found for output port id");
+		goto err_exit;
+	}
+	portid_eth_dev = rte_eth_dev_allocated(if_name);
+	if (!portid_eth_dev) {
+		plt_err("eth_dev not found for output port id");
+		goto err_exit;
+	}
+	if (strcmp(portid_eth_dev->device->driver->name, eth_dev->device->driver->name) != 0) {
+		plt_err("Output port not under same driver");
+		goto err_exit;
+	}
+	hw_dst = portid_eth_dev->data->dev_private;
+	roc_npc_dst = &hw_dst->npc;
+	*dst_pf_func = roc_npc_dst->pf_func;
+	*dst_channel = hw_dst->npc.channel;
+
+	return 0;
+
+err_exit:
+	return -EINVAL;
+}
+
+static int
+roc_npc_parse_sample_subaction(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[],
+			       struct roc_npc_action_sample *sample_action)
+{
+	uint16_t dst_pf_func = 0, dst_channel = 0;
+	const struct roc_npc_action_vf *vf_act;
+	int rc = 0, count = 0;
+	bool is_empty = true;
+
+	if (sample_action->ratio != 1) {
+		plt_err("Sample ratio must be 1");
+		return -EINVAL;
+	}
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		is_empty = false;
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_PF:
+			count++;
+			sample_action->action_type |= ROC_NPC_ACTION_TYPE_PF;
+			break;
+		case RTE_FLOW_ACTION_TYPE_VF:
+			count++;
+			vf_act = (const struct roc_npc_action_vf *)actions->conf;
+			sample_action->action_type |= ROC_NPC_ACTION_TYPE_VF;
+			sample_action->pf_func = vf_act->id & NPC_PFVF_FUNC_MASK;
+			break;
+		case RTE_FLOW_ACTION_TYPE_PORT_ID:
+			rc = npc_parse_port_id_action(eth_dev, actions, &dst_pf_func, &dst_channel);
+			if (rc)
+				return -EINVAL;
+
+			count++;
+			sample_action->action_type |= ROC_NPC_ACTION_TYPE_PORT_ID;
+			sample_action->pf_func = dst_pf_func;
+			sample_action->channel = dst_channel;
+			break;
+		default:
+			continue;
+		}
+	}
+
+	if (count > 1 || is_empty)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int
 cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 		 const struct rte_flow_action actions[], struct roc_npc_action in_actions[],
-		 uint32_t *flowkey_cfg, uint16_t *dst_pf_func)
+		 struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
+		 uint16_t *dst_pf_func)
 {
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
 	const struct rte_flow_action_queue *act_q = NULL;
 	const struct rte_flow_action_ethdev *act_ethdev;
+	const struct rte_flow_action_sample *act_sample;
 	const struct rte_flow_action_port_id *port_act;
 	struct rte_eth_dev *portid_eth_dev;
 	char if_name[RTE_ETH_NAME_MAX_LEN];
@@ -237,9 +325,21 @@ cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 			in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE;
 			in_actions[i].conf = actions->conf;
 			break;
+		case RTE_FLOW_ACTION_TYPE_SAMPLE:
+			act_sample = actions->conf;
+			in_sample_actions->ratio = act_sample->ratio;
+			rc = roc_npc_parse_sample_subaction(eth_dev, act_sample->actions,
+							    in_sample_actions);
+			if (rc) {
+				plt_err("Sample subaction parsing failed.");
+				goto err_exit;
+			}
+
+			in_actions[i].type = ROC_NPC_ACTION_TYPE_SAMPLE;
+			in_actions[i].conf = in_sample_actions;
+			break;
 		default:
-			plt_npc_dbg("Action is not supported = %d",
-				    actions->type);
+			plt_npc_dbg("Action is not supported = %d", actions->type);
 			goto err_exit;
 		}
 		i++;
@@ -263,7 +363,9 @@ static int
 cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 		   const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
 		   struct roc_npc_attr *in_attr, struct roc_npc_item_info in_pattern[],
-		   struct roc_npc_action in_actions[], uint32_t *flowkey_cfg, uint16_t *dst_pf_func)
+		   struct roc_npc_action in_actions[],
+		   struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
+		   uint16_t *dst_pf_func)
 {
 	int i = 0;
 
@@ -282,7 +384,8 @@ cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr
 	}
 	in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
 
-	return cnxk_map_actions(eth_dev, attr, actions, in_actions, flowkey_cfg, dst_pf_func);
+	return cnxk_map_actions(eth_dev, attr, actions, in_actions, in_sample_actions, flowkey_cfg,
+				dst_pf_func);
 }
 
 static int
@@ -293,6 +396,7 @@ cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr
 	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
 	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_npc_action_sample in_sample_action;
 	struct roc_npc *npc = &dev->npc;
 	struct roc_npc_attr in_attr;
 	struct roc_npc_flow flow;
@@ -306,10 +410,11 @@ cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr
 		return 0;
 
 	memset(&flow, 0, sizeof(flow));
+	memset(&in_sample_action, 0, sizeof(in_sample_action));
 	flow.is_validate = true;
 
 	rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
-				&flowkey_cfg, &dst_pf_func);
+				&in_sample_action, &flowkey_cfg, &dst_pf_func);
 	if (rc) {
 		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
 				   "Failed to map flow data");
@@ -335,6 +440,7 @@ cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
 	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
 	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
+	struct roc_npc_action_sample in_sample_action;
 	struct roc_npc *npc = &dev->npc;
 	struct roc_npc_attr in_attr;
 	struct roc_npc_flow *flow;
@@ -342,8 +448,9 @@ cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 	int errcode = 0;
 	int rc;
 
+	memset(&in_sample_action, 0, sizeof(in_sample_action));
 	rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
-				&npc->flowkey_cfg_state, &dst_pf_func);
+				&in_sample_action, &npc->flowkey_cfg_state, &dst_pf_func);
 	if (rc) {
 		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
 				   "Failed to map flow data");
-- 
2.39.2


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

* [dpdk-dev] [PATCH v2 3/3] common/cnxk: add egress mirror support
  2023-12-14 14:50 ` [dpdk-dev] [PATCH v2 1/3] common/cnxk: support mirror flow action psatheesh
  2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 2/3] net/cnxk: " psatheesh
@ 2023-12-14 14:50   ` psatheesh
  1 sibling, 0 replies; 8+ messages in thread
From: psatheesh @ 2023-12-14 14:50 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: dev, Satheesh Paul

From: Satha Rao <skoteshwar@marvell.com>

Added ROC api to send packets on multiple links when egress mirror
enabled.

Signed-off-by: Satha Rao <skoteshwar@marvell.com>
Reviewed-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
Reviewed-by: Satheesh Paul <psatheesh@marvell.com>
---
 drivers/common/cnxk/roc_nix.h        |  2 +
 drivers/common/cnxk/roc_nix_tm_ops.c | 70 ++++++++++++++++++++++++++++
 drivers/common/cnxk/roc_npc.c        | 26 +++++++++++
 drivers/common/cnxk/version.map      |  1 +
 4 files changed, 99 insertions(+)

diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index c1ebf971f7..84e6fc3df5 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -755,6 +755,8 @@ int __roc_api roc_nix_tm_mark_config(struct roc_nix *roc_nix,
 				     int mark_red);
 uint64_t __roc_api roc_nix_tm_mark_format_get(struct roc_nix *roc_nix,
 					      uint64_t *flags);
+int __roc_api roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func,
+					     bool enable);
 
 /* Ingress Policer API */
 int __roc_api roc_nix_bpf_timeunit_get(struct roc_nix *roc_nix,
diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c b/drivers/common/cnxk/roc_nix_tm_ops.c
index 2c53472047..900b182c76 100644
--- a/drivers/common/cnxk/roc_nix_tm_ops.c
+++ b/drivers/common/cnxk/roc_nix_tm_ops.c
@@ -1316,3 +1316,73 @@ roc_nix_tm_root_has_sp(struct roc_nix *roc_nix)
 		return false;
 	return true;
 }
+
+static inline struct nix *
+pf_func_to_nix_get(uint16_t pf_func)
+{
+	struct roc_nix *roc_nix_tmp = NULL;
+	struct roc_nix_list *nix_list;
+
+	nix_list = roc_idev_nix_list_get();
+	if (nix_list == NULL)
+		return NULL;
+
+	/* Find the NIX of given pf_func */
+	TAILQ_FOREACH(roc_nix_tmp, nix_list, next) {
+		struct nix *nix = roc_nix_to_nix_priv(roc_nix_tmp);
+
+		if (nix->dev.pf_func == pf_func)
+			return nix;
+	}
+
+	return NULL;
+}
+
+int
+roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func, bool enable)
+{
+	struct nix *src_nix = roc_nix_to_nix_priv(roc_nix), *dst_nix;
+	struct mbox *mbox = (&src_nix->dev)->mbox;
+	struct nix_txschq_config *req = NULL;
+	struct nix_tm_node_list *list;
+	struct nix_tm_node *node;
+	int rc = 0, k;
+
+	dst_nix = pf_func_to_nix_get(dst_pf_func);
+	if (!dst_nix)
+		return -EINVAL;
+
+	if (dst_nix == src_nix)
+		return 0;
+
+	list = nix_tm_node_list(src_nix, src_nix->tm_tree);
+	TAILQ_FOREACH(node, list, node) {
+		if (node->hw_lvl != src_nix->tm_link_cfg_lvl)
+			continue;
+
+		if (!(node->flags & NIX_TM_NODE_HWRES))
+			continue;
+
+		/* Allocating TL3 request */
+		req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
+		req->lvl = src_nix->tm_link_cfg_lvl;
+		k = 0;
+
+		/* Enable PFC/pause on the identified TL3 */
+		req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, dst_nix->tx_link);
+		if (enable)
+			req->regval[k] |= BIT_ULL(12);
+		else
+			req->regval[k] &= ~(BIT_ULL(12));
+		req->regval_mask[k] = ~(BIT_ULL(12));
+		k++;
+
+		req->num_regs = k;
+		rc = mbox_process(mbox);
+		mbox_put(mbox);
+		if (rc)
+			goto err;
+	}
+err:
+	return rc;
+}
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 65f99549c9..9a0fe5f4e2 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -1595,6 +1595,21 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
 		goto err_exit;
 	}
 
+	/* If Egress mirror requested then enable TL3_TL2_LINK_CFG */
+	if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
+		if (flow->mcast_pf_funcs[0] == npc->pf_func)
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[1], true);
+		else
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[0], true);
+		if (rc) {
+			plt_err("Adding egress mirror failed");
+			*errcode = rc;
+			goto err_exit;
+		}
+	}
+
 	rc = npc_rss_action_program(roc_npc, actions, flow);
 	if (rc != 0) {
 		*errcode = rc;
@@ -1706,6 +1721,17 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 			return rc;
 	}
 
+	/* Disable egress mirror rule */
+	if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
+		if (flow->mcast_pf_funcs[0] == npc->pf_func)
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[1], false);
+		else
+			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+							    flow->mcast_pf_funcs[0], false);
+		if (rc)
+			plt_err("Failed to remove egress mirror rule");
+	}
 	if (flow->is_sampling_rule)
 		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 1b531da36d..7b6afa63a9 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -355,6 +355,7 @@ INTERNAL {
 	roc_nix_switch_hdr_set;
 	roc_nix_eeprom_info_get;
 	roc_nix_smq_flush;
+	roc_nix_tm_egress_link_cfg_set;
 	roc_nix_tm_dump;
 	roc_nix_tm_err_to_rte_err;
 	roc_nix_tm_fini;
-- 
2.39.2


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

* Re: [dpdk-dev] [PATCH v2 2/3] net/cnxk: support mirror flow action
  2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 2/3] net/cnxk: " psatheesh
@ 2023-12-15  5:34     ` Jerin Jacob
  0 siblings, 0 replies; 8+ messages in thread
From: Jerin Jacob @ 2023-12-15  5:34 UTC (permalink / raw)
  To: psatheesh, Harman Kalra
  Cc: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao, dev

On Thu, Dec 14, 2023 at 8:28 PM <psatheesh@marvell.com> wrote:
>
> From: Satheesh Paul <psatheesh@marvell.com>
>
> Added RTE_FLOW_ACTION_TYPE_SAMPLE action type for cnxk device.
>
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>


Series applied to dpdk-next-eventdev/for-main. Thanks.

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

end of thread, other threads:[~2023-12-15  5:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-14 10:58 [dpdk-dev] [PATCH 1/3] common/cnxk: support mirror flow action psatheesh
2023-12-14 10:58 ` [dpdk-dev] [PATCH 2/3] net/cnxk: " psatheesh
2023-12-14 13:43   ` [EXT] " Jerin Jacob Kollanukkaran
2023-12-14 10:58 ` [dpdk-dev] [PATCH 3/3] common/cnxk: add egress mirror support psatheesh
2023-12-14 14:50 ` [dpdk-dev] [PATCH v2 1/3] common/cnxk: support mirror flow action psatheesh
2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 2/3] net/cnxk: " psatheesh
2023-12-15  5:34     ` Jerin Jacob
2023-12-14 14:50   ` [dpdk-dev] [PATCH v2 3/3] common/cnxk: add egress mirror support psatheesh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).