xref: /dpdk/drivers/common/cnxk/roc_npc_parse.c (revision 296e9040e2c15b424cf716bfdde0f5257c17a9fd)
1c34ea71bSKiran Kumar K /* SPDX-License-Identifier: BSD-3-Clause
2c34ea71bSKiran Kumar K  * Copyright(C) 2021 Marvell.
3c34ea71bSKiran Kumar K  */
4c34ea71bSKiran Kumar K #include "roc_api.h"
5c34ea71bSKiran Kumar K #include "roc_priv.h"
6c34ea71bSKiran Kumar K 
7c34ea71bSKiran Kumar K const struct roc_npc_item_info *
npc_parse_skip_void_and_any_items(const struct roc_npc_item_info * pattern)8c34ea71bSKiran Kumar K npc_parse_skip_void_and_any_items(const struct roc_npc_item_info *pattern)
9c34ea71bSKiran Kumar K {
10c34ea71bSKiran Kumar K 	while ((pattern->type == ROC_NPC_ITEM_TYPE_VOID) ||
11c34ea71bSKiran Kumar K 	       (pattern->type == ROC_NPC_ITEM_TYPE_ANY))
12c34ea71bSKiran Kumar K 		pattern++;
13c34ea71bSKiran Kumar K 
14c34ea71bSKiran Kumar K 	return pattern;
15c34ea71bSKiran Kumar K }
16c34ea71bSKiran Kumar K 
17c34ea71bSKiran Kumar K int
npc_parse_meta_items(struct npc_parse_state * pst)18c34ea71bSKiran Kumar K npc_parse_meta_items(struct npc_parse_state *pst)
19c34ea71bSKiran Kumar K {
20c34ea71bSKiran Kumar K 	PLT_SET_USED(pst);
21c34ea71bSKiran Kumar K 	return 0;
22c34ea71bSKiran Kumar K }
23c34ea71bSKiran Kumar K 
244968b362SSatheesh Paul int
npc_parse_mark_item(struct npc_parse_state * pst)254968b362SSatheesh Paul npc_parse_mark_item(struct npc_parse_state *pst)
264968b362SSatheesh Paul {
274968b362SSatheesh Paul 	if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MARK) {
284968b362SSatheesh Paul 		if (pst->flow->nix_intf != NIX_INTF_RX)
294968b362SSatheesh Paul 			return -EINVAL;
304968b362SSatheesh Paul 
314968b362SSatheesh Paul 		pst->is_second_pass_rule = true;
324968b362SSatheesh Paul 		pst->pattern++;
334968b362SSatheesh Paul 	}
344968b362SSatheesh Paul 
354968b362SSatheesh Paul 	return 0;
364968b362SSatheesh Paul }
374968b362SSatheesh Paul 
38*296e9040SKiran Kumar K int
npc_parse_port_representor_id(struct npc_parse_state * pst)39*296e9040SKiran Kumar K npc_parse_port_representor_id(struct npc_parse_state *pst)
40*296e9040SKiran Kumar K {
41*296e9040SKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_REPRESENTED_PORT)
42*296e9040SKiran Kumar K 		return 0;
43*296e9040SKiran Kumar K 
44*296e9040SKiran Kumar K 	pst->pattern++;
45*296e9040SKiran Kumar K 
46*296e9040SKiran Kumar K 	return 0;
47*296e9040SKiran Kumar K }
48*296e9040SKiran Kumar K 
49*296e9040SKiran Kumar K int
npc_parse_represented_port_id(struct npc_parse_state * pst)50*296e9040SKiran Kumar K npc_parse_represented_port_id(struct npc_parse_state *pst)
51*296e9040SKiran Kumar K {
52*296e9040SKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_REPRESENTED_PORT)
53*296e9040SKiran Kumar K 		return 0;
54*296e9040SKiran Kumar K 
55*296e9040SKiran Kumar K 	if (pst->flow->nix_intf != NIX_INTF_RX)
56*296e9040SKiran Kumar K 		return -EINVAL;
57*296e9040SKiran Kumar K 
58*296e9040SKiran Kumar K 	pst->pattern++;
59*296e9040SKiran Kumar K 
60*296e9040SKiran Kumar K 	return 0;
61*296e9040SKiran Kumar K }
62*296e9040SKiran Kumar K 
6384d2ea9dSKiran Kumar K static int
npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw * raw_spec,const struct roc_npc_flow_item_raw * raw_mask,struct npc_parse_item_info * info,uint8_t * spec_buf,uint8_t * mask_buf)6484d2ea9dSKiran Kumar K npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
6584d2ea9dSKiran Kumar K 			  const struct roc_npc_flow_item_raw *raw_mask,
66*296e9040SKiran Kumar K 			  struct npc_parse_item_info *info, uint8_t *spec_buf, uint8_t *mask_buf)
6784d2ea9dSKiran Kumar K {
6884d2ea9dSKiran Kumar K 
6984d2ea9dSKiran Kumar K 	memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
7084d2ea9dSKiran Kumar K 	memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
7184d2ea9dSKiran Kumar K 
7284d2ea9dSKiran Kumar K 	memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
7384d2ea9dSKiran Kumar K 	       raw_spec->length);
7484d2ea9dSKiran Kumar K 
7584d2ea9dSKiran Kumar K 	if (raw_mask && raw_mask->pattern) {
7684d2ea9dSKiran Kumar K 		memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
7784d2ea9dSKiran Kumar K 		       raw_spec->length);
7884d2ea9dSKiran Kumar K 	} else {
7984d2ea9dSKiran Kumar K 		memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
8084d2ea9dSKiran Kumar K 	}
8184d2ea9dSKiran Kumar K 
8284d2ea9dSKiran Kumar K 	info->len = NPC_MAX_RAW_ITEM_LEN;
8384d2ea9dSKiran Kumar K 	info->spec = spec_buf;
8484d2ea9dSKiran Kumar K 	info->mask = mask_buf;
8584d2ea9dSKiran Kumar K 	return 0;
8684d2ea9dSKiran Kumar K }
8784d2ea9dSKiran Kumar K 
8884d2ea9dSKiran Kumar K int
npc_parse_pre_l2(struct npc_parse_state * pst)8984d2ea9dSKiran Kumar K npc_parse_pre_l2(struct npc_parse_state *pst)
9084d2ea9dSKiran Kumar K {
9184d2ea9dSKiran Kumar K 	uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
9284d2ea9dSKiran Kumar K 	uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
9384d2ea9dSKiran Kumar K 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN] = {0};
9484d2ea9dSKiran Kumar K 	const struct roc_npc_flow_item_raw *raw_spec;
9584d2ea9dSKiran Kumar K 	struct npc_parse_item_info info;
9684d2ea9dSKiran Kumar K 	int lid, lt, len;
9784d2ea9dSKiran Kumar K 	int rc;
9884d2ea9dSKiran Kumar K 
9984d2ea9dSKiran Kumar K 	if (pst->npc->switch_header_type != ROC_PRIV_FLAGS_PRE_L2)
10084d2ea9dSKiran Kumar K 		return 0;
10184d2ea9dSKiran Kumar K 
10284d2ea9dSKiran Kumar K 	/* Identify the pattern type into lid, lt */
10384d2ea9dSKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_RAW)
10484d2ea9dSKiran Kumar K 		return 0;
10584d2ea9dSKiran Kumar K 
10684d2ea9dSKiran Kumar K 	lid = NPC_LID_LA;
10784d2ea9dSKiran Kumar K 	lt = NPC_LT_LA_CUSTOM_PRE_L2_ETHER;
10884d2ea9dSKiran Kumar K 	info.hw_hdr_len = 0;
10984d2ea9dSKiran Kumar K 
11084d2ea9dSKiran Kumar K 	raw_spec = pst->pattern->spec;
11184d2ea9dSKiran Kumar K 	len = raw_spec->length + raw_spec->offset;
11284d2ea9dSKiran Kumar K 	if (len > NPC_MAX_RAW_ITEM_LEN)
11384d2ea9dSKiran Kumar K 		return -EINVAL;
11484d2ea9dSKiran Kumar K 
11584d2ea9dSKiran Kumar K 	if (raw_spec->relative == 0 || raw_spec->search || raw_spec->limit ||
11684d2ea9dSKiran Kumar K 	    raw_spec->offset < 0)
11784d2ea9dSKiran Kumar K 		return -EINVAL;
11884d2ea9dSKiran Kumar K 
11984d2ea9dSKiran Kumar K 	npc_flow_raw_item_prepare(
12084d2ea9dSKiran Kumar K 		(const struct roc_npc_flow_item_raw *)pst->pattern->spec,
12184d2ea9dSKiran Kumar K 		(const struct roc_npc_flow_item_raw *)pst->pattern->mask, &info,
12284d2ea9dSKiran Kumar K 		raw_spec_buf, raw_mask_buf);
12384d2ea9dSKiran Kumar K 
1240e5d72c4SSatheesh Paul 	info.def_mask = NULL;
12584d2ea9dSKiran Kumar K 	info.hw_mask = &hw_mask;
12684d2ea9dSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
12784d2ea9dSKiran Kumar K 
12884d2ea9dSKiran Kumar K 	/* Basic validation of item parameters */
12984d2ea9dSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
13084d2ea9dSKiran Kumar K 	if (rc)
13184d2ea9dSKiran Kumar K 		return rc;
13284d2ea9dSKiran Kumar K 
13384d2ea9dSKiran Kumar K 	/* Update pst if not validate only? clash check? */
13484d2ea9dSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, 0);
13584d2ea9dSKiran Kumar K }
13684d2ea9dSKiran Kumar K 
137c34ea71bSKiran Kumar K int
npc_parse_cpt_hdr(struct npc_parse_state * pst)138c34ea71bSKiran Kumar K npc_parse_cpt_hdr(struct npc_parse_state *pst)
139c34ea71bSKiran Kumar K {
140c34ea71bSKiran Kumar K 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
141c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
142c34ea71bSKiran Kumar K 	int lid, lt;
143c34ea71bSKiran Kumar K 	int rc;
144c34ea71bSKiran Kumar K 
145c34ea71bSKiran Kumar K 	/* Identify the pattern type into lid, lt */
146c34ea71bSKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR)
147c34ea71bSKiran Kumar K 		return 0;
148c34ea71bSKiran Kumar K 
149c34ea71bSKiran Kumar K 	lid = NPC_LID_LA;
150c34ea71bSKiran Kumar K 	lt = NPC_LT_LA_CPT_HDR;
151c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
152c34ea71bSKiran Kumar K 
153c34ea71bSKiran Kumar K 	/* Prepare for parsing the item */
154244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
155c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
156c34ea71bSKiran Kumar K 	info.len = pst->pattern->size;
157c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
158c34ea71bSKiran Kumar K 	info.spec = NULL;
159c34ea71bSKiran Kumar K 	info.mask = NULL;
160c34ea71bSKiran Kumar K 
161c34ea71bSKiran Kumar K 	/* Basic validation of item parameters */
162c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
163c34ea71bSKiran Kumar K 	if (rc)
164c34ea71bSKiran Kumar K 		return rc;
165c34ea71bSKiran Kumar K 
166c34ea71bSKiran Kumar K 	/* Update pst if not validate only? clash check? */
167c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, 0);
168c34ea71bSKiran Kumar K }
169c34ea71bSKiran Kumar K 
170c34ea71bSKiran Kumar K int
npc_parse_higig2_hdr(struct npc_parse_state * pst)171c34ea71bSKiran Kumar K npc_parse_higig2_hdr(struct npc_parse_state *pst)
172c34ea71bSKiran Kumar K {
173c34ea71bSKiran Kumar K 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
174c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
175c34ea71bSKiran Kumar K 	int lid, lt;
176c34ea71bSKiran Kumar K 	int rc;
177c34ea71bSKiran Kumar K 
178c34ea71bSKiran Kumar K 	/* Identify the pattern type into lid, lt */
179c34ea71bSKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
180c34ea71bSKiran Kumar K 		return 0;
181c34ea71bSKiran Kumar K 
182c34ea71bSKiran Kumar K 	lid = NPC_LID_LA;
183c34ea71bSKiran Kumar K 	lt = NPC_LT_LA_HIGIG2_ETHER;
184c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
185c34ea71bSKiran Kumar K 
186c34ea71bSKiran Kumar K 	if (pst->flow->nix_intf == NIX_INTF_TX) {
187c34ea71bSKiran Kumar K 		lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
188c34ea71bSKiran Kumar K 		info.hw_hdr_len = NPC_IH_LENGTH;
189c34ea71bSKiran Kumar K 	}
190c34ea71bSKiran Kumar K 
191c34ea71bSKiran Kumar K 	/* Prepare for parsing the item */
192244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
193c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
194c34ea71bSKiran Kumar K 	info.len = pst->pattern->size;
195c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
196c34ea71bSKiran Kumar K 	info.spec = NULL;
197c34ea71bSKiran Kumar K 	info.mask = NULL;
198c34ea71bSKiran Kumar K 
199c34ea71bSKiran Kumar K 	/* Basic validation of item parameters */
200c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
201c34ea71bSKiran Kumar K 	if (rc)
202c34ea71bSKiran Kumar K 		return rc;
203c34ea71bSKiran Kumar K 
204c34ea71bSKiran Kumar K 	/* Update pst if not validate only? clash check? */
205c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, 0);
206c34ea71bSKiran Kumar K }
207c34ea71bSKiran Kumar K 
208c34ea71bSKiran Kumar K int
npc_parse_tx_queue(struct npc_parse_state * pst)209b7fff4e4SSatheesh Paul npc_parse_tx_queue(struct npc_parse_state *pst)
210b7fff4e4SSatheesh Paul {
211b7fff4e4SSatheesh Paul 	struct nix_inst_hdr_s nix_inst_hdr, nix_inst_hdr_mask;
212b7fff4e4SSatheesh Paul 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
213b7fff4e4SSatheesh Paul 	struct npc_parse_item_info parse_info;
214b7fff4e4SSatheesh Paul 	const uint16_t *send_queue;
215b7fff4e4SSatheesh Paul 	int lid, lt, rc = 0;
216b7fff4e4SSatheesh Paul 
217b7fff4e4SSatheesh Paul 	memset(&nix_inst_hdr, 0, sizeof(nix_inst_hdr));
218b7fff4e4SSatheesh Paul 	memset(&nix_inst_hdr_mask, 0, sizeof(nix_inst_hdr_mask));
219b7fff4e4SSatheesh Paul 	memset(&parse_info, 0, sizeof(parse_info));
220b7fff4e4SSatheesh Paul 
221b7fff4e4SSatheesh Paul 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_TX_QUEUE)
222b7fff4e4SSatheesh Paul 		return 0;
223b7fff4e4SSatheesh Paul 
224b7fff4e4SSatheesh Paul 	if (pst->flow->nix_intf != NIX_INTF_TX)
225b7fff4e4SSatheesh Paul 		return NPC_ERR_INVALID_SPEC;
226b7fff4e4SSatheesh Paul 
227b7fff4e4SSatheesh Paul 	lid = NPC_LID_LA;
228b7fff4e4SSatheesh Paul 	lt = NPC_LT_LA_IH_NIX_ETHER;
229b7fff4e4SSatheesh Paul 	send_queue = (const uint16_t *)pst->pattern->spec;
230b7fff4e4SSatheesh Paul 
231b7fff4e4SSatheesh Paul 	if (*send_queue >= pst->nb_tx_queues)
232b7fff4e4SSatheesh Paul 		return NPC_ERR_INVALID_SPEC;
233b7fff4e4SSatheesh Paul 
234b7fff4e4SSatheesh Paul 	nix_inst_hdr.sq = *send_queue;
235b7fff4e4SSatheesh Paul 	nix_inst_hdr_mask.sq = 0xFFFF;
236b7fff4e4SSatheesh Paul 
237b7fff4e4SSatheesh Paul 	parse_info.def_mask = NULL;
238b7fff4e4SSatheesh Paul 	parse_info.spec = &nix_inst_hdr;
239b7fff4e4SSatheesh Paul 	parse_info.mask = &nix_inst_hdr_mask;
240b7fff4e4SSatheesh Paul 	parse_info.len = sizeof(nix_inst_hdr);
241b7fff4e4SSatheesh Paul 	parse_info.def_mask = NULL;
242b7fff4e4SSatheesh Paul 	parse_info.hw_hdr_len = 0;
243b7fff4e4SSatheesh Paul 
244b7fff4e4SSatheesh Paul 	memset(hw_mask, 0, sizeof(hw_mask));
245b7fff4e4SSatheesh Paul 
246b7fff4e4SSatheesh Paul 	parse_info.hw_mask = &hw_mask;
247b7fff4e4SSatheesh Paul 	npc_get_hw_supp_mask(pst, &parse_info, lid, lt);
248b7fff4e4SSatheesh Paul 
249b7fff4e4SSatheesh Paul 	rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
250b7fff4e4SSatheesh Paul 	if (!rc)
251b7fff4e4SSatheesh Paul 		return NPC_ERR_INVALID_MASK;
252b7fff4e4SSatheesh Paul 
253b7fff4e4SSatheesh Paul 	rc = npc_update_parse_state(pst, &parse_info, lid, lt, 0);
254b7fff4e4SSatheesh Paul 	if (rc)
255b7fff4e4SSatheesh Paul 		return rc;
256b7fff4e4SSatheesh Paul 
257b7fff4e4SSatheesh Paul 	return 0;
258b7fff4e4SSatheesh Paul }
259b7fff4e4SSatheesh Paul 
260b7fff4e4SSatheesh Paul int
npc_parse_la(struct npc_parse_state * pst)261c34ea71bSKiran Kumar K npc_parse_la(struct npc_parse_state *pst)
262c34ea71bSKiran Kumar K {
263b8ac8b08SSatheesh Paul 	const struct roc_npc_flow_item_eth *eth_item;
264c34ea71bSKiran Kumar K 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
265c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
266c34ea71bSKiran Kumar K 	int lid, lt;
267c34ea71bSKiran Kumar K 	int rc;
268c34ea71bSKiran Kumar K 
269c34ea71bSKiran Kumar K 	/* Identify the pattern type into lid, lt */
270c34ea71bSKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
271c34ea71bSKiran Kumar K 		return 0;
272c34ea71bSKiran Kumar K 
27378c78d87SKiran Kumar K 	pst->has_eth_type = true;
274b8ac8b08SSatheesh Paul 	eth_item = pst->pattern->spec;
275b8ac8b08SSatheesh Paul 
276c34ea71bSKiran Kumar K 	lid = NPC_LID_LA;
277c34ea71bSKiran Kumar K 	lt = NPC_LT_LA_ETHER;
278c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
279c34ea71bSKiran Kumar K 
280c34ea71bSKiran Kumar K 	if (pst->flow->nix_intf == NIX_INTF_TX) {
281c34ea71bSKiran Kumar K 		lt = NPC_LT_LA_IH_NIX_ETHER;
282c34ea71bSKiran Kumar K 		info.hw_hdr_len = NPC_IH_LENGTH;
283c34ea71bSKiran Kumar K 		if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
284c34ea71bSKiran Kumar K 			lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
285c34ea71bSKiran Kumar K 			info.hw_hdr_len += NPC_HIGIG2_LENGTH;
286c34ea71bSKiran Kumar K 		}
287c34ea71bSKiran Kumar K 	} else {
288c34ea71bSKiran Kumar K 		if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
289c34ea71bSKiran Kumar K 			lt = NPC_LT_LA_HIGIG2_ETHER;
290c34ea71bSKiran Kumar K 			info.hw_hdr_len = NPC_HIGIG2_LENGTH;
291c34ea71bSKiran Kumar K 		}
292c34ea71bSKiran Kumar K 	}
293c34ea71bSKiran Kumar K 
294c34ea71bSKiran Kumar K 	/* Prepare for parsing the item */
295244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
296c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
297b8ac8b08SSatheesh Paul 	info.len = sizeof(eth_item->hdr);
298c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
299c34ea71bSKiran Kumar K 	info.spec = NULL;
300c34ea71bSKiran Kumar K 	info.mask = NULL;
301c34ea71bSKiran Kumar K 
302c34ea71bSKiran Kumar K 	/* Basic validation of item parameters */
303c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
304c34ea71bSKiran Kumar K 	if (rc)
305c34ea71bSKiran Kumar K 		return rc;
306c34ea71bSKiran Kumar K 
307b8ac8b08SSatheesh Paul 	rc = npc_update_parse_state(pst, &info, lid, lt, 0);
308b8ac8b08SSatheesh Paul 	if (rc)
309b8ac8b08SSatheesh Paul 		return rc;
310b8ac8b08SSatheesh Paul 
311b8ac8b08SSatheesh Paul 	if (eth_item && eth_item->has_vlan)
312b8ac8b08SSatheesh Paul 		pst->set_vlan_ltype_mask = true;
313b8ac8b08SSatheesh Paul 
314b8ac8b08SSatheesh Paul 	return 0;
315c34ea71bSKiran Kumar K }
316c34ea71bSKiran Kumar K 
317b8ac8b08SSatheesh Paul #define NPC_MAX_SUPPORTED_VLANS 3
318b8ac8b08SSatheesh Paul 
31947412486SSatheesh Paul static int
npc_parse_vlan_count(const struct roc_npc_item_info * pattern,const struct roc_npc_item_info ** pattern_list,const struct roc_npc_flow_item_vlan ** vlan_items,int * vlan_count)32047412486SSatheesh Paul npc_parse_vlan_count(const struct roc_npc_item_info *pattern,
32147412486SSatheesh Paul 		     const struct roc_npc_item_info **pattern_list,
32247412486SSatheesh Paul 		     const struct roc_npc_flow_item_vlan **vlan_items, int *vlan_count)
323c34ea71bSKiran Kumar K {
32447412486SSatheesh Paul 	*vlan_count = 0;
325c34ea71bSKiran Kumar K 	while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
32647412486SSatheesh Paul 		if (*vlan_count > NPC_MAX_SUPPORTED_VLANS - 1)
327b8ac8b08SSatheesh Paul 			return NPC_ERR_PATTERN_NOTSUP;
328b8ac8b08SSatheesh Paul 
32947412486SSatheesh Paul 		/* Don't support ranges */
33047412486SSatheesh Paul 		if (pattern->last != NULL)
33147412486SSatheesh Paul 			return NPC_ERR_INVALID_RANGE;
332c34ea71bSKiran Kumar K 
33347412486SSatheesh Paul 		/* If spec is NULL, both mask and last must be NULL, this
33447412486SSatheesh Paul 		 * makes it to match ANY value (eq to mask = 0).
33547412486SSatheesh Paul 		 * Setting either mask or last without spec is an error
33647412486SSatheesh Paul 		 */
33747412486SSatheesh Paul 		if (pattern->spec == NULL) {
33847412486SSatheesh Paul 			if (pattern->last != NULL && pattern->mask != NULL)
33947412486SSatheesh Paul 				return NPC_ERR_INVALID_SPEC;
340c34ea71bSKiran Kumar K 		}
34147412486SSatheesh Paul 
34247412486SSatheesh Paul 		pattern_list[*vlan_count] = pattern;
34347412486SSatheesh Paul 		vlan_items[*vlan_count] = pattern->spec;
34447412486SSatheesh Paul 		(*vlan_count)++;
34547412486SSatheesh Paul 
346c34ea71bSKiran Kumar K 		pattern++;
347c34ea71bSKiran Kumar K 		pattern = npc_parse_skip_void_and_any_items(pattern);
348c34ea71bSKiran Kumar K 	}
349c34ea71bSKiran Kumar K 
35047412486SSatheesh Paul 	return 0;
35147412486SSatheesh Paul }
35247412486SSatheesh Paul 
35347412486SSatheesh Paul static int
npc_parse_vlan_ltype_get(struct npc_parse_state * pst,const struct roc_npc_flow_item_vlan ** vlan_item,int vlan_count,int * ltype,int * lflags)35447412486SSatheesh Paul npc_parse_vlan_ltype_get(struct npc_parse_state *pst,
35547412486SSatheesh Paul 			 const struct roc_npc_flow_item_vlan **vlan_item, int vlan_count,
35647412486SSatheesh Paul 			 int *ltype, int *lflags)
35747412486SSatheesh Paul {
35847412486SSatheesh Paul 	switch (vlan_count) {
359c34ea71bSKiran Kumar K 	case 1:
36047412486SSatheesh Paul 		*ltype = NPC_LT_LB_CTAG;
361b8ac8b08SSatheesh Paul 		if (vlan_item[0] && vlan_item[0]->has_more_vlan)
36247412486SSatheesh Paul 			*ltype = NPC_LT_LB_STAG_QINQ;
363c34ea71bSKiran Kumar K 		break;
364c34ea71bSKiran Kumar K 	case 2:
365b8ac8b08SSatheesh Paul 		if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
366b8ac8b08SSatheesh Paul 			if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
367b8ac8b08SSatheesh Paul 			      0x3ULL << NPC_LFLAG_LB_OFFSET))
368b8ac8b08SSatheesh Paul 				return NPC_ERR_PATTERN_NOTSUP;
369b8ac8b08SSatheesh Paul 
370b8ac8b08SSatheesh Paul 			/* This lflag value will match either one of
371b8ac8b08SSatheesh Paul 			 * NPC_F_LB_L_WITH_STAG_STAG,
372b8ac8b08SSatheesh Paul 			 * NPC_F_LB_L_WITH_QINQ_CTAG,
373b8ac8b08SSatheesh Paul 			 * NPC_F_LB_L_WITH_QINQ_QINQ and
374b8ac8b08SSatheesh Paul 			 * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
375b8ac8b08SSatheesh Paul 			 * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
376b8ac8b08SSatheesh Paul 			 * hence will not match.
377b8ac8b08SSatheesh Paul 			 */
378b8ac8b08SSatheesh Paul 
37947412486SSatheesh Paul 			*lflags = NPC_F_LB_L_WITH_QINQ_CTAG & NPC_F_LB_L_WITH_QINQ_QINQ &
380b8ac8b08SSatheesh Paul 				  NPC_F_LB_L_WITH_STAG_STAG;
381b8ac8b08SSatheesh Paul 		}
38247412486SSatheesh Paul 		*ltype = NPC_LT_LB_STAG_QINQ;
383c34ea71bSKiran Kumar K 		break;
384c34ea71bSKiran Kumar K 	case 3:
385b8ac8b08SSatheesh Paul 		if (vlan_item[2] && vlan_item[2]->has_more_vlan)
386b8ac8b08SSatheesh Paul 			return NPC_ERR_PATTERN_NOTSUP;
38747412486SSatheesh Paul 		if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] & 0x3ULL << NPC_LFLAG_LB_OFFSET))
38847412486SSatheesh Paul 			return NPC_ERR_PATTERN_NOTSUP;
38947412486SSatheesh Paul 		*ltype = NPC_LT_LB_STAG_QINQ;
39047412486SSatheesh Paul 		*lflags = NPC_F_STAG_STAG_CTAG;
391c34ea71bSKiran Kumar K 		break;
392c34ea71bSKiran Kumar K 	default:
393c34ea71bSKiran Kumar K 		return NPC_ERR_PATTERN_NOTSUP;
394c34ea71bSKiran Kumar K 	}
39547412486SSatheesh Paul 
39647412486SSatheesh Paul 	return 0;
39747412486SSatheesh Paul }
39847412486SSatheesh Paul 
39947412486SSatheesh Paul static int
npc_update_vlan_parse_state(struct npc_parse_state * pst,const struct roc_npc_item_info * pattern,int lid,int lt,uint8_t lflags,int vlan_count)40047412486SSatheesh Paul npc_update_vlan_parse_state(struct npc_parse_state *pst, const struct roc_npc_item_info *pattern,
40147412486SSatheesh Paul 			    int lid, int lt, uint8_t lflags, int vlan_count)
40247412486SSatheesh Paul {
40347412486SSatheesh Paul 	uint8_t vlan_spec[NPC_MAX_SUPPORTED_VLANS * sizeof(struct roc_vlan_hdr)];
40447412486SSatheesh Paul 	uint8_t vlan_mask[NPC_MAX_SUPPORTED_VLANS * sizeof(struct roc_vlan_hdr)];
40547412486SSatheesh Paul 	int rc = 0, i, offset = NPC_TPID_LENGTH;
40647412486SSatheesh Paul 	struct npc_parse_item_info parse_info;
40747412486SSatheesh Paul 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
40847412486SSatheesh Paul 
40947412486SSatheesh Paul 	memset(vlan_spec, 0, sizeof(struct roc_vlan_hdr) * NPC_MAX_SUPPORTED_VLANS);
41047412486SSatheesh Paul 	memset(vlan_mask, 0, sizeof(struct roc_vlan_hdr) * NPC_MAX_SUPPORTED_VLANS);
41147412486SSatheesh Paul 	memset(&parse_info, 0, sizeof(parse_info));
41247412486SSatheesh Paul 
41347412486SSatheesh Paul 	if (vlan_count > 2)
41447412486SSatheesh Paul 		vlan_count = 2;
41547412486SSatheesh Paul 
41647412486SSatheesh Paul 	for (i = 0; i < vlan_count; i++) {
41747412486SSatheesh Paul 		if (pattern[i].spec)
41847412486SSatheesh Paul 			memcpy(vlan_spec + offset, pattern[i].spec, sizeof(struct roc_vlan_hdr));
41947412486SSatheesh Paul 		if (pattern[i].mask)
42047412486SSatheesh Paul 			memcpy(vlan_mask + offset, pattern[i].mask, sizeof(struct roc_vlan_hdr));
42147412486SSatheesh Paul 
42247412486SSatheesh Paul 		offset += 4;
42347412486SSatheesh Paul 	}
42447412486SSatheesh Paul 
42547412486SSatheesh Paul 	parse_info.def_mask = NULL;
42647412486SSatheesh Paul 	parse_info.spec = vlan_spec;
42747412486SSatheesh Paul 	parse_info.mask = vlan_mask;
42847412486SSatheesh Paul 	parse_info.def_mask = NULL;
42947412486SSatheesh Paul 	parse_info.hw_hdr_len = 0;
43047412486SSatheesh Paul 
43147412486SSatheesh Paul 	lid = NPC_LID_LB;
43247412486SSatheesh Paul 	parse_info.hw_mask = hw_mask;
43347412486SSatheesh Paul 
43447412486SSatheesh Paul 	if (lt == NPC_LT_LB_CTAG)
43547412486SSatheesh Paul 		parse_info.len = sizeof(struct roc_vlan_hdr) + NPC_TPID_LENGTH;
43647412486SSatheesh Paul 
43747412486SSatheesh Paul 	if (lt == NPC_LT_LB_STAG_QINQ)
43847412486SSatheesh Paul 		parse_info.len = sizeof(struct roc_vlan_hdr) * 2 + NPC_TPID_LENGTH;
43947412486SSatheesh Paul 
44047412486SSatheesh Paul 	memset(hw_mask, 0, sizeof(hw_mask));
44147412486SSatheesh Paul 
44247412486SSatheesh Paul 	parse_info.hw_mask = &hw_mask;
44347412486SSatheesh Paul 	npc_get_hw_supp_mask(pst, &parse_info, lid, lt);
44447412486SSatheesh Paul 
44547412486SSatheesh Paul 	rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
44647412486SSatheesh Paul 	if (!rc)
44747412486SSatheesh Paul 		return NPC_ERR_INVALID_MASK;
44847412486SSatheesh Paul 
44947412486SSatheesh Paul 	/* Point pattern to last item consumed */
45047412486SSatheesh Paul 	pst->pattern = pattern;
45147412486SSatheesh Paul 	return npc_update_parse_state(pst, &parse_info, lid, lt, lflags);
45247412486SSatheesh Paul }
45347412486SSatheesh Paul 
45447412486SSatheesh Paul static int
npc_parse_lb_vlan(struct npc_parse_state * pst)45547412486SSatheesh Paul npc_parse_lb_vlan(struct npc_parse_state *pst)
45647412486SSatheesh Paul {
45747412486SSatheesh Paul 	const struct roc_npc_flow_item_vlan *vlan_items[NPC_MAX_SUPPORTED_VLANS];
45847412486SSatheesh Paul 	const struct roc_npc_item_info *pattern_list[NPC_MAX_SUPPORTED_VLANS];
45947412486SSatheesh Paul 	const struct roc_npc_item_info *last_pattern;
46047412486SSatheesh Paul 	int vlan_count = 0, rc = 0;
46147412486SSatheesh Paul 	int lid, lt, lflags;
46247412486SSatheesh Paul 
46347412486SSatheesh Paul 	lid = NPC_LID_LB;
46447412486SSatheesh Paul 	lflags = 0;
46547412486SSatheesh Paul 	last_pattern = pst->pattern;
46647412486SSatheesh Paul 
46747412486SSatheesh Paul 	rc = npc_parse_vlan_count(pst->pattern, pattern_list, vlan_items, &vlan_count);
46847412486SSatheesh Paul 	if (rc)
46947412486SSatheesh Paul 		return rc;
47047412486SSatheesh Paul 
47147412486SSatheesh Paul 	rc = npc_parse_vlan_ltype_get(pst, vlan_items, vlan_count, &lt, &lflags);
47247412486SSatheesh Paul 	if (rc)
47347412486SSatheesh Paul 		return rc;
47447412486SSatheesh Paul 
47547412486SSatheesh Paul 	if (vlan_count == 3) {
47647412486SSatheesh Paul 		if (pattern_list[2]->spec != NULL && pattern_list[2]->mask != NULL &&
47747412486SSatheesh Paul 		    pattern_list[2]->last != NULL)
47847412486SSatheesh Paul 			return NPC_ERR_PATTERN_NOTSUP;
47947412486SSatheesh Paul 
48047412486SSatheesh Paul 		/* Matching can be done only for two tags. */
48147412486SSatheesh Paul 		vlan_count = 2;
48247412486SSatheesh Paul 		last_pattern++;
48347412486SSatheesh Paul 	}
48447412486SSatheesh Paul 
48547412486SSatheesh Paul 	rc = npc_update_vlan_parse_state(pst, pattern_list[0], lid, lt, lflags, vlan_count);
48647412486SSatheesh Paul 	if (rc)
48747412486SSatheesh Paul 		return rc;
48847412486SSatheesh Paul 
48947412486SSatheesh Paul 	if (vlan_count > 1)
49047412486SSatheesh Paul 		pst->pattern = last_pattern + vlan_count;
49147412486SSatheesh Paul 
49247412486SSatheesh Paul 	return 0;
49347412486SSatheesh Paul }
49447412486SSatheesh Paul 
49547412486SSatheesh Paul int
npc_parse_lb(struct npc_parse_state * pst)49647412486SSatheesh Paul npc_parse_lb(struct npc_parse_state *pst)
49747412486SSatheesh Paul {
49847412486SSatheesh Paul 	const struct roc_npc_item_info *pattern = pst->pattern;
49947412486SSatheesh Paul 	const struct roc_npc_item_info *last_pattern;
50047412486SSatheesh Paul 	const struct roc_npc_flow_item_raw *raw_spec;
50147412486SSatheesh Paul 	uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
50247412486SSatheesh Paul 	uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
50347412486SSatheesh Paul 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
50447412486SSatheesh Paul 	struct npc_parse_item_info info;
50547412486SSatheesh Paul 	int lid, lt, lflags, len = 0;
50647412486SSatheesh Paul 	int rc;
50747412486SSatheesh Paul 
50847412486SSatheesh Paul 	info.def_mask = NULL;
50947412486SSatheesh Paul 	info.spec = NULL;
51047412486SSatheesh Paul 	info.mask = NULL;
51147412486SSatheesh Paul 	info.def_mask = NULL;
51247412486SSatheesh Paul 	info.hw_hdr_len = NPC_TPID_LENGTH;
51347412486SSatheesh Paul 
51447412486SSatheesh Paul 	lid = NPC_LID_LB;
51547412486SSatheesh Paul 	lflags = 0;
51647412486SSatheesh Paul 	last_pattern = pattern;
51747412486SSatheesh Paul 
51847412486SSatheesh Paul 	if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
51947412486SSatheesh Paul 		/* RTE vlan is either 802.1q or 802.1ad,
52047412486SSatheesh Paul 		 * this maps to either CTAG/STAG. We need to decide
52147412486SSatheesh Paul 		 * based on number of VLANS present. Matching is
52247412486SSatheesh Paul 		 * supported on first two tags.
52347412486SSatheesh Paul 		 */
52447412486SSatheesh Paul 
52547412486SSatheesh Paul 		return npc_parse_lb_vlan(pst);
526c34ea71bSKiran Kumar K 	} else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
527c34ea71bSKiran Kumar K 		/* we can support ETAG and match a subsequent CTAG
528c34ea71bSKiran Kumar K 		 * without any matching support.
529c34ea71bSKiran Kumar K 		 */
530c34ea71bSKiran Kumar K 		lt = NPC_LT_LB_ETAG;
531c34ea71bSKiran Kumar K 		lflags = 0;
532c34ea71bSKiran Kumar K 
533c34ea71bSKiran Kumar K 		last_pattern = pst->pattern;
534c34ea71bSKiran Kumar K 		pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
535c34ea71bSKiran Kumar K 		if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
536c34ea71bSKiran Kumar K 			/* set supported mask to NULL for vlan tag */
537c34ea71bSKiran Kumar K 			info.hw_mask = NULL;
538c34ea71bSKiran Kumar K 			info.len = pattern->size;
539c34ea71bSKiran Kumar K 			rc = npc_parse_item_basic(pattern, &info);
540c34ea71bSKiran Kumar K 			if (rc != 0)
541c34ea71bSKiran Kumar K 				return rc;
542c34ea71bSKiran Kumar K 
543c34ea71bSKiran Kumar K 			lflags = NPC_F_ETAG_CTAG;
544c34ea71bSKiran Kumar K 			last_pattern = pattern;
545c34ea71bSKiran Kumar K 		}
546c34ea71bSKiran Kumar K 		info.len = pattern->size;
547c34ea71bSKiran Kumar K 	} else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
548c34ea71bSKiran Kumar K 		info.hw_mask = NULL;
549c6353c57SSatheesh Paul 		info.len = pattern->size;
550c34ea71bSKiran Kumar K 		lt = NPC_LT_LB_STAG_QINQ;
551c34ea71bSKiran Kumar K 		lflags = NPC_F_STAG_CTAG;
5520686d9a3SSatheesh Paul 	} else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_PPPOES) {
5530686d9a3SSatheesh Paul 		info.hw_mask = NULL;
5540686d9a3SSatheesh Paul 		info.len = pattern->size;
5550686d9a3SSatheesh Paul 		info.hw_hdr_len = 2;
5560686d9a3SSatheesh Paul 		lt = NPC_LT_LB_PPPOE;
557612ce5cfSSatheesh Paul 	} else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
558612ce5cfSSatheesh Paul 		raw_spec = pst->pattern->spec;
559612ce5cfSSatheesh Paul 		if (raw_spec->relative)
560612ce5cfSSatheesh Paul 			return 0;
561612ce5cfSSatheesh Paul 		len = raw_spec->length + raw_spec->offset;
562612ce5cfSSatheesh Paul 		if (len > NPC_MAX_RAW_ITEM_LEN)
563612ce5cfSSatheesh Paul 			return -EINVAL;
564612ce5cfSSatheesh Paul 
565612ce5cfSSatheesh Paul 		if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
566612ce5cfSSatheesh Paul 			lt = NPC_LT_LB_VLAN_EXDSA;
567612ce5cfSSatheesh Paul 		} else if (pst->npc->switch_header_type ==
568612ce5cfSSatheesh Paul 			   ROC_PRIV_FLAGS_EXDSA) {
569612ce5cfSSatheesh Paul 			lt = NPC_LT_LB_EXDSA;
570612ce5cfSSatheesh Paul 		} else {
571612ce5cfSSatheesh Paul 			return -EINVAL;
572612ce5cfSSatheesh Paul 		}
573612ce5cfSSatheesh Paul 
574612ce5cfSSatheesh Paul 		npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
575612ce5cfSSatheesh Paul 						  pst->pattern->spec,
576612ce5cfSSatheesh Paul 					  (const struct roc_npc_flow_item_raw *)
577612ce5cfSSatheesh Paul 						  pst->pattern->mask,
578612ce5cfSSatheesh Paul 					  &info, raw_spec_buf, raw_mask_buf);
579612ce5cfSSatheesh Paul 
580612ce5cfSSatheesh Paul 		info.hw_hdr_len = 0;
581c34ea71bSKiran Kumar K 	} else {
582c34ea71bSKiran Kumar K 		return 0;
583c34ea71bSKiran Kumar K 	}
584c34ea71bSKiran Kumar K 
585c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
586c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
587c34ea71bSKiran Kumar K 
588c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
589c34ea71bSKiran Kumar K 	if (rc != 0)
590c34ea71bSKiran Kumar K 		return rc;
591c34ea71bSKiran Kumar K 
592c34ea71bSKiran Kumar K 	/* Point pattern to last item consumed */
593c34ea71bSKiran Kumar K 	pst->pattern = last_pattern;
594c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, lflags);
595c34ea71bSKiran Kumar K }
596c34ea71bSKiran Kumar K 
597c34ea71bSKiran Kumar K static int
npc_parse_mpls_label_stack(struct npc_parse_state * pst,int * flag)598c34ea71bSKiran Kumar K npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
599c34ea71bSKiran Kumar K {
600c34ea71bSKiran Kumar K 	uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
601c34ea71bSKiran Kumar K 			       NPC_F_MPLS_4_LABELS};
602c34ea71bSKiran Kumar K 	const struct roc_npc_item_info *pattern = pst->pattern;
603c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
604c34ea71bSKiran Kumar K 	int nr_labels = 0;
605c34ea71bSKiran Kumar K 	int rc;
606c34ea71bSKiran Kumar K 
607c34ea71bSKiran Kumar K 	/*
608c34ea71bSKiran Kumar K 	 * pst->pattern points to first MPLS label. We only check
609c34ea71bSKiran Kumar K 	 * that subsequent labels do not have anything to match.
610c34ea71bSKiran Kumar K 	 */
611244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
612c34ea71bSKiran Kumar K 	info.hw_mask = NULL;
613c34ea71bSKiran Kumar K 	info.len = pattern->size;
614c34ea71bSKiran Kumar K 	info.spec = NULL;
615c34ea71bSKiran Kumar K 	info.mask = NULL;
616c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
617c34ea71bSKiran Kumar K 
618c34ea71bSKiran Kumar K 	while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
619c34ea71bSKiran Kumar K 		nr_labels++;
620c34ea71bSKiran Kumar K 
621c34ea71bSKiran Kumar K 		/* Basic validation of Second/Third/Fourth mpls item */
622c34ea71bSKiran Kumar K 		if (nr_labels > 1) {
623c34ea71bSKiran Kumar K 			rc = npc_parse_item_basic(pattern, &info);
624c34ea71bSKiran Kumar K 			if (rc != 0)
625c34ea71bSKiran Kumar K 				return rc;
626c34ea71bSKiran Kumar K 		}
627c34ea71bSKiran Kumar K 		pst->last_pattern = pattern;
628c34ea71bSKiran Kumar K 		pattern++;
629c34ea71bSKiran Kumar K 		pattern = npc_parse_skip_void_and_any_items(pattern);
630c34ea71bSKiran Kumar K 	}
631c34ea71bSKiran Kumar K 
632c34ea71bSKiran Kumar K 	if (nr_labels < 1 || nr_labels > 4)
633c34ea71bSKiran Kumar K 		return NPC_ERR_PATTERN_NOTSUP;
634c34ea71bSKiran Kumar K 
635c34ea71bSKiran Kumar K 	*flag = flag_list[nr_labels - 1];
636c34ea71bSKiran Kumar K 	return 0;
637c34ea71bSKiran Kumar K }
638c34ea71bSKiran Kumar K 
639c34ea71bSKiran Kumar K static int
npc_parse_mpls(struct npc_parse_state * pst,int lid)640c34ea71bSKiran Kumar K npc_parse_mpls(struct npc_parse_state *pst, int lid)
641c34ea71bSKiran Kumar K {
642c34ea71bSKiran Kumar K 	/* Find number of MPLS labels */
643c34ea71bSKiran Kumar K 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
644c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
645c34ea71bSKiran Kumar K 	int lt, lflags;
646c34ea71bSKiran Kumar K 	int rc;
647c34ea71bSKiran Kumar K 
648c34ea71bSKiran Kumar K 	lflags = 0;
649c34ea71bSKiran Kumar K 
650c34ea71bSKiran Kumar K 	if (lid == NPC_LID_LC)
651c34ea71bSKiran Kumar K 		lt = NPC_LT_LC_MPLS;
652c34ea71bSKiran Kumar K 	else if (lid == NPC_LID_LD)
653c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_TU_MPLS_IN_IP;
654c34ea71bSKiran Kumar K 	else
655c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_TU_MPLS_IN_UDP;
656c34ea71bSKiran Kumar K 
657c34ea71bSKiran Kumar K 	/* Prepare for parsing the first item */
658c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
659c34ea71bSKiran Kumar K 	info.len = pst->pattern->size;
660c34ea71bSKiran Kumar K 	info.spec = NULL;
661c34ea71bSKiran Kumar K 	info.mask = NULL;
662244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
663c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
664c34ea71bSKiran Kumar K 
665c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
666c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
667c34ea71bSKiran Kumar K 	if (rc != 0)
668c34ea71bSKiran Kumar K 		return rc;
669c34ea71bSKiran Kumar K 
670c34ea71bSKiran Kumar K 	/*
671c34ea71bSKiran Kumar K 	 * Parse for more labels.
672c34ea71bSKiran Kumar K 	 * This sets lflags and pst->last_pattern correctly.
673c34ea71bSKiran Kumar K 	 */
674c34ea71bSKiran Kumar K 	rc = npc_parse_mpls_label_stack(pst, &lflags);
675c34ea71bSKiran Kumar K 	if (rc != 0)
676c34ea71bSKiran Kumar K 		return rc;
677c34ea71bSKiran Kumar K 
678c34ea71bSKiran Kumar K 	pst->tunnel = 1;
679c34ea71bSKiran Kumar K 	pst->pattern = pst->last_pattern;
680c34ea71bSKiran Kumar K 
681c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, lflags);
682c34ea71bSKiran Kumar K }
683c34ea71bSKiran Kumar K 
684c34ea71bSKiran Kumar K static inline void
npc_check_lc_ip_tunnel(struct npc_parse_state * pst)685c34ea71bSKiran Kumar K npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
686c34ea71bSKiran Kumar K {
687c34ea71bSKiran Kumar K 	const struct roc_npc_item_info *pattern = pst->pattern + 1;
688c34ea71bSKiran Kumar K 
689c34ea71bSKiran Kumar K 	pattern = npc_parse_skip_void_and_any_items(pattern);
690c34ea71bSKiran Kumar K 	if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
691c34ea71bSKiran Kumar K 	    pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
692c34ea71bSKiran Kumar K 	    pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
693c34ea71bSKiran Kumar K 		pst->tunnel = 1;
694c34ea71bSKiran Kumar K }
695c34ea71bSKiran Kumar K 
696474e275bSSatheesh Paul static int
npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 * ipv6_spec,struct npc_parse_state * pst,uint8_t * flags)697474e275bSSatheesh Paul npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
698474e275bSSatheesh Paul 			struct npc_parse_state *pst, uint8_t *flags)
699474e275bSSatheesh Paul {
700474e275bSSatheesh Paul 	int flags_count = 0;
701474e275bSSatheesh Paul 
702474e275bSSatheesh Paul 	if (ipv6_spec->has_hop_ext) {
703474e275bSSatheesh Paul 		*flags = NPC_F_LC_L_EXT_HOP;
704474e275bSSatheesh Paul 		flags_count++;
705474e275bSSatheesh Paul 	}
706474e275bSSatheesh Paul 	if (ipv6_spec->has_route_ext) {
707474e275bSSatheesh Paul 		*flags = NPC_F_LC_L_EXT_ROUT;
708474e275bSSatheesh Paul 		flags_count++;
709474e275bSSatheesh Paul 	}
710474e275bSSatheesh Paul 	if (ipv6_spec->has_frag_ext) {
711474e275bSSatheesh Paul 		*flags = NPC_F_LC_U_IP6_FRAG;
712474e275bSSatheesh Paul 		flags_count++;
713474e275bSSatheesh Paul 	}
714474e275bSSatheesh Paul 	if (ipv6_spec->has_dest_ext) {
715474e275bSSatheesh Paul 		*flags = NPC_F_LC_L_EXT_DEST;
716474e275bSSatheesh Paul 		flags_count++;
717474e275bSSatheesh Paul 	}
718474e275bSSatheesh Paul 	if (ipv6_spec->has_mobil_ext) {
719474e275bSSatheesh Paul 		*flags = NPC_F_LC_L_EXT_MOBILITY;
720474e275bSSatheesh Paul 		flags_count++;
721474e275bSSatheesh Paul 	}
722474e275bSSatheesh Paul 	if (ipv6_spec->has_hip_ext) {
723474e275bSSatheesh Paul 		*flags = NPC_F_LC_L_EXT_HOSTID;
724474e275bSSatheesh Paul 		flags_count++;
725474e275bSSatheesh Paul 	}
726474e275bSSatheesh Paul 	if (ipv6_spec->has_shim6_ext) {
727474e275bSSatheesh Paul 		*flags = NPC_F_LC_L_EXT_SHIM6;
728474e275bSSatheesh Paul 		flags_count++;
729474e275bSSatheesh Paul 	}
730474e275bSSatheesh Paul 	if (ipv6_spec->has_auth_ext) {
731474e275bSSatheesh Paul 		pst->lt[NPC_LID_LD] = NPC_LT_LD_AH;
732474e275bSSatheesh Paul 		flags_count++;
733474e275bSSatheesh Paul 	}
734474e275bSSatheesh Paul 	if (ipv6_spec->has_esp_ext) {
735474e275bSSatheesh Paul 		pst->lt[NPC_LID_LE] = NPC_LT_LE_ESP;
736474e275bSSatheesh Paul 		flags_count++;
737474e275bSSatheesh Paul 	}
738474e275bSSatheesh Paul 
739474e275bSSatheesh Paul 	if (flags_count > 1)
740474e275bSSatheesh Paul 		return -EINVAL;
741474e275bSSatheesh Paul 
742474e275bSSatheesh Paul 	if (flags_count)
743474e275bSSatheesh Paul 		pst->set_ipv6ext_ltype_mask = true;
744474e275bSSatheesh Paul 
745474e275bSSatheesh Paul 	return 0;
746474e275bSSatheesh Paul }
747474e275bSSatheesh Paul 
748e3315630SSatheesh Paul static int
npc_process_ipv6_item(struct npc_parse_state * pst)7490a6a4437SSatheesh Paul npc_process_ipv6_item(struct npc_parse_state *pst)
750e3315630SSatheesh Paul {
7516441b7a4SKiran Kumar K 	uint8_t ipv6_hdr_mask[2 * sizeof(struct roc_ipv6_hdr)];
7526441b7a4SKiran Kumar K 	uint8_t ipv6_hdr_buf[2 * sizeof(struct roc_ipv6_hdr)];
7530a6a4437SSatheesh Paul 	const struct roc_npc_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
7540a6a4437SSatheesh Paul 	const struct roc_npc_item_info *pattern = pst->pattern;
7550a6a4437SSatheesh Paul 	int offset = 0, rc = 0, lid, item_count = 0;
7560a6a4437SSatheesh Paul 	struct npc_parse_item_info parse_info;
7570a6a4437SSatheesh Paul 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
7580a6a4437SSatheesh Paul 	uint8_t flags = 0, ltype;
759e3315630SSatheesh Paul 
7600a6a4437SSatheesh Paul 	memset(ipv6_hdr_buf, 0, sizeof(ipv6_hdr_buf));
7610a6a4437SSatheesh Paul 	memset(ipv6_hdr_mask, 0, sizeof(ipv6_hdr_mask));
7620a6a4437SSatheesh Paul 
7630a6a4437SSatheesh Paul 	ipv6_spec = pst->pattern->spec;
7640a6a4437SSatheesh Paul 	ipv6_mask = pst->pattern->mask;
7650a6a4437SSatheesh Paul 
7660a6a4437SSatheesh Paul 	parse_info.def_mask = NULL;
7670a6a4437SSatheesh Paul 	parse_info.spec = ipv6_hdr_buf;
7680a6a4437SSatheesh Paul 	parse_info.mask = ipv6_hdr_mask;
7690a6a4437SSatheesh Paul 	parse_info.def_mask = NULL;
7700a6a4437SSatheesh Paul 	parse_info.hw_hdr_len = 0;
7710a6a4437SSatheesh Paul 	parse_info.len = sizeof(ipv6_spec->hdr);
7720a6a4437SSatheesh Paul 
7730a6a4437SSatheesh Paul 	pst->set_ipv6ext_ltype_mask = true;
7740a6a4437SSatheesh Paul 
775e3315630SSatheesh Paul 	lid = NPC_LID_LC;
7760a6a4437SSatheesh Paul 	ltype = NPC_LT_LC_IP6;
777e3315630SSatheesh Paul 
7780a6a4437SSatheesh Paul 	if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
7790a6a4437SSatheesh Paul 		item_count++;
780e3315630SSatheesh Paul 		if (ipv6_spec) {
7810a6a4437SSatheesh Paul 			memcpy(ipv6_hdr_buf, &ipv6_spec->hdr, sizeof(struct roc_ipv6_hdr));
782e3315630SSatheesh Paul 			rc = npc_handle_ipv6ext_attr(ipv6_spec, pst, &flags);
783e3315630SSatheesh Paul 			if (rc)
784e3315630SSatheesh Paul 				return rc;
785e3315630SSatheesh Paul 		}
7860a6a4437SSatheesh Paul 		if (ipv6_mask)
7870a6a4437SSatheesh Paul 			memcpy(ipv6_hdr_mask, &ipv6_mask->hdr, sizeof(struct roc_ipv6_hdr));
7880a6a4437SSatheesh Paul 	}
789e3315630SSatheesh Paul 
7900a6a4437SSatheesh Paul 	offset = sizeof(struct roc_ipv6_hdr);
791e3315630SSatheesh Paul 
7920a6a4437SSatheesh Paul 	while (pattern->type != ROC_NPC_ITEM_TYPE_END) {
7930a6a4437SSatheesh Paul 		/* Don't support ranges */
7940a6a4437SSatheesh Paul 		if (pattern->last != NULL)
7950a6a4437SSatheesh Paul 			return NPC_ERR_INVALID_RANGE;
796e3315630SSatheesh Paul 
7970a6a4437SSatheesh Paul 		/* If spec is NULL, both mask and last must be NULL, this
7980a6a4437SSatheesh Paul 		 * makes it to match ANY value (eq to mask = 0).
7990a6a4437SSatheesh Paul 		 * Setting either mask or last without spec is
8000a6a4437SSatheesh Paul 		 * an error
8010a6a4437SSatheesh Paul 		 */
8020a6a4437SSatheesh Paul 		if (pattern->spec == NULL) {
8030a6a4437SSatheesh Paul 			if (pattern->last != NULL && pattern->mask != NULL)
8040a6a4437SSatheesh Paul 				return NPC_ERR_INVALID_SPEC;
8050a6a4437SSatheesh Paul 		}
8060a6a4437SSatheesh Paul 		/* Either one ROC_NPC_ITEM_TYPE_IPV6_EXT or
8070a6a4437SSatheesh Paul 		 * one ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT is supported
8080a6a4437SSatheesh Paul 		 * following an ROC_NPC_ITEM_TYPE_IPV6 item.
8090a6a4437SSatheesh Paul 		 */
8100a6a4437SSatheesh Paul 		if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6_EXT) {
8110a6a4437SSatheesh Paul 			item_count++;
8120a6a4437SSatheesh Paul 			ltype = NPC_LT_LC_IP6_EXT;
8130a6a4437SSatheesh Paul 			parse_info.len =
8140a6a4437SSatheesh Paul 				sizeof(struct roc_ipv6_hdr) + sizeof(struct roc_flow_item_ipv6_ext);
8150a6a4437SSatheesh Paul 			if (pattern->spec)
8160a6a4437SSatheesh Paul 				memcpy(ipv6_hdr_buf + offset, pattern->spec,
8170a6a4437SSatheesh Paul 				       sizeof(struct roc_flow_item_ipv6_ext));
8180a6a4437SSatheesh Paul 			if (pattern->mask)
8190a6a4437SSatheesh Paul 				memcpy(ipv6_hdr_mask + offset, pattern->mask,
8200a6a4437SSatheesh Paul 				       sizeof(struct roc_flow_item_ipv6_ext));
8210a6a4437SSatheesh Paul 			break;
8220a6a4437SSatheesh Paul 		} else if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT) {
8230a6a4437SSatheesh Paul 			item_count++;
8240a6a4437SSatheesh Paul 			ltype = NPC_LT_LC_IP6_EXT;
8250a6a4437SSatheesh Paul 			flags = NPC_F_LC_U_IP6_FRAG;
8260a6a4437SSatheesh Paul 			parse_info.len =
8270a6a4437SSatheesh Paul 				sizeof(struct roc_ipv6_hdr) + sizeof(struct roc_ipv6_fragment_ext);
8280a6a4437SSatheesh Paul 			if (pattern->spec)
8290a6a4437SSatheesh Paul 				memcpy(ipv6_hdr_buf + offset, pattern->spec,
8300a6a4437SSatheesh Paul 				       sizeof(struct roc_ipv6_fragment_ext));
8310a6a4437SSatheesh Paul 			if (pattern->mask)
8320a6a4437SSatheesh Paul 				memcpy(ipv6_hdr_mask + offset, pattern->mask,
8330a6a4437SSatheesh Paul 				       sizeof(struct roc_ipv6_fragment_ext));
8340a6a4437SSatheesh Paul 
8350a6a4437SSatheesh Paul 			break;
8366441b7a4SKiran Kumar K 		} else if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT) {
8376441b7a4SKiran Kumar K 			item_count++;
8386441b7a4SKiran Kumar K 			ltype = NPC_LT_LC_IP6_EXT;
8396441b7a4SKiran Kumar K 			parse_info.len = sizeof(struct roc_ipv6_hdr) + pattern->size;
8406441b7a4SKiran Kumar K 
8416441b7a4SKiran Kumar K 			if (pattern->spec)
8426441b7a4SKiran Kumar K 				memcpy(ipv6_hdr_buf + offset, pattern->spec, pattern->size);
8436441b7a4SKiran Kumar K 			if (pattern->mask)
8446441b7a4SKiran Kumar K 				memcpy(ipv6_hdr_mask + offset, pattern->mask, pattern->size);
8456441b7a4SKiran Kumar K 			break;
8460a6a4437SSatheesh Paul 		}
8470a6a4437SSatheesh Paul 
8480a6a4437SSatheesh Paul 		pattern++;
8490a6a4437SSatheesh Paul 		pattern = npc_parse_skip_void_and_any_items(pattern);
8500a6a4437SSatheesh Paul 	}
8510a6a4437SSatheesh Paul 
8520a6a4437SSatheesh Paul 	memset(hw_mask, 0, sizeof(hw_mask));
8530a6a4437SSatheesh Paul 
8540a6a4437SSatheesh Paul 	parse_info.hw_mask = &hw_mask;
8550a6a4437SSatheesh Paul 	npc_get_hw_supp_mask(pst, &parse_info, lid, ltype);
8560a6a4437SSatheesh Paul 
8570a6a4437SSatheesh Paul 	rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
8580a6a4437SSatheesh Paul 	if (!rc)
8590a6a4437SSatheesh Paul 		return NPC_ERR_INVALID_MASK;
8600a6a4437SSatheesh Paul 
8610a6a4437SSatheesh Paul 	rc = npc_update_parse_state(pst, &parse_info, lid, ltype, flags);
862e3315630SSatheesh Paul 	if (rc)
863e3315630SSatheesh Paul 		return rc;
864e3315630SSatheesh Paul 
8650a6a4437SSatheesh Paul 	if (pst->npc->hash_extract_cap) {
8660a6a4437SSatheesh Paul 		rc = npc_process_ipv6_field_hash(parse_info.spec, parse_info.mask, pst, ltype);
8670a6a4437SSatheesh Paul 		if (rc)
8680a6a4437SSatheesh Paul 			return rc;
8690a6a4437SSatheesh Paul 	}
8700a6a4437SSatheesh Paul 
8710a6a4437SSatheesh Paul 	/* npc_update_parse_state() increments pattern once.
8720a6a4437SSatheesh Paul 	 * Check if additional increment is required.
8730a6a4437SSatheesh Paul 	 */
8740a6a4437SSatheesh Paul 	if (item_count == 2)
8750a6a4437SSatheesh Paul 		pst->pattern++;
876e3315630SSatheesh Paul 
877e3315630SSatheesh Paul 	return 0;
878e3315630SSatheesh Paul }
879e3315630SSatheesh Paul 
880c34ea71bSKiran Kumar K int
npc_parse_lc(struct npc_parse_state * pst)881c34ea71bSKiran Kumar K npc_parse_lc(struct npc_parse_state *pst)
882c34ea71bSKiran Kumar K {
883612ce5cfSSatheesh Paul 	const struct roc_npc_flow_item_raw *raw_spec;
884612ce5cfSSatheesh Paul 	uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
885612ce5cfSSatheesh Paul 	uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
886c34ea71bSKiran Kumar K 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
887c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
888474e275bSSatheesh Paul 	int rc, lid, lt, len = 0;
889474e275bSSatheesh Paul 	uint8_t flags = 0;
890c34ea71bSKiran Kumar K 
891c34ea71bSKiran Kumar K 	if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
892c34ea71bSKiran Kumar K 		return npc_parse_mpls(pst, NPC_LID_LC);
893c34ea71bSKiran Kumar K 
894244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
895c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
896c34ea71bSKiran Kumar K 	info.spec = NULL;
897c34ea71bSKiran Kumar K 	info.mask = NULL;
898c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
899c34ea71bSKiran Kumar K 	lid = NPC_LID_LC;
900c34ea71bSKiran Kumar K 
901c34ea71bSKiran Kumar K 	switch (pst->pattern->type) {
902c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_IPV4:
903c34ea71bSKiran Kumar K 		lt = NPC_LT_LC_IP;
904c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
905c34ea71bSKiran Kumar K 		break;
906c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_IPV6:
9070a6a4437SSatheesh Paul 	case ROC_NPC_ITEM_TYPE_IPV6_EXT:
9080a6a4437SSatheesh Paul 	case ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT:
9096441b7a4SKiran Kumar K 	case ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT:
9100a6a4437SSatheesh Paul 		return npc_process_ipv6_item(pst);
911c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
912c34ea71bSKiran Kumar K 		lt = NPC_LT_LC_ARP;
913c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
914c34ea71bSKiran Kumar K 		break;
915c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
916c34ea71bSKiran Kumar K 		lt = NPC_LT_LC_CUSTOM0;
917c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
918c34ea71bSKiran Kumar K 		break;
919612ce5cfSSatheesh Paul 	case ROC_NPC_ITEM_TYPE_RAW:
920612ce5cfSSatheesh Paul 		raw_spec = pst->pattern->spec;
921612ce5cfSSatheesh Paul 		if (!raw_spec->relative)
922612ce5cfSSatheesh Paul 			return 0;
923612ce5cfSSatheesh Paul 
924612ce5cfSSatheesh Paul 		len = raw_spec->length + raw_spec->offset;
925612ce5cfSSatheesh Paul 		if (len > NPC_MAX_RAW_ITEM_LEN)
926612ce5cfSSatheesh Paul 			return -EINVAL;
927612ce5cfSSatheesh Paul 
928612ce5cfSSatheesh Paul 		npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
929612ce5cfSSatheesh Paul 						  pst->pattern->spec,
930612ce5cfSSatheesh Paul 					  (const struct roc_npc_flow_item_raw *)
931612ce5cfSSatheesh Paul 						  pst->pattern->mask,
932612ce5cfSSatheesh Paul 					  &info, raw_spec_buf, raw_mask_buf);
933612ce5cfSSatheesh Paul 
934612ce5cfSSatheesh Paul 		lid = NPC_LID_LC;
935612ce5cfSSatheesh Paul 		lt = NPC_LT_LC_NGIO;
936612ce5cfSSatheesh Paul 		info.hw_mask = &hw_mask;
937612ce5cfSSatheesh Paul 		npc_get_hw_supp_mask(pst, &info, lid, lt);
938612ce5cfSSatheesh Paul 		break;
939c34ea71bSKiran Kumar K 	default:
940c34ea71bSKiran Kumar K 		/* No match at this layer */
941c34ea71bSKiran Kumar K 		return 0;
942c34ea71bSKiran Kumar K 	}
943c34ea71bSKiran Kumar K 
944c34ea71bSKiran Kumar K 	/* Identify if IP tunnels MPLS or IPv4/v6 */
945c34ea71bSKiran Kumar K 	npc_check_lc_ip_tunnel(pst);
946c34ea71bSKiran Kumar K 
947c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
948c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
949612ce5cfSSatheesh Paul 
950c34ea71bSKiran Kumar K 	if (rc != 0)
951c34ea71bSKiran Kumar K 		return rc;
952c34ea71bSKiran Kumar K 
953474e275bSSatheesh Paul 	return npc_update_parse_state(pst, &info, lid, lt, flags);
954c34ea71bSKiran Kumar K }
955c34ea71bSKiran Kumar K 
956c34ea71bSKiran Kumar K int
npc_parse_ld(struct npc_parse_state * pst)957c34ea71bSKiran Kumar K npc_parse_ld(struct npc_parse_state *pst)
958c34ea71bSKiran Kumar K {
959c34ea71bSKiran Kumar K 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
960c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
961c34ea71bSKiran Kumar K 	int lid, lt, lflags;
962c34ea71bSKiran Kumar K 	int rc;
963c34ea71bSKiran Kumar K 
964c34ea71bSKiran Kumar K 	if (pst->tunnel) {
965c34ea71bSKiran Kumar K 		/* We have already parsed MPLS or IPv4/v6 followed
966c34ea71bSKiran Kumar K 		 * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
967c34ea71bSKiran Kumar K 		 * would be parsed as tunneled versions. Skip
968c34ea71bSKiran Kumar K 		 * this layer, except for tunneled MPLS. If LC is
969c34ea71bSKiran Kumar K 		 * MPLS, we have anyway skipped all stacked MPLS
970c34ea71bSKiran Kumar K 		 * labels.
971c34ea71bSKiran Kumar K 		 */
972c34ea71bSKiran Kumar K 		if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
973c34ea71bSKiran Kumar K 			return npc_parse_mpls(pst, NPC_LID_LD);
974c34ea71bSKiran Kumar K 		return 0;
975c34ea71bSKiran Kumar K 	}
976244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
977c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
978c34ea71bSKiran Kumar K 	info.spec = NULL;
979c34ea71bSKiran Kumar K 	info.mask = NULL;
980c34ea71bSKiran Kumar K 	info.len = 0;
981c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
982c34ea71bSKiran Kumar K 
983c34ea71bSKiran Kumar K 	lid = NPC_LID_LD;
984c34ea71bSKiran Kumar K 	lflags = 0;
985c34ea71bSKiran Kumar K 
986c34ea71bSKiran Kumar K 	switch (pst->pattern->type) {
987c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_ICMP:
988c34ea71bSKiran Kumar K 		if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
989c34ea71bSKiran Kumar K 			lt = NPC_LT_LD_ICMP6;
990c34ea71bSKiran Kumar K 		else
991c34ea71bSKiran Kumar K 			lt = NPC_LT_LD_ICMP;
992c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
993c34ea71bSKiran Kumar K 		break;
994c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_UDP:
995c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_UDP;
996c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
997c34ea71bSKiran Kumar K 		break;
998c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_IGMP:
999c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_IGMP;
1000c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1001c34ea71bSKiran Kumar K 		break;
1002c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_TCP:
1003c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_TCP;
1004c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1005c34ea71bSKiran Kumar K 		break;
1006c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_SCTP:
1007c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_SCTP;
1008c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1009c34ea71bSKiran Kumar K 		break;
1010c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_GRE:
1011c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_GRE;
1012c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
10133b1a48f1SSatheesh Paul 		pst->tunnel = 1;
1014c34ea71bSKiran Kumar K 		break;
1015c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_GRE_KEY:
1016c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_GRE;
1017c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1018c34ea71bSKiran Kumar K 		info.hw_hdr_len = 4;
10193b1a48f1SSatheesh Paul 		pst->tunnel = 1;
1020c34ea71bSKiran Kumar K 		break;
1021c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_NVGRE:
1022c34ea71bSKiran Kumar K 		lt = NPC_LT_LD_NVGRE;
1023c34ea71bSKiran Kumar K 		lflags = NPC_F_GRE_NVGRE;
1024c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1025c34ea71bSKiran Kumar K 		/* Further IP/Ethernet are parsed as tunneled */
1026c34ea71bSKiran Kumar K 		pst->tunnel = 1;
1027c34ea71bSKiran Kumar K 		break;
1028c34ea71bSKiran Kumar K 	default:
1029c34ea71bSKiran Kumar K 		return 0;
1030c34ea71bSKiran Kumar K 	}
1031c34ea71bSKiran Kumar K 
1032c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
1033c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
1034c34ea71bSKiran Kumar K 	if (rc != 0)
1035c34ea71bSKiran Kumar K 		return rc;
1036c34ea71bSKiran Kumar K 
1037c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, lflags);
1038c34ea71bSKiran Kumar K }
1039c34ea71bSKiran Kumar K 
1040c34ea71bSKiran Kumar K int
npc_parse_le(struct npc_parse_state * pst)1041c34ea71bSKiran Kumar K npc_parse_le(struct npc_parse_state *pst)
1042c34ea71bSKiran Kumar K {
1043c34ea71bSKiran Kumar K 	const struct roc_npc_item_info *pattern = pst->pattern;
104404087b78SSatheesh Paul 	const struct roc_npc_item_esp_hdr *esp = NULL;
1045c34ea71bSKiran Kumar K 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1046c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
1047c34ea71bSKiran Kumar K 	int lid, lt, lflags;
1048c34ea71bSKiran Kumar K 	int rc;
1049c34ea71bSKiran Kumar K 
1050c34ea71bSKiran Kumar K 	if (pst->tunnel)
1051c34ea71bSKiran Kumar K 		return 0;
1052c34ea71bSKiran Kumar K 
1053c34ea71bSKiran Kumar K 	if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
1054c34ea71bSKiran Kumar K 		return npc_parse_mpls(pst, NPC_LID_LE);
1055c34ea71bSKiran Kumar K 
1056c34ea71bSKiran Kumar K 	info.spec = NULL;
1057c34ea71bSKiran Kumar K 	info.mask = NULL;
1058c34ea71bSKiran Kumar K 	info.hw_mask = NULL;
1059c34ea71bSKiran Kumar K 	info.def_mask = NULL;
1060c34ea71bSKiran Kumar K 	info.len = 0;
1061c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
1062c34ea71bSKiran Kumar K 	lid = NPC_LID_LE;
1063c34ea71bSKiran Kumar K 	lflags = 0;
1064c34ea71bSKiran Kumar K 
1065c34ea71bSKiran Kumar K 	/* Ensure we are not matching anything in UDP */
1066c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pattern, &info);
1067c34ea71bSKiran Kumar K 	if (rc)
1068c34ea71bSKiran Kumar K 		return rc;
1069c34ea71bSKiran Kumar K 
1070c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
1071c34ea71bSKiran Kumar K 	pattern = npc_parse_skip_void_and_any_items(pattern);
1072c34ea71bSKiran Kumar K 	switch (pattern->type) {
1073c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_VXLAN:
1074c34ea71bSKiran Kumar K 		lflags = NPC_F_UDP_VXLAN;
1075c34ea71bSKiran Kumar K 		info.len = pattern->size;
1076c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_VXLAN;
1077c34ea71bSKiran Kumar K 		break;
1078c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_GTPC:
1079c34ea71bSKiran Kumar K 		lflags = NPC_F_UDP_GTP_GTPC;
1080c34ea71bSKiran Kumar K 		info.len = pattern->size;
1081c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_GTPC;
1082c34ea71bSKiran Kumar K 		break;
1083c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_GTPU:
1084c34ea71bSKiran Kumar K 		lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
1085c34ea71bSKiran Kumar K 		info.len = pattern->size;
1086c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_GTPU;
1087c34ea71bSKiran Kumar K 		break;
1088c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_GENEVE:
1089c34ea71bSKiran Kumar K 		lflags = NPC_F_UDP_GENEVE;
1090c34ea71bSKiran Kumar K 		info.len = pattern->size;
1091c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_GENEVE;
1092c34ea71bSKiran Kumar K 		break;
1093c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
1094c34ea71bSKiran Kumar K 		lflags = NPC_F_UDP_VXLANGPE;
1095c34ea71bSKiran Kumar K 		info.len = pattern->size;
1096c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_VXLANGPE;
1097c34ea71bSKiran Kumar K 		break;
1098c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_ESP:
1099c34ea71bSKiran Kumar K 		lt = NPC_LT_LE_ESP;
1100c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
110104087b78SSatheesh Paul 		esp = (const struct roc_npc_item_esp_hdr *)pattern->spec;
110204087b78SSatheesh Paul 		if (esp)
110304087b78SSatheesh Paul 			pst->flow->spi_to_sa_info.spi = esp->spi;
1104c34ea71bSKiran Kumar K 		break;
1105c34ea71bSKiran Kumar K 	default:
1106c34ea71bSKiran Kumar K 		return 0;
1107c34ea71bSKiran Kumar K 	}
1108c34ea71bSKiran Kumar K 
1109c34ea71bSKiran Kumar K 	pst->tunnel = 1;
1110c34ea71bSKiran Kumar K 
1111c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
1112c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pattern, &info);
1113c34ea71bSKiran Kumar K 	if (rc != 0)
1114c34ea71bSKiran Kumar K 		return rc;
1115c34ea71bSKiran Kumar K 
1116c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, lflags);
1117c34ea71bSKiran Kumar K }
1118c34ea71bSKiran Kumar K 
1119c34ea71bSKiran Kumar K int
npc_parse_lf(struct npc_parse_state * pst)1120c34ea71bSKiran Kumar K npc_parse_lf(struct npc_parse_state *pst)
1121c34ea71bSKiran Kumar K {
1122c34ea71bSKiran Kumar K 	const struct roc_npc_item_info *pattern, *last_pattern;
1123c34ea71bSKiran Kumar K 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
11244f52aafaSHarman Kalra 	const struct roc_npc_flow_item_eth *eth_item;
1125c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
1126c34ea71bSKiran Kumar K 	int lid, lt, lflags;
1127c34ea71bSKiran Kumar K 	int nr_vlans = 0;
1128c34ea71bSKiran Kumar K 	int rc;
1129c34ea71bSKiran Kumar K 
1130c34ea71bSKiran Kumar K 	/* We hit this layer if there is a tunneling protocol */
1131c34ea71bSKiran Kumar K 	if (!pst->tunnel)
1132c34ea71bSKiran Kumar K 		return 0;
1133c34ea71bSKiran Kumar K 
1134c34ea71bSKiran Kumar K 	if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
1135c34ea71bSKiran Kumar K 		return 0;
1136c34ea71bSKiran Kumar K 
1137c34ea71bSKiran Kumar K 	lid = NPC_LID_LF;
1138c34ea71bSKiran Kumar K 	lt = NPC_LT_LF_TU_ETHER;
1139c34ea71bSKiran Kumar K 	lflags = 0;
1140c34ea71bSKiran Kumar K 
11414f52aafaSHarman Kalra 	eth_item = pst->pattern->spec;
11424f52aafaSHarman Kalra 
1143c34ea71bSKiran Kumar K 	/* No match support for vlan tags */
1144244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
1145c34ea71bSKiran Kumar K 	info.hw_mask = NULL;
11464f52aafaSHarman Kalra 	info.len = sizeof(eth_item->hdr);
1147c34ea71bSKiran Kumar K 	info.spec = NULL;
1148c34ea71bSKiran Kumar K 	info.mask = NULL;
1149c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
1150c34ea71bSKiran Kumar K 
1151c34ea71bSKiran Kumar K 	/* Look ahead and find out any VLAN tags. These can be
1152c34ea71bSKiran Kumar K 	 * detected but no data matching is available.
1153c34ea71bSKiran Kumar K 	 */
1154c34ea71bSKiran Kumar K 	last_pattern = pst->pattern;
1155c34ea71bSKiran Kumar K 	pattern = pst->pattern + 1;
1156c34ea71bSKiran Kumar K 	pattern = npc_parse_skip_void_and_any_items(pattern);
1157c34ea71bSKiran Kumar K 	while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
1158c34ea71bSKiran Kumar K 		nr_vlans++;
1159c34ea71bSKiran Kumar K 		last_pattern = pattern;
1160c34ea71bSKiran Kumar K 		pattern++;
1161c34ea71bSKiran Kumar K 		pattern = npc_parse_skip_void_and_any_items(pattern);
1162c34ea71bSKiran Kumar K 	}
1163c34ea71bSKiran Kumar K 	switch (nr_vlans) {
1164c34ea71bSKiran Kumar K 	case 0:
1165c34ea71bSKiran Kumar K 		break;
1166c34ea71bSKiran Kumar K 	case 1:
1167c34ea71bSKiran Kumar K 		lflags = NPC_F_TU_ETHER_CTAG;
1168c34ea71bSKiran Kumar K 		break;
1169c34ea71bSKiran Kumar K 	case 2:
1170c34ea71bSKiran Kumar K 		lflags = NPC_F_TU_ETHER_STAG_CTAG;
1171c34ea71bSKiran Kumar K 		break;
1172c34ea71bSKiran Kumar K 	default:
1173c34ea71bSKiran Kumar K 		return NPC_ERR_PATTERN_NOTSUP;
1174c34ea71bSKiran Kumar K 	}
1175c34ea71bSKiran Kumar K 
1176c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
11774f52aafaSHarman Kalra 	info.len = sizeof(eth_item->hdr);
1178c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
1179c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
1180c34ea71bSKiran Kumar K 	info.spec = NULL;
1181c34ea71bSKiran Kumar K 	info.mask = NULL;
1182c34ea71bSKiran Kumar K 
11834f52aafaSHarman Kalra 	if (eth_item && eth_item->has_vlan)
11844f52aafaSHarman Kalra 		pst->set_vlan_ltype_mask = true;
11854f52aafaSHarman Kalra 
1186c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
1187c34ea71bSKiran Kumar K 	if (rc != 0)
1188c34ea71bSKiran Kumar K 		return rc;
1189c34ea71bSKiran Kumar K 
1190c34ea71bSKiran Kumar K 	pst->pattern = last_pattern;
1191c34ea71bSKiran Kumar K 
1192c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, lflags);
1193c34ea71bSKiran Kumar K }
1194c34ea71bSKiran Kumar K 
1195c34ea71bSKiran Kumar K int
npc_parse_lg(struct npc_parse_state * pst)1196c34ea71bSKiran Kumar K npc_parse_lg(struct npc_parse_state *pst)
1197c34ea71bSKiran Kumar K {
1198c34ea71bSKiran Kumar K 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1199c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
1200c34ea71bSKiran Kumar K 	int lid, lt;
1201c34ea71bSKiran Kumar K 	int rc;
1202c34ea71bSKiran Kumar K 
1203c34ea71bSKiran Kumar K 	if (!pst->tunnel)
1204c34ea71bSKiran Kumar K 		return 0;
1205c34ea71bSKiran Kumar K 
1206244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
1207c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
1208c34ea71bSKiran Kumar K 	info.spec = NULL;
1209c34ea71bSKiran Kumar K 	info.mask = NULL;
1210c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
1211c34ea71bSKiran Kumar K 	lid = NPC_LID_LG;
1212c34ea71bSKiran Kumar K 
1213c34ea71bSKiran Kumar K 	if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
1214c34ea71bSKiran Kumar K 		lt = NPC_LT_LG_TU_IP;
1215c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1216c34ea71bSKiran Kumar K 	} else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
1217c34ea71bSKiran Kumar K 		lt = NPC_LT_LG_TU_IP6;
1218c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1219c34ea71bSKiran Kumar K 	} else {
1220c34ea71bSKiran Kumar K 		/* There is no tunneled IP header */
1221c34ea71bSKiran Kumar K 		return 0;
1222c34ea71bSKiran Kumar K 	}
1223c34ea71bSKiran Kumar K 
1224c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
1225c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
1226c34ea71bSKiran Kumar K 	if (rc != 0)
1227c34ea71bSKiran Kumar K 		return rc;
1228c34ea71bSKiran Kumar K 
1229c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, 0);
1230c34ea71bSKiran Kumar K }
1231c34ea71bSKiran Kumar K 
1232c34ea71bSKiran Kumar K int
npc_parse_lh(struct npc_parse_state * pst)1233c34ea71bSKiran Kumar K npc_parse_lh(struct npc_parse_state *pst)
1234c34ea71bSKiran Kumar K {
1235c34ea71bSKiran Kumar K 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1236c34ea71bSKiran Kumar K 	struct npc_parse_item_info info;
1237c34ea71bSKiran Kumar K 	int lid, lt;
1238c34ea71bSKiran Kumar K 	int rc;
1239c34ea71bSKiran Kumar K 
1240c34ea71bSKiran Kumar K 	if (!pst->tunnel)
1241c34ea71bSKiran Kumar K 		return 0;
1242c34ea71bSKiran Kumar K 
1243244a996fSGowrishankar Muthukrishnan 	info.def_mask = NULL;
1244c34ea71bSKiran Kumar K 	info.hw_mask = &hw_mask;
1245c34ea71bSKiran Kumar K 	info.spec = NULL;
1246c34ea71bSKiran Kumar K 	info.mask = NULL;
1247c34ea71bSKiran Kumar K 	info.hw_hdr_len = 0;
1248c34ea71bSKiran Kumar K 	lid = NPC_LID_LH;
1249c34ea71bSKiran Kumar K 
1250c34ea71bSKiran Kumar K 	switch (pst->pattern->type) {
1251c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_UDP:
1252c34ea71bSKiran Kumar K 		lt = NPC_LT_LH_TU_UDP;
1253c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1254c34ea71bSKiran Kumar K 		break;
1255c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_TCP:
1256c34ea71bSKiran Kumar K 		lt = NPC_LT_LH_TU_TCP;
1257c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1258c34ea71bSKiran Kumar K 		break;
1259c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_SCTP:
1260c34ea71bSKiran Kumar K 		lt = NPC_LT_LH_TU_SCTP;
1261c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1262c34ea71bSKiran Kumar K 		break;
1263c34ea71bSKiran Kumar K 	case ROC_NPC_ITEM_TYPE_ESP:
1264c34ea71bSKiran Kumar K 		lt = NPC_LT_LH_TU_ESP;
1265c34ea71bSKiran Kumar K 		info.len = pst->pattern->size;
1266c34ea71bSKiran Kumar K 		break;
1267c34ea71bSKiran Kumar K 	default:
1268c34ea71bSKiran Kumar K 		return 0;
1269c34ea71bSKiran Kumar K 	}
1270c34ea71bSKiran Kumar K 
1271c34ea71bSKiran Kumar K 	npc_get_hw_supp_mask(pst, &info, lid, lt);
1272c34ea71bSKiran Kumar K 	rc = npc_parse_item_basic(pst->pattern, &info);
1273c34ea71bSKiran Kumar K 	if (rc != 0)
1274c34ea71bSKiran Kumar K 		return rc;
1275c34ea71bSKiran Kumar K 
1276c34ea71bSKiran Kumar K 	return npc_update_parse_state(pst, &info, lid, lt, 0);
1277c34ea71bSKiran Kumar K }
1278