All of lore.kernel.org
 help / color / mirror / Atom feed
From: <psatheesh@marvell.com>
To: Nithin Dabilpuram <ndabilpuram@marvell.com>,
	Kiran Kumar K <kirankumark@marvell.com>,
	Sunil Kumar Kori <skori@marvell.com>,
	Satha Rao <skoteshwar@marvell.com>
Cc: <dev@dpdk.org>, Satheesh Paul <psatheesh@marvell.com>
Subject: [dpdk-dev] [PATCH] common/cnxk: support for dual VLAN insert and strip actions
Date: Mon, 19 Jul 2021 11:11:57 +0530	[thread overview]
Message-ID: <20210719054157.1665582-1-psatheesh@marvell.com> (raw)

From: Satheesh Paul <psatheesh@marvell.com>

Add roc API to configure dual VLAN tag addition and removal.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
 drivers/common/cnxk/roc_npc.c      | 339 ++++++++++++++++++++++-------
 drivers/common/cnxk/roc_npc.h      |   1 +
 drivers/common/cnxk/roc_npc_priv.h |  11 +-
 3 files changed, 267 insertions(+), 84 deletions(-)

diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index aff4eef554..52a54b3990 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -10,7 +10,7 @@ roc_npc_vtag_actions_get(struct roc_npc *roc_npc)
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 
-	return npc->vtag_actions;
+	return npc->vtag_strip_actions;
 }
 
 int
@@ -18,8 +18,8 @@ roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count)
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 
-	npc->vtag_actions -= count;
-	return npc->vtag_actions;
+	npc->vtag_strip_actions -= count;
+	return npc->vtag_strip_actions;
 }
 
 int
@@ -481,6 +481,23 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr,
 			goto err_exit;
 		}
 
+		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");
+			errcode = NPC_ERR_ACTION_NOTSUP;
+			goto err_exit;
+		}
+
+		if (vlan_insert_action &&
+		    (req_act & ROC_NPC_ACTION_TYPE_DROP)) {
+			plt_err("Both VLAN insert and drop actions cannot be supported");
+			errcode = NPC_ERR_ACTION_NOTSUP;
+			goto err_exit;
+		}
+
 		if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
 			flow->npc_action = NIX_TX_ACTIONOP_DROP;
 		} else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) ||
@@ -526,14 +543,14 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr,
 	}
 
 	if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)
-		npc->vtag_actions++;
-
-	/* Only VLAN action is provided */
-	if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP)
-		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
+		npc->vtag_strip_actions++;
 
 	/* Set NIX_RX_ACTIONOP */
