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, <, &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