-	if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) {
+	if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
+		/* Only VLAN action is provided */
+		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
+	} else if (req_act &
+		   (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) {
 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
 		if (req_act & ROC_NPC_ACTION_TYPE_QUEUE)
 			flow->npc_action |= (uint64_t)rq << 20;
@@ -872,6 +889,11 @@ npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 	vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def;
 	vtag_cfg->tx.free_vtag0 = true;
 
+	if (flow->vtag_insert_count == 2) {
+		vtag_cfg->tx.vtag1_idx = tx_vtag_action.act.vtag1_def;
+		vtag_cfg->tx.free_vtag1 = true;
+	}
+
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		return rc;
@@ -880,120 +902,271 @@ npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 }
 
 static int
-npc_vtag_action_program(struct roc_npc *roc_npc,
-			const struct roc_npc_action actions[],
-			struct roc_npc_flow *flow)
+npc_vtag_insert_action_parse(const struct roc_npc_action actions[],
+			     struct roc_npc_flow *flow,
+			     struct npc_action_vtag_info *vlan_info,
+			     int *parsed_cnt)
 {
-	uint16_t vlan_id = 0, vlan_ethtype = ROC_ETHER_TYPE_VLAN;
-	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
-	struct roc_nix *roc_nix = roc_npc->roc_nix;
-	struct nix_vtag_config *vtag_cfg;
-	struct nix_vtag_config_rsp *rsp;
-	uint64_t rx_vtag_action = 0;
-	uint8_t vlan_pcp = 0;
-	struct mbox *mbox;
-	struct nix *nix;
-	int rc;
-
-	union {
-		uint64_t reg;
-		struct nix_tx_vtag_action_s act;
-	} tx_vtag_action;
-
-	nix = roc_nix_to_nix_priv(roc_nix);
-	mbox = (&nix->dev)->mbox;
-
-	flow->vtag_insert_enabled = false;
-
-	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
-		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
-			if (npc->vtag_actions == 1) {
-				vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
+	bool vlan_id_found = false, ethtype_found = false, pcp_found = false;
+	int count = 0;
 
-				if (vtag_cfg == NULL)
-					return -ENOSPC;
+	*parsed_cnt = 0;
 
-				vtag_cfg->cfg_type = VTAG_RX;
-				vtag_cfg->rx.strip_vtag = 1;
-				/* Always capture */
-				vtag_cfg->rx.capture_vtag = 1;
-				vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
-				vtag_cfg->rx.vtag_type = 0;
+	/* This function parses parameters of one VLAN. When a parameter is
+	 * found repeated, it treats it as the end of first VLAN's parameters
+	 * and returns. The caller calls again to parse the parameters of the
+	 * second VLAN.
+	 */
 
-				rc = mbox_process(mbox);
-				if (rc)
-					return rc;
-			}
+	for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) {
+		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) {
+			if (vlan_id_found)
+				return 0;
 
-			rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
-			rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8);
-			rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR;
-			flow->vtag_action = rx_vtag_action;
-		} else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) {
 			const struct roc_npc_action_of_set_vlan_vid *vtag =
 				(const struct roc_npc_action_of_set_vlan_vid *)
 					actions->conf;
-			vlan_id = plt_be_to_cpu_16(vtag->vlan_vid);
-			if (vlan_id > 0xfff) {
+
+			vlan_info->vlan_id = plt_be_to_cpu_16(vtag->vlan_vid);
+
+			if (vlan_info->vlan_id > 0xfff) {
 				plt_err("Invalid vlan_id for set vlan action");
 				return -EINVAL;
 			}
+
 			flow->vtag_insert_enabled = true;
+			(*parsed_cnt)++;
+			vlan_id_found = true;
 		} else if (actions->type ==
 			   ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) {
+			if (ethtype_found)
+				return 0;
+
 			const struct roc_npc_action_of_push_vlan *ethtype =
 				(const struct roc_npc_action_of_push_vlan *)
 					actions->conf;
-			vlan_ethtype = plt_be_to_cpu_16(ethtype->ethertype);
-			if (vlan_ethtype != ROC_ETHER_TYPE_VLAN &&
-			    vlan_ethtype != ROC_ETHER_TYPE_QINQ) {
+			vlan_info->vlan_ethtype =
+				plt_be_to_cpu_16(ethtype->ethertype);
+			if (vlan_info->vlan_ethtype != ROC_ETHER_TYPE_VLAN &&
+			    vlan_info->vlan_ethtype != ROC_ETHER_TYPE_QINQ) {
 				plt_err("Invalid ethtype specified for push"
 					" vlan action");
 				return -EINVAL;
 			}
 			flow->vtag_insert_enabled = true;
+			(*parsed_cnt)++;
+			ethtype_found = true;
 		} else if (actions->type ==
 			   ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
+			if (pcp_found)
+				return 0;
 			const struct roc_npc_action_of_set_vlan_pcp *pcp =
 				(const struct roc_npc_action_of_set_vlan_pcp *)
 					actions->conf;
-			vlan_pcp = pcp->vlan_pcp;
-			if (vlan_pcp > 0x7) {
+			vlan_info->vlan_pcp = pcp->vlan_pcp;
+			if (vlan_info->vlan_pcp > 0x7) {
 				plt_err("Invalid PCP value for pcp action");
 				return -EINVAL;
 			}
 			flow->vtag_insert_enabled = true;
+			(*parsed_cnt)++;
+			pcp_found = true;
+		} else {
+			return 0;
 		}
 	}
 
-	if (flow->vtag_insert_enabled) {
-		vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
+	return 0;
+}
 
-		if (vtag_cfg == NULL)
-			return -ENOSPC;
+static int
+npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow,
+				 struct npc_action_vtag_info *vlan_info)
+{
+	struct nix_vtag_config *vtag_cfg;
+	struct nix_vtag_config_rsp *rsp;
+	int rc = 0;
 
-		vtag_cfg->cfg_type = VTAG_TX;
-		vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
-		vtag_cfg->tx.vtag0 =
-			((vlan_ethtype << 16) | (vlan_pcp << 13) | vlan_id);
+	union {
+		uint64_t reg;
+		struct nix_tx_vtag_action_s act;
+	} tx_vtag_action;
 
-		vtag_cfg->tx.cfg_vtag0 = 1;
-		rc = mbox_process_msg(mbox, (void *)&rsp);
-		if (rc)
-			return rc;
+	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
 
-		if (rsp->vtag0_idx < 0) {
-			plt_err("Failed to config TX VTAG action");
-			return -EINVAL;
-		}
+	if (vtag_cfg == NULL)
+		return -ENOSPC;
+
+	vtag_cfg->cfg_type = VTAG_TX;
+	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
+	vtag_cfg->tx.vtag0 =
+		((vlan_info[0].vlan_ethtype << 16) |
+		 (vlan_info[0].vlan_pcp << 13) | vlan_info[0].vlan_id);
+
+	vtag_cfg->tx.cfg_vtag0 = 1;
+
+	if (flow->vtag_insert_count == 2) {
+		vtag_cfg->tx.vtag1 =
+			((vlan_info[1].vlan_ethtype << 16) |
+			 (vlan_info[1].vlan_pcp << 13) | vlan_info[1].vlan_id);
+
+		vtag_cfg->tx.cfg_vtag1 = 1;
+	}
+
+	rc = mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		return rc;
+
+	if (rsp->vtag0_idx < 0 ||
+	    ((flow->vtag_insert_count == 2) && (rsp->vtag1_idx < 0))) {
+		plt_err("Failed to config TX VTAG action");
+		return -EINVAL;
+	}
 
-		tx_vtag_action.reg = 0;
-		tx_vtag_action.act.vtag0_def = rsp->vtag0_idx;
-		tx_vtag_action.act.vtag0_lid = NPC_LID_LA;
-		tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT;
-		tx_vtag_action.act.vtag0_relptr =
+	tx_vtag_action.reg = 0;
+	tx_vtag_action.act.vtag0_def = rsp->vtag0_idx;
+	tx_vtag_action.act.vtag0_lid = NPC_LID_LA;
+	tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT;
+	tx_vtag_action.act.vtag0_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR;
+
+	if (flow->vtag_insert_count == 2) {
+		tx_vtag_action.act.vtag1_def = rsp->vtag1_idx;
+		tx_vtag_action.act.vtag1_lid = NPC_LID_LA;
+		tx_vtag_action.act.vtag1_op = NIX_TX_VTAGOP_INSERT;
+		/* NIX_TX_VTAG_ACTION_S
+		 *  If Vtag 0 is inserted, hardware adjusts the Vtag 1 byte
+		 *  offset accordingly. Thus, if the two offsets are equal in
+		 *  the structure, hardware inserts Vtag 1 immediately after
+		 *  Vtag 0 in the packet.
+		 */
+		tx_vtag_action.act.vtag1_relptr =
 			NIX_TX_VTAGACTION_VTAG0_RELPTR;
-		flow->vtag_action = tx_vtag_action.reg;
+	}
+
+	flow->vtag_action = tx_vtag_action.reg;
+
+	return 0;
+}
+
+static int
+npc_vtag_strip_action_configure(struct mbox *mbox,
+				const struct roc_npc_action actions[],
+				struct roc_npc_flow *flow, int *strip_cnt)
+{
+	struct nix_vtag_config *vtag_cfg;
+	uint64_t rx_vtag_action = 0;
+	int count = 0, rc = 0;
+
+	*strip_cnt = 0;
+
+	for (; count < NPC_ACTION_MAX_VLANS_STRIPPED; count++, actions++) {
+		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP)
+			(*strip_cnt)++;
+	}
+
+	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
+
+	if (vtag_cfg == NULL)
+		return -ENOSPC;
+
+	vtag_cfg->cfg_type = VTAG_RX;
+	vtag_cfg->rx.strip_vtag = 1;
+	/* Always capture */
+	vtag_cfg->rx.capture_vtag = 1;
+	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
+	vtag_cfg->rx.vtag_type = 0;
+
+	rc = mbox_process(mbox);
+	if (rc)
+		return rc;
+
+	rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
+	rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8);
+	rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR;
+
+	if (*strip_cnt == 2) {
+		rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47);
+		rx_vtag_action |= ((uint64_t)NPC_LID_LB << 40);
+		rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR << 32;
+	}
+	flow->vtag_action = rx_vtag_action;
+
+	return 0;
+}
+
+static int
+npc_vtag_action_program(struct roc_npc *roc_npc,
+			const struct roc_npc_action actions[],
+			struct roc_npc_flow *flow)
+{
+	bool vlan_strip_parsed = false, vlan_insert_parsed = false;
+	const struct roc_npc_action *insert_actions;
+	struct roc_nix *roc_nix = roc_npc->roc_nix;
+	struct npc_action_vtag_info vlan_info[2];
+	int parsed_cnt = 0, strip_cnt = 0;
+	int tot_vlan_params = 0;
+	struct mbox *mbox;
+	struct nix *nix;
+	int i, rc;
+
+	nix = roc_nix_to_nix_priv(roc_nix);
+	mbox = (&nix->dev)->mbox;
+
+	memset(vlan_info, 0, sizeof(vlan_info));
+
+	flow->vtag_insert_enabled = false;
+
+	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
+		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
+			if (vlan_strip_parsed) {
+				plt_err("Incorrect VLAN strip actions");
+				return -EINVAL;
+			}
+			rc = npc_vtag_strip_action_configure(mbox, actions,
+							     flow, &strip_cnt);
+			if (rc)
+				return rc;
+
+			if (strip_cnt == 2)
+				actions++;
+
+			vlan_strip_parsed = true;
+		} else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT ||
+			   actions->type ==
+				   ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT ||
+			   actions->type ==
+				   ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
+			if (vlan_insert_parsed) {
+				plt_err("Incorrect VLAN insert actions");
+				return -EINVAL;
+			}
+
+			insert_actions = actions;
+
+			for (i = 0; i < 2; i++) {
+				rc = npc_vtag_insert_action_parse(
+					insert_actions, flow, &vlan_info[i],
+					&parsed_cnt);
+
+				if (rc)
+					return rc;
+
+				if (parsed_cnt) {
+					insert_actions += parsed_cnt;
+					tot_vlan_params += parsed_cnt;
+					flow->vtag_insert_count++;
+				}
+			}
+			actions += tot_vlan_params - 1;
+			vlan_insert_parsed = true;
+		}
+	}
+
+	if (flow->vtag_insert_enabled) {
+		rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info);
+
+		if (rc)
+			return rc;
 	}
 	return 0;
 }
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index 2c0a536c93..e86595fe9a 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -124,6 +124,7 @@ struct roc_npc_flow {
 	uint64_t npc_action;
 	uint64_t vtag_action;
 	bool vtag_insert_enabled;
+	uint8_t vtag_insert_count;
 #define ROC_NPC_MAX_FLOW_PATTERNS 32
 	struct roc_npc_flow_dump_data dump_data[ROC_NPC_MAX_FLOW_PATTERNS];
 	uint16_t num_patterns;
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index 484c3aeb1f..1ba8adcd4b 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -57,6 +57,15 @@
 	(NPC_NIXLF_MAX * NPC_MCAME_PER_LF +                                    \
 	 (NPC_RVUPF_MAX_10XX - 1) * NPC_MCAME_PER_PF)
 
+#define NPC_ACTION_MAX_VLAN_PARAMS    3
+#define NPC_ACTION_MAX_VLANS_STRIPPED 2
+
+struct npc_action_vtag_info {
+	uint16_t vlan_id;
+	uint16_t vlan_ethtype;
+	uint8_t vlan_pcp;
+};
+
 enum npc_err_status {
 	NPC_ERR_PARAM = -1024,
 	NPC_ERR_NO_MEM,
@@ -350,7 +359,7 @@ struct npc {
 	uint16_t flow_max_priority;		/* Max priority for flow */
 	uint16_t switch_header_type; /* Suppprted switch header type */
 	uint32_t mark_actions;	     /* Number of mark actions */
-	uint32_t vtag_actions;	     /* vtag insert/strip actions */
+	uint32_t vtag_strip_actions; /* vtag insert/strip actions */
 	uint16_t pf_func;	     /* pf_func of device */
 	npc_dxcfg_t prx_dxcfg;	     /* intf, lid, lt, extract */
 	npc_fxcfg_t prx_fxcfg;	     /* Flag extract */
-- 
2.25.4


             reply	other threads:[~2021-07-19  5:42 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-19  5:41 psatheesh [this message]
2021-09-07  1:58 ` [dpdk-dev] [PATCH] common/cnxk: support for dual VLAN insert and strip actions Jerin Jacob
2021-09-16 14:30   ` Jerin Jacob

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210719054157.1665582-1-psatheesh@marvell.com \
    --to=psatheesh@marvell.com \
    --cc=dev@dpdk.org \
    --cc=kirankumark@marvell.com \
    --cc=ndabilpuram@marvell.com \
    --cc=skori@marvell.com \
    --cc=skoteshwar@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